mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-22 10:05:32 +01:00
Merge branch '4.3.4' of https://github.com/TrinityCore/TrinityCore into 4.3.4
This commit is contained in:
@@ -15,6 +15,10 @@ project(TrinityCore)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
cmake_policy(SET CMP0005 OLD)
|
||||
|
||||
# add this options before PROJECT keyword
|
||||
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
|
||||
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
|
||||
|
||||
# Set RPATH-handing (CMake parameters)
|
||||
set(CMAKE_SKIP_BUILD_RPATH 0)
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH 0)
|
||||
|
||||
40
COPYING
40
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.
|
||||
|
||||
10
README
10
README
@@ -44,3 +44,13 @@ the doc directory.
|
||||
SQL files to create the database can be found in the sql directory. Files
|
||||
to update your database from an older revision/version can be found in the
|
||||
sql/updates directory.
|
||||
|
||||
TrinityCore Requirements
|
||||
Platform: Linux, Windows or Mac
|
||||
Processor with SSE2 support
|
||||
ACE ≥ 5.8.3
|
||||
MySQL ≥ 5.1.0
|
||||
CMake ≥ 2.8.0
|
||||
OpenSSL ≥ 0.9.8o
|
||||
GCC ≥ 4.3 (Linux only)
|
||||
MS Visual Studio ≥ 9 (2008) (Windows only)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Set build-directive (used in core to tell which buildtype we used)
|
||||
add_definitions(-D_BUILD_DIRECTIVE="${CMAKE_BUILD_TYPE}")
|
||||
add_definitions(-D_BUILD_DIRECTIVE="'${CMAKE_BUILD_TYPE}'")
|
||||
|
||||
if(PLATFORM EQUAL 32)
|
||||
add_definitions(-axSSE2)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -21,11 +21,9 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
if(SERVERS)
|
||||
add_subdirectory(acelite)
|
||||
if(USE_MYSQL_SOURCES)
|
||||
add_subdirectory(acelite)
|
||||
if(USE_MYSQL_SOURCES)
|
||||
add_subdirectory(mysqllite)
|
||||
endif()
|
||||
endif()
|
||||
if(TOOLS)
|
||||
add_subdirectory(bzip2)
|
||||
@@ -34,6 +32,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
endif()
|
||||
|
||||
add_subdirectory(g3dlite)
|
||||
add_subdirectory(recastnavigation)
|
||||
|
||||
if(SERVERS)
|
||||
add_subdirectory(gsoap)
|
||||
|
||||
@@ -36,6 +36,10 @@ gSOAP (a portable development toolkit for C and C++ XML Web services and XML dat
|
||||
http://gsoap2.sourceforge.net/
|
||||
Version: 2.8.10
|
||||
|
||||
recastnavigation (Recast is state of the art navigation mesh construction toolset for games)
|
||||
http://code.google.com/p/recastnavigation/
|
||||
Version: 1.4
|
||||
|
||||
StormLib (a pack of modules, written in C++, which are able to read and also to write files from/to the MPQ archives)
|
||||
http://www.zezula.net/en/mpq/stormlib.html
|
||||
Version: 8.04
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
20
dep/recastnavigation/CMakeLists.txt
Normal file
20
dep/recastnavigation/CMakeLists.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (C) 2005-2011 MaNGOS project <http://getmangos.com/>
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
add_subdirectory(Detour)
|
||||
add_subdirectory(Recast)
|
||||
28
dep/recastnavigation/Detour/CMakeLists.txt
Normal file
28
dep/recastnavigation/Detour/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
# Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
|
||||
#
|
||||
# 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.
|
||||
|
||||
set(Detour_STAT_SRCS
|
||||
DetourAlloc.cpp
|
||||
DetourCommon.cpp
|
||||
DetourNavMesh.cpp
|
||||
DetourNavMeshBuilder.cpp
|
||||
DetourNavMeshQuery.cpp
|
||||
DetourNode.cpp
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/dep/zlib
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(Detour STATIC ${Detour_STAT_SRCS})
|
||||
|
||||
target_link_libraries(Detour ${ZLIB_LIBRARIES})
|
||||
50
dep/recastnavigation/Detour/DetourAlloc.cpp
Normal file
50
dep/recastnavigation/Detour/DetourAlloc.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "DetourAlloc.h"
|
||||
|
||||
static void *dtAllocDefault(int size, dtAllocHint)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void dtFreeDefault(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static dtAllocFunc* sAllocFunc = dtAllocDefault;
|
||||
static dtFreeFunc* sFreeFunc = dtFreeDefault;
|
||||
|
||||
void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc)
|
||||
{
|
||||
sAllocFunc = allocFunc ? allocFunc : dtAllocDefault;
|
||||
sFreeFunc = freeFunc ? freeFunc : dtFreeDefault;
|
||||
}
|
||||
|
||||
void* dtAlloc(int size, dtAllocHint hint)
|
||||
{
|
||||
return sAllocFunc(size, hint);
|
||||
}
|
||||
|
||||
void dtFree(void* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
sFreeFunc(ptr);
|
||||
}
|
||||
36
dep/recastnavigation/Detour/DetourAlloc.h
Normal file
36
dep/recastnavigation/Detour/DetourAlloc.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef DETOURALLOCATOR_H
|
||||
#define DETOURALLOCATOR_H
|
||||
|
||||
enum dtAllocHint
|
||||
{
|
||||
DT_ALLOC_PERM, // Memory persist after a function call.
|
||||
DT_ALLOC_TEMP // Memory used temporarily within a function.
|
||||
};
|
||||
|
||||
typedef void* (dtAllocFunc)(int size, dtAllocHint hint);
|
||||
typedef void (dtFreeFunc)(void* ptr);
|
||||
|
||||
void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc);
|
||||
|
||||
void* dtAlloc(int size, dtAllocHint hint);
|
||||
void dtFree(void* ptr);
|
||||
|
||||
#endif
|
||||
33
dep/recastnavigation/Detour/DetourAssert.h
Normal file
33
dep/recastnavigation/Detour/DetourAssert.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef DETOURASSERT_H
|
||||
#define DETOURASSERT_H
|
||||
|
||||
// Note: This header file's only purpose is to include define assert.
|
||||
// Feel free to change the file and include your own implementation instead.
|
||||
|
||||
#ifdef NDEBUG
|
||||
// From http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/
|
||||
# define dtAssert(x) do { (void)sizeof(x); } while(__LINE__==-1,false)
|
||||
#else
|
||||
# include <assert.h>
|
||||
# define dtAssert assert
|
||||
#endif
|
||||
|
||||
#endif // DETOURASSERT_H
|
||||
329
dep/recastnavigation/Detour/DetourCommon.cpp
Normal file
329
dep/recastnavigation/Detour/DetourCommon.cpp
Normal file
@@ -0,0 +1,329 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include <math.h>
|
||||
#include "DetourCommon.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
float dtSqrt(float x)
|
||||
{
|
||||
return sqrtf(x);
|
||||
}
|
||||
|
||||
void dtClosestPtPointTriangle(float* closest, const float* p,
|
||||
const float* a, const float* b, const float* c)
|
||||
{
|
||||
// Check if P in vertex region outside A
|
||||
float ab[3], ac[3], ap[3];
|
||||
dtVsub(ab, b, a);
|
||||
dtVsub(ac, c, a);
|
||||
dtVsub(ap, p, a);
|
||||
float d1 = dtVdot(ab, ap);
|
||||
float d2 = dtVdot(ac, ap);
|
||||
if (d1 <= 0.0f && d2 <= 0.0f)
|
||||
{
|
||||
// barycentric coordinates (1,0,0)
|
||||
dtVcopy(closest, a);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if P in vertex region outside B
|
||||
float bp[3];
|
||||
dtVsub(bp, p, b);
|
||||
float d3 = dtVdot(ab, bp);
|
||||
float d4 = dtVdot(ac, bp);
|
||||
if (d3 >= 0.0f && d4 <= d3)
|
||||
{
|
||||
// barycentric coordinates (0,1,0)
|
||||
dtVcopy(closest, b);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if P in edge region of AB, if so return projection of P onto AB
|
||||
float vc = d1*d4 - d3*d2;
|
||||
if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f)
|
||||
{
|
||||
// barycentric coordinates (1-v,v,0)
|
||||
float v = d1 / (d1 - d3);
|
||||
closest[0] = a[0] + v * ab[0];
|
||||
closest[1] = a[1] + v * ab[1];
|
||||
closest[2] = a[2] + v * ab[2];
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if P in vertex region outside C
|
||||
float cp[3];
|
||||
dtVsub(cp, p, c);
|
||||
float d5 = dtVdot(ab, cp);
|
||||
float d6 = dtVdot(ac, cp);
|
||||
if (d6 >= 0.0f && d5 <= d6)
|
||||
{
|
||||
// barycentric coordinates (0,0,1)
|
||||
dtVcopy(closest, c);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if P in edge region of AC, if so return projection of P onto AC
|
||||
float vb = d5*d2 - d1*d6;
|
||||
if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f)
|
||||
{
|
||||
// barycentric coordinates (1-w,0,w)
|
||||
float w = d2 / (d2 - d6);
|
||||
closest[0] = a[0] + w * ac[0];
|
||||
closest[1] = a[1] + w * ac[1];
|
||||
closest[2] = a[2] + w * ac[2];
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if P in edge region of BC, if so return projection of P onto BC
|
||||
float va = d3*d6 - d5*d4;
|
||||
if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f)
|
||||
{
|
||||
// barycentric coordinates (0,1-w,w)
|
||||
float w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
|
||||
closest[0] = b[0] + w * (c[0] - b[0]);
|
||||
closest[1] = b[1] + w * (c[1] - b[1]);
|
||||
closest[2] = b[2] + w * (c[2] - b[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
// P inside face region. Compute Q through its barycentric coordinates (u,v,w)
|
||||
float denom = 1.0f / (va + vb + vc);
|
||||
float v = vb * denom;
|
||||
float w = vc * denom;
|
||||
closest[0] = a[0] + ab[0] * v + ac[0] * w;
|
||||
closest[1] = a[1] + ab[1] * v + ac[1] * w;
|
||||
closest[2] = a[2] + ab[2] * v + ac[2] * w;
|
||||
}
|
||||
|
||||
bool dtIntersectSegmentPoly2D(const float* p0, const float* p1,
|
||||
const float* verts, int nverts,
|
||||
float& tmin, float& tmax,
|
||||
int& segMin, int& segMax)
|
||||
{
|
||||
static const float EPS = 0.00000001f;
|
||||
|
||||
tmin = 0;
|
||||
tmax = 1;
|
||||
segMin = -1;
|
||||
segMax = -1;
|
||||
|
||||
float dir[3];
|
||||
dtVsub(dir, p1, p0);
|
||||
|
||||
for (int i = 0, j = nverts-1; i < nverts; j=i++)
|
||||
{
|
||||
float edge[3], diff[3];
|
||||
dtVsub(edge, &verts[i*3], &verts[j*3]);
|
||||
dtVsub(diff, p0, &verts[j*3]);
|
||||
const float n = dtVperp2D(edge, diff);
|
||||
const float d = dtVperp2D(dir, edge);
|
||||
if (fabsf(d) < EPS)
|
||||
{
|
||||
// S is nearly parallel to this edge
|
||||
if (n < 0)
|
||||
return false;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
const float t = n / d;
|
||||
if (d < 0)
|
||||
{
|
||||
// segment S is entering across this edge
|
||||
if (t > tmin)
|
||||
{
|
||||
tmin = t;
|
||||
segMin = j;
|
||||
// S enters after leaving polygon
|
||||
if (tmin > tmax)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// segment S is leaving across this edge
|
||||
if (t < tmax)
|
||||
{
|
||||
tmax = t;
|
||||
segMax = j;
|
||||
// S leaves before entering polygon
|
||||
if (tmax < tmin)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float dtDistancePtSegSqr2D(const float* pt, const float* p, const float* q, float& t)
|
||||
{
|
||||
float pqx = q[0] - p[0];
|
||||
float pqz = q[2] - p[2];
|
||||
float dx = pt[0] - p[0];
|
||||
float dz = pt[2] - p[2];
|
||||
float d = pqx*pqx + pqz*pqz;
|
||||
t = pqx*dx + pqz*dz;
|
||||
if (d > 0) t /= d;
|
||||
if (t < 0) t = 0;
|
||||
else if (t > 1) t = 1;
|
||||
dx = p[0] + t*pqx - pt[0];
|
||||
dz = p[2] + t*pqz - pt[2];
|
||||
return dx*dx + dz*dz;
|
||||
}
|
||||
|
||||
void dtCalcPolyCenter(float* tc, const unsigned short* idx, int nidx, const float* verts)
|
||||
{
|
||||
tc[0] = 0.0f;
|
||||
tc[1] = 0.0f;
|
||||
tc[2] = 0.0f;
|
||||
for (int j = 0; j < nidx; ++j)
|
||||
{
|
||||
const float* v = &verts[idx[j]*3];
|
||||
tc[0] += v[0];
|
||||
tc[1] += v[1];
|
||||
tc[2] += v[2];
|
||||
}
|
||||
const float s = 1.0f / nidx;
|
||||
tc[0] *= s;
|
||||
tc[1] *= s;
|
||||
tc[2] *= s;
|
||||
}
|
||||
|
||||
bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b, const float* c, float& h)
|
||||
{
|
||||
float v0[3], v1[3], v2[3];
|
||||
dtVsub(v0, c,a);
|
||||
dtVsub(v1, b,a);
|
||||
dtVsub(v2, p,a);
|
||||
|
||||
const float dot00 = dtVdot2D(v0, v0);
|
||||
const float dot01 = dtVdot2D(v0, v1);
|
||||
const float dot02 = dtVdot2D(v0, v2);
|
||||
const float dot11 = dtVdot2D(v1, v1);
|
||||
const float dot12 = dtVdot2D(v1, v2);
|
||||
|
||||
// Compute barycentric coordinates
|
||||
const float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
|
||||
const float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
|
||||
const float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
|
||||
|
||||
// The (sloppy) epsilon is needed to allow to get height of points which
|
||||
// are interpolated along the edges of the triangles.
|
||||
static const float EPS = 1e-4f;
|
||||
|
||||
// If point lies inside the triangle, return interpolated ycoord.
|
||||
if (u >= -EPS && v >= -EPS && (u+v) <= 1+EPS)
|
||||
{
|
||||
h = a[1] + v0[1]*u + v1[1]*v;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dtPointInPolygon(const float* pt, const float* verts, const int nverts)
|
||||
{
|
||||
// TODO: Replace pnpoly with triArea2D tests?
|
||||
int i, j;
|
||||
bool c = false;
|
||||
for (i = 0, j = nverts-1; i < nverts; j = i++)
|
||||
{
|
||||
const float* vi = &verts[i*3];
|
||||
const float* vj = &verts[j*3];
|
||||
if (((vi[2] > pt[2]) != (vj[2] > pt[2])) &&
|
||||
(pt[0] < (vj[0]-vi[0]) * (pt[2]-vi[2]) / (vj[2]-vi[2]) + vi[0]) )
|
||||
c = !c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
bool dtDistancePtPolyEdgesSqr(const float* pt, const float* verts, const int nverts,
|
||||
float* ed, float* et)
|
||||
{
|
||||
// TODO: Replace pnpoly with triArea2D tests?
|
||||
int i, j;
|
||||
bool c = false;
|
||||
for (i = 0, j = nverts-1; i < nverts; j = i++)
|
||||
{
|
||||
const float* vi = &verts[i*3];
|
||||
const float* vj = &verts[j*3];
|
||||
if (((vi[2] > pt[2]) != (vj[2] > pt[2])) &&
|
||||
(pt[0] < (vj[0]-vi[0]) * (pt[2]-vi[2]) / (vj[2]-vi[2]) + vi[0]) )
|
||||
c = !c;
|
||||
ed[j] = dtDistancePtSegSqr2D(pt, vj, vi, et[j]);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static void projectPoly(const float* axis, const float* poly, const int npoly,
|
||||
float& rmin, float& rmax)
|
||||
{
|
||||
rmin = rmax = dtVdot2D(axis, &poly[0]);
|
||||
for (int i = 1; i < npoly; ++i)
|
||||
{
|
||||
const float d = dtVdot2D(axis, &poly[i*3]);
|
||||
rmin = dtMin(rmin, d);
|
||||
rmax = dtMax(rmax, d);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool overlapRange(const float amin, const float amax,
|
||||
const float bmin, const float bmax,
|
||||
const float eps)
|
||||
{
|
||||
return ((amin+eps) > bmax || (amax-eps) < bmin) ? false : true;
|
||||
}
|
||||
|
||||
bool dtOverlapPolyPoly2D(const float* polya, const int npolya,
|
||||
const float* polyb, const int npolyb)
|
||||
{
|
||||
const float eps = 1e-4f;
|
||||
|
||||
for (int i = 0, j = npolya-1; i < npolya; j=i++)
|
||||
{
|
||||
const float* va = &polya[j*3];
|
||||
const float* vb = &polya[i*3];
|
||||
const float n[3] = { vb[2]-va[2], 0, -(vb[0]-va[0]) };
|
||||
float amin,amax,bmin,bmax;
|
||||
projectPoly(n, polya, npolya, amin,amax);
|
||||
projectPoly(n, polyb, npolyb, bmin,bmax);
|
||||
if (!overlapRange(amin,amax, bmin,bmax, eps))
|
||||
{
|
||||
// Found separating axis
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = 0, j = npolyb-1; i < npolyb; j=i++)
|
||||
{
|
||||
const float* va = &polyb[j*3];
|
||||
const float* vb = &polyb[i*3];
|
||||
const float n[3] = { vb[2]-va[2], 0, -(vb[0]-va[0]) };
|
||||
float amin,amax,bmin,bmax;
|
||||
projectPoly(n, polya, npolya, amin,amax);
|
||||
projectPoly(n, polyb, npolyb, bmin,bmax);
|
||||
if (!overlapRange(amin,amax, bmin,bmax, eps))
|
||||
{
|
||||
// Found separating axis
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
248
dep/recastnavigation/Detour/DetourCommon.h
Normal file
248
dep/recastnavigation/Detour/DetourCommon.h
Normal file
@@ -0,0 +1,248 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef DETOURCOMMON_H
|
||||
#define DETOURCOMMON_H
|
||||
|
||||
template<class T> inline void dtSwap(T& a, T& b) { T t = a; a = b; b = t; }
|
||||
template<class T> inline T dtMin(T a, T b) { return a < b ? a : b; }
|
||||
template<class T> inline T dtMax(T a, T b) { return a > b ? a : b; }
|
||||
template<class T> inline T dtAbs(T a) { return a < 0 ? -a : a; }
|
||||
template<class T> inline T dtSqr(T a) { return a*a; }
|
||||
template<class T> inline T dtClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); }
|
||||
|
||||
float dtSqrt(float x);
|
||||
|
||||
inline void dtVcross(float* dest, const float* v1, const float* v2)
|
||||
{
|
||||
dest[0] = v1[1]*v2[2] - v1[2]*v2[1];
|
||||
dest[1] = v1[2]*v2[0] - v1[0]*v2[2];
|
||||
dest[2] = v1[0]*v2[1] - v1[1]*v2[0];
|
||||
}
|
||||
|
||||
inline float dtVdot(const float* v1, const float* v2)
|
||||
{
|
||||
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
|
||||
}
|
||||
|
||||
inline void dtVmad(float* dest, const float* v1, const float* v2, const float s)
|
||||
{
|
||||
dest[0] = v1[0]+v2[0]*s;
|
||||
dest[1] = v1[1]+v2[1]*s;
|
||||
dest[2] = v1[2]+v2[2]*s;
|
||||
}
|
||||
|
||||
inline void dtVlerp(float* dest, const float* v1, const float* v2, const float t)
|
||||
{
|
||||
dest[0] = v1[0]+(v2[0]-v1[0])*t;
|
||||
dest[1] = v1[1]+(v2[1]-v1[1])*t;
|
||||
dest[2] = v1[2]+(v2[2]-v1[2])*t;
|
||||
}
|
||||
|
||||
inline void dtVadd(float* dest, const float* v1, const float* v2)
|
||||
{
|
||||
dest[0] = v1[0]+v2[0];
|
||||
dest[1] = v1[1]+v2[1];
|
||||
dest[2] = v1[2]+v2[2];
|
||||
}
|
||||
|
||||
inline void dtVsub(float* dest, const float* v1, const float* v2)
|
||||
{
|
||||
dest[0] = v1[0]-v2[0];
|
||||
dest[1] = v1[1]-v2[1];
|
||||
dest[2] = v1[2]-v2[2];
|
||||
}
|
||||
|
||||
inline void dtVscale(float* dest, const float* v, const float t)
|
||||
{
|
||||
dest[0] = v[0]*t;
|
||||
dest[1] = v[1]*t;
|
||||
dest[2] = v[2]*t;
|
||||
}
|
||||
|
||||
inline void dtVmin(float* mn, const float* v)
|
||||
{
|
||||
mn[0] = dtMin(mn[0], v[0]);
|
||||
mn[1] = dtMin(mn[1], v[1]);
|
||||
mn[2] = dtMin(mn[2], v[2]);
|
||||
}
|
||||
|
||||
inline void dtVmax(float* mx, const float* v)
|
||||
{
|
||||
mx[0] = dtMax(mx[0], v[0]);
|
||||
mx[1] = dtMax(mx[1], v[1]);
|
||||
mx[2] = dtMax(mx[2], v[2]);
|
||||
}
|
||||
|
||||
inline void dtVset(float* dest, const float x, const float y, const float z)
|
||||
{
|
||||
dest[0] = x; dest[1] = y; dest[2] = z;
|
||||
}
|
||||
|
||||
inline void dtVcopy(float* dest, const float* a)
|
||||
{
|
||||
dest[0] = a[0];
|
||||
dest[1] = a[1];
|
||||
dest[2] = a[2];
|
||||
}
|
||||
|
||||
inline float dtVlen(const float* v)
|
||||
{
|
||||
return dtSqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
|
||||
}
|
||||
|
||||
inline float dtVlenSqr(const float* v)
|
||||
{
|
||||
return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
|
||||
}
|
||||
|
||||
inline float dtVdist(const float* v1, const float* v2)
|
||||
{
|
||||
const float dx = v2[0] - v1[0];
|
||||
const float dy = v2[1] - v1[1];
|
||||
const float dz = v2[2] - v1[2];
|
||||
return dtSqrt(dx*dx + dy*dy + dz*dz);
|
||||
}
|
||||
|
||||
inline float dtVdistSqr(const float* v1, const float* v2)
|
||||
{
|
||||
const float dx = v2[0] - v1[0];
|
||||
const float dy = v2[1] - v1[1];
|
||||
const float dz = v2[2] - v1[2];
|
||||
return dx*dx + dy*dy + dz*dz;
|
||||
}
|
||||
|
||||
inline float dtVdist2D(const float* v1, const float* v2)
|
||||
{
|
||||
const float dx = v2[0] - v1[0];
|
||||
const float dz = v2[2] - v1[2];
|
||||
return dtSqrt(dx*dx + dz*dz);
|
||||
}
|
||||
|
||||
inline float dtVdist2DSqr(const float* v1, const float* v2)
|
||||
{
|
||||
const float dx = v2[0] - v1[0];
|
||||
const float dz = v2[2] - v1[2];
|
||||
return dx*dx + dz*dz;
|
||||
}
|
||||
|
||||
inline void dtVnormalize(float* v)
|
||||
{
|
||||
float d = 1.0f / dtSqrt(dtSqr(v[0]) + dtSqr(v[1]) + dtSqr(v[2]));
|
||||
v[0] *= d;
|
||||
v[1] *= d;
|
||||
v[2] *= d;
|
||||
}
|
||||
|
||||
inline bool dtVequal(const float* p0, const float* p1)
|
||||
{
|
||||
static const float thr = dtSqr(1.0f/16384.0f);
|
||||
const float d = dtVdistSqr(p0, p1);
|
||||
return d < thr;
|
||||
}
|
||||
|
||||
inline unsigned int dtNextPow2(unsigned int v)
|
||||
{
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
return v;
|
||||
}
|
||||
|
||||
inline unsigned int dtIlog2(unsigned int v)
|
||||
{
|
||||
unsigned int r;
|
||||
unsigned int shift;
|
||||
r = (v > 0xffff) << 4; v >>= r;
|
||||
shift = (v > 0xff) << 3; v >>= shift; r |= shift;
|
||||
shift = (v > 0xf) << 2; v >>= shift; r |= shift;
|
||||
shift = (v > 0x3) << 1; v >>= shift; r |= shift;
|
||||
r |= (v >> 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
inline int dtAlign4(int x) { return (x+3) & ~3; }
|
||||
|
||||
inline int dtOppositeTile(int side) { return (side+4) & 0x7; }
|
||||
|
||||
inline float dtVdot2D(const float* u, const float* v)
|
||||
{
|
||||
return u[0]*v[0] + u[2]*v[2];
|
||||
}
|
||||
|
||||
inline float dtVperp2D(const float* u, const float* v)
|
||||
{
|
||||
return u[2]*v[0] - u[0]*v[2];
|
||||
}
|
||||
|
||||
inline float dtTriArea2D(const float* a, const float* b, const float* c)
|
||||
{
|
||||
const float abx = b[0] - a[0];
|
||||
const float abz = b[2] - a[2];
|
||||
const float acx = c[0] - a[0];
|
||||
const float acz = c[2] - a[2];
|
||||
return acx*abz - abx*acz;
|
||||
}
|
||||
|
||||
inline bool dtOverlapQuantBounds(const unsigned short amin[3], const unsigned short amax[3],
|
||||
const unsigned short bmin[3], const unsigned short bmax[3])
|
||||
{
|
||||
bool overlap = true;
|
||||
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
|
||||
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
|
||||
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
|
||||
return overlap;
|
||||
}
|
||||
|
||||
inline bool dtOverlapBounds(const float* amin, const float* amax,
|
||||
const float* bmin, const float* bmax)
|
||||
{
|
||||
bool overlap = true;
|
||||
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
|
||||
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
|
||||
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
|
||||
return overlap;
|
||||
}
|
||||
|
||||
void dtClosestPtPointTriangle(float* closest, const float* p,
|
||||
const float* a, const float* b, const float* c);
|
||||
|
||||
bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b, const float* c, float& h);
|
||||
|
||||
bool dtIntersectSegmentPoly2D(const float* p0, const float* p1,
|
||||
const float* verts, int nverts,
|
||||
float& tmin, float& tmax,
|
||||
int& segMin, int& segMax);
|
||||
|
||||
bool dtPointInPolygon(const float* pt, const float* verts, const int nverts);
|
||||
|
||||
bool dtDistancePtPolyEdgesSqr(const float* pt, const float* verts, const int nverts,
|
||||
float* ed, float* et);
|
||||
|
||||
float dtDistancePtSegSqr2D(const float* pt, const float* p, const float* q, float& t);
|
||||
|
||||
void dtCalcPolyCenter(float* tc, const unsigned short* idx, int nidx, const float* verts);
|
||||
|
||||
bool dtOverlapPolyPoly2D(const float* polya, const int npolya,
|
||||
const float* polyb, const int npolyb);
|
||||
|
||||
#endif // DETOURCOMMON_H
|
||||
1235
dep/recastnavigation/Detour/DetourNavMesh.cpp
Normal file
1235
dep/recastnavigation/Detour/DetourNavMesh.cpp
Normal file
File diff suppressed because it is too large
Load Diff
428
dep/recastnavigation/Detour/DetourNavMesh.h
Normal file
428
dep/recastnavigation/Detour/DetourNavMesh.h
Normal file
@@ -0,0 +1,428 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef DETOURNAVMESH_H
|
||||
#define DETOURNAVMESH_H
|
||||
|
||||
#include "DetourAlloc.h"
|
||||
|
||||
#ifdef WIN32
|
||||
typedef unsigned __int64 uint64;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#ifndef uint64_t
|
||||
#ifdef __linux__
|
||||
#include <linux/types.h>
|
||||
#endif
|
||||
#endif
|
||||
typedef uint64_t uint64;
|
||||
#endif
|
||||
|
||||
// Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef.
|
||||
// It is also recommended to change dtHashRef() to proper 64-bit hash too.
|
||||
|
||||
// Reference to navigation polygon.
|
||||
typedef uint64 dtPolyRef;
|
||||
|
||||
// Reference to navigation mesh tile.
|
||||
typedef uint64 dtTileRef;
|
||||
|
||||
// Maximum number of vertices per navigation polygon.
|
||||
static const int DT_VERTS_PER_POLYGON = 6;
|
||||
|
||||
static const int DT_NAVMESH_MAGIC = 'D'<<24 | 'N'<<16 | 'A'<<8 | 'V'; //'DNAV';
|
||||
static const int DT_NAVMESH_VERSION = 6;
|
||||
|
||||
static const int DT_NAVMESH_STATE_MAGIC = 'D'<<24 | 'N'<<16 | 'M'<<8 | 'S'; //'DNMS';
|
||||
static const int DT_NAVMESH_STATE_VERSION = 1;
|
||||
|
||||
static const unsigned short DT_EXT_LINK = 0x8000;
|
||||
static const unsigned int DT_NULL_LINK = 0xffffffff;
|
||||
static const unsigned int DT_OFFMESH_CON_BIDIR = 1;
|
||||
|
||||
static const int DT_MAX_AREAS = 64;
|
||||
|
||||
static const int STATIC_SALT_BITS = 12;
|
||||
static const int STATIC_TILE_BITS = 21;
|
||||
static const int STATIC_POLY_BITS = 31;
|
||||
// we cannot have over 31 bits for either tile nor poly
|
||||
// without changing polyCount to use 64bits too.
|
||||
|
||||
// Flags for addTile
|
||||
enum dtTileFlags
|
||||
{
|
||||
DT_TILE_FREE_DATA = 0x01, // Navmesh owns the tile memory and should free it.
|
||||
};
|
||||
|
||||
// Flags returned by findStraightPath().
|
||||
enum dtStraightPathFlags
|
||||
{
|
||||
DT_STRAIGHTPATH_START = 0x01, // The vertex is the start position.
|
||||
DT_STRAIGHTPATH_END = 0x02, // The vertex is the end position.
|
||||
DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, // The vertex is start of an off-mesh link.
|
||||
};
|
||||
|
||||
// Flags describing polygon properties.
|
||||
enum dtPolyTypes
|
||||
{
|
||||
DT_POLYTYPE_GROUND = 0, // Regular ground polygons.
|
||||
DT_POLYTYPE_OFFMESH_CONNECTION = 1, // Off-mesh connections.
|
||||
};
|
||||
|
||||
enum dtStatus
|
||||
{
|
||||
DT_FAILURE = 0, // Operation failed.
|
||||
DT_FAILURE_DATA_MAGIC,
|
||||
DT_FAILURE_DATA_VERSION,
|
||||
DT_FAILURE_OUT_OF_MEMORY,
|
||||
DT_SUCCESS, // Operation succeed.
|
||||
DT_IN_PROGRESS, // Operation still in progress.
|
||||
};
|
||||
|
||||
|
||||
// Structure describing the navigation polygon data.
|
||||
struct dtPoly
|
||||
{
|
||||
unsigned int firstLink; // Index to first link in linked list.
|
||||
unsigned short verts[DT_VERTS_PER_POLYGON]; // Indices to vertices of the poly.
|
||||
unsigned short neis[DT_VERTS_PER_POLYGON]; // Refs to neighbours of the poly.
|
||||
unsigned short flags; // Flags (see dtPolyFlags).
|
||||
unsigned char vertCount; // Number of vertices.
|
||||
unsigned char areaAndtype; // Bit packed: Area ID of the polygon, and Polygon type, see dtPolyTypes..
|
||||
inline void setArea(unsigned char a) { areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f); }
|
||||
inline void setType(unsigned char t) { areaAndtype = (areaAndtype & 0x3f) | (t << 6); }
|
||||
inline unsigned char getArea() const { return areaAndtype & 0x3f; }
|
||||
inline unsigned char getType() const { return areaAndtype >> 6; }
|
||||
};
|
||||
|
||||
// Stucture describing polygon detail triangles.
|
||||
struct dtPolyDetail
|
||||
{
|
||||
unsigned int vertBase; // Offset to detail vertex array.
|
||||
unsigned int triBase; // Offset to detail triangle array.
|
||||
unsigned char vertCount; // Number of vertices in the detail mesh.
|
||||
unsigned char triCount; // Number of triangles.
|
||||
};
|
||||
|
||||
// Stucture describing a link to another polygon.
|
||||
struct dtLink
|
||||
{
|
||||
dtPolyRef ref; // Neighbour reference.
|
||||
unsigned int next; // Index to next link.
|
||||
unsigned char edge; // Index to polygon edge which owns this link.
|
||||
unsigned char side; // If boundary link, defines on which side the link is.
|
||||
unsigned char bmin, bmax; // If boundary link, defines the sub edge area.
|
||||
};
|
||||
|
||||
struct dtBVNode
|
||||
{
|
||||
unsigned short bmin[3], bmax[3]; // BVnode bounds
|
||||
int i; // Index to item or if negative, escape index.
|
||||
};
|
||||
|
||||
struct dtOffMeshConnection
|
||||
{
|
||||
float pos[6]; // Both end point locations.
|
||||
float rad; // Link connection radius.
|
||||
unsigned short poly; // Poly Id
|
||||
unsigned char flags; // Link flags
|
||||
unsigned char side; // End point side.
|
||||
unsigned int userId; // User ID to identify this connection.
|
||||
};
|
||||
|
||||
struct dtMeshHeader
|
||||
{
|
||||
int magic; // Magic number, used to identify the data.
|
||||
int version; // Data version number.
|
||||
int x, y; // Location of the time on the grid.
|
||||
unsigned int userId; // User ID of the tile.
|
||||
int polyCount; // Number of polygons in the tile.
|
||||
int vertCount; // Number of vertices in the tile.
|
||||
int maxLinkCount; // Number of allocated links.
|
||||
int detailMeshCount; // Number of detail meshes.
|
||||
int detailVertCount; // Number of detail vertices.
|
||||
int detailTriCount; // Number of detail triangles.
|
||||
int bvNodeCount; // Number of BVtree nodes.
|
||||
int offMeshConCount; // Number of Off-Mesh links.
|
||||
int offMeshBase; // Index to first polygon which is Off-Mesh link.
|
||||
float walkableHeight; // Height of the agent.
|
||||
float walkableRadius; // Radius of the agent
|
||||
float walkableClimb; // Max climb height of the agent.
|
||||
float bmin[3], bmax[3]; // Bounding box of the tile.
|
||||
float bvQuantFactor; // BVtree quantization factor (world to bvnode coords)
|
||||
};
|
||||
|
||||
struct dtMeshTile
|
||||
{
|
||||
unsigned int salt; // Counter describing modifications to the tile.
|
||||
|
||||
unsigned int linksFreeList; // Index to next free link.
|
||||
dtMeshHeader* header; // Pointer to tile header.
|
||||
dtPoly* polys; // Pointer to the polygons (will be updated when tile is added).
|
||||
float* verts; // Pointer to the vertices (will be updated when tile added).
|
||||
dtLink* links; // Pointer to the links (will be updated when tile added).
|
||||
dtPolyDetail* detailMeshes; // Pointer to detail meshes (will be updated when tile added).
|
||||
float* detailVerts; // Pointer to detail vertices (will be updated when tile added).
|
||||
unsigned char* detailTris; // Pointer to detail triangles (will be updated when tile added).
|
||||
dtBVNode* bvTree; // Pointer to BVtree nodes (will be updated when tile added).
|
||||
dtOffMeshConnection* offMeshCons; // Pointer to Off-Mesh links. (will be updated when tile added).
|
||||
|
||||
unsigned char* data; // Pointer to tile data.
|
||||
int dataSize; // Size of the tile data.
|
||||
int flags; // Tile flags, see dtTileFlags.
|
||||
dtMeshTile* next; // Next free tile or, next tile in spatial grid.
|
||||
};
|
||||
|
||||
struct dtNavMeshParams
|
||||
{
|
||||
float orig[3]; // Origin of the nav mesh tile space.
|
||||
float tileWidth, tileHeight; // Width and height of each tile.
|
||||
int maxTiles; // Maximum number of tiles the navmesh can contain.
|
||||
int maxPolys; // Maximum number of polygons each tile can contain.
|
||||
};
|
||||
|
||||
|
||||
class dtNavMesh
|
||||
{
|
||||
public:
|
||||
dtNavMesh();
|
||||
~dtNavMesh();
|
||||
|
||||
// Initializes the nav mesh for tiled use.
|
||||
// Params:
|
||||
// params - (in) navmesh initialization params, see dtNavMeshParams.
|
||||
// Returns: True if succeed, else false.
|
||||
dtStatus init(const dtNavMeshParams* params);
|
||||
|
||||
// Initializes the nav mesh for single tile use.
|
||||
// Params:
|
||||
// data - (in) Data of the new tile mesh.
|
||||
// dataSize - (in) Data size of the new tile mesh.
|
||||
// flags - (in) Tile flags, see dtTileFlags.
|
||||
// Returns: True if succeed, else false.
|
||||
dtStatus init(unsigned char* data, const int dataSize, const int flags);
|
||||
|
||||
// Returns pointer to navmesh initialization params.
|
||||
const dtNavMeshParams* getParams() const;
|
||||
|
||||
// Adds new tile into the navmesh.
|
||||
// The add will fail if the data is in wrong format,
|
||||
// there is not enough tiles left, or if there is a tile already at the location.
|
||||
// Params:
|
||||
// data - (in) Data of the new tile mesh.
|
||||
// dataSize - (in) Data size of the new tile mesh.
|
||||
// flags - (in) Tile flags, see dtTileFlags.
|
||||
// lastRef - (in,optional) Last tile ref, the tile will be restored so that
|
||||
// the reference (as well as poly references) will be the same. Default: 0.
|
||||
// result - (out,optional) tile ref if the tile was succesfully added.
|
||||
dtStatus addTile(unsigned char* data, int dataSize, int flags, dtTileRef lastRef, dtTileRef* result);
|
||||
|
||||
// Removes specified tile.
|
||||
// Params:
|
||||
// ref - (in) Reference to the tile to remove.
|
||||
// data - (out) Data associated with deleted tile.
|
||||
// dataSize - (out) Size of the data associated with deleted tile.
|
||||
dtStatus removeTile(dtTileRef ref, unsigned char** data, int* dataSize);
|
||||
|
||||
// Calculates tile location based in input world position.
|
||||
// Params:
|
||||
// pos - (in) world position of the query.
|
||||
// tx - (out) tile x location.
|
||||
// ty - (out) tile y location.
|
||||
void calcTileLoc(const float* pos, int* tx, int* ty) const;
|
||||
|
||||
// Returns pointer to tile at specified location.
|
||||
// Params:
|
||||
// x,y - (in) Location of the tile to get.
|
||||
// Returns: pointer to tile if tile exists or 0 tile does not exists.
|
||||
const dtMeshTile* getTileAt(int x, int y) const;
|
||||
|
||||
// Returns reference to tile at specified location.
|
||||
// Params:
|
||||
// x,y - (in) Location of the tile to get.
|
||||
// Returns: reference to tile if tile exists or 0 tile does not exists.
|
||||
dtTileRef getTileRefAt(int x, int y) const;
|
||||
|
||||
// Returns tile references of a tile based on tile pointer.
|
||||
dtTileRef getTileRef(const dtMeshTile* tile) const;
|
||||
|
||||
// Returns tile based on references.
|
||||
const dtMeshTile* getTileByRef(dtTileRef ref) const;
|
||||
|
||||
// Returns max number of tiles.
|
||||
int getMaxTiles() const;
|
||||
|
||||
// Returns pointer to tile in the tile array.
|
||||
// Params:
|
||||
// i - (in) Index to the tile to retrieve, max index is getMaxTiles()-1.
|
||||
// Returns: Pointer to specified tile.
|
||||
const dtMeshTile* getTile(int i) const;
|
||||
|
||||
// Returns pointer to tile and polygon pointed by the polygon reference.
|
||||
// Params:
|
||||
// ref - (in) reference to a polygon.
|
||||
// tile - (out) pointer to the tile containing the polygon.
|
||||
// poly - (out) pointer to the polygon.
|
||||
dtStatus getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const;
|
||||
|
||||
// Returns pointer to tile and polygon pointed by the polygon reference.
|
||||
// Note: this function does not check if 'ref' s valid, and is thus faster. Use only with valid refs!
|
||||
// Params:
|
||||
// ref - (in) reference to a polygon.
|
||||
// tile - (out) pointer to the tile containing the polygon.
|
||||
// poly - (out) pointer to the polygon.
|
||||
void getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const;
|
||||
|
||||
// Returns true if polygon reference points to valid data.
|
||||
bool isValidPolyRef(dtPolyRef ref) const;
|
||||
|
||||
// Returns base poly id for specified tile, polygon refs can be deducted from this.
|
||||
dtPolyRef getPolyRefBase(const dtMeshTile* tile) const;
|
||||
|
||||
// Returns start and end location of an off-mesh link polygon.
|
||||
// Params:
|
||||
// prevRef - (in) ref to the polygon before the link (used to select direction).
|
||||
// polyRef - (in) ref to the off-mesh link polygon.
|
||||
// startPos[3] - (out) start point of the link.
|
||||
// endPos[3] - (out) end point of the link.
|
||||
// Returns: true if link is found.
|
||||
dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const;
|
||||
|
||||
// Returns pointer to off-mesh connection based on polyref, or null if ref not valid.
|
||||
const dtOffMeshConnection* getOffMeshConnectionByRef(dtPolyRef ref) const;
|
||||
|
||||
// Sets polygon flags.
|
||||
dtStatus setPolyFlags(dtPolyRef ref, unsigned short flags);
|
||||
|
||||
// Return polygon flags.
|
||||
dtStatus getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const;
|
||||
|
||||
// Set polygon type.
|
||||
dtStatus setPolyArea(dtPolyRef ref, unsigned char area);
|
||||
|
||||
// Return polygon area type.
|
||||
dtStatus getPolyArea(dtPolyRef ref, unsigned char* resultArea) const;
|
||||
|
||||
|
||||
// Returns number of bytes required to store tile state.
|
||||
int getTileStateSize(const dtMeshTile* tile) const;
|
||||
|
||||
// Stores tile state to buffer.
|
||||
dtStatus storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const;
|
||||
|
||||
// Restores tile state.
|
||||
dtStatus restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize);
|
||||
|
||||
|
||||
// Encodes a tile id.
|
||||
inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const
|
||||
{
|
||||
return ((dtPolyRef)salt << (m_polyBits+m_tileBits)) | ((dtPolyRef)it << m_polyBits) | (dtPolyRef)ip;
|
||||
}
|
||||
|
||||
// Decodes a tile id.
|
||||
inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const
|
||||
{
|
||||
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
|
||||
const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
|
||||
const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
|
||||
salt = (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
|
||||
it = (unsigned int)((ref >> m_polyBits) & tileMask);
|
||||
ip = (unsigned int)(ref & polyMask);
|
||||
}
|
||||
|
||||
// Decodes a tile salt.
|
||||
inline unsigned int decodePolyIdSalt(dtPolyRef ref) const
|
||||
{
|
||||
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
|
||||
return (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
|
||||
}
|
||||
|
||||
// Decodes a tile id.
|
||||
inline unsigned int decodePolyIdTile(dtPolyRef ref) const
|
||||
{
|
||||
const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
|
||||
return (unsigned int)((ref >> m_polyBits) & tileMask);
|
||||
}
|
||||
|
||||
// Decodes a poly id.
|
||||
inline unsigned int decodePolyIdPoly(dtPolyRef ref) const
|
||||
{
|
||||
const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
|
||||
return (unsigned int)(ref & polyMask);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Returns pointer to tile in the tile array.
|
||||
dtMeshTile* getTile(int i);
|
||||
|
||||
// Returns neighbour tile based on side.
|
||||
dtMeshTile* getNeighbourTileAt(int x, int y, int side) const;
|
||||
// Returns all polygons in neighbour tile based on portal defined by the segment.
|
||||
int findConnectingPolys(const float* va, const float* vb,
|
||||
const dtMeshTile* tile, int side,
|
||||
dtPolyRef* con, float* conarea, int maxcon) const;
|
||||
|
||||
// Builds internal polygons links for a tile.
|
||||
void connectIntLinks(dtMeshTile* tile);
|
||||
// Builds internal polygons links for a tile.
|
||||
void connectIntOffMeshLinks(dtMeshTile* tile);
|
||||
|
||||
// Builds external polygon links for a tile.
|
||||
void connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side);
|
||||
// Builds external polygon links for a tile.
|
||||
void connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int side);
|
||||
|
||||
// Removes external links at specified side.
|
||||
void unconnectExtLinks(dtMeshTile* tile, int side);
|
||||
|
||||
|
||||
// TODO: These methods are duplicates from dtNavMeshQuery, but are needed for off-mesh connection finding.
|
||||
|
||||
// Queries polygons within a tile.
|
||||
int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax,
|
||||
dtPolyRef* polys, const int maxPolys) const;
|
||||
// Find nearest polygon within a tile.
|
||||
dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center,
|
||||
const float* extents, float* nearestPt) const;
|
||||
// Returns closest point on polygon.
|
||||
dtStatus closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip,
|
||||
const float* pos, float* closest) const;
|
||||
|
||||
dtNavMeshParams m_params; // Current initialization params. TODO: do not store this info twice.
|
||||
float m_orig[3]; // Origin of the tile (0,0)
|
||||
float m_tileWidth, m_tileHeight; // Dimensions of each tile.
|
||||
int m_maxTiles; // Max number of tiles.
|
||||
int m_tileLutSize; // Tile hash lookup size (must be pot).
|
||||
int m_tileLutMask; // Tile hash lookup mask.
|
||||
|
||||
dtMeshTile** m_posLookup; // Tile hash lookup.
|
||||
dtMeshTile* m_nextFree; // Freelist of tiles.
|
||||
dtMeshTile* m_tiles; // List of tiles.
|
||||
|
||||
unsigned int m_saltBits; // Number of salt bits in the tile ID.
|
||||
unsigned int m_tileBits; // Number of tile bits in the tile ID.
|
||||
unsigned int m_polyBits; // Number of poly bits in the tile ID.
|
||||
};
|
||||
|
||||
// Helper function to allocate navmesh class using Detour allocator.
|
||||
dtNavMesh* dtAllocNavMesh();
|
||||
void dtFreeNavMesh(dtNavMesh* navmesh);
|
||||
|
||||
#endif // DETOURNAVMESH_H
|
||||
717
dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp
Normal file
717
dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp
Normal file
@@ -0,0 +1,717 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "DetourNavMesh.h"
|
||||
#include "DetourCommon.h"
|
||||
#include "DetourNavMeshBuilder.h"
|
||||
#include "DetourAlloc.h"
|
||||
#include "DetourAssert.h"
|
||||
|
||||
static unsigned short MESH_NULL_IDX = 0xffff;
|
||||
|
||||
|
||||
struct BVItem
|
||||
{
|
||||
unsigned short bmin[3];
|
||||
unsigned short bmax[3];
|
||||
int i;
|
||||
};
|
||||
|
||||
static int compareItemX(const void* va, const void* vb)
|
||||
{
|
||||
const BVItem* a = (const BVItem*)va;
|
||||
const BVItem* b = (const BVItem*)vb;
|
||||
if (a->bmin[0] < b->bmin[0])
|
||||
return -1;
|
||||
if (a->bmin[0] > b->bmin[0])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compareItemY(const void* va, const void* vb)
|
||||
{
|
||||
const BVItem* a = (const BVItem*)va;
|
||||
const BVItem* b = (const BVItem*)vb;
|
||||
if (a->bmin[1] < b->bmin[1])
|
||||
return -1;
|
||||
if (a->bmin[1] > b->bmin[1])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compareItemZ(const void* va, const void* vb)
|
||||
{
|
||||
const BVItem* a = (const BVItem*)va;
|
||||
const BVItem* b = (const BVItem*)vb;
|
||||
if (a->bmin[2] < b->bmin[2])
|
||||
return -1;
|
||||
if (a->bmin[2] > b->bmin[2])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void calcExtends(BVItem* items, const int /*nitems*/, const int imin, const int imax,
|
||||
unsigned short* bmin, unsigned short* bmax)
|
||||
{
|
||||
bmin[0] = items[imin].bmin[0];
|
||||
bmin[1] = items[imin].bmin[1];
|
||||
bmin[2] = items[imin].bmin[2];
|
||||
|
||||
bmax[0] = items[imin].bmax[0];
|
||||
bmax[1] = items[imin].bmax[1];
|
||||
bmax[2] = items[imin].bmax[2];
|
||||
|
||||
for (int i = imin+1; i < imax; ++i)
|
||||
{
|
||||
const BVItem& it = items[i];
|
||||
if (it.bmin[0] < bmin[0]) bmin[0] = it.bmin[0];
|
||||
if (it.bmin[1] < bmin[1]) bmin[1] = it.bmin[1];
|
||||
if (it.bmin[2] < bmin[2]) bmin[2] = it.bmin[2];
|
||||
|
||||
if (it.bmax[0] > bmax[0]) bmax[0] = it.bmax[0];
|
||||
if (it.bmax[1] > bmax[1]) bmax[1] = it.bmax[1];
|
||||
if (it.bmax[2] > bmax[2]) bmax[2] = it.bmax[2];
|
||||
}
|
||||
}
|
||||
|
||||
inline int longestAxis(unsigned short x, unsigned short y, unsigned short z)
|
||||
{
|
||||
int axis = 0;
|
||||
unsigned short maxVal = x;
|
||||
if (y > maxVal)
|
||||
{
|
||||
axis = 1;
|
||||
maxVal = y;
|
||||
}
|
||||
if (z > maxVal)
|
||||
{
|
||||
axis = 2;
|
||||
maxVal = z;
|
||||
}
|
||||
return axis;
|
||||
}
|
||||
|
||||
static void subdivide(BVItem* items, int nitems, int imin, int imax, int& curNode, dtBVNode* nodes)
|
||||
{
|
||||
int inum = imax - imin;
|
||||
int icur = curNode;
|
||||
|
||||
dtBVNode& node = nodes[curNode++];
|
||||
|
||||
if (inum == 1)
|
||||
{
|
||||
// Leaf
|
||||
node.bmin[0] = items[imin].bmin[0];
|
||||
node.bmin[1] = items[imin].bmin[1];
|
||||
node.bmin[2] = items[imin].bmin[2];
|
||||
|
||||
node.bmax[0] = items[imin].bmax[0];
|
||||
node.bmax[1] = items[imin].bmax[1];
|
||||
node.bmax[2] = items[imin].bmax[2];
|
||||
|
||||
node.i = items[imin].i;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Split
|
||||
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
|
||||
|
||||
int axis = longestAxis(node.bmax[0] - node.bmin[0],
|
||||
node.bmax[1] - node.bmin[1],
|
||||
node.bmax[2] - node.bmin[2]);
|
||||
|
||||
if (axis == 0)
|
||||
{
|
||||
// Sort along x-axis
|
||||
qsort(items+imin, inum, sizeof(BVItem), compareItemX);
|
||||
}
|
||||
else if (axis == 1)
|
||||
{
|
||||
// Sort along y-axis
|
||||
qsort(items+imin, inum, sizeof(BVItem), compareItemY);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sort along z-axis
|
||||
qsort(items+imin, inum, sizeof(BVItem), compareItemZ);
|
||||
}
|
||||
|
||||
int isplit = imin+inum/2;
|
||||
|
||||
// Left
|
||||
subdivide(items, nitems, imin, isplit, curNode, nodes);
|
||||
// Right
|
||||
subdivide(items, nitems, isplit, imax, curNode, nodes);
|
||||
|
||||
int iescape = curNode - icur;
|
||||
// Negative index means escape.
|
||||
node.i = -iescape;
|
||||
}
|
||||
}
|
||||
|
||||
static int createBVTree(const unsigned short* verts, const int /*nverts*/,
|
||||
const unsigned short* polys, const int npolys, const int nvp,
|
||||
const float cs, const float ch,
|
||||
const int /*nnodes*/, dtBVNode* nodes)
|
||||
{
|
||||
// Build tree
|
||||
BVItem* items = (BVItem*)dtAlloc(sizeof(BVItem)*npolys, DT_ALLOC_TEMP);
|
||||
for (int i = 0; i < npolys; i++)
|
||||
{
|
||||
BVItem& it = items[i];
|
||||
it.i = i;
|
||||
// Calc polygon bounds.
|
||||
const unsigned short* p = &polys[i*nvp*2];
|
||||
it.bmin[0] = it.bmax[0] = verts[p[0]*3+0];
|
||||
it.bmin[1] = it.bmax[1] = verts[p[0]*3+1];
|
||||
it.bmin[2] = it.bmax[2] = verts[p[0]*3+2];
|
||||
|
||||
for (int j = 1; j < nvp; ++j)
|
||||
{
|
||||
if (p[j] == MESH_NULL_IDX) break;
|
||||
unsigned short x = verts[p[j]*3+0];
|
||||
unsigned short y = verts[p[j]*3+1];
|
||||
unsigned short z = verts[p[j]*3+2];
|
||||
|
||||
if (x < it.bmin[0]) it.bmin[0] = x;
|
||||
if (y < it.bmin[1]) it.bmin[1] = y;
|
||||
if (z < it.bmin[2]) it.bmin[2] = z;
|
||||
|
||||
if (x > it.bmax[0]) it.bmax[0] = x;
|
||||
if (y > it.bmax[1]) it.bmax[1] = y;
|
||||
if (z > it.bmax[2]) it.bmax[2] = z;
|
||||
}
|
||||
// Remap y
|
||||
it.bmin[1] = (unsigned short)floorf((float)it.bmin[1]*ch/cs);
|
||||
it.bmax[1] = (unsigned short)ceilf((float)it.bmax[1]*ch/cs);
|
||||
}
|
||||
|
||||
int curNode = 0;
|
||||
subdivide(items, npolys, 0, npolys, curNode, nodes);
|
||||
|
||||
dtFree(items);
|
||||
|
||||
return curNode;
|
||||
}
|
||||
|
||||
static unsigned char classifyOffMeshPoint(const float* pt, const float* bmin, const float* bmax)
|
||||
{
|
||||
static const unsigned char XP = 1<<0;
|
||||
static const unsigned char ZP = 1<<1;
|
||||
static const unsigned char XM = 1<<2;
|
||||
static const unsigned char ZM = 1<<3;
|
||||
|
||||
unsigned char outcode = 0;
|
||||
outcode |= (pt[0] >= bmax[0]) ? XP : 0;
|
||||
outcode |= (pt[2] >= bmax[2]) ? ZP : 0;
|
||||
outcode |= (pt[0] < bmin[0]) ? XM : 0;
|
||||
outcode |= (pt[2] < bmin[2]) ? ZM : 0;
|
||||
|
||||
switch (outcode)
|
||||
{
|
||||
case XP: return 0;
|
||||
case XP|ZP: return 1;
|
||||
case ZP: return 2;
|
||||
case XM|ZP: return 3;
|
||||
case XM: return 4;
|
||||
case XM|ZM: return 5;
|
||||
case ZM: return 6;
|
||||
case XP|ZM: return 7;
|
||||
};
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
// TODO: Better error handling.
|
||||
|
||||
bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize)
|
||||
{
|
||||
if (params->nvp > DT_VERTS_PER_POLYGON)
|
||||
return false;
|
||||
if (params->vertCount >= 0xffff)
|
||||
return false;
|
||||
if (!params->vertCount || !params->verts)
|
||||
return false;
|
||||
if (!params->polyCount || !params->polys)
|
||||
return false;
|
||||
if (!params->detailMeshes || !params->detailVerts || !params->detailTris)
|
||||
return false;
|
||||
|
||||
const int nvp = params->nvp;
|
||||
|
||||
// Classify off-mesh connection points. We store only the connections
|
||||
// whose start point is inside the tile.
|
||||
unsigned char* offMeshConClass = 0;
|
||||
int storedOffMeshConCount = 0;
|
||||
int offMeshConLinkCount = 0;
|
||||
|
||||
if (params->offMeshConCount > 0)
|
||||
{
|
||||
offMeshConClass = (unsigned char*)dtAlloc(sizeof(unsigned char)*params->offMeshConCount*2, DT_ALLOC_TEMP);
|
||||
if (!offMeshConClass)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < params->offMeshConCount; ++i)
|
||||
{
|
||||
offMeshConClass[i*2+0] = classifyOffMeshPoint(¶ms->offMeshConVerts[(i*2+0)*3], params->bmin, params->bmax);
|
||||
offMeshConClass[i*2+1] = classifyOffMeshPoint(¶ms->offMeshConVerts[(i*2+1)*3], params->bmin, params->bmax);
|
||||
|
||||
// Cound how many links should be allocated for off-mesh connections.
|
||||
if (offMeshConClass[i*2+0] == 0xff)
|
||||
offMeshConLinkCount++;
|
||||
if (offMeshConClass[i*2+1] == 0xff)
|
||||
offMeshConLinkCount++;
|
||||
|
||||
if (offMeshConClass[i*2+0] == 0xff)
|
||||
storedOffMeshConCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Off-mesh connectionss are stored as polygons, adjust values.
|
||||
const int totPolyCount = params->polyCount + storedOffMeshConCount;
|
||||
const int totVertCount = params->vertCount + storedOffMeshConCount*2;
|
||||
|
||||
// Find portal edges which are at tile borders.
|
||||
int edgeCount = 0;
|
||||
int portalCount = 0;
|
||||
for (int i = 0; i < params->polyCount; ++i)
|
||||
{
|
||||
const unsigned short* p = ¶ms->polys[i*2*nvp];
|
||||
for (int j = 0; j < nvp; ++j)
|
||||
{
|
||||
if (p[j] == MESH_NULL_IDX) break;
|
||||
int nj = j+1;
|
||||
if (nj >= nvp || p[nj] == MESH_NULL_IDX) nj = 0;
|
||||
const unsigned short* va = ¶ms->verts[p[j]*3];
|
||||
const unsigned short* vb = ¶ms->verts[p[nj]*3];
|
||||
|
||||
edgeCount++;
|
||||
|
||||
if (params->tileSize > 0)
|
||||
{
|
||||
if (va[0] == params->tileSize && vb[0] == params->tileSize)
|
||||
portalCount++; // x+
|
||||
else if (va[2] == params->tileSize && vb[2] == params->tileSize)
|
||||
portalCount++; // z+
|
||||
else if (va[0] == 0 && vb[0] == 0)
|
||||
portalCount++; // x-
|
||||
else if (va[2] == 0 && vb[2] == 0)
|
||||
portalCount++; // z-
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int maxLinkCount = edgeCount + portalCount*2 + offMeshConLinkCount*2;
|
||||
|
||||
// Find unique detail vertices.
|
||||
int uniqueDetailVertCount = 0;
|
||||
for (int i = 0; i < params->polyCount; ++i)
|
||||
{
|
||||
const unsigned short* p = ¶ms->polys[i*nvp*2];
|
||||
int ndv = params->detailMeshes[i*4+1];
|
||||
int nv = 0;
|
||||
for (int j = 0; j < nvp; ++j)
|
||||
{
|
||||
if (p[j] == MESH_NULL_IDX) break;
|
||||
nv++;
|
||||
}
|
||||
ndv -= nv;
|
||||
uniqueDetailVertCount += ndv;
|
||||
}
|
||||
|
||||
// Calculate data size
|
||||
const int headerSize = dtAlign4(sizeof(dtMeshHeader));
|
||||
const int vertsSize = dtAlign4(sizeof(float)*3*totVertCount);
|
||||
const int polysSize = dtAlign4(sizeof(dtPoly)*totPolyCount);
|
||||
const int linksSize = dtAlign4(sizeof(dtLink)*maxLinkCount);
|
||||
const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*params->polyCount);
|
||||
const int detailVertsSize = dtAlign4(sizeof(float)*3*uniqueDetailVertCount);
|
||||
const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*params->detailTriCount);
|
||||
const int bvTreeSize = dtAlign4(sizeof(dtBVNode)*params->polyCount*2);
|
||||
const int offMeshConsSize = dtAlign4(sizeof(dtOffMeshConnection)*storedOffMeshConCount);
|
||||
|
||||
const int dataSize = headerSize + vertsSize + polysSize + linksSize +
|
||||
detailMeshesSize + detailVertsSize + detailTrisSize +
|
||||
bvTreeSize + offMeshConsSize;
|
||||
|
||||
unsigned char* data = (unsigned char*)dtAlloc(sizeof(unsigned char)*dataSize, DT_ALLOC_PERM);
|
||||
if (!data)
|
||||
{
|
||||
dtFree(offMeshConClass);
|
||||
return false;
|
||||
}
|
||||
memset(data, 0, dataSize);
|
||||
|
||||
unsigned char* d = data;
|
||||
dtMeshHeader* header = (dtMeshHeader*)d; d += headerSize;
|
||||
float* navVerts = (float*)d; d += vertsSize;
|
||||
dtPoly* navPolys = (dtPoly*)d; d += polysSize;
|
||||
d += linksSize;
|
||||
dtPolyDetail* navDMeshes = (dtPolyDetail*)d; d += detailMeshesSize;
|
||||
float* navDVerts = (float*)d; d += detailVertsSize;
|
||||
unsigned char* navDTris = (unsigned char*)d; d += detailTrisSize;
|
||||
dtBVNode* navBvtree = (dtBVNode*)d; d += bvTreeSize;
|
||||
dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshConsSize;
|
||||
|
||||
|
||||
// Store header
|
||||
header->magic = DT_NAVMESH_MAGIC;
|
||||
header->version = DT_NAVMESH_VERSION;
|
||||
header->x = params->tileX;
|
||||
header->y = params->tileY;
|
||||
header->userId = params->userId;
|
||||
header->polyCount = totPolyCount;
|
||||
header->vertCount = totVertCount;
|
||||
header->maxLinkCount = maxLinkCount;
|
||||
dtVcopy(header->bmin, params->bmin);
|
||||
dtVcopy(header->bmax, params->bmax);
|
||||
header->detailMeshCount = params->polyCount;
|
||||
header->detailVertCount = uniqueDetailVertCount;
|
||||
header->detailTriCount = params->detailTriCount;
|
||||
header->bvQuantFactor = 1.0f / params->cs;
|
||||
header->offMeshBase = params->polyCount;
|
||||
header->walkableHeight = params->walkableHeight;
|
||||
header->walkableRadius = params->walkableRadius;
|
||||
header->walkableClimb = params->walkableClimb;
|
||||
header->offMeshConCount = storedOffMeshConCount;
|
||||
header->bvNodeCount = params->polyCount*2;
|
||||
|
||||
const int offMeshVertsBase = params->vertCount;
|
||||
const int offMeshPolyBase = params->polyCount;
|
||||
|
||||
// Store vertices
|
||||
// Mesh vertices
|
||||
for (int i = 0; i < params->vertCount; ++i)
|
||||
{
|
||||
const unsigned short* iv = ¶ms->verts[i*3];
|
||||
float* v = &navVerts[i*3];
|
||||
v[0] = params->bmin[0] + iv[0] * params->cs;
|
||||
v[1] = params->bmin[1] + iv[1] * params->ch;
|
||||
v[2] = params->bmin[2] + iv[2] * params->cs;
|
||||
}
|
||||
// Off-mesh link vertices.
|
||||
int n = 0;
|
||||
for (int i = 0; i < params->offMeshConCount; ++i)
|
||||
{
|
||||
// Only store connections which start from this tile.
|
||||
if (offMeshConClass[i*2+0] == 0xff)
|
||||
{
|
||||
const float* linkv = ¶ms->offMeshConVerts[i*2*3];
|
||||
float* v = &navVerts[(offMeshVertsBase + n*2)*3];
|
||||
dtVcopy(&v[0], &linkv[0]);
|
||||
dtVcopy(&v[3], &linkv[3]);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
// Store polygons
|
||||
// Mesh polys
|
||||
const unsigned short* src = params->polys;
|
||||
for (int i = 0; i < params->polyCount; ++i)
|
||||
{
|
||||
dtPoly* p = &navPolys[i];
|
||||
p->vertCount = 0;
|
||||
p->flags = params->polyFlags[i];
|
||||
p->setArea(params->polyAreas[i]);
|
||||
p->setType(DT_POLYTYPE_GROUND);
|
||||
for (int j = 0; j < nvp; ++j)
|
||||
{
|
||||
if (src[j] == MESH_NULL_IDX) break;
|
||||
p->verts[j] = src[j];
|
||||
p->neis[j] = (src[nvp+j]+1) & 0xffff;
|
||||
p->vertCount++;
|
||||
}
|
||||
src += nvp*2;
|
||||
}
|
||||
// Off-mesh connection vertices.
|
||||
n = 0;
|
||||
for (int i = 0; i < params->offMeshConCount; ++i)
|
||||
{
|
||||
// Only store connections which start from this tile.
|
||||
if (offMeshConClass[i*2+0] == 0xff)
|
||||
{
|
||||
dtPoly* p = &navPolys[offMeshPolyBase+n];
|
||||
p->vertCount = 2;
|
||||
p->verts[0] = (unsigned short)(offMeshVertsBase + n*2+0);
|
||||
p->verts[1] = (unsigned short)(offMeshVertsBase + n*2+1);
|
||||
p->flags = params->offMeshConFlags[i];
|
||||
p->setArea(params->offMeshConAreas[i]);
|
||||
p->setType(DT_POLYTYPE_OFFMESH_CONNECTION);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
// Store portal edges.
|
||||
if (params->tileSize > 0)
|
||||
{
|
||||
for (int i = 0; i < params->polyCount; ++i)
|
||||
{
|
||||
dtPoly* poly = &navPolys[i];
|
||||
for (int j = 0; j < poly->vertCount; ++j)
|
||||
{
|
||||
int nj = j+1;
|
||||
if (nj >= poly->vertCount) nj = 0;
|
||||
|
||||
const unsigned short* va = ¶ms->verts[poly->verts[j]*3];
|
||||
const unsigned short* vb = ¶ms->verts[poly->verts[nj]*3];
|
||||
|
||||
if (va[0] == params->tileSize && vb[0] == params->tileSize) // x+
|
||||
poly->neis[j] = DT_EXT_LINK | 0;
|
||||
else if (va[2] == params->tileSize && vb[2] == params->tileSize) // z+
|
||||
poly->neis[j] = DT_EXT_LINK | 2;
|
||||
else if (va[0] == 0 && vb[0] == 0) // x-
|
||||
poly->neis[j] = DT_EXT_LINK | 4;
|
||||
else if (va[2] == 0 && vb[2] == 0) // z-
|
||||
poly->neis[j] = DT_EXT_LINK | 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store detail meshes and vertices.
|
||||
// The nav polygon vertices are stored as the first vertices on each mesh.
|
||||
// We compress the mesh data by skipping them and using the navmesh coordinates.
|
||||
unsigned short vbase = 0;
|
||||
for (int i = 0; i < params->polyCount; ++i)
|
||||
{
|
||||
dtPolyDetail& dtl = navDMeshes[i];
|
||||
const int vb = (int)params->detailMeshes[i*4+0];
|
||||
const int ndv = (int)params->detailMeshes[i*4+1];
|
||||
const int nv = navPolys[i].vertCount;
|
||||
dtl.vertBase = (unsigned int)vbase;
|
||||
dtl.vertCount = (unsigned char)(ndv-nv);
|
||||
dtl.triBase = (unsigned int)params->detailMeshes[i*4+2];
|
||||
dtl.triCount = (unsigned char)params->detailMeshes[i*4+3];
|
||||
// Copy vertices except the first 'nv' verts which are equal to nav poly verts.
|
||||
if (ndv-nv)
|
||||
{
|
||||
memcpy(&navDVerts[vbase*3], ¶ms->detailVerts[(vb+nv)*3], sizeof(float)*3*(ndv-nv));
|
||||
vbase += (unsigned short)(ndv-nv);
|
||||
}
|
||||
}
|
||||
// Store triangles.
|
||||
memcpy(navDTris, params->detailTris, sizeof(unsigned char)*4*params->detailTriCount);
|
||||
|
||||
// Store and create BVtree.
|
||||
// TODO: take detail mesh into account! use byte per bbox extent?
|
||||
createBVTree(params->verts, params->vertCount, params->polys, params->polyCount,
|
||||
nvp, params->cs, params->ch, params->polyCount*2, navBvtree);
|
||||
|
||||
// Store Off-Mesh connections.
|
||||
n = 0;
|
||||
for (int i = 0; i < params->offMeshConCount; ++i)
|
||||
{
|
||||
// Only store connections which start from this tile.
|
||||
if (offMeshConClass[i*2+0] == 0xff)
|
||||
{
|
||||
dtOffMeshConnection* con = &offMeshCons[n];
|
||||
con->poly = (unsigned short)(offMeshPolyBase + n);
|
||||
// Copy connection end-points.
|
||||
const float* endPts = ¶ms->offMeshConVerts[i*2*3];
|
||||
dtVcopy(&con->pos[0], &endPts[0]);
|
||||
dtVcopy(&con->pos[3], &endPts[3]);
|
||||
con->rad = params->offMeshConRad[i];
|
||||
con->flags = params->offMeshConDir[i] ? DT_OFFMESH_CON_BIDIR : 0;
|
||||
con->side = offMeshConClass[i*2+1];
|
||||
if (params->offMeshConUserID)
|
||||
con->userId = params->offMeshConUserID[i];
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
dtFree(offMeshConClass);
|
||||
|
||||
*outData = data;
|
||||
*outDataSize = dataSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void swapByte(unsigned char* a, unsigned char* b)
|
||||
{
|
||||
unsigned char tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
inline void swapEndian(unsigned short* v)
|
||||
{
|
||||
unsigned char* x = (unsigned char*)v;
|
||||
swapByte(x+0, x+1);
|
||||
}
|
||||
|
||||
inline void swapEndian(short* v)
|
||||
{
|
||||
unsigned char* x = (unsigned char*)v;
|
||||
swapByte(x+0, x+1);
|
||||
}
|
||||
|
||||
inline void swapEndian(unsigned int* v)
|
||||
{
|
||||
unsigned char* x = (unsigned char*)v;
|
||||
swapByte(x+0, x+3); swapByte(x+1, x+2);
|
||||
}
|
||||
|
||||
inline void swapEndian(int* v)
|
||||
{
|
||||
unsigned char* x = (unsigned char*)v;
|
||||
swapByte(x+0, x+3); swapByte(x+1, x+2);
|
||||
}
|
||||
|
||||
inline void swapEndian(float* v)
|
||||
{
|
||||
unsigned char* x = (unsigned char*)v;
|
||||
swapByte(x+0, x+3); swapByte(x+1, x+2);
|
||||
}
|
||||
|
||||
bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/)
|
||||
{
|
||||
dtMeshHeader* header = (dtMeshHeader*)data;
|
||||
|
||||
int swappedMagic = DT_NAVMESH_MAGIC;
|
||||
int swappedVersion = DT_NAVMESH_VERSION;
|
||||
swapEndian(&swappedMagic);
|
||||
swapEndian(&swappedVersion);
|
||||
|
||||
if ((header->magic != DT_NAVMESH_MAGIC || header->version != DT_NAVMESH_VERSION) &&
|
||||
(header->magic != swappedMagic || header->version != swappedVersion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
swapEndian(&header->magic);
|
||||
swapEndian(&header->version);
|
||||
swapEndian(&header->x);
|
||||
swapEndian(&header->y);
|
||||
swapEndian(&header->userId);
|
||||
swapEndian(&header->polyCount);
|
||||
swapEndian(&header->vertCount);
|
||||
swapEndian(&header->maxLinkCount);
|
||||
swapEndian(&header->detailMeshCount);
|
||||
swapEndian(&header->detailVertCount);
|
||||
swapEndian(&header->detailTriCount);
|
||||
swapEndian(&header->bvNodeCount);
|
||||
swapEndian(&header->offMeshConCount);
|
||||
swapEndian(&header->offMeshBase);
|
||||
swapEndian(&header->walkableHeight);
|
||||
swapEndian(&header->walkableRadius);
|
||||
swapEndian(&header->walkableClimb);
|
||||
swapEndian(&header->bmin[0]);
|
||||
swapEndian(&header->bmin[1]);
|
||||
swapEndian(&header->bmin[2]);
|
||||
swapEndian(&header->bmax[0]);
|
||||
swapEndian(&header->bmax[1]);
|
||||
swapEndian(&header->bmax[2]);
|
||||
swapEndian(&header->bvQuantFactor);
|
||||
|
||||
// Freelist index and pointers are updated when tile is added, no need to swap.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
|
||||
{
|
||||
// Make sure the data is in right format.
|
||||
dtMeshHeader* header = (dtMeshHeader*)data;
|
||||
if (header->magic != DT_NAVMESH_MAGIC)
|
||||
return false;
|
||||
if (header->version != DT_NAVMESH_VERSION)
|
||||
return false;
|
||||
|
||||
// Patch header pointers.
|
||||
const int headerSize = dtAlign4(sizeof(dtMeshHeader));
|
||||
const int vertsSize = dtAlign4(sizeof(float)*3*header->vertCount);
|
||||
const int polysSize = dtAlign4(sizeof(dtPoly)*header->polyCount);
|
||||
const int linksSize = dtAlign4(sizeof(dtLink)*(header->maxLinkCount));
|
||||
const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*header->detailMeshCount);
|
||||
const int detailVertsSize = dtAlign4(sizeof(float)*3*header->detailVertCount);
|
||||
const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*header->detailTriCount);
|
||||
const int bvtreeSize = dtAlign4(sizeof(dtBVNode)*header->bvNodeCount);
|
||||
const int offMeshLinksSize = dtAlign4(sizeof(dtOffMeshConnection)*header->offMeshConCount);
|
||||
|
||||
unsigned char* d = data + headerSize;
|
||||
float* verts = (float*)d; d += vertsSize;
|
||||
dtPoly* polys = (dtPoly*)d; d += polysSize;
|
||||
/*dtLink* links = (dtLink*)d;*/ d += linksSize;
|
||||
dtPolyDetail* detailMeshes = (dtPolyDetail*)d; d += detailMeshesSize;
|
||||
float* detailVerts = (float*)d; d += detailVertsSize;
|
||||
/*unsigned char* detailTris = (unsigned char*)d;*/ d += detailTrisSize;
|
||||
dtBVNode* bvTree = (dtBVNode*)d; d += bvtreeSize;
|
||||
dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshLinksSize;
|
||||
|
||||
// Vertices
|
||||
for (int i = 0; i < header->vertCount*3; ++i)
|
||||
{
|
||||
swapEndian(&verts[i]);
|
||||
}
|
||||
|
||||
// Polys
|
||||
for (int i = 0; i < header->polyCount; ++i)
|
||||
{
|
||||
dtPoly* p = &polys[i];
|
||||
// poly->firstLink is update when tile is added, no need to swap.
|
||||
for (int j = 0; j < DT_VERTS_PER_POLYGON; ++j)
|
||||
{
|
||||
swapEndian(&p->verts[j]);
|
||||
swapEndian(&p->neis[j]);
|
||||
}
|
||||
swapEndian(&p->flags);
|
||||
}
|
||||
|
||||
// Links are rebuild when tile is added, no need to swap.
|
||||
|
||||
// Detail meshes
|
||||
for (int i = 0; i < header->detailMeshCount; ++i)
|
||||
{
|
||||
dtPolyDetail* pd = &detailMeshes[i];
|
||||
swapEndian(&pd->vertBase);
|
||||
swapEndian(&pd->triBase);
|
||||
}
|
||||
|
||||
// Detail verts
|
||||
for (int i = 0; i < header->detailVertCount*3; ++i)
|
||||
{
|
||||
swapEndian(&detailVerts[i]);
|
||||
}
|
||||
|
||||
// BV-tree
|
||||
for (int i = 0; i < header->bvNodeCount; ++i)
|
||||
{
|
||||
dtBVNode* node = &bvTree[i];
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
swapEndian(&node->bmin[j]);
|
||||
swapEndian(&node->bmax[j]);
|
||||
}
|
||||
swapEndian(&node->i);
|
||||
}
|
||||
|
||||
// Off-mesh Connections.
|
||||
for (int i = 0; i < header->offMeshConCount; ++i)
|
||||
{
|
||||
dtOffMeshConnection* con = &offMeshCons[i];
|
||||
for (int j = 0; j < 6; ++j)
|
||||
swapEndian(&con->pos[j]);
|
||||
swapEndian(&con->rad);
|
||||
swapEndian(&con->poly);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
77
dep/recastnavigation/Detour/DetourNavMeshBuilder.h
Normal file
77
dep/recastnavigation/Detour/DetourNavMeshBuilder.h
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef DETOURNAVMESHBUILDER_H
|
||||
#define DETOURNAVMESHBUILDER_H
|
||||
|
||||
#include "DetourAlloc.h"
|
||||
|
||||
|
||||
// The units of the parameters are specified in parenthesis as follows:
|
||||
// (vx) voxels, (wu) world units
|
||||
struct dtNavMeshCreateParams
|
||||
{
|
||||
// Navmesh vertices.
|
||||
const unsigned short* verts; // Array of vertices, each vertex has 3 components. (vx).
|
||||
int vertCount; // Vertex count
|
||||
// Navmesh polygons
|
||||
const unsigned short* polys; // Array of polygons, uses same format as rcPolyMesh.
|
||||
const unsigned short* polyFlags; // Array of flags per polygon.
|
||||
const unsigned char* polyAreas; // Array of area ids per polygon.
|
||||
int polyCount; // Number of polygons
|
||||
int nvp; // Number of verts per polygon.
|
||||
// Navmesh Detail
|
||||
const unsigned int* detailMeshes; // Detail meshes, uses same format as rcPolyMeshDetail.
|
||||
const float* detailVerts; // Detail mesh vertices, uses same format as rcPolyMeshDetail (wu).
|
||||
int detailVertsCount; // Total number of detail vertices
|
||||
const unsigned char* detailTris; // Array of detail tris per detail mesh.
|
||||
int detailTriCount; // Total number of detail triangles.
|
||||
// Off-Mesh Connections.
|
||||
const float* offMeshConVerts; // Off-mesh connection vertices (wu).
|
||||
const float* offMeshConRad; // Off-mesh connection radii (wu).
|
||||
const unsigned short* offMeshConFlags; // Off-mesh connection flags.
|
||||
const unsigned char* offMeshConAreas; // Off-mesh connection area ids.
|
||||
const unsigned char* offMeshConDir; // Off-mesh connection direction flags (1 = bidir, 0 = oneway).
|
||||
const unsigned int* offMeshConUserID; // Off-mesh connection user id (optional).
|
||||
int offMeshConCount; // Number of off-mesh connections
|
||||
// Tile location
|
||||
unsigned int userId; // User ID bound to the tile.
|
||||
int tileX, tileY; // Tile location (tile coords).
|
||||
float bmin[3], bmax[3]; // Tile bounds (wu).
|
||||
// Settings
|
||||
float walkableHeight; // Agent height (wu).
|
||||
float walkableRadius; // Agent radius (wu).
|
||||
float walkableClimb; // Agent max climb (wu).
|
||||
float cs; // Cell size (xz) (wu).
|
||||
float ch; // Cell height (y) (wu).
|
||||
int tileSize; // Tile size (width & height) (vx).
|
||||
};
|
||||
|
||||
// Build navmesh data from given input data.
|
||||
bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize);
|
||||
|
||||
// Swaps endianess of navmesh header.
|
||||
bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int dataSize);
|
||||
|
||||
// Swaps endianess of the navmesh data. This function assumes that the header is in correct
|
||||
// endianess already. Call dtNavMeshHeaderSwapEndian() first on the data if the data is
|
||||
// assumed to be in wrong endianess to start with. If converting from native endianess to foreign,
|
||||
// call dtNavMeshHeaderSwapEndian() after the data has been swapped.
|
||||
bool dtNavMeshDataSwapEndian(unsigned char* data, const int dataSize);
|
||||
|
||||
#endif // DETOURNAVMESHBUILDER_H
|
||||
2564
dep/recastnavigation/Detour/DetourNavMeshQuery.cpp
Normal file
2564
dep/recastnavigation/Detour/DetourNavMeshQuery.cpp
Normal file
File diff suppressed because it is too large
Load Diff
407
dep/recastnavigation/Detour/DetourNavMeshQuery.h
Normal file
407
dep/recastnavigation/Detour/DetourNavMeshQuery.h
Normal file
@@ -0,0 +1,407 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef DETOURNAVMESHQUERY_H
|
||||
#define DETOURNAVMESHQUERY_H
|
||||
|
||||
#include "DetourNavMesh.h"
|
||||
|
||||
|
||||
// Define DT_VIRTUAL_QUERYFILTER if you wish to derive a custom filter from dtQueryFilter.
|
||||
// On certain platforms indirect or virtual function call is expensive. The default
|
||||
// setting is to use non-virtual functions, the actualy implementations of the functions
|
||||
// are declared as inline for maximum speed.
|
||||
|
||||
//#define DT_VIRTUAL_QUERYFILTER 1
|
||||
|
||||
// Class for polygon filtering and cost calculation during query operations.
|
||||
// - It is possible to derive a custom query filter from dtQueryFilter by overriding
|
||||
// the virtual functions passFilter() and getCost().
|
||||
// - Both functions should be as fast as possible. Use cached local copy of data
|
||||
// instead of accessing your own objects where possible.
|
||||
// - You do not need to adhere to the flags and cost logic provided by the default
|
||||
// implementation.
|
||||
// - In order for the A* to work properly, the cost should be proportional to
|
||||
// the travel distance. Using cost modifier less than 1.0 is likely to lead
|
||||
// to problems during pathfinding.
|
||||
class dtQueryFilter
|
||||
{
|
||||
float m_areaCost[DT_MAX_AREAS]; // Array storing cost per area type, used by default implementation.
|
||||
unsigned short m_includeFlags; // Include poly flags, used by default implementation.
|
||||
unsigned short m_excludeFlags; // Exclude poly flags, used by default implementation.
|
||||
|
||||
public:
|
||||
dtQueryFilter();
|
||||
|
||||
// Returns true if the polygon is can visited.
|
||||
// Params:
|
||||
// ref - (in) reference to the polygon test.
|
||||
// tile - (in) pointer to the tile of the polygon test.
|
||||
// poly - (in) pointer to the polygon test.
|
||||
#ifdef DT_VIRTUAL_QUERYFILTER
|
||||
virtual bool passFilter(const dtPolyRef ref,
|
||||
const dtMeshTile* tile,
|
||||
const dtPoly* poly) const;
|
||||
#else
|
||||
bool passFilter(const dtPolyRef ref,
|
||||
const dtMeshTile* tile,
|
||||
const dtPoly* poly) const;
|
||||
#endif
|
||||
|
||||
// Returns cost to travel from 'pa' to 'pb'.'
|
||||
// The segment is fully contained inside 'cur'.
|
||||
// 'pa' lies on the edge between 'prev' and 'cur',
|
||||
// 'pb' lies on the edge between 'cur' and 'next'.
|
||||
// Params:
|
||||
// pa - (in) segment start position.
|
||||
// pb - (in) segment end position.
|
||||
// prevRef, prevTile, prevPoly - (in) data describing the previous polygon, can be null.
|
||||
// curRef, curTile, curPoly - (in) data describing the current polygon.
|
||||
// nextRef, nextTile, nextPoly - (in) data describing the next polygon, can be null.
|
||||
#ifdef DT_VIRTUAL_QUERYFILTER
|
||||
virtual float getCost(const float* pa, const float* pb,
|
||||
const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly,
|
||||
const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly,
|
||||
const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const;
|
||||
#else
|
||||
float getCost(const float* pa, const float* pb,
|
||||
const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly,
|
||||
const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly,
|
||||
const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const;
|
||||
#endif
|
||||
|
||||
// Getters and setters for the default implementation data.
|
||||
inline float getAreaCost(const int i) const { return m_areaCost[i]; }
|
||||
inline void setAreaCost(const int i, const float cost) { m_areaCost[i] = cost; }
|
||||
|
||||
inline unsigned short getIncludeFlags() const { return m_includeFlags; }
|
||||
inline void setIncludeFlags(const unsigned short flags) { m_includeFlags = flags; }
|
||||
|
||||
inline unsigned short getExcludeFlags() const { return m_excludeFlags; }
|
||||
inline void setExcludeFlags(const unsigned short flags) { m_excludeFlags = flags; }
|
||||
};
|
||||
|
||||
class dtNavMeshQuery
|
||||
{
|
||||
public:
|
||||
dtNavMeshQuery();
|
||||
~dtNavMeshQuery();
|
||||
|
||||
// Initializes the nav mesh query.
|
||||
// Params:
|
||||
// nav - (in) pointer to navigation mesh data.
|
||||
// maxNodes - (in) Maximum number of search nodes to use (max 65536).
|
||||
// Returns: True if succeed, else false.
|
||||
dtStatus init(const dtNavMesh* nav, const int maxNodes);
|
||||
|
||||
// Finds the nearest navigation polygon around the center location.
|
||||
// Params:
|
||||
// center[3] - (in) The center of the search box.
|
||||
// extents[3] - (in) The extents of the search box.
|
||||
// filter - (in) path polygon filter.
|
||||
// nearestRef - (out) Reference to the nearest polygon.
|
||||
// nearestPt[3] - (out, opt) The nearest point on found polygon, null if not needed.
|
||||
// Returns: Reference identifier for the polygon, or 0 if no polygons found.
|
||||
dtStatus findNearestPoly(const float* center, const float* extents,
|
||||
const dtQueryFilter* filter,
|
||||
dtPolyRef* nearestRef, float* nearestPt) const;
|
||||
|
||||
// Returns polygons which overlap the query box.
|
||||
// Params:
|
||||
// center[3] - (in) the center of the search box.
|
||||
// extents[3] - (in) the extents of the search box.
|
||||
// filter - (in) path polygon filter.
|
||||
// polys - (out) array holding the search result.
|
||||
// polyCount - (out) Number of polygons in search result array.
|
||||
// maxPolys - (in) The max number of polygons the polys array can hold.
|
||||
dtStatus queryPolygons(const float* center, const float* extents,
|
||||
const dtQueryFilter* filter,
|
||||
dtPolyRef* polys, int* polyCount, const int maxPolys) const;
|
||||
|
||||
// Finds path from start polygon to end polygon.
|
||||
// If target polygon canno be reached through the navigation graph,
|
||||
// the last node on the array is nearest node to the end polygon.
|
||||
// Start end end positions are needed to calculate more accurate
|
||||
// traversal cost at start end end polygons.
|
||||
// Params:
|
||||
// startRef - (in) ref to path start polygon.
|
||||
// endRef - (in) ref to path end polygon.
|
||||
// startPos[3] - (in) Path start location.
|
||||
// endPos[3] - (in) Path end location.
|
||||
// filter - (in) path polygon filter.
|
||||
// path - (out) array holding the search result.
|
||||
// pathCount - (out) Number of polygons in search result array.
|
||||
// maxPath - (in) The max number of polygons the path array can hold. Must be at least 1.
|
||||
dtStatus findPath(dtPolyRef startRef, dtPolyRef endRef,
|
||||
const float* startPos, const float* endPos,
|
||||
const dtQueryFilter* filter,
|
||||
dtPolyRef* path, int* pathCount, const int maxPath) const;
|
||||
|
||||
// Intializes sliced path find query.
|
||||
// Note 1: calling any other dtNavMeshQuery method before calling findPathEnd()
|
||||
// may results in corrupted data!
|
||||
// Note 2: The pointer to filter is store, and used in subsequent
|
||||
// calls to updateSlicedFindPath().
|
||||
// Params:
|
||||
// startRef - (in) ref to path start polygon.
|
||||
// endRef - (in) ref to path end polygon.
|
||||
// startPos[3] - (in) Path start location.
|
||||
// endPos[3] - (in) Path end location.
|
||||
// filter - (in) path polygon filter.
|
||||
dtStatus initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef,
|
||||
const float* startPos, const float* endPos,
|
||||
const dtQueryFilter* filter);
|
||||
|
||||
// Updates sliced path find query.
|
||||
// Params:
|
||||
// maxIter - (in) max number of iterations to update.
|
||||
// Returns: Path query state.
|
||||
dtStatus updateSlicedFindPath(const int maxIter);
|
||||
|
||||
// Finalizes sliced path find query and returns found path.
|
||||
// path - (out) array holding the search result.
|
||||
// pathCount - (out) Number of polygons in search result array.
|
||||
// maxPath - (in) The max number of polygons the path array can hold.
|
||||
dtStatus finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath);
|
||||
|
||||
// Finalizes partial sliced path find query and returns path to the furthest
|
||||
// polygon on the existing path that was visited during the search.
|
||||
// existing - (out) Array of polygons in the existing path.
|
||||
// existingSize - (out) Number of polygons in existing path array.
|
||||
// path - (out) array holding the search result.
|
||||
// pathCount - (out) Number of polygons in search result array.
|
||||
// maxPath - (in) The max number of polygons the path array can hold.
|
||||
dtStatus finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize,
|
||||
dtPolyRef* path, int* pathCount, const int maxPath);
|
||||
|
||||
// Finds a straight path from start to end locations within the corridor
|
||||
// described by the path polygons.
|
||||
// Start and end locations will be clamped on the corridor.
|
||||
// The returned polygon references are point to polygon which was entered when
|
||||
// a path point was added. For the end point, zero will be returned. This allows
|
||||
// to match for example off-mesh link points to their representative polygons.
|
||||
// Params:
|
||||
// startPos[3] - (in) Path start location.
|
||||
// endPo[3] - (in) Path end location.
|
||||
// path - (in) Array of connected polygons describing the corridor.
|
||||
// pathSize - (in) Number of polygons in path array.
|
||||
// straightPath - (out) Points describing the straight path.
|
||||
// straightPathFlags - (out, opt) Flags describing each point type, see dtStraightPathFlags.
|
||||
// straightPathRefs - (out, opt) References to polygons at point locations.
|
||||
// straightPathCount - (out) Number of points in the path.
|
||||
// maxStraightPath - (in) The max number of points the straight path array can hold. Must be at least 1.
|
||||
dtStatus findStraightPath(const float* startPos, const float* endPos,
|
||||
const dtPolyRef* path, const int pathSize,
|
||||
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
|
||||
int* straightPathCount, const int maxStraightPath) const;
|
||||
|
||||
// Moves from startPos to endPos constrained to the navmesh.
|
||||
// If the endPos is reachable, the resultPos will be endPos,
|
||||
// or else the resultPos will be the nearest point in navmesh.
|
||||
// Note: The resulting point is not projected to the ground, use getPolyHeight() to get height.
|
||||
// Note: The algorithm is optimized for small delta movement and small number of polygons.
|
||||
// Params:
|
||||
// startRef - (in) ref to the polygon where startPos lies.
|
||||
// startPos[3] - (in) start position of the mover.
|
||||
// endPos[3] - (in) desired end position of the mover.
|
||||
// filter - (in) path polygon filter.
|
||||
// resultPos[3] - (out) new position of the mover.
|
||||
// visited - (out) array of visited polygons.
|
||||
// visitedCount - (out) Number of entries in the visited array.
|
||||
// maxVisitedSize - (in) max number of polygons in the visited array.
|
||||
dtStatus moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos,
|
||||
const dtQueryFilter* filter,
|
||||
float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const;
|
||||
|
||||
// Casts 'walkability' ray along the navmesh surface from startPos towards the endPos.
|
||||
// Params:
|
||||
// startRef - (in) ref to the polygon where the start lies.
|
||||
// startPos[3] - (in) start position of the query.
|
||||
// endPos[3] - (in) end position of the query.
|
||||
// t - (out) hit parameter along the segment, FLT_MAX if no hit.
|
||||
// hitNormal[3] - (out) normal of the nearest hit.
|
||||
// filter - (in) path polygon filter.
|
||||
// path - (out,opt) visited path polygons.
|
||||
// pathCount - (out,opt) Number of polygons visited.
|
||||
// maxPath - (in) max number of polygons in the path array.
|
||||
dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos,
|
||||
const dtQueryFilter* filter,
|
||||
float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const;
|
||||
|
||||
// Returns distance to nearest wall from the specified location.
|
||||
// Params:
|
||||
// startRef - (in) ref to the polygon where the center lies.
|
||||
// centerPos[3] - (in) center if the query circle.
|
||||
// maxRadius - (in) max search radius.
|
||||
// filter - (in) path polygon filter.
|
||||
// hitDist - (out) distance to nearest wall from the test location.
|
||||
// hitPos[3] - (out) location of the nearest hit.
|
||||
// hitNormal[3] - (out) normal of the nearest hit.
|
||||
dtStatus findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius,
|
||||
const dtQueryFilter* filter,
|
||||
float* hitDist, float* hitPos, float* hitNormal) const;
|
||||
|
||||
// Finds polygons found along the navigation graph which touch the specified circle.
|
||||
// Params:
|
||||
// startRef - (in) ref to the polygon where the search starts.
|
||||
// centerPos[3] - (in) center if the query circle.
|
||||
// radius - (in) radius of the query circle.
|
||||
// filter - (in) path polygon filter.
|
||||
// resultRef - (out, opt) refs to the polygons touched by the circle.
|
||||
// resultParent - (out, opt) parent of each result polygon.
|
||||
// resultCost - (out, opt) search cost at each result polygon.
|
||||
// resultCount - (out, opt) Number of results.
|
||||
// maxResult - (int) maximum capacity of search results.
|
||||
dtStatus findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius,
|
||||
const dtQueryFilter* filter,
|
||||
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
|
||||
int* resultCount, const int maxResult) const;
|
||||
|
||||
// Finds polygons found along the navigation graph which touch the convex polygon shape.
|
||||
// Params:
|
||||
// startRef - (in) ref to the polygon where the search starts.
|
||||
// verts[3*n] - (in) vertices describing convex polygon shape (CCW).
|
||||
// nverts - (in) number of vertices in the polygon.
|
||||
// filter - (in) path polygon filter.
|
||||
// resultRef - (out, opt) refs to the polygons touched by the circle.
|
||||
// resultParent - (out, opt) parent of each result polygon.
|
||||
// resultCost - (out, opt) search cost at each result polygon.
|
||||
// resultCount - (out) number of results.
|
||||
// maxResult - (int) maximum capacity of search results.
|
||||
dtStatus findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts,
|
||||
const dtQueryFilter* filter,
|
||||
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
|
||||
int* resultCount, const int maxResult) const;
|
||||
|
||||
// Finds non-overlapping local neighbourhood around center location.
|
||||
// Note: The algorithm is optimized for small query radius and small number of polygons.
|
||||
// Params:
|
||||
// startRef - (in) ref to the polygon where the search starts.
|
||||
// centerPos[3] - (in) center if the query circle.
|
||||
// radius - (in) radius of the query circle.
|
||||
// filter - (in) path polygon filter.
|
||||
// resultRef - (out) refs to the polygons touched by the circle.
|
||||
// resultParent - (out, opt) parent of each result polygon.
|
||||
// resultCount - (out) number of results.
|
||||
// maxResult - (int) maximum capacity of search results.
|
||||
dtStatus findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius,
|
||||
const dtQueryFilter* filter,
|
||||
dtPolyRef* resultRef, dtPolyRef* resultParent,
|
||||
int* resultCount, const int maxResult) const;
|
||||
|
||||
// Returns wall segments of specified polygon.
|
||||
// Params:
|
||||
// ref - (in) ref to the polygon.
|
||||
// filter - (in) path polygon filter.
|
||||
// segments[6*maxSegments] - (out) wall segments (2 endpoints per segment).
|
||||
// segmentCount - (out) number of wall segments.
|
||||
// maxSegments - (in) max number of segments that can be stored in 'segments'.
|
||||
dtStatus getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter,
|
||||
float* segments, int* segmentCount, const int maxSegments) const;
|
||||
|
||||
// Returns closest point on navigation polygon.
|
||||
// Uses detail polygons to find the closest point to the navigation polygon surface.
|
||||
// Params:
|
||||
// ref - (in) ref to the polygon.
|
||||
// pos[3] - (in) the point to check.
|
||||
// closest[3] - (out) closest point.
|
||||
// Returns: true if closest point found.
|
||||
dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const;
|
||||
|
||||
// Returns closest point on navigation polygon boundary.
|
||||
// Uses the navigation polygon boundary to snap the point to poly boundary
|
||||
// if it is outside the polygon. Much faster than closestPointToPoly. Does not affect height.
|
||||
// Params:
|
||||
// ref - (in) ref to the polygon.
|
||||
// pos[3] - (in) the point to check.
|
||||
// closest[3] - (out) closest point.
|
||||
// Returns: true if closest point found.
|
||||
dtStatus closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const;
|
||||
|
||||
// Returns start and end location of an off-mesh link polygon.
|
||||
// Params:
|
||||
// prevRef - (in) ref to the polygon before the link (used to select direction).
|
||||
// polyRef - (in) ref to the off-mesh link polygon.
|
||||
// startPos[3] - (out) start point of the link.
|
||||
// endPos[3] - (out) end point of the link.
|
||||
// Returns: true if link is found.
|
||||
dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const;
|
||||
|
||||
// Returns height of the polygon at specified location.
|
||||
// Params:
|
||||
// ref - (in) ref to the polygon.
|
||||
// pos[3] - (in) the point where to locate the height.
|
||||
// height - (out) height at the location.
|
||||
// Returns: true if over polygon.
|
||||
dtStatus getPolyHeight(dtPolyRef ref, const float* pos, float* height) const;
|
||||
|
||||
// Returns true if poly reference ins in closed list.
|
||||
bool isInClosedList(dtPolyRef ref) const;
|
||||
|
||||
class dtNodePool* getNodePool() const { return m_nodePool; }
|
||||
|
||||
private:
|
||||
|
||||
// Returns neighbour tile based on side.
|
||||
dtMeshTile* getNeighbourTileAt(int x, int y, int side) const;
|
||||
|
||||
// Queries polygons within a tile.
|
||||
int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, const dtQueryFilter* filter,
|
||||
dtPolyRef* polys, const int maxPolys) const;
|
||||
// Find nearest polygon within a tile.
|
||||
dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents,
|
||||
const dtQueryFilter* filter, float* nearestPt) const;
|
||||
// Returns closest point on polygon.
|
||||
dtStatus closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, const float* pos, float* closest) const;
|
||||
|
||||
// Returns portal points between two polygons.
|
||||
dtStatus getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right,
|
||||
unsigned char& fromType, unsigned char& toType) const;
|
||||
dtStatus getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile,
|
||||
dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile,
|
||||
float* left, float* right) const;
|
||||
|
||||
// Returns edge mid point between two polygons.
|
||||
dtStatus getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const;
|
||||
dtStatus getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile,
|
||||
dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile,
|
||||
float* mid) const;
|
||||
|
||||
const dtNavMesh* m_nav; // Pointer to navmesh data.
|
||||
|
||||
struct dtQueryData
|
||||
{
|
||||
dtStatus status;
|
||||
struct dtNode* lastBestNode;
|
||||
float lastBestNodeCost;
|
||||
dtPolyRef startRef, endRef;
|
||||
float startPos[3], endPos[3];
|
||||
const dtQueryFilter* filter;
|
||||
};
|
||||
dtQueryData m_query; // Sliced query state.
|
||||
|
||||
class dtNodePool* m_tinyNodePool; // Pointer to small node pool.
|
||||
class dtNodePool* m_nodePool; // Pointer to node pool.
|
||||
class dtNodeQueue* m_openList; // Pointer to open list queue.
|
||||
};
|
||||
|
||||
// Helper function to allocate navmesh query class using Detour allocator.
|
||||
dtNavMeshQuery* dtAllocNavMeshQuery();
|
||||
void dtFreeNavMeshQuery(dtNavMeshQuery* query);
|
||||
|
||||
#endif // DETOURNAVMESHQUERY_H
|
||||
164
dep/recastnavigation/Detour/DetourNode.cpp
Normal file
164
dep/recastnavigation/Detour/DetourNode.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include "DetourNode.h"
|
||||
#include "DetourAlloc.h"
|
||||
#include "DetourAssert.h"
|
||||
#include "DetourCommon.h"
|
||||
#include <string.h>
|
||||
|
||||
inline unsigned int dtHashRef(dtPolyRef a)
|
||||
{
|
||||
a = (~a) + (a << 18);
|
||||
a = a ^ (a >> 31);
|
||||
a = a * 21;
|
||||
a = a ^ (a >> 11);
|
||||
a = a + (a << 6);
|
||||
a = a ^ (a >> 22);
|
||||
return (unsigned int)a;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
dtNodePool::dtNodePool(int maxNodes, int hashSize) :
|
||||
m_nodes(0),
|
||||
m_first(0),
|
||||
m_next(0),
|
||||
m_maxNodes(maxNodes),
|
||||
m_hashSize(hashSize),
|
||||
m_nodeCount(0)
|
||||
{
|
||||
dtAssert(dtNextPow2(m_hashSize) == (unsigned int)m_hashSize);
|
||||
dtAssert(m_maxNodes > 0);
|
||||
|
||||
m_nodes = (dtNode*)dtAlloc(sizeof(dtNode)*m_maxNodes, DT_ALLOC_PERM);
|
||||
m_next = (unsigned short*)dtAlloc(sizeof(unsigned short)*m_maxNodes, DT_ALLOC_PERM);
|
||||
m_first = (unsigned short*)dtAlloc(sizeof(unsigned short)*hashSize, DT_ALLOC_PERM);
|
||||
|
||||
dtAssert(m_nodes);
|
||||
dtAssert(m_next);
|
||||
dtAssert(m_first);
|
||||
|
||||
memset(m_first, 0xff, sizeof(unsigned short)*m_hashSize);
|
||||
memset(m_next, 0xff, sizeof(unsigned short)*m_maxNodes);
|
||||
}
|
||||
|
||||
dtNodePool::~dtNodePool()
|
||||
{
|
||||
dtFree(m_nodes);
|
||||
dtFree(m_next);
|
||||
dtFree(m_first);
|
||||
}
|
||||
|
||||
void dtNodePool::clear()
|
||||
{
|
||||
memset(m_first, 0xff, sizeof(unsigned short)*m_hashSize);
|
||||
m_nodeCount = 0;
|
||||
}
|
||||
|
||||
dtNode* dtNodePool::findNode(dtPolyRef id)
|
||||
{
|
||||
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
|
||||
unsigned short i = m_first[bucket];
|
||||
while (i != DT_NULL_IDX)
|
||||
{
|
||||
if (m_nodes[i].id == id)
|
||||
return &m_nodes[i];
|
||||
i = m_next[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
dtNode* dtNodePool::getNode(dtPolyRef id)
|
||||
{
|
||||
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
|
||||
unsigned short i = m_first[bucket];
|
||||
dtNode* node = 0;
|
||||
while (i != DT_NULL_IDX)
|
||||
{
|
||||
if (m_nodes[i].id == id)
|
||||
return &m_nodes[i];
|
||||
i = m_next[i];
|
||||
}
|
||||
|
||||
if (m_nodeCount >= m_maxNodes)
|
||||
return 0;
|
||||
|
||||
i = (unsigned short)m_nodeCount;
|
||||
m_nodeCount++;
|
||||
|
||||
// Init node
|
||||
node = &m_nodes[i];
|
||||
node->pidx = 0;
|
||||
node->cost = 0;
|
||||
node->total = 0;
|
||||
node->id = id;
|
||||
node->flags = 0;
|
||||
|
||||
m_next[i] = m_first[bucket];
|
||||
m_first[bucket] = i;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
dtNodeQueue::dtNodeQueue(int n) :
|
||||
m_heap(0),
|
||||
m_capacity(n),
|
||||
m_size(0)
|
||||
{
|
||||
dtAssert(m_capacity > 0);
|
||||
|
||||
m_heap = (dtNode**)dtAlloc(sizeof(dtNode*)*(m_capacity+1), DT_ALLOC_PERM);
|
||||
dtAssert(m_heap);
|
||||
}
|
||||
|
||||
dtNodeQueue::~dtNodeQueue()
|
||||
{
|
||||
dtFree(m_heap);
|
||||
}
|
||||
|
||||
void dtNodeQueue::bubbleUp(int i, dtNode* node)
|
||||
{
|
||||
int parent = (i-1)/2;
|
||||
// note: (index > 0) means there is a parent
|
||||
while ((i > 0) && (m_heap[parent]->total > node->total))
|
||||
{
|
||||
m_heap[i] = m_heap[parent];
|
||||
i = parent;
|
||||
parent = (i-1)/2;
|
||||
}
|
||||
m_heap[i] = node;
|
||||
}
|
||||
|
||||
void dtNodeQueue::trickleDown(int i, dtNode* node)
|
||||
{
|
||||
int child = (i*2)+1;
|
||||
while (child < m_size)
|
||||
{
|
||||
if (((child+1) < m_size) &&
|
||||
(m_heap[child]->total > m_heap[child+1]->total))
|
||||
{
|
||||
child++;
|
||||
}
|
||||
m_heap[i] = m_heap[child];
|
||||
i = child;
|
||||
child = (i*2)+1;
|
||||
}
|
||||
bubbleUp(i, node);
|
||||
}
|
||||
157
dep/recastnavigation/Detour/DetourNode.h
Normal file
157
dep/recastnavigation/Detour/DetourNode.h
Normal file
@@ -0,0 +1,157 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef DETOURNODE_H
|
||||
#define DETOURNODE_H
|
||||
|
||||
#include "DetourNavMesh.h"
|
||||
|
||||
enum dtNodeFlags
|
||||
{
|
||||
DT_NODE_OPEN = 0x01,
|
||||
DT_NODE_CLOSED = 0x02,
|
||||
};
|
||||
|
||||
static const unsigned short DT_NULL_IDX = 0xffff;
|
||||
|
||||
struct dtNode
|
||||
{
|
||||
float pos[3]; // Position of the node.
|
||||
float cost; // Cost from previous node to current node.
|
||||
float total; // Cost up to the node.
|
||||
unsigned int pidx : 30; // Index to parent node.
|
||||
unsigned int flags : 2; // Node flags 0/open/closed.
|
||||
dtPolyRef id; // Polygon ref the node corresponds to.
|
||||
};
|
||||
|
||||
class dtNodePool
|
||||
{
|
||||
public:
|
||||
dtNodePool(int maxNodes, int hashSize);
|
||||
~dtNodePool();
|
||||
inline void operator=(const dtNodePool&) {}
|
||||
void clear();
|
||||
dtNode* getNode(dtPolyRef id);
|
||||
dtNode* findNode(dtPolyRef id);
|
||||
|
||||
inline unsigned int getNodeIdx(const dtNode* node) const
|
||||
{
|
||||
if (!node) return 0;
|
||||
return (unsigned int)(node - m_nodes)+1;
|
||||
}
|
||||
|
||||
inline dtNode* getNodeAtIdx(unsigned int idx)
|
||||
{
|
||||
if (!idx) return 0;
|
||||
return &m_nodes[idx-1];
|
||||
}
|
||||
|
||||
inline const dtNode* getNodeAtIdx(unsigned int idx) const
|
||||
{
|
||||
if (!idx) return 0;
|
||||
return &m_nodes[idx-1];
|
||||
}
|
||||
|
||||
inline int getMemUsed() const
|
||||
{
|
||||
return sizeof(*this) +
|
||||
sizeof(dtNode)*m_maxNodes +
|
||||
sizeof(unsigned short)*m_maxNodes +
|
||||
sizeof(unsigned short)*m_hashSize;
|
||||
}
|
||||
|
||||
inline int getMaxNodes() const { return m_maxNodes; }
|
||||
|
||||
inline int getHashSize() const { return m_hashSize; }
|
||||
inline unsigned short getFirst(int bucket) const { return m_first[bucket]; }
|
||||
inline unsigned short getNext(int i) const { return m_next[i]; }
|
||||
|
||||
private:
|
||||
|
||||
dtNode* m_nodes;
|
||||
unsigned short* m_first;
|
||||
unsigned short* m_next;
|
||||
const int m_maxNodes;
|
||||
const int m_hashSize;
|
||||
int m_nodeCount;
|
||||
};
|
||||
|
||||
class dtNodeQueue
|
||||
{
|
||||
public:
|
||||
dtNodeQueue(int n);
|
||||
~dtNodeQueue();
|
||||
inline void operator=(dtNodeQueue&) {}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
inline dtNode* top()
|
||||
{
|
||||
return m_heap[0];
|
||||
}
|
||||
|
||||
inline dtNode* pop()
|
||||
{
|
||||
dtNode* result = m_heap[0];
|
||||
m_size--;
|
||||
trickleDown(0, m_heap[m_size]);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void push(dtNode* node)
|
||||
{
|
||||
m_size++;
|
||||
bubbleUp(m_size-1, node);
|
||||
}
|
||||
|
||||
inline void modify(dtNode* node)
|
||||
{
|
||||
for (int i = 0; i < m_size; ++i)
|
||||
{
|
||||
if (m_heap[i] == node)
|
||||
{
|
||||
bubbleUp(i, node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool empty() const { return m_size == 0; }
|
||||
|
||||
inline int getMemUsed() const
|
||||
{
|
||||
return sizeof(*this) +
|
||||
sizeof(dtNode*)*(m_capacity+1);
|
||||
}
|
||||
|
||||
inline int getCapacity() const { return m_capacity; }
|
||||
|
||||
private:
|
||||
void bubbleUp(int i, dtNode* node);
|
||||
void trickleDown(int i, dtNode* node);
|
||||
|
||||
dtNode** m_heap;
|
||||
const int m_capacity;
|
||||
int m_size;
|
||||
};
|
||||
|
||||
|
||||
#endif // DETOURNODE_H
|
||||
532
dep/recastnavigation/Detour/DetourObstacleAvoidance.cpp
Normal file
532
dep/recastnavigation/Detour/DetourObstacleAvoidance.cpp
Normal file
@@ -0,0 +1,532 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include "DetourObstacleAvoidance.h"
|
||||
#include "DetourCommon.h"
|
||||
#include "DetourAlloc.h"
|
||||
#include "DetourAssert.h"
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <new>
|
||||
|
||||
|
||||
static int sweepCircleCircle(const float* c0, const float r0, const float* v,
|
||||
const float* c1, const float r1,
|
||||
float& tmin, float& tmax)
|
||||
{
|
||||
static const float EPS = 0.0001f;
|
||||
float s[3];
|
||||
dtVsub(s,c1,c0);
|
||||
float r = r0+r1;
|
||||
float c = dtVdot2D(s,s) - r*r;
|
||||
float a = dtVdot2D(v,v);
|
||||
if (a < EPS) return 0; // not moving
|
||||
|
||||
// Overlap, calc time to exit.
|
||||
float b = dtVdot2D(v,s);
|
||||
float d = b*b - a*c;
|
||||
if (d < 0.0f) return 0; // no intersection.
|
||||
a = 1.0f / a;
|
||||
const float rd = dtSqrt(d);
|
||||
tmin = (b - rd) * a;
|
||||
tmax = (b + rd) * a;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int isectRaySeg(const float* ap, const float* u,
|
||||
const float* bp, const float* bq,
|
||||
float& t)
|
||||
{
|
||||
float v[3], w[3];
|
||||
dtVsub(v,bq,bp);
|
||||
dtVsub(w,ap,bp);
|
||||
float d = dtVperp2D(u,v);
|
||||
if (fabsf(d) < 1e-6f) return 0;
|
||||
d = 1.0f/d;
|
||||
t = dtVperp2D(v,w) * d;
|
||||
if (t < 0 || t > 1) return 0;
|
||||
float s = dtVperp2D(u,w) * d;
|
||||
if (s < 0 || s > 1) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
dtObstacleAvoidanceDebugData* dtAllocObstacleAvoidanceDebugData()
|
||||
{
|
||||
void* mem = dtAlloc(sizeof(dtObstacleAvoidanceDebugData), DT_ALLOC_PERM);
|
||||
if (!mem) return 0;
|
||||
return new(mem) dtObstacleAvoidanceDebugData;
|
||||
}
|
||||
|
||||
void dtFreeObstacleAvoidanceDebugData(dtObstacleAvoidanceDebugData* ptr)
|
||||
{
|
||||
if (!ptr) return;
|
||||
ptr->~dtObstacleAvoidanceDebugData();
|
||||
dtFree(ptr);
|
||||
}
|
||||
|
||||
|
||||
dtObstacleAvoidanceDebugData::dtObstacleAvoidanceDebugData() :
|
||||
m_nsamples(0),
|
||||
m_maxSamples(0),
|
||||
m_vel(0),
|
||||
m_ssize(0),
|
||||
m_pen(0),
|
||||
m_vpen(0),
|
||||
m_vcpen(0),
|
||||
m_spen(0),
|
||||
m_tpen(0)
|
||||
{
|
||||
}
|
||||
|
||||
dtObstacleAvoidanceDebugData::~dtObstacleAvoidanceDebugData()
|
||||
{
|
||||
dtFree(m_vel);
|
||||
dtFree(m_ssize);
|
||||
dtFree(m_pen);
|
||||
dtFree(m_vpen);
|
||||
dtFree(m_vcpen);
|
||||
dtFree(m_spen);
|
||||
dtFree(m_tpen);
|
||||
}
|
||||
|
||||
bool dtObstacleAvoidanceDebugData::init(const int maxSamples)
|
||||
{
|
||||
dtAssert(maxSamples);
|
||||
m_maxSamples = maxSamples;
|
||||
|
||||
m_vel = (float*)dtAlloc(sizeof(float)*3*m_maxSamples, DT_ALLOC_PERM);
|
||||
if (!m_vel)
|
||||
return false;
|
||||
m_pen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM);
|
||||
if (!m_pen)
|
||||
return false;
|
||||
m_ssize = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM);
|
||||
if (!m_ssize)
|
||||
return false;
|
||||
m_vpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM);
|
||||
if (!m_vpen)
|
||||
return false;
|
||||
m_vcpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM);
|
||||
if (!m_vcpen)
|
||||
return false;
|
||||
m_spen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM);
|
||||
if (!m_spen)
|
||||
return false;
|
||||
m_tpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM);
|
||||
if (!m_tpen)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dtObstacleAvoidanceDebugData::reset()
|
||||
{
|
||||
m_nsamples = 0;
|
||||
}
|
||||
|
||||
void dtObstacleAvoidanceDebugData::addSample(const float* vel, const float ssize, const float pen,
|
||||
const float vpen, const float vcpen, const float spen, const float tpen)
|
||||
{
|
||||
if (m_nsamples >= m_maxSamples)
|
||||
return;
|
||||
dtAssert(m_vel);
|
||||
dtAssert(m_ssize);
|
||||
dtAssert(m_pen);
|
||||
dtAssert(m_vpen);
|
||||
dtAssert(m_vcpen);
|
||||
dtAssert(m_spen);
|
||||
dtAssert(m_tpen);
|
||||
dtVcopy(&m_vel[m_nsamples*3], vel);
|
||||
m_ssize[m_nsamples] = ssize;
|
||||
m_pen[m_nsamples] = pen;
|
||||
m_vpen[m_nsamples] = vpen;
|
||||
m_vcpen[m_nsamples] = vcpen;
|
||||
m_spen[m_nsamples] = spen;
|
||||
m_tpen[m_nsamples] = tpen;
|
||||
m_nsamples++;
|
||||
}
|
||||
|
||||
static void normalizeArray(float* arr, const int n)
|
||||
{
|
||||
// Normalize penaly range.
|
||||
float minPen = FLT_MAX;
|
||||
float maxPen = -FLT_MAX;
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
minPen = dtMin(minPen, arr[i]);
|
||||
maxPen = dtMax(maxPen, arr[i]);
|
||||
}
|
||||
const float penRange = maxPen-minPen;
|
||||
const float s = penRange > 0.001f ? (1.0f / penRange) : 1;
|
||||
for (int i = 0; i < n; ++i)
|
||||
arr[i] = dtClamp((arr[i]-minPen)*s, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void dtObstacleAvoidanceDebugData::normalizeSamples()
|
||||
{
|
||||
normalizeArray(m_pen, m_nsamples);
|
||||
normalizeArray(m_vpen, m_nsamples);
|
||||
normalizeArray(m_vcpen, m_nsamples);
|
||||
normalizeArray(m_spen, m_nsamples);
|
||||
normalizeArray(m_tpen, m_nsamples);
|
||||
}
|
||||
|
||||
|
||||
dtObstacleAvoidanceQuery* dtAllocObstacleAvoidanceQuery()
|
||||
{
|
||||
void* mem = dtAlloc(sizeof(dtObstacleAvoidanceQuery), DT_ALLOC_PERM);
|
||||
if (!mem) return 0;
|
||||
return new(mem) dtObstacleAvoidanceQuery;
|
||||
}
|
||||
|
||||
void dtFreeObstacleAvoidanceQuery(dtObstacleAvoidanceQuery* ptr)
|
||||
{
|
||||
if (!ptr) return;
|
||||
ptr->~dtObstacleAvoidanceQuery();
|
||||
dtFree(ptr);
|
||||
}
|
||||
|
||||
|
||||
dtObstacleAvoidanceQuery::dtObstacleAvoidanceQuery() :
|
||||
m_velBias(0.0f),
|
||||
m_weightDesVel(0.0f),
|
||||
m_weightCurVel(0.0f),
|
||||
m_weightSide(0.0f),
|
||||
m_weightToi(0.0f),
|
||||
m_horizTime(0.0f),
|
||||
m_maxCircles(0),
|
||||
m_circles(0),
|
||||
m_ncircles(0),
|
||||
m_maxSegments(0),
|
||||
m_segments(0),
|
||||
m_nsegments(0)
|
||||
{
|
||||
}
|
||||
|
||||
dtObstacleAvoidanceQuery::~dtObstacleAvoidanceQuery()
|
||||
{
|
||||
dtFree(m_circles);
|
||||
dtFree(m_segments);
|
||||
}
|
||||
|
||||
bool dtObstacleAvoidanceQuery::init(const int maxCircles, const int maxSegments)
|
||||
{
|
||||
m_maxCircles = maxCircles;
|
||||
m_ncircles = 0;
|
||||
m_circles = (dtObstacleCircle*)dtAlloc(sizeof(dtObstacleCircle)*m_maxCircles, DT_ALLOC_PERM);
|
||||
if (!m_circles)
|
||||
return false;
|
||||
memset(m_circles, 0, sizeof(dtObstacleCircle)*m_maxCircles);
|
||||
|
||||
m_maxSegments = maxSegments;
|
||||
m_nsegments = 0;
|
||||
m_segments = (dtObstacleSegment*)dtAlloc(sizeof(dtObstacleSegment)*m_maxSegments, DT_ALLOC_PERM);
|
||||
if (!m_segments)
|
||||
return false;
|
||||
memset(m_segments, 0, sizeof(dtObstacleSegment)*m_maxSegments);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dtObstacleAvoidanceQuery::reset()
|
||||
{
|
||||
m_ncircles = 0;
|
||||
m_nsegments = 0;
|
||||
}
|
||||
|
||||
void dtObstacleAvoidanceQuery::addCircle(const float* pos, const float rad,
|
||||
const float* vel, const float* dvel)
|
||||
{
|
||||
if (m_ncircles >= m_maxCircles)
|
||||
return;
|
||||
|
||||
dtObstacleCircle* cir = &m_circles[m_ncircles++];
|
||||
dtVcopy(cir->p, pos);
|
||||
cir->rad = rad;
|
||||
dtVcopy(cir->vel, vel);
|
||||
dtVcopy(cir->dvel, dvel);
|
||||
}
|
||||
|
||||
void dtObstacleAvoidanceQuery::addSegment(const float* p, const float* q)
|
||||
{
|
||||
if (m_nsegments > m_maxSegments)
|
||||
return;
|
||||
|
||||
dtObstacleSegment* seg = &m_segments[m_nsegments++];
|
||||
dtVcopy(seg->p, p);
|
||||
dtVcopy(seg->q, q);
|
||||
}
|
||||
|
||||
void dtObstacleAvoidanceQuery::prepare(const float* pos, const float* dvel)
|
||||
{
|
||||
// Prepare obstacles
|
||||
for (int i = 0; i < m_ncircles; ++i)
|
||||
{
|
||||
dtObstacleCircle* cir = &m_circles[i];
|
||||
|
||||
// Side
|
||||
const float* pa = pos;
|
||||
const float* pb = cir->p;
|
||||
|
||||
const float orig[3] = {0,0};
|
||||
float dv[3];
|
||||
dtVsub(cir->dp,pb,pa);
|
||||
dtVnormalize(cir->dp);
|
||||
dtVsub(dv, cir->dvel, dvel);
|
||||
|
||||
const float a = dtTriArea2D(orig, cir->dp,dv);
|
||||
if (a < 0.01f)
|
||||
{
|
||||
cir->np[0] = -cir->dp[2];
|
||||
cir->np[2] = cir->dp[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
cir->np[0] = cir->dp[2];
|
||||
cir->np[2] = -cir->dp[0];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_nsegments; ++i)
|
||||
{
|
||||
dtObstacleSegment* seg = &m_segments[i];
|
||||
|
||||
// Precalc if the agent is really close to the segment.
|
||||
const float r = 0.01f;
|
||||
float t;
|
||||
seg->touch = dtDistancePtSegSqr2D(pos, seg->p, seg->q, t) < dtSqr(r);
|
||||
}
|
||||
}
|
||||
|
||||
float dtObstacleAvoidanceQuery::processSample(const float* vcand, const float cs,
|
||||
const float* pos, const float rad,
|
||||
const float vmax, const float* vel, const float* dvel,
|
||||
dtObstacleAvoidanceDebugData* debug)
|
||||
{
|
||||
// Find min time of impact and exit amongst all obstacles.
|
||||
float tmin = m_horizTime;
|
||||
float side = 0;
|
||||
int nside = 0;
|
||||
|
||||
for (int i = 0; i < m_ncircles; ++i)
|
||||
{
|
||||
const dtObstacleCircle* cir = &m_circles[i];
|
||||
|
||||
// RVO
|
||||
float vab[3];
|
||||
dtVscale(vab, vcand, 2);
|
||||
dtVsub(vab, vab, vel);
|
||||
dtVsub(vab, vab, cir->vel);
|
||||
|
||||
// Side
|
||||
side += dtClamp(dtMin(dtVdot2D(cir->dp,vab)*0.5f+0.5f, dtVdot2D(cir->np,vab)*2), 0.0f, 1.0f);
|
||||
nside++;
|
||||
|
||||
float htmin = 0, htmax = 0;
|
||||
if (!sweepCircleCircle(pos,rad, vab, cir->p,cir->rad, htmin, htmax))
|
||||
continue;
|
||||
|
||||
// Handle overlapping obstacles.
|
||||
if (htmin < 0.0f && htmax > 0.0f)
|
||||
{
|
||||
// Avoid more when overlapped.
|
||||
htmin = -htmin * 0.5f;
|
||||
}
|
||||
|
||||
if (htmin >= 0.0f)
|
||||
{
|
||||
// The closest obstacle is somewhere ahead of us, keep track of nearest obstacle.
|
||||
if (htmin < tmin)
|
||||
tmin = htmin;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_nsegments; ++i)
|
||||
{
|
||||
const dtObstacleSegment* seg = &m_segments[i];
|
||||
float htmin = 0;
|
||||
|
||||
if (seg->touch)
|
||||
{
|
||||
// Special case when the agent is very close to the segment.
|
||||
float sdir[3], snorm[3];
|
||||
dtVsub(sdir, seg->q, seg->p);
|
||||
snorm[0] = -sdir[2];
|
||||
snorm[2] = sdir[0];
|
||||
// If the velocity is pointing towards the segment, no collision.
|
||||
if (dtVdot2D(snorm, vcand) < 0.0f)
|
||||
continue;
|
||||
// Else immediate collision.
|
||||
htmin = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isectRaySeg(pos, vcand, seg->p, seg->q, htmin))
|
||||
continue;
|
||||
}
|
||||
|
||||
// Avoid less when facing walls.
|
||||
htmin *= 2.0f;
|
||||
|
||||
// The closest obstacle is somewhere ahead of us, keep track of nearest obstacle.
|
||||
if (htmin < tmin)
|
||||
tmin = htmin;
|
||||
}
|
||||
|
||||
// Normalize side bias, to prevent it dominating too much.
|
||||
if (nside)
|
||||
side /= nside;
|
||||
|
||||
const float ivmax = 1.0f / vmax;
|
||||
const float vpen = m_weightDesVel * (dtVdist2D(vcand, dvel) * ivmax);
|
||||
const float vcpen = m_weightCurVel * (dtVdist2D(vcand, vel) * ivmax);
|
||||
const float spen = m_weightSide * side;
|
||||
const float tpen = m_weightToi * (1.0f/(0.1f+tmin / m_horizTime));
|
||||
|
||||
const float penalty = vpen + vcpen + spen + tpen;
|
||||
|
||||
// Store different penalties for debug viewing
|
||||
if (debug)
|
||||
debug->addSample(vcand, cs, penalty, vpen, vcpen, spen, tpen);
|
||||
|
||||
return penalty;
|
||||
}
|
||||
|
||||
void dtObstacleAvoidanceQuery::sampleVelocityGrid(const float* pos, const float rad, const float vmax,
|
||||
const float* vel, const float* dvel,
|
||||
float* nvel, const int gsize,
|
||||
dtObstacleAvoidanceDebugData* debug)
|
||||
{
|
||||
prepare(pos, dvel);
|
||||
|
||||
dtVset(nvel, 0,0,0);
|
||||
|
||||
if (debug)
|
||||
debug->reset();
|
||||
|
||||
const float cvx = dvel[0] * m_velBias;
|
||||
const float cvz = dvel[2] * m_velBias;
|
||||
const float cs = vmax * 2 * (1 - m_velBias) / (float)(gsize-1);
|
||||
const float half = (gsize-1)*cs*0.5f;
|
||||
|
||||
float minPenalty = FLT_MAX;
|
||||
|
||||
for (int y = 0; y < gsize; ++y)
|
||||
{
|
||||
for (int x = 0; x < gsize; ++x)
|
||||
{
|
||||
float vcand[3];
|
||||
vcand[0] = cvx + x*cs - half;
|
||||
vcand[1] = 0;
|
||||
vcand[2] = cvz + y*cs - half;
|
||||
|
||||
if (dtSqr(vcand[0])+dtSqr(vcand[2]) > dtSqr(vmax+cs/2)) continue;
|
||||
|
||||
const float penalty = processSample(vcand, cs, pos,rad,vmax,vel,dvel, debug);
|
||||
if (penalty < minPenalty)
|
||||
{
|
||||
minPenalty = penalty;
|
||||
dtVcopy(nvel, vcand);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const float DT_PI = 3.14159265f;
|
||||
|
||||
void dtObstacleAvoidanceQuery::sampleVelocityAdaptive(const float* pos, const float rad, const float vmax,
|
||||
const float* vel, const float* dvel, float* nvel,
|
||||
const int ndivs, const int nrings, const int depth,
|
||||
dtObstacleAvoidanceDebugData* debug)
|
||||
{
|
||||
prepare(pos, dvel);
|
||||
|
||||
dtVset(nvel, 0,0,0);
|
||||
|
||||
if (debug)
|
||||
debug->reset();
|
||||
|
||||
// Build sampling pattern aligned to desired velocity.
|
||||
static const int MAX_PATTERN_DIVS = 32;
|
||||
static const int MAX_PATTERN_RINGS = 4;
|
||||
float pat[(MAX_PATTERN_DIVS*MAX_PATTERN_RINGS+1)*2];
|
||||
int npat = 0;
|
||||
|
||||
const int nd = dtClamp(ndivs, 1, MAX_PATTERN_DIVS);
|
||||
const int nr = dtClamp(nrings, 1, MAX_PATTERN_RINGS);
|
||||
const float da = (1.0f/nd) * DT_PI*2;
|
||||
const float dang = atan2f(dvel[2], dvel[0]);
|
||||
|
||||
// Always add sample at zero
|
||||
pat[npat*2+0] = 0;
|
||||
pat[npat*2+1] = 0;
|
||||
npat++;
|
||||
|
||||
for (int j = 0; j < nr; ++j)
|
||||
{
|
||||
const float rad = (float)(nr-j)/(float)nr;
|
||||
float a = dang + (j&1)*0.5f*da;
|
||||
for (int i = 0; i < nd; ++i)
|
||||
{
|
||||
pat[npat*2+0] = cosf(a)*rad;
|
||||
pat[npat*2+1] = sinf(a)*rad;
|
||||
npat++;
|
||||
a += da;
|
||||
}
|
||||
}
|
||||
|
||||
// Start sampling.
|
||||
float cr = vmax * (1.0f-m_velBias);
|
||||
float res[3];
|
||||
dtVset(res, dvel[0] * m_velBias, 0, dvel[2] * m_velBias);
|
||||
|
||||
for (int k = 0; k < depth; ++k)
|
||||
{
|
||||
float minPenalty = FLT_MAX;
|
||||
float bvel[3];
|
||||
dtVset(bvel, 0,0,0);
|
||||
|
||||
for (int i = 0; i < npat; ++i)
|
||||
{
|
||||
float vcand[3];
|
||||
vcand[0] = res[0] + pat[i*2+0]*cr;
|
||||
vcand[1] = 0;
|
||||
vcand[2] = res[2] + pat[i*2+1]*cr;
|
||||
|
||||
if (dtSqr(vcand[0])+dtSqr(vcand[2]) > dtSqr(vmax+0.001f)) continue;
|
||||
|
||||
const float penalty = processSample(vcand,cr/10, pos,rad,vmax,vel,dvel, debug);
|
||||
if (penalty < minPenalty)
|
||||
{
|
||||
minPenalty = penalty;
|
||||
dtVcopy(bvel, vcand);
|
||||
}
|
||||
}
|
||||
|
||||
dtVcopy(res, bvel);
|
||||
|
||||
cr *= 0.5f;
|
||||
}
|
||||
|
||||
dtVcopy(nvel, res);
|
||||
}
|
||||
|
||||
148
dep/recastnavigation/Detour/DetourObstacleAvoidance.h
Normal file
148
dep/recastnavigation/Detour/DetourObstacleAvoidance.h
Normal file
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef DETOUROBSTACLEAVOIDANCE_H
|
||||
#define DETOUROBSTACLEAVOIDANCE_H
|
||||
|
||||
struct dtObstacleCircle
|
||||
{
|
||||
float p[3]; // Position of the obstacle
|
||||
float vel[3]; // Velocity of the obstacle
|
||||
float dvel[3]; // Velocity of the obstacle
|
||||
float rad; // Radius of the obstacle
|
||||
float dp[3], np[3]; // Use for side selection during sampling.
|
||||
};
|
||||
|
||||
struct dtObstacleSegment
|
||||
{
|
||||
float p[3], q[3]; // End points of the obstacle segment
|
||||
bool touch;
|
||||
};
|
||||
|
||||
static const int RVO_SAMPLE_RAD = 15;
|
||||
static const int MAX_RVO_SAMPLES = (RVO_SAMPLE_RAD*2+1)*(RVO_SAMPLE_RAD*2+1) + 100;
|
||||
|
||||
class dtObstacleAvoidanceDebugData
|
||||
{
|
||||
public:
|
||||
dtObstacleAvoidanceDebugData();
|
||||
~dtObstacleAvoidanceDebugData();
|
||||
|
||||
bool init(const int maxSamples);
|
||||
void reset();
|
||||
void addSample(const float* vel, const float ssize, const float pen,
|
||||
const float vpen, const float vcpen, const float spen, const float tpen);
|
||||
|
||||
void normalizeSamples();
|
||||
|
||||
inline int getSampleCount() const { return m_nsamples; }
|
||||
inline const float* getSampleVelocity(const int i) const { return &m_vel[i*3]; }
|
||||
inline float getSampleSize(const int i) const { return m_ssize[i]; }
|
||||
inline float getSamplePenalty(const int i) const { return m_pen[i]; }
|
||||
inline float getSampleDesiredVelocityPenalty(const int i) const { return m_vpen[i]; }
|
||||
inline float getSampleCurrentVelocityPenalty(const int i) const { return m_vcpen[i]; }
|
||||
inline float getSamplePreferredSidePenalty(const int i) const { return m_spen[i]; }
|
||||
inline float getSampleCollisionTimePenalty(const int i) const { return m_tpen[i]; }
|
||||
|
||||
private:
|
||||
int m_nsamples;
|
||||
int m_maxSamples;
|
||||
float* m_vel;
|
||||
float* m_ssize;
|
||||
float* m_pen;
|
||||
float* m_vpen;
|
||||
float* m_vcpen;
|
||||
float* m_spen;
|
||||
float* m_tpen;
|
||||
};
|
||||
|
||||
dtObstacleAvoidanceDebugData* dtAllocObstacleAvoidanceDebugData();
|
||||
void dtFreeObstacleAvoidanceDebugData(dtObstacleAvoidanceDebugData* ptr);
|
||||
|
||||
|
||||
class dtObstacleAvoidanceQuery
|
||||
{
|
||||
public:
|
||||
dtObstacleAvoidanceQuery();
|
||||
~dtObstacleAvoidanceQuery();
|
||||
|
||||
bool init(const int maxCircles, const int maxSegments);
|
||||
|
||||
void reset();
|
||||
|
||||
void addCircle(const float* pos, const float rad,
|
||||
const float* vel, const float* dvel);
|
||||
|
||||
void addSegment(const float* p, const float* q);
|
||||
|
||||
inline void setVelocitySelectionBias(float v) { m_velBias = v; }
|
||||
inline void setDesiredVelocityWeight(float w) { m_weightDesVel = w; }
|
||||
inline void setCurrentVelocityWeight(float w) { m_weightCurVel = w; }
|
||||
inline void setPreferredSideWeight(float w) { m_weightSide = w; }
|
||||
inline void setCollisionTimeWeight(float w) { m_weightToi = w; }
|
||||
inline void setTimeHorizon(float t) { m_horizTime = t; }
|
||||
|
||||
void sampleVelocityGrid(const float* pos, const float rad, const float vmax,
|
||||
const float* vel, const float* dvel, float* nvel,
|
||||
const int gsize,
|
||||
dtObstacleAvoidanceDebugData* debug = 0);
|
||||
|
||||
void sampleVelocityAdaptive(const float* pos, const float rad, const float vmax,
|
||||
const float* vel, const float* dvel, float* nvel,
|
||||
const int ndivs, const int nrings, const int depth,
|
||||
dtObstacleAvoidanceDebugData* debug = 0);
|
||||
|
||||
inline int getObstacleCircleCount() const { return m_ncircles; }
|
||||
const dtObstacleCircle* getObstacleCircle(const int i) { return &m_circles[i]; }
|
||||
|
||||
inline int getObstacleSegmentCount() const { return m_nsegments; }
|
||||
const dtObstacleSegment* getObstacleSegment(const int i) { return &m_segments[i]; }
|
||||
|
||||
private:
|
||||
|
||||
void prepare(const float* pos, const float* dvel);
|
||||
|
||||
float processSample(const float* vcand, const float cs,
|
||||
const float* pos, const float rad,
|
||||
const float vmax, const float* vel, const float* dvel,
|
||||
dtObstacleAvoidanceDebugData* debug);
|
||||
|
||||
dtObstacleCircle* insertCircle(const float dist);
|
||||
dtObstacleSegment* insertSegment(const float dist);
|
||||
|
||||
float m_velBias;
|
||||
float m_weightDesVel;
|
||||
float m_weightCurVel;
|
||||
float m_weightSide;
|
||||
float m_weightToi;
|
||||
float m_horizTime;
|
||||
|
||||
int m_maxCircles;
|
||||
dtObstacleCircle* m_circles;
|
||||
int m_ncircles;
|
||||
|
||||
int m_maxSegments;
|
||||
dtObstacleSegment* m_segments;
|
||||
int m_nsegments;
|
||||
};
|
||||
|
||||
dtObstacleAvoidanceQuery* dtAllocObstacleAvoidanceQuery();
|
||||
void dtFreeObstacleAvoidanceQuery(dtObstacleAvoidanceQuery* ptr);
|
||||
|
||||
|
||||
#endif // DETOUROBSTACLEAVOIDANCE_H
|
||||
18
dep/recastnavigation/License.txt
Normal file
18
dep/recastnavigation/License.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
Copyright (c) 2009 Mikko Mononen memon@inside.org
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
120
dep/recastnavigation/Readme.txt
Normal file
120
dep/recastnavigation/Readme.txt
Normal file
@@ -0,0 +1,120 @@
|
||||
|
||||
Recast & Detour Version 1.4
|
||||
|
||||
|
||||
Recast
|
||||
|
||||
Recast is state of the art navigation mesh construction toolset for games.
|
||||
|
||||
* It is automatic, which means that you can throw any level geometry
|
||||
at it and you will get robust mesh out
|
||||
* It is fast which means swift turnaround times for level designers
|
||||
* It is open source so it comes with full source and you can
|
||||
customize it to your hearts content.
|
||||
|
||||
The Recast process starts with constructing a voxel mold from a level geometry
|
||||
and then casting a navigation mesh over it. The process consists of three steps,
|
||||
building the voxel mold, partitioning the mold into simple regions, peeling off
|
||||
the regions as simple polygons.
|
||||
|
||||
1. The voxel mold is build from the input triangle mesh by rasterizing
|
||||
the triangles into a multi-layer heightfield. Some simple filters are
|
||||
then applied to the mold to prune out locations where the character
|
||||
would not be able to move.
|
||||
2. The walkable areas described by the mold are divided into simple
|
||||
overlayed 2D regions. The resulting regions have only one non-overlapping
|
||||
contour, which simplifies the final step of the process tremendously.
|
||||
3. The navigation polygons are peeled off from the regions by first tracing
|
||||
the boundaries and then simplifying them. The resulting polygons are
|
||||
finally converted to convex polygons which makes them perfect for
|
||||
pathfinding and spatial reasoning about the level.
|
||||
|
||||
The toolset code is located in the Recast folder and demo application using the Recast
|
||||
toolset is located in the RecastDemo folder.
|
||||
|
||||
The project files with this distribution can be compiled with Microsoft Visual C++ 2008
|
||||
(you can download it for free) and XCode 3.1.
|
||||
|
||||
|
||||
Detour
|
||||
|
||||
Recast is accompanied with Detour, path-finding and spatial reasoning toolkit. You can use any navigation mesh with Detour, but of course the data generated with Recast fits perfectly.
|
||||
|
||||
Detour offers simple static navigation mesh which is suitable for many simple cases, as well as tiled navigation mesh which allows you to plug in and out pieces of the mesh. The tiled mesh allows to create systems where you stream new navigation data in and out as the player progresses the level, or you may regenerate tiles as the world changes.
|
||||
|
||||
|
||||
Latest code available at http://code.google.com/p/recastnavigation/
|
||||
|
||||
|
||||
--
|
||||
|
||||
Release Notes
|
||||
|
||||
----------------
|
||||
* Recast 1.4
|
||||
Released August 24th, 2009
|
||||
|
||||
- Added detail height mesh generation (RecastDetailMesh.cpp) for single,
|
||||
tiled statmeshes as well as tilemesh.
|
||||
- Added feature to contour tracing which detects extra vertices along
|
||||
tile edges which should be removed later.
|
||||
- Changed the tiled stat mesh preprocess, so that it first generated
|
||||
polymeshes per tile and finally combines them.
|
||||
- Fixed bug in the GUI code where invisible buttons could be pressed.
|
||||
|
||||
----------------
|
||||
* Recast 1.31
|
||||
Released July 24th, 2009
|
||||
|
||||
- Better cost and heuristic functions.
|
||||
- Fixed tile navmesh raycast on tile borders.
|
||||
|
||||
----------------
|
||||
* Recast 1.3
|
||||
Released July 14th, 2009
|
||||
|
||||
- Added dtTileNavMesh which allows to dynamically add and remove navmesh pieces at runtime.
|
||||
- Renamed stat navmesh types to dtStat* (i.e. dtPoly is now dtStatPoly).
|
||||
- Moved common code used by tile and stat navmesh to DetourNode.h/cpp and DetourCommon.h/cpp.
|
||||
- Refactores the demo code.
|
||||
|
||||
----------------
|
||||
* Recast 1.2
|
||||
Released June 17th, 2009
|
||||
|
||||
- Added tiled mesh generation. The tiled generation allows to generate navigation for
|
||||
much larger worlds, it removes some of the artifacts that comes from distance fields
|
||||
in open areas, and allows later streaming and dynamic runtime generation
|
||||
- Improved and added some debug draw modes
|
||||
- API change: The helper function rcBuildNavMesh does not exists anymore,
|
||||
had to change few internal things to cope with the tiled processing,
|
||||
similar API functionality will be added later once the tiled process matures
|
||||
- The demo is getting way too complicated, need to split demos
|
||||
- Fixed several filtering functions so that the mesh is tighter to the geometry,
|
||||
sometimes there could be up error up to tow voxel units close to walls,
|
||||
now it should be just one.
|
||||
|
||||
----------------
|
||||
* Recast 1.1
|
||||
Released April 11th, 2009
|
||||
|
||||
This is the first release of Detour.
|
||||
|
||||
----------------
|
||||
* Recast 1.0
|
||||
Released March 29th, 2009
|
||||
|
||||
This is the first release of Recast.
|
||||
|
||||
The process is not always as robust as I would wish. The watershed phase sometimes swallows tiny islands
|
||||
which are close to edges. These droppings are handled in rcBuildContours, but the code is not
|
||||
particularly robust either.
|
||||
|
||||
Another non-robust case is when portal contours (contours shared between two regions) are always
|
||||
assumed to be straight. That can lead to overlapping contours specially when the level has
|
||||
large open areas.
|
||||
|
||||
|
||||
|
||||
Mikko Mononen
|
||||
memon@inside.org
|
||||
31
dep/recastnavigation/Recast/CMakeLists.txt
Normal file
31
dep/recastnavigation/Recast/CMakeLists.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
# Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
|
||||
#
|
||||
# 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.
|
||||
|
||||
set(Recast_STAT_SRCS
|
||||
Recast.cpp
|
||||
RecastAlloc.cpp
|
||||
RecastArea.cpp
|
||||
RecastContour.cpp
|
||||
RecastFilter.cpp
|
||||
RecastMesh.cpp
|
||||
RecastMeshDetail.cpp
|
||||
RecastRasterization.cpp
|
||||
RecastRegion.cpp
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/dep/zlib
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(Recast STATIC ${Recast_STAT_SRCS})
|
||||
|
||||
target_link_libraries(Recast ${ZLIB_LIBRARIES})
|
||||
423
dep/recastnavigation/Recast/Recast.cpp
Normal file
423
dep/recastnavigation/Recast/Recast.cpp
Normal file
@@ -0,0 +1,423 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include <float.h>
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "Recast.h"
|
||||
#include "RecastAlloc.h"
|
||||
#include "RecastAssert.h"
|
||||
|
||||
float rcSqrt(float x)
|
||||
{
|
||||
return sqrtf(x);
|
||||
}
|
||||
|
||||
|
||||
void rcContext::log(const rcLogCategory category, const char* format, ...)
|
||||
{
|
||||
if (!m_logEnabled)
|
||||
return;
|
||||
static const int MSG_SIZE = 512;
|
||||
char msg[MSG_SIZE];
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int len = vsnprintf(msg, MSG_SIZE, format, ap);
|
||||
if (len >= MSG_SIZE)
|
||||
{
|
||||
len = MSG_SIZE-1;
|
||||
msg[MSG_SIZE-1] = '\0';
|
||||
}
|
||||
va_end(ap);
|
||||
doLog(category, msg, len);
|
||||
}
|
||||
|
||||
rcHeightfield* rcAllocHeightfield()
|
||||
{
|
||||
rcHeightfield* hf = (rcHeightfield*)rcAlloc(sizeof(rcHeightfield), RC_ALLOC_PERM);
|
||||
memset(hf, 0, sizeof(rcHeightfield));
|
||||
return hf;
|
||||
}
|
||||
|
||||
void rcFreeHeightField(rcHeightfield* hf)
|
||||
{
|
||||
if (!hf) return;
|
||||
// Delete span array.
|
||||
rcFree(hf->spans);
|
||||
// Delete span pools.
|
||||
while (hf->pools)
|
||||
{
|
||||
rcSpanPool* next = hf->pools->next;
|
||||
rcFree(hf->pools);
|
||||
hf->pools = next;
|
||||
}
|
||||
rcFree(hf);
|
||||
}
|
||||
|
||||
rcCompactHeightfield* rcAllocCompactHeightfield()
|
||||
{
|
||||
rcCompactHeightfield* chf = (rcCompactHeightfield*)rcAlloc(sizeof(rcCompactHeightfield), RC_ALLOC_PERM);
|
||||
memset(chf, 0, sizeof(rcCompactHeightfield));
|
||||
return chf;
|
||||
}
|
||||
|
||||
void rcFreeCompactHeightfield(rcCompactHeightfield* chf)
|
||||
{
|
||||
if (!chf) return;
|
||||
rcFree(chf->cells);
|
||||
rcFree(chf->spans);
|
||||
rcFree(chf->dist);
|
||||
rcFree(chf->areas);
|
||||
rcFree(chf);
|
||||
}
|
||||
|
||||
rcContourSet* rcAllocContourSet()
|
||||
{
|
||||
rcContourSet* cset = (rcContourSet*)rcAlloc(sizeof(rcContourSet), RC_ALLOC_PERM);
|
||||
memset(cset, 0, sizeof(rcContourSet));
|
||||
return cset;
|
||||
}
|
||||
|
||||
void rcFreeContourSet(rcContourSet* cset)
|
||||
{
|
||||
if (!cset) return;
|
||||
for (int i = 0; i < cset->nconts; ++i)
|
||||
{
|
||||
rcFree(cset->conts[i].verts);
|
||||
rcFree(cset->conts[i].rverts);
|
||||
}
|
||||
rcFree(cset->conts);
|
||||
rcFree(cset);
|
||||
}
|
||||
|
||||
rcPolyMesh* rcAllocPolyMesh()
|
||||
{
|
||||
rcPolyMesh* pmesh = (rcPolyMesh*)rcAlloc(sizeof(rcPolyMesh), RC_ALLOC_PERM);
|
||||
memset(pmesh, 0, sizeof(rcPolyMesh));
|
||||
return pmesh;
|
||||
}
|
||||
|
||||
void rcFreePolyMesh(rcPolyMesh* pmesh)
|
||||
{
|
||||
if (!pmesh) return;
|
||||
rcFree(pmesh->verts);
|
||||
rcFree(pmesh->polys);
|
||||
rcFree(pmesh->regs);
|
||||
rcFree(pmesh->flags);
|
||||
rcFree(pmesh->areas);
|
||||
rcFree(pmesh);
|
||||
}
|
||||
|
||||
rcPolyMeshDetail* rcAllocPolyMeshDetail()
|
||||
{
|
||||
rcPolyMeshDetail* dmesh = (rcPolyMeshDetail*)rcAlloc(sizeof(rcPolyMeshDetail), RC_ALLOC_PERM);
|
||||
memset(dmesh, 0, sizeof(rcPolyMeshDetail));
|
||||
return dmesh;
|
||||
}
|
||||
|
||||
void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh)
|
||||
{
|
||||
if (!dmesh) return;
|
||||
rcFree(dmesh->meshes);
|
||||
rcFree(dmesh->verts);
|
||||
rcFree(dmesh->tris);
|
||||
rcFree(dmesh);
|
||||
}
|
||||
|
||||
|
||||
void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax)
|
||||
{
|
||||
// Calculate bounding box.
|
||||
rcVcopy(bmin, verts);
|
||||
rcVcopy(bmax, verts);
|
||||
for (int i = 1; i < nv; ++i)
|
||||
{
|
||||
const float* v = &verts[i*3];
|
||||
rcVmin(bmin, v);
|
||||
rcVmax(bmax, v);
|
||||
}
|
||||
}
|
||||
|
||||
void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* h)
|
||||
{
|
||||
*w = (int)((bmax[0] - bmin[0])/cs+0.5f);
|
||||
*h = (int)((bmax[2] - bmin[2])/cs+0.5f);
|
||||
}
|
||||
|
||||
bool rcCreateHeightfield(rcContext* /*ctx*/, rcHeightfield& hf, int width, int height,
|
||||
const float* bmin, const float* bmax,
|
||||
float cs, float ch)
|
||||
{
|
||||
// TODO: VC complains about unref formal variable, figure out a way to handle this better.
|
||||
// rcAssert(ctx);
|
||||
|
||||
hf.width = width;
|
||||
hf.height = height;
|
||||
rcVcopy(hf.bmin, bmin);
|
||||
rcVcopy(hf.bmax, bmax);
|
||||
hf.cs = cs;
|
||||
hf.ch = ch;
|
||||
hf.spans = (rcSpan**)rcAlloc(sizeof(rcSpan*)*hf.width*hf.height, RC_ALLOC_PERM);
|
||||
if (!hf.spans)
|
||||
return false;
|
||||
memset(hf.spans, 0, sizeof(rcSpan*)*hf.width*hf.height);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void calcTriNormal(const float* v0, const float* v1, const float* v2, float* norm)
|
||||
{
|
||||
float e0[3], e1[3];
|
||||
rcVsub(e0, v1, v0);
|
||||
rcVsub(e1, v2, v0);
|
||||
rcVcross(norm, e0, e1);
|
||||
rcVnormalize(norm);
|
||||
}
|
||||
|
||||
void rcMarkWalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle,
|
||||
const float* verts, int /*nv*/,
|
||||
const int* tris, int nt,
|
||||
unsigned char* areas)
|
||||
{
|
||||
// TODO: VC complains about unref formal variable, figure out a way to handle this better.
|
||||
// rcAssert(ctx);
|
||||
|
||||
const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI);
|
||||
|
||||
float norm[3];
|
||||
|
||||
for (int i = 0; i < nt; ++i)
|
||||
{
|
||||
const int* tri = &tris[i*3];
|
||||
calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm);
|
||||
// Check if the face is walkable.
|
||||
if (norm[1] > walkableThr)
|
||||
areas[i] = RC_WALKABLE_AREA;
|
||||
}
|
||||
}
|
||||
|
||||
void rcClearUnwalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle,
|
||||
const float* verts, int /*nv*/,
|
||||
const int* tris, int nt,
|
||||
unsigned char* areas)
|
||||
{
|
||||
// TODO: VC complains about unref formal variable, figure out a way to handle this better.
|
||||
// rcAssert(ctx);
|
||||
|
||||
const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI);
|
||||
|
||||
float norm[3];
|
||||
|
||||
for (int i = 0; i < nt; ++i)
|
||||
{
|
||||
const int* tri = &tris[i*3];
|
||||
calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm);
|
||||
// Check if the face is walkable.
|
||||
if (norm[1] <= walkableThr)
|
||||
areas[i] = RC_NULL_AREA;
|
||||
}
|
||||
}
|
||||
|
||||
int rcGetHeightFieldSpanCount(rcContext* /*ctx*/, rcHeightfield& hf)
|
||||
{
|
||||
// TODO: VC complains about unref formal variable, figure out a way to handle this better.
|
||||
// rcAssert(ctx);
|
||||
|
||||
const int w = hf.width;
|
||||
const int h = hf.height;
|
||||
int spanCount = 0;
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
for (rcSpan* s = hf.spans[x + y*w]; s; s = s->next)
|
||||
{
|
||||
if (s->area != RC_NULL_AREA)
|
||||
spanCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return spanCount;
|
||||
}
|
||||
|
||||
bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb,
|
||||
rcHeightfield& hf, rcCompactHeightfield& chf)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_BUILD_COMPACTHEIGHTFIELD);
|
||||
|
||||
const int w = hf.width;
|
||||
const int h = hf.height;
|
||||
const int spanCount = rcGetHeightFieldSpanCount(ctx, hf);
|
||||
|
||||
// Fill in header.
|
||||
chf.width = w;
|
||||
chf.height = h;
|
||||
chf.spanCount = spanCount;
|
||||
chf.walkableHeight = walkableHeight;
|
||||
chf.walkableClimb = walkableClimb;
|
||||
chf.maxRegions = 0;
|
||||
rcVcopy(chf.bmin, hf.bmin);
|
||||
rcVcopy(chf.bmax, hf.bmax);
|
||||
chf.bmax[1] += walkableHeight*hf.ch;
|
||||
chf.cs = hf.cs;
|
||||
chf.ch = hf.ch;
|
||||
chf.cells = (rcCompactCell*)rcAlloc(sizeof(rcCompactCell)*w*h, RC_ALLOC_PERM);
|
||||
if (!chf.cells)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.cells' (%d)", w*h);
|
||||
return false;
|
||||
}
|
||||
memset(chf.cells, 0, sizeof(rcCompactCell)*w*h);
|
||||
chf.spans = (rcCompactSpan*)rcAlloc(sizeof(rcCompactSpan)*spanCount, RC_ALLOC_PERM);
|
||||
if (!chf.spans)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.spans' (%d)", spanCount);
|
||||
return false;
|
||||
}
|
||||
memset(chf.spans, 0, sizeof(rcCompactSpan)*spanCount);
|
||||
chf.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*spanCount, RC_ALLOC_PERM);
|
||||
if (!chf.areas)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.areas' (%d)", spanCount);
|
||||
return false;
|
||||
}
|
||||
memset(chf.areas, RC_NULL_AREA, sizeof(unsigned char)*spanCount);
|
||||
|
||||
const int MAX_HEIGHT = 0xffff;
|
||||
|
||||
// Fill in cells and spans.
|
||||
int idx = 0;
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const rcSpan* s = hf.spans[x + y*w];
|
||||
// If there are no spans at this cell, just leave the data to index=0, count=0.
|
||||
if (!s) continue;
|
||||
rcCompactCell& c = chf.cells[x+y*w];
|
||||
c.index = idx;
|
||||
c.count = 0;
|
||||
while (s)
|
||||
{
|
||||
if (s->area != RC_NULL_AREA)
|
||||
{
|
||||
const int bot = (int)s->smax;
|
||||
const int top = s->next ? (int)s->next->smin : MAX_HEIGHT;
|
||||
chf.spans[idx].y = (unsigned short)rcClamp(bot, 0, 0xffff);
|
||||
chf.spans[idx].h = (unsigned char)rcClamp(top - bot, 0, 0xff);
|
||||
chf.areas[idx] = s->area;
|
||||
idx++;
|
||||
c.count++;
|
||||
}
|
||||
s = s->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find neighbour connections.
|
||||
const int MAX_LAYERS = RC_NOT_CONNECTED-1;
|
||||
int tooHighNeighbour = 0;
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
rcCompactSpan& s = chf.spans[i];
|
||||
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
rcSetCon(s, dir, RC_NOT_CONNECTED);
|
||||
const int nx = x + rcGetDirOffsetX(dir);
|
||||
const int ny = y + rcGetDirOffsetY(dir);
|
||||
// First check that the neighbour cell is in bounds.
|
||||
if (nx < 0 || ny < 0 || nx >= w || ny >= h)
|
||||
continue;
|
||||
|
||||
// Iterate over all neighbour spans and check if any of the is
|
||||
// accessible from current cell.
|
||||
const rcCompactCell& nc = chf.cells[nx+ny*w];
|
||||
for (int k = (int)nc.index, nk = (int)(nc.index+nc.count); k < nk; ++k)
|
||||
{
|
||||
const rcCompactSpan& ns = chf.spans[k];
|
||||
const int bot = rcMax(s.y, ns.y);
|
||||
const int top = rcMin(s.y+s.h, ns.y+ns.h);
|
||||
|
||||
// Check that the gap between the spans is walkable,
|
||||
// and that the climb height between the gaps is not too high.
|
||||
if ((top - bot) >= walkableHeight && rcAbs((int)ns.y - (int)s.y) <= walkableClimb)
|
||||
{
|
||||
// Mark direction as walkable.
|
||||
const int idx = k - (int)nc.index;
|
||||
if (idx < 0 || idx > MAX_LAYERS)
|
||||
{
|
||||
tooHighNeighbour = rcMax(tooHighNeighbour, idx);
|
||||
continue;
|
||||
}
|
||||
rcSetCon(s, dir, idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tooHighNeighbour > MAX_LAYERS)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Heightfield has too many layers %d (max: %d)",
|
||||
tooHighNeighbour, MAX_LAYERS);
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_BUILD_COMPACTHEIGHTFIELD);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
static int getHeightfieldMemoryUsage(const rcHeightfield& hf)
|
||||
{
|
||||
int size = 0;
|
||||
size += sizeof(hf);
|
||||
size += hf.width * hf.height * sizeof(rcSpan*);
|
||||
|
||||
rcSpanPool* pool = hf.pools;
|
||||
while (pool)
|
||||
{
|
||||
size += (sizeof(rcSpanPool) - sizeof(rcSpan)) + sizeof(rcSpan)*RC_SPANS_PER_POOL;
|
||||
pool = pool->next;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static int getCompactHeightFieldMemoryusage(const rcCompactHeightfield& chf)
|
||||
{
|
||||
int size = 0;
|
||||
size += sizeof(rcCompactHeightfield);
|
||||
size += sizeof(rcCompactSpan) * chf.spanCount;
|
||||
size += sizeof(rcCompactCell) * chf.width * chf.height;
|
||||
return size;
|
||||
}
|
||||
*/
|
||||
688
dep/recastnavigation/Recast/Recast.h
Normal file
688
dep/recastnavigation/Recast/Recast.h
Normal file
@@ -0,0 +1,688 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef RECAST_H
|
||||
#define RECAST_H
|
||||
|
||||
// Some math headers don't have PI defined.
|
||||
static const float RC_PI = 3.14159265f;
|
||||
|
||||
enum rcLogCategory
|
||||
{
|
||||
RC_LOG_PROGRESS = 1,
|
||||
RC_LOG_WARNING,
|
||||
RC_LOG_ERROR,
|
||||
};
|
||||
|
||||
enum rcTimerLabel
|
||||
{
|
||||
RC_TIMER_TOTAL,
|
||||
RC_TIMER_TEMP,
|
||||
RC_TIMER_RASTERIZE_TRIANGLES,
|
||||
RC_TIMER_BUILD_COMPACTHEIGHTFIELD,
|
||||
RC_TIMER_BUILD_CONTOURS,
|
||||
RC_TIMER_BUILD_CONTOURS_TRACE,
|
||||
RC_TIMER_BUILD_CONTOURS_SIMPLIFY,
|
||||
RC_TIMER_FILTER_BORDER,
|
||||
RC_TIMER_FILTER_WALKABLE,
|
||||
RC_TIMER_MEDIAN_AREA,
|
||||
RC_TIMER_FILTER_LOW_OBSTACLES,
|
||||
RC_TIMER_BUILD_POLYMESH,
|
||||
RC_TIMER_MERGE_POLYMESH,
|
||||
RC_TIMER_ERODE_AREA,
|
||||
RC_TIMER_MARK_BOX_AREA,
|
||||
RC_TIMER_MARK_CONVEXPOLY_AREA,
|
||||
RC_TIMER_BUILD_DISTANCEFIELD,
|
||||
RC_TIMER_BUILD_DISTANCEFIELD_DIST,
|
||||
RC_TIMER_BUILD_DISTANCEFIELD_BLUR,
|
||||
RC_TIMER_BUILD_REGIONS,
|
||||
RC_TIMER_BUILD_REGIONS_WATERSHED,
|
||||
RC_TIMER_BUILD_REGIONS_EXPAND,
|
||||
RC_TIMER_BUILD_REGIONS_FLOOD,
|
||||
RC_TIMER_BUILD_REGIONS_FILTER,
|
||||
RC_TIMER_BUILD_POLYMESHDETAIL,
|
||||
RC_TIMER_MERGE_POLYMESHDETAIL,
|
||||
RC_MAX_TIMERS
|
||||
};
|
||||
|
||||
// Build context provides several optional utilities needed for the build process,
|
||||
// such as timing, logging, and build time collecting.
|
||||
class rcContext
|
||||
{
|
||||
public:
|
||||
inline rcContext(bool state = true) : m_logEnabled(state), m_timerEnabled(state) {}
|
||||
virtual ~rcContext() {}
|
||||
|
||||
// Enables or disables logging.
|
||||
inline void enableLog(bool state) { m_logEnabled = state; }
|
||||
// Resets log.
|
||||
inline void resetLog() { if (m_logEnabled) doResetLog(); }
|
||||
// Logs a message.
|
||||
void log(const rcLogCategory category, const char* format, ...);
|
||||
|
||||
// Enables or disables timer.
|
||||
inline void enableTimer(bool state) { m_timerEnabled = state; }
|
||||
// Resets all timers.
|
||||
inline void resetTimers() { if (m_timerEnabled) doResetTimers(); }
|
||||
// Starts timer, used for performance timing.
|
||||
inline void startTimer(const rcTimerLabel label) { if (m_timerEnabled) doStartTimer(label); }
|
||||
// Stops timer, used for performance timing.
|
||||
inline void stopTimer(const rcTimerLabel label) { if (m_timerEnabled) doStopTimer(label); }
|
||||
// Returns time accumulated between timer start/stop.
|
||||
inline int getAccumulatedTime(const rcTimerLabel label) const { return m_timerEnabled ? doGetAccumulatedTime(label) : -1; }
|
||||
|
||||
protected:
|
||||
// Virtual functions to override for custom implementations.
|
||||
virtual void doResetLog() {}
|
||||
virtual void doLog(const rcLogCategory /*category*/, const char* /*msg*/, const int /*len*/) {}
|
||||
virtual void doResetTimers() {}
|
||||
virtual void doStartTimer(const rcTimerLabel /*label*/) {}
|
||||
virtual void doStopTimer(const rcTimerLabel /*label*/) {}
|
||||
virtual int doGetAccumulatedTime(const rcTimerLabel /*label*/) const { return -1; }
|
||||
|
||||
bool m_logEnabled;
|
||||
bool m_timerEnabled;
|
||||
};
|
||||
|
||||
|
||||
// The units of the parameters are specified in parenthesis as follows:
|
||||
// (vx) voxels, (wu) world units
|
||||
struct rcConfig
|
||||
{
|
||||
int width, height; // Dimensions of the rasterized heightfield (vx)
|
||||
int tileSize; // Width and Height of a tile (vx)
|
||||
int borderSize; // Non-navigable Border around the heightfield (vx)
|
||||
float cs, ch; // Grid cell size and height (wu)
|
||||
float bmin[3], bmax[3]; // Grid bounds (wu)
|
||||
float walkableSlopeAngle; // Maximum walkable slope angle in degrees.
|
||||
int walkableHeight; // Minimum height where the agent can still walk (vx)
|
||||
int walkableClimb; // Maximum height between grid cells the agent can climb (vx)
|
||||
int walkableRadius; // Radius of the agent in cells (vx)
|
||||
int maxEdgeLen; // Maximum contour edge length (vx)
|
||||
float maxSimplificationError; // Maximum distance error from contour to cells (vx)
|
||||
int minRegionArea; // Regions whose area is smaller than this threshold will be removed. (vx)
|
||||
int mergeRegionArea; // Regions whose area is smaller than this threshold will be merged (vx)
|
||||
int maxVertsPerPoly; // Max number of vertices per polygon
|
||||
float detailSampleDist; // Detail mesh sample spacing.
|
||||
float detailSampleMaxError; // Detail mesh simplification max sample error.
|
||||
};
|
||||
|
||||
// Define number of bits in the above structure for smin/smax.
|
||||
// The max height is used for clamping rasterized values.
|
||||
static const int RC_SPAN_HEIGHT_BITS = 16;
|
||||
static const int RC_SPAN_MAX_HEIGHT = (1<<RC_SPAN_HEIGHT_BITS)-1;
|
||||
|
||||
// Heightfield span.
|
||||
struct rcSpan
|
||||
{
|
||||
unsigned int smin : 16; // Span min height.
|
||||
unsigned int smax : 16; // Span max height.
|
||||
unsigned char area; // Span area type.
|
||||
rcSpan* next; // Next span in column.
|
||||
};
|
||||
|
||||
// Number of spans allocated per pool.
|
||||
static const int RC_SPANS_PER_POOL = 2048;
|
||||
|
||||
// Memory pool used for quick span allocation.
|
||||
struct rcSpanPool
|
||||
{
|
||||
rcSpanPool* next; // Pointer to next pool.
|
||||
rcSpan items[RC_SPANS_PER_POOL]; // Array of spans.
|
||||
};
|
||||
|
||||
// Dynamic span-heightfield.
|
||||
struct rcHeightfield
|
||||
{
|
||||
int width, height; // Dimension of the heightfield.
|
||||
float bmin[3], bmax[3]; // Bounding box of the heightfield
|
||||
float cs, ch; // Cell size and height.
|
||||
rcSpan** spans; // Heightfield of spans (width*height).
|
||||
rcSpanPool* pools; // Linked list of span pools.
|
||||
rcSpan* freelist; // Pointer to next free span.
|
||||
};
|
||||
|
||||
rcHeightfield* rcAllocHeightfield();
|
||||
void rcFreeHeightField(rcHeightfield* hf);
|
||||
|
||||
|
||||
struct rcCompactCell
|
||||
{
|
||||
unsigned int index : 24; // Index to first span in column.
|
||||
unsigned int count : 8; // Number of spans in this column.
|
||||
};
|
||||
|
||||
struct rcCompactSpan
|
||||
{
|
||||
unsigned short y; // Bottom coordinate of the span.
|
||||
unsigned short reg;
|
||||
unsigned int con : 24; // Connections to neighbour cells.
|
||||
unsigned int h : 8; // Height of the span.
|
||||
};
|
||||
|
||||
// Compact static heightfield.
|
||||
struct rcCompactHeightfield
|
||||
{
|
||||
int width, height; // Width and height of the heightfield.
|
||||
int spanCount; // Number of spans in the heightfield.
|
||||
int walkableHeight, walkableClimb; // Agent properties.
|
||||
unsigned short maxDistance; // Maximum distance value stored in heightfield.
|
||||
unsigned short maxRegions; // Maximum Region Id stored in heightfield.
|
||||
float bmin[3], bmax[3]; // Bounding box of the heightfield.
|
||||
float cs, ch; // Cell size and height.
|
||||
rcCompactCell* cells; // Pointer to width*height cells.
|
||||
rcCompactSpan* spans; // Pointer to spans.
|
||||
unsigned short* dist; // Pointer to per span distance to border.
|
||||
unsigned char* areas; // Pointer to per span area ID.
|
||||
};
|
||||
|
||||
rcCompactHeightfield* rcAllocCompactHeightfield();
|
||||
void rcFreeCompactHeightfield(rcCompactHeightfield* chf);
|
||||
|
||||
|
||||
struct rcContour
|
||||
{
|
||||
int* verts; // Vertex coordinates, each vertex contains 4 components.
|
||||
int nverts; // Number of vertices.
|
||||
int* rverts; // Raw vertex coordinates, each vertex contains 4 components.
|
||||
int nrverts; // Number of raw vertices.
|
||||
unsigned short reg; // Region ID of the contour.
|
||||
unsigned char area; // Area ID of the contour.
|
||||
};
|
||||
|
||||
struct rcContourSet
|
||||
{
|
||||
rcContour* conts; // Pointer to all contours.
|
||||
int nconts; // Number of contours.
|
||||
float bmin[3], bmax[3]; // Bounding box of the heightfield.
|
||||
float cs, ch; // Cell size and height.
|
||||
};
|
||||
|
||||
rcContourSet* rcAllocContourSet();
|
||||
void rcFreeContourSet(rcContourSet* cset);
|
||||
|
||||
|
||||
// Polymesh store a connected mesh of polygons.
|
||||
// The polygons are store in an array where each polygons takes
|
||||
// 'nvp*2' elements. The first 'nvp' elements are indices to vertices
|
||||
// and the second 'nvp' elements are indices to neighbour polygons.
|
||||
// If a polygon has less than 'bvp' vertices, the remaining indices
|
||||
// are set to RC_MESH_NULL_IDX. If an polygon edge does not have a neighbour
|
||||
// the neighbour index is set to RC_MESH_NULL_IDX.
|
||||
// Vertices can be transformed into world space as follows:
|
||||
// x = bmin[0] + verts[i*3+0]*cs;
|
||||
// y = bmin[1] + verts[i*3+1]*ch;
|
||||
// z = bmin[2] + verts[i*3+2]*cs;
|
||||
struct rcPolyMesh
|
||||
{
|
||||
unsigned short* verts; // Vertices of the mesh, 3 elements per vertex.
|
||||
unsigned short* polys; // Polygons of the mesh, nvp*2 elements per polygon.
|
||||
unsigned short* regs; // Region ID of the polygons.
|
||||
unsigned short* flags; // Per polygon flags.
|
||||
unsigned char* areas; // Area ID of polygons.
|
||||
int nverts; // Number of vertices.
|
||||
int npolys; // Number of polygons.
|
||||
int maxpolys; // Number of allocated polygons.
|
||||
int nvp; // Max number of vertices per polygon.
|
||||
float bmin[3], bmax[3]; // Bounding box of the mesh.
|
||||
float cs, ch; // Cell size and height.
|
||||
};
|
||||
|
||||
rcPolyMesh* rcAllocPolyMesh();
|
||||
void rcFreePolyMesh(rcPolyMesh* pmesh);
|
||||
|
||||
|
||||
// Detail mesh generated from a rcPolyMesh.
|
||||
// Each submesh represents a polygon in the polymesh and they are stored in
|
||||
// exactly same order. Each submesh is described as 4 values:
|
||||
// base vertex, vertex count, base triangle, triangle count. That is,
|
||||
// const unsigned char* t = &dmesh.tris[(tbase+i)*3]; and
|
||||
// const float* v = &dmesh.verts[(vbase+t[j])*3];
|
||||
// If the input polygon has 'n' vertices, those vertices are first in the
|
||||
// submesh vertex list. This allows to compres the mesh by not storing the
|
||||
// first vertices and using the polymesh vertices instead.
|
||||
// Max number of vertices per submesh is 127 and
|
||||
// max number of triangles per submesh is 255.
|
||||
|
||||
struct rcPolyMeshDetail
|
||||
{
|
||||
unsigned int* meshes; // Pointer to all mesh data.
|
||||
float* verts; // Pointer to all vertex data.
|
||||
unsigned char* tris; // Pointer to all triangle data.
|
||||
int nmeshes; // Number of meshes.
|
||||
int nverts; // Number of total vertices.
|
||||
int ntris; // Number of triangles.
|
||||
};
|
||||
|
||||
rcPolyMeshDetail* rcAllocPolyMeshDetail();
|
||||
void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh);
|
||||
|
||||
|
||||
// If heightfield region ID has the following bit set, the region is on border area
|
||||
// and excluded from many calculations.
|
||||
static const unsigned short RC_BORDER_REG = 0x8000;
|
||||
|
||||
// If contour region ID has the following bit set, the vertex will be later
|
||||
// removed in order to match the segments and vertices at tile boundaries.
|
||||
static const int RC_BORDER_VERTEX = 0x10000;
|
||||
|
||||
static const int RC_AREA_BORDER = 0x20000;
|
||||
|
||||
enum rcBuildContoursFlags
|
||||
{
|
||||
RC_CONTOUR_TESS_WALL_EDGES = 0x01, // Tessellate wall edges
|
||||
RC_CONTOUR_TESS_AREA_EDGES = 0x02, // Tessellate edges between areas.
|
||||
};
|
||||
|
||||
// Mask used with contours to extract region id.
|
||||
static const int RC_CONTOUR_REG_MASK = 0xffff;
|
||||
|
||||
// Null index which is used with meshes to mark unset or invalid indices.
|
||||
static const unsigned short RC_MESH_NULL_IDX = 0xffff;
|
||||
|
||||
// Area ID that is considered empty.
|
||||
static const unsigned char RC_NULL_AREA = 0;
|
||||
|
||||
// Area ID that is considered generally walkable.
|
||||
static const unsigned char RC_WALKABLE_AREA = 63;
|
||||
|
||||
// Value returned by rcGetCon() if the direction is not connected.
|
||||
static const int RC_NOT_CONNECTED = 0x3f;
|
||||
|
||||
// Compact span neighbour helpers.
|
||||
inline void rcSetCon(rcCompactSpan& s, int dir, int i)
|
||||
{
|
||||
const unsigned int shift = (unsigned int)dir*6;
|
||||
unsigned int con = s.con;
|
||||
s.con = (con & ~(0x3f << shift)) | (((unsigned int)i & 0x3f) << shift);
|
||||
}
|
||||
|
||||
inline int rcGetCon(const rcCompactSpan& s, int dir)
|
||||
{
|
||||
const unsigned int shift = (unsigned int)dir*6;
|
||||
return (s.con >> shift) & 0x3f;
|
||||
}
|
||||
|
||||
inline int rcGetDirOffsetX(int dir)
|
||||
{
|
||||
const int offset[4] = { -1, 0, 1, 0, };
|
||||
return offset[dir&0x03];
|
||||
}
|
||||
|
||||
inline int rcGetDirOffsetY(int dir)
|
||||
{
|
||||
const int offset[4] = { 0, 1, 0, -1 };
|
||||
return offset[dir&0x03];
|
||||
}
|
||||
|
||||
// Common helper functions
|
||||
template<class T> inline void rcSwap(T& a, T& b) { T t = a; a = b; b = t; }
|
||||
template<class T> inline T rcMin(T a, T b) { return a < b ? a : b; }
|
||||
template<class T> inline T rcMax(T a, T b) { return a > b ? a : b; }
|
||||
template<class T> inline T rcAbs(T a) { return a < 0 ? -a : a; }
|
||||
template<class T> inline T rcSqr(T a) { return a*a; }
|
||||
template<class T> inline T rcClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); }
|
||||
float rcSqrt(float x);
|
||||
|
||||
// Common vector helper functions.
|
||||
inline void rcVcross(float* dest, const float* v1, const float* v2)
|
||||
{
|
||||
dest[0] = v1[1]*v2[2] - v1[2]*v2[1];
|
||||
dest[1] = v1[2]*v2[0] - v1[0]*v2[2];
|
||||
dest[2] = v1[0]*v2[1] - v1[1]*v2[0];
|
||||
}
|
||||
|
||||
inline float rcVdot(const float* v1, const float* v2)
|
||||
{
|
||||
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
|
||||
}
|
||||
|
||||
inline void rcVmad(float* dest, const float* v1, const float* v2, const float s)
|
||||
{
|
||||
dest[0] = v1[0]+v2[0]*s;
|
||||
dest[1] = v1[1]+v2[1]*s;
|
||||
dest[2] = v1[2]+v2[2]*s;
|
||||
}
|
||||
|
||||
inline void rcVadd(float* dest, const float* v1, const float* v2)
|
||||
{
|
||||
dest[0] = v1[0]+v2[0];
|
||||
dest[1] = v1[1]+v2[1];
|
||||
dest[2] = v1[2]+v2[2];
|
||||
}
|
||||
|
||||
inline void rcVsub(float* dest, const float* v1, const float* v2)
|
||||
{
|
||||
dest[0] = v1[0]-v2[0];
|
||||
dest[1] = v1[1]-v2[1];
|
||||
dest[2] = v1[2]-v2[2];
|
||||
}
|
||||
|
||||
inline void rcVmin(float* mn, const float* v)
|
||||
{
|
||||
mn[0] = rcMin(mn[0], v[0]);
|
||||
mn[1] = rcMin(mn[1], v[1]);
|
||||
mn[2] = rcMin(mn[2], v[2]);
|
||||
}
|
||||
|
||||
inline void rcVmax(float* mx, const float* v)
|
||||
{
|
||||
mx[0] = rcMax(mx[0], v[0]);
|
||||
mx[1] = rcMax(mx[1], v[1]);
|
||||
mx[2] = rcMax(mx[2], v[2]);
|
||||
}
|
||||
|
||||
inline void rcVcopy(float* dest, const float* v)
|
||||
{
|
||||
dest[0] = v[0];
|
||||
dest[1] = v[1];
|
||||
dest[2] = v[2];
|
||||
}
|
||||
|
||||
inline float rcVdist(const float* v1, const float* v2)
|
||||
{
|
||||
float dx = v2[0] - v1[0];
|
||||
float dy = v2[1] - v1[1];
|
||||
float dz = v2[2] - v1[2];
|
||||
return rcSqrt(dx*dx + dy*dy + dz*dz);
|
||||
}
|
||||
|
||||
inline float rcVdistSqr(const float* v1, const float* v2)
|
||||
{
|
||||
float dx = v2[0] - v1[0];
|
||||
float dy = v2[1] - v1[1];
|
||||
float dz = v2[2] - v1[2];
|
||||
return dx*dx + dy*dy + dz*dz;
|
||||
}
|
||||
|
||||
inline void rcVnormalize(float* v)
|
||||
{
|
||||
float d = 1.0f / rcSqrt(rcSqr(v[0]) + rcSqr(v[1]) + rcSqr(v[2]));
|
||||
v[0] *= d;
|
||||
v[1] *= d;
|
||||
v[2] *= d;
|
||||
}
|
||||
|
||||
inline bool rcVequal(const float* p0, const float* p1)
|
||||
{
|
||||
static const float thr = rcSqr(1.0f/16384.0f);
|
||||
const float d = rcVdistSqr(p0, p1);
|
||||
return d < thr;
|
||||
}
|
||||
|
||||
// Calculated bounding box of array of vertices.
|
||||
// Params:
|
||||
// verts - (in) array of vertices
|
||||
// nv - (in) vertex count
|
||||
// bmin, bmax - (out) bounding box
|
||||
void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax);
|
||||
|
||||
// Calculates grid size based on bounding box and grid cell size.
|
||||
// Params:
|
||||
// bmin, bmax - (in) bounding box
|
||||
// cs - (in) grid cell size
|
||||
// w - (out) grid width
|
||||
// h - (out) grid height
|
||||
void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* h);
|
||||
|
||||
// Creates and initializes new heightfield.
|
||||
// Params:
|
||||
// hf - (in/out) heightfield to initialize.
|
||||
// width - (in) width of the heightfield.
|
||||
// height - (in) height of the heightfield.
|
||||
// bmin, bmax - (in) bounding box of the heightfield
|
||||
// cs - (in) grid cell size
|
||||
// ch - (in) grid cell height
|
||||
bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int height,
|
||||
const float* bmin, const float* bmax,
|
||||
float cs, float ch);
|
||||
|
||||
// Sets the RC_WALKABLE_AREA for every triangle whose slope is below
|
||||
// the maximum walkable slope angle.
|
||||
// Params:
|
||||
// walkableSlopeAngle - (in) maximum slope angle in degrees.
|
||||
// verts - (in) array of vertices
|
||||
// nv - (in) vertex count
|
||||
// tris - (in) array of triangle vertex indices
|
||||
// nt - (in) triangle count
|
||||
// areas - (out) array of triangle area types
|
||||
void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv,
|
||||
const int* tris, int nt, unsigned char* areas);
|
||||
|
||||
// Sets the RC_NULL_AREA for every triangle whose slope is steeper than
|
||||
// the maximum walkable slope angle.
|
||||
// Params:
|
||||
// walkableSlopeAngle - (in) maximum slope angle in degrees.
|
||||
// verts - (in) array of vertices
|
||||
// nv - (in) vertex count
|
||||
// tris - (in) array of triangle vertex indices
|
||||
// nt - (in) triangle count
|
||||
// areas - (out) array of triangle are types
|
||||
void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv,
|
||||
const int* tris, int nt, unsigned char* areas);
|
||||
|
||||
// Adds span to heightfield.
|
||||
// The span addition can set to favor flags. If the span is merged to
|
||||
// another span and the new smax is within 'flagMergeThr' units away
|
||||
// from the existing span the span flags are merged and stored.
|
||||
// Params:
|
||||
// solid - (in) heightfield where the spans is added to
|
||||
// x,y - (in) location on the heightfield where the span is added
|
||||
// smin,smax - (in) spans min/max height
|
||||
// flags - (in) span flags (zero or WALKABLE)
|
||||
// flagMergeThr - (in) merge threshold.
|
||||
void rcAddSpan(rcContext* ctx, rcHeightfield& solid, const int x, const int y,
|
||||
const unsigned short smin, const unsigned short smax,
|
||||
const unsigned short area, const int flagMergeThr);
|
||||
|
||||
// Rasterizes a triangle into heightfield spans.
|
||||
// Params:
|
||||
// v0,v1,v2 - (in) the vertices of the triangle.
|
||||
// area - (in) area type of the triangle.
|
||||
// solid - (in) heightfield where the triangle is rasterized
|
||||
// flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable.
|
||||
void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2,
|
||||
const unsigned char area, rcHeightfield& solid,
|
||||
const int flagMergeThr = 1);
|
||||
|
||||
// Rasterizes indexed triangle mesh into heightfield spans.
|
||||
// Params:
|
||||
// verts - (in) array of vertices
|
||||
// nv - (in) vertex count
|
||||
// tris - (in) array of triangle vertex indices
|
||||
// area - (in) array of triangle area types.
|
||||
// nt - (in) triangle count
|
||||
// solid - (in) heightfield where the triangles are rasterized
|
||||
// flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable.
|
||||
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv,
|
||||
const int* tris, const unsigned char* areas, const int nt,
|
||||
rcHeightfield& solid, const int flagMergeThr = 1);
|
||||
|
||||
// Rasterizes indexed triangle mesh into heightfield spans.
|
||||
// Params:
|
||||
// verts - (in) array of vertices
|
||||
// nv - (in) vertex count
|
||||
// tris - (in) array of triangle vertex indices
|
||||
// area - (in) array of triangle area types.
|
||||
// nt - (in) triangle count
|
||||
// solid - (in) heightfield where the triangles are rasterized
|
||||
// flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable.
|
||||
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv,
|
||||
const unsigned short* tris, const unsigned char* areas, const int nt,
|
||||
rcHeightfield& solid, const int flagMergeThr = 1);
|
||||
|
||||
// Rasterizes the triangles into heightfield spans.
|
||||
// Params:
|
||||
// verts - (in) array of vertices
|
||||
// area - (in) array of triangle area types.
|
||||
// nt - (in) triangle count
|
||||
// solid - (in) heightfield where the triangles are rasterized
|
||||
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt,
|
||||
rcHeightfield& solid, const int flagMergeThr = 1);
|
||||
|
||||
// Marks non-walkable low obstacles as walkable if they are closer than walkableClimb
|
||||
// from a walkable surface. Applying this filter allows to step over low hanging
|
||||
// low obstacles.
|
||||
// Params:
|
||||
// walkableHeight - (in) minimum height where the agent can still walk
|
||||
// solid - (in/out) heightfield describing the solid space
|
||||
// TODO: Missuses ledge flag, must be called before rcFilterLedgeSpans!
|
||||
void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid);
|
||||
|
||||
// Removes WALKABLE flag from all spans that are at ledges. This filtering
|
||||
// removes possible overestimation of the conservative voxelization so that
|
||||
// the resulting mesh will not have regions hanging in air over ledges.
|
||||
// Params:
|
||||
// walkableHeight - (in) minimum height where the agent can still walk
|
||||
// walkableClimb - (in) maximum height between grid cells the agent can climb
|
||||
// solid - (in/out) heightfield describing the solid space
|
||||
void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight,
|
||||
const int walkableClimb, rcHeightfield& solid);
|
||||
|
||||
// Removes WALKABLE flag from all spans which have smaller than
|
||||
// 'walkableHeight' clearance above them.
|
||||
// Params:
|
||||
// walkableHeight - (in) minimum height where the agent can still walk
|
||||
// solid - (in/out) heightfield describing the solid space
|
||||
void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid);
|
||||
|
||||
// Returns number of spans contained in a heightfield.
|
||||
// Params:
|
||||
// hf - (in) heightfield to be compacted
|
||||
// Returns number of spans.
|
||||
int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf);
|
||||
|
||||
// Builds compact representation of the heightfield.
|
||||
// Params:
|
||||
// walkableHeight - (in) minimum height where the agent can still walk
|
||||
// walkableClimb - (in) maximum height between grid cells the agent can climb
|
||||
// flags - (in) require flags for a cell to be included in the compact heightfield.
|
||||
// hf - (in) heightfield to be compacted
|
||||
// chf - (out) compact heightfield representing the open space.
|
||||
// Returns false if operation ran out of memory.
|
||||
bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb,
|
||||
rcHeightfield& hf, rcCompactHeightfield& chf);
|
||||
|
||||
// Erodes walkable area.
|
||||
// Params:
|
||||
// radius - (in) radius of erosion (max 255).
|
||||
// chf - (in/out) compact heightfield to erode.
|
||||
// Returns false if operation ran out of memory.
|
||||
bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf);
|
||||
|
||||
// Applies median filter to walkable area types, removing noise.
|
||||
// Params:
|
||||
// chf - (in/out) compact heightfield to erode.
|
||||
// Returns false if operation ran out of memory.
|
||||
bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf);
|
||||
|
||||
// Marks the area of the convex polygon into the area type of the compact heightfield.
|
||||
// Params:
|
||||
// bmin/bmax - (in) bounds of the axis aligned box.
|
||||
// areaId - (in) area ID to mark.
|
||||
// chf - (in/out) compact heightfield to mark.
|
||||
void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId,
|
||||
rcCompactHeightfield& chf);
|
||||
|
||||
// Marks the area of the convex polygon into the area type of the compact heightfield.
|
||||
// Params:
|
||||
// verts - (in) vertices of the convex polygon.
|
||||
// nverts - (in) number of vertices in the polygon.
|
||||
// hmin/hmax - (in) min and max height of the polygon.
|
||||
// areaId - (in) area ID to mark.
|
||||
// chf - (in/out) compact heightfield to mark.
|
||||
void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
|
||||
const float hmin, const float hmax, unsigned char areaId,
|
||||
rcCompactHeightfield& chf);
|
||||
|
||||
// Builds distance field and stores it into the combat heightfield.
|
||||
// Params:
|
||||
// chf - (in/out) compact heightfield representing the open space.
|
||||
// Returns false if operation ran out of memory.
|
||||
bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf);
|
||||
|
||||
// Divides the walkable heighfied into simple regions using watershed partitioning.
|
||||
// Each region has only one contour and no overlaps.
|
||||
// The regions are stored in the compact heightfield 'reg' field.
|
||||
// The process sometimes creates small regions. If the area of a regions is
|
||||
// smaller than 'mergeRegionArea' then the region will be merged with a neighbour
|
||||
// region if possible. If multiple regions form an area which is smaller than
|
||||
// 'minRegionArea' all the regions belonging to that area will be removed.
|
||||
// Here area means the count of spans in an area.
|
||||
// Params:
|
||||
// chf - (in/out) compact heightfield representing the open space.
|
||||
// minRegionArea - (in) the smallest allowed region area.
|
||||
// maxMergeRegionArea - (in) the largest allowed region area which can be merged.
|
||||
// Returns false if operation ran out of memory.
|
||||
bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
const int borderSize, const int minRegionArea, const int mergeRegionArea);
|
||||
|
||||
// Divides the walkable heighfied into simple regions using simple monotone partitioning.
|
||||
// Each region has only one contour and no overlaps.
|
||||
// The regions are stored in the compact heightfield 'reg' field.
|
||||
// The process sometimes creates small regions. If the area of a regions is
|
||||
// smaller than 'mergeRegionArea' then the region will be merged with a neighbour
|
||||
// region if possible. If multiple regions form an area which is smaller than
|
||||
// 'minRegionArea' all the regions belonging to that area will be removed.
|
||||
// Here area means the count of spans in an area.
|
||||
// Params:
|
||||
// chf - (in/out) compact heightfield representing the open space.
|
||||
// minRegionArea - (in) the smallest allowed regions size.
|
||||
// maxMergeRegionArea - (in) the largest allowed regions size which can be merged.
|
||||
// Returns false if operation ran out of memory.
|
||||
bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
const int borderSize, const int minRegionArea, const int mergeRegionArea);
|
||||
|
||||
// Builds simplified contours from the regions outlines.
|
||||
// Params:
|
||||
// chf - (in) compact heightfield which has regions set.
|
||||
// maxError - (in) maximum allowed distance between simplified contour and cells.
|
||||
// maxEdgeLen - (in) maximum allowed contour edge length in cells.
|
||||
// cset - (out) Resulting contour set.
|
||||
// flags - (in) build flags, see rcBuildContoursFlags.
|
||||
// Returns false if operation ran out of memory.
|
||||
bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
const float maxError, const int maxEdgeLen,
|
||||
rcContourSet& cset, const int flags = RC_CONTOUR_TESS_WALL_EDGES);
|
||||
|
||||
// Builds connected convex polygon mesh from contour polygons.
|
||||
// Params:
|
||||
// cset - (in) contour set.
|
||||
// nvp - (in) maximum number of vertices per polygon.
|
||||
// mesh - (out) poly mesh.
|
||||
// Returns false if operation ran out of memory.
|
||||
bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& mesh);
|
||||
|
||||
bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh);
|
||||
|
||||
// Builds detail triangle mesh for each polygon in the poly mesh.
|
||||
// Params:
|
||||
// mesh - (in) poly mesh to detail.
|
||||
// chf - (in) compact height field, used to query height for new vertices.
|
||||
// sampleDist - (in) spacing between height samples used to generate more detail into mesh.
|
||||
// sampleMaxError - (in) maximum allowed distance between simplified detail mesh and height sample.
|
||||
// pmdtl - (out) detail mesh.
|
||||
// Returns false if operation ran out of memory.
|
||||
bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf,
|
||||
const float sampleDist, const float sampleMaxError,
|
||||
rcPolyMeshDetail& dmesh);
|
||||
|
||||
bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh);
|
||||
|
||||
|
||||
#endif // RECAST_H
|
||||
67
dep/recastnavigation/Recast/RecastAlloc.cpp
Normal file
67
dep/recastnavigation/Recast/RecastAlloc.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "RecastAlloc.h"
|
||||
|
||||
static void *rcAllocDefault(int size, rcAllocHint)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void rcFreeDefault(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static rcAllocFunc* sRecastAllocFunc = rcAllocDefault;
|
||||
static rcFreeFunc* sRecastFreeFunc = rcFreeDefault;
|
||||
|
||||
void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc)
|
||||
{
|
||||
sRecastAllocFunc = allocFunc ? allocFunc : rcAllocDefault;
|
||||
sRecastFreeFunc = freeFunc ? freeFunc : rcFreeDefault;
|
||||
}
|
||||
|
||||
void* rcAlloc(int size, rcAllocHint hint)
|
||||
{
|
||||
return sRecastAllocFunc(size, hint);
|
||||
}
|
||||
|
||||
void rcFree(void* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
sRecastFreeFunc(ptr);
|
||||
}
|
||||
|
||||
|
||||
void rcIntArray::resize(int n)
|
||||
{
|
||||
if (n > m_cap)
|
||||
{
|
||||
if (!m_cap) m_cap = n;
|
||||
while (m_cap < n) m_cap *= 2;
|
||||
int* newData = (int*)rcAlloc(m_cap*sizeof(int), RC_ALLOC_TEMP);
|
||||
if (m_size && newData) memcpy(newData, m_data, m_size*sizeof(int));
|
||||
rcFree(m_data);
|
||||
m_data = newData;
|
||||
}
|
||||
m_size = n;
|
||||
}
|
||||
|
||||
69
dep/recastnavigation/Recast/RecastAlloc.h
Normal file
69
dep/recastnavigation/Recast/RecastAlloc.h
Normal file
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef RECASTALLOC_H
|
||||
#define RECASTALLOC_H
|
||||
|
||||
enum rcAllocHint
|
||||
{
|
||||
RC_ALLOC_PERM, // Memory persist after a function call.
|
||||
RC_ALLOC_TEMP // Memory used temporarily within a function.
|
||||
};
|
||||
|
||||
typedef void* (rcAllocFunc)(int size, rcAllocHint hint);
|
||||
typedef void (rcFreeFunc)(void* ptr);
|
||||
|
||||
void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc);
|
||||
|
||||
void* rcAlloc(int size, rcAllocHint hint);
|
||||
void rcFree(void* ptr);
|
||||
|
||||
|
||||
|
||||
// Simple dynamic array ints.
|
||||
class rcIntArray
|
||||
{
|
||||
int* m_data;
|
||||
int m_size, m_cap;
|
||||
inline rcIntArray(const rcIntArray&);
|
||||
inline rcIntArray& operator=(const rcIntArray&);
|
||||
public:
|
||||
inline rcIntArray() : m_data(0), m_size(0), m_cap(0) {}
|
||||
inline rcIntArray(int n) : m_data(0), m_size(0), m_cap(0) { resize(n); }
|
||||
inline ~rcIntArray() { rcFree(m_data); }
|
||||
void resize(int n);
|
||||
inline void push(int item) { resize(m_size+1); m_data[m_size-1] = item; }
|
||||
inline int pop() { if (m_size > 0) m_size--; return m_data[m_size]; }
|
||||
inline const int& operator[](int i) const { return m_data[i]; }
|
||||
inline int& operator[](int i) { return m_data[i]; }
|
||||
inline int size() const { return m_size; }
|
||||
};
|
||||
|
||||
// Simple internal helper class to delete array in scope
|
||||
template<class T> class rcScopedDelete
|
||||
{
|
||||
T* ptr;
|
||||
inline T* operator=(T* p);
|
||||
public:
|
||||
inline rcScopedDelete() : ptr(0) {}
|
||||
inline rcScopedDelete(T* p) : ptr(p) {}
|
||||
inline ~rcScopedDelete() { rcFree(ptr); }
|
||||
inline operator T*() { return ptr; }
|
||||
};
|
||||
|
||||
#endif
|
||||
413
dep/recastnavigation/Recast/RecastArea.cpp
Normal file
413
dep/recastnavigation/Recast/RecastArea.cpp
Normal file
@@ -0,0 +1,413 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include <float.h>
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "Recast.h"
|
||||
#include "RecastAlloc.h"
|
||||
#include "RecastAssert.h"
|
||||
|
||||
|
||||
bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
const int w = chf.width;
|
||||
const int h = chf.height;
|
||||
|
||||
ctx->startTimer(RC_TIMER_ERODE_AREA);
|
||||
|
||||
unsigned char* dist = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP);
|
||||
if (!dist)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "erodeWalkableArea: Out of memory 'dist' (%d).", chf.spanCount);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Init distance.
|
||||
memset(dist, 0xff, sizeof(unsigned char)*chf.spanCount);
|
||||
|
||||
// Mark boundary cells.
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
if (chf.areas[i] != RC_NULL_AREA)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
int nc = 0;
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
nc++;
|
||||
}
|
||||
// At least one missing neighbour.
|
||||
if (nc != 4)
|
||||
dist[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char nd;
|
||||
|
||||
// Pass 1
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
|
||||
if (rcGetCon(s, 0) != RC_NOT_CONNECTED)
|
||||
{
|
||||
// (-1,0)
|
||||
const int ax = x + rcGetDirOffsetX(0);
|
||||
const int ay = y + rcGetDirOffsetY(0);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 0);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
nd = (unsigned char)rcMin((int)dist[ai]+2, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
|
||||
// (-1,-1)
|
||||
if (rcGetCon(as, 3) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int aax = ax + rcGetDirOffsetX(3);
|
||||
const int aay = ay + rcGetDirOffsetY(3);
|
||||
const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 3);
|
||||
nd = (unsigned char)rcMin((int)dist[aai]+3, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
}
|
||||
}
|
||||
if (rcGetCon(s, 3) != RC_NOT_CONNECTED)
|
||||
{
|
||||
// (0,-1)
|
||||
const int ax = x + rcGetDirOffsetX(3);
|
||||
const int ay = y + rcGetDirOffsetY(3);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 3);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
nd = (unsigned char)rcMin((int)dist[ai]+2, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
|
||||
// (1,-1)
|
||||
if (rcGetCon(as, 2) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int aax = ax + rcGetDirOffsetX(2);
|
||||
const int aay = ay + rcGetDirOffsetY(2);
|
||||
const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 2);
|
||||
nd = (unsigned char)rcMin((int)dist[aai]+3, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pass 2
|
||||
for (int y = h-1; y >= 0; --y)
|
||||
{
|
||||
for (int x = w-1; x >= 0; --x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
|
||||
if (rcGetCon(s, 2) != RC_NOT_CONNECTED)
|
||||
{
|
||||
// (1,0)
|
||||
const int ax = x + rcGetDirOffsetX(2);
|
||||
const int ay = y + rcGetDirOffsetY(2);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 2);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
nd = (unsigned char)rcMin((int)dist[ai]+2, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
|
||||
// (1,1)
|
||||
if (rcGetCon(as, 1) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int aax = ax + rcGetDirOffsetX(1);
|
||||
const int aay = ay + rcGetDirOffsetY(1);
|
||||
const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 1);
|
||||
nd = (unsigned char)rcMin((int)dist[aai]+3, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
}
|
||||
}
|
||||
if (rcGetCon(s, 1) != RC_NOT_CONNECTED)
|
||||
{
|
||||
// (0,1)
|
||||
const int ax = x + rcGetDirOffsetX(1);
|
||||
const int ay = y + rcGetDirOffsetY(1);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 1);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
nd = (unsigned char)rcMin((int)dist[ai]+2, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
|
||||
// (-1,1)
|
||||
if (rcGetCon(as, 0) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int aax = ax + rcGetDirOffsetX(0);
|
||||
const int aay = ay + rcGetDirOffsetY(0);
|
||||
const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 0);
|
||||
nd = (unsigned char)rcMin((int)dist[aai]+3, 255);
|
||||
if (nd < dist[i])
|
||||
dist[i] = nd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned char thr = (unsigned char)(radius*2);
|
||||
for (int i = 0; i < chf.spanCount; ++i)
|
||||
if (dist[i] < thr)
|
||||
chf.areas[i] = RC_NULL_AREA;
|
||||
|
||||
rcFree(dist);
|
||||
|
||||
ctx->stopTimer(RC_TIMER_ERODE_AREA);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void insertSort(unsigned char* a, const int n)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 1; i < n; i++)
|
||||
{
|
||||
const unsigned char value = a[i];
|
||||
for (j = i - 1; j >= 0 && a[j] > value; j--)
|
||||
a[j+1] = a[j];
|
||||
a[j+1] = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
const int w = chf.width;
|
||||
const int h = chf.height;
|
||||
|
||||
ctx->startTimer(RC_TIMER_MEDIAN_AREA);
|
||||
|
||||
unsigned char* areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP);
|
||||
if (!areas)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "medianFilterWalkableArea: Out of memory 'areas' (%d).", chf.spanCount);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Init distance.
|
||||
memset(areas, 0xff, sizeof(unsigned char)*chf.spanCount);
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
if (chf.areas[i] == RC_NULL_AREA)
|
||||
{
|
||||
areas[i] = chf.areas[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned char nei[9];
|
||||
for (int j = 0; j < 9; ++j)
|
||||
nei[j] = chf.areas[i];
|
||||
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = x + rcGetDirOffsetX(dir);
|
||||
const int ay = y + rcGetDirOffsetY(dir);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
|
||||
if (chf.areas[ai] != RC_NULL_AREA)
|
||||
nei[dir*2+0] = chf.areas[ai];
|
||||
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
const int dir2 = (dir+1) & 0x3;
|
||||
if (rcGetCon(as, dir2) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax2 = ax + rcGetDirOffsetX(dir2);
|
||||
const int ay2 = ay + rcGetDirOffsetY(dir2);
|
||||
const int ai2 = (int)chf.cells[ax2+ay2*w].index + rcGetCon(as, dir2);
|
||||
if (chf.areas[ai2] != RC_NULL_AREA)
|
||||
nei[dir*2+1] = chf.areas[ai2];
|
||||
}
|
||||
}
|
||||
}
|
||||
insertSort(nei, 9);
|
||||
areas[i] = nei[4];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(chf.areas, areas, sizeof(unsigned char)*chf.spanCount);
|
||||
|
||||
rcFree(areas);
|
||||
|
||||
ctx->stopTimer(RC_TIMER_MEDIAN_AREA);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId,
|
||||
rcCompactHeightfield& chf)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_MARK_BOX_AREA);
|
||||
|
||||
int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
|
||||
int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch);
|
||||
int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs);
|
||||
int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs);
|
||||
int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch);
|
||||
int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs);
|
||||
|
||||
if (maxx < 0) return;
|
||||
if (minx >= chf.width) return;
|
||||
if (maxz < 0) return;
|
||||
if (minz >= chf.height) return;
|
||||
|
||||
if (minx < 0) minx = 0;
|
||||
if (maxx >= chf.width) maxx = chf.width-1;
|
||||
if (minz < 0) minz = 0;
|
||||
if (maxz >= chf.height) maxz = chf.height-1;
|
||||
|
||||
for (int z = minz; z <= maxz; ++z)
|
||||
{
|
||||
for (int x = minx; x <= maxx; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+z*chf.width];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
rcCompactSpan& s = chf.spans[i];
|
||||
if ((int)s.y >= miny && (int)s.y <= maxy)
|
||||
{
|
||||
chf.areas[i] = areaId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_MARK_BOX_AREA);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int pointInPoly(int nvert, const float* verts, const float* p)
|
||||
{
|
||||
int i, j, c = 0;
|
||||
for (i = 0, j = nvert-1; i < nvert; j = i++)
|
||||
{
|
||||
const float* vi = &verts[i*3];
|
||||
const float* vj = &verts[j*3];
|
||||
if (((vi[2] > p[2]) != (vj[2] > p[2])) &&
|
||||
(p[0] < (vj[0]-vi[0]) * (p[2]-vi[2]) / (vj[2]-vi[2]) + vi[0]) )
|
||||
c = !c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
|
||||
const float hmin, const float hmax, unsigned char areaId,
|
||||
rcCompactHeightfield& chf)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_MARK_CONVEXPOLY_AREA);
|
||||
|
||||
float bmin[3], bmax[3];
|
||||
rcVcopy(bmin, verts);
|
||||
rcVcopy(bmax, verts);
|
||||
for (int i = 1; i < nverts; ++i)
|
||||
{
|
||||
rcVmin(bmin, &verts[i*3]);
|
||||
rcVmax(bmax, &verts[i*3]);
|
||||
}
|
||||
bmin[1] = hmin;
|
||||
bmax[1] = hmax;
|
||||
|
||||
int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
|
||||
int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch);
|
||||
int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs);
|
||||
int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs);
|
||||
int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch);
|
||||
int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs);
|
||||
|
||||
if (maxx < 0) return;
|
||||
if (minx >= chf.width) return;
|
||||
if (maxz < 0) return;
|
||||
if (minz >= chf.height) return;
|
||||
|
||||
if (minx < 0) minx = 0;
|
||||
if (maxx >= chf.width) maxx = chf.width-1;
|
||||
if (minz < 0) minz = 0;
|
||||
if (maxz >= chf.height) maxz = chf.height-1;
|
||||
|
||||
|
||||
// TODO: Optimize.
|
||||
for (int z = minz; z <= maxz; ++z)
|
||||
{
|
||||
for (int x = minx; x <= maxx; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+z*chf.width];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
rcCompactSpan& s = chf.spans[i];
|
||||
if ((int)s.y >= miny && (int)s.y <= maxy)
|
||||
{
|
||||
float p[3];
|
||||
p[0] = chf.bmin[0] + (x+0.5f)*chf.cs;
|
||||
p[1] = 0;
|
||||
p[2] = chf.bmin[2] + (z+0.5f)*chf.cs;
|
||||
|
||||
if (pointInPoly(nverts, verts, p))
|
||||
{
|
||||
chf.areas[i] = areaId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_MARK_CONVEXPOLY_AREA);
|
||||
}
|
||||
33
dep/recastnavigation/Recast/RecastAssert.h
Normal file
33
dep/recastnavigation/Recast/RecastAssert.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef RECASTASSERT_H
|
||||
#define RECASTASSERT_H
|
||||
|
||||
// Note: This header file's only purpose is to include define assert.
|
||||
// Feel free to change the file and include your own implementation instead.
|
||||
|
||||
#ifdef NDEBUG
|
||||
// From http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/
|
||||
# define rcAssert(x) do { (void)sizeof(x); } while(__LINE__==-1,false)
|
||||
#else
|
||||
# include <assert.h>
|
||||
# define rcAssert assert
|
||||
#endif
|
||||
|
||||
#endif // RECASTASSERT_H
|
||||
804
dep/recastnavigation/Recast/RecastContour.cpp
Normal file
804
dep/recastnavigation/Recast/RecastContour.cpp
Normal file
@@ -0,0 +1,804 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "Recast.h"
|
||||
#include "RecastAlloc.h"
|
||||
#include "RecastAssert.h"
|
||||
|
||||
|
||||
static int getCornerHeight(int x, int y, int i, int dir,
|
||||
const rcCompactHeightfield& chf,
|
||||
bool& isBorderVertex)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
int ch = (int)s.y;
|
||||
int dirp = (dir+1) & 0x3;
|
||||
|
||||
unsigned int regs[4] = {0,0,0,0};
|
||||
|
||||
// Combine region and area codes in order to prevent
|
||||
// border vertices which are in between two areas to be removed.
|
||||
regs[0] = chf.spans[i].reg | (chf.areas[i] << 16);
|
||||
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = x + rcGetDirOffsetX(dir);
|
||||
const int ay = y + rcGetDirOffsetY(dir);
|
||||
const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
ch = rcMax(ch, (int)as.y);
|
||||
regs[1] = chf.spans[ai].reg | (chf.areas[ai] << 16);
|
||||
if (rcGetCon(as, dirp) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax2 = ax + rcGetDirOffsetX(dirp);
|
||||
const int ay2 = ay + rcGetDirOffsetY(dirp);
|
||||
const int ai2 = (int)chf.cells[ax2+ay2*chf.width].index + rcGetCon(as, dirp);
|
||||
const rcCompactSpan& as2 = chf.spans[ai2];
|
||||
ch = rcMax(ch, (int)as2.y);
|
||||
regs[2] = chf.spans[ai2].reg | (chf.areas[ai2] << 16);
|
||||
}
|
||||
}
|
||||
if (rcGetCon(s, dirp) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = x + rcGetDirOffsetX(dirp);
|
||||
const int ay = y + rcGetDirOffsetY(dirp);
|
||||
const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dirp);
|
||||
const rcCompactSpan& as = chf.spans[ai];
|
||||
ch = rcMax(ch, (int)as.y);
|
||||
regs[3] = chf.spans[ai].reg | (chf.areas[ai] << 16);
|
||||
if (rcGetCon(as, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax2 = ax + rcGetDirOffsetX(dir);
|
||||
const int ay2 = ay + rcGetDirOffsetY(dir);
|
||||
const int ai2 = (int)chf.cells[ax2+ay2*chf.width].index + rcGetCon(as, dir);
|
||||
const rcCompactSpan& as2 = chf.spans[ai2];
|
||||
ch = rcMax(ch, (int)as2.y);
|
||||
regs[2] = chf.spans[ai2].reg | (chf.areas[ai2] << 16);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the vertex is special edge vertex, these vertices will be removed later.
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
const int a = j;
|
||||
const int b = (j+1) & 0x3;
|
||||
const int c = (j+2) & 0x3;
|
||||
const int d = (j+3) & 0x3;
|
||||
|
||||
// The vertex is a border vertex there are two same exterior cells in a row,
|
||||
// followed by two interior cells and none of the regions are out of bounds.
|
||||
const bool twoSameExts = (regs[a] & regs[b] & RC_BORDER_REG) != 0 && regs[a] == regs[b];
|
||||
const bool twoInts = ((regs[c] | regs[d]) & RC_BORDER_REG) == 0;
|
||||
const bool intsSameArea = (regs[c]>>16) == (regs[d]>>16);
|
||||
const bool noZeros = regs[a] != 0 && regs[b] != 0 && regs[c] != 0 && regs[d] != 0;
|
||||
if (twoSameExts && twoInts && intsSameArea && noZeros)
|
||||
{
|
||||
isBorderVertex = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
static void walkContour(int x, int y, int i,
|
||||
rcCompactHeightfield& chf,
|
||||
unsigned char* flags, rcIntArray& points)
|
||||
{
|
||||
// Choose the first non-connected edge
|
||||
unsigned char dir = 0;
|
||||
while ((flags[i] & (1 << dir)) == 0)
|
||||
dir++;
|
||||
|
||||
unsigned char startDir = dir;
|
||||
int starti = i;
|
||||
|
||||
const unsigned char area = chf.areas[i];
|
||||
|
||||
int iter = 0;
|
||||
while (++iter < 40000)
|
||||
{
|
||||
if (flags[i] & (1 << dir))
|
||||
{
|
||||
// Choose the edge corner
|
||||
bool isBorderVertex = false;
|
||||
bool isAreaBorder = false;
|
||||
int px = x;
|
||||
int py = getCornerHeight(x, y, i, dir, chf, isBorderVertex);
|
||||
int pz = y;
|
||||
switch(dir)
|
||||
{
|
||||
case 0: pz++; break;
|
||||
case 1: px++; pz++; break;
|
||||
case 2: px++; break;
|
||||
}
|
||||
int r = 0;
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = x + rcGetDirOffsetX(dir);
|
||||
const int ay = y + rcGetDirOffsetY(dir);
|
||||
const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir);
|
||||
r = (int)chf.spans[ai].reg;
|
||||
if (area != chf.areas[ai])
|
||||
isAreaBorder = true;
|
||||
}
|
||||
if (isBorderVertex)
|
||||
r |= RC_BORDER_VERTEX;
|
||||
if (isAreaBorder)
|
||||
r |= RC_AREA_BORDER;
|
||||
points.push(px);
|
||||
points.push(py);
|
||||
points.push(pz);
|
||||
points.push(r);
|
||||
|
||||
flags[i] &= ~(1 << dir); // Remove visited edges
|
||||
dir = (dir+1) & 0x3; // Rotate CW
|
||||
}
|
||||
else
|
||||
{
|
||||
int ni = -1;
|
||||
const int nx = x + rcGetDirOffsetX(dir);
|
||||
const int ny = y + rcGetDirOffsetY(dir);
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const rcCompactCell& nc = chf.cells[nx+ny*chf.width];
|
||||
ni = (int)nc.index + rcGetCon(s, dir);
|
||||
}
|
||||
if (ni == -1)
|
||||
{
|
||||
// Should not happen.
|
||||
return;
|
||||
}
|
||||
x = nx;
|
||||
y = ny;
|
||||
i = ni;
|
||||
dir = (dir+3) & 0x3; // Rotate CCW
|
||||
}
|
||||
|
||||
if (starti == i && startDir == dir)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static float distancePtSeg(const int x, const int z,
|
||||
const int px, const int pz,
|
||||
const int qx, const int qz)
|
||||
{
|
||||
/* float pqx = (float)(qx - px);
|
||||
float pqy = (float)(qy - py);
|
||||
float pqz = (float)(qz - pz);
|
||||
float dx = (float)(x - px);
|
||||
float dy = (float)(y - py);
|
||||
float dz = (float)(z - pz);
|
||||
float d = pqx*pqx + pqy*pqy + pqz*pqz;
|
||||
float t = pqx*dx + pqy*dy + pqz*dz;
|
||||
if (d > 0)
|
||||
t /= d;
|
||||
if (t < 0)
|
||||
t = 0;
|
||||
else if (t > 1)
|
||||
t = 1;
|
||||
|
||||
dx = px + t*pqx - x;
|
||||
dy = py + t*pqy - y;
|
||||
dz = pz + t*pqz - z;
|
||||
|
||||
return dx*dx + dy*dy + dz*dz;*/
|
||||
|
||||
float pqx = (float)(qx - px);
|
||||
float pqz = (float)(qz - pz);
|
||||
float dx = (float)(x - px);
|
||||
float dz = (float)(z - pz);
|
||||
float d = pqx*pqx + pqz*pqz;
|
||||
float t = pqx*dx + pqz*dz;
|
||||
if (d > 0)
|
||||
t /= d;
|
||||
if (t < 0)
|
||||
t = 0;
|
||||
else if (t > 1)
|
||||
t = 1;
|
||||
|
||||
dx = px + t*pqx - x;
|
||||
dz = pz + t*pqz - z;
|
||||
|
||||
return dx*dx + dz*dz;
|
||||
}
|
||||
|
||||
static void simplifyContour(rcIntArray& points, rcIntArray& simplified,
|
||||
const float maxError, const int maxEdgeLen, const int buildFlags)
|
||||
{
|
||||
// Add initial points.
|
||||
bool hasConnections = false;
|
||||
for (int i = 0; i < points.size(); i += 4)
|
||||
{
|
||||
if ((points[i+3] & RC_CONTOUR_REG_MASK) != 0)
|
||||
{
|
||||
hasConnections = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasConnections)
|
||||
{
|
||||
// The contour has some portals to other regions.
|
||||
// Add a new point to every location where the region changes.
|
||||
for (int i = 0, ni = points.size()/4; i < ni; ++i)
|
||||
{
|
||||
int ii = (i+1) % ni;
|
||||
const bool differentRegs = (points[i*4+3] & RC_CONTOUR_REG_MASK) != (points[ii*4+3] & RC_CONTOUR_REG_MASK);
|
||||
const bool areaBorders = (points[i*4+3] & RC_AREA_BORDER) != (points[ii*4+3] & RC_AREA_BORDER);
|
||||
if (differentRegs || areaBorders)
|
||||
{
|
||||
simplified.push(points[i*4+0]);
|
||||
simplified.push(points[i*4+1]);
|
||||
simplified.push(points[i*4+2]);
|
||||
simplified.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (simplified.size() == 0)
|
||||
{
|
||||
// If there is no connections at all,
|
||||
// create some initial points for the simplification process.
|
||||
// Find lower-left and upper-right vertices of the contour.
|
||||
int llx = points[0];
|
||||
int lly = points[1];
|
||||
int llz = points[2];
|
||||
int lli = 0;
|
||||
int urx = points[0];
|
||||
int ury = points[1];
|
||||
int urz = points[2];
|
||||
int uri = 0;
|
||||
for (int i = 0; i < points.size(); i += 4)
|
||||
{
|
||||
int x = points[i+0];
|
||||
int y = points[i+1];
|
||||
int z = points[i+2];
|
||||
if (x < llx || (x == llx && z < llz))
|
||||
{
|
||||
llx = x;
|
||||
lly = y;
|
||||
llz = z;
|
||||
lli = i/4;
|
||||
}
|
||||
if (x > urx || (x == urx && z > urz))
|
||||
{
|
||||
urx = x;
|
||||
ury = y;
|
||||
urz = z;
|
||||
uri = i/4;
|
||||
}
|
||||
}
|
||||
simplified.push(llx);
|
||||
simplified.push(lly);
|
||||
simplified.push(llz);
|
||||
simplified.push(lli);
|
||||
|
||||
simplified.push(urx);
|
||||
simplified.push(ury);
|
||||
simplified.push(urz);
|
||||
simplified.push(uri);
|
||||
}
|
||||
|
||||
// Add points until all raw points are within
|
||||
// error tolerance to the simplified shape.
|
||||
const int pn = points.size()/4;
|
||||
for (int i = 0; i < simplified.size()/4; )
|
||||
{
|
||||
int ii = (i+1) % (simplified.size()/4);
|
||||
|
||||
const int ax = simplified[i*4+0];
|
||||
const int az = simplified[i*4+2];
|
||||
const int ai = simplified[i*4+3];
|
||||
|
||||
const int bx = simplified[ii*4+0];
|
||||
const int bz = simplified[ii*4+2];
|
||||
const int bi = simplified[ii*4+3];
|
||||
|
||||
// Find maximum deviation from the segment.
|
||||
float maxd = 0;
|
||||
int maxi = -1;
|
||||
int ci, cinc, endi;
|
||||
|
||||
// Traverse the segment in lexilogical order so that the
|
||||
// max deviation is calculated similarly when traversing
|
||||
// opposite segments.
|
||||
if (bx > ax || (bx == ax && bz > az))
|
||||
{
|
||||
cinc = 1;
|
||||
ci = (ai+cinc) % pn;
|
||||
endi = bi;
|
||||
}
|
||||
else
|
||||
{
|
||||
cinc = pn-1;
|
||||
ci = (bi+cinc) % pn;
|
||||
endi = ai;
|
||||
}
|
||||
|
||||
// Tessellate only outer edges oredges between areas.
|
||||
if ((points[ci*4+3] & RC_CONTOUR_REG_MASK) == 0 ||
|
||||
(points[ci*4+3] & RC_AREA_BORDER))
|
||||
{
|
||||
while (ci != endi)
|
||||
{
|
||||
float d = distancePtSeg(points[ci*4+0], points[ci*4+2], ax, az, bx, bz);
|
||||
if (d > maxd)
|
||||
{
|
||||
maxd = d;
|
||||
maxi = ci;
|
||||
}
|
||||
ci = (ci+cinc) % pn;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If the max deviation is larger than accepted error,
|
||||
// add new point, else continue to next segment.
|
||||
if (maxi != -1 && maxd > (maxError*maxError))
|
||||
{
|
||||
// Add space for the new point.
|
||||
simplified.resize(simplified.size()+4);
|
||||
const int n = simplified.size()/4;
|
||||
for (int j = n-1; j > i; --j)
|
||||
{
|
||||
simplified[j*4+0] = simplified[(j-1)*4+0];
|
||||
simplified[j*4+1] = simplified[(j-1)*4+1];
|
||||
simplified[j*4+2] = simplified[(j-1)*4+2];
|
||||
simplified[j*4+3] = simplified[(j-1)*4+3];
|
||||
}
|
||||
// Add the point.
|
||||
simplified[(i+1)*4+0] = points[maxi*4+0];
|
||||
simplified[(i+1)*4+1] = points[maxi*4+1];
|
||||
simplified[(i+1)*4+2] = points[maxi*4+2];
|
||||
simplified[(i+1)*4+3] = maxi;
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
// Split too long edges.
|
||||
if (maxEdgeLen > 0 && (buildFlags & (RC_CONTOUR_TESS_WALL_EDGES|RC_CONTOUR_TESS_AREA_EDGES)) != 0)
|
||||
{
|
||||
for (int i = 0; i < simplified.size()/4; )
|
||||
{
|
||||
const int ii = (i+1) % (simplified.size()/4);
|
||||
|
||||
const int ax = simplified[i*4+0];
|
||||
const int az = simplified[i*4+2];
|
||||
const int ai = simplified[i*4+3];
|
||||
|
||||
const int bx = simplified[ii*4+0];
|
||||
const int bz = simplified[ii*4+2];
|
||||
const int bi = simplified[ii*4+3];
|
||||
|
||||
// Find maximum deviation from the segment.
|
||||
int maxi = -1;
|
||||
int ci = (ai+1) % pn;
|
||||
|
||||
// Tessellate only outer edges or edges between areas.
|
||||
bool tess = false;
|
||||
// Wall edges.
|
||||
if ((buildFlags & RC_CONTOUR_TESS_WALL_EDGES) && (points[ci*4+3] & RC_CONTOUR_REG_MASK) == 0)
|
||||
tess = true;
|
||||
// Edges between areas.
|
||||
if ((buildFlags & RC_CONTOUR_TESS_AREA_EDGES) && (points[ci*4+3] & RC_AREA_BORDER))
|
||||
tess = true;
|
||||
|
||||
if (tess)
|
||||
{
|
||||
int dx = bx - ax;
|
||||
int dz = bz - az;
|
||||
if (dx*dx + dz*dz > maxEdgeLen*maxEdgeLen)
|
||||
{
|
||||
// Round based on the segments in lexilogical order so that the
|
||||
// max tesselation is consistent regardles in which direction
|
||||
// segments are traversed.
|
||||
if (bx > ax || (bx == ax && bz > az))
|
||||
{
|
||||
const int n = bi < ai ? (bi+pn - ai) : (bi - ai);
|
||||
maxi = (ai + n/2) % pn;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int n = bi < ai ? (bi+pn - ai) : (bi - ai);
|
||||
maxi = (ai + (n+1)/2) % pn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the max deviation is larger than accepted error,
|
||||
// add new point, else continue to next segment.
|
||||
if (maxi != -1)
|
||||
{
|
||||
// Add space for the new point.
|
||||
simplified.resize(simplified.size()+4);
|
||||
const int n = simplified.size()/4;
|
||||
for (int j = n-1; j > i; --j)
|
||||
{
|
||||
simplified[j*4+0] = simplified[(j-1)*4+0];
|
||||
simplified[j*4+1] = simplified[(j-1)*4+1];
|
||||
simplified[j*4+2] = simplified[(j-1)*4+2];
|
||||
simplified[j*4+3] = simplified[(j-1)*4+3];
|
||||
}
|
||||
// Add the point.
|
||||
simplified[(i+1)*4+0] = points[maxi*4+0];
|
||||
simplified[(i+1)*4+1] = points[maxi*4+1];
|
||||
simplified[(i+1)*4+2] = points[maxi*4+2];
|
||||
simplified[(i+1)*4+3] = maxi;
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < simplified.size()/4; ++i)
|
||||
{
|
||||
// The edge vertex flag is take from the current raw point,
|
||||
// and the neighbour region is take from the next raw point.
|
||||
const int ai = (simplified[i*4+3]+1) % pn;
|
||||
const int bi = simplified[i*4+3];
|
||||
simplified[i*4+3] = (points[ai*4+3] & RC_CONTOUR_REG_MASK) | (points[bi*4+3] & RC_BORDER_VERTEX);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void removeDegenerateSegments(rcIntArray& simplified)
|
||||
{
|
||||
// Remove adjacent vertices which are equal on xz-plane,
|
||||
// or else the triangulator will get confused.
|
||||
for (int i = 0; i < simplified.size()/4; ++i)
|
||||
{
|
||||
int ni = i+1;
|
||||
if (ni >= (simplified.size()/4))
|
||||
ni = 0;
|
||||
|
||||
if (simplified[i*4+0] == simplified[ni*4+0] &&
|
||||
simplified[i*4+2] == simplified[ni*4+2])
|
||||
{
|
||||
// Degenerate segment, remove.
|
||||
for (int j = i; j < simplified.size()/4-1; ++j)
|
||||
{
|
||||
simplified[j*4+0] = simplified[(j+1)*4+0];
|
||||
simplified[j*4+1] = simplified[(j+1)*4+1];
|
||||
simplified[j*4+2] = simplified[(j+1)*4+2];
|
||||
simplified[j*4+3] = simplified[(j+1)*4+3];
|
||||
}
|
||||
simplified.resize(simplified.size()-4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int calcAreaOfPolygon2D(const int* verts, const int nverts)
|
||||
{
|
||||
int area = 0;
|
||||
for (int i = 0, j = nverts-1; i < nverts; j=i++)
|
||||
{
|
||||
const int* vi = &verts[i*4];
|
||||
const int* vj = &verts[j*4];
|
||||
area += vi[0] * vj[2] - vj[0] * vi[2];
|
||||
}
|
||||
return (area+1) / 2;
|
||||
}
|
||||
|
||||
inline bool ileft(const int* a, const int* b, const int* c)
|
||||
{
|
||||
return (b[0] - a[0]) * (c[2] - a[2]) - (c[0] - a[0]) * (b[2] - a[2]) <= 0;
|
||||
}
|
||||
|
||||
static void getClosestIndices(const int* vertsa, const int nvertsa,
|
||||
const int* vertsb, const int nvertsb,
|
||||
int& ia, int& ib)
|
||||
{
|
||||
int closestDist = 0xfffffff;
|
||||
ia = -1, ib = -1;
|
||||
for (int i = 0; i < nvertsa; ++i)
|
||||
{
|
||||
const int in = (i+1) % nvertsa;
|
||||
const int ip = (i+nvertsa-1) % nvertsa;
|
||||
const int* va = &vertsa[i*4];
|
||||
const int* van = &vertsa[in*4];
|
||||
const int* vap = &vertsa[ip*4];
|
||||
|
||||
for (int j = 0; j < nvertsb; ++j)
|
||||
{
|
||||
const int* vb = &vertsb[j*4];
|
||||
// vb must be "infront" of va.
|
||||
if (ileft(vap,va,vb) && ileft(va,van,vb))
|
||||
{
|
||||
const int dx = vb[0] - va[0];
|
||||
const int dz = vb[2] - va[2];
|
||||
const int d = dx*dx + dz*dz;
|
||||
if (d < closestDist)
|
||||
{
|
||||
ia = i;
|
||||
ib = j;
|
||||
closestDist = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool mergeContours(rcContour& ca, rcContour& cb, int ia, int ib)
|
||||
{
|
||||
const int maxVerts = ca.nverts + cb.nverts + 2;
|
||||
int* verts = (int*)rcAlloc(sizeof(int)*maxVerts*4, RC_ALLOC_PERM);
|
||||
if (!verts)
|
||||
return false;
|
||||
|
||||
int nv = 0;
|
||||
|
||||
// Copy contour A.
|
||||
for (int i = 0; i <= ca.nverts; ++i)
|
||||
{
|
||||
int* dst = &verts[nv*4];
|
||||
const int* src = &ca.verts[((ia+i)%ca.nverts)*4];
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = src[3];
|
||||
nv++;
|
||||
}
|
||||
|
||||
// Copy contour B
|
||||
for (int i = 0; i <= cb.nverts; ++i)
|
||||
{
|
||||
int* dst = &verts[nv*4];
|
||||
const int* src = &cb.verts[((ib+i)%cb.nverts)*4];
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = src[3];
|
||||
nv++;
|
||||
}
|
||||
|
||||
rcFree(ca.verts);
|
||||
ca.verts = verts;
|
||||
ca.nverts = nv;
|
||||
|
||||
rcFree(cb.verts);
|
||||
cb.verts = 0;
|
||||
cb.nverts = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
|
||||
const float maxError, const int maxEdgeLen,
|
||||
rcContourSet& cset, const int buildFlags)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
const int w = chf.width;
|
||||
const int h = chf.height;
|
||||
|
||||
ctx->startTimer(RC_TIMER_BUILD_CONTOURS);
|
||||
|
||||
rcVcopy(cset.bmin, chf.bmin);
|
||||
rcVcopy(cset.bmax, chf.bmax);
|
||||
cset.cs = chf.cs;
|
||||
cset.ch = chf.ch;
|
||||
|
||||
int maxContours = rcMax((int)chf.maxRegions, 8);
|
||||
cset.conts = (rcContour*)rcAlloc(sizeof(rcContour)*maxContours, RC_ALLOC_PERM);
|
||||
if (!cset.conts)
|
||||
return false;
|
||||
cset.nconts = 0;
|
||||
|
||||
rcScopedDelete<unsigned char> flags = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP);
|
||||
if (!flags)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'flags' (%d).", chf.spanCount);
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx->startTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
|
||||
|
||||
// Mark boundaries.
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
unsigned char res = 0;
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
if (!chf.spans[i].reg || (chf.spans[i].reg & RC_BORDER_REG))
|
||||
{
|
||||
flags[i] = 0;
|
||||
continue;
|
||||
}
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
unsigned short r = 0;
|
||||
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||||
{
|
||||
const int ax = x + rcGetDirOffsetX(dir);
|
||||
const int ay = y + rcGetDirOffsetY(dir);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
|
||||
r = chf.spans[ai].reg;
|
||||
}
|
||||
if (r == chf.spans[i].reg)
|
||||
res |= (1 << dir);
|
||||
}
|
||||
flags[i] = res ^ 0xf; // Inverse, mark non connected edges.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
|
||||
|
||||
ctx->startTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
|
||||
|
||||
rcIntArray verts(256);
|
||||
rcIntArray simplified(64);
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
if (flags[i] == 0 || flags[i] == 0xf)
|
||||
{
|
||||
flags[i] = 0;
|
||||
continue;
|
||||
}
|
||||
const unsigned short reg = chf.spans[i].reg;
|
||||
if (!reg || (reg & RC_BORDER_REG))
|
||||
continue;
|
||||
const unsigned char area = chf.areas[i];
|
||||
|
||||
verts.resize(0);
|
||||
simplified.resize(0);
|
||||
walkContour(x, y, i, chf, flags, verts);
|
||||
simplifyContour(verts, simplified, maxError, maxEdgeLen, buildFlags);
|
||||
removeDegenerateSegments(simplified);
|
||||
|
||||
// Store region->contour remap info.
|
||||
// Create contour.
|
||||
if (simplified.size()/4 >= 3)
|
||||
{
|
||||
if (cset.nconts >= maxContours)
|
||||
{
|
||||
// Allocate more contours.
|
||||
// This can happen when there are tiny holes in the heightfield.
|
||||
const int oldMax = maxContours;
|
||||
maxContours *= 2;
|
||||
rcContour* newConts = (rcContour*)rcAlloc(sizeof(rcContour)*maxContours, RC_ALLOC_PERM);
|
||||
for (int j = 0; j < cset.nconts; ++j)
|
||||
{
|
||||
newConts[j] = cset.conts[j];
|
||||
// Reset source pointers to prevent data deletion.
|
||||
cset.conts[j].verts = 0;
|
||||
cset.conts[j].rverts = 0;
|
||||
}
|
||||
rcFree(cset.conts);
|
||||
cset.conts = newConts;
|
||||
|
||||
ctx->log(RC_LOG_WARNING, "rcBuildContours: Expanding max contours from %d to %d.", oldMax, maxContours);
|
||||
}
|
||||
|
||||
rcContour* cont = &cset.conts[cset.nconts++];
|
||||
|
||||
cont->nverts = simplified.size()/4;
|
||||
cont->verts = (int*)rcAlloc(sizeof(int)*cont->nverts*4, RC_ALLOC_PERM);
|
||||
if (!cont->verts)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'verts' (%d).", cont->nverts);
|
||||
return false;
|
||||
}
|
||||
memcpy(cont->verts, &simplified[0], sizeof(int)*cont->nverts*4);
|
||||
|
||||
cont->nrverts = verts.size()/4;
|
||||
cont->rverts = (int*)rcAlloc(sizeof(int)*cont->nrverts*4, RC_ALLOC_PERM);
|
||||
if (!cont->rverts)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'rverts' (%d).", cont->nrverts);
|
||||
return false;
|
||||
}
|
||||
memcpy(cont->rverts, &verts[0], sizeof(int)*cont->nrverts*4);
|
||||
|
||||
/* cont->cx = cont->cy = cont->cz = 0;
|
||||
for (int i = 0; i < cont->nverts; ++i)
|
||||
{
|
||||
cont->cx += cont->verts[i*4+0];
|
||||
cont->cy += cont->verts[i*4+1];
|
||||
cont->cz += cont->verts[i*4+2];
|
||||
}
|
||||
cont->cx /= cont->nverts;
|
||||
cont->cy /= cont->nverts;
|
||||
cont->cz /= cont->nverts;*/
|
||||
|
||||
cont->reg = reg;
|
||||
cont->area = area;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check and merge droppings.
|
||||
// Sometimes the previous algorithms can fail and create several contours
|
||||
// per area. This pass will try to merge the holes into the main region.
|
||||
for (int i = 0; i < cset.nconts; ++i)
|
||||
{
|
||||
rcContour& cont = cset.conts[i];
|
||||
// Check if the contour is would backwards.
|
||||
if (calcAreaOfPolygon2D(cont.verts, cont.nverts) < 0)
|
||||
{
|
||||
// Find another contour which has the same region ID.
|
||||
int mergeIdx = -1;
|
||||
for (int j = 0; j < cset.nconts; ++j)
|
||||
{
|
||||
if (i == j) continue;
|
||||
if (cset.conts[j].nverts && cset.conts[j].reg == cont.reg)
|
||||
{
|
||||
// Make sure the polygon is correctly oriented.
|
||||
if (calcAreaOfPolygon2D(cset.conts[j].verts, cset.conts[j].nverts))
|
||||
{
|
||||
mergeIdx = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mergeIdx == -1)
|
||||
{
|
||||
ctx->log(RC_LOG_WARNING, "rcBuildContours: Could not find merge target for bad contour %d.", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
rcContour& mcont = cset.conts[mergeIdx];
|
||||
// Merge by closest points.
|
||||
int ia = 0, ib = 0;
|
||||
getClosestIndices(mcont.verts, mcont.nverts, cont.verts, cont.nverts, ia, ib);
|
||||
if (ia == -1 || ib == -1)
|
||||
{
|
||||
ctx->log(RC_LOG_WARNING, "rcBuildContours: Failed to find merge points for %d and %d.", i, mergeIdx);
|
||||
continue;
|
||||
}
|
||||
if (!mergeContours(mcont, cont, ia, ib))
|
||||
{
|
||||
ctx->log(RC_LOG_WARNING, "rcBuildContours: Failed to merge contours %d and %d.", i, mergeIdx);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
|
||||
|
||||
ctx->stopTimer(RC_TIMER_BUILD_CONTOURS);
|
||||
|
||||
return true;
|
||||
}
|
||||
179
dep/recastnavigation/Recast/RecastFilter.cpp
Normal file
179
dep/recastnavigation/Recast/RecastFilter.cpp
Normal file
@@ -0,0 +1,179 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "Recast.h"
|
||||
#include "RecastAssert.h"
|
||||
|
||||
|
||||
void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_FILTER_LOW_OBSTACLES);
|
||||
|
||||
const int w = solid.width;
|
||||
const int h = solid.height;
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
rcSpan* ps = 0;
|
||||
bool previousWalkable = false;
|
||||
|
||||
for (rcSpan* s = solid.spans[x + y*w]; s; ps = s, s = s->next)
|
||||
{
|
||||
const bool walkable = s->area != RC_NULL_AREA;
|
||||
// If current span is not walkable, but there is walkable
|
||||
// span just below it, mark the span above it walkable too.
|
||||
if (!walkable && previousWalkable)
|
||||
{
|
||||
if (rcAbs((int)s->smax - (int)ps->smax) <= walkableClimb)
|
||||
s->area = RC_NULL_AREA;
|
||||
}
|
||||
// Copy walkable flag so that it cannot propagate
|
||||
// past multiple non-walkable objects.
|
||||
previousWalkable = walkable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_FILTER_LOW_OBSTACLES);
|
||||
}
|
||||
|
||||
void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walkableClimb,
|
||||
rcHeightfield& solid)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_FILTER_BORDER);
|
||||
|
||||
const int w = solid.width;
|
||||
const int h = solid.height;
|
||||
const int MAX_HEIGHT = 0xffff;
|
||||
|
||||
// Mark border spans.
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
for (rcSpan* s = solid.spans[x + y*w]; s; s = s->next)
|
||||
{
|
||||
// Skip non walkable spans.
|
||||
if (s->area == RC_NULL_AREA)
|
||||
continue;
|
||||
|
||||
const int bot = (int)(s->smax);
|
||||
const int top = s->next ? (int)(s->next->smin) : MAX_HEIGHT;
|
||||
|
||||
// Find neighbours minimum height.
|
||||
int minh = MAX_HEIGHT;
|
||||
|
||||
// Min and max height of accessible neighbours.
|
||||
int asmin = s->smax;
|
||||
int asmax = s->smax;
|
||||
|
||||
for (int dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
int dx = x + rcGetDirOffsetX(dir);
|
||||
int dy = y + rcGetDirOffsetY(dir);
|
||||
// Skip neighbours which are out of bounds.
|
||||
if (dx < 0 || dy < 0 || dx >= w || dy >= h)
|
||||
{
|
||||
minh = rcMin(minh, -walkableClimb - bot);
|
||||
continue;
|
||||
}
|
||||
|
||||
// From minus infinity to the first span.
|
||||
rcSpan* ns = solid.spans[dx + dy*w];
|
||||
int nbot = -walkableClimb;
|
||||
int ntop = ns ? (int)ns->smin : MAX_HEIGHT;
|
||||
// Skip neightbour if the gap between the spans is too small.
|
||||
if (rcMin(top,ntop) - rcMax(bot,nbot) > walkableHeight)
|
||||
minh = rcMin(minh, nbot - bot);
|
||||
|
||||
// Rest of the spans.
|
||||
for (ns = solid.spans[dx + dy*w]; ns; ns = ns->next)
|
||||
{
|
||||
nbot = (int)ns->smax;
|
||||
ntop = ns->next ? (int)ns->next->smin : MAX_HEIGHT;
|
||||
// Skip neightbour if the gap between the spans is too small.
|
||||
if (rcMin(top,ntop) - rcMax(bot,nbot) > walkableHeight)
|
||||
{
|
||||
minh = rcMin(minh, nbot - bot);
|
||||
|
||||
// Find min/max accessible neighbour height.
|
||||
if (rcAbs(nbot - bot) <= walkableClimb)
|
||||
{
|
||||
if (nbot < asmin) asmin = nbot;
|
||||
if (nbot > asmax) asmax = nbot;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The current span is close to a ledge if the drop to any
|
||||
// neighbour span is less than the walkableClimb.
|
||||
if (minh < -walkableClimb)
|
||||
s->area = RC_NULL_AREA;
|
||||
|
||||
// If the difference between all neighbours is too large,
|
||||
// we are at steep slope, mark the span as ledge.
|
||||
if ((asmax - asmin) > walkableClimb)
|
||||
{
|
||||
s->area = RC_NULL_AREA;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_FILTER_BORDER);
|
||||
}
|
||||
|
||||
void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_FILTER_WALKABLE);
|
||||
|
||||
const int w = solid.width;
|
||||
const int h = solid.height;
|
||||
const int MAX_HEIGHT = 0xffff;
|
||||
|
||||
// Remove walkable flag from spans which do not have enough
|
||||
// space above them for the agent to stand there.
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
for (rcSpan* s = solid.spans[x + y*w]; s; s = s->next)
|
||||
{
|
||||
const int bot = (int)(s->smax);
|
||||
const int top = s->next ? (int)(s->next->smin) : MAX_HEIGHT;
|
||||
if ((top - bot) <= walkableHeight)
|
||||
s->area = RC_NULL_AREA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_FILTER_WALKABLE);
|
||||
}
|
||||
1322
dep/recastnavigation/Recast/RecastMesh.cpp
Normal file
1322
dep/recastnavigation/Recast/RecastMesh.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1237
dep/recastnavigation/Recast/RecastMeshDetail.cpp
Normal file
1237
dep/recastnavigation/Recast/RecastMeshDetail.cpp
Normal file
File diff suppressed because it is too large
Load Diff
360
dep/recastnavigation/Recast/RecastRasterization.cpp
Normal file
360
dep/recastnavigation/Recast/RecastRasterization.cpp
Normal file
@@ -0,0 +1,360 @@
|
||||
//
|
||||
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "Recast.h"
|
||||
#include "RecastAlloc.h"
|
||||
#include "RecastAssert.h"
|
||||
|
||||
inline bool overlapBounds(const float* amin, const float* amax, const float* bmin, const float* bmax)
|
||||
{
|
||||
bool overlap = true;
|
||||
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
|
||||
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
|
||||
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
|
||||
return overlap;
|
||||
}
|
||||
|
||||
inline bool overlapInterval(unsigned short amin, unsigned short amax,
|
||||
unsigned short bmin, unsigned short bmax)
|
||||
{
|
||||
if (amax < bmin) return false;
|
||||
if (amin > bmax) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static rcSpan* allocSpan(rcHeightfield& hf)
|
||||
{
|
||||
// If running out of memory, allocate new page and update the freelist.
|
||||
if (!hf.freelist || !hf.freelist->next)
|
||||
{
|
||||
// Create new page.
|
||||
// Allocate memory for the new pool.
|
||||
rcSpanPool* pool = (rcSpanPool*)rcAlloc(sizeof(rcSpanPool), RC_ALLOC_PERM);
|
||||
if (!pool) return 0;
|
||||
pool->next = 0;
|
||||
// Add the pool into the list of pools.
|
||||
pool->next = hf.pools;
|
||||
hf.pools = pool;
|
||||
// Add new items to the free list.
|
||||
rcSpan* freelist = hf.freelist;
|
||||
rcSpan* head = &pool->items[0];
|
||||
rcSpan* it = &pool->items[RC_SPANS_PER_POOL];
|
||||
do
|
||||
{
|
||||
--it;
|
||||
it->next = freelist;
|
||||
freelist = it;
|
||||
}
|
||||
while (it != head);
|
||||
hf.freelist = it;
|
||||
}
|
||||
|
||||
// Pop item from in front of the free list.
|
||||
rcSpan* it = hf.freelist;
|
||||
hf.freelist = hf.freelist->next;
|
||||
return it;
|
||||
}
|
||||
|
||||
static void freeSpan(rcHeightfield& hf, rcSpan* ptr)
|
||||
{
|
||||
if (!ptr) return;
|
||||
// Add the node in front of the free list.
|
||||
ptr->next = hf.freelist;
|
||||
hf.freelist = ptr;
|
||||
}
|
||||
|
||||
static void addSpan(rcHeightfield& hf, const int x, const int y,
|
||||
const unsigned short smin, const unsigned short smax,
|
||||
const unsigned char area, const int flagMergeThr)
|
||||
{
|
||||
|
||||
int idx = x + y*hf.width;
|
||||
|
||||
rcSpan* s = allocSpan(hf);
|
||||
s->smin = smin;
|
||||
s->smax = smax;
|
||||
s->area = area;
|
||||
s->next = 0;
|
||||
|
||||
// Empty cell, add he first span.
|
||||
if (!hf.spans[idx])
|
||||
{
|
||||
hf.spans[idx] = s;
|
||||
return;
|
||||
}
|
||||
rcSpan* prev = 0;
|
||||
rcSpan* cur = hf.spans[idx];
|
||||
|
||||
// Insert and merge spans.
|
||||
while (cur)
|
||||
{
|
||||
if (cur->smin > s->smax)
|
||||
{
|
||||
// Current span is further than the new span, break.
|
||||
break;
|
||||
}
|
||||
else if (cur->smax < s->smin)
|
||||
{
|
||||
// Current span is before the new span advance.
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Merge spans.
|
||||
if (cur->smin < s->smin)
|
||||
s->smin = cur->smin;
|
||||
if (cur->smax > s->smax)
|
||||
s->smax = cur->smax;
|
||||
|
||||
// Merge flags.
|
||||
if (rcAbs((int)s->smax - (int)cur->smax) <= flagMergeThr)
|
||||
s->area = rcMax(s->area, cur->area);
|
||||
|
||||
// Remove current span.
|
||||
rcSpan* next = cur->next;
|
||||
freeSpan(hf, cur);
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
else
|
||||
hf.spans[idx] = next;
|
||||
cur = next;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert new span.
|
||||
if (prev)
|
||||
{
|
||||
s->next = prev->next;
|
||||
prev->next = s;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->next = hf.spans[idx];
|
||||
hf.spans[idx] = s;
|
||||
}
|
||||
}
|
||||
|
||||
void rcAddSpan(rcContext* /*ctx*/, rcHeightfield& hf, const int x, const int y,
|
||||
const unsigned short smin, const unsigned short smax,
|
||||
const unsigned char area, const int flagMergeThr)
|
||||
{
|
||||
// rcAssert(ctx);
|
||||
addSpan(hf, x,y, smin, smax, area, flagMergeThr);
|
||||
}
|
||||
|
||||
static int clipPoly(const float* in, int n, float* out, float pnx, float pnz, float pd)
|
||||
{
|
||||
float d[12];
|
||||
for (int i = 0; i < n; ++i)
|
||||
d[i] = pnx*in[i*3+0] + pnz*in[i*3+2] + pd;
|
||||
|
||||
int m = 0;
|
||||
for (int i = 0, j = n-1; i < n; j=i, ++i)
|
||||
{
|
||||
bool ina = d[j] >= 0;
|
||||
bool inb = d[i] >= 0;
|
||||
if (ina != inb)
|
||||
{
|
||||
float s = d[j] / (d[j] - d[i]);
|
||||
out[m*3+0] = in[j*3+0] + (in[i*3+0] - in[j*3+0])*s;
|
||||
out[m*3+1] = in[j*3+1] + (in[i*3+1] - in[j*3+1])*s;
|
||||
out[m*3+2] = in[j*3+2] + (in[i*3+2] - in[j*3+2])*s;
|
||||
m++;
|
||||
}
|
||||
if (inb)
|
||||
{
|
||||
out[m*3+0] = in[i*3+0];
|
||||
out[m*3+1] = in[i*3+1];
|
||||
out[m*3+2] = in[i*3+2];
|
||||
m++;
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static void rasterizeTri(const float* v0, const float* v1, const float* v2,
|
||||
const unsigned char area, rcHeightfield& hf,
|
||||
const float* bmin, const float* bmax,
|
||||
const float cs, const float ics, const float ich,
|
||||
const int flagMergeThr)
|
||||
{
|
||||
const int w = hf.width;
|
||||
const int h = hf.height;
|
||||
float tmin[3], tmax[3];
|
||||
const float by = bmax[1] - bmin[1];
|
||||
|
||||
// Calculate the bounding box of the triangle.
|
||||
rcVcopy(tmin, v0);
|
||||
rcVcopy(tmax, v0);
|
||||
rcVmin(tmin, v1);
|
||||
rcVmin(tmin, v2);
|
||||
rcVmax(tmax, v1);
|
||||
rcVmax(tmax, v2);
|
||||
|
||||
// If the triangle does not touch the bbox of the heightfield, skip the triagle.
|
||||
if (!overlapBounds(bmin, bmax, tmin, tmax))
|
||||
return;
|
||||
|
||||
// Calculate the footpring of the triangle on the grid.
|
||||
int x0 = (int)((tmin[0] - bmin[0])*ics);
|
||||
int y0 = (int)((tmin[2] - bmin[2])*ics);
|
||||
int x1 = (int)((tmax[0] - bmin[0])*ics);
|
||||
int y1 = (int)((tmax[2] - bmin[2])*ics);
|
||||
x0 = rcClamp(x0, 0, w-1);
|
||||
y0 = rcClamp(y0, 0, h-1);
|
||||
x1 = rcClamp(x1, 0, w-1);
|
||||
y1 = rcClamp(y1, 0, h-1);
|
||||
|
||||
// Clip the triangle into all grid cells it touches.
|
||||
float in[7*3], out[7*3], inrow[7*3];
|
||||
|
||||
for (int y = y0; y <= y1; ++y)
|
||||
{
|
||||
// Clip polygon to row.
|
||||
rcVcopy(&in[0], v0);
|
||||
rcVcopy(&in[1*3], v1);
|
||||
rcVcopy(&in[2*3], v2);
|
||||
int nvrow = 3;
|
||||
const float cz = bmin[2] + y*cs;
|
||||
nvrow = clipPoly(in, nvrow, out, 0, 1, -cz);
|
||||
if (nvrow < 3) continue;
|
||||
nvrow = clipPoly(out, nvrow, inrow, 0, -1, cz+cs);
|
||||
if (nvrow < 3) continue;
|
||||
|
||||
for (int x = x0; x <= x1; ++x)
|
||||
{
|
||||
// Clip polygon to column.
|
||||
int nv = nvrow;
|
||||
const float cx = bmin[0] + x*cs;
|
||||
nv = clipPoly(inrow, nv, out, 1, 0, -cx);
|
||||
if (nv < 3) continue;
|
||||
nv = clipPoly(out, nv, in, -1, 0, cx+cs);
|
||||
if (nv < 3) continue;
|
||||
|
||||
// Calculate min and max of the span.
|
||||
float smin = in[1], smax = in[1];
|
||||
for (int i = 1; i < nv; ++i)
|
||||
{
|
||||
smin = rcMin(smin, in[i*3+1]);
|
||||
smax = rcMax(smax, in[i*3+1]);
|
||||
}
|
||||
smin -= bmin[1];
|
||||
smax -= bmin[1];
|
||||
// Skip the span if it is outside the heightfield bbox
|
||||
if (smax < 0.0f) continue;
|
||||
if (smin > by) continue;
|
||||
// Clamp the span to the heightfield bbox.
|
||||
if (smin < 0.0f) smin = 0;
|
||||
if (smax > by) smax = by;
|
||||
|
||||
// Snap the span to the heightfield height grid.
|
||||
unsigned short ismin = (unsigned short)rcClamp((int)floorf(smin * ich), 0, RC_SPAN_MAX_HEIGHT);
|
||||
unsigned short ismax = (unsigned short)rcClamp((int)ceilf(smax * ich), (int)ismin+1, RC_SPAN_MAX_HEIGHT);
|
||||
|
||||
addSpan(hf, x, y, ismin, ismax, area, flagMergeThr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2,
|
||||
const unsigned char area, rcHeightfield& solid,
|
||||
const int flagMergeThr)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
|
||||
const float ics = 1.0f/solid.cs;
|
||||
const float ich = 1.0f/solid.ch;
|
||||
rasterizeTri(v0, v1, v2, area, solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr);
|
||||
|
||||
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
}
|
||||
|
||||
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
|
||||
const int* tris, const unsigned char* areas, const int nt,
|
||||
rcHeightfield& solid, const int flagMergeThr)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
|
||||
const float ics = 1.0f/solid.cs;
|
||||
const float ich = 1.0f/solid.ch;
|
||||
// Rasterize triangles.
|
||||
for (int i = 0; i < nt; ++i)
|
||||
{
|
||||
const float* v0 = &verts[tris[i*3+0]*3];
|
||||
const float* v1 = &verts[tris[i*3+1]*3];
|
||||
const float* v2 = &verts[tris[i*3+2]*3];
|
||||
// Rasterize.
|
||||
rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr);
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
}
|
||||
|
||||
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
|
||||
const unsigned short* tris, const unsigned char* areas, const int nt,
|
||||
rcHeightfield& solid, const int flagMergeThr)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
|
||||
const float ics = 1.0f/solid.cs;
|
||||
const float ich = 1.0f/solid.ch;
|
||||
// Rasterize triangles.
|
||||
for (int i = 0; i < nt; ++i)
|
||||
{
|
||||
const float* v0 = &verts[tris[i*3+0]*3];
|
||||
const float* v1 = &verts[tris[i*3+1]*3];
|
||||
const float* v2 = &verts[tris[i*3+2]*3];
|
||||
// Rasterize.
|
||||
rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr);
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
}
|
||||
|
||||
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt,
|
||||
rcHeightfield& solid, const int flagMergeThr)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
|
||||
ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
|
||||
const float ics = 1.0f/solid.cs;
|
||||
const float ich = 1.0f/solid.ch;
|
||||
// Rasterize triangles.
|
||||
for (int i = 0; i < nt; ++i)
|
||||
{
|
||||
const float* v0 = &verts[(i*3+0)*3];
|
||||
const float* v1 = &verts[(i*3+1)*3];
|
||||
const float* v2 = &verts[(i*3+2)*3];
|
||||
// Rasterize.
|
||||
rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr);
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||||
}
|
||||
1283
dep/recastnavigation/Recast/RecastRegion.cpp
Normal file
1283
dep/recastnavigation/Recast/RecastRegion.cpp
Normal file
File diff suppressed because it is too large
Load Diff
20
dep/recastnavigation/TODO.txt
Normal file
20
dep/recastnavigation/TODO.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
TODO/Roadmap
|
||||
|
||||
Summer/Autumn 2009
|
||||
|
||||
- Off mesh links (jump links)
|
||||
- Area annotations
|
||||
- Embed extra data per polygon
|
||||
- Height conforming navmesh
|
||||
|
||||
|
||||
Autumn/Winter 2009/2010
|
||||
|
||||
- Detour path following
|
||||
- More dynamic example with tile navmesh
|
||||
- Faster small tile process
|
||||
|
||||
|
||||
More info at http://digestingduck.blogspot.com/2009/07/recast-and-detour-roadmap.html
|
||||
|
||||
-
|
||||
@@ -1,8 +1,8 @@
|
||||
-- MySQL dump 10.13 Distrib 5.5.21, for Win64 (x86)
|
||||
-- MySQL dump 10.13 Distrib 5.6.9-rc, for Win64 (x86_64)
|
||||
--
|
||||
-- Host: localhost Database: auth_4x
|
||||
-- ------------------------------------------------------
|
||||
-- Server version 5.5.21
|
||||
-- Server version 5.6.9-rc
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
@@ -38,6 +38,8 @@ CREATE TABLE `account` (
|
||||
`online` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`expansion` tinyint(3) unsigned NOT NULL DEFAULT '3',
|
||||
`mutetime` bigint(20) NOT NULL DEFAULT '0',
|
||||
`mutereason` varchar(255) NOT NULL DEFAULT '',
|
||||
`muteby` varchar(50) NOT NULL DEFAULT '',
|
||||
`locale` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`os` varchar(3) NOT NULL DEFAULT '',
|
||||
`recruiter` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
@@ -157,6 +159,241 @@ LOCK TABLES `logs` WRITE;
|
||||
/*!40000 ALTER TABLE `logs` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rbac_account_groups`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `rbac_account_groups`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `rbac_account_groups` (
|
||||
`accountId` int(10) unsigned NOT NULL COMMENT 'Account id',
|
||||
`groupId` int(10) unsigned NOT NULL COMMENT 'Group id',
|
||||
`realmId` int(11) NOT NULL DEFAULT '-1' COMMENT 'Realm Id, -1 means all',
|
||||
PRIMARY KEY (`accountId`,`groupId`,`realmId`),
|
||||
KEY `fk__rbac_account_groups__rbac_groups` (`groupId`),
|
||||
CONSTRAINT `fk__rbac_account_groups__account` FOREIGN KEY (`accountId`) REFERENCES `account` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk__rbac_account_groups__rbac_groups` FOREIGN KEY (`groupId`) REFERENCES `rbac_groups` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Account-Group relation';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `rbac_account_groups`
|
||||
--
|
||||
|
||||
LOCK TABLES `rbac_account_groups` WRITE;
|
||||
/*!40000 ALTER TABLE `rbac_account_groups` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `rbac_account_groups` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rbac_account_permissions`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `rbac_account_permissions`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `rbac_account_permissions` (
|
||||
`accountId` int(10) unsigned NOT NULL COMMENT 'Account id',
|
||||
`permissionId` int(10) unsigned NOT NULL COMMENT 'Permission id',
|
||||
`granted` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Granted = 1, Denied = 0',
|
||||
`realmId` int(11) NOT NULL DEFAULT '-1' COMMENT 'Realm Id, -1 means all',
|
||||
PRIMARY KEY (`accountId`,`permissionId`,`realmId`),
|
||||
KEY `fk__rbac_account_roles__rbac_permissions` (`permissionId`),
|
||||
CONSTRAINT `fk__rbac_account_permissions__account` FOREIGN KEY (`accountId`) REFERENCES `account` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk__rbac_account_roles__rbac_permissions` FOREIGN KEY (`permissionId`) REFERENCES `rbac_permissions` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Account-Permission relation';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `rbac_account_permissions`
|
||||
--
|
||||
|
||||
LOCK TABLES `rbac_account_permissions` WRITE;
|
||||
/*!40000 ALTER TABLE `rbac_account_permissions` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `rbac_account_permissions` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rbac_account_roles`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `rbac_account_roles`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `rbac_account_roles` (
|
||||
`accountId` int(10) unsigned NOT NULL COMMENT 'Account id',
|
||||
`roleId` int(10) unsigned NOT NULL COMMENT 'Role id',
|
||||
`granted` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Granted = 1, Denied = 0',
|
||||
`realmId` int(11) NOT NULL DEFAULT '-1' COMMENT 'Realm Id, -1 means all',
|
||||
PRIMARY KEY (`accountId`,`roleId`,`realmId`),
|
||||
KEY `fk__rbac_account_roles__rbac_roles` (`roleId`),
|
||||
CONSTRAINT `fk__rbac_account_roles__account` FOREIGN KEY (`accountId`) REFERENCES `account` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk__rbac_account_roles__rbac_roles` FOREIGN KEY (`roleId`) REFERENCES `rbac_roles` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Account-Role relation';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `rbac_account_roles`
|
||||
--
|
||||
|
||||
LOCK TABLES `rbac_account_roles` WRITE;
|
||||
/*!40000 ALTER TABLE `rbac_account_roles` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `rbac_account_roles` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rbac_group_roles`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `rbac_group_roles`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `rbac_group_roles` (
|
||||
`groupId` int(10) unsigned NOT NULL COMMENT 'group id',
|
||||
`roleId` int(10) unsigned NOT NULL COMMENT 'Role id',
|
||||
PRIMARY KEY (`groupId`,`roleId`),
|
||||
KEY `fk__rbac_group_roles__rbac_roles` (`roleId`),
|
||||
CONSTRAINT `fk__rbac_group_roles__rbac_roles` FOREIGN KEY (`roleId`) REFERENCES `rbac_roles` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk__rbac_group_roles__rbac_groups` FOREIGN KEY (`groupId`) REFERENCES `rbac_groups` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Group Role relation';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `rbac_group_roles`
|
||||
--
|
||||
|
||||
LOCK TABLES `rbac_group_roles` WRITE;
|
||||
/*!40000 ALTER TABLE `rbac_group_roles` DISABLE KEYS */;
|
||||
INSERT INTO `rbac_group_roles` VALUES (1,1),(2,2),(3,3),(4,4),(2,5),(1,6),(1,7);
|
||||
/*!40000 ALTER TABLE `rbac_group_roles` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rbac_groups`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `rbac_groups`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `rbac_groups` (
|
||||
`id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Group id',
|
||||
`name` varchar(50) NOT NULL COMMENT 'Group name',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Group List';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `rbac_groups`
|
||||
--
|
||||
|
||||
LOCK TABLES `rbac_groups` WRITE;
|
||||
/*!40000 ALTER TABLE `rbac_groups` DISABLE KEYS */;
|
||||
INSERT INTO `rbac_groups` VALUES (1,'Player'),(2,'Moderator'),(3,'GameMaster'),(4,'Administrator');
|
||||
/*!40000 ALTER TABLE `rbac_groups` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rbac_permissions`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `rbac_permissions`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `rbac_permissions` (
|
||||
`id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Permission id',
|
||||
`name` varchar(100) NOT NULL COMMENT 'Permission name',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Permission List';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `rbac_permissions`
|
||||
--
|
||||
|
||||
LOCK TABLES `rbac_permissions` WRITE;
|
||||
/*!40000 ALTER TABLE `rbac_permissions` DISABLE KEYS */;
|
||||
INSERT INTO `rbac_permissions` VALUES (1,'Instant logout'),(2,'Skip Queue'),(3,'Join Normal Battleground'),(4,'Join Random Battleground'),(5,'Join Arenas'),(6,'Join Dungeon Finder'),(7,'Player Commands (Temporal till commands moved to rbac)'),(8,'Moderator Commands (Temporal till commands moved to rbac)'),(9,'GameMaster Commands (Temporal till commands moved to rbac)'),(10,'Administrator Commands (Temporal till commands moved to rbac)');
|
||||
/*!40000 ALTER TABLE `rbac_permissions` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rbac_role_permissions`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `rbac_role_permissions`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `rbac_role_permissions` (
|
||||
`roleId` int(10) unsigned NOT NULL COMMENT 'Role id',
|
||||
`permissionId` int(10) unsigned NOT NULL COMMENT 'Permission id',
|
||||
PRIMARY KEY (`roleId`,`permissionId`),
|
||||
KEY `fk__role_permissions__rbac_permissions` (`permissionId`),
|
||||
CONSTRAINT `fk__role_permissions__rbac_roles` FOREIGN KEY (`roleId`) REFERENCES `rbac_roles` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk__role_permissions__rbac_permissions` FOREIGN KEY (`permissionId`) REFERENCES `rbac_permissions` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Role Permission relation';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `rbac_role_permissions`
|
||||
--
|
||||
|
||||
LOCK TABLES `rbac_role_permissions` WRITE;
|
||||
/*!40000 ALTER TABLE `rbac_role_permissions` DISABLE KEYS */;
|
||||
INSERT INTO `rbac_role_permissions` VALUES (5,1),(5,2),(6,3),(6,4),(6,5),(7,6),(1,7),(2,8),(3,9),(4,10);
|
||||
/*!40000 ALTER TABLE `rbac_role_permissions` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rbac_roles`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `rbac_roles`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `rbac_roles` (
|
||||
`id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Role id',
|
||||
`name` varchar(50) NOT NULL COMMENT 'Role name',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Roles List';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `rbac_roles`
|
||||
--
|
||||
|
||||
LOCK TABLES `rbac_roles` WRITE;
|
||||
/*!40000 ALTER TABLE `rbac_roles` DISABLE KEYS */;
|
||||
INSERT INTO `rbac_roles` VALUES (1,'Player Commands'),(2,'Moderator Commands'),(3,'GameMaster Commands'),(4,'Administrator Commands'),(5,'Quick Login/Logout'),(6,'Use Battleground/Arenas'),(7,'Use Dungeon Finder');
|
||||
/*!40000 ALTER TABLE `rbac_roles` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rbac_security_level_groups`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `rbac_security_level_groups`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `rbac_security_level_groups` (
|
||||
`secId` int(10) unsigned NOT NULL COMMENT 'Security Level id',
|
||||
`groupId` int(10) unsigned NOT NULL COMMENT 'group id',
|
||||
PRIMARY KEY (`secId`,`groupId`),
|
||||
KEY `fk__rbac_security_level_groups__rbac_groups` (`groupId`),
|
||||
CONSTRAINT `fk__rbac_security_level_groups__rbac_groups` FOREIGN KEY (`groupId`) REFERENCES `rbac_groups` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Default groups to assign when an account is set gm level';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `rbac_security_level_groups`
|
||||
--
|
||||
|
||||
LOCK TABLES `rbac_security_level_groups` WRITE;
|
||||
/*!40000 ALTER TABLE `rbac_security_level_groups` DISABLE KEYS */;
|
||||
INSERT INTO `rbac_security_level_groups` VALUES (0,1),(1,1),(2,1),(3,1),(1,2),(2,2),(3,2),(2,3),(3,3),(3,4);
|
||||
/*!40000 ALTER TABLE `rbac_security_level_groups` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `realmcharacters`
|
||||
--
|
||||
@@ -193,6 +430,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',
|
||||
@@ -211,7 +450,7 @@ CREATE TABLE `realmlist` (
|
||||
|
||||
LOCK TABLES `realmlist` WRITE;
|
||||
/*!40000 ALTER TABLE `realmlist` DISABLE KEYS */;
|
||||
INSERT INTO `realmlist` VALUES (1,'Trinity','127.0.0.1',8085,1,0,1,0,0,15595);
|
||||
INSERT INTO `realmlist` VALUES (1,'Trinity','127.0.0.1','127.0.0.1','255.255.255.0',8085,1,0,1,0,0,15595);
|
||||
/*!40000 ALTER TABLE `realmlist` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
@@ -250,4 +489,4 @@ UNLOCK TABLES;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
-- Dump completed on 2012-08-08 19:01:34
|
||||
-- Dump completed on 2013-02-04 16:07:23
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
-- MySQL dump 10.13 Distrib 5.5.21, for Win64 (x86)
|
||||
-- MySQL dump 10.13 Distrib 5.6.9-rc, for Win64 (x86_64)
|
||||
--
|
||||
-- Host: localhost Database: characters_4x
|
||||
-- ------------------------------------------------------
|
||||
-- Server version 5.5.21
|
||||
-- Server version 5.6.9-rc
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
@@ -244,7 +244,7 @@ UNLOCK TABLES;
|
||||
DROP TABLE IF EXISTS `calendar_events`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `calendar_events` (
|
||||
CREATE TABLE `calendar_events` (
|
||||
`id` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`creator` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`title` varchar(255) NOT NULL DEFAULT '',
|
||||
@@ -258,6 +258,15 @@ CREATE TABLE IF NOT EXISTS `calendar_events` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `calendar_events`
|
||||
--
|
||||
|
||||
LOCK TABLES `calendar_events` WRITE;
|
||||
/*!40000 ALTER TABLE `calendar_events` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `calendar_events` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `calendar_invites`
|
||||
--
|
||||
@@ -265,7 +274,7 @@ CREATE TABLE IF NOT EXISTS `calendar_events` (
|
||||
DROP TABLE IF EXISTS `calendar_invites`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `calendar_invites` (
|
||||
CREATE TABLE `calendar_invites` (
|
||||
`id` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`event` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||
`invitee` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
@@ -278,6 +287,15 @@ CREATE TABLE IF NOT EXISTS `calendar_invites` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `calendar_invites`
|
||||
--
|
||||
|
||||
LOCK TABLES `calendar_invites` WRITE;
|
||||
/*!40000 ALTER TABLE `calendar_invites` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `calendar_invites` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `channels`
|
||||
--
|
||||
@@ -949,6 +967,30 @@ LOCK TABLES `character_queststatus_daily` WRITE;
|
||||
/*!40000 ALTER TABLE `character_queststatus_daily` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `character_queststatus_monthly`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `character_queststatus_monthly`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `character_queststatus_monthly` (
|
||||
`guid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier',
|
||||
`quest` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Quest Identifier',
|
||||
PRIMARY KEY (`guid`,`quest`),
|
||||
KEY `idx_guid` (`guid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `character_queststatus_monthly`
|
||||
--
|
||||
|
||||
LOCK TABLES `character_queststatus_monthly` WRITE;
|
||||
/*!40000 ALTER TABLE `character_queststatus_monthly` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `character_queststatus_monthly` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `character_queststatus_rewarded`
|
||||
--
|
||||
@@ -997,30 +1039,6 @@ LOCK TABLES `character_queststatus_seasonal` WRITE;
|
||||
/*!40000 ALTER TABLE `character_queststatus_seasonal` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `character_queststatus_monthly`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `character_queststatus_monthly`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `character_queststatus_monthly` (
|
||||
`guid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier',
|
||||
`quest` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Quest Identifier',
|
||||
PRIMARY KEY (`guid`,`quest`),
|
||||
KEY `idx_guid` (`guid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `character_queststatus_monthly`
|
||||
--
|
||||
|
||||
LOCK TABLES `character_queststatus_monthly` WRITE;
|
||||
/*!40000 ALTER TABLE `character_queststatus_monthly` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `character_queststatus_monthly` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `character_queststatus_weekly`
|
||||
--
|
||||
@@ -2009,7 +2027,7 @@ UNLOCK TABLES;
|
||||
DROP TABLE IF EXISTS `guild_member_withdraw`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `guild_member_withdraw` (
|
||||
CREATE TABLE `guild_member_withdraw` (
|
||||
`guid` int(10) unsigned NOT NULL,
|
||||
`tab0` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`tab1` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
@@ -2204,6 +2222,15 @@ CREATE TABLE `item_loot_items` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `item_loot_items`
|
||||
--
|
||||
|
||||
LOCK TABLES `item_loot_items` WRITE;
|
||||
/*!40000 ALTER TABLE `item_loot_items` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `item_loot_items` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `item_loot_money`
|
||||
--
|
||||
@@ -2217,6 +2244,15 @@ CREATE TABLE `item_loot_money` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `item_loot_money`
|
||||
--
|
||||
|
||||
LOCK TABLES `item_loot_money` WRITE;
|
||||
/*!40000 ALTER TABLE `item_loot_money` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `item_loot_money` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `item_refund_instance`
|
||||
--
|
||||
@@ -2621,4 +2657,4 @@ UNLOCK TABLES;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
-- Dump completed on 2012-09-10 11:54:51
|
||||
-- Dump completed on 2013-02-04 16:22:06
|
||||
|
||||
3
sql/updates/auth/2013_01_27_00_auth_realmlist.sql
Normal file
3
sql/updates/auth/2013_01_27_00_auth_realmlist.sql
Normal file
@@ -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`;
|
||||
179
sql/updates/auth/2013_02_04_00_auth_misc.sql
Normal file
179
sql/updates/auth/2013_02_04_00_auth_misc.sql
Normal file
@@ -0,0 +1,179 @@
|
||||
-- Explicitly set the account-table to use INNODB-engine (to allow foreign keys and transactions)
|
||||
ALTER TABLE account ENGINE=InnoDB;
|
||||
|
||||
-- Delete bad data from the DB before adding foreign keys
|
||||
DELETE FROM `account_access` WHERE `id` NOT IN (SELECT `id` FROM `account`);
|
||||
|
||||
-- Need them first in case of re-execute due to foreign keys
|
||||
DROP TABLE IF EXISTS `rbac_account_permissions`;
|
||||
DROP TABLE IF EXISTS `rbac_account_roles`;
|
||||
DROP TABLE IF EXISTS `rbac_account_groups`;
|
||||
DROP TABLE IF EXISTS `rbac_role_permissions`;
|
||||
DROP TABLE IF EXISTS `rbac_group_roles`;
|
||||
DROP TABLE IF EXISTS `rbac_security_level_groups`;
|
||||
DROP TABLE IF EXISTS `rbac_permissions`;
|
||||
DROP TABLE IF EXISTS `rbac_roles`;
|
||||
DROP TABLE IF EXISTS `rbac_groups`;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `rbac_groups` (
|
||||
`id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Group id',
|
||||
`name` varchar(50) NOT NULL COMMENT 'Group name',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Group List';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `rbac_roles` (
|
||||
`id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Role id',
|
||||
`name` varchar(50) NOT NULL COMMENT 'Role name',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Roles List';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `rbac_permissions` (
|
||||
`id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Permission id',
|
||||
`name` varchar(100) NOT NULL COMMENT 'Permission name',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Permission List';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `rbac_group_roles` (
|
||||
`groupId` int(10) unsigned NOT NULL COMMENT 'group id',
|
||||
`roleId` int(10) unsigned NOT NULL COMMENT 'Role id',
|
||||
PRIMARY KEY (`groupId`, `roleId`),
|
||||
CONSTRAINT `fk__rbac_group_roles__rbac_roles`
|
||||
FOREIGN KEY (`roleId`) REFERENCES `rbac_roles`(`id`)
|
||||
ON DELETE CASCADE ON UPDATE RESTRICT,
|
||||
CONSTRAINT `fk__rbac_group_roles__rbac_groups`
|
||||
FOREIGN KEY (`groupId`) REFERENCES `rbac_groups`(`id`)
|
||||
ON DELETE CASCADE ON UPDATE RESTRICT
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Group Role relation';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `rbac_role_permissions` (
|
||||
`roleId` int(10) unsigned NOT NULL COMMENT 'Role id',
|
||||
`permissionId` int(10) unsigned NOT NULL COMMENT 'Permission id',
|
||||
PRIMARY KEY (`roleId`, `permissionId`),
|
||||
CONSTRAINT `fk__role_permissions__rbac_roles`
|
||||
FOREIGN KEY (`roleId`) REFERENCES `rbac_roles`(`id`)
|
||||
ON DELETE CASCADE ON UPDATE RESTRICT,
|
||||
CONSTRAINT `fk__role_permissions__rbac_permissions`
|
||||
FOREIGN KEY (`permissionId`) REFERENCES `rbac_permissions`(`id`)
|
||||
ON DELETE CASCADE ON UPDATE RESTRICT
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Role Permission relation';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `rbac_security_level_groups` (
|
||||
`secId` int(10) unsigned NOT NULL COMMENT 'Security Level id',
|
||||
`groupId` int(10) unsigned NOT NULL COMMENT 'group id',
|
||||
PRIMARY KEY (`secId`, `groupId`),
|
||||
CONSTRAINT `fk__rbac_security_level_groups__rbac_groups`
|
||||
FOREIGN KEY (`groupId`) REFERENCES `rbac_groups`(`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Default groups to assign when an account is set gm level';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `rbac_account_groups` (
|
||||
`accountId` int(10) unsigned NOT NULL COMMENT 'Account id',
|
||||
`groupId` int(10) unsigned NOT NULL COMMENT 'Group id',
|
||||
`realmId` int(11) NOT NULL DEFAULT '-1' COMMENT 'Realm Id, -1 means all',
|
||||
PRIMARY KEY (`accountId`, `groupId`, `realmId`),
|
||||
CONSTRAINT `fk__rbac_account_groups__account`
|
||||
FOREIGN KEY (`accountId`) REFERENCES `account`(`id`)
|
||||
ON DELETE CASCADE ON UPDATE RESTRICT,
|
||||
CONSTRAINT `fk__rbac_account_groups__rbac_groups`
|
||||
FOREIGN KEY (`groupId`) REFERENCES `rbac_groups`(`id`)
|
||||
ON DELETE CASCADE ON UPDATE RESTRICT
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Account-Group relation';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `rbac_account_roles` (
|
||||
`accountId` int(10) unsigned NOT NULL COMMENT 'Account id',
|
||||
`roleId` int(10) unsigned NOT NULL COMMENT 'Role id',
|
||||
`granted` tinyint(1) NOT NULL default 1 COMMENT 'Granted = 1, Denied = 0',
|
||||
`realmId` int(11) NOT NULL DEFAULT '-1' COMMENT 'Realm Id, -1 means all',
|
||||
PRIMARY KEY (`accountId`, `roleId`, `realmId`),
|
||||
CONSTRAINT `fk__rbac_account_roles__account`
|
||||
FOREIGN KEY (`accountId`) REFERENCES `account`(`id`)
|
||||
ON DELETE CASCADE ON UPDATE RESTRICT,
|
||||
CONSTRAINT `fk__rbac_account_roles__rbac_roles`
|
||||
FOREIGN KEY (`roleId`) REFERENCES `rbac_roles`(`id`)
|
||||
ON DELETE CASCADE ON UPDATE RESTRICT
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Account-Role relation';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `rbac_account_permissions` (
|
||||
`accountId` int(10) unsigned NOT NULL COMMENT 'Account id',
|
||||
`permissionId` int(10) unsigned NOT NULL COMMENT 'Permission id',
|
||||
`granted` tinyint(1) NOT NULL default 1 COMMENT 'Granted = 1, Denied = 0',
|
||||
`realmId` int(11) NOT NULL DEFAULT '-1' COMMENT 'Realm Id, -1 means all',
|
||||
PRIMARY KEY (`accountId`, `permissionId`, `realmId`),
|
||||
CONSTRAINT `fk__rbac_account_permissions__account`
|
||||
FOREIGN KEY (`accountId`) REFERENCES `account`(`id`)
|
||||
ON DELETE CASCADE ON UPDATE RESTRICT,
|
||||
CONSTRAINT `fk__rbac_account_roles__rbac_permissions`
|
||||
FOREIGN KEY (`permissionId`) REFERENCES `rbac_permissions`(`id`)
|
||||
ON DELETE CASCADE ON UPDATE RESTRICT
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Account-Permission relation';
|
||||
|
||||
DELETE FROM `rbac_permissions` WHERE `id` BETWEEN 1 AND 10;
|
||||
INSERT INTO `rbac_permissions` (`id`, `name`) VALUES
|
||||
(1, 'Instant logout'),
|
||||
(2, 'Skip Queue'),
|
||||
(3, 'Join Normal Battleground'),
|
||||
(4, 'Join Random Battleground'),
|
||||
(5, 'Join Arenas'),
|
||||
(6, 'Join Dungeon Finder'),
|
||||
(7, 'Player Commands (Temporal till commands moved to rbac)'),
|
||||
(8, 'Moderator Commands (Temporal till commands moved to rbac)'),
|
||||
(9, 'GameMaster Commands (Temporal till commands moved to rbac)'),
|
||||
(10, 'Administrator Commands (Temporal till commands moved to rbac)');
|
||||
|
||||
DELETE FROM `rbac_roles` WHERE `id` BETWEEN 1 AND 7;
|
||||
INSERT INTO `rbac_roles` (`id`, `name`) VALUES
|
||||
(1, 'Player Commands'),
|
||||
(2, 'Moderator Commands'),
|
||||
(3, 'GameMaster Commands'),
|
||||
(4, 'Administrator Commands'),
|
||||
(5, 'Quick Login/Logout'),
|
||||
(6, 'Use Battleground/Arenas'),
|
||||
(7, 'Use Dungeon Finder');
|
||||
|
||||
DELETE FROM `rbac_groups` WHERE `id` BETWEEN 1 AND 4;
|
||||
INSERT INTO `rbac_groups` (`id`, `name`) VALUES
|
||||
(1, 'Player'),
|
||||
(2, 'Moderator'),
|
||||
(3, 'GameMaster'),
|
||||
(4, 'Administrator');
|
||||
|
||||
DELETE FROM `rbac_role_permissions` WHERE `roleId` BETWEEN 1 AND 7;
|
||||
INSERT INTO `rbac_role_permissions` (`roleId`, `permissionId`) VALUES
|
||||
(5, 1),
|
||||
(5, 2),
|
||||
(6, 3),
|
||||
(6, 4),
|
||||
(6, 5),
|
||||
(7, 6),
|
||||
(1, 7),
|
||||
(2, 8),
|
||||
(3, 9),
|
||||
(4, 10);
|
||||
|
||||
DELETE FROM `rbac_group_roles` WHERE `groupId` BETWEEN 1 AND 4;
|
||||
INSERT INTO `rbac_group_roles` (`groupId`, `roleId`) VALUES
|
||||
(1, 1),
|
||||
(1, 6),
|
||||
(1, 7),
|
||||
(2, 2),
|
||||
(2, 5),
|
||||
(3, 3),
|
||||
(4, 4);
|
||||
|
||||
TRUNCATE `rbac_account_groups`;
|
||||
INSERT INTO `rbac_account_groups` (`accountId`, `groupId`, `realmId`) SELECT `id`, 1, -1 FROM `account`; -- Add Player group to all accounts
|
||||
INSERT INTO `rbac_account_groups` (`accountId`, `groupId`, `realmId`) SELECT `id`, 2, `RealmID` FROM `account_access` WHERE `gmlevel` > 0; -- Add Moderator group to all Moderator or higher GM level
|
||||
INSERT INTO `rbac_account_groups` (`accountId`, `groupId`, `realmId`) SELECT `id`, 3, `RealmID` FROM `account_access` WHERE `gmlevel` > 1; -- Add GameMaster group to all GameMasters or higher GM level
|
||||
INSERT INTO `rbac_account_groups` (`accountId`, `groupId`, `realmId`) SELECT `id`, 4, `RealmID` FROM `account_access` WHERE `gmlevel` > 2; -- Add Administrator group to all Administrators
|
||||
|
||||
TRUNCATE `rbac_security_level_groups`;
|
||||
INSERT INTO `rbac_security_level_groups` (`secId`, `groupId`) VALUES
|
||||
(0, 1),
|
||||
(1, 1),
|
||||
(1, 2),
|
||||
(2, 1),
|
||||
(2, 2),
|
||||
(2, 3),
|
||||
(3, 1),
|
||||
(3, 2),
|
||||
(3, 3),
|
||||
(3, 4);
|
||||
3
sql/updates/auth/2013_02_04_01_auth_account.sql
Normal file
3
sql/updates/auth/2013_02_04_01_auth_account.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE `account`
|
||||
ADD COLUMN `mutereason` VARCHAR(255) NOT NULL DEFAULT '' AFTER `mutetime`,
|
||||
ADD COLUMN `muteby` VARCHAR(50) NOT NULL DEFAULT '' AFTER `mutereason`;
|
||||
2
sql/updates/auth/2013_02_05_00_auth_account.sql
Normal file
2
sql/updates/auth/2013_02_05_00_auth_account.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- Explicitly set the account-table to use INNODB-engine (to allow foreign keys and transactions)
|
||||
ALTER TABLE account ENGINE=InnoDB;
|
||||
3
sql/updates/auth/2013_02_07_00_auth_account.sql
Normal file
3
sql/updates/auth/2013_02_07_00_auth_account.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
UPDATE `account` SET `sessionkey`='';
|
||||
ALTER TABLE `account`
|
||||
CHANGE `sessionkey` `sessionkey` varchar(80) NOT NULL DEFAULT '' COMMENT 'Temporary storage of session key used to pass data from authserver to worldserver' AFTER `sha_pass_hash`;
|
||||
1
sql/updates/auth/2013_02_08_00_auth_account.sql
Normal file
1
sql/updates/auth/2013_02_08_00_auth_account.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE `account` CHANGE `sessionkey` `sessionkey` varchar(80) NOT NULL DEFAULT '' AFTER `sha_pass_hash`;
|
||||
@@ -0,0 +1,2 @@
|
||||
-- Add missing fields for new titles field
|
||||
UPDATE `characters` SET knownTitles = CONCAT(knownTitles, '0 0 ') WHERE (LENGTH(knownTitles) - LENGTH(REPLACE(knownTitles, ' ', ''))) = 6;
|
||||
28
sql/updates/world/2013_01_19_06_world_trinity_string.sql
Normal file
28
sql/updates/world/2013_01_19_06_world_trinity_string.sql
Normal file
@@ -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;
|
||||
1
sql/updates/world/2013_01_20_00_world_sai.sql
Normal file
1
sql/updates/world/2013_01_20_00_world_sai.sql
Normal file
@@ -0,0 +1 @@
|
||||
UPDATE `smart_scripts` SET `event_type`=25,`event_flags`=0,`event_param1`=0,`event_param2`=0 WHERE `entryorguid`=16029 AND `source_type`=0 AND `id`=0; -- Sludge Belcher
|
||||
10
sql/updates/world/2013_01_20_01_world_creature_text.sql
Normal file
10
sql/updates/world/2013_01_20_01_world_creature_text.sql
Normal file
@@ -0,0 +1,10 @@
|
||||
UPDATE `creature_text` SET `sound`=14344 WHERE `entry`=29310 AND `groupid`=1 AND `id`=0;
|
||||
UPDATE `creature_text` SET `sound`=14345 WHERE `entry`=29310 AND `groupid`=1 AND `id`=1;
|
||||
UPDATE `creature_text` SET `text`='Yogg-Saron! Grant me your power!', `sound`=14346 WHERE `entry`=29310 AND `groupid`=2 AND `id`=0;
|
||||
UPDATE `creature_text` SET `sound`=14347 WHERE `entry`=29310 AND `groupid`=2 AND `id`=1;
|
||||
UPDATE `creature_text` SET `sound`=14348 WHERE `entry`=29310 AND `groupid`=3 AND `id`=0;
|
||||
UPDATE `creature_text` SET `sound`=14349 WHERE `entry`=29310 AND `groupid`=3 AND `id`=1;
|
||||
UPDATE `creature_text` SET `sound`=14351 WHERE `entry`=29310 AND `groupid`=4;
|
||||
UPDATE `creature_text` SET `sound`=14354 WHERE `entry`=29310 AND `groupid`=5 AND `id`=2;
|
||||
UPDATE `creature_text` SET `sound`=14355 WHERE `entry`=29310 AND `groupid`=5 AND `id`=3;
|
||||
UPDATE `creature_text` SET `text`='The faithful shall be exalted, but there is more work to be done. We will press on until all of Azeroth lies beneath his shadow!', `sound`=14356 WHERE `entry`=29310 AND `groupid`=5 AND `id`=4;
|
||||
10
sql/updates/world/2013_01_20_02_world_creature_text.sql
Normal file
10
sql/updates/world/2013_01_20_02_world_creature_text.sql
Normal file
@@ -0,0 +1,10 @@
|
||||
UPDATE `creature_text` SET `sound`=14430, `type`=14 WHERE `entry`=29306 AND `groupid`=0;
|
||||
UPDATE `creature_text` SET `sound`=14431, `type`=14 WHERE `entry`=29306 AND `groupid`=4;
|
||||
UPDATE `creature_text` SET `sound`=14432, `type`=14 WHERE `entry`=29306 AND `groupid`=5;
|
||||
UPDATE `creature_text` SET `sound`=14433, `type`=14 WHERE `entry`=29306 AND `groupid`=3 AND `id`=0;
|
||||
UPDATE `creature_text` SET `sound`=14434, `type`=14 WHERE `entry`=29306 AND `groupid`=3 AND `id`=1;
|
||||
UPDATE `creature_text` SET `sound`=14435, `type`=14 WHERE `entry`=29306 AND `groupid`=3 AND `id`=2;
|
||||
UPDATE `creature_text` SET `sound`=14436, `type`=14 WHERE `entry`=29306 AND `groupid`=1 AND `id`=0;
|
||||
UPDATE `creature_text` SET `sound`=14437, `type`=14, `text`='Who needs gods when we ARE gods?' WHERE `entry`=29306 AND `groupid`=1 AND `id`=1;
|
||||
UPDATE `creature_text` SET `sound`=14438, `type`=14 WHERE `entry`=29306 AND `groupid`=1 AND `id`=2;
|
||||
UPDATE `creature_text` SET `sound`=14439, `type`=14 WHERE `entry`=29306 AND `groupid`=2;
|
||||
15
sql/updates/world/2013_01_20_03_world_creature_text.sql
Normal file
15
sql/updates/world/2013_01_20_03_world_creature_text.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
-- Moorabi
|
||||
UPDATE `creature_text` SET `sound`=14721, `text`='We fought back da Scourge. What chance joo thinkin'' JOO got?' WHERE `entry`=29305 AND `groupid`=0;
|
||||
UPDATE `creature_text` SET `sound`=14722 WHERE `entry`=29305 AND `groupid`=3;
|
||||
UPDATE `creature_text` SET `sound`=14723, `text`='Da ground gonna swallow you up!' WHERE `entry`=29305 AND `groupid`=4;
|
||||
UPDATE `creature_text` SET `sound`=14726, `text`='Who gonna stop me? You?' WHERE `entry`=29305 AND `groupid`=1 AND `id`=0;
|
||||
UPDATE `creature_text` SET `sound`=14727, `text`='Not so tough now!!' WHERE `entry`=29305 AND `groupid`=1 AND `id`=1;
|
||||
UPDATE `creature_text` SET `sound`=14728, `text`='If our gods can die... den so can we....' WHERE `entry`=29305 AND `groupid`=2;
|
||||
|
||||
-- Slad'ran
|
||||
UPDATE `creature_text` SET `sound`=14444, `type`=14 WHERE `entry`=29304 AND `groupid`=3;
|
||||
UPDATE `creature_text` SET `sound`=14445, `type`=14, `text`='A thousssand fangsss gonna rend your flesh!' WHERE `entry`=29304 AND `groupid`=4;
|
||||
UPDATE `creature_text` SET `sound`=14446, `type`=14, `text`='You not breathin''? Good.' WHERE `entry`=29304 AND `groupid`=1 AND `id`=0;
|
||||
UPDATE `creature_text` SET `sound`=14447, `type`=14 WHERE `entry`=29304 AND `groupid`=1 AND `id`=1;
|
||||
UPDATE `creature_text` SET `sound`=14448, `type`=14, `text`='I eat you next, mon.' WHERE `entry`=29304 AND `groupid`=1 AND `id`=2;
|
||||
UPDATE `creature_text` SET `sound`=14449, `type`=14, `text`='I sssee now... Ssscourge wasss not... our greatessst enemy....' WHERE `entry`=29304 AND `groupid`=2;
|
||||
81
sql/updates/world/2013_01_20_03_world_spell_script_names.sql
Normal file
81
sql/updates/world/2013_01_20_03_world_spell_script_names.sql
Normal file
@@ -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');
|
||||
12
sql/updates/world/2013_01_20_04_world_creature_text.sql
Normal file
12
sql/updates/world/2013_01_20_04_world_creature_text.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
-- Text for Crushridge Warmonger
|
||||
SET @ENTRY := 2287;
|
||||
DELETE FROM `creature_text` WHERE `entry`=@ENTRY AND `groupid`=1;
|
||||
INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES
|
||||
(@ENTRY,1,0,'%s goes into a frenzy!',16,0,100,0,0,0,'Crushridge Warmonger');
|
||||
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid` = 12236 AND `id`=9;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid` = 2428 AND `id`=10;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid` = 2287 AND `id`=1;
|
||||
UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid` = 2287 AND `id`=3;
|
||||
UPDATE `smart_scripts` SET `action_param1`=1 WHERE `entryorguid` = 2287 AND `id`=4;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid` = 8561 AND `id`=11;
|
||||
41
sql/updates/world/2013_01_20_05_world_sai.sql
Normal file
41
sql/updates/world/2013_01_20_05_world_sai.sql
Normal file
@@ -0,0 +1,41 @@
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=14390 AND `source_type`=0 AND `id`=9;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=2587 AND `source_type`=0 AND `id`=8;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=4064 AND `source_type`=0 AND `id`=9;
|
||||
UPDATE `smart_scripts` SET `link`=3 WHERE `entryorguid`=29181 AND `source_type`=0 AND `id`=2;
|
||||
UPDATE `smart_scripts` SET `link`=0,`event_type`=61,`event_param2`=0,`event_param3`=0 WHERE `entryorguid`=29181 AND `source_type`=0 AND `id`=3;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=29186 AND `source_type`=0 AND `id`=1;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=29199 AND `source_type`=0 AND `id`=1;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=29199 AND `source_type`=0 AND `id`=2;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=29204 AND `source_type`=0 AND `id`=1;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=29204 AND `source_type`=0 AND `id`=2;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=29200 AND `source_type`=0 AND `id`=1;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=29200 AND `source_type`=0 AND `id`=2;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=29176 AND `source_type`=0 AND `id`=1;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=500 AND `source_type`=0 AND `id`=10;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=4462 AND `source_type`=0 AND `id`=10;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=14467 AND `source_type`=0 AND `id`=1;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=2719 AND `source_type`=0 AND `id`=3;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=6004 AND `source_type`=0 AND `id`=9;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=23580 AND `source_type`=0 AND `id`=1;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=17270 AND `source_type`=0 AND `id`=13;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=29836 AND `source_type`=0 AND `id`=13;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=578 AND `source_type`=0 AND `id`=8;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=1397 AND `source_type`=0 AND `id`=14;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=1123 AND `source_type`=0 AND `id`=10;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=1123 AND `source_type`=0 AND `id`=16;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=3142 AND `source_type`=0 AND `id`=0;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=15641 AND `source_type`=0 AND `id`=9;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=424 AND `source_type`=0 AND `id`=9;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=19507 AND `source_type`=0 AND `id`=1;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=3643 AND `source_type`=1 AND `id`=0;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=1162 AND `source_type`=0 AND `id`=9;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=1162 AND `source_type`=0 AND `id`=10;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=3987 AND `source_type`=0 AND `id`=1;
|
||||
|
||||
UPDATE `smart_scripts` SET `event_flags`=0 WHERE `entryorguid`=6066 AND `source_type`=0 AND `id`=0;
|
||||
UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=8477 AND `source_type`=0 AND `id`=0;
|
||||
UPDATE `smart_scripts` SET `event_flags`=0 WHERE `entryorguid`=29206 AND `source_type`=0 AND `id`=0;
|
||||
UPDATE `smart_scripts` SET `event_flags`=0 WHERE `entryorguid`=29182 AND `source_type`=0 AND `id` IN (0,1);
|
||||
UPDATE `smart_scripts` SET `event_flags`=0 WHERE `entryorguid`=29177 AND `source_type`=0 AND `id`=0;
|
||||
UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=29684 AND `source_type`=0 AND `id` IN (0,1);
|
||||
UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=15631 AND `source_type`=0 AND `id`=0;
|
||||
24
sql/updates/world/2013_01_20_06_world_creature.sql
Normal file
24
sql/updates/world/2013_01_20_06_world_creature.sql
Normal file
@@ -0,0 +1,24 @@
|
||||
-- Image of Commander Ameer <The Protectorate> (22919)
|
||||
SET @GUID := 43492;
|
||||
|
||||
UPDATE `creature_template` SET `npcflag`=`npcflag`|2,`unit_flags`=`unit_flags`&~33554432 WHERE `entry`=22919;
|
||||
|
||||
DELETE FROM `creature` WHERE `guid`=@GUID;
|
||||
INSERT INTO `creature` (`guid`,`id`,`map`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`curhealth`) VALUES
|
||||
(@GUID,22919,530,3866.55,5978.68,291.792,4.10061,300,6986);
|
||||
|
||||
DELETE FROM `creature_questrelation` WHERE `id`=22919;
|
||||
INSERT INTO `creature_questrelation` (`id`,`quest`) VALUES
|
||||
(22919,10981), -- Nexus-Prince Shaffar's Personal Chamber
|
||||
(22919,10975), -- Purging the Chambers of Bash'ir
|
||||
(22919,10977), -- Stasis Chambers of the Mana-Tombs
|
||||
(22919,10976); -- The Mark of the Nexus-King
|
||||
|
||||
DELETE FROM `creature_involvedrelation` WHERE `id`=22919;
|
||||
INSERT INTO `creature_involvedrelation` (`id`,`quest`) VALUES
|
||||
(22919,10981), -- Nexus-Prince Shaffar's Personal Chamber
|
||||
(22919,10975), -- Purging the Chambers of Bash'ir
|
||||
(22919,10974), -- Stasis Chambers of Bash'ir
|
||||
(22919,10977), -- Stasis Chambers of the Mana-Tombs
|
||||
(22919,10982), -- The Eye of Haramad
|
||||
(22919,10976); -- The Mark of the Nexus-King
|
||||
5
sql/updates/world/2013_01_20_07_world_sai.sql
Normal file
5
sql/updates/world/2013_01_20_07_world_sai.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=234 AND `source_type`=0 AND `id`=0;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=2554 AND `source_type`=0 AND `id`=9;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=12265 AND `source_type`=0 AND `id`=1;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=12265 AND `source_type`=0 AND `id`=3;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=16704 AND `source_type`=0 AND `id`=13;
|
||||
4
sql/updates/world/2013_01_20_08_world_sai.sql
Normal file
4
sql/updates/world/2013_01_20_08_world_sai.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
UPDATE `smart_scripts` SET `link`=0,`event_type`=61 WHERE `entryorguid`=13601 AND `source_type`=0 AND `id`=4;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=13601 AND `source_type`=0 AND `id`=10;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=17670 AND `source_type`=0 AND `id`=13;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=11878 AND `source_type`=0 AND `id`=13;
|
||||
18
sql/updates/world/2013_01_20_09_world_spell_dbc.sql
Normal file
18
sql/updates/world/2013_01_20_09_world_spell_dbc.sql
Normal file
@@ -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');
|
||||
2
sql/updates/world/2013_01_21_00_world_misc.sql
Normal file
2
sql/updates/world/2013_01_21_00_world_misc.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
UPDATE `spell_dbc` SET `EffectImplicitTargetB1`=7,`EffectRadiusIndex1`=18 WHERE `Id`=24211;
|
||||
UPDATE `conditions` SET `ConditionTypeOrReference`=31,`ConditionTarget`=0 WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=24211;
|
||||
@@ -0,0 +1 @@
|
||||
UPDATE `creature_template` SET `faction_A`=14,`faction_H`=14 WHERE `entry`=22920;
|
||||
7
sql/updates/world/2013_01_21_02_world_sai.sql
Normal file
7
sql/updates/world/2013_01_21_02_world_sai.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=16459 AND `source_type`=0 AND `id`=2;
|
||||
UPDATE `smart_scripts` SET `event_flags`=0 WHERE `entryorguid`=5263 AND `source_type`=0 AND `id`=0;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=19255 AND `source_type`=0 AND `id`=0;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=5888 AND `source_type`=0 AND `id`=0;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=10828 AND `source_type`=0 AND `id`=0;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=29181 AND `source_type`=0 AND `id`=1;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=16403 AND `source_type`=0 AND `id`=9;
|
||||
11
sql/updates/world/2013_01_22_00_world_command.sql
Normal file
11
sql/updates/world/2013_01_22_00_world_command.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
DELETE FROM `command` WHERE `name`='mmap' OR `name` LIKE 'mmap%';
|
||||
DELETE FROM `command` WHERE `name` LIKE 'disable add mmap' OR `name` LIKE 'disable remove 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'),
|
||||
('disable add mmap', '3', 'Syntax: .disable add mmap $entry $flag $comment'),
|
||||
('disable remove mmap', '3', 'Syntax: .disable remove mmap $entry');
|
||||
22
sql/updates/world/2013_01_22_01_world_sai.sql
Normal file
22
sql/updates/world/2013_01_22_01_world_sai.sql
Normal file
@@ -0,0 +1,22 @@
|
||||
UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid`=20882 AND `source_type`=0 AND `id`=0;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=20896 AND `source_type`=0 AND `id`=3;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=20900 AND `source_type`=0 AND `id`=3;
|
||||
UPDATE `smart_scripts` SET `link`=0,`event_type`=61 WHERE `entryorguid`=4063 AND `source_type`=0 AND `id`=3;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=2245 AND `source_type`=0 AND `id`=8;
|
||||
UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=7038 AND `source_type`=0 AND `id`=17;
|
||||
UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=2345 AND `source_type`=0 AND `id`=11;
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=314 AND `source_type`=0;
|
||||
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
|
||||
(314, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Eliza - Phase 0 - On spawn - Prevent combat movement'),
|
||||
(314, 0, 2, 3, 4, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Eliza - Phase 0 - On aggro - Say'),
|
||||
(314, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Eliza - Phase 0 - On aggro - Set phase 1'),
|
||||
(314, 0, 4, 0, 9, 1, 100, 0, 0, 40, 0, 0, 11, 20819, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 'Eliza - Phase 1 - In combat - Cast Frostbolt'),
|
||||
(314, 0, 5, 0, 9, 1, 100, 0, 0, 5, 0, 0, 21, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Eliza - Phase 1 - 0 to 5 yards - Activate combat movement'),
|
||||
(314, 0, 6, 0, 9, 1, 100, 0, 5, 35, 0, 0, 21, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Eliza - Phase 1 - 5 to 35 yards - Deactivate combat movement'),
|
||||
(314, 0, 7, 0, 9, 1, 100, 0, 35, 80, 0, 0, 21, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Eliza - Phase 1 - 35 to 80 yards - Activate combat movement'),
|
||||
(314, 0, 8, 0, 0, 1, 100, 0, 4100, 6400, 72300, 72300, 11, 3107, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Eliza - Phase 1 - In combat - Summon Elizas Guard'),
|
||||
(314, 0, 9, 0, 0, 1, 100, 0, 2100, 2900, 12500, 36300, 11, 11831, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 'Eliza - Phase 1 - In combat - Cast Frost Nova'),
|
||||
(314, 0, 10, 12, 3, 1, 100, 0, 0, 7, 0, 0, 21, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Eliza - Phase 1 - At 7% mana - Start combat movement'),
|
||||
(314, 0, 11, 0, 61, 1, 100, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Eliza - Phase 1 - At 7% mana - Set phase 2'),
|
||||
(314, 0, 12, 0, 3, 2, 100, 0, 15, 100, 100, 100, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Eliza - Phase 2 - At 15% mana - Set phase 1');
|
||||
@@ -0,0 +1,4 @@
|
||||
-- 85256 - Templar's Verdict
|
||||
DELETE FROM `spell_script_names` WHERE `spell_id`=85256;
|
||||
INSERT INTO `spell_script_names` VALUES
|
||||
(85256,'spell_pal_templar_s_verdict');
|
||||
5
sql/updates/world/2013_01_23_00_world_misc.sql
Normal file
5
sql/updates/world/2013_01_23_00_world_misc.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
-- readd flight aura on Wyrmrest Defender npcs
|
||||
UPDATE `creature_template_addon` SET `auras`='50069' WHERE `entry`=27629;
|
||||
|
||||
-- correct SAI on Nerub'ar Broodkeeper
|
||||
UPDATE `smart_scripts` SET `event_param1`=0 WHERE `entryorguid`=36725 AND `source_type`=0 AND `id`=1;
|
||||
10
sql/updates/world/2013_01_23_01_world_misc.sql
Normal file
10
sql/updates/world/2013_01_23_01_world_misc.sql
Normal file
@@ -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).');
|
||||
77
sql/updates/world/2013_01_23_02_world_spell_script_names.sql
Normal file
77
sql/updates/world/2013_01_23_02_world_spell_script_names.sql
Normal file
@@ -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');
|
||||
32
sql/updates/world/2013_01_24_00_world_sai.sql
Normal file
32
sql/updates/world/2013_01_24_00_world_sai.sql
Normal file
@@ -0,0 +1,32 @@
|
||||
SET @AETHER_RAY := 22181;
|
||||
SET @WRANGLED_RAY := 23343;
|
||||
SET @WRANGLE_SPELL := 40856;
|
||||
SET @WRANGLED_FORCE_CAST := 40917;
|
||||
SET @WRANGLED_AURA := 40926;
|
||||
SET @QUEST_GIVER := 23335;
|
||||
|
||||
DELETE FROM `creature_text` WHERE `entry`=@AETHER_RAY;
|
||||
INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES
|
||||
(@AETHER_RAY,1,0,'The Aether Ray appears ready to be wrangled.',16,0,100,0,0,0,'Aether Ray');
|
||||
|
||||
DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@AETHER_RAY;
|
||||
UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@AETHER_RAY;
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=@AETHER_RAY;
|
||||
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
|
||||
(@AETHER_RAY, 0, 0, 0, 0, 0, 100, 0, 5000, 6000, 8000, 9000, 11, 35333, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Aether Ray - IC - Cast Tail Swipe'),
|
||||
(@AETHER_RAY, 0, 1, 0, 2, 0, 100, 1, 0, 40, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Aether Ray - On 40 % HP - Say emote'),
|
||||
(@AETHER_RAY, 0, 2, 3, 8, 0, 100, 0, @WRANGLE_SPELL, 0, 0, 0, 41, 1000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Aether Ray - On spellcast - Despawn'),
|
||||
(@AETHER_RAY, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 11, @WRANGLED_FORCE_CAST, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Aether Ray - Link with 2 - Summon Wrangled Aether Ray');
|
||||
|
||||
DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@WRANGLED_RAY;
|
||||
UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@WRANGLED_RAY;
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=@WRANGLED_RAY;
|
||||
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
|
||||
(@WRANGLED_RAY, 0, 0, 1, 54, 0, 100, 1, 0, 0, 0, 0, 85, @WRANGLED_AURA, 3, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'On spawn - Cast Wrangled Aura - Action Invoker'),
|
||||
(@WRANGLED_RAY, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 29, 0, 0, @QUEST_GIVER, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Wrangled Ray - Link with 0 - Follow Player'),
|
||||
(@WRANGLED_RAY, 0, 2, 0, 65, 0, 100, 0, 0, 0, 0, 0, 41, 1000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Wrangled Ray - On follow complete - Despawn');
|
||||
|
||||
DELETE FROM `conditions` WHERE `SourceEntry`=@WRANGLE_SPELL;
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||
(17, 0, @WRANGLE_SPELL, 0, 0, 31, 1, 3, 22181, 0, 0, 0, 0, '', 'Spell only hits Aether Rey'),
|
||||
(17, 0, @WRANGLE_SPELL, 0, 0, 38, 1, 40, 4, 0, 0, 0, 0, '', 'Spell only hits if at or below 40%');
|
||||
8
sql/updates/world/2013_01_25_00_world_creature_text.sql
Normal file
8
sql/updates/world/2013_01_25_00_world_creature_text.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
-- Update text's with creature_text.type old format values - some missing texts should be fixed.
|
||||
-- based on http://collab.kpsn.org/display/tc/Creature+text+tc2#Creaturetexttc2-type
|
||||
UPDATE `creature_text` SET `type`=12 WHERE `type`=0; -- Say
|
||||
UPDATE `creature_text` SET `type`=14 WHERE `type`=1; -- Yell
|
||||
UPDATE `creature_text` SET `type`=16 WHERE `type`=2; -- Emote
|
||||
UPDATE `creature_text` SET `type`=41 WHERE `type`=3; -- Boss Emote
|
||||
UPDATE `creature_text` SET `type`=15 WHERE `type`=4; -- Whisper
|
||||
UPDATE `creature_text` SET `type`=42 WHERE `type`=5; -- Boss Whisper
|
||||
@@ -0,0 +1,3 @@
|
||||
DELETE FROM `spell_linked_spell` WHERE `spell_trigger` IN (77769, -77769);
|
||||
INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES
|
||||
(77769, 82946, 2, 'Trap Launcher - Add/Remove');
|
||||
@@ -0,0 +1,14 @@
|
||||
UPDATE `creature_classlevelstats` SET `basehp1`=9741 WHERE `level`=82 AND `class`=1;
|
||||
UPDATE `creature_classlevelstats` SET `basehp0`=5971, `basehp1`=10300 WHERE `level`=84 AND `class`=1;
|
||||
UPDATE `creature_classlevelstats` SET `basehp0`=6141 WHERE `level`=85 AND `class`=1;
|
||||
|
||||
UPDATE `creature_classlevelstats` SET `basehp1`=1006 WHERE `level`=31 AND `class`=2;
|
||||
UPDATE `creature_classlevelstats` SET `basemana`=4081 WHERE `level`=81 AND `class`=2;
|
||||
UPDATE `creature_classlevelstats` SET `basemana`=4363 WHERE `level`=84 AND `class`=2;
|
||||
UPDATE `creature_classlevelstats` SET `basehp2`=15498, `basemana`=4454 WHERE `level`=85 AND `class`=2;
|
||||
UPDATE `creature_classlevelstats` SET `basehp2`=16515, `basemana`=4735 WHERE `level`=88 AND `class`=2;
|
||||
|
||||
UPDATE `creature_classlevelstats` SET `basemana`=9328 WHERE `level`=83 AND `class`=8;
|
||||
UPDATE `creature_classlevelstats` SET `basemana`=9512 WHERE `level`=84 AND `class`=8;
|
||||
UPDATE `creature_classlevelstats` SET `basehp0`=4299, `basemana`=9697 WHERE `level`=85 AND `class`=8;
|
||||
UPDATE `creature_classlevelstats` SET `basemana`=10232 WHERE `level`=88 AND `class`=8;
|
||||
41
sql/updates/world/2013_01_25_02_world_smart_scripts.sql
Normal file
41
sql/updates/world/2013_01_25_02_world_smart_scripts.sql
Normal file
@@ -0,0 +1,41 @@
|
||||
-- Kalaran Windblade: SAI
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=8479 AND `source_type`=0;
|
||||
INSERT INTO `smart_scripts`(`entryorguid`,`id`,`link`,`event_type`,`event_param1`,`event_param2`,`action_type`,`action_param1`,`target_type`,`comment`) VALUES
|
||||
(8479,0,1,62,1321,0,26,3441,7,'Kalaran Windblade - On gossip select - Quest credit'),
|
||||
(8479,1,0,61,0,0,72,0,7,'Kalaran Windblade - On gossip select - Close gossip'),
|
||||
(8479,2,3,62,1323,2,11,19797,7,'Kalaran Windblade - On gossip select - Cast 19797'),
|
||||
(8479,3,0,61,0,0,72,0,7,'Kalaran Windblade - On gossip select - Close gossip'),
|
||||
(8479,4,0,62,1323,3,80,847900,1,'Kalaran Windblade - On gossip select - Run script');
|
||||
|
||||
-- Kalaran Windblade: SAI action list
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=847900 AND `source_type`=9;
|
||||
INSERT INTO `smart_scripts`(`entryorguid`,`source_type`,`id`,`event_param1`,`event_param2`,`action_type`,`action_param1`,`target_type`,`comment`) VALUES
|
||||
(847900,9,0,0,0,72,0,7,'Kalaran Windblade - Action 0 - Close gossip'),
|
||||
(847900,9,1,0,0,83,3,1,'Kalaran Windblade - Action 1 - Remove NPC flags'),
|
||||
(847900,9,2,1000,1000,1,0,1,'Kalaran Windblade - Action 2 - Say 0'),
|
||||
(847900,9,3,1000,1000,17,69,1,'Kalaran Windblade - Action 3 - Emote state use standing'),
|
||||
(847900,9,4,60000,60000,17,0,1,'Kalaran Windblade - Action 4 - Emote state none'),
|
||||
(847900,9,5,1000,1000,15,3453,7,'Kalaran Windblade - Action 5 - Give quest credit'),
|
||||
(847900,9,6,1000,1000,82,3,1,'Kalaran Windblade - Action 6 - Add NPC flags');
|
||||
|
||||
-- Kalaran Windblade: Creature text
|
||||
DELETE FROM `creature_text` WHERE `entry`=8479;
|
||||
INSERT INTO `creature_text`(`entry`,`groupid`,`id`,`text`,`type`,`probability`,`comment`) VALUE
|
||||
(8479,0,0,'Be patient, $N. The torch is almost complete.',12,100,'Kalaran Windblade - Smart AI');
|
||||
|
||||
-- Captured Mountaineer: SAI
|
||||
UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=2211;
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=2211 AND `source_type`=0;
|
||||
INSERT INTO `smart_scripts`(`entryorguid`,`id`,`event_type`,`event_param1`,`action_type`,`action_param1`,`action_param2`,`target_type`,`comment`) VALUE
|
||||
(2211,0,20,492,80,221100,2,1,'Captured Mountaineer - On quest reward - Start timed action list');
|
||||
|
||||
-- Captured Mountaineer: SAI action list
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=221100 AND `source_type`=9;
|
||||
INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`event_param1`,`event_param2`,`action_type`,`action_param1`,`target_type`,`comment`) VALUES
|
||||
(221100,9,0,1000,1000,1,0,1,'Captured Mountaineer - Action 0 - Say 0'),
|
||||
(221100,9,1,4000,4000,37,0,1,'Captured Mountaineer - Action 2 - Suicide');
|
||||
|
||||
-- Captured Mountaineer: Creature text
|
||||
DELETE FROM `creature_text` WHERE `entry`=2211;
|
||||
INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`probability`,`emote`,`comment`) VALUE
|
||||
(2211,0,0,'I raise my brew and hope to be rid of the likes of you! Cheers, you no good scoundrel, $N!',12,100,7,'Captured Mountaineer - Reward quest 492');
|
||||
8
sql/updates/world/2013_01_26_00_world_misc.sql
Normal file
8
sql/updates/world/2013_01_26_00_world_misc.sql
Normal file
@@ -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.');
|
||||
@@ -0,0 +1,7 @@
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_gen_running_wild';
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_gen_two_forms';
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_gen_darkflight';
|
||||
INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
|
||||
(87840,'spell_gen_running_wild'),
|
||||
(68996,'spell_gen_two_forms'),
|
||||
(68992,'spell_gen_darkflight');
|
||||
@@ -0,0 +1,5 @@
|
||||
-- Coren Direbrew ( http://old.wowhead.com/npc=23872 ) loot fix by dele
|
||||
DELETE FROM `creature_loot_template` WHERE `entry`=23872 AND `item` IN (38280,38281);
|
||||
INSERT INTO `creature_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES
|
||||
(23872,38280,100,1,0,1,1), -- Direbrew's Dire Brew Alliance version
|
||||
(23872,38281,100,1,0,1,1); -- Direbrew's Dire Brew Horde version
|
||||
@@ -0,0 +1,26 @@
|
||||
-- Add reference for Zone Drop Netherstorm Blues
|
||||
DELETE FROM `reference_loot_template` WHERE `entry`=14501;
|
||||
INSERT INTO `reference_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES
|
||||
(14501,31940,0,1,1,1,1), -- Ethereum Torque
|
||||
(14501,31936,0,1,1,1,1), -- Fiery Cloak
|
||||
(14501,31565,0,1,1,1,1), -- Skystalker's Boots
|
||||
(14501,31573,0,1,1,1,1), -- Mistshroud Boots
|
||||
(14501,31557,0,1,1,1,1), -- Windchanneller's Boots
|
||||
(14501,31937,0,1,1,1,1), -- Living Cloak
|
||||
(14501,31928,0,1,1,1,1), -- Dark Band
|
||||
(14501,31581,0,1,1,1,1), -- Slatesteel Boots
|
||||
(14501,31929,0,1,1,1,1), -- Enigmatic Band
|
||||
(14501,31938,0,1,1,1,1), -- Enigmatic Cloak
|
||||
(14501,31943,0,1,1,1,1), -- Ethereum Band
|
||||
(14501,31939,0,1,1,1,1), -- Dark Cloak
|
||||
(14501,31925,0,1,1,1,1), -- Fiery Band
|
||||
(14501,31926,0,1,1,1,1), -- Frigid Band
|
||||
(14501,31927,0,1,1,1,1), -- Living Band
|
||||
(14501,32520,0,1,1,1,1), -- Manaforged Sphere
|
||||
(14501,31935,0,1,1,1,1); -- Frigid Cloak
|
||||
-- Add loot for Protectorate Treasure Cache
|
||||
UPDATE `item_template` SET `minMoneyLoot`=10000,`maxMoneyLoot`=10000 WHERE `entry`=32064;
|
||||
DELETE FROM `item_loot_template` WHERE `entry`=32064;
|
||||
INSERT INTO `item_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES
|
||||
(32064,1,80,1,1,-24013,1), -- one from greens
|
||||
(32064,2,20,1,1,-14501,1); -- one from blue items
|
||||
108
sql/updates/world/2013_01_26_03_world_conditions.sql
Normal file
108
sql/updates/world/2013_01_26_03_world_conditions.sql
Normal file
@@ -0,0 +1,108 @@
|
||||
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (18431,17731);
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||
-- Bellowing Roar
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176838, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176837, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176835, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176834, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176832, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176831, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176833, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176825, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176824, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176823, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176819, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176813, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176812, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176809, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176515, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176514, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176513, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176911, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176910, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176909, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176908, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176842, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176841, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176840, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176839, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176836, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176826, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176811, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176810, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176922, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176921, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176920, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176919, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176915, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176914, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176913, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176912, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176830, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176829, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176828, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176827, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176822, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176821, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176820, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176818, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176817, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176816, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176815, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176814, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176918, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176917, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
(13, 2, 18431, 0, 0, 31, 0, 5, 176916, 0, 0, 0, 0, '', 'Bellowing Roar - Lava Fissure'),
|
||||
-- Eruption
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176838, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176837, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176835, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176834, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176832, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176831, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176833, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176825, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176824, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176823, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176819, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176813, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176812, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176809, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176515, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176514, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176513, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176911, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176910, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176909, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176908, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176842, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176841, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176840, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176839, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176836, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176826, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176811, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176810, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176922, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176921, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176920, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176919, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176915, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176914, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176913, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176912, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176830, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176829, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176828, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176827, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176822, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176821, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176820, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176818, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176817, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176816, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176815, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176814, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176918, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176917, 0, 0, 0, 0, '', 'Eruption - Lava Fissure'),
|
||||
(13, 2, 17731, 0, 0, 31, 0, 5, 176916, 0, 0, 0, 0, '', 'Eruption - Lava Fissure');
|
||||
29
sql/updates/world/2013_01_26_04_world_item_loot_template.sql
Normal file
29
sql/updates/world/2013_01_26_04_world_item_loot_template.sql
Normal file
@@ -0,0 +1,29 @@
|
||||
-- Change loot in Mithril Bound Trunk to always give an item
|
||||
DELETE FROM `item_loot_template` WHERE `entry`=21228;
|
||||
INSERT INTO `item_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES
|
||||
-- Group1: Leather @ 70%
|
||||
(21228,4304,40,1,1,2,4), -- Thick Leather
|
||||
(21228,8170,30,1,1,1,2), -- Rugged Leather
|
||||
-- Group2: Cloth @ 70%
|
||||
(21228, 4339,40,1,2,1,3), -- Bolt of Mageweave
|
||||
(21228,14048,30,1,2,1,2), -- Bolt of Runecloth
|
||||
-- Ungrouped:
|
||||
(21228,6149,20,1,0,1,2), -- Greater Mana Potion
|
||||
(21228,3928,20,1,0,1,2), -- Superior Healing Potion
|
||||
(21228,34109,50,1,0,1,1), -- Weather-Beaten Journal
|
||||
(21228, 3914, 1,1,0,1,1), -- Journeyman's Backpack
|
||||
(21228,7976,0.05,1,0,1,1), -- Plans: Mithril Shield Spike
|
||||
(21228,7909,0.4,1,0,1,1), -- Aquamarine
|
||||
(21228,7910,0.3,1,0,1,1), -- Star Ruby
|
||||
(21228,1613,0.3,1,0,1,1), -- Spiritchaser Staff
|
||||
(21228,9295,0.3,1,0,1,1), -- Recipe: Invisibility Potion
|
||||
(21228,7468,0.2,1,0,1,1), -- Regal Robe
|
||||
(21228,9291,0.2,1,0,1,1), -- Field Plate Leggings
|
||||
(21228,9910,0.2,1,0,1,1), -- Royal Gloves
|
||||
(21228,10320,0.2,1,0,1,1), -- Pattern: Red Mageweave Headband
|
||||
(21228,15245,0.2,1,0,1,1), -- Vorpal Dagger
|
||||
(21228,8281,0.2,1,0,1,1), -- Valorous Pauldrons
|
||||
(21228,1685,0.2,1,0,1,1), -- Troll-hide Bag
|
||||
(21228,8163,0.2,1,0,1,1), -- Jouster's Pauldrons
|
||||
(21228,8141,0.2,1,0,1,1), -- Chromite Greaves
|
||||
(21228,8121,0.2,1,0,1,1); -- Heraldic Gloves
|
||||
116
sql/updates/world/2013_01_26_05_world_misc.sql
Normal file
116
sql/updates/world/2013_01_26_05_world_misc.sql
Normal file
@@ -0,0 +1,116 @@
|
||||
-- Issue 5882: Dire Maul Arena Rare Bosses
|
||||
-- Spawnlocations are from YTDB need to be checked!
|
||||
SET @GUID := 45758; -- set the guid for spawning
|
||||
SET @POOL := 358; -- set the poolid for the spawn
|
||||
DELETE FROM `creature` WHERE `id` IN (11447,11497,11498);
|
||||
INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`,`npcflag`,`unit_flags`,`dynamicflags`) VALUES
|
||||
(@GUID ,11447,1,1,1,0,0,-3799.62,1063.83,132.806,1.20424,21600,0,0,60000, 0,0,0,0,0),
|
||||
(@GUID+1,11497,1,1,1,0,0,-3731.22,1061.32,132.345,1.78150,21600,0,0,73000,24340,0,0,0,0),
|
||||
(@GUID+2,11498,1,1,1,0,0,-3690.96,1077.14,131.969,2.65172,21600,0,0,57000, 0,0,0,0,0);
|
||||
DELETE FROM `pool_template` WHERE `entry`=@POOL;
|
||||
INSERT INTO `pool_template` (`entry`,`max_limit`,`description`) VALUES
|
||||
(@POOL,1,'Max 1 Rare in Dire Maul Arena');
|
||||
DELETE FROM `pool_creature` WHERE `pool_entry`=@POOL;
|
||||
INSERT INTO `pool_creature` (`guid`,`pool_entry`,`chance`,`description`) VALUES
|
||||
(@GUID ,@POOL,0, 'Rare Spawn Dire Maul Arena'),
|
||||
(@GUID+1,@POOL,0, 'Rare Spawn Dire Maul Arena'),
|
||||
(@GUID+2,@POOL,0, 'Rare Spawn Dire Maul Arena');
|
||||
-- Issue 5925: Missing Sand Shark from Durotar
|
||||
-- Thx Mogale for sniffing
|
||||
DELETE FROM `creature` WHERE `id`=5435;
|
||||
INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`,`npcflag`,`unit_flags`,`dynamicflags`) VALUES
|
||||
(43494,5435,1,1,1,0,0,-1144.251,-4336.333,-8.457234,4.602825,900,4,0,741,0,1,0,0,0);
|
||||
-- Issue 8498: Fix 2 centaurs stuck in the ground (by Baric)
|
||||
UPDATE creature SET position_z=93.67 WHERE guid IN (14007, 20588);
|
||||
-- Issue 568: No Mercy for the Captured
|
||||
-- Gossip Menu Options
|
||||
DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (9510,9509,9508,9507);
|
||||
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
|
||||
-- Chancellor
|
||||
(9510,0,0, 'No, chancellor.. I wouldn''t say that I''m here to ''rescue'' you, per se.',1,1,0,0,0,0,NULL),
|
||||
(9510,1,0, 'Where is Senior Scrivener Barriga being held?' ,1,1,50424,0,0,0,NULL),
|
||||
(9510,2,0, 'Did you see where they took Sanitation Engineer Burke?',1,1,50426,0,0,0,NULL),
|
||||
(9510,3,0, 'Any idea where they''re keeping Deathguard Schneider?' ,1,1,50425,0,0,0,NULL),
|
||||
-- Engineer
|
||||
(9509,0,0, 'Affraid not. Your days as a sanitation engineer are coming to an end', 1,1, 0,0,0,0,NULL),
|
||||
(9509,1,0, 'Can you tell me where they have Chancellor Amai caged?',1,1,50423,0,0,0,NULL),
|
||||
(9509,2,0, 'Where is Senior Scrivener Barriga being held?' ,1,1,50424,0,0,0,NULL),
|
||||
(9509,3,0, 'Any idea where they''re keeping Deathguard Schneider?' ,1,1,50425,0,0,0,NULL),
|
||||
-- Scrivener
|
||||
(9508,0,0, 'Not today, senior scrivener!' ,1,1, 0,0,0,0,NULL),
|
||||
(9508,1,0, 'Can you tell me where they have Chancellor Amai caged?',1,1,50423,0,0,0,NULL),
|
||||
(9508,2,0, 'Did you see where they took Sanitation Engineer Burke?',1,1,50426,0,0,0,NULL),
|
||||
(9508,3,0, 'Any idea where they''re keeping Deathguard Schneider?' ,1,1,50425,0,0,0,NULL),
|
||||
-- Schneider
|
||||
(9507,0,0, 'I''m affraid not. Schneider. Your time has come!' ,1,1, 0,0,0,0,NULL),
|
||||
(9507,1,0, 'Can you tell me where they have Chancellor Amai caged?',1,1,50423,0,0,0,NULL),
|
||||
(9507,2,0, 'Where is Senior Scrivener Barriga being held?' ,1,1,50424,0,0,0,NULL),
|
||||
(9507,3,0, 'Did you see where they took Sanitation Engineer Burke?',1,1,50426,0,0,0,NULL);
|
||||
-- Gossip Menu
|
||||
DELETE FROM `gossip_menu` WHERE `entry` IN (50423,50424,50425,50426);
|
||||
INSERT INTO `gossip_menu` (`entry`, `text_id`) VALUES
|
||||
(50423,12833), -- I think I saw them take him over by the north side of the abbey, near the archery targets.
|
||||
(50424,12827), -- I think they put him in a cage over near the lumbermill.
|
||||
(50425,12832), -- I think they have her down near the gallows.
|
||||
(50426,12830); -- I think he's on the south side of the abbey.
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid` IN (27376,27378,27379,27381) AND `source_type`=0;
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid` IN (2737600,2737800,2737900,2738100) AND `source_type`=9;
|
||||
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
|
||||
-- Deathguard Schneider
|
||||
(27376 ,0,0,0,62,0,100,0,9507,0,0,0,80,2737600,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0, "Deathguard Schneider - On Gossip Option Select - Start Script"),
|
||||
(27376 ,0,1,0,10,0,100,0,0,10,180000,300000,1,1,0,0,0,0,0,17,0,10,0,0.0,0.0,0.0,0.0,"Deathguard Schneider - On LoS with Player Near - Say Line 1"),
|
||||
(2737600,9,0,0,0,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0.0,0.0,0.0,0.0, "Deathguard Schneider - Script - Close Gossip"),
|
||||
(2737600,9,1,0,0,0,100,0,200,200,0,0,1,0,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0, "Deathguard Schneider - Script - Say line 0"),
|
||||
(2737600,9,2,0,0,0,100,0,5000,5000,0,0,2,14,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0, "Deathguard Schneider - Script - Set facton 14 (Hostile)"),
|
||||
(2737600,9,3,0,0,0,100,0,2500,2500,0,0,46,1,0,0,0,0,0,0,0,0,0,0.0,0.0,0.0,0.0, "Deathguard Schneider - Script - Move"),
|
||||
-- Senior Scrivener Barriga
|
||||
(27378 ,0,0,0,62,0,100,0,9508,0,0,0,80,2737800,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0,"Senior Scrivener Barriga - On Gossip Option Select - Start Script"),
|
||||
(27378 ,0,1,0,10,0,100,0,0,10,180000,300000,1,1,0,0,0,0,0,17,0,10,0,0.0,0.0,0.0,0.0,"Senior Scrivener Barriga - On LoS with Player Near - Say Line 1"),
|
||||
(2737800,9,0,0,0,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0.0,0.0,0.0,0.0, "Deathguard Schneider - Script - Close Gossip"),
|
||||
(2737800,9,1,0,0,0,100,0,200,200,0,0,1,0,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0,"Senior Scrivener Barriga - Say line 0"),
|
||||
(2737800,9,2,0,0,0,100,0,5000,5000,0,0,2,14,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0,"Senior Scrivener Barriga - Set facton 14"),
|
||||
(2737800,9,3,0,0,0,100,0,2500,2500,0,0,46,1,0,0,0,0,0,0,0,0,0,0.0,0.0,0.0,0.0,"Senior Scrivener Barriga - Move"),
|
||||
-- Engineer Burke
|
||||
(27379 ,0,0,0,62,0,100,0,9509,0,0,0,80,2737900,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0,"Engineer Burke - On Gossip Option Select - Start Script"),
|
||||
(27379 ,0,1,0,10,0,100,0,0,10,180000,300000,1,1,0,0,0,0,0,17,0,10,0,0.0,0.0,0.0,0.0,"Engineer Burke - On LoS with Player Near - Say Line 1"),
|
||||
(2737900,9,0,0,0,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0.0,0.0,0.0,0.0, "Deathguard Schneider - Script - Close Gossip"),
|
||||
(2737900,9,1,0,0,0,100,0,200,200,0,0,1,0,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0,"Engineer Burke - Script - Say line 0"),
|
||||
(2737900,9,2,0,0,0,100,0,5000,5000,0,0,2,14,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0,"Engineer Burke - Script - Set facton 14"),
|
||||
(2737900,9,3,0,0,0,100,0,2500,2500,0,0,46,1,0,0,0,0,0,0,0,0,0,0.0,0.0,0.0,0.0,"Engineer Burke - Script - Move"),
|
||||
-- Chancellor Amai
|
||||
(27381 ,0,0,0,62,0,100,0,9510,0,0,0,80,2738100,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0,"Chancellor Amai - On Gossip Option Select - Start Script"),
|
||||
(27381 ,0,1,0,10,0,100,0,0,10,180000,300000,1,1,0,0,0,0,0,17,0,10,0,0.0,0.0,0.0,0.0,"Chancellor Amai - On LoS with Player Near - Say Line 1"),
|
||||
(2738100,9,0,0,0,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0.0,0.0,0.0,0.0, "Deathguard Schneider - Script - Close Gossip"),
|
||||
(2738100,9,1,0,0,0,100,0,200,200,0,0,1,0,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0,"Chancellor Amai - Script - Say line 0"),
|
||||
(2738100,9,2,0,0,0,100,0,5000,5000,0,0,2,14,0,0,0,0,0,1,0,0,0,0.0,0.0,0.0,0.0,"Chancellor Amai - Script - Set facton 14"),
|
||||
(2738100,9,3,0,0,0,100,0,2500,2500,0,0,46,1,0,0,0,0,0,0,0,0,0,0.0,0.0,0.0,0.0,"Chancellor Amai - Script - Move");
|
||||
-- Creature Texts
|
||||
DELETE FROM `creature_text` WHERE `entry` IN (27376,27378,27379,27381);
|
||||
INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES
|
||||
(27376,0,0, 'What do you mean my time has come? I''ll kill you where you stand!',12,0,100,0,0,0, 'Deathguard Schneider before going hostile'),
|
||||
(27376,1,0, 'Hey, over here!',12,0,100,0,0,0, 'Deathguard Schneider upon LoS'),
|
||||
(27378,0,0, 'You can''t possibly mean to.... I''ll write you up for this, $C!',12,0,100,0,0,0, 'Senior Scrivener Barriga before going hostile'),
|
||||
(27378,1,0, 'If you''d be so kind, please let me out of here!',12,0,100,0,0,0, 'Senior Scrivener Barriga upon LoS'),
|
||||
(27379,0,0, 'No! I beg you! Please don''t kill me!',12,0,100,0,0,0, 'Engineer Burke before going hostile'),
|
||||
(27379,1,0, 'Can Someone let me out of here? I need to get back to Venomspite and finish my shift.',12,0,100,0,0,0, 'Engineer Burke upon LoS'),
|
||||
(27381,0,0, 'What is the meaning of this? Stop! I''ll double whatever they''re paying you!',12,0,100,0,0,0, 'Chancellor Amai before going hostile'),
|
||||
(27381,1,0, 'I just arrived in Venomspite. How could i have possibly wronged you?',12,0,100,0,0,0, 'Chancellor Amai upon Los');
|
||||
-- Conditions
|
||||
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup` IN (9507,9508,9509,9510);
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||
(15,9507,0,0,9,12245,0,0,0, '', 'Deathguard Schneider: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9507,1,0,9,12245,0,0,0, '', 'Deathguard Schneider: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9507,2,0,9,12245,0,0,0, '', 'Deathguard Schneider: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9507,3,0,9,12245,0,0,0, '', 'Deathguard Schneider: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9508,0,0,9,12245,0,0,0, '', 'Senior Scivener Barriga: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9508,1,0,9,12245,0,0,0, '', 'Senior Scivener Barriga: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9508,2,0,9,12245,0,0,0, '', 'Senior Scivener Barriga: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9508,3,0,9,12245,0,0,0, '', 'Senior Scivener Barriga: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9509,0,0,9,12245,0,0,0, '', 'Engineer Burke: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9509,1,0,9,12245,0,0,0, '', 'Engineer Burke: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9509,2,0,9,12245,0,0,0, '', 'Engineer Burke: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9509,3,0,9,12245,0,0,0, '', 'Engineer Burke: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9510,0,0,9,12245,0,0,0, '', 'Chancellor Amai: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9510,1,0,9,12245,0,0,0, '', 'Chancellor Amai: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9510,2,0,9,12245,0,0,0, '', 'Chancellor Amai: Show Gossip only if on quest "No Mercy for the Captured" '),
|
||||
(15,9510,3,0,9,12245,0,0,0, '', 'Chancellor Amai: Show Gossip only if on quest "No Mercy for the Captured" ');
|
||||
5
sql/updates/world/2013_01_26_05_world_misc_pinfo.sql
Normal file
5
sql/updates/world/2013_01_26_05_world_misc_pinfo.sql
Normal file
@@ -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';
|
||||
@@ -0,0 +1 @@
|
||||
UPDATE `creature_template` SET `equipment_id`=0 WHERE `entry`=1019;
|
||||
@@ -0,0 +1,3 @@
|
||||
DELETE FROM `gameobject_template` WHERE `entry`=175984;
|
||||
INSERT INTO `gameobject_template` (`entry`, `type`, `displayId`, `name`, `IconName`, `castBarCaption`, `unk1`, `data0`, `data1`, `data2`, `data3`, `data4`, `data5`, `data6`, `data7`, `data8`, `data9`, `data10`, `data11`, `data12`, `data13`, `data14`, `data15`, `data16`, `data17`, `data18`, `data19`, `data20`, `data21`, `data22`, `data23`, `size`, `questItem1`, `questItem2`, `questItem3`, `questItem4`, `questItem5`, `questItem6`, `WDBVerified`) VALUES
|
||||
(175984, 8, 216, 'Cauldron', '', '', '', 4, 10, 2061, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 15354);
|
||||
35
sql/updates/world/2013_01_27_00_world_creature.sql
Normal file
35
sql/updates/world/2013_01_27_00_world_creature.sql
Normal file
@@ -0,0 +1,35 @@
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=3094 AND source_type=0;
|
||||
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
|
||||
(3094,0,0,0,11,0,100,0,0,0,0,0,11,4986,2,0,0,0,0,1,0,0,0,0,0,0,0,'Unseen - On Respawn - Cast Unseen');
|
||||
-- Spawns for Unseen from Sniffs
|
||||
SET @GUID:=100173;
|
||||
DELETE FROM `creature` WHERE `id`=3094;
|
||||
INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`,`npcflag`,`unit_flags`,`dynamicflags`) VALUES
|
||||
(@GUID ,3094,0,1,1,0,0,-10694.8,345.662,44.4895,2.09338,300,0,0,2215,0,0,0,0,0),
|
||||
(@GUID+01,3094,0,1,1,0,0,-10702.9,360.152,39.7227,4.04982,300,0,0,2215,0,0,0,0,0),
|
||||
(@GUID+02,3094,0,1,1,0,0,-10707.4,314.112,40.1481,4.46221,300,0,0,2215,0,0,0,0,0),
|
||||
(@GUID+03,3094,0,1,1,0,0,-11096.8,-960.518,65.3837,0.650136,300,0,0,2292,0,0,0,0,0),
|
||||
(@GUID+04,3094,0,1,1,0,0,-10800.4,-655.44,41.3178,0.206699,300,0,0,2292,0,0,0,0,0),
|
||||
(@GUID+05,3094,0,1,1,0,0,-10782.8,-635.116,42.1594,2.53933,300,0,0,2138,0,0,0,0,0),
|
||||
(@GUID+06,3094,0,1,1,0,0,-10806.6,-616.345,40.0752,4.601,300,0,0,2138,0,0,0,0,0),
|
||||
(@GUID+07,3094,0,1,1,0,0,-10837.1,-573.623,36.5976,6.13188,300,0,0,2292,0,0,0,0,0),
|
||||
(@GUID+08,3094,0,1,1,0,0,-10823,-564.998,37.4107,1.71623,300,0,0,2138,0,0,0,0,0),
|
||||
(@GUID+10,3094,0,1,1,0,0,-10924,446.213,46.2609,5.96992,300,0,0,2138,0,0,0,0,0),
|
||||
(@GUID+11,3094,0,1,1,0,0,-10747.1,257.103,42.0292,1.18606,300,0,0,2215,0,0,0,0,0),
|
||||
(@GUID+12,3094,0,1,1,0,0,-10759.6,343.884,38.3282,5.24523,300,0,0,2138,0,0,0,0,0),
|
||||
(@GUID+13,3094,0,1,1,0,0,-10731.5,364.135,37.2459,4.06321,300,0,0,2138,0,0,0,0,0),
|
||||
(@GUID+14,3094,0,1,1,0,0,-10701.5,347.995,39.7227,3.22043,300,0,0,2215,0,0,0,0,0),
|
||||
(@GUID+15,3094,0,1,1,0,0,-10694.8,344.219,39.7097,2.706,300,0,0,2292,0,0,0,0,0),
|
||||
(@GUID+16,3094,0,1,1,0,0,-10715.6,263.155,43.9056,2.1562,300,0,0,2292,0,0,0,0,0),
|
||||
(@GUID+17,3094,0,1,1,0,0,-11091.8,-954.163,65.348,1.59261,300,0,0,2215,0,0,0,0,0),
|
||||
(@GUID+18,3094,0,1,1,0,0,-10937.8,-936.044,76.878,1.18113,300,0,0,2292,0,0,0,0,0),
|
||||
(@GUID+19,3094,0,1,1,0,0,-10964.1,-949.174,71.1917,2.08064,300,0,0,2292,0,0,0,0,0),
|
||||
(@GUID+20,3094,0,1,1,0,0,-10934.9,-928.656,72.1262,3.08437,300,0,0,2215,0,0,0,0,0),
|
||||
(@GUID+21,3094,0,1,1,0,0,-10929.6,-936.748,72.126,2.29741,300,0,0,2292,0,0,0,0,0),
|
||||
(@GUID+22,3094,0,1,1,0,0,-10798.5,-635.655,41.1281,1.31804,300,0,0,2292,0,0,0,0,0),
|
||||
(@GUID+23,3094,0,1,1,0,0,-10830.1,-616.585,38.7076,3.76848,300,0,0,2292,0,0,0,0,0),
|
||||
(@GUID+24,3094,0,1,1,0,0,-10677.6,314.27,33.6022,1.28606,300,0,0,2292,0,0,0,0,0),
|
||||
(@GUID+25,3094,0,1,1,0,0,-10684.3,314.55,40.7586,3.14353,300,0,0,2138,0,0,0,0,0),
|
||||
(@GUID+26,3094,0,1,1,0,0,-10368.7,-1258.33,35.9096,0.448286,300,0,0,2138,0,0,0,0,0),
|
||||
(@GUID+27,3094,0,1,1,0,0,-10347.4,-1287.13,35.3003,1.44967,300,0,0,2138,0,0,0,0,0),
|
||||
(@GUID+28,3094,0,1,1,0,0,-10368.6,-1290.02,35.303,0.263719,300,0,0,2292,0,0,0,0,0);
|
||||
@@ -0,0 +1,3 @@
|
||||
DELETE FROM `gameobject_template` WHERE `entry`=181073;
|
||||
INSERT INTO `gameobject_template` (`entry`, `type`, `displayId`, `name`, `IconName`, `castBarCaption`, `unk1`, `data0`, `data1`, `data2`, `data3`, `data4`, `data5`, `data6`, `data7`, `data8`, `data9`, `data10`, `data11`, `data12`, `data13`, `data14`, `data15`, `data16`, `data17`, `data18`, `data19`, `data20`, `data21`, `data22`, `data23`, `size`, `questItem1`, `questItem2`, `questItem3`, `questItem4`, `questItem5`, `questItem6`, `WDBVerified`) VALUES
|
||||
(181073, 2, 216, 'Fragrant Cauldron', '', '', '', 93, 7244, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 15211);
|
||||
8
sql/updates/world/2013_01_28_00_world_gameobject.sql
Normal file
8
sql/updates/world/2013_01_28_00_world_gameobject.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
-- Doors should be closed
|
||||
UPDATE `gameobject` SET `state`=1 WHERE `guid` IN (150074, 150073, 150077);
|
||||
|
||||
-- Duplicated Gameobject
|
||||
DELETE FROM `gameobject` WHERE `guid`=150081;
|
||||
|
||||
-- Fix loots
|
||||
UPDATE `gameobject_loot_template` SET `ChanceOrQuestChance`=-100 WHERE `entry` IN (27310, 27239);
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE `creature_template` DROP `trainer_spell`;
|
||||
@@ -0,0 +1,7 @@
|
||||
DELETE FROM `gameobject_loot_template` WHERE `entry`=24524 AND `item`=52676;
|
||||
INSERT INTO `gameobject_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES
|
||||
(24524,52676,100,1,0,1,1);
|
||||
|
||||
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=4 AND `SourceGroup`=24524 AND `SourceEntry`=52676;
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
|
||||
(4,24524,52676,0,0,1,0,72221,0,0,0,0,0,'','Loot Cache of the Ley-Guardian only when aura Luck of the Draw applied');
|
||||
@@ -0,0 +1,2 @@
|
||||
UPDATE `achievement_criteria_data` SET `value1`=2 WHERE `criteria_id`=12979 AND `type`=12;
|
||||
UPDATE `achievement_criteria_data` SET `value1`=1 WHERE `criteria_id`=12971 AND `type`=12;
|
||||
@@ -0,0 +1,9 @@
|
||||
UPDATE `gameobject_loot_template` SET `ChanceOrQuestChance`=-100 WHERE `entry`=27310 AND `item`=47035;
|
||||
UPDATE `gameobject_loot_template` SET `ChanceOrQuestChance`=-100 WHERE `entry`=27239 AND `item`=46364;
|
||||
UPDATE `gameobject_loot_template` SET `ChanceOrQuestChance`=-100 WHERE `entry`=24589 AND `item`=43697;
|
||||
UPDATE `gameobject_loot_template` SET `ChanceOrQuestChance`=-100 WHERE `entry`=26666 AND `item`=44319;
|
||||
UPDATE `gameobject_loot_template` SET `ChanceOrQuestChance`=-100 WHERE `entry`=26667 AND `item`=44320;
|
||||
UPDATE `gameobject_loot_template` SET `ChanceOrQuestChance`=-100 WHERE `entry`=26668 AND `item`=44321;
|
||||
UPDATE `gameobject_loot_template` SET `ChanceOrQuestChance`=-100 WHERE `entry`=26878 AND `item`=45062;
|
||||
UPDATE `gameobject_loot_template` SET `ChanceOrQuestChance`=-100 WHERE `entry`=27725 AND `item`=49648;
|
||||
UPDATE `gameobject_loot_template` SET `ChanceOrQuestChance`=-100 WHERE `entry`=27723 AND `item`=49678;
|
||||
@@ -0,0 +1,6 @@
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_warl_demon_soul', 'spell_warl_conflagrate', 'spell_warl_fel_flame');
|
||||
DELETE FROM `spell_script_names` WHERE `spell_id` IN (17962, 77799, 77801);
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(17962, 'spell_warl_conflagrate'),
|
||||
(77799, 'spell_warl_fel_flame'),
|
||||
(77801, 'spell_warl_demon_soul');
|
||||
1
sql/updates/world/2013_02_01_00_world_gameobject.sql
Normal file
1
sql/updates/world/2013_02_01_00_world_gameobject.sql
Normal file
@@ -0,0 +1 @@
|
||||
DELETE FROM `gameobject` WHERE `id`=180184;
|
||||
@@ -0,0 +1,12 @@
|
||||
-- loot for Prismatic Black Diamond
|
||||
DELETE FROM `spell_loot_template` WHERE `entry`=62941;
|
||||
INSERT INTO `spell_loot_template` (`entry`, `item`, `ChanceOrQuestChance`, `lootmode`, `groupid`, `mincountOrRef`, `maxcount`) VALUES
|
||||
(62941, 23094, 0, 1, 1, 1, 1),
|
||||
(62941, 23095, 0, 1, 1, 1, 1),
|
||||
(62941, 28595, 0, 1, 1, 1, 1),
|
||||
(62941, 23116, 0, 1, 1, 1, 1),
|
||||
(62941, 23118, 0, 1, 1, 1, 1),
|
||||
(62941, 23119, 0, 1, 1, 1, 1),
|
||||
(62941, 23120, 0, 1, 1, 1, 1),
|
||||
(62941, 23114, 0, 1, 1, 1, 1),
|
||||
(62941, 23115, 0, 1, 1, 1, 1);
|
||||
@@ -0,0 +1,4 @@
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_marrowgar_bone_slice';
|
||||
INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
|
||||
(69055,'spell_marrowgar_bone_slice'),
|
||||
(70814,'spell_marrowgar_bone_slice');
|
||||
2
sql/updates/world/2013_02_01_03_world_wdbverified.sql
Normal file
2
sql/updates/world/2013_02_01_03_world_wdbverified.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
UPDATE `npc_text` SET `WDBVerified`=1 WHERE `ID` IN (16777215, 31023);
|
||||
UPDATE `gameobject_template` SET `WDBVerified`=1 WHERE `entry` IN (401003, 300238, 300212, 300209, 300208, 300207, 300204, 300203, 300200, 300199, 300190, 300188, 300187, 300185, 300182, 300175, 300170, 300033);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user