Refactoring part 2 [W.I.P]

This commit is contained in:
Yehonal
2016-08-12 00:46:43 +02:00
parent a73ad5cd6e
commit b0c8eceb08
504 changed files with 19 additions and 35 deletions

View File

@@ -1,33 +0,0 @@
# Copyright (C)
#
# 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.
# Enforce compileparameters for corebuilds under GCC
# This to stop a few silly crashes that could have been avoided IF people
# weren't doing some -O3 psychooptimizations etc.
if(CMAKE_COMPILER_IS_GNUCXX AND NOT MINGW)
add_definitions(-fno-delete-null-pointer-checks)
endif()
if( SERVERS )
set(sources_windows_Debugging
${CMAKE_SOURCE_DIR}/modules/acore/framework/Debugging/WheatyExceptionReport.cpp
${CMAKE_SOURCE_DIR}/modules/acore/framework/Debugging/WheatyExceptionReport.h
)
add_subdirectory(game)
add_subdirectory(authserver)
add_subdirectory(scripts)
add_subdirectory(worldserver)
else()
if( TOOLS )
add_subdirectory(collision)
add_subdirectory(shared)
endif()
endif()

View File

@@ -1,81 +0,0 @@
/*
* Copyright (C) MaNGOS, TrinityCore, SunwellCore and AzerothCore
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AuthCodes.h"
#include <cstddef>
namespace AuthHelper
{
static RealmBuildInfo const PostBcAcceptedClientBuilds[] =
{
{15595, 4, 3, 4, ' '},
{14545, 4, 2, 2, ' '},
{13623, 4, 0, 6, 'a'},
{12340, 3, 3, 5, 'a'},
{11723, 3, 3, 3, 'a'},
{11403, 3, 3, 2, ' '},
{11159, 3, 3, 0, 'a'},
{10505, 3, 2, 2, 'a'},
{9947, 3, 1, 3, ' '},
{8606, 2, 4, 3, ' '},
{0, 0, 0, 0, ' '} // terminator
};
static RealmBuildInfo const PreBcAcceptedClientBuilds[] =
{
{6141, 1, 12, 3, ' '},
{6005, 1, 12, 2, ' '},
{5875, 1, 12, 1, ' '},
{0, 0, 0, 0, ' '} // terminator
};
bool IsPreBCAcceptedClientBuild(int build)
{
for (int i = 0; PreBcAcceptedClientBuilds[i].Build; ++i)
if (PreBcAcceptedClientBuilds[i].Build == build)
return true;
return false;
}
bool IsPostBCAcceptedClientBuild(int build)
{
for (int i = 0; PostBcAcceptedClientBuilds[i].Build; ++i)
if (PostBcAcceptedClientBuilds[i].Build == build)
return true;
return false;
}
bool IsAcceptedClientBuild(int build)
{
return (IsPostBCAcceptedClientBuild(build) || IsPreBCAcceptedClientBuild(build));
}
RealmBuildInfo const* GetBuildInfo(int build)
{
for (int i = 0; PostBcAcceptedClientBuilds[i].Build; ++i)
if (PostBcAcceptedClientBuilds[i].Build == build)
return &PostBcAcceptedClientBuilds[i];
for (int i = 0; PreBcAcceptedClientBuilds[i].Build; ++i)
if (PreBcAcceptedClientBuilds[i].Build == build)
return &PreBcAcceptedClientBuilds[i];
return NULL;
}
};

View File

@@ -1,97 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _AUTHCODES_H
#define _AUTHCODES_H
enum AuthResult
{
WOW_SUCCESS = 0x00,
WOW_FAIL_BANNED = 0x03,
WOW_FAIL_UNKNOWN_ACCOUNT = 0x04,
WOW_FAIL_INCORRECT_PASSWORD = 0x05,
WOW_FAIL_ALREADY_ONLINE = 0x06,
WOW_FAIL_NO_TIME = 0x07,
WOW_FAIL_DB_BUSY = 0x08,
WOW_FAIL_VERSION_INVALID = 0x09,
WOW_FAIL_VERSION_UPDATE = 0x0A,
WOW_FAIL_INVALID_SERVER = 0x0B,
WOW_FAIL_SUSPENDED = 0x0C,
WOW_FAIL_FAIL_NOACCESS = 0x0D,
WOW_SUCCESS_SURVEY = 0x0E,
WOW_FAIL_PARENTCONTROL = 0x0F,
WOW_FAIL_LOCKED_ENFORCED = 0x10,
WOW_FAIL_TRIAL_ENDED = 0x11,
WOW_FAIL_USE_BATTLENET = 0x12,
WOW_FAIL_ANTI_INDULGENCE = 0x13,
WOW_FAIL_EXPIRED = 0x14,
WOW_FAIL_NO_GAME_ACCOUNT = 0x15,
WOW_FAIL_CHARGEBACK = 0x16,
WOW_FAIL_INTERNET_GAME_ROOM_WITHOUT_BNET = 0x17,
WOW_FAIL_GAME_ACCOUNT_LOCKED = 0x18,
WOW_FAIL_UNLOCKABLE_LOCK = 0x19,
WOW_FAIL_CONVERSION_REQUIRED = 0x20,
WOW_FAIL_DISCONNECTED = 0xFF
};
enum LoginResult
{
LOGIN_OK = 0x00,
LOGIN_FAILED = 0x01,
LOGIN_FAILED2 = 0x02,
LOGIN_BANNED = 0x03,
LOGIN_UNKNOWN_ACCOUNT = 0x04,
LOGIN_UNKNOWN_ACCOUNT3 = 0x05,
LOGIN_ALREADYONLINE = 0x06,
LOGIN_NOTIME = 0x07,
LOGIN_DBBUSY = 0x08,
LOGIN_BADVERSION = 0x09,
LOGIN_DOWNLOAD_FILE = 0x0A,
LOGIN_FAILED3 = 0x0B,
LOGIN_SUSPENDED = 0x0C,
LOGIN_FAILED4 = 0x0D,
LOGIN_CONNECTED = 0x0E,
LOGIN_PARENTALCONTROL = 0x0F,
LOGIN_LOCKED_ENFORCED = 0x10
};
enum ExpansionFlags
{
POST_BC_EXP_FLAG = 0x2,
PRE_BC_EXP_FLAG = 0x1,
NO_VALID_EXP_FLAG = 0x0
};
struct RealmBuildInfo
{
int Build;
int MajorVersion;
int MinorVersion;
int BugfixVersion;
int HotfixVersion;
};
namespace AuthHelper
{
RealmBuildInfo const* GetBuildInfo(int build);
bool IsAcceptedClientBuild(int build);
bool IsPostBCAcceptedClientBuild(int build);
bool IsPreBCAcceptedClientBuild(int build);
};
#endif

View File

@@ -1,112 +0,0 @@
# Copyright (C)
#
# 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.
########### authserver ###############
file(GLOB_RECURSE sources_authentication Authentication/*.cpp Authentication/*.h)
file(GLOB_RECURSE sources_realms Realms/*.cpp Realms/*.h)
file(GLOB_RECURSE sources_server Server/*.cpp Server/*.h)
file(GLOB sources_localdir *.cpp *.h)
if (USE_COREPCH)
set(authserver_PCH_HDR PrecompiledHeaders/authPCH.h)
set(authserver_PCH_SRC PrecompiledHeaders/authPCH.cpp)
endif()
set(authserver_SRCS
${authserver_SRCS}
${sources_authentication}
${sources_realms}
${sources_server}
${sources_localdir}
)
if( WIN32 )
set(authserver_SRCS
${authserver_SRCS}
${sources_windows_Debugging}
)
if ( MSVC )
set(authserver_SRCS
${authserver_SRCS}
authserver.rc
)
endif ()
endif()
include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/modules/acore/framework
${CMAKE_SOURCE_DIR}/modules/acore/framework/Database
${CMAKE_SOURCE_DIR}/modules/acore/framework/Debugging
${CMAKE_SOURCE_DIR}/modules/acore/framework/Packets
${CMAKE_SOURCE_DIR}/modules/acore/framework/Cryptography
${CMAKE_SOURCE_DIR}/modules/acore/framework/Cryptography/Authentication
${CMAKE_SOURCE_DIR}/modules/acore/framework/Logging
${CMAKE_SOURCE_DIR}/modules/acore/framework/Threading
${CMAKE_SOURCE_DIR}/modules/acore/framework/Utilities
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Authentication
${CMAKE_CURRENT_SOURCE_DIR}/Realms
${CMAKE_CURRENT_SOURCE_DIR}/Server
${ACE_INCLUDE_DIR}
${MYSQL_INCLUDE_DIR}
${OPENSSL_INCLUDE_DIR}
)
add_executable(authserver
${authserver_SRCS}
${authserver_PCH_SRC}
)
add_dependencies(authserver revision.h)
if( NOT WIN32 )
set_target_properties(authserver PROPERTIES
COMPILE_DEFINITIONS _TRINITY_REALM_CONFIG="${CONF_DIR}/authserver.conf"
)
endif()
target_link_libraries(authserver
shared
${MYSQL_LIBRARY}
${OPENSSL_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${ACE_LIBRARY}
)
if( WIN32 )
if ( MSVC )
add_custom_command(TARGET authserver
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/authserver.conf.dist ${CMAKE_BINARY_DIR}/bin/$(ConfigurationName)/
)
elseif ( MINGW )
add_custom_command(TARGET authserver
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/authserver.conf.dist ${CMAKE_BINARY_DIR}/bin/
)
endif()
endif()
if( UNIX )
install(TARGETS authserver DESTINATION bin)
elseif( WIN32 )
install(TARGETS authserver DESTINATION "${CMAKE_INSTALL_PREFIX}")
endif()
install(FILES authserver.conf.dist DESTINATION ${CONF_DIR})
# Generate precompiled header
if (USE_COREPCH)
add_cxx_pch(authserver ${authserver_PCH_HDR} ${authserver_PCH_SRC})
endif()
CU_RUN_HOOK("AFTER_AUTHSERVER_CMAKE")

View File

@@ -1,354 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file main.cpp
* @brief Authentication Server main program
*
* This file contains the main program for the
* authentication server
*/
#include <ace/Dev_Poll_Reactor.h>
#include <ace/TP_Reactor.h>
#include <ace/ACE.h>
#include <ace/Sig_Handler.h>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#include "Common.h"
#include "Database/DatabaseEnv.h"
#include "Configuration/Config.h"
#include "Log.h"
#include "SystemConfig.h"
#include "Util.h"
#include "SignalHandler.h"
#include "RealmList.h"
#include "RealmAcceptor.h"
#ifdef __linux__
#include <sched.h>
#include <sys/resource.h>
#define PROCESS_HIGH_PRIORITY -15 // [-20, 19], default is 0
#endif
#ifndef _TRINITY_REALM_CONFIG
# define _TRINITY_REALM_CONFIG "authserver.conf"
#endif
bool StartDB();
void StopDB();
bool stopEvent = false; // Setting it to true stops the server
LoginDatabaseWorkerPool LoginDatabase; // Accessor to the authserver database
/// Handle authserver's termination signals
class AuthServerSignalHandler : public Trinity::SignalHandler
{
public:
virtual void HandleSignal(int sigNum)
{
switch (sigNum)
{
case SIGINT:
case SIGTERM:
stopEvent = true;
break;
}
}
};
/// Print out the usage string for this program on the console.
void usage(const char* prog)
{
sLog->outString("Usage: \n %s [<options>]\n"
" -c config_file use config_file as configuration file\n\r",
prog);
}
/// Launch the auth server
extern int main(int argc, char** argv)
{
// Command line parsing to get the configuration file name
char const* configFile = _TRINITY_REALM_CONFIG;
int count = 1;
while (count < argc)
{
if (strcmp(argv[count], "-c") == 0)
{
if (++count >= argc)
{
printf("Runtime-Error: -c option requires an input argument\n");
usage(argv[0]);
return 1;
}
else
configFile = argv[count];
}
++count;
}
std::string cfg_def_file=_TRINITY_REALM_CONFIG;
cfg_def_file += ".dist";
if (!sConfigMgr->LoadInitial(cfg_def_file.c_str())) {
printf("Invalid or missing default configuration file : %s\n", cfg_def_file.c_str());
return 1;
}
if (!sConfigMgr->LoadMore(configFile))
{
printf("Invalid or missing configuration file : %s\n", configFile);
printf("Verify that the file exists and has \'[authserver]\' written in the top of the file!\n");
return 1;
}
sLog->outString("%s (authserver)", _FULLVERSION);
sLog->outString("<Ctrl-C> to stop.\n");
sLog->outString(" █████╗ ███████╗███████╗██████╗ ██████╗ ████████╗██╗ ██╗");
sLog->outString(" ██╔══██╗╚══███╔╝██╔════╝██╔══██╗██╔═══██╗╚══██╔══╝██║ ██║");
sLog->outString(" ███████║ ███╔╝ █████╗ ██████╔╝██║ ██║ ██║ ███████║");
sLog->outString(" ██╔══██║ ███╔╝ ██╔══╝ ██╔══██╗██║ ██║ ██║ ██╔══██║");
sLog->outString(" ██║ ██║███████╗███████╗██║ ██║╚██████╔╝ ██║ ██║ ██║");
sLog->outString(" ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝");
sLog->outString(" ██████╗ ██████╗ ██████╗ ███████╗");
sLog->outString(" ██╔════╝██╔═══██╗██╔══██╗██╔════╝");
sLog->outString(" ██║ ██║ ██║██████╔╝█████╗");
sLog->outString(" ██║ ██║ ██║██╔══██╗██╔══╝");
sLog->outString(" ╚██████╗╚██████╔╝██║ ██║███████╗");
sLog->outString(" ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝\n");
sLog->outString(" AzerothCore 3.3.5a - www.azerothcore.org\n");
sLog->outString("Using configuration file %s.", configFile);
sLog->outDetail("%s (Library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
#if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL)
ACE_Reactor::instance(new ACE_Reactor(new ACE_Dev_Poll_Reactor(ACE::max_handles(), 1), 1), true);
#else
ACE_Reactor::instance(new ACE_Reactor(new ACE_TP_Reactor(), true), true);
#endif
sLog->outBasic("Max allowed open files is %d", ACE::max_handles());
// authserver PID file creation
std::string pidFile = sConfigMgr->GetStringDefault("PidFile", "");
if (!pidFile.empty())
{
if (uint32 pid = CreatePIDFile(pidFile))
sLog->outError("Daemon PID: %u\n", pid);
else
{
sLog->outError("Cannot create PID file %s.\n", pidFile.c_str());
return 1;
}
}
// Initialize the database connection
if (!StartDB())
return 1;
// Initialize the log database
sLog->SetLogDB(false);
sLog->SetRealmID(0); // ensure we've set realm to 0 (authserver realmid)
// Get the list of realms for the server
sRealmList->Initialize(sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 20));
if (sRealmList->size() == 0)
{
sLog->outError("No valid realms specified.");
return 1;
}
// Launch the listening network socket
RealmAcceptor acceptor;
int32 rmport = sConfigMgr->GetIntDefault("RealmServerPort", 3724);
if (rmport < 0 || rmport > 0xFFFF)
{
sLog->outError("Specified port out of allowed range (1-65535)");
return 1;
}
std::string bind_ip = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0");
ACE_INET_Addr bind_addr(uint16(rmport), bind_ip.c_str());
if (acceptor.open(bind_addr, ACE_Reactor::instance(), ACE_NONBLOCK) == -1)
{
sLog->outError("Auth server can not bind to %s:%d", bind_ip.c_str(), rmport);
return 1;
}
// Initialize the signal handlers
AuthServerSignalHandler SignalINT, SignalTERM;
// Register authservers's signal handlers
ACE_Sig_Handler Handler;
Handler.register_handler(SIGINT, &SignalINT);
Handler.register_handler(SIGTERM, &SignalTERM);
#if defined(_WIN32) || defined(__linux__)
///- Handle affinity for multiple processors and process priority
uint32 affinity = sConfigMgr->GetIntDefault("UseProcessors", 0);
bool highPriority = sConfigMgr->GetBoolDefault("ProcessPriority", false);
#ifdef _WIN32 // Windows
HANDLE hProcess = GetCurrentProcess();
if (affinity > 0)
{
ULONG_PTR appAff;
ULONG_PTR sysAff;
if (GetProcessAffinityMask(hProcess, &appAff, &sysAff))
{
// remove non accessible processors
ULONG_PTR currentAffinity = affinity & appAff;
if (!currentAffinity)
sLog->outError("server.authserver", "Processors marked in UseProcessors bitmask (hex) %x are not accessible for the authserver. Accessible processors bitmask (hex): %x", affinity, appAff);
else if (SetProcessAffinityMask(hProcess, currentAffinity))
sLog->outString("server.authserver", "Using processors (bitmask, hex): %x", currentAffinity);
else
sLog->outError("server.authserver", "Can't set used processors (hex): %x", currentAffinity);
}
}
if (highPriority)
{
if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS))
sLog->outString("server.authserver", "authserver process priority class set to HIGH");
else
sLog->outError("server.authserver", "Can't set authserver process priority class.");
}
#else // Linux
if (affinity > 0)
{
cpu_set_t mask;
CPU_ZERO(&mask);
for (unsigned int i = 0; i < sizeof(affinity) * 8; ++i)
if (affinity & (1 << i))
CPU_SET(i, &mask);
if (sched_setaffinity(0, sizeof(mask), &mask))
sLog->outError("server.authserver", "Can't set used processors (hex): %x, error: %s", affinity, strerror(errno));
else
{
CPU_ZERO(&mask);
sched_getaffinity(0, sizeof(mask), &mask);
sLog->outString("server.authserver", "Using processors (bitmask, hex): %lx", *(__cpu_mask*)(&mask));
}
}
if (highPriority)
{
if (setpriority(PRIO_PROCESS, 0, PROCESS_HIGH_PRIORITY))
sLog->outError("server.authserver", "Can't set authserver process priority class, error: %s", strerror(errno));
else
sLog->outString("server.authserver", "authserver process priority class set to %i", getpriority(PRIO_PROCESS, 0));
}
#endif
#endif
// maximum counter for next ping
uint32 numLoops = (sConfigMgr->GetIntDefault("MaxPingTime", 30) * (MINUTE * 1000000 / 100000));
uint32 loopCounter = 0;
// possibly enable db logging; avoid massive startup spam by doing it here.
if (sConfigMgr->GetBoolDefault("EnableLogDB", false))
{
sLog->outString("Enabling database logging...");
sLog->SetLogDB(true);
}
// Wait for termination signal
while (!stopEvent)
{
// dont move this outside the loop, the reactor will modify it
ACE_Time_Value interval(0, 100000);
if (ACE_Reactor::instance()->run_reactor_event_loop(interval) == -1)
break;
if ((++loopCounter) == numLoops)
{
loopCounter = 0;
sLog->outDetail("Ping MySQL to keep connection alive");
LoginDatabase.KeepAlive();
}
}
// Close the Database Pool and library
StopDB();
sLog->outString("Halting process...");
return 0;
}
/// Initialize connection to the database
bool StartDB()
{
MySQL::Library_Init();
std::string dbstring = sConfigMgr->GetStringDefault("LoginDatabaseInfo", "");
if (dbstring.empty())
{
sLog->outError("Database not specified");
return false;
}
int32 worker_threads = sConfigMgr->GetIntDefault("LoginDatabase.WorkerThreads", 1);
if (worker_threads < 1 || worker_threads > 32)
{
sLog->outError("Improper value specified for LoginDatabase.WorkerThreads, defaulting to 1.");
worker_threads = 1;
}
int32 synch_threads = sConfigMgr->GetIntDefault("LoginDatabase.SynchThreads", 1);
if (synch_threads < 1 || synch_threads > 32)
{
sLog->outError("Improper value specified for LoginDatabase.SynchThreads, defaulting to 1.");
synch_threads = 1;
}
// NOTE: While authserver is singlethreaded you should keep synch_threads == 1. Increasing it is just silly since only 1 will be used ever.
if (!LoginDatabase.Open(dbstring.c_str(), uint8(worker_threads), uint8(synch_threads)))
{
sLog->outError("Cannot connect to database");
return false;
}
sLog->outString("Started auth database connection pool.");
return true;
}
/// Close the connection to the database
void StopDB()
{
LoginDatabase.Close();
MySQL::Library_End();
}

View File

@@ -1 +0,0 @@
#include "authPCH.h"

View File

@@ -1,6 +0,0 @@
#include "Configuration/Config.h"
#include "Database/DatabaseEnv.h"
#include "Log.h"
#include "RealmList.h"
#include "RealmSocket.h"
#include "Common.h"

View File

@@ -1,106 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Common.h"
#include "RealmList.h"
#include "Database/DatabaseEnv.h"
RealmList::RealmList() : m_UpdateInterval(0), m_NextUpdateTime(time(NULL)) { }
// Load the realm list from the database
void RealmList::Initialize(uint32 updateInterval)
{
m_UpdateInterval = updateInterval;
// Get the content of the realmlist table in the database
UpdateRealms(true);
}
void RealmList::UpdateRealm(uint32 id, const std::string& name, ACE_INET_Addr const& address, ACE_INET_Addr const& localAddr, ACE_INET_Addr const& localSubmask, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build)
{
// Create new if not exist or update existed
Realm& realm = m_realms[name];
realm.m_ID = id;
realm.name = name;
realm.icon = icon;
realm.flag = flag;
realm.timezone = timezone;
realm.allowedSecurityLevel = allowedSecurityLevel;
realm.populationLevel = popu;
// Append port to IP address.
realm.ExternalAddress = address;
realm.LocalAddress = localAddr;
realm.LocalSubnetMask = localSubmask;
realm.gamebuild = build;
}
void RealmList::UpdateIfNeed()
{
// maybe disabled or updated recently
if (!m_UpdateInterval || m_NextUpdateTime > time(NULL))
return;
m_NextUpdateTime = time(NULL) + m_UpdateInterval;
// Clears Realm list
m_realms.clear();
// Get the content of the realmlist table in the database
UpdateRealms();
}
void RealmList::UpdateRealms(bool init)
{
sLog->outString("Updating Realm List...");
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST);
PreparedQueryResult result = LoginDatabase.Query(stmt);
// Circle through results and add them to the realm map
if (result)
{
do
{
Field* fields = result->Fetch();
uint32 realmId = fields[0].GetUInt32();
std::string name = fields[1].GetString();
std::string externalAddress = fields[2].GetString();
std::string localAddress = fields[3].GetString();
std::string localSubmask = fields[4].GetString();
uint16 port = fields[5].GetUInt16();
uint8 icon = fields[6].GetUInt8();
RealmFlags flag = RealmFlags(fields[7].GetUInt8());
uint8 timezone = fields[8].GetUInt8();
uint8 allowedSecurityLevel = fields[9].GetUInt8();
float pop = fields[10].GetFloat();
uint32 build = fields[11].GetUInt32();
ACE_INET_Addr externalAddr(port, externalAddress.c_str(), AF_INET);
ACE_INET_Addr localAddr(port, localAddress.c_str(), AF_INET);
ACE_INET_Addr submask(0, localSubmask.c_str(), AF_INET);
UpdateRealm(realmId, name, externalAddr, localAddr, submask, icon, flag, timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build);
if (init)
sLog->outString("Added realm \"%s\" at %s:%u.", name.c_str(), m_realms[name].ExternalAddress.get_host_addr(), port);
}
while (result->NextRow());
}
}

View File

@@ -1,85 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _REALMLIST_H
#define _REALMLIST_H
#include <ace/Singleton.h>
#include <ace/Null_Mutex.h>
#include <ace/INET_Addr.h>
#include "Common.h"
enum RealmFlags
{
REALM_FLAG_NONE = 0x00,
REALM_FLAG_INVALID = 0x01,
REALM_FLAG_OFFLINE = 0x02,
REALM_FLAG_SPECIFYBUILD = 0x04,
REALM_FLAG_UNK1 = 0x08,
REALM_FLAG_UNK2 = 0x10,
REALM_FLAG_RECOMMENDED = 0x20,
REALM_FLAG_NEW = 0x40,
REALM_FLAG_FULL = 0x80
};
// Storage object for a realm
struct Realm
{
ACE_INET_Addr ExternalAddress;
ACE_INET_Addr LocalAddress;
ACE_INET_Addr LocalSubnetMask;
std::string name;
uint8 icon;
RealmFlags flag;
uint8 timezone;
uint32 m_ID;
AccountTypes allowedSecurityLevel;
float populationLevel;
uint32 gamebuild;
};
/// Storage object for the list of realms on the server
class RealmList
{
public:
typedef std::map<std::string, Realm> RealmMap;
RealmList();
~RealmList() { }
void Initialize(uint32 updateInterval);
void UpdateIfNeed();
void AddRealm(const Realm& NewRealm) { m_realms[NewRealm.name] = NewRealm; }
RealmMap::const_iterator begin() const { return m_realms.begin(); }
RealmMap::const_iterator end() const { return m_realms.end(); }
uint32 size() const { return m_realms.size(); }
private:
void UpdateRealms(bool init=false);
void UpdateRealm(uint32 id, const std::string& name, ACE_INET_Addr const& address, ACE_INET_Addr const& localAddr, ACE_INET_Addr const& localSubmask, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build);
RealmMap m_realms;
uint32 m_UpdateInterval;
time_t m_NextUpdateTime;
};
#define sRealmList ACE_Singleton<RealmList, ACE_Null_Mutex>::instance()
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,82 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _AUTHSOCKET_H
#define _AUTHSOCKET_H
#include "Common.h"
#include "BigNumber.h"
#include "RealmSocket.h"
class ACE_INET_Addr;
struct Realm;
// Handle login commands
class AuthSocket: public RealmSocket::Session
{
public:
const static int s_BYTE_SIZE = 32;
AuthSocket(RealmSocket& socket);
virtual ~AuthSocket(void);
virtual void OnRead(void);
virtual void OnAccept(void);
virtual void OnClose(void);
static ACE_INET_Addr const& GetAddressForClient(Realm const& realm, ACE_INET_Addr const& clientAddr);
bool _HandleLogonChallenge();
bool _HandleLogonProof();
bool _HandleReconnectChallenge();
bool _HandleReconnectProof();
bool _HandleRealmList();
//data transfer handle for patch
bool _HandleXferResume();
bool _HandleXferCancel();
bool _HandleXferAccept();
void _SetVSFields(const std::string& rI);
FILE* pPatch;
ACE_Thread_Mutex patcherLock;
private:
RealmSocket& socket_;
RealmSocket& socket(void) { return socket_; }
BigNumber N, s, g, v;
BigNumber b, B;
BigNumber K;
BigNumber _reconnectProof;
bool _authed;
std::string _login;
// Since GetLocaleByName() is _NOT_ bijective, we have to store the locale as a string. Otherwise we can't differ
// between enUS and enGB, which is important for the patch system
std::string _localizationName;
std::string _os;
uint16 _build;
uint8 _expversion;
AccountTypes _accountSecurityLevel;
};
#endif

View File

@@ -1,70 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __REALMACCEPTOR_H__
#define __REALMACCEPTOR_H__
#include <ace/Acceptor.h>
#include <ace/SOCK_Acceptor.h>
#include "RealmSocket.h"
#include "AuthSocket.h"
class RealmAcceptor : public ACE_Acceptor<RealmSocket, ACE_SOCK_Acceptor>
{
public:
RealmAcceptor(void) { }
virtual ~RealmAcceptor(void)
{
if (reactor())
reactor()->cancel_timer(this, 1);
}
protected:
virtual int make_svc_handler(RealmSocket* &sh)
{
if (sh == 0)
ACE_NEW_RETURN(sh, RealmSocket, -1);
sh->reactor(reactor());
sh->set_session(new AuthSocket(*sh));
return 0;
}
virtual int handle_timeout(const ACE_Time_Value& /*current_time*/, const void* /*act = 0*/)
{
sLog->outBasic("Resuming acceptor");
reactor()->cancel_timer(this, 1);
return reactor()->register_handler(this, ACE_Event_Handler::ACCEPT_MASK);
}
virtual int handle_accept_error(void)
{
#if defined(ENFILE) && defined(EMFILE)
if (errno == ENFILE || errno == EMFILE)
{
sLog->outError("Out of file descriptors, suspending incoming connections for 10 seconds");
reactor()->remove_handler(this, ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);
reactor()->schedule_timer(this, NULL, ACE_Time_Value(10));
}
#endif
return 0;
}
};
#endif

View File

@@ -1,291 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ace/OS_NS_string.h>
#include <ace/INET_Addr.h>
#include <ace/SString.h>
#include "RealmSocket.h"
#include "Log.h"
RealmSocket::Session::Session(void) { }
RealmSocket::Session::~Session(void) { }
RealmSocket::RealmSocket(void) :
input_buffer_(4096), session_(NULL),
_remoteAddress(), _remotePort(0)
{
reference_counting_policy().value(ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
msg_queue()->high_water_mark(8 * 1024 * 1024);
msg_queue()->low_water_mark(8 * 1024 * 1024);
}
RealmSocket::~RealmSocket(void)
{
if (msg_queue())
msg_queue()->close();
// delete RealmSocketObject must never be called from our code.
closing_ = true;
delete session_;
peer().close();
}
int RealmSocket::open(void * arg)
{
ACE_INET_Addr addr;
if (peer().get_remote_addr(addr) == -1)
{
sLog->outError("Error %s while opening realm socket!", ACE_OS::strerror(errno));
return -1;
}
_remoteAddress = addr.get_host_addr();
_remotePort = addr.get_port_number();
// Register with ACE Reactor
if (Base::open(arg) == -1)
return -1;
if (session_)
session_->OnAccept();
// reactor takes care of the socket from now on
remove_reference();
return 0;
}
int RealmSocket::close(u_long)
{
shutdown();
closing_ = true;
remove_reference();
return 0;
}
const std::string& RealmSocket::getRemoteAddress(void) const
{
return _remoteAddress;
}
uint16 RealmSocket::getRemotePort(void) const
{
return _remotePort;
}
size_t RealmSocket::recv_len(void) const
{
return input_buffer_.length();
}
bool RealmSocket::recv_soft(char *buf, size_t len)
{
if (input_buffer_.length() < len)
return false;
ACE_OS::memcpy(buf, input_buffer_.rd_ptr(), len);
return true;
}
bool RealmSocket::recv(char *buf, size_t len)
{
bool ret = recv_soft(buf, len);
if (ret)
recv_skip(len);
return ret;
}
void RealmSocket::recv_skip(size_t len)
{
input_buffer_.rd_ptr(len);
}
ssize_t RealmSocket::noblk_send(ACE_Message_Block &message_block)
{
const size_t len = message_block.length();
if (len == 0)
return -1;
// Try to send the message directly.
#ifdef MSG_NOSIGNAL
ssize_t n = peer().send(message_block.rd_ptr(), len, MSG_NOSIGNAL);
#else
ssize_t n = peer().send(message_block.rd_ptr(), len);
#endif // MSG_NOSIGNAL
if (n < 0)
{
if (errno == EWOULDBLOCK) // Blocking signal
return 0;
else // Error happened
return -1;
}
else if (n == 0)
{
// Can this happen ?
return -1;
}
// return bytes transmitted
return n;
}
bool RealmSocket::send(const char *buf, size_t len)
{
if (buf == NULL || len == 0)
return true;
ACE_Data_Block db(len, ACE_Message_Block::MB_DATA, (const char*)buf, 0, 0, ACE_Message_Block::DONT_DELETE, 0);
ACE_Message_Block message_block(&db, ACE_Message_Block::DONT_DELETE, 0);
message_block.wr_ptr(len);
if (msg_queue()->is_empty())
{
// Try to send it directly.
ssize_t n = noblk_send(message_block);
if (n < 0)
return false;
size_t un = size_t(n);
if (un == len)
return true;
// fall down
message_block.rd_ptr(un);
}
ACE_Message_Block* mb = message_block.clone();
if (msg_queue()->enqueue_tail(mb, (ACE_Time_Value *)(&ACE_Time_Value::zero)) == -1)
{
mb->release();
return false;
}
if (reactor()->schedule_wakeup(this, ACE_Event_Handler::WRITE_MASK) == -1)
return false;
return true;
}
int RealmSocket::handle_output(ACE_HANDLE)
{
if (closing_)
return -1;
ACE_Message_Block* mb = 0;
if (msg_queue()->is_empty())
{
reactor()->cancel_wakeup(this, ACE_Event_Handler::WRITE_MASK);
return 0;
}
if (msg_queue()->dequeue_head(mb, (ACE_Time_Value *)(&ACE_Time_Value::zero)) == -1)
return -1;
ssize_t n = noblk_send(*mb);
if (n < 0)
{
mb->release();
return -1;
}
else if (size_t(n) == mb->length())
{
mb->release();
return 1;
}
else
{
mb->rd_ptr(n);
if (msg_queue()->enqueue_head(mb, (ACE_Time_Value *) &ACE_Time_Value::zero) == -1)
{
mb->release();
return -1;
}
return 0;
}
ACE_NOTREACHED(return -1);
}
int RealmSocket::handle_close(ACE_HANDLE h, ACE_Reactor_Mask)
{
// As opposed to WorldSocket::handle_close, we don't need locks here.
closing_ = true;
if (h == ACE_INVALID_HANDLE)
peer().close_writer();
if (session_)
session_->OnClose();
reactor()->remove_handler(this, ACE_Event_Handler::DONT_CALL | ACE_Event_Handler::ALL_EVENTS_MASK);
return 0;
}
int RealmSocket::handle_input(ACE_HANDLE)
{
if (closing_)
return -1;
const ssize_t space = input_buffer_.space();
ssize_t n = peer().recv(input_buffer_.wr_ptr(), space);
if (n < 0)
return errno == EWOULDBLOCK ? 0 : -1;
else if (n == 0) // EOF
return -1;
input_buffer_.wr_ptr((size_t)n);
if (session_ != NULL)
{
session_->OnRead();
input_buffer_.crunch();
}
// return 1 in case there is more data to read from OS
return n == space ? 1 : 0;
}
void RealmSocket::set_session(Session* session)
{
delete session_;
session_ = session;
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __REALMSOCKET_H__
#define __REALMSOCKET_H__
#include <ace/Synch_Traits.h>
#include <ace/Svc_Handler.h>
#include <ace/SOCK_Stream.h>
#include <ace/Message_Block.h>
#include <ace/Basic_Types.h>
#include "Common.h"
class RealmSocket : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
{
private:
typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> Base;
public:
class Session
{
public:
Session(void);
virtual ~Session(void);
virtual void OnRead(void) = 0;
virtual void OnAccept(void) = 0;
virtual void OnClose(void) = 0;
};
RealmSocket(void);
virtual ~RealmSocket(void);
size_t recv_len(void) const;
bool recv_soft(char *buf, size_t len);
bool recv(char *buf, size_t len);
void recv_skip(size_t len);
bool send(const char *buf, size_t len);
const std::string& getRemoteAddress(void) const;
uint16 getRemotePort(void) const;
virtual int open(void *);
virtual int close(u_long);
virtual int handle_input(ACE_HANDLE = ACE_INVALID_HANDLE);
virtual int handle_output(ACE_HANDLE = ACE_INVALID_HANDLE);
virtual int handle_close(ACE_HANDLE = ACE_INVALID_HANDLE, ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
void set_session(Session* session);
private:
ssize_t noblk_send(ACE_Message_Block &message_block);
ACE_Message_Block input_buffer_;
Session* session_;
std::string _remoteAddress;
uint16 _remotePort;
};
#endif /* __REALMSOCKET_H__ */

Binary file not shown.

View File

@@ -1,260 +0,0 @@
###############################################
# Trinity Core Auth Server configuration file #
###############################################
[authserver]
###################################################################################################
# SECTION INDEX
#
# EXAMPLE CONFIG
# AUTH SERVER SETTINGS
# MYSQL SETTINGS
#
###################################################################################################
###################################################################################################
# EXAMPLE CONFIG
#
# Variable
# Description: Brief description what the variable is doing.
# Important: Annotation for important things about this variable.
# Example: "Example, i.e. if the value is a string"
# Default: 10 - (Enabled|Comment|Variable name in case of grouped config options)
# 0 - (Disabled|Comment|Variable name in case of grouped config options)
#
# Note to developers:
# - Copy this example to keep the formatting.
# - Line breaks should be at column 100.
###################################################################################################
###################################################################################################
# AUTH SERVER SETTINGS
#
# LogsDir
# Description: Logs directory setting.
# Important: LogsDir needs to be quoted, as the string might contain space characters.
# Logs directory must exists, or log file creation will be disabled.
# Default: "" - (Log files will be stored in the current path)
LogsDir = ""
#
# MaxPingTime
# Description: Time (in minutes) between database pings.
# Default: 30
MaxPingTime = 30
#
# RealmServerPort
# Description: TCP port to reach the auth server.
# Default: 3724
RealmServerPort = 3724
#
#
# BindIP
# Description: Bind auth server to IP/hostname
# Default: "0.0.0.0" - (Bind to all IPs on the system)
BindIP = "0.0.0.0"
#
# PidFile
# Description: Auth server PID file.
# Example: "./authserver.pid" - (Enabled)
# Default: "" - (Disabled)
PidFile = ""
#
# LogLevel
# Description: Server console level of logging
# Default: 0 - (Minimum)
# 1 - (Basic)
# 2 - (Detail)
# 3 - (Full/Debug)
LogLevel = 0
#
# LogFile
# Description: Log file for main server log.
# Default: "Auth.log" - (Enabled)
# "" - (Disabled)
LogFile = "Auth.log"
#
# Debug Log Mask
# Description: Bitmask that determines which debug log output (level 3)
# will be logged.
# Possible flags:
#
# 64 - Anything related to network input/output,
# such as packet handlers and netcode logs
#
# Simply add the values together to create a bitmask.
# For more info see enum DebugLogFilters in Log.h
#
# Default: 0 (nothing)
DebugLogMask = 64
#
# SQLDriverLogFile
# Description: Log file for SQL driver events.
# Example: "SQLDriver.log" - (Enabled)
# Default: "" - (Disabled)
SQLDriverLogFile = ""
#
# SQLDriverQueryLogging
# Description: Log SQL queries to the SQLDriverLogFile and console.
# Default: 0 - (Disabled, Query errors only)
# 1 - (Enabled, Full query logging - may have performance impact)
SQLDriverQueryLogging = 0
#
# LogTimestamp
# Description: Append timestamp to the server log file name.
# Logname_YYYY-MM-DD_HH-MM-SS.Ext for Logname.Ext
# Default: 0 - (Disabled)
# 1 - (Enabled)
LogTimestamp = 0
#
# LogFileLevel
# Description: Server file level of logging
# Default: 0 - (Minimum)
# 1 - (Basic)
# 2 - (Detail)
# 3 - (Full/Debug)
LogFileLevel = 0
#
# LogColors
# Description: Colors for log messages (Format: "normal basic detail debug").
# Colors: 0 - Black
# 1 - Red
# 2 - Green
# 3 - Brown
# 4 - Blue
# 5 - Magenta
# 6 - Cyan
# 7 - Grey
# 8 - Yellow
# 9 - Lred
# 10 - Lgreen
# 11 - Lblue
# 12 - Lmagenta
# 13 - Lcyan
# 14 - White
# Example: "13 11 9 5" - (Enabled)
# Default: "" - (Disabled)
LogColors = ""
#
# EnableLogDB
# Description: Write log messages to database (LogDatabaseInfo).
# Default: 0 - (Disabled)
# 1 - (Enabled)
EnableLogDB = 0
#
# DBLogLevel
# Description: Log level of databases logging.
# Default: 1 - (Basic)
# 0 - (Minimum)
# 2 - (Detail)
# 3 - (Full/Debug)
DBLogLevel = 1
#
# UseProcessors
# Description: Processors mask for Windows and Linux based multi-processor systems.
# Example: A computer with 2 CPUs:
# 1 - 1st CPU only, 2 - 2nd CPU only, 3 - 1st and 2nd CPU, because 1 | 2 is 3
# Default: 0 - (Selected by OS)
# 1+ - (Bit mask value of selected processors)
UseProcessors = 0
#
# ProcessPriority
# Description: Process priority setting for Windows and Linux based systems.
# Details: On Linux, a nice value of -15 is used. (requires superuser). On Windows, process is set to HIGH class.
# Default: 0 - (Normal)
# 1 - (High)
ProcessPriority = 0
#
# RealmsStateUpdateDelay
# Description: Time (in seconds) between realm list updates.
# Default: 20 - (Enabled)
# 0 - (Disabled)
RealmsStateUpdateDelay = 20
#
# WrongPass.MaxCount
# Description: Number of login attemps with wrong password before the account or IP will be
# banned.
# Default: 0 - (Disabled)
# 1+ - (Enabled)
WrongPass.MaxCount = 0
#
# WrongPass.BanTime
# Description: Time (in seconds) for banning account or IP for invalid login attempts.
# Default: 600 - (10 minutes)
# 0 - (Permanent ban)
WrongPass.BanTime = 600
#
# WrongPass.BanType
# Description: Ban type for invalid login attempts.
# Default: 0 - (Ban IP)
# 1 - (Ban Account)
WrongPass.BanType = 0
#
###################################################################################################
###################################################################################################
# MYSQL SETTINGS
#
# LoginDatabaseInfo
# Description: Database connection settings for the realm server.
# Example: "hostname;port;username;password;database"
# ".;somenumber;username;password;database" - (Use named pipes on Windows
# "enable-named-pipe" to [mysqld]
# section my.ini)
# ".;/path/to/unix_socket;username;password;database" - (use Unix sockets on
# Unix/Linux)
# Default: "127.0.0.1;3306;root;root;auth"
LoginDatabaseInfo = "127.0.0.1;3306;root;root;auth"
#
# LoginDatabase.WorkerThreads
# Description: The amount of worker threads spawned to handle asynchronous (delayed) MySQL
# statements. Each worker thread is mirrored with its own connection to the
# Default: 1
LoginDatabase.WorkerThreads = 1
#
###################################################################################################

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

View File

@@ -1,93 +0,0 @@
/*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "resource.h"
#include "revision.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "windows.h" //"afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_APPICON ICON "authserver.ico"
/////////////////////////////////////////////////////////////////////////////
// Neutre (Par défaut système) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUSD)
#ifdef _WIN32
LANGUAGE LANG_NEUTRAL, SUBLANG_SYS_DEFAULT
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
PRODUCTVERSION VER_PRODUCTVERSION
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifndef _DEBUG
FILEFLAGS 0
#else
#define VER_PRERELEASE VS_FF_PRERELEASE
#define VER_PRIVATEBUILD VS_FF_PRIVATEBUILD
#define VER_DEBUG 0
FILEFLAGS (VER_PRIVATEBUILD|VER_PRERELEASE|VER_DEBUG)
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_APP
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080004b0"
BEGIN
VALUE "CompanyName", VER_COMPANYNAME_STR
VALUE "FileDescription", "Authentication Server Daemon"
VALUE "FileVersion", VER_FILEVERSION_STR
VALUE "InternalName", "authserver"
VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
VALUE "OriginalFilename", "authserver.exe"
VALUE "ProductName", "Authentication Server"
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x800, 1200
END
END
#endif

View File

@@ -1,15 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by SunwellCore.rc
//
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -1,323 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CombatAI.h"
#include "SpellMgr.h"
#include "SpellInfo.h"
#include "Vehicle.h"
#include "ObjectAccessor.h"
#include "Player.h"
/////////////////
// AggressorAI
/////////////////
int AggressorAI::Permissible(const Creature* creature)
{
// have some hostile factions, it will be selected by IsHostileTo check at MoveInLineOfSight
if (!creature->IsCivilian() && !creature->IsNeutralToAll())
return PERMIT_BASE_PROACTIVE;
return PERMIT_BASE_NO;
}
void AggressorAI::UpdateAI(uint32 /*diff*/)
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
/////////////////
// CombatAI
/////////////////
void CombatAI::InitializeAI()
{
for (uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
if (me->m_spells[i] && sSpellMgr->GetSpellInfo(me->m_spells[i]))
spells.push_back(me->m_spells[i]);
CreatureAI::InitializeAI();
}
void CombatAI::Reset()
{
events.Reset();
}
void CombatAI::JustDied(Unit* killer)
{
for (SpellVct::iterator i = spells.begin(); i != spells.end(); ++i)
if (AISpellInfo[*i].condition == AICOND_DIE)
me->CastSpell(killer, *i, true);
}
void CombatAI::EnterCombat(Unit* who)
{
for (SpellVct::iterator i = spells.begin(); i != spells.end(); ++i)
{
if (AISpellInfo[*i].condition == AICOND_AGGRO)
me->CastSpell(who, *i, false);
else if (AISpellInfo[*i].condition == AICOND_COMBAT)
events.ScheduleEvent(*i, AISpellInfo[*i].cooldown + rand()%AISpellInfo[*i].cooldown);
}
}
void CombatAI::UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (uint32 spellId = events.ExecuteEvent())
{
DoCast(spellId);
events.ScheduleEvent(spellId, AISpellInfo[spellId].cooldown + rand()%AISpellInfo[spellId].cooldown);
}
else
DoMeleeAttackIfReady();
}
/////////////////
// CasterAI
/////////////////
void CasterAI::InitializeAI()
{
CombatAI::InitializeAI();
m_attackDist = 30.0f;
for (SpellVct::iterator itr = spells.begin(); itr != spells.end(); ++itr)
if (AISpellInfo[*itr].condition == AICOND_COMBAT && m_attackDist > GetAISpellInfo(*itr)->maxRange)
m_attackDist = GetAISpellInfo(*itr)->maxRange;
if (m_attackDist == 30.0f)
m_attackDist = MELEE_RANGE;
}
void CasterAI::EnterCombat(Unit* who)
{
if (spells.empty())
return;
uint32 spell = rand()%spells.size();
uint32 count = 0;
for (SpellVct::iterator itr = spells.begin(); itr != spells.end(); ++itr, ++count)
{
if (AISpellInfo[*itr].condition == AICOND_AGGRO)
me->CastSpell(who, *itr, false);
else if (AISpellInfo[*itr].condition == AICOND_COMBAT)
{
uint32 cooldown = GetAISpellInfo(*itr)->realCooldown;
if (count == spell)
{
DoCast(spells[spell]);
cooldown += me->GetCurrentSpellCastTime(*itr);
}
events.ScheduleEvent(*itr, cooldown);
}
}
}
void CasterAI::UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->GetVictim()->HasBreakableByDamageCrowdControlAura(me))
{
me->InterruptNonMeleeSpells(false);
return;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (uint32 spellId = events.ExecuteEvent())
{
DoCast(spellId);
uint32 casttime = me->GetCurrentSpellCastTime(spellId);
events.ScheduleEvent(spellId, (casttime ? casttime : 500) + GetAISpellInfo(spellId)->realCooldown);
}
}
//////////////
// ArcherAI
//////////////
ArcherAI::ArcherAI(Creature* c) : CreatureAI(c)
{
if (!me->m_spells[0])
sLog->outError("ArcherAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry());
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->m_spells[0]);
m_minRange = spellInfo ? spellInfo->GetMinRange(false) : 0;
if (!m_minRange)
m_minRange = MELEE_RANGE;
me->m_CombatDistance = spellInfo ? spellInfo->GetMaxRange(false) : 0;
me->m_SightDistance = me->m_CombatDistance;
}
void ArcherAI::AttackStart(Unit* who)
{
if (!who)
return;
if (me->IsWithinCombatRange(who, m_minRange))
{
if (me->Attack(who, true) && !who->IsFlying())
me->GetMotionMaster()->MoveChase(who);
}
else
{
if (me->Attack(who, false) && !who->IsFlying())
me->GetMotionMaster()->MoveChase(who, me->m_CombatDistance);
}
if (who->IsFlying())
me->GetMotionMaster()->MoveIdle();
}
void ArcherAI::UpdateAI(uint32 /*diff*/)
{
if (!UpdateVictim())
return;
if (!me->IsWithinCombatRange(me->GetVictim(), m_minRange))
DoSpellAttackIfReady(me->m_spells[0]);
else
DoMeleeAttackIfReady();
}
//////////////
// TurretAI
//////////////
TurretAI::TurretAI(Creature* c) : CreatureAI(c)
{
if (!me->m_spells[0])
sLog->outError("TurretAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry());
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->m_spells[0]);
m_minRange = spellInfo ? spellInfo->GetMinRange(false) : 0;
me->m_CombatDistance = spellInfo ? spellInfo->GetMaxRange(false) : 0;
me->m_SightDistance = me->m_CombatDistance;
}
bool TurretAI::CanAIAttack(const Unit* /*who*/) const
{
// TODO: use one function to replace it
if (!me->IsWithinCombatRange(me->GetVictim(), me->m_CombatDistance)
|| (m_minRange && me->IsWithinCombatRange(me->GetVictim(), m_minRange)))
return false;
return true;
}
void TurretAI::AttackStart(Unit* who)
{
if (who)
me->Attack(who, false);
}
void TurretAI::UpdateAI(uint32 /*diff*/)
{
if (!UpdateVictim())
return;
if( me->m_spells[0] )
DoSpellAttackIfReady(me->m_spells[0]);
}
//////////////
// VehicleAI
//////////////
VehicleAI::VehicleAI(Creature* c) : CreatureAI(c), m_ConditionsTimer(VEHICLE_CONDITION_CHECK_TIME)
{
LoadConditions();
m_DoDismiss = false;
m_DismissTimer = VEHICLE_DISMISS_TIME;
}
//NOTE: VehicleAI::UpdateAI runs even while the vehicle is mounted
void VehicleAI::UpdateAI(uint32 diff)
{
CheckConditions(diff);
if (m_DoDismiss)
{
if (m_DismissTimer < diff)
{
m_DoDismiss = false;
me->DespawnOrUnsummon();
}
else
m_DismissTimer -= diff;
}
}
void VehicleAI::OnCharmed(bool apply)
{
if (!me->GetVehicleKit()->IsVehicleInUse() && !apply && !conditions.empty()) // was used and has conditions
m_DoDismiss = true; // needs reset
else if (apply)
m_DoDismiss = false; // in use again
m_DismissTimer = VEHICLE_DISMISS_TIME;//reset timer
}
void VehicleAI::LoadConditions()
{
conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE, me->GetEntry());
//if (!conditions.empty())
;//sLog->outDebug(LOG_FILTER_CONDITIONSYS, "VehicleAI::LoadConditions: loaded %u conditions", uint32(conditions.size()));
}
void VehicleAI::CheckConditions(uint32 diff)
{
if (m_ConditionsTimer < diff)
{
if (!conditions.empty())
{
if (Vehicle* vehicleKit = me->GetVehicleKit())
for (SeatMap::iterator itr = vehicleKit->Seats.begin(); itr != vehicleKit->Seats.end(); ++itr)
if (Unit* passenger = ObjectAccessor::GetUnit(*me, itr->second.Passenger.Guid))
{
if (Player* player = passenger->ToPlayer())
{
if (!sConditionMgr->IsObjectMeetToConditions(player, me, conditions))
{
player->ExitVehicle();
return; // check other pessanger in next tick
}
}
}
}
m_ConditionsTimer = VEHICLE_CONDITION_CHECK_TIME;
}
else
m_ConditionsTimer -= diff;
}

View File

@@ -1,120 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_COMBATAI_H
#define TRINITY_COMBATAI_H
#include "CreatureAI.h"
#include "CreatureAIImpl.h"
#include "ConditionMgr.h"
class Creature;
class AggressorAI : public CreatureAI
{
public:
explicit AggressorAI(Creature* c) : CreatureAI(c) {}
void UpdateAI(uint32);
static int Permissible(const Creature*);
};
typedef std::vector<uint32> SpellVct;
class CombatAI : public CreatureAI
{
public:
explicit CombatAI(Creature* c) : CreatureAI(c) {}
void InitializeAI();
void Reset();
void EnterCombat(Unit* who);
void JustDied(Unit* killer);
void UpdateAI(uint32 diff);
static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
protected:
EventMap events;
SpellVct spells;
};
class CasterAI : public CombatAI
{
public:
explicit CasterAI(Creature* c) : CombatAI(c) { m_attackDist = MELEE_RANGE; }
void InitializeAI();
void AttackStart(Unit* victim) { AttackStartCaster(victim, m_attackDist); }
void UpdateAI(uint32 diff);
void EnterCombat(Unit* /*who*/);
private:
float m_attackDist;
};
struct ArcherAI : public CreatureAI
{
public:
explicit ArcherAI(Creature* c);
void AttackStart(Unit* who);
void UpdateAI(uint32 diff);
static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
protected:
float m_minRange;
};
struct TurretAI : public CreatureAI
{
public:
explicit TurretAI(Creature* c);
bool CanAIAttack(const Unit* who) const;
void AttackStart(Unit* who);
void UpdateAI(uint32 diff);
static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
protected:
float m_minRange;
};
#define VEHICLE_CONDITION_CHECK_TIME 1000
#define VEHICLE_DISMISS_TIME 5000
struct VehicleAI : public CreatureAI
{
public:
explicit VehicleAI(Creature* creature);
void UpdateAI(uint32 diff);
void MoveInLineOfSight(Unit*) {}
void AttackStart(Unit*) {}
void OnCharmed(bool apply);
static int Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
private:
void LoadConditions();
void CheckConditions(uint32 diff);
ConditionList conditions;
uint32 m_ConditionsTimer;
bool m_DoDismiss;
uint32 m_DismissTimer;
};
#endif

View File

@@ -1,29 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GameObjectAI.h"
//GameObjectAI::GameObjectAI(GameObject* g) : go(g) {}
int GameObjectAI::Permissible(const GameObject* go)
{
if (go->GetAIName() == "GameObjectAI")
return PERMIT_BASE_SPECIAL;
return PERMIT_BASE_NO;
}
NullGameObjectAI::NullGameObjectAI(GameObject* g) : GameObjectAI(g) {}

View File

@@ -1,76 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_GAMEOBJECTAI_H
#define TRINITY_GAMEOBJECTAI_H
#include "Define.h"
#include <list>
#include "Object.h"
#include "QuestDef.h"
#include "GameObject.h"
#include "CreatureAI.h"
class GameObjectAI
{
protected:
GameObject* const go;
public:
explicit GameObjectAI(GameObject* g) : go(g) {}
virtual ~GameObjectAI() {}
virtual void UpdateAI(uint32 /*diff*/) {}
virtual void InitializeAI() { Reset(); }
virtual void Reset() { }
// Pass parameters between AI
virtual void DoAction(int32 /*param = 0 */) {}
virtual void SetGUID(uint64 /*guid*/, int32 /*id = 0 */) {}
virtual uint64 GetGUID(int32 /*id = 0 */) const { return 0; }
static int Permissible(GameObject const* go);
virtual bool GossipHello(Player* /*player*/, bool reportUse) { return false; }
virtual bool GossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) { return false; }
virtual bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, char const* /*code*/) { return false; }
virtual bool QuestAccept(Player* /*player*/, Quest const* /*quest*/) { return false; }
virtual bool QuestReward(Player* /*player*/, Quest const* /*quest*/, uint32 /*opt*/) { return false; }
virtual uint32 GetDialogStatus(Player* /*player*/) { return DIALOG_STATUS_SCRIPTED_NO_STATUS; }
virtual void Destroyed(Player* /*player*/, uint32 /*eventId*/) {}
virtual uint32 GetData(uint32 /*id*/) const { return 0; }
virtual void SetData64(uint32 /*id*/, uint64 /*value*/) {}
virtual uint64 GetData64(uint32 /*id*/) const { return 0; }
virtual void SetData(uint32 /*id*/, uint32 /*value*/) {}
virtual void OnGameEvent(bool /*start*/, uint16 /*eventId*/) {}
virtual void OnStateChanged(uint32 /*state*/, Unit* /*unit*/) {}
virtual void EventInform(uint32 /*eventId*/) {}
virtual void SpellHit(Unit* unit, const SpellInfo* spellInfo) {}
};
class NullGameObjectAI : public GameObjectAI
{
public:
explicit NullGameObjectAI(GameObject* g);
void UpdateAI(uint32 /*diff*/) {}
static int Permissible(GameObject const* /*go*/) { return PERMIT_BASE_IDLE; }
};
#endif

View File

@@ -1,69 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GuardAI.h"
#include "Errors.h"
#include "Player.h"
#include "ObjectAccessor.h"
#include "World.h"
#include "CreatureAIImpl.h"
int GuardAI::Permissible(Creature const* creature)
{
if (creature->IsGuard())
return PERMIT_BASE_SPECIAL;
return PERMIT_BASE_NO;
}
GuardAI::GuardAI(Creature* creature) : ScriptedAI(creature)
{
}
void GuardAI::Reset()
{
ScriptedAI::Reset();
me->CastSpell(me, 18950 /*SPELL_INVISIBILITY_AND_STEALTH_DETECTION*/, true);
}
void GuardAI::EnterEvadeMode()
{
if (!me->IsAlive())
{
me->GetMotionMaster()->MoveIdle();
me->CombatStop(true);
me->DeleteThreatList();
return;
}
;//sLog->outDebug(LOG_FILTER_UNITS, "Guard entry: %u enters evade mode.", me->GetEntry());
me->RemoveAllAuras();
me->DeleteThreatList();
me->CombatStop(true);
// Remove ChaseMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
me->GetMotionMaster()->MoveTargetedHome();
}
void GuardAI::JustDied(Unit* killer)
{
if (Player* player = killer->GetCharmerOrOwnerPlayerOrPlayerItself())
me->SendZoneUnderAttackMessage(player);
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_GUARDAI_H
#define TRINITY_GUARDAI_H
#include "ScriptedCreature.h"
class Creature;
class GuardAI : public ScriptedAI
{
public:
explicit GuardAI(Creature* creature);
static int Permissible(Creature const* creature);
void Reset();
void EnterEvadeMode();
void JustDied(Unit* killer);
};
#endif

View File

@@ -1,92 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PassiveAI.h"
#include "Creature.h"
#include "TemporarySummon.h"
PassiveAI::PassiveAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); }
PossessedAI::PossessedAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); }
NullCreatureAI::NullCreatureAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); }
void PassiveAI::UpdateAI(uint32)
{
if (me->IsInCombat() && me->getAttackers().empty())
EnterEvadeMode();
}
void PossessedAI::AttackStart(Unit* target)
{
me->Attack(target, true);
}
void PossessedAI::UpdateAI(uint32 /*diff*/)
{
if (me->GetVictim())
{
if (!me->IsValidAttackTarget(me->GetVictim()))
me->AttackStop();
else
DoMeleeAttackIfReady();
}
}
void PossessedAI::JustDied(Unit* /*u*/)
{
// We died while possessed, disable our loot
me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
}
void PossessedAI::KilledUnit(Unit* victim)
{
// We killed a creature, disable victim's loot
//if (victim->GetTypeId() == TYPEID_UNIT)
// victim->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
}
void CritterAI::DamageTaken(Unit*, uint32&, DamageEffectType, SpellSchoolMask)
{
if (!me->HasUnitState(UNIT_STATE_FLEEING))
me->SetControlled(true, UNIT_STATE_FLEEING);
_combatTimer = 1;
}
void CritterAI::EnterEvadeMode()
{
if (me->HasUnitState(UNIT_STATE_FLEEING))
me->SetControlled(false, UNIT_STATE_FLEEING);
CreatureAI::EnterEvadeMode();
_combatTimer = 0;
}
void CritterAI::UpdateAI(uint32 diff)
{
if (me->IsInCombat())
{
_combatTimer += diff;
if (_combatTimer >= 5000)
EnterEvadeMode();
}
}
void TriggerAI::IsSummonedBy(Unit* summoner)
{
if (me->m_spells[0])
me->CastSpell(me, me->m_spells[0], false, 0, 0, summoner ? summoner->GetGUID() : 0);
}

View File

@@ -1,89 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_PASSIVEAI_H
#define TRINITY_PASSIVEAI_H
#include "CreatureAI.h"
//#include "CreatureAIImpl.h"
class PassiveAI : public CreatureAI
{
public:
explicit PassiveAI(Creature* c);
void MoveInLineOfSight(Unit*) {}
void AttackStart(Unit*) {}
void UpdateAI(uint32);
static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; }
};
class PossessedAI : public CreatureAI
{
public:
explicit PossessedAI(Creature* c);
void MoveInLineOfSight(Unit*) {}
void AttackStart(Unit* target);
void UpdateAI(uint32);
void EnterEvadeMode() {}
void JustDied(Unit*);
void KilledUnit(Unit* victim);
static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; }
};
class NullCreatureAI : public CreatureAI
{
public:
explicit NullCreatureAI(Creature* c);
void MoveInLineOfSight(Unit*) {}
void AttackStart(Unit*) {}
void UpdateAI(uint32) {}
void EnterEvadeMode() {}
void OnCharmed(bool /*apply*/) {}
static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; }
};
class CritterAI : public PassiveAI
{
public:
explicit CritterAI(Creature* c) : PassiveAI(c) { _combatTimer = 0; }
void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask);
void EnterEvadeMode();
void UpdateAI(uint32);
// Xinef: Added
private:
uint32 _combatTimer;
};
class TriggerAI : public NullCreatureAI
{
public:
explicit TriggerAI(Creature* c) : NullCreatureAI(c) {}
void IsSummonedBy(Unit* summoner);
};
#endif

View File

@@ -1,744 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PetAI.h"
#include "Errors.h"
#include "Pet.h"
#include "Player.h"
#include "DBCStores.h"
#include "Spell.h"
#include "ObjectAccessor.h"
#include "SpellMgr.h"
#include "Creature.h"
#include "World.h"
#include "Util.h"
#include "Group.h"
#include "SpellInfo.h"
#include "SpellAuraEffects.h"
#include "WorldSession.h"
int PetAI::Permissible(const Creature* creature)
{
if (creature->IsPet())
return PERMIT_BASE_SPECIAL;
return PERMIT_BASE_NO;
}
PetAI::PetAI(Creature* c) : CreatureAI(c), i_tracker(TIME_INTERVAL_LOOK)
{
UpdateAllies();
}
bool PetAI::_needToStop()
{
// This is needed for charmed creatures, as once their target was reset other effects can trigger threat
if (me->IsCharmed() && me->GetVictim() == me->GetCharmer())
return true;
// xinef: dont allow to follow targets out of visibility range
if (me->GetExactDist(me->GetVictim()) > me->GetVisibilityRange()-5.0f)
return true;
// dont allow pets to follow targets far away from owner
if (Unit* owner = me->GetCharmerOrOwner())
if (owner->GetExactDist(me) >= (owner->GetVisibilityRange()-10.0f))
return true;
if (!me->_CanDetectFeignDeathOf(me->GetVictim()))
return true;
if (me->isTargetNotAcceptableByMMaps(me->GetVictim()->GetGUID(), sWorld->GetGameTime(), me->GetVictim()))
return true;
return !me->CanCreatureAttack(me->GetVictim());
}
void PetAI::_stopAttack()
{
if (!me->IsAlive())
{
;//sLog->outStaticDebug("Creature stoped attacking cuz his dead [guid=%u]", me->GetGUIDLow());
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
me->CombatStop();
me->getHostileRefManager().deleteReferences();
return;
}
me->AttackStop();
me->InterruptNonMeleeSpells(false);
me->GetCharmInfo()->SetIsCommandAttack(false);
ClearCharmInfoFlags();
HandleReturnMovement();
}
void PetAI::_doMeleeAttack()
{
// Xinef: Imps cannot attack with melee
if (!_canMeleeAttack())
return;
DoMeleeAttackIfReady();
}
bool PetAI::_canMeleeAttack() const
{
return me->GetEntry() != 416 /*ENTRY_IMP*/ &&
me->GetEntry() != 510 /*ENTRY_WATER_ELEMENTAL*/ &&
me->GetEntry() != 37994 /*ENTRY_WATER_ELEMENTAL_PERM*/;
}
void PetAI::UpdateAI(uint32 diff)
{
if (!me->IsAlive() || !me->GetCharmInfo())
return;
Unit* owner = me->GetCharmerOrOwner();
if (m_updateAlliesTimer <= diff)
// UpdateAllies self set update timer
UpdateAllies();
else
m_updateAlliesTimer -= diff;
if (me->GetVictim() && me->GetVictim()->IsAlive())
{
// is only necessary to stop casting, the pet must not exit combat
if (me->GetVictim()->HasBreakableByDamageCrowdControlAura(me))
{
me->InterruptNonMeleeSpells(false);
return;
}
if (_needToStop())
{
;//sLog->outStaticDebug("Pet AI stopped attacking [guid=%u]", me->GetGUIDLow());
_stopAttack();
return;
}
// Check before attacking to prevent pets from leaving stay position
if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY))
{
if (me->GetCharmInfo()->IsCommandAttack() || (me->GetCharmInfo()->IsAtStay() && me->IsWithinMeleeRange(me->GetVictim())))
_doMeleeAttack();
}
else
_doMeleeAttack();
}
else if (!me->GetCharmInfo() || (!me->GetCharmInfo()->GetForcedSpell() && !me->HasUnitState(UNIT_STATE_CASTING)))
{
if (me->HasReactState(REACT_AGGRESSIVE) || me->GetCharmInfo()->IsAtStay())
{
// Every update we need to check targets only in certain cases
// Aggressive - Allow auto select if owner or pet don't have a target
// Stay - Only pick from pet or owner targets / attackers so targets won't run by
// while chasing our owner. Don't do auto select.
// All other cases (ie: defensive) - Targets are assigned by AttackedBy(), OwnerAttackedBy(), OwnerAttacked(), etc.
Unit* nextTarget = SelectNextTarget(me->HasReactState(REACT_AGGRESSIVE));
if (nextTarget)
AttackStart(nextTarget);
else
HandleReturnMovement();
}
else
HandleReturnMovement();
}
// xinef: charm info must be always available
if (!me->GetCharmInfo())
return;
// Autocast (casted only in combat or persistent spells in any state)
if (!me->HasUnitState(UNIT_STATE_CASTING))
{
if (owner && owner->GetTypeId() == TYPEID_PLAYER && me->GetCharmInfo()->GetForcedSpell() && me->GetCharmInfo()->GetForcedTarget())
{
owner->ToPlayer()->GetSession()->HandlePetActionHelper(me, me->GetGUID(), abs(me->GetCharmInfo()->GetForcedSpell()), ACT_ENABLED, me->GetCharmInfo()->GetForcedTarget());
// xinef: if spell was casted properly and we are in passive mode, handle return
if (!me->GetCharmInfo()->GetForcedSpell() && me->HasReactState(REACT_PASSIVE))
{
if (me->HasUnitState(UNIT_STATE_CASTING))
{
me->GetMotionMaster()->Clear(false);
me->StopMoving();
}
else
_stopAttack();
}
return;
}
// xinef: dont allow ghouls to cast spells below 75 energy
if (me->IsPet() && me->ToPet()->IsPetGhoul() && me->GetPower(POWER_ENERGY) < 75)
return;
typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
TargetSpellList targetSpellStore;
for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i)
{
uint32 spellID = me->GetPetAutoSpellOnPos(i);
if (!spellID)
continue;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
if (!spellInfo)
continue;
if (me->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
continue;
// check spell cooldown, this should be checked in CheckCast...
if (me->HasSpellCooldown(spellInfo->Id))
continue;
if (spellInfo->IsPositive())
{
if (spellInfo->CanBeUsedInCombat())
{
// Check if we're in combat or commanded to attack
if (!me->IsInCombat() && !me->GetCharmInfo()->IsCommandAttack())
continue;
}
Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);
spell->LoadScripts(); // xinef: load for CanAutoCast (calling CheckPetCast)
bool spellUsed = false;
// Some spells can target enemy or friendly (DK Ghoul's Leap)
// Check for enemy first (pet then owner)
Unit* target = me->getAttackerForHelper();
if (!target && owner)
target = owner->getAttackerForHelper();
if (target)
{
if (CanAttack(target) && spell->CanAutoCast(target))
{
targetSpellStore.push_back(std::make_pair(target, spell));
spellUsed = true;
}
}
// No enemy, check friendly
if (!spellUsed)
{
for (std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
{
Unit* ally = ObjectAccessor::GetUnit(*me, *tar);
//only buff targets that are in combat, unless the spell can only be cast while out of combat
if (!ally)
continue;
if (spell->CanAutoCast(ally))
{
targetSpellStore.push_back(std::make_pair(ally, spell));
spellUsed = true;
break;
}
}
}
// No valid targets at all
if (!spellUsed)
delete spell;
}
else if (me->GetVictim() && CanAttack(me->GetVictim(), spellInfo) && spellInfo->CanBeUsedInCombat())
{
Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);
if (spell->CanAutoCast(me->GetVictim()))
targetSpellStore.push_back(std::make_pair(me->GetVictim(), spell));
else
delete spell;
}
}
//found units to cast on to
if (!targetSpellStore.empty())
{
uint32 index = urand(0, targetSpellStore.size() - 1);
Spell* spell = targetSpellStore[index].second;
Unit* target = targetSpellStore[index].first;
targetSpellStore.erase(targetSpellStore.begin() + index);
SpellCastTargets targets;
targets.SetUnitTarget(target);
if (!me->HasInArc(M_PI, target))
{
me->SetInFront(target);
if (target && target->GetTypeId() == TYPEID_PLAYER)
me->SendUpdateToPlayer(target->ToPlayer());
if (owner && owner->GetTypeId() == TYPEID_PLAYER)
me->SendUpdateToPlayer(owner->ToPlayer());
}
me->AddSpellCooldown(spell->m_spellInfo->Id, 0, 0);
spell->prepare(&targets);
}
// deleted cached Spell objects
for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
delete itr->second;
}
}
void PetAI::UpdateAllies()
{
Unit* owner = me->GetCharmerOrOwner();
Group* group = NULL;
m_updateAlliesTimer = 10*IN_MILLISECONDS; //update friendly targets every 10 seconds, lesser checks increase performance
if (!owner)
return;
else if (owner->GetTypeId() == TYPEID_PLAYER)
group = owner->ToPlayer()->GetGroup();
//only pet and owner/not in group->ok
if (m_AllySet.size() == 2 && !group)
return;
//owner is in group; group members filled in already (no raid -> subgroupcount = whole count)
if (group && !group->isRaidGroup() && m_AllySet.size() == (group->GetMembersCount() + 2))
return;
m_AllySet.clear();
m_AllySet.insert(me->GetGUID());
if (group) //add group
{
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
{
Player* Target = itr->GetSource();
if (!Target || !Target->IsInMap(owner) || !group->SameSubGroup(owner->ToPlayer(), Target))
continue;
if (Target->GetGUID() == owner->GetGUID())
continue;
m_AllySet.insert(Target->GetGUID());
}
}
else //remove group
m_AllySet.insert(owner->GetGUID());
}
void PetAI::KilledUnit(Unit* victim)
{
// Called from Unit::Kill() in case where pet or owner kills something
// if owner killed this victim, pet may still be attacking something else
if (me->GetVictim() && me->GetVictim() != victim)
return;
// Xinef: if pet is channeling a spell and owner killed something different, dont interrupt it
if (me->HasUnitState(UNIT_STATE_CASTING) && me->GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT) && me->GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT) != victim->GetGUID())
return;
// Clear target just in case. May help problem where health / focus / mana
// regen gets stuck. Also resets attack command.
// Can't use _stopAttack() because that activates movement handlers and ignores
// next target selection
me->AttackStop();
me->InterruptNonMeleeSpells(false);
// Before returning to owner, see if there are more things to attack
if (Unit* nextTarget = SelectNextTarget(false))
AttackStart(nextTarget);
else
HandleReturnMovement(); // Return
}
void PetAI::AttackStart(Unit* target)
{
// Overrides Unit::AttackStart to correctly evaluate Pet states
// Check all pet states to decide if we can attack this target
if (!CanAttack(target))
return;
// Only chase if not commanded to stay or if stay but commanded to attack
DoAttack(target, (!me->GetCharmInfo()->HasCommandState(COMMAND_STAY) || me->GetCharmInfo()->IsCommandAttack()));
}
void PetAI::OwnerAttackedBy(Unit* attacker)
{
// Called when owner takes damage. This function helps keep pets from running off
// simply due to owner gaining aggro.
if (!attacker)
return;
// Passive pets don't do anything
if (me->HasReactState(REACT_PASSIVE))
return;
// Prevent pet from disengaging from current target
if (me->GetVictim() && me->GetVictim()->IsAlive())
return;
// Continue to evaluate and attack if necessary
AttackStart(attacker);
}
void PetAI::OwnerAttacked(Unit* target)
{
// Called when owner attacks something. Allows defensive pets to know
// that they need to assist
// Target might be NULL if called from spell with invalid cast targets
if (!target)
return;
// Passive pets don't do anything
if (me->HasReactState(REACT_PASSIVE))
return;
// Prevent pet from disengaging from current target
if (me->GetVictim() && me->GetVictim()->IsAlive())
return;
// Continue to evaluate and attack if necessary
AttackStart(target);
}
Unit* PetAI::SelectNextTarget(bool allowAutoSelect) const
{
// Provides next target selection after current target death.
// This function should only be called internally by the AI
// Targets are not evaluated here for being valid targets, that is done in _CanAttack()
// The parameter: allowAutoSelect lets us disable aggressive pet auto targeting for certain situations
// Passive pets don't do next target selection
if (me->HasReactState(REACT_PASSIVE))
return NULL;
// Check pet attackers first so we don't drag a bunch of targets to the owner
if (Unit* myAttacker = me->getAttackerForHelper())
if (!myAttacker->HasBreakableByDamageCrowdControlAura() && me->_CanDetectFeignDeathOf(myAttacker) && me->CanCreatureAttack(myAttacker) && !me->isTargetNotAcceptableByMMaps(myAttacker->GetGUID(), sWorld->GetGameTime(), myAttacker))
return myAttacker;
// Check pet's attackers first to prevent dragging mobs back to owner
if (me->HasAuraType(SPELL_AURA_MOD_TAUNT))
{
const Unit::AuraEffectList& tauntAuras = me->GetAuraEffectsByType(SPELL_AURA_MOD_TAUNT);
if (!tauntAuras.empty())
for (Unit::AuraEffectList::const_reverse_iterator itr = tauntAuras.rbegin(); itr != tauntAuras.rend(); ++itr)
if (Unit* caster = (*itr)->GetCaster())
if (me->_CanDetectFeignDeathOf(caster) && me->CanCreatureAttack(caster) && !caster->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, me->GetGUID()))
return caster;
}
// Not sure why we wouldn't have an owner but just in case...
Unit* owner = me->GetCharmerOrOwner();
if (!owner)
return NULL;
// Check owner attackers
if (Unit* ownerAttacker = owner->getAttackerForHelper())
if (!ownerAttacker->HasBreakableByDamageCrowdControlAura() && me->_CanDetectFeignDeathOf(ownerAttacker) && me->CanCreatureAttack(ownerAttacker) && !me->isTargetNotAcceptableByMMaps(ownerAttacker->GetGUID(), sWorld->GetGameTime(), ownerAttacker))
return ownerAttacker;
// Check owner victim
// 3.0.2 - Pets now start attacking their owners victim in defensive mode as soon as the hunter does
if (Unit* ownerVictim = owner->GetVictim())
if (me->_CanDetectFeignDeathOf(ownerVictim) && me->CanCreatureAttack(ownerVictim) && !me->isTargetNotAcceptableByMMaps(ownerVictim->GetGUID(), sWorld->GetGameTime(), ownerVictim))
return ownerVictim;
// Neither pet or owner had a target and aggressive pets can pick any target
// To prevent aggressive pets from chain selecting targets and running off, we
// only select a random target if certain conditions are met.
if (allowAutoSelect)
if (!me->GetCharmInfo()->IsReturning() || me->GetCharmInfo()->IsFollowing() || me->GetCharmInfo()->IsAtStay())
if (Unit* nearTarget = me->ToCreature()->SelectNearestTargetInAttackDistance(MAX_AGGRO_RADIUS))
return nearTarget;
// Default - no valid targets
return NULL;
}
void PetAI::HandleReturnMovement()
{
// Handles moving the pet back to stay or owner
// Prevent activating movement when under control of spells
// such as "Eyes of the Beast"
if (me->isPossessed())
return;
if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY))
{
if (!me->GetCharmInfo()->IsAtStay() && !me->GetCharmInfo()->IsReturning())
{
if (me->GetCharmInfo()->HasStayPosition())
{
// Return to previous position where stay was clicked
if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE)
{
float x, y, z;
me->GetCharmInfo()->GetStayPosition(x, y, z);
ClearCharmInfoFlags();
me->GetCharmInfo()->SetIsReturning(true);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MovePoint(me->GetUInt32Value(OBJECT_FIELD_GUID), x, y, z);
}
}
}
}
else // COMMAND_FOLLOW
{
if (!me->GetCharmInfo()->IsFollowing() && !me->GetCharmInfo()->IsReturning())
{
if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE)
{
ClearCharmInfoFlags();
me->GetCharmInfo()->SetIsReturning(true);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveFollow(me->GetCharmerOrOwner(), PET_FOLLOW_DIST, me->GetFollowAngle());
}
}
}
me->GetCharmInfo()->SetForcedSpell(0);
me->GetCharmInfo()->SetForcedTargetGUID(0);
// xinef: remember that npcs summoned by npcs can also be pets
me->DeleteThreatList();
me->ClearInPetCombat();
}
void PetAI::SpellHit(Unit* caster, const SpellInfo* spellInfo)
{
// Xinef: taunt behavior code
if (spellInfo->HasAura(SPELL_AURA_MOD_TAUNT) && !me->HasReactState(REACT_PASSIVE))
{
me->GetCharmInfo()->SetForcedSpell(0);
me->GetCharmInfo()->SetForcedTargetGUID(0);
AttackStart(caster);
}
}
void PetAI::DoAttack(Unit* target, bool chase)
{
// Handles attack with or without chase and also resets flags
// for next update / creature kill
if (me->Attack(target, true))
{
// xinef: properly fix fake combat after pet is sent to attack
if (Unit* owner = me->GetOwner())
owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
// Play sound to let the player know the pet is attacking something it picked on its own
if (me->HasReactState(REACT_AGGRESSIVE) && !me->GetCharmInfo()->IsCommandAttack())
me->SendPetAIReaction(me->GetGUID());
if (CharmInfo* ci = me->GetCharmInfo())
{
ci->SetIsAtStay(false);
ci->SetIsCommandFollow(false);
ci->SetIsFollowing(false);
ci->SetIsReturning(false);
}
if (chase)
{
me->GetMotionMaster()->MoveChase(target, !_canMeleeAttack() ? 20.0f: 0.0f, me->GetAngle(target));
}
else // (Stay && ((Aggressive || Defensive) && In Melee Range)))
{
me->GetCharmInfo()->SetIsAtStay(true);
me->GetMotionMaster()->MovementExpiredOnSlot(MOTION_SLOT_ACTIVE, false);
me->GetMotionMaster()->MoveIdle();
}
}
}
void PetAI::MovementInform(uint32 moveType, uint32 data)
{
// Receives notification when pet reaches stay or follow owner
switch (moveType)
{
case POINT_MOTION_TYPE:
{
// Pet is returning to where stay was clicked. data should be
// pet's GUIDLow since we set that as the waypoint ID
if (data == me->GetGUIDLow() && me->GetCharmInfo()->IsReturning())
{
ClearCharmInfoFlags();
me->GetCharmInfo()->SetIsAtStay(true);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
}
break;
}
case FOLLOW_MOTION_TYPE:
{
// If data is owner's GUIDLow then we've reached follow point,
// otherwise we're probably chasing a creature
if (me->GetCharmerOrOwner() && me->GetCharmInfo() && data == me->GetCharmerOrOwner()->GetGUIDLow() && me->GetCharmInfo()->IsReturning())
{
ClearCharmInfoFlags();
me->GetCharmInfo()->SetIsFollowing(true);
}
break;
}
default:
break;
}
}
bool PetAI::CanAttack(Unit* target, const SpellInfo* spellInfo)
{
// Evaluates wether a pet can attack a specific target based on CommandState, ReactState and other flags
// IMPORTANT: The order in which things are checked is important, be careful if you add or remove checks
// Hmmm...
if (!target)
return false;
if (!target->IsAlive())
{
// xinef: if target is invalid, pet should evade automaticly
// Clear target to prevent getting stuck on dead targets
//me->AttackStop();
//me->InterruptNonMeleeSpells(false);
return false;
}
// xinef: check unit states of pet
if (me->HasUnitState(UNIT_STATE_LOST_CONTROL))
return false;
// xinef: pets of mounted players have stunned flag only, check this also
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED))
return false;
// pussywizard: ZOMG! TEMP!
if (!me->GetCharmInfo())
{
sLog->outMisc("PetAI::CanAttack (A1) - %u, %u", me->GetEntry(), GUID_LOPART(me->GetOwnerGUID()));
return false;
}
// Passive - passive pets can attack if told to
if (me->HasReactState(REACT_PASSIVE))
return me->GetCharmInfo()->IsCommandAttack();
// CC - mobs under crowd control can be attacked if owner commanded
if (target->HasBreakableByDamageCrowdControlAura() && (!spellInfo || !spellInfo->HasAttribute(SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS)))
return me->GetCharmInfo()->IsCommandAttack();
// Returning - pets ignore attacks only if owner clicked follow
if (me->GetCharmInfo()->IsReturning())
return !me->GetCharmInfo()->IsCommandFollow();
// Stay - can attack if target is within range or commanded to
if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY))
return (me->IsWithinMeleeRange(target) || me->GetCharmInfo()->IsCommandAttack());
// Pets attacking something (or chasing) should only switch targets if owner tells them to
if (me->GetVictim() && me->GetVictim() != target)
{
// Check if our owner selected this target and clicked "attack"
Unit* ownerTarget = NULL;
if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
ownerTarget = owner->GetSelectedUnit();
else
ownerTarget = me->GetCharmerOrOwner()->GetVictim();
if (ownerTarget && me->GetCharmInfo()->IsCommandAttack())
return (target->GetGUID() == ownerTarget->GetGUID());
}
// Follow
if (me->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
return !me->GetCharmInfo()->IsReturning();
// default, though we shouldn't ever get here
return false;
}
void PetAI::ReceiveEmote(Player* player, uint32 emote)
{
if (me->GetOwnerGUID() && me->GetOwnerGUID() == player->GetGUID())
switch (emote)
{
case TEXT_EMOTE_COWER:
if (me->IsPet() && me->ToPet()->IsPetGhoul())
me->HandleEmoteCommand(/*EMOTE_ONESHOT_ROAR*/EMOTE_ONESHOT_OMNICAST_GHOUL);
break;
case TEXT_EMOTE_ANGRY:
if (me->IsPet() && me->ToPet()->IsPetGhoul())
me->HandleEmoteCommand(/*EMOTE_ONESHOT_COWER*/EMOTE_STATE_STUN);
break;
case TEXT_EMOTE_GLARE:
if (me->IsPet() && me->ToPet()->IsPetGhoul())
me->HandleEmoteCommand(EMOTE_STATE_STUN);
break;
case TEXT_EMOTE_SOOTHE:
if (me->IsPet() && me->ToPet()->IsPetGhoul())
me->HandleEmoteCommand(EMOTE_ONESHOT_OMNICAST_GHOUL);
break;
}
}
void PetAI::ClearCharmInfoFlags()
{
// Quick access to set all flags to FALSE
CharmInfo* ci = me->GetCharmInfo();
if (ci)
{
ci->SetIsAtStay(false);
ci->SetIsCommandAttack(false);
ci->SetIsCommandFollow(false);
ci->SetIsFollowing(false);
ci->SetIsReturning(false);
}
}
void PetAI::AttackedBy(Unit* attacker)
{
// Called when pet takes damage. This function helps keep pets from running off
// simply due to gaining aggro.
if (!attacker)
return;
// Passive pets don't do anything
if (me->HasReactState(REACT_PASSIVE))
return;
// Prevent pet from disengaging from current target
if (me->GetVictim() && me->GetVictim()->IsAlive())
return;
// Continue to evaluate and attack if necessary
AttackStart(attacker);
}

View File

@@ -1,72 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_PETAI_H
#define TRINITY_PETAI_H
#include "CreatureAI.h"
#include "Timer.h"
class Creature;
class Spell;
class PetAI : public CreatureAI
{
public:
explicit PetAI(Creature* c);
void UpdateAI(uint32);
static int Permissible(const Creature*);
void KilledUnit(Unit* /*victim*/);
void AttackStart(Unit* target);
void MovementInform(uint32 moveType, uint32 data);
void OwnerAttackedBy(Unit* attacker);
void OwnerAttacked(Unit* target);
void AttackedBy(Unit* attacker);
void ReceiveEmote(Player* player, uint32 textEmote);
// The following aren't used by the PetAI but need to be defined to override
// default CreatureAI functions which interfere with the PetAI
//
void MoveInLineOfSight(Unit* /*who*/) {} // CreatureAI interferes with returning pets
void MoveInLineOfSight_Safe(Unit* /*who*/) {} // CreatureAI interferes with returning pets
void EnterEvadeMode() {} // For fleeing, pets don't use this type of Evade mechanic
void SpellHit(Unit* caster, const SpellInfo* spellInfo);
private:
bool _isVisible(Unit*) const;
bool _needToStop(void);
void _stopAttack(void);
void _doMeleeAttack();
bool _canMeleeAttack() const;
void UpdateAllies();
TimeTracker i_tracker;
std::set<uint64> m_AllySet;
uint32 m_updateAlliesTimer;
Unit* SelectNextTarget(bool allowAutoSelect) const;
void HandleReturnMovement();
void DoAttack(Unit* target, bool chase);
bool CanAttack(Unit* target, const SpellInfo* spellInfo = NULL);
void ClearCharmInfoFlags();
};
#endif

View File

@@ -1,40 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ByteBuffer.h"
#include "ReactorAI.h"
#include "Errors.h"
#include "Log.h"
#include "ObjectAccessor.h"
#include "CreatureAIImpl.h"
int ReactorAI::Permissible(const Creature* creature)
{
if (creature->IsCivilian() || creature->IsNeutralToAll())
return PERMIT_BASE_REACTIVE;
return PERMIT_BASE_NO;
}
void ReactorAI::UpdateAI(uint32 /*diff*/)
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_REACTORAI_H
#define TRINITY_REACTORAI_H
#include "CreatureAI.h"
class Unit;
class ReactorAI : public CreatureAI
{
public:
explicit ReactorAI(Creature* c) : CreatureAI(c) {}
void MoveInLineOfSight(Unit*) {}
void UpdateAI(uint32 diff);
static int Permissible(const Creature*);
};
#endif

View File

@@ -1,117 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "TotemAI.h"
#include "Totem.h"
#include "Creature.h"
#include "DBCStores.h"
#include "ObjectAccessor.h"
#include "SpellMgr.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
int TotemAI::Permissible(Creature const* creature)
{
if (creature->IsTotem())
return PERMIT_BASE_PROACTIVE;
return PERMIT_BASE_NO;
}
TotemAI::TotemAI(Creature* c) : CreatureAI(c), i_victimGuid(0)
{
ASSERT(c->IsTotem());
}
void TotemAI::SpellHit(Unit* /*caster*/, const SpellInfo* spellInfo)
{
}
void TotemAI::DoAction(int32 param)
{
}
void TotemAI::MoveInLineOfSight(Unit* /*who*/)
{
}
void TotemAI::EnterEvadeMode()
{
me->CombatStop(true);
}
void TotemAI::UpdateAI(uint32 /*diff*/)
{
if (me->ToTotem()->GetTotemType() != TOTEM_ACTIVE)
return;
if (!me->IsAlive() || me->IsNonMeleeSpellCast(false))
return;
// Search spell
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->ToTotem()->GetSpell());
if (!spellInfo)
return;
// Get spell range
float max_range = spellInfo->GetMaxRange(false);
// SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems
// pointer to appropriate target if found any
Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(*me, i_victimGuid) : NULL;
// Search victim if no, not attackable, or out of range, or friendly (possible in case duel end)
if (!victim ||
!victim->isTargetableForAttack(true, me) || !me->IsWithinDistInMap(victim, max_range) ||
me->IsFriendlyTo(victim) || !me->CanSeeOrDetect(victim))
{
victim = NULL;
Trinity::NearestAttackableUnitInObjectRangeCheck u_check(me, me, max_range);
Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck> checker(me, victim, u_check);
me->VisitNearbyObject(max_range, checker);
}
// If have target
if (victim)
{
// remember
i_victimGuid = victim->GetGUID();
// attack
me->SetInFront(victim); // client change orientation by self
me->CastSpell(victim, me->ToTotem()->GetSpell(), false);
}
else
i_victimGuid = 0;
}
void TotemAI::AttackStart(Unit* /*victim*/)
{
// Sentry totem sends ping on attack
if (me->GetEntry() == SENTRY_TOTEM_ENTRY && me->GetOwner()->GetTypeId() == TYPEID_PLAYER)
{
WorldPacket data(MSG_MINIMAP_PING, (8+4+4));
data << me->GetGUID();
data << me->GetPositionX();
data << me->GetPositionY();
me->GetOwner()->ToPlayer()->GetSession()->SendPacket(&data);
}
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_TOTEMAI_H
#define TRINITY_TOTEMAI_H
#include "CreatureAI.h"
#include "Timer.h"
class Creature;
class Totem;
class TotemAI : public CreatureAI
{
public:
explicit TotemAI(Creature* c);
void MoveInLineOfSight(Unit* who);
void AttackStart(Unit* victim);
void EnterEvadeMode();
void SpellHit(Unit* /*caster*/, const SpellInfo* /*spellInfo*/);
void DoAction(int32 param);
void UpdateAI(uint32 diff);
static int Permissible(Creature const* creature);
private:
uint64 i_victimGuid;
};
class KillMagnetEvent : public BasicEvent
{
public:
KillMagnetEvent(Unit& self) : _self(self) { }
bool Execute(uint64 e_time, uint32 p_time)
{
_self.setDeathState(JUST_DIED);
return true;
}
protected:
Unit& _self;
};
#endif

View File

@@ -1,336 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "UnitAI.h"
#include "Player.h"
#include "Creature.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
#include "SpellMgr.h"
#include "SpellInfo.h"
#include "Spell.h"
#include "CreatureAIImpl.h"
void UnitAI::AttackStart(Unit* victim)
{
if (victim && me->Attack(victim, true))
me->GetMotionMaster()->MoveChase(victim);
}
void UnitAI::AttackStartCaster(Unit* victim, float dist)
{
if (victim && me->Attack(victim, false))
me->GetMotionMaster()->MoveChase(victim, dist);
}
void UnitAI::DoMeleeAttackIfReady()
{
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
Unit *victim = me->GetVictim();
if (!victim || !victim->IsInWorld())
return;
if (!me->IsWithinMeleeRange(victim))
return;
//Make sure our attack is ready and we aren't currently casting before checking distance
if (me->isAttackReady())
{
// xinef: prevent base and off attack in same time, delay attack at 0.2 sec
if (me->haveOffhandWeapon())
if (me->getAttackTimer(OFF_ATTACK) < ATTACK_DISPLAY_DELAY)
me->setAttackTimer(OFF_ATTACK, ATTACK_DISPLAY_DELAY);
me->AttackerStateUpdate(victim);
me->resetAttackTimer();
}
if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK))
{
// xinef: delay main hand attack if both will hit at the same time (players code)
if (me->getAttackTimer(BASE_ATTACK) < ATTACK_DISPLAY_DELAY)
me->setAttackTimer(BASE_ATTACK, ATTACK_DISPLAY_DELAY);
me->AttackerStateUpdate(victim, OFF_ATTACK);
me->resetAttackTimer(OFF_ATTACK);
}
}
bool UnitAI::DoSpellAttackIfReady(uint32 spell)
{
if (me->HasUnitState(UNIT_STATE_CASTING) || !me->isAttackReady())
return true;
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell))
{
if (me->IsWithinCombatRange(me->GetVictim(), spellInfo->GetMaxRange(false)))
{
me->CastSpell(me->GetVictim(), spell, false);
me->resetAttackTimer();
return true;
}
}
return false;
}
Unit* UnitAI::SelectTarget(SelectAggroTarget targetType, uint32 position, float dist, bool playerOnly, int32 aura)
{
return SelectTarget(targetType, position, DefaultTargetSelector(me, dist, playerOnly, aura));
}
void UnitAI::SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, float dist, bool playerOnly, int32 aura)
{
SelectTargetList(targetList, DefaultTargetSelector(me, dist, playerOnly, aura), num, targetType);
}
float UnitAI::DoGetSpellMaxRange(uint32 spellId, bool positive)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
return spellInfo ? spellInfo->GetMaxRange(positive) : 0;
}
void UnitAI::DoAddAuraToAllHostilePlayers(uint32 spellid)
{
if (me->IsInCombat())
{
ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList();
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
{
if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
if (unit->GetTypeId() == TYPEID_PLAYER)
me->AddAura(spellid, unit);
}
}
}
void UnitAI::DoCastToAllHostilePlayers(uint32 spellid, bool triggered)
{
if (me->IsInCombat())
{
ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList();
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
{
if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
if (unit->GetTypeId() == TYPEID_PLAYER)
me->CastSpell(unit, spellid, triggered);
}
}
}
void UnitAI::DoCast(uint32 spellId)
{
Unit* target = NULL;
//sLog->outError("aggre %u %u", spellId, (uint32)AISpellInfo[spellId].target);
switch (AISpellInfo[spellId].target)
{
default:
case AITARGET_SELF: target = me; break;
case AITARGET_VICTIM: target = me->GetVictim(); break;
case AITARGET_ENEMY:
{
const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(spellId);
bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS);
//float range = GetSpellMaxRange(spellInfo, false);
target = SelectTarget(SELECT_TARGET_RANDOM, 0, spellInfo->GetMaxRange(false), playerOnly);
break;
}
case AITARGET_ALLY: target = me; break;
case AITARGET_BUFF: target = me; break;
case AITARGET_DEBUFF:
{
const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(spellId);
bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS);
float range = spellInfo->GetMaxRange(false);
DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId);
if (!(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM)
&& targetSelector(me->GetVictim()))
target = me->GetVictim();
else
target = SelectTarget(SELECT_TARGET_RANDOM, 0, targetSelector);
break;
}
}
if (target)
me->CastSpell(target, spellId, false);
}
void UnitAI::DoCast(Unit* victim, uint32 spellId, bool triggered)
{
if (!victim || (me->HasUnitState(UNIT_STATE_CASTING) && !triggered))
return;
me->CastSpell(victim, spellId, triggered);
}
void UnitAI::DoCastVictim(uint32 spellId, bool triggered)
{
if (!me->GetVictim() || (me->HasUnitState(UNIT_STATE_CASTING) && !triggered))
return;
me->CastSpell(me->GetVictim(), spellId, triggered);
}
void UnitAI::DoCastAOE(uint32 spellId, bool triggered)
{
if (!triggered && me->HasUnitState(UNIT_STATE_CASTING))
return;
me->CastSpell((Unit*)NULL, spellId, triggered);
}
#define UPDATE_TARGET(a) {if (AIInfo->target<a) AIInfo->target=a;}
void UnitAI::FillAISpellInfo()
{
AISpellInfo = new AISpellInfoType[sSpellMgr->GetSpellInfoStoreSize()];
AISpellInfoType* AIInfo = AISpellInfo;
const SpellInfo* spellInfo;
for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i, ++AIInfo)
{
spellInfo = sSpellMgr->GetSpellInfo(i);
if (!spellInfo)
continue;
if (spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD))
AIInfo->condition = AICOND_DIE;
else if (spellInfo->IsPassive() || spellInfo->GetDuration() == -1)
AIInfo->condition = AICOND_AGGRO;
else
AIInfo->condition = AICOND_COMBAT;
if (AIInfo->cooldown < spellInfo->RecoveryTime)
AIInfo->cooldown = spellInfo->RecoveryTime;
if (!spellInfo->GetMaxRange(false))
UPDATE_TARGET(AITARGET_SELF)
else
{
for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
{
uint32 targetType = spellInfo->Effects[j].TargetA.GetTarget();
if (targetType == TARGET_UNIT_TARGET_ENEMY
|| targetType == TARGET_DEST_TARGET_ENEMY)
UPDATE_TARGET(AITARGET_VICTIM)
else if (targetType == TARGET_UNIT_DEST_AREA_ENEMY)
UPDATE_TARGET(AITARGET_ENEMY)
if (spellInfo->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA)
{
if (targetType == TARGET_UNIT_TARGET_ENEMY)
UPDATE_TARGET(AITARGET_DEBUFF)
else if (spellInfo->IsPositive())
UPDATE_TARGET(AITARGET_BUFF)
}
}
}
AIInfo->realCooldown = spellInfo->RecoveryTime + spellInfo->StartRecoveryTime;
AIInfo->maxRange = spellInfo->GetMaxRange(false) * 3 / 4;
}
}
//Enable PlayerAI when charmed
void PlayerAI::OnCharmed(bool apply)
{
me->IsAIEnabled = apply;
}
void SimpleCharmedAI::UpdateAI(uint32 /*diff*/)
{
Creature* charmer = me->GetCharmer()->ToCreature();
//kill self if charm aura has infinite duration
if (charmer->IsInEvadeMode())
{
Unit::AuraEffectList const& auras = me->GetAuraEffectsByType(SPELL_AURA_MOD_CHARM);
for (Unit::AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
if ((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetBase()->IsPermanent())
{
Unit::Kill(charmer, me);
return;
}
}
if (!charmer->IsInCombat())
me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, me->GetFollowAngle());
Unit* target = me->GetVictim();
if (!target || !charmer->IsValidAttackTarget(target))
AttackStart(charmer->SelectNearestTargetInAttackDistance(ATTACK_DISTANCE));
}
SpellTargetSelector::SpellTargetSelector(Unit* caster, uint32 spellId) :
_caster(caster), _spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(sSpellMgr->GetSpellInfo(spellId), caster))
{
ASSERT(_spellInfo);
}
bool SpellTargetSelector::operator()(Unit const* target) const
{
if (!target)
return false;
if (_spellInfo->CheckTarget(_caster, target) != SPELL_CAST_OK)
return false;
// copypasta from Spell::CheckRange
uint32 range_type = _spellInfo->RangeEntry ? _spellInfo->RangeEntry->type : 0;
float max_range = _caster->GetSpellMaxRangeForTarget(target, _spellInfo);
float min_range = _caster->GetSpellMinRangeForTarget(target, _spellInfo);
if (target && target != _caster)
{
if (range_type == SPELL_RANGE_MELEE)
{
// Because of lag, we can not check too strictly here.
if (!_caster->IsWithinMeleeRange(target, max_range))
return false;
}
else if (!_caster->IsWithinCombatRange(target, max_range))
return false;
if (range_type == SPELL_RANGE_RANGED)
{
if (_caster->IsWithinMeleeRange(target))
return false;
}
else if (min_range && _caster->IsWithinCombatRange(target, min_range)) // skip this check if min_range = 0
return false;
}
return true;
}
bool NonTankTargetSelector::operator()(Unit const* target) const
{
if (!target)
return false;
if (_playerOnly && target->GetTypeId() != TYPEID_PLAYER)
return false;
return target != _source->GetVictim();
}

View File

@@ -1,340 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_UNITAI_H
#define TRINITY_UNITAI_H
#include "Define.h"
#include "Unit.h"
#include "Containers.h"
#include <list>
class Player;
class Quest;
class Unit;
struct AISpellInfoType;
//Selection method used by SelectTarget
enum SelectAggroTarget
{
SELECT_TARGET_RANDOM = 0, //Just selects a random target
SELECT_TARGET_TOPAGGRO, //Selects targes from top aggro to bottom
SELECT_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top
SELECT_TARGET_NEAREST,
SELECT_TARGET_FARTHEST,
};
// default predicate function to select target based on distance, player and/or aura criteria
struct DefaultTargetSelector : public std::unary_function<Unit*, bool>
{
const Unit* me;
float m_dist;
bool m_playerOnly;
int32 m_aura;
// unit: the reference unit
// dist: if 0: ignored, if > 0: maximum distance to the reference unit, if < 0: minimum distance to the reference unit
// playerOnly: self explaining
// aura: if 0: ignored, if > 0: the target shall have the aura, if < 0, the target shall NOT have the aura
DefaultTargetSelector(Unit const* unit, float dist, bool playerOnly, int32 aura) : me(unit), m_dist(dist), m_playerOnly(playerOnly), m_aura(aura) {}
bool operator()(Unit const* target) const
{
if (!me)
return false;
if (!target)
return false;
if (m_playerOnly && (target->GetTypeId() != TYPEID_PLAYER))
return false;
if (m_dist > 0.0f && !me->IsWithinCombatRange(target, m_dist))
return false;
if (m_dist < 0.0f && me->IsWithinCombatRange(target, -m_dist))
return false;
if (m_aura)
{
if (m_aura > 0)
{
if (!target->HasAura(m_aura))
return false;
}
else
{
if (target->HasAura(-m_aura))
return false;
}
}
return true;
}
};
// Target selector for spell casts checking range, auras and attributes
// TODO: Add more checks from Spell::CheckCast
struct SpellTargetSelector : public std::unary_function<Unit*, bool>
{
public:
SpellTargetSelector(Unit* caster, uint32 spellId);
bool operator()(Unit const* target) const;
private:
Unit const* _caster;
SpellInfo const* _spellInfo;
};
// Very simple target selector, will just skip main target
// NOTE: When passing to UnitAI::SelectTarget remember to use 0 as position for random selection
// because tank will not be in the temporary list
struct NonTankTargetSelector : public std::unary_function<Unit*, bool>
{
public:
NonTankTargetSelector(Creature* source, bool playerOnly = true) : _source(source), _playerOnly(playerOnly) { }
bool operator()(Unit const* target) const;
private:
Creature const* _source;
bool _playerOnly;
};
// Simple selector for units using mana
struct PowerUsersSelector : public std::unary_function<Unit*, bool>
{
Unit const* _me;
float const _dist;
bool const _playerOnly;
Powers const _power;
PowerUsersSelector(Unit const* unit, Powers power, float dist, bool playerOnly) : _me(unit), _power(power), _dist(dist), _playerOnly(playerOnly) { }
bool operator()(Unit const* target) const
{
if (!_me || !target)
return false;
if (target->getPowerType() != _power)
return false;
if (_playerOnly && target->GetTypeId() != TYPEID_PLAYER)
return false;
if (_dist > 0.0f && !_me->IsWithinCombatRange(target, _dist))
return false;
if (_dist < 0.0f && _me->IsWithinCombatRange(target, -_dist))
return false;
return true;
}
};
struct FarthestTargetSelector : public std::unary_function<Unit*, bool>
{
FarthestTargetSelector(Unit const* unit, float dist, bool playerOnly, bool inLos) : _me(unit), _dist(dist), _playerOnly(playerOnly), _inLos(inLos) {}
bool operator()(Unit const* target) const
{
if (!_me || !target)
return false;
if (_playerOnly && target->GetTypeId() != TYPEID_PLAYER)
return false;
if (_dist > 0.0f && !_me->IsWithinCombatRange(target, _dist))
return false;
if (_inLos && !_me->IsWithinLOSInMap(target))
return false;
return true;
}
private:
const Unit* _me;
float _dist;
bool _playerOnly;
bool _inLos;
};
class UnitAI
{
protected:
Unit* const me;
public:
explicit UnitAI(Unit* unit) : me(unit) {}
virtual ~UnitAI() {}
virtual bool CanAIAttack(Unit const* /*target*/) const { return true; }
virtual void AttackStart(Unit* /*target*/);
virtual void UpdateAI(uint32 diff) = 0;
virtual void InitializeAI() { if (!me->isDead()) Reset(); }
virtual void Reset() {};
// Called when unit is charmed
virtual void OnCharmed(bool apply) = 0;
// Pass parameters between AI
virtual void DoAction(int32 /*param*/) {}
virtual uint32 GetData(uint32 /*id = 0*/) const { return 0; }
virtual void SetData(uint32 /*id*/, uint32 /*value*/) {}
virtual void SetGUID(uint64 /*guid*/, int32 /*id*/ = 0) {}
virtual uint64 GetGUID(int32 /*id*/ = 0) const { return 0; }
Unit* SelectTarget(SelectAggroTarget targetType, uint32 position = 0, float dist = 0.0f, bool playerOnly = false, int32 aura = 0);
// Select the targets satifying the predicate.
// predicate shall extend std::unary_function<Unit*, bool>
template <class PREDICATE> Unit* SelectTarget(SelectAggroTarget targetType, uint32 position, PREDICATE const& predicate)
{
ThreatContainer::StorageType const& threatlist = me->getThreatManager().getThreatList();
if (position >= threatlist.size())
return NULL;
std::list<Unit*> targetList;
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
if (predicate((*itr)->getTarget()))
targetList.push_back((*itr)->getTarget());
if (position >= targetList.size())
return NULL;
if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST)
targetList.sort(Trinity::ObjectDistanceOrderPred(me));
switch (targetType)
{
case SELECT_TARGET_NEAREST:
case SELECT_TARGET_TOPAGGRO:
{
std::list<Unit*>::iterator itr = targetList.begin();
std::advance(itr, position);
return *itr;
}
case SELECT_TARGET_FARTHEST:
case SELECT_TARGET_BOTTOMAGGRO:
{
std::list<Unit*>::reverse_iterator ritr = targetList.rbegin();
std::advance(ritr, position);
return *ritr;
}
case SELECT_TARGET_RANDOM:
{
std::list<Unit*>::iterator itr = targetList.begin();
std::advance(itr, urand(position, targetList.size() - 1));
return *itr;
}
default:
break;
}
return NULL;
}
void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, float dist = 0.0f, bool playerOnly = false, int32 aura = 0);
// Select the targets satifying the predicate.
// predicate shall extend std::unary_function<Unit*, bool>
template <class PREDICATE> void SelectTargetList(std::list<Unit*>& targetList, PREDICATE const& predicate, uint32 maxTargets, SelectAggroTarget targetType)
{
ThreatContainer::StorageType const& threatlist = me->getThreatManager().getThreatList();
if (threatlist.empty())
return;
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
if (predicate((*itr)->getTarget()))
targetList.push_back((*itr)->getTarget());
if (targetList.size() < maxTargets)
return;
if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST)
targetList.sort(Trinity::ObjectDistanceOrderPred(me));
if (targetType == SELECT_TARGET_FARTHEST || targetType == SELECT_TARGET_BOTTOMAGGRO)
targetList.reverse();
if (targetType == SELECT_TARGET_RANDOM)
Trinity::Containers::RandomResizeList(targetList, maxTargets);
else
targetList.resize(maxTargets);
}
// Called at any Damage to any victim (before damage apply)
virtual void DamageDealt(Unit* /*victim*/, uint32& /*damage*/, DamageEffectType /*damageType*/) { }
// Called at any Damage from any attacker (before damage apply)
// Note: it for recalculation damage or special reaction at damage
// for attack reaction use AttackedBy called for not DOT damage in Unit::DealDamage also
virtual void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/ ) {}
// Called when the creature receives heal
virtual void HealReceived(Unit* /*done_by*/, uint32& /*addhealth*/) {}
// Called when the unit heals
virtual void HealDone(Unit* /*done_to*/, uint32& /*addhealth*/) {}
void AttackStartCaster(Unit* victim, float dist);
void DoAddAuraToAllHostilePlayers(uint32 spellid);
void DoCast(uint32 spellId);
void DoCast(Unit* victim, uint32 spellId, bool triggered = false);
void DoCastToAllHostilePlayers(uint32 spellid, bool triggered = false);
void DoCastVictim(uint32 spellId, bool triggered = false);
void DoCastAOE(uint32 spellId, bool triggered = false);
float DoGetSpellMaxRange(uint32 spellId, bool positive = false);
void DoMeleeAttackIfReady();
bool DoSpellAttackIfReady(uint32 spell);
static AISpellInfoType* AISpellInfo;
static void FillAISpellInfo();
virtual void sGossipHello(Player* /*player*/) {}
virtual void sGossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) {}
virtual void sGossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, char const* /*code*/) {}
virtual void sQuestAccept(Player* /*player*/, Quest const* /*quest*/) {}
virtual void sQuestSelect(Player* /*player*/, Quest const* /*quest*/) {}
virtual void sQuestComplete(Player* /*player*/, Quest const* /*quest*/) {}
virtual void sQuestReward(Player* /*player*/, Quest const* /*quest*/, uint32 /*opt*/) {}
virtual void sOnGameEvent(bool /*start*/, uint16 /*eventId*/) {}
};
class PlayerAI : public UnitAI
{
protected:
Player* const me;
public:
explicit PlayerAI(Player* player) : UnitAI((Unit*)player), me(player) {}
void OnCharmed(bool apply);
};
class SimpleCharmedAI : public PlayerAI
{
public:
void UpdateAI(uint32 diff);
SimpleCharmedAI(Player* player): PlayerAI(player) {}
};
#endif

View File

@@ -1,268 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CreatureAI.h"
#include "CreatureAIImpl.h"
#include "Creature.h"
#include "World.h"
#include "SpellMgr.h"
#include "Vehicle.h"
#include "Log.h"
#include "MapReference.h"
#include "Player.h"
#include "CreatureTextMgr.h"
//Disable CreatureAI when charmed
void CreatureAI::OnCharmed(bool /*apply*/)
{
//me->IsAIEnabled = !apply;*/
me->NeedChangeAI = true;
me->IsAIEnabled = false;
}
AISpellInfoType* UnitAI::AISpellInfo;
AISpellInfoType* GetAISpellInfo(uint32 i) { return &CreatureAI::AISpellInfo[i]; }
void CreatureAI::Talk(uint8 id, WorldObject const* whisperTarget /*= NULL*/)
{
sCreatureTextMgr->SendChat(me, id, whisperTarget);
}
void CreatureAI::DoZoneInCombat(Creature* creature /*= NULL*/, float maxRangeToNearestTarget /* = 50.0f*/)
{
if (!creature)
creature = me;
if (!creature->CanHaveThreatList())
return;
Map* map = creature->GetMap();
if (!map->IsDungeon()) //use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated
{
sLog->outError("DoZoneInCombat call for map that isn't an instance (creature entry = %d)", creature->GetTypeId() == TYPEID_UNIT ? creature->ToCreature()->GetEntry() : 0);
return;
}
// Xinef: Skip creatures in evade mode
if (!creature->HasReactState(REACT_PASSIVE) && !creature->GetVictim() && !creature->IsInEvadeMode())
{
if (Unit* nearTarget = creature->SelectNearestTarget(maxRangeToNearestTarget))
creature->AI()->AttackStart(nearTarget);
else if (creature->IsSummon())
{
if (Unit* summoner = creature->ToTempSummon()->GetSummoner())
{
Unit* target = summoner->getAttackerForHelper();
if (!target && summoner->CanHaveThreatList() && !summoner->getThreatManager().isThreatListEmpty())
target = summoner->getThreatManager().getHostilTarget();
if (target && (creature->IsFriendlyTo(summoner) || creature->IsHostileTo(target)))
creature->AI()->AttackStart(target);
}
}
}
if (!creature->HasReactState(REACT_PASSIVE) && !creature->GetVictim())
{
sLog->outError("DoZoneInCombat called for creature that has empty threat list (creature entry = %u)", creature->GetEntry());
return;
}
Map::PlayerList const& playerList = map->GetPlayers();
if (playerList.isEmpty())
return;
for (Map::PlayerList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr)
{
if (Player* player = itr->GetSource())
{
if (player->IsGameMaster())
continue;
if (player->IsAlive())
{
creature->SetInCombatWith(player);
player->SetInCombatWith(creature);
creature->AddThreat(player, 0.0f);
}
/* Causes certain things to never leave the threat list (Priest Lightwell, etc):
for (Unit::ControlSet::const_iterator itr = player->m_Controlled.begin(); itr != player->m_Controlled.end(); ++itr)
{
creature->SetInCombatWith(*itr);
(*itr)->SetInCombatWith(creature);
creature->AddThreat(*itr, 0.0f);
}*/
}
}
}
// scripts does not take care about MoveInLineOfSight loops
// MoveInLineOfSight can be called inside another MoveInLineOfSight and cause stack overflow
void CreatureAI::MoveInLineOfSight_Safe(Unit* who)
{
if (m_MoveInLineOfSight_locked == true)
return;
m_MoveInLineOfSight_locked = true;
MoveInLineOfSight(who);
m_MoveInLineOfSight_locked = false;
}
void CreatureAI::MoveInLineOfSight(Unit* who)
{
if (me->GetVictim())
return;
// pussywizard: civilian, non-combat pet or any other NOT HOSTILE TO ANYONE (!)
if (me->IsMoveInLineOfSightDisabled())
if (me->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET || // nothing more to do, return
!who->IsInCombat() || // if not in combat, nothing more to do
!me->IsWithinDist(who, ATTACK_DISTANCE)) // if in combat and in dist - neutral to all can actually assist other creatures
return;
if (me->CanStartAttack(who))
AttackStart(who);
}
void CreatureAI::EnterEvadeMode()
{
if (!_EnterEvadeMode())
return;
;//sLog->outDebug(LOG_FILTER_UNITS, "Creature %u enters evade mode.", me->GetEntry());
if (!me->GetVehicle()) // otherwise me will be in evade mode forever
{
if (Unit* owner = me->GetCharmerOrOwner())
{
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE);
}
else
{
// Required to prevent attacking creatures that are evading and cause them to reenter combat
// Does not apply to MoveFollow
me->AddUnitState(UNIT_STATE_EVADE);
me->GetMotionMaster()->MoveTargetedHome();
}
}
Reset();
if (me->IsVehicle()) // use the same sequence of addtoworld, aireset may remove all summons!
me->GetVehicleKit()->Reset(true);
}
/*void CreatureAI::AttackedBy(Unit* attacker)
{
if (!me->GetVictim())
AttackStart(attacker);
}*/
void CreatureAI::SetGazeOn(Unit* target)
{
if (me->IsValidAttackTarget(target))
{
AttackStart(target);
me->SetReactState(REACT_PASSIVE);
}
}
bool CreatureAI::UpdateVictimWithGaze()
{
if (!me->IsInCombat())
return false;
if (me->HasReactState(REACT_PASSIVE))
{
if (me->GetVictim())
return true;
else
me->SetReactState(REACT_AGGRESSIVE);
}
if (Unit* victim = me->SelectVictim())
AttackStart(victim);
return me->GetVictim();
}
bool CreatureAI::UpdateVictim()
{
if (!me->IsInCombat())
return false;
if (!me->HasReactState(REACT_PASSIVE))
{
if (Unit* victim = me->SelectVictim())
AttackStart(victim);
return me->GetVictim();
}
// xinef: if we have any victim, just return true
else if (me->GetVictim() && me->GetExactDist(me->GetVictim()) < 30.0f)
return true;
else if (me->getThreatManager().isThreatListEmpty())
{
EnterEvadeMode();
return false;
}
return true;
}
bool CreatureAI::_EnterEvadeMode()
{
if (!me->IsAlive())
return false;
// don't remove vehicle auras, passengers aren't supposed to drop off the vehicle
// don't remove clone caster on evade (to be verified)
me->RemoveEvadeAuras();
// sometimes bosses stuck in combat?
me->DeleteThreatList();
me->CombatStop(true);
me->LoadCreaturesAddon(true);
me->SetLootRecipient(NULL);
me->ResetPlayerDamageReq();
me->SetLastDamagedTime(0);
if (me->IsInEvadeMode())
return false;
return true;
}
Creature* CreatureAI::DoSummon(uint32 entry, const Position& pos, uint32 despawnTime, TempSummonType summonType)
{
return me->SummonCreature(entry, pos, summonType, despawnTime);
}
Creature* CreatureAI::DoSummon(uint32 entry, WorldObject* obj, float radius, uint32 despawnTime, TempSummonType summonType)
{
Position pos;
obj->GetRandomNearPosition(pos, radius);
return me->SummonCreature(entry, pos, summonType, despawnTime);
}
Creature* CreatureAI::DoSummonFlyer(uint32 entry, WorldObject* obj, float flightZ, float radius, uint32 despawnTime, TempSummonType summonType)
{
Position pos;
obj->GetRandomNearPosition(pos, radius);
pos.m_positionZ += flightZ;
return me->SummonCreature(entry, pos, summonType, despawnTime);
}

View File

@@ -1,193 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_CREATUREAI_H
#define TRINITY_CREATUREAI_H
#include "Creature.h"
#include "UnitAI.h"
#include "Common.h"
class WorldObject;
class Unit;
class Creature;
class Player;
class SpellInfo;
#define TIME_INTERVAL_LOOK 5000
#define VISIBILITY_RANGE 10000
//Spell targets used by SelectSpell
enum SelectTargetType
{
SELECT_TARGET_DONTCARE = 0, //All target types allowed
SELECT_TARGET_SELF, //Only Self casting
SELECT_TARGET_SINGLE_ENEMY, //Only Single Enemy
SELECT_TARGET_AOE_ENEMY, //Only AoE Enemy
SELECT_TARGET_ANY_ENEMY, //AoE or Single Enemy
SELECT_TARGET_SINGLE_FRIEND, //Only Single Friend
SELECT_TARGET_AOE_FRIEND, //Only AoE Friend
SELECT_TARGET_ANY_FRIEND, //AoE or Single Friend
};
//Spell Effects used by SelectSpell
enum SelectEffect
{
SELECT_EFFECT_DONTCARE = 0, //All spell effects allowed
SELECT_EFFECT_DAMAGE, //Spell does damage
SELECT_EFFECT_HEALING, //Spell does healing
SELECT_EFFECT_AURA, //Spell applies an aura
};
enum SCEquip
{
EQUIP_NO_CHANGE = -1,
EQUIP_UNEQUIP = 0
};
class CreatureAI : public UnitAI
{
protected:
Creature* const me;
bool UpdateVictim();
bool UpdateVictimWithGaze();
void SetGazeOn(Unit* target);
Creature* DoSummon(uint32 entry, Position const& pos, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN);
Creature* DoSummon(uint32 entry, WorldObject* obj, float radius = 5.0f, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN);
Creature* DoSummonFlyer(uint32 entry, WorldObject* obj, float flightZ, float radius = 5.0f, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN);
public:
void Talk(uint8 id, WorldObject const* whisperTarget = NULL);
explicit CreatureAI(Creature* creature) : UnitAI(creature), me(creature), m_MoveInLineOfSight_locked(false) {}
virtual ~CreatureAI() {}
/// == Reactions At =================================
// Called if IsVisible(Unit* who) is true at each who move, reaction at visibility zone enter
void MoveInLineOfSight_Safe(Unit* who);
// Called in Creature::Update when deathstate = DEAD. Inherited classes may maniuplate the ability to respawn based on scripted events.
virtual bool CanRespawn() { return true; }
// Called for reaction at stopping attack at no attackers or targets
virtual void EnterEvadeMode();
// Called for reaction at enter to combat if not in combat yet (enemy can be NULL)
virtual void EnterCombat(Unit* /*victim*/) {}
// Called when the creature is killed
virtual void JustDied(Unit* /*killer*/) {}
// Called when the creature kills a unit
virtual void KilledUnit(Unit* /*victim*/) {}
// Called when the creature summon successfully other creature
virtual void JustSummoned(Creature* /*summon*/) {}
virtual void IsSummonedBy(Unit* /*summoner*/) {}
virtual void SummonedCreatureDespawn(Creature* /*summon*/) {}
virtual void SummonedCreatureDies(Creature* /*summon*/, Unit* /*killer*/) {}
// Called when hit by a spell
virtual void SpellHit(Unit* /*caster*/, SpellInfo const* /*spell*/) {}
// Called when spell hits a target
virtual void SpellHitTarget(Unit* /*target*/, SpellInfo const* /*spell*/) {}
// Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc)
virtual void AttackedBy(Unit* /*attacker*/) {}
virtual bool IsEscorted() { return false; }
// Called when creature is spawned or respawned (for reseting variables)
virtual void JustRespawned() { Reset(); }
// Called at waypoint reached or point movement finished
virtual void MovementInform(uint32 /*type*/, uint32 /*id*/) {}
void OnCharmed(bool apply);
// Called at reaching home after evade
virtual void JustReachedHome() {}
void DoZoneInCombat(Creature* creature = NULL, float maxRangeToNearestTarget = 50.0f);
// Called at text emote receive from player
virtual void ReceiveEmote(Player* /*player*/, uint32 /*emoteId*/) {}
// Called when owner takes damage
virtual void OwnerAttackedBy(Unit* /*attacker*/) {}
// Called when owner attacks something
virtual void OwnerAttacked(Unit* /*target*/) {}
/// == Triggered Actions Requested ==================
// Called when creature attack expected (if creature can and no have current victim)
// Note: for reaction at hostile action must be called AttackedBy function.
//virtual void AttackStart(Unit*) {}
// Called at World update tick
//virtual void UpdateAI(uint32 /*diff*/) {}
/// == State checks =================================
// Is unit visible for MoveInLineOfSight
//virtual bool IsVisible(Unit*) const { return false; }
// called when the corpse of this creature gets removed
virtual void CorpseRemoved(uint32& /*respawnDelay*/) {}
// Called when victim entered water and creature can not enter water
//virtual bool CanReachByRangeAttack(Unit*) { return false; }
/// == Fields =======================================
virtual void PassengerBoarded(Unit* /*passenger*/, int8 /*seatId*/, bool /*apply*/) {}
virtual void OnSpellClick(Unit* /*clicker*/, bool& /*result*/) { }
virtual bool CanSeeAlways(WorldObject const* /*obj*/) { return false; }
virtual bool CanBeSeen(Player const* /*seer*/) { return true; }
protected:
virtual void MoveInLineOfSight(Unit* /*who*/);
bool _EnterEvadeMode();
private:
bool m_MoveInLineOfSight_locked;
};
enum Permitions
{
PERMIT_BASE_NO = -1,
PERMIT_BASE_IDLE = 1,
PERMIT_BASE_REACTIVE = 100,
PERMIT_BASE_PROACTIVE = 200,
PERMIT_BASE_FACTION_SPECIFIC = 400,
PERMIT_BASE_SPECIAL = 800
};
#endif

View File

@@ -1,80 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_CREATUREAIFACTORY_H
#define TRINITY_CREATUREAIFACTORY_H
//#include "Policies/Singleton.h"
#include "ObjectRegistry.h"
#include "FactoryHolder.h"
#include "GameObjectAI.h"
struct SelectableAI : public FactoryHolder<CreatureAI>, public Permissible<Creature>
{
SelectableAI(const char* id) : FactoryHolder<CreatureAI>(id) {}
};
template<class REAL_AI>
struct CreatureAIFactory : public SelectableAI
{
CreatureAIFactory(const char* name) : SelectableAI(name) {}
CreatureAI* Create(void*) const;
int Permit(const Creature* c) const { return REAL_AI::Permissible(c); }
};
template<class REAL_AI>
inline CreatureAI*
CreatureAIFactory<REAL_AI>::Create(void* data) const
{
Creature* creature = reinterpret_cast<Creature*>(data);
return (new REAL_AI(creature));
}
typedef FactoryHolder<CreatureAI> CreatureAICreator;
typedef FactoryHolder<CreatureAI>::FactoryHolderRegistry CreatureAIRegistry;
typedef FactoryHolder<CreatureAI>::FactoryHolderRepository CreatureAIRepository;
//GO
struct SelectableGameObjectAI : public FactoryHolder<GameObjectAI>, public Permissible<GameObject>
{
SelectableGameObjectAI(const char* id) : FactoryHolder<GameObjectAI>(id) {}
};
template<class REAL_GO_AI>
struct GameObjectAIFactory : public SelectableGameObjectAI
{
GameObjectAIFactory(const char* name) : SelectableGameObjectAI(name) {}
GameObjectAI* Create(void*) const;
int Permit(const GameObject* g) const { return REAL_GO_AI::Permissible(g); }
};
template<class REAL_GO_AI>
inline GameObjectAI*
GameObjectAIFactory<REAL_GO_AI>::Create(void* data) const
{
GameObject* go = reinterpret_cast<GameObject*>(data);
return (new REAL_GO_AI(go));
}
typedef FactoryHolder<GameObjectAI> GameObjectAICreator;
typedef FactoryHolder<GameObjectAI>::FactoryHolderRegistry GameObjectAIRegistry;
typedef FactoryHolder<GameObjectAI>::FactoryHolderRepository GameObjectAIRepository;
#endif

View File

@@ -1,347 +0,0 @@
/*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CREATUREAIIMPL_H
#define CREATUREAIIMPL_H
#include "Common.h"
#include "Define.h"
#include "TemporarySummon.h"
#include "CreatureAI.h"
#include "SpellMgr.h"
template<class T>
inline
const T& RAND(const T& v1, const T& v2)
{
return (urand(0, 1)) ? v1 : v2;
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3)
{
switch (urand(0, 2))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
}
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4)
{
switch (urand(0, 3))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
case 3: return v4;
}
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
{
switch (urand(0, 4))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
case 3: return v4;
case 4: return v5;
}
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6)
{
switch (urand(0, 5))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
case 3: return v4;
case 4: return v5;
case 5: return v6;
}
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7)
{
switch (urand(0, 6))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
case 3: return v4;
case 4: return v5;
case 5: return v6;
case 6: return v7;
}
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8)
{
switch (urand(0, 7))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
case 3: return v4;
case 4: return v5;
case 5: return v6;
case 6: return v7;
case 7: return v8;
}
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
const T& v9)
{
switch (urand(0, 8))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
case 3: return v4;
case 4: return v5;
case 5: return v6;
case 6: return v7;
case 7: return v8;
case 8: return v9;
}
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
const T& v9, const T& v10)
{
switch (urand(0, 9))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
case 3: return v4;
case 4: return v5;
case 5: return v6;
case 6: return v7;
case 7: return v8;
case 8: return v9;
case 9: return v10;
}
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
const T& v9, const T& v10, const T& v11)
{
switch (urand(0, 10))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
case 3: return v4;
case 4: return v5;
case 5: return v6;
case 6: return v7;
case 7: return v8;
case 8: return v9;
case 9: return v10;
case 10: return v11;
}
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
const T& v9, const T& v10, const T& v11, const T& v12)
{
switch (urand(0, 11))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
case 3: return v4;
case 4: return v5;
case 5: return v6;
case 6: return v7;
case 7: return v8;
case 8: return v9;
case 9: return v10;
case 10: return v11;
case 11: return v12;
}
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
const T& v9, const T& v10, const T& v11, const T& v12, const T& v13)
{
switch (urand(0, 12))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
case 3: return v4;
case 4: return v5;
case 5: return v6;
case 6: return v7;
case 7: return v8;
case 8: return v9;
case 9: return v10;
case 10: return v11;
case 11: return v12;
case 12: return v13;
}
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
const T& v9, const T& v10, const T& v11, const T& v12, const T& v13, const T& v14)
{
switch (urand(0, 13))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
case 3: return v4;
case 4: return v5;
case 5: return v6;
case 6: return v7;
case 7: return v8;
case 8: return v9;
case 9: return v10;
case 10: return v11;
case 11: return v12;
case 12: return v13;
case 13: return v14;
}
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
const T& v9, const T& v10, const T& v11, const T& v12, const T& v13, const T& v14, const T& v15)
{
switch (urand(0, 14))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
case 3: return v4;
case 4: return v5;
case 5: return v6;
case 6: return v7;
case 7: return v8;
case 8: return v9;
case 9: return v10;
case 10: return v11;
case 11: return v12;
case 12: return v13;
case 13: return v14;
case 14: return v15;
}
}
template<class T>
inline
const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8,
const T& v9, const T& v10, const T& v11, const T& v12, const T& v13, const T& v14, const T& v15, const T& v16)
{
switch (urand(0, 15))
{
default:
case 0: return v1;
case 1: return v2;
case 2: return v3;
case 3: return v4;
case 4: return v5;
case 5: return v6;
case 6: return v7;
case 7: return v8;
case 8: return v9;
case 9: return v10;
case 10: return v11;
case 11: return v12;
case 12: return v13;
case 13: return v14;
case 14: return v15;
case 15: return v16;
}
}
enum AITarget
{
AITARGET_SELF,
AITARGET_VICTIM,
AITARGET_ENEMY,
AITARGET_ALLY,
AITARGET_BUFF,
AITARGET_DEBUFF,
};
enum AICondition
{
AICOND_AGGRO,
AICOND_COMBAT,
AICOND_DIE,
};
#define AI_DEFAULT_COOLDOWN 5000
struct AISpellInfoType
{
AISpellInfoType() : target(AITARGET_SELF), condition(AICOND_COMBAT)
, cooldown(AI_DEFAULT_COOLDOWN), realCooldown(0), maxRange(0.0f){}
AITarget target;
AICondition condition;
uint32 cooldown;
uint32 realCooldown;
float maxRange;
};
AISpellInfoType* GetAISpellInfo(uint32 i);
#endif

View File

@@ -1,59 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PassiveAI.h"
#include "ReactorAI.h"
#include "CombatAI.h"
#include "GuardAI.h"
#include "PetAI.h"
#include "TotemAI.h"
#include "RandomMovementGenerator.h"
#include "MovementGeneratorImpl.h"
#include "CreatureAIRegistry.h"
#include "WaypointMovementGenerator.h"
#include "CreatureAIFactory.h"
#include "SmartAI.h"
//#include "CreatureAIImpl.h"
namespace AIRegistry
{
void Initialize()
{
(new CreatureAIFactory<NullCreatureAI>("NullCreatureAI"))->RegisterSelf();
(new CreatureAIFactory<TriggerAI>("TriggerAI"))->RegisterSelf();
(new CreatureAIFactory<AggressorAI>("AggressorAI"))->RegisterSelf();
(new CreatureAIFactory<ReactorAI>("ReactorAI"))->RegisterSelf();
(new CreatureAIFactory<PassiveAI>("PassiveAI"))->RegisterSelf();
(new CreatureAIFactory<CritterAI>("CritterAI"))->RegisterSelf();
(new CreatureAIFactory<GuardAI>("GuardAI"))->RegisterSelf();
(new CreatureAIFactory<PetAI>("PetAI"))->RegisterSelf();
(new CreatureAIFactory<TotemAI>("TotemAI"))->RegisterSelf();
(new CreatureAIFactory<CombatAI>("CombatAI"))->RegisterSelf();
(new CreatureAIFactory<ArcherAI>("ArcherAI"))->RegisterSelf();
(new CreatureAIFactory<TurretAI>("TurretAI"))->RegisterSelf();
(new CreatureAIFactory<VehicleAI>("VehicleAI"))->RegisterSelf();
(new CreatureAIFactory<SmartAI>("SmartAI"))->RegisterSelf();
(new GameObjectAIFactory<GameObjectAI>("GameObjectAI"))->RegisterSelf();
(new GameObjectAIFactory<SmartGameObjectAI>("SmartGameObjectAI"))->RegisterSelf();
(new MovementGeneratorFactory<RandomMovementGenerator<Creature> >(RANDOM_MOTION_TYPE))->RegisterSelf();
(new MovementGeneratorFactory<WaypointMovementGenerator<Creature> >(WAYPOINT_MOTION_TYPE))->RegisterSelf();
}
}

View File

@@ -1,27 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_CREATUREAIREGISTRY_H
#define TRINITY_CREATUREAIREGISTRY_H
namespace AIRegistry
{
void Initialize(void);
}
#endif

View File

@@ -1,154 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Creature.h"
#include "CreatureAISelector.h"
#include "PassiveAI.h"
#include "MovementGenerator.h"
#include "Pet.h"
#include "TemporarySummon.h"
#include "CreatureAIFactory.h"
#include "ScriptMgr.h"
namespace FactorySelector
{
CreatureAI* selectAI(Creature* creature)
{
const CreatureAICreator* ai_factory = NULL;
CreatureAIRegistry& ai_registry(*CreatureAIRepository::instance());
// xinef: if we have controlable guardian, define petai for players as they can steer him, otherwise db / normal ai
// xinef: dont remember why i changed this qq commented out as may break some quests
if (creature->IsPet()/* || (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Guardian*)creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER)*/)
ai_factory = ai_registry.GetRegistryItem("PetAI");
//scriptname in db
if (!ai_factory)
if (CreatureAI* scriptedAI = sScriptMgr->GetCreatureAI(creature))
return scriptedAI;
// AIname in db
std::string ainame=creature->GetAIName();
if (!ai_factory && !ainame.empty())
ai_factory = ai_registry.GetRegistryItem(ainame);
// select by NPC flags
if (!ai_factory)
{
if (creature->IsVehicle())
ai_factory = ai_registry.GetRegistryItem("VehicleAI");
else if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Guardian*)creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER)
ai_factory = ai_registry.GetRegistryItem("PetAI");
else if (creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK))
ai_factory = ai_registry.GetRegistryItem("NullCreatureAI");
else if (creature->IsGuard())
ai_factory = ai_registry.GetRegistryItem("GuardAI");
else if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
ai_factory = ai_registry.GetRegistryItem("PetAI");
else if (creature->IsTotem())
ai_factory = ai_registry.GetRegistryItem("TotemAI");
else if (creature->IsTrigger())
{
if (creature->m_spells[0])
ai_factory = ai_registry.GetRegistryItem("TriggerAI");
else
ai_factory = ai_registry.GetRegistryItem("NullCreatureAI");
}
else if (creature->IsCritter() && !creature->HasUnitTypeMask(UNIT_MASK_GUARDIAN))
ai_factory = ai_registry.GetRegistryItem("CritterAI");
}
// select by permit check
if (!ai_factory)
{
int best_val = -1;
typedef CreatureAIRegistry::RegistryMapType RMT;
RMT const& l = ai_registry.GetRegisteredItems();
for (RMT::const_iterator iter = l.begin(); iter != l.end(); ++iter)
{
const CreatureAICreator* factory = iter->second;
const SelectableAI* p = dynamic_cast<const SelectableAI*>(factory);
ASSERT(p);
int val = p->Permit(creature);
if (val > best_val)
{
best_val = val;
ai_factory = p;
}
}
}
// select NullCreatureAI if not another cases
// xinef: unused
// ainame = (ai_factory == NULL) ? "NullCreatureAI" : ai_factory->key();
;//sLog->outDebug(LOG_FILTER_TSCR, "Creature %u used AI is %s.", creature->GetGUIDLow(), ainame.c_str());
return (ai_factory == NULL ? new NullCreatureAI(creature) : ai_factory->Create(creature));
}
MovementGenerator* selectMovementGenerator(Creature* creature)
{
MovementGeneratorRegistry& mv_registry(*MovementGeneratorRepository::instance());
ASSERT(creature->GetCreatureTemplate());
const MovementGeneratorCreator* mv_factory = mv_registry.GetRegistryItem(creature->GetDefaultMovementType());
/* if (mv_factory == NULL)
{
int best_val = -1;
StringVector l;
mv_registry.GetRegisteredItems(l);
for (StringVector::iterator iter = l.begin(); iter != l.end(); ++iter)
{
const MovementGeneratorCreator *factory = mv_registry.GetRegistryItem((*iter).c_str());
const SelectableMovement *p = dynamic_cast<const SelectableMovement *>(factory);
ASSERT(p != NULL);
int val = p->Permit(creature);
if (val > best_val)
{
best_val = val;
mv_factory = p;
}
}
}*/
return (mv_factory == NULL ? NULL : mv_factory->Create(creature));
}
GameObjectAI* SelectGameObjectAI(GameObject* go)
{
const GameObjectAICreator* ai_factory = NULL;
GameObjectAIRegistry& ai_registry(*GameObjectAIRepository::instance());
if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go))
return scriptedAI;
ai_factory = ai_registry.GetRegistryItem(go->GetAIName());
//future goAI types go here
// xinef: unused
//std::string ainame = (ai_factory == NULL || go->GetScriptId()) ? "NullGameObjectAI" : ai_factory->key();
;//sLog->outDebug(LOG_FILTER_TSCR, "GameObject %u used AI is %s.", go->GetGUIDLow(), ainame.c_str());
return (ai_factory == NULL ? new NullGameObjectAI(go) : ai_factory->Create(go));
}
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_CREATUREAISELECTOR_H
#define TRINITY_CREATUREAISELECTOR_H
class CreatureAI;
class Creature;
class MovementGenerator;
class GameObjectAI;
class GameObject;
namespace FactorySelector
{
CreatureAI* selectAI(Creature*);
MovementGenerator* selectMovementGenerator(Creature*);
GameObjectAI* SelectGameObjectAI(GameObject*);
}
#endif

View File

@@ -1,668 +0,0 @@
/*
* Copyright (C)
*
*
*
* This program is free software licensed under GPL version 2
* Please see the included DOCS/LICENSE.TXT for more information */
#include "ScriptedCreature.h"
#include "Item.h"
#include "Spell.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "Cell.h"
#include "CellImpl.h"
#include "ObjectMgr.h"
#include "TemporarySummon.h"
// Spell summary for ScriptedAI::SelectSpell
struct TSpellSummary
{
uint8 Targets; // set of enum SelectTarget
uint8 Effects; // set of enum SelectEffect
} extern* SpellSummary;
void SummonList::DoZoneInCombat(uint32 entry)
{
for (StorageType::iterator i = storage_.begin(); i != storage_.end();)
{
Creature* summon = ObjectAccessor::GetCreature(*me, *i);
++i;
if (summon && summon->IsAIEnabled
&& (!entry || summon->GetEntry() == entry))
{
summon->AI()->DoZoneInCombat();
}
}
}
void SummonList::DespawnEntry(uint32 entry)
{
for (StorageType::iterator i = storage_.begin(); i != storage_.end();)
{
Creature* summon = ObjectAccessor::GetCreature(*me, *i);
if (!summon)
i = storage_.erase(i);
else if (summon->GetEntry() == entry)
{
i = storage_.erase(i);
summon->DespawnOrUnsummon();
}
else
++i;
}
}
void SummonList::DespawnAll()
{
while (!storage_.empty())
{
Creature* summon = ObjectAccessor::GetCreature(*me, storage_.front());
storage_.pop_front();
if (summon)
summon->DespawnOrUnsummon();
}
}
void SummonList::RemoveNotExisting()
{
for (StorageType::iterator i = storage_.begin(); i != storage_.end();)
{
if (ObjectAccessor::GetCreature(*me, *i))
++i;
else
i = storage_.erase(i);
}
}
bool SummonList::HasEntry(uint32 entry) const
{
for (StorageType::const_iterator i = storage_.begin(); i != storage_.end(); ++i)
{
Creature* summon = ObjectAccessor::GetCreature(*me, *i);
if (summon && summon->GetEntry() == entry)
return true;
}
return false;
}
uint32 SummonList::GetEntryCount(uint32 entry) const
{
uint32 count = 0;
for (StorageType::const_iterator i = storage_.begin(); i != storage_.end(); ++i)
{
Creature* summon = ObjectAccessor::GetCreature(*me, *i);
if (summon && summon->GetEntry() == entry)
++count;
}
return count;
}
void SummonList::Respawn()
{
for (StorageType::iterator i = storage_.begin(); i != storage_.end();)
{
if (Creature* summon = ObjectAccessor::GetCreature(*me, *i))
{
summon->Respawn(true);
++i;
}
else
i = storage_.erase(i);
}
}
Creature* SummonList::GetCreatureWithEntry(uint32 entry) const
{
for (StorageType::const_iterator i = storage_.begin(); i != storage_.end(); ++i)
{
if (Creature* summon = ObjectAccessor::GetCreature(*me, *i))
if (summon->GetEntry() == entry)
return summon;
}
return NULL;
}
ScriptedAI::ScriptedAI(Creature* creature) : CreatureAI(creature),
me(creature),
IsFleeing(false),
_evadeCheckCooldown(2500),
_isCombatMovementAllowed(true)
{
_isHeroic = me->GetMap()->IsHeroic();
_difficulty = Difficulty(me->GetMap()->GetSpawnMode());
}
void ScriptedAI::AttackStartNoMove(Unit* who)
{
if (!who)
return;
if (me->Attack(who, true))
DoStartNoMovement(who);
}
void ScriptedAI::AttackStart(Unit* who)
{
if (IsCombatMovementAllowed())
CreatureAI::AttackStart(who);
else
AttackStartNoMove(who);
}
void ScriptedAI::UpdateAI(uint32 /*diff*/)
{
//Check if we have a current target
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
void ScriptedAI::DoStartMovement(Unit* victim, float distance, float angle)
{
if (victim)
me->GetMotionMaster()->MoveChase(victim, distance, angle);
}
void ScriptedAI::DoStartNoMovement(Unit* victim)
{
if (!victim)
return;
me->GetMotionMaster()->MoveIdle();
}
void ScriptedAI::DoStopAttack()
{
if (me->GetVictim())
me->AttackStop();
}
void ScriptedAI::DoCastSpell(Unit* target, SpellInfo const* spellInfo, bool triggered)
{
if (!target || me->IsNonMeleeSpellCast(false))
return;
me->StopMoving();
me->CastSpell(target, spellInfo, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE);
}
void ScriptedAI::DoPlaySoundToSet(WorldObject* source, uint32 soundId)
{
if (!source)
return;
if (!sSoundEntriesStore.LookupEntry(soundId))
{
sLog->outError("TSCR: Invalid soundId %u used in DoPlaySoundToSet (Source: TypeId %u, GUID %u)", soundId, source->GetTypeId(), source->GetGUIDLow());
return;
}
source->PlayDirectSound(soundId);
}
Creature* ScriptedAI::DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, uint32 type, uint32 despawntime)
{
return me->SummonCreature(entry, me->GetPositionX() + offsetX, me->GetPositionY() + offsetY, me->GetPositionZ() + offsetZ, angle, TempSummonType(type), despawntime);
}
SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mechanic, SelectTargetType targets, uint32 powerCostMin, uint32 powerCostMax, float rangeMin, float rangeMax, SelectEffect effects)
{
//No target so we can't cast
if (!target)
return NULL;
//Silenced so we can't cast
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
return NULL;
//Using the extended script system we first create a list of viable spells
SpellInfo const* apSpell[CREATURE_MAX_SPELLS];
memset(apSpell, 0, CREATURE_MAX_SPELLS * sizeof(SpellInfo*));
uint32 spellCount = 0;
SpellInfo const* tempSpell = NULL;
//Check if each spell is viable(set it to null if not)
for (uint32 i = 0; i < CREATURE_MAX_SPELLS; i++)
{
tempSpell = sSpellMgr->GetSpellInfo(me->m_spells[i]);
//This spell doesn't exist
if (!tempSpell)
continue;
// Targets and Effects checked first as most used restrictions
//Check the spell targets if specified
if (targets && !(SpellSummary[me->m_spells[i]].Targets & (1 << (targets-1))))
continue;
//Check the type of spell if we are looking for a specific spell type
if (effects && !(SpellSummary[me->m_spells[i]].Effects & (1 << (effects-1))))
continue;
//Check for school if specified
if (school && (tempSpell->SchoolMask & school) == 0)
continue;
//Check for spell mechanic if specified
if (mechanic && tempSpell->Mechanic != mechanic)
continue;
//Make sure that the spell uses the requested amount of power
if (powerCostMin && tempSpell->ManaCost < powerCostMin)
continue;
if (powerCostMax && tempSpell->ManaCost > powerCostMax)
continue;
//Continue if we don't have the mana to actually cast this spell
if (tempSpell->ManaCost > me->GetPower(Powers(tempSpell->PowerType)))
continue;
//Check if the spell meets our range requirements
if (rangeMin && me->GetSpellMinRangeForTarget(target, tempSpell) < rangeMin)
continue;
if (rangeMax && me->GetSpellMaxRangeForTarget(target, tempSpell) > rangeMax)
continue;
//Check if our target is in range
if (me->IsWithinDistInMap(target, float(me->GetSpellMinRangeForTarget(target, tempSpell))) || !me->IsWithinDistInMap(target, float(me->GetSpellMaxRangeForTarget(target, tempSpell))))
continue;
//All good so lets add it to the spell list
apSpell[spellCount] = tempSpell;
++spellCount;
}
//We got our usable spells so now lets randomly pick one
if (!spellCount)
return NULL;
return apSpell[urand(0, spellCount - 1)];
}
void ScriptedAI::DoResetThreat()
{
if (!me->CanHaveThreatList() || me->getThreatManager().isThreatListEmpty())
{
sLog->outError("DoResetThreat called for creature that either cannot have threat list or has empty threat list (me entry = %d)", me->GetEntry());
return;
}
me->getThreatManager().resetAllAggro();
}
float ScriptedAI::DoGetThreat(Unit* unit)
{
if (!unit)
return 0.0f;
return me->getThreatManager().getThreat(unit);
}
void ScriptedAI::DoModifyThreatPercent(Unit* unit, int32 pct)
{
if (!unit)
return;
me->getThreatManager().modifyThreatPercent(unit, pct);
}
void ScriptedAI::DoTeleportPlayer(Unit* unit, float x, float y, float z, float o)
{
if (!unit)
return;
if (Player* player = unit->ToPlayer())
player->TeleportTo(unit->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT);
else
sLog->outError("TSCR: Creature " UI64FMTD " (Entry: %u) Tried to teleport non-player unit (Type: %u GUID: " UI64FMTD ") to x: %f y:%f z: %f o: %f. Aborted.", me->GetGUID(), me->GetEntry(), unit->GetTypeId(), unit->GetGUID(), x, y, z, o);
}
void ScriptedAI::DoTeleportAll(float x, float y, float z, float o)
{
Map* map = me->GetMap();
if (!map->IsDungeon())
return;
Map::PlayerList const& PlayerList = map->GetPlayers();
for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr)
if (Player* player = itr->GetSource())
if (player->IsAlive())
player->TeleportTo(me->GetMapId(), x, y, z, o, TELE_TO_NOT_LEAVE_COMBAT);
}
Unit* ScriptedAI::DoSelectLowestHpFriendly(float range, uint32 minHPDiff)
{
Unit* unit = NULL;
Trinity::MostHPMissingInRange u_check(me, range, minHPDiff);
Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange> searcher(me, unit, u_check);
me->VisitNearbyObject(range, searcher);
return unit;
}
std::list<Creature*> ScriptedAI::DoFindFriendlyCC(float range)
{
std::list<Creature*> list;
Trinity::FriendlyCCedInRange u_check(me, range);
Trinity::CreatureListSearcher<Trinity::FriendlyCCedInRange> searcher(me, list, u_check);
me->VisitNearbyObject(range, searcher);
return list;
}
std::list<Creature*> ScriptedAI::DoFindFriendlyMissingBuff(float range, uint32 uiSpellid)
{
std::list<Creature*> list;
Trinity::FriendlyMissingBuffInRange u_check(me, range, uiSpellid);
Trinity::CreatureListSearcher<Trinity::FriendlyMissingBuffInRange> searcher(me, list, u_check);
me->VisitNearbyObject(range, searcher);
return list;
}
Player* ScriptedAI::GetPlayerAtMinimumRange(float minimumRange)
{
Player* player = NULL;
CellCoord pair(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
Cell cell(pair);
cell.SetNoCreate();
Trinity::PlayerAtMinimumRangeAway check(me, minimumRange);
Trinity::PlayerSearcher<Trinity::PlayerAtMinimumRangeAway> searcher(me, player, check);
TypeContainerVisitor<Trinity::PlayerSearcher<Trinity::PlayerAtMinimumRangeAway>, GridTypeMapContainer> visitor(searcher);
cell.Visit(pair, visitor, *me->GetMap(), *me, minimumRange);
return player;
}
void ScriptedAI::SetEquipmentSlots(bool loadDefault, int32 mainHand /*= EQUIP_NO_CHANGE*/, int32 offHand /*= EQUIP_NO_CHANGE*/, int32 ranged /*= EQUIP_NO_CHANGE*/)
{
if (loadDefault)
{
me->LoadEquipment(me->GetOriginalEquipmentId(), true);
return;
}
if (mainHand >= 0)
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(mainHand));
if (offHand >= 0)
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(offHand));
if (ranged >= 0)
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, uint32(ranged));
}
void ScriptedAI::SetCombatMovement(bool allowMovement)
{
_isCombatMovementAllowed = allowMovement;
}
enum eNPCs
{
NPC_BROODLORD = 12017,
NPC_JAN_ALAI = 23578,
NPC_SARTHARION = 28860,
NPC_FREYA = 32906,
};
bool ScriptedAI::EnterEvadeIfOutOfCombatArea()
{
if (me->IsInEvadeMode() || !me->IsInCombat())
return false;
if (_evadeCheckCooldown == time(NULL))
return false;
_evadeCheckCooldown = time(NULL);
if (!CheckEvadeIfOutOfCombatArea())
return false;
EnterEvadeMode();
return true;
}
Player* ScriptedAI::SelectTargetFromPlayerList(float maxdist, uint32 excludeAura, bool mustBeInLOS) const
{
Map::PlayerList const& pList = me->GetMap()->GetPlayers();
std::vector<Player*> tList;
for(Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
{
if (me->GetDistance(itr->GetSource()) > maxdist || !itr->GetSource()->IsAlive() || itr->GetSource()->IsGameMaster())
continue;
if (excludeAura && itr->GetSource()->HasAura(excludeAura))
continue;
if (mustBeInLOS && !me->IsWithinLOSInMap(itr->GetSource()))
continue;
tList.push_back(itr->GetSource());
}
if (!tList.empty())
return tList[urand(0,tList.size()-1)];
else
return NULL;
}
// BossAI - for instanced bosses
BossAI::BossAI(Creature* creature, uint32 bossId) : ScriptedAI(creature),
instance(creature->GetInstanceScript()),
summons(creature),
_boundary(instance ? instance->GetBossBoundary(bossId) : NULL),
_bossId(bossId)
{
}
void BossAI::_Reset()
{
if (!me->IsAlive())
return;
me->ResetLootMode();
events.Reset();
summons.DespawnAll();
if (instance)
instance->SetBossState(_bossId, NOT_STARTED);
}
void BossAI::_JustDied()
{
events.Reset();
summons.DespawnAll();
if (instance)
{
instance->SetBossState(_bossId, DONE);
instance->SaveToDB();
}
}
void BossAI::_EnterCombat()
{
me->setActive(true);
DoZoneInCombat();
if (instance)
{
// bosses do not respawn, check only on enter combat
if (!instance->CheckRequiredBosses(_bossId))
{
EnterEvadeMode();
return;
}
instance->SetBossState(_bossId, IN_PROGRESS);
}
}
void BossAI::TeleportCheaters()
{
float x, y, z;
me->GetPosition(x, y, z);
ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList();
for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
if (Unit* target = (*itr)->getTarget())
if (target->GetTypeId() == TYPEID_PLAYER && !CheckBoundary(target))
target->NearTeleportTo(x, y, z, 0);
}
bool BossAI::CheckBoundary(Unit* who)
{
if (!GetBoundary() || !who)
return true;
for (BossBoundaryMap::const_iterator itr = GetBoundary()->begin(); itr != GetBoundary()->end(); ++itr)
{
switch (itr->first)
{
case BOUNDARY_N:
if (who->GetPositionX() > itr->second)
return false;
break;
case BOUNDARY_S:
if (who->GetPositionX() < itr->second)
return false;
break;
case BOUNDARY_E:
if (who->GetPositionY() < itr->second)
return false;
break;
case BOUNDARY_W:
if (who->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_NW:
if (who->GetPositionX() + who->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_SE:
if (who->GetPositionX() + who->GetPositionY() < itr->second)
return false;
break;
case BOUNDARY_NE:
if (who->GetPositionX() - who->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_SW:
if (who->GetPositionX() - who->GetPositionY() < itr->second)
return false;
break;
default:
break;
}
}
return true;
}
void BossAI::JustSummoned(Creature* summon)
{
summons.Summon(summon);
if (me->IsInCombat())
DoZoneInCombat(summon);
}
void BossAI::SummonedCreatureDespawn(Creature* summon)
{
summons.Despawn(summon);
}
void BossAI::UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
ExecuteEvent(eventId);
DoMeleeAttackIfReady();
}
// WorldBossAI - for non-instanced bosses
WorldBossAI::WorldBossAI(Creature* creature) :
ScriptedAI(creature),
summons(creature)
{
}
void WorldBossAI::_Reset()
{
if (!me->IsAlive())
return;
events.Reset();
summons.DespawnAll();
}
void WorldBossAI::_JustDied()
{
events.Reset();
summons.DespawnAll();
}
void WorldBossAI::_EnterCombat()
{
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true);
if (target)
AttackStart(target);
}
void WorldBossAI::JustSummoned(Creature* summon)
{
summons.Summon(summon);
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true);
if (target)
summon->AI()->AttackStart(target);
}
void WorldBossAI::SummonedCreatureDespawn(Creature* summon)
{
summons.Despawn(summon);
}
void WorldBossAI::UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
ExecuteEvent(eventId);
DoMeleeAttackIfReady();
}
// SD2 grid searchers.
Creature* GetClosestCreatureWithEntry(WorldObject* source, uint32 entry, float maxSearchRange, bool alive /*= true*/)
{
return source->FindNearestCreature(entry, maxSearchRange, alive);
}
GameObject* GetClosestGameObjectWithEntry(WorldObject* source, uint32 entry, float maxSearchRange)
{
return source->FindNearestGameObject(entry, maxSearchRange);
}
void GetCreatureListWithEntryInGrid(std::list<Creature*>& list, WorldObject* source, uint32 entry, float maxSearchRange)
{
source->GetCreatureListWithEntryInGrid(list, entry, maxSearchRange);
}
void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject* source, uint32 entry, float maxSearchRange)
{
source->GetGameObjectListWithEntryInGrid(list, entry, maxSearchRange);
}

View File

@@ -1,457 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SCRIPTEDCREATURE_H_
#define SCRIPTEDCREATURE_H_
#include "Creature.h"
#include "CreatureAI.h"
#include "CreatureAIImpl.h"
#include "InstanceScript.h"
#define CAST_AI(a, b) (dynamic_cast<a*>(b))
class InstanceScript;
class SummonList
{
public:
typedef std::list<uint64> StorageType;
typedef StorageType::iterator iterator;
typedef StorageType::const_iterator const_iterator;
typedef StorageType::size_type size_type;
typedef StorageType::value_type value_type;
explicit SummonList(Creature* creature)
: me(creature)
{ }
// And here we see a problem of original inheritance approach. People started
// to exploit presence of std::list members, so I have to provide wrappers
iterator begin()
{
return storage_.begin();
}
const_iterator begin() const
{
return storage_.begin();
}
iterator end()
{
return storage_.end();
}
const_iterator end() const
{
return storage_.end();
}
iterator erase(iterator i)
{
return storage_.erase(i);
}
bool empty() const
{
return storage_.empty();
}
size_type size() const
{
return storage_.size();
}
void clear()
{
storage_.clear();
}
void Summon(Creature const* summon) { storage_.push_back(summon->GetGUID()); }
void Despawn(Creature const* summon) { storage_.remove(summon->GetGUID()); }
void DespawnEntry(uint32 entry);
void DespawnAll();
template <typename T>
void DespawnIf(T const &predicate)
{
storage_.remove_if(predicate);
}
void DoAction(int32 info, uint16 max = 0)
{
if (max)
RemoveNotExisting(); // pussywizard: when max is set, non existing can be chosen and nothing will happen
StorageType listCopy = storage_;
for (StorageType::const_iterator i = listCopy.begin(); i != listCopy.end(); ++i)
{
if (Creature* summon = ObjectAccessor::GetCreature(*me, *i))
if (summon->IsAIEnabled)
summon->AI()->DoAction(info);
}
}
template <class Predicate>
void DoAction(int32 info, Predicate& predicate, uint16 max = 0)
{
if (max)
RemoveNotExisting(); // pussywizard: when max is set, non existing can be chosen and nothing will happen
// We need to use a copy of SummonList here, otherwise original SummonList would be modified
StorageType listCopy = storage_;
Trinity::Containers::RandomResizeList<uint64, Predicate>(listCopy, predicate, max);
for (StorageType::iterator i = listCopy.begin(); i != listCopy.end(); ++i)
{
Creature* summon = ObjectAccessor::GetCreature(*me, *i);
if (summon)
{
if (summon->IsAIEnabled)
summon->AI()->DoAction(info);
}
else
storage_.remove(*i);
}
}
void DoZoneInCombat(uint32 entry = 0);
void RemoveNotExisting();
bool HasEntry(uint32 entry) const;
uint32 GetEntryCount(uint32 entry) const;
void Respawn();
Creature* GetCreatureWithEntry(uint32 entry) const;
private:
Creature* me;
StorageType storage_;
};
class EntryCheckPredicate
{
public:
EntryCheckPredicate(uint32 entry) : _entry(entry) {}
bool operator()(uint64 guid) { return GUID_ENPART(guid) == _entry; }
private:
uint32 _entry;
};
class PlayerOrPetCheck
{
public:
bool operator() (WorldObject* unit) const
{
if (unit->GetTypeId() != TYPEID_PLAYER)
if (!IS_PLAYER_GUID(unit->ToUnit()->GetOwnerGUID()))
return true;
return false;
}
};
struct ScriptedAI : public CreatureAI
{
explicit ScriptedAI(Creature* creature);
virtual ~ScriptedAI() {}
// *************
//CreatureAI Functions
// *************
void AttackStartNoMove(Unit* target);
// Called at any Damage from any attacker (before damage apply)
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) {}
//Called at World update tick
virtual void UpdateAI(uint32 diff);
//Called at creature death
void JustDied(Unit* /*killer*/) {}
//Called at creature killing another unit
void KilledUnit(Unit* /*victim*/) {}
// Called when the creature summon successfully other creature
void JustSummoned(Creature* /*summon*/) {}
// Called when a summoned creature is despawned
void SummonedCreatureDespawn(Creature* /*summon*/) {}
// Called when hit by a spell
void SpellHit(Unit* /*caster*/, SpellInfo const* /*spell*/) {}
// Called when spell hits a target
void SpellHitTarget(Unit* /*target*/, SpellInfo const* /*spell*/) {}
//Called at waypoint reached or PointMovement end
void MovementInform(uint32 /*type*/, uint32 /*id*/) {}
// Called when AI is temporarily replaced or put back when possess is applied or removed
void OnPossess(bool /*apply*/) {}
// *************
// Variables
// *************
//Pointer to creature we are manipulating
Creature* me;
//For fleeing
bool IsFleeing;
// *************
//Pure virtual functions
// *************
//Called at creature reset either by death or evade
void Reset() {}
//Called at creature aggro either by MoveInLOS or Attack Start
void EnterCombat(Unit* /*victim*/) {}
// Called before EnterCombat even before the creature is in combat.
void AttackStart(Unit* /*target*/);
// *************
//AI Helper Functions
// *************
//Start movement toward victim
void DoStartMovement(Unit* target, float distance = 0.0f, float angle = 0.0f);
//Start no movement on victim
void DoStartNoMovement(Unit* target);
//Stop attack of current victim
void DoStopAttack();
//Cast spell by spell info
void DoCastSpell(Unit* target, SpellInfo const* spellInfo, bool triggered = false);
//Plays a sound to all nearby players
void DoPlaySoundToSet(WorldObject* source, uint32 soundId);
//Drops all threat to 0%. Does not remove players from the threat list
void DoResetThreat();
float DoGetThreat(Unit* unit);
void DoModifyThreatPercent(Unit* unit, int32 pct);
//Teleports a player without dropping threat (only teleports to same map)
void DoTeleportPlayer(Unit* unit, float x, float y, float z, float o);
void DoTeleportAll(float x, float y, float z, float o);
//Returns friendly unit with the most amount of hp missing from max hp
Unit* DoSelectLowestHpFriendly(float range, uint32 minHPDiff = 1);
//Returns a list of friendly CC'd units within range
std::list<Creature*> DoFindFriendlyCC(float range);
//Returns a list of all friendly units missing a specific buff within range
std::list<Creature*> DoFindFriendlyMissingBuff(float range, uint32 spellId);
//Return a player with at least minimumRange from me
Player* GetPlayerAtMinimumRange(float minRange);
//Spawns a creature relative to me
Creature* DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, uint32 type, uint32 despawntime);
bool HealthBelowPct(uint32 pct) const { return me->HealthBelowPct(pct); }
bool HealthAbovePct(uint32 pct) const { return me->HealthAbovePct(pct); }
//Returns spells that meet the specified criteria from the creatures spell list
SpellInfo const* SelectSpell(Unit* target, uint32 school, uint32 mechanic, SelectTargetType targets, uint32 powerCostMin, uint32 powerCostMax, float rangeMin, float rangeMax, SelectEffect effect);
void SetEquipmentSlots(bool loadDefault, int32 mainHand = EQUIP_NO_CHANGE, int32 offHand = EQUIP_NO_CHANGE, int32 ranged = EQUIP_NO_CHANGE);
// Used to control if MoveChase() is to be used or not in AttackStart(). Some creatures does not chase victims
// NOTE: If you use SetCombatMovement while the creature is in combat, it will do NOTHING - This only affects AttackStart
// You should make the necessary to make it happen so.
// Remember that if you modified _isCombatMovementAllowed (e.g: using SetCombatMovement) it will not be reset at Reset().
// It will keep the last value you set.
void SetCombatMovement(bool allowMovement);
bool IsCombatMovementAllowed() const { return _isCombatMovementAllowed; }
bool EnterEvadeIfOutOfCombatArea();
virtual bool CheckEvadeIfOutOfCombatArea() const { return false; }
// return true for heroic mode. i.e.
// - for dungeon in mode 10-heroic,
// - for raid in mode 10-Heroic
// - for raid in mode 25-heroic
// DO NOT USE to check raid in mode 25-normal.
bool IsHeroic() const { return _isHeroic; }
// return the dungeon or raid difficulty
Difficulty GetDifficulty() const { return _difficulty; }
// return true for 25 man or 25 man heroic mode
bool Is25ManRaid() const { return _difficulty & RAID_DIFFICULTY_MASK_25MAN; }
template<class T> inline
const T& DUNGEON_MODE(const T& normal5, const T& heroic10) const
{
switch (_difficulty)
{
case DUNGEON_DIFFICULTY_NORMAL:
return normal5;
case DUNGEON_DIFFICULTY_HEROIC:
return heroic10;
default:
break;
}
return heroic10;
}
template<class T> inline
const T& RAID_MODE(const T& normal10, const T& normal25) const
{
switch (_difficulty)
{
case RAID_DIFFICULTY_10MAN_NORMAL:
return normal10;
case RAID_DIFFICULTY_25MAN_NORMAL:
return normal25;
default:
break;
}
return normal25;
}
template<class T> inline
const T& RAID_MODE(const T& normal10, const T& normal25, const T& heroic10, const T& heroic25) const
{
switch (_difficulty)
{
case RAID_DIFFICULTY_10MAN_NORMAL:
return normal10;
case RAID_DIFFICULTY_25MAN_NORMAL:
return normal25;
case RAID_DIFFICULTY_10MAN_HEROIC:
return heroic10;
case RAID_DIFFICULTY_25MAN_HEROIC:
return heroic25;
default:
break;
}
return heroic25;
}
Player* SelectTargetFromPlayerList(float maxdist, uint32 excludeAura = 0, bool mustBeInLOS = false) const;
private:
Difficulty _difficulty;
uint32 _evadeCheckCooldown;
bool _isCombatMovementAllowed;
bool _isHeroic;
};
class BossAI : public ScriptedAI
{
public:
BossAI(Creature* creature, uint32 bossId);
virtual ~BossAI() {}
InstanceScript* const instance;
BossBoundaryMap const* GetBoundary() const { return _boundary; }
void JustSummoned(Creature* summon);
void SummonedCreatureDespawn(Creature* summon);
virtual void UpdateAI(uint32 diff);
// Hook used to execute events scheduled into EventMap without the need
// to override UpdateAI
// note: You must re-schedule the event within this method if the event
// is supposed to run more than once
virtual void ExecuteEvent(uint32 /*eventId*/) { }
void Reset() { _Reset(); }
void EnterCombat(Unit* /*who*/) { _EnterCombat(); }
void JustDied(Unit* /*killer*/) { _JustDied(); }
void JustReachedHome() { _JustReachedHome(); }
protected:
void _Reset();
void _EnterCombat();
void _JustDied();
void _JustReachedHome() { me->setActive(false); }
bool CheckInRoom()
{
if (CheckBoundary(me))
return true;
EnterEvadeMode();
return false;
}
bool CheckBoundary(Unit* who);
void TeleportCheaters();
EventMap events;
SummonList summons;
private:
BossBoundaryMap const* const _boundary;
uint32 const _bossId;
};
class WorldBossAI : public ScriptedAI
{
public:
WorldBossAI(Creature* creature);
virtual ~WorldBossAI() {}
void JustSummoned(Creature* summon);
void SummonedCreatureDespawn(Creature* summon);
virtual void UpdateAI(uint32 diff);
// Hook used to execute events scheduled into EventMap without the need
// to override UpdateAI
// note: You must re-schedule the event within this method if the event
// is supposed to run more than once
virtual void ExecuteEvent(uint32 /*eventId*/) { }
void Reset() { _Reset(); }
void EnterCombat(Unit* /*who*/) { _EnterCombat(); }
void JustDied(Unit* /*killer*/) { _JustDied(); }
protected:
void _Reset();
void _EnterCombat();
void _JustDied();
EventMap events;
SummonList summons;
};
// SD2 grid searchers.
Creature* GetClosestCreatureWithEntry(WorldObject* source, uint32 entry, float maxSearchRange, bool alive = true);
GameObject* GetClosestGameObjectWithEntry(WorldObject* source, uint32 entry, float maxSearchRange);
void GetCreatureListWithEntryInGrid(std::list<Creature*>& list, WorldObject* source, uint32 entry, float maxSearchRange);
void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject* source, uint32 entry, float maxSearchRange);
#endif // SCRIPTEDCREATURE_H_

View File

@@ -1,584 +0,0 @@
/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* This program is free software licensed under GPL version 2
* Please see the included DOCS/LICENSE.TXT for more information */
/* ScriptData
SDName: Npc_EscortAI
SD%Complete: 100
SDComment:
SDCategory: Npc
EndScriptData */
#include "ScriptedCreature.h"
#include "ScriptedEscortAI.h"
#include "Group.h"
#include "Player.h"
enum ePoints
{
POINT_LAST_POINT = 0xFFFFFF,
POINT_HOME = 0xFFFFFE
};
npc_escortAI::npc_escortAI(Creature* creature) : ScriptedAI(creature),
m_uiPlayerGUID(0),
m_uiWPWaitTimer(1000),
m_uiPlayerCheckTimer(0),
m_uiEscortState(STATE_ESCORT_NONE),
MaxPlayerDistance(DEFAULT_MAX_PLAYER_DISTANCE),
m_pQuestForEscort(NULL),
m_bIsActiveAttacker(true),
m_bIsRunning(false),
m_bCanInstantRespawn(false),
m_bCanReturnToStart(false),
DespawnAtEnd(true),
DespawnAtFar(true),
ScriptWP(false),
HasImmuneToNPCFlags(false)
{}
void npc_escortAI::AttackStart(Unit* who)
{
if (!who)
return;
if (me->Attack(who, true))
{
MovementGeneratorType type = me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE);
if (type == ESCORT_MOTION_TYPE || type == POINT_MOTION_TYPE)
{
me->GetMotionMaster()->MovementExpired();
//me->DisableSpline();
me->StopMoving();
}
if (IsCombatMovementAllowed())
me->GetMotionMaster()->MoveChase(who);
}
}
//see followerAI
bool npc_escortAI::AssistPlayerInCombat(Unit* who)
{
if (!who || !who->GetVictim())
return false;
//experimental (unknown) flag not present
if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_AID_PLAYERS))
return false;
//not a player
if (!who->GetVictim()->GetCharmerOrOwnerPlayerOrPlayerItself())
return false;
//never attack friendly
if (!me->IsValidAttackTarget(who))
return false;
//too far away and no free sight?
if (me->IsWithinDistInMap(who, GetMaxPlayerDistance()) && me->IsWithinLOSInMap(who))
{
AttackStart(who);
return true;
}
return false;
}
void npc_escortAI::MoveInLineOfSight(Unit* who)
{
if (me->GetVictim())
return;
if (!me->HasUnitState(UNIT_STATE_STUNNED) && who->isTargetableForAttack(true, me) && who->isInAccessiblePlaceFor(me))
if (HasEscortState(STATE_ESCORT_ESCORTING) && AssistPlayerInCombat(who))
return;
if (me->CanStartAttack(who))
AttackStart(who);
}
void npc_escortAI::JustDied(Unit* /*killer*/)
{
if (!HasEscortState(STATE_ESCORT_ESCORTING) || !m_uiPlayerGUID || !m_pQuestForEscort)
return;
if (Player* player = GetPlayerForEscort())
{
if (Group* group = player->GetGroup())
{
for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next())
if (Player* member = groupRef->GetSource())
if (member->IsInMap(player) && member->GetQuestStatus(m_pQuestForEscort->GetQuestId()) == QUEST_STATUS_INCOMPLETE)
member->FailQuest(m_pQuestForEscort->GetQuestId());
}
else
{
if (player->GetQuestStatus(m_pQuestForEscort->GetQuestId()) == QUEST_STATUS_INCOMPLETE)
player->FailQuest(m_pQuestForEscort->GetQuestId());
}
}
}
void npc_escortAI::JustRespawned()
{
RemoveEscortState(STATE_ESCORT_ESCORTING|STATE_ESCORT_RETURNING|STATE_ESCORT_PAUSED);
if (!IsCombatMovementAllowed())
SetCombatMovement(true);
//add a small delay before going to first waypoint, normal in near all cases
m_uiWPWaitTimer = 1000;
if (me->getFaction() != me->GetCreatureTemplate()->faction)
me->RestoreFaction();
Reset();
}
void npc_escortAI::ReturnToLastPoint()
{
float x, y, z, o;
me->SetWalk(false);
me->GetHomePosition(x, y, z, o);
me->GetMotionMaster()->MovePoint(POINT_LAST_POINT, x, y, z);
}
void npc_escortAI::EnterEvadeMode()
{
me->RemoveAllAuras();
me->DeleteThreatList();
me->CombatStop(true);
me->SetLootRecipient(NULL);
if (HasEscortState(STATE_ESCORT_ESCORTING))
{
AddEscortState(STATE_ESCORT_RETURNING);
ReturnToLastPoint();
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: EscortAI has left combat and is now returning to last point");
}
else
{
me->GetMotionMaster()->MoveTargetedHome();
if (HasImmuneToNPCFlags)
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
Reset();
}
}
bool npc_escortAI::IsPlayerOrGroupInRange()
{
if (Player* player = GetPlayerForEscort())
{
if (Group* group = player->GetGroup())
{
for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next())
if (Player* member = groupRef->GetSource())
if (me->IsWithinDistInMap(member, GetMaxPlayerDistance()))
return true;
}
else if (me->IsWithinDistInMap(player, GetMaxPlayerDistance()))
return true;
}
return false;
}
void npc_escortAI::UpdateAI(uint32 diff)
{
if (HasEscortState(STATE_ESCORT_ESCORTING) && !me->GetVictim() && m_uiWPWaitTimer && !HasEscortState(STATE_ESCORT_RETURNING))
{
if (m_uiWPWaitTimer <= diff)
{
if (CurrentWP == WaypointList.end())
{
if (DespawnAtEnd)
{
if (m_bCanReturnToStart)
{
float fRetX, fRetY, fRetZ;
me->GetRespawnPosition(fRetX, fRetY, fRetZ);
me->GetMotionMaster()->MovePoint(POINT_HOME, fRetX, fRetY, fRetZ);
m_uiWPWaitTimer = 0;
return;
}
if (m_bCanInstantRespawn)
{
me->setDeathState(JUST_DIED);
me->Respawn();
}
else
me->DespawnOrUnsummon();
}
// xinef: remove escort state, escort was finished (lack of this line resulted in skipping UpdateEscortAI calls after finished escort)
RemoveEscortState(STATE_ESCORT_ESCORTING);
return;
}
if (!HasEscortState(STATE_ESCORT_PAUSED))
{
// xinef, start escort if there is no spline active
if (me->movespline->Finalized())
{
Movement::PointsArray pathPoints;
GenerateWaypointArray(&pathPoints);
me->GetMotionMaster()->MoveSplinePath(&pathPoints);
}
WaypointStart(CurrentWP->id);
m_uiWPWaitTimer = 0;
}
}
else
m_uiWPWaitTimer -= diff;
}
//Check if player or any member of his group is within range
if (HasEscortState(STATE_ESCORT_ESCORTING) && m_uiPlayerGUID && !me->GetVictim() && !HasEscortState(STATE_ESCORT_RETURNING))
{
m_uiPlayerCheckTimer += diff;
if (m_uiPlayerCheckTimer > 1000)
{
if (DespawnAtFar && !IsPlayerOrGroupInRange())
{
if (m_bCanInstantRespawn)
{
me->setDeathState(JUST_DIED);
me->Respawn();
}
else
me->DespawnOrUnsummon();
return;
}
m_uiPlayerCheckTimer = 0;
}
}
UpdateEscortAI(diff);
}
void npc_escortAI::UpdateEscortAI(uint32 /*diff*/)
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
void npc_escortAI::MovementInform(uint32 moveType, uint32 pointId)
{
// xinef: no action allowed if there is no escort
if (!HasEscortState(STATE_ESCORT_ESCORTING))
return;
if (moveType == POINT_MOTION_TYPE)
{
//Combat start position reached, continue waypoint movement
if (pointId == POINT_LAST_POINT)
{
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: EscortAI has returned to original position before combat");
me->SetWalk(!m_bIsRunning);
RemoveEscortState(STATE_ESCORT_RETURNING);
if (!m_uiWPWaitTimer)
m_uiWPWaitTimer = 1;
}
else if (pointId == POINT_HOME)
{
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: EscortAI has returned to original home location and will continue from beginning of waypoint list.");
CurrentWP = WaypointList.begin();
m_uiWPWaitTimer = 1;
}
}
else if (moveType == ESCORT_MOTION_TYPE)
{
if (m_uiWPWaitTimer <= 1 && !HasEscortState(STATE_ESCORT_PAUSED) && CurrentWP != WaypointList.end())
{
//Call WP function
me->SetPosition(CurrentWP->x, CurrentWP->y, CurrentWP->z, me->GetOrientation());
me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
WaypointReached(CurrentWP->id);
m_uiWPWaitTimer = CurrentWP->WaitTimeMs + 1;
++CurrentWP;
if (m_uiWPWaitTimer > 1 || HasEscortState(STATE_ESCORT_PAUSED))
{
if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == ESCORT_MOTION_TYPE)
me->GetMotionMaster()->MovementExpired();
me->StopMovingOnCurrentPos();
me->GetMotionMaster()->MoveIdle();
}
}
}
}
/*
void npc_escortAI::OnPossess(bool apply)
{
// We got possessed in the middle of being escorted, store the point
// where we left off to come back to when possess is removed
if (HasEscortState(STATE_ESCORT_ESCORTING))
{
if (apply)
me->GetPosition(LastPos.x, LastPos.y, LastPos.z);
else
{
Returning = true;
me->GetMotionMaster()->MovementExpired();
me->GetMotionMaster()->MovePoint(WP_LAST_POINT, LastPos.x, LastPos.y, LastPos.z);
}
}
}
*/
void npc_escortAI::AddWaypoint(uint32 id, float x, float y, float z, uint32 waitTime)
{
Escort_Waypoint t(id, x, y, z, waitTime);
WaypointList.push_back(t);
// i think SD2 no longer uses this function
ScriptWP = true;
/*PointMovement wp;
wp.m_uiCreatureEntry = me->GetEntry();
wp.m_uiPointId = id;
wp.m_fX = x;
wp.m_fY = y;
wp.m_fZ = z;
wp.m_uiWaitTime = WaitTimeMs;
PointMovementMap[wp.m_uiCreatureEntry].push_back(wp);*/
}
void npc_escortAI::FillPointMovementListForCreature()
{
ScriptPointVector const& movePoints = sScriptSystemMgr->GetPointMoveList(me->GetEntry());
if (movePoints.empty())
return;
ScriptPointVector::const_iterator itrEnd = movePoints.end();
for (ScriptPointVector::const_iterator itr = movePoints.begin(); itr != itrEnd; ++itr)
{
Escort_Waypoint point(itr->uiPointId, itr->fX, itr->fY, itr->fZ, itr->uiWaitTime);
WaypointList.push_back(point);
}
}
void npc_escortAI::SetRun(bool on)
{
if (on)
{
if (!m_bIsRunning)
me->SetWalk(false);
else
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: EscortAI attempt to set run mode, but is already running.");
}
else
{
if (m_bIsRunning)
me->SetWalk(true);
else
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: EscortAI attempt to set walk mode, but is already walking.");
}
m_bIsRunning = on;
}
//TODO: get rid of this many variables passed in function.
void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false */, uint64 playerGUID /* = 0 */, Quest const* quest /* = NULL */, bool instantRespawn /* = false */, bool canLoopPath /* = false */, bool resetWaypoints /* = true */)
{
if (me->GetVictim())
{
sLog->outError("TSCR ERROR: EscortAI (script: %s, creature entry: %u) attempts to Start while in combat", me->GetScriptName().c_str(), me->GetEntry());
return;
}
if (HasEscortState(STATE_ESCORT_ESCORTING))
{
sLog->outError("TSCR: EscortAI (script: %s, creature entry: %u) attempts to Start while already escorting", me->GetScriptName().c_str(), me->GetEntry());
return;
}
if (!ScriptWP && resetWaypoints) // sd2 never adds wp in script, but tc does
{
if (!WaypointList.empty())
WaypointList.clear();
FillPointMovementListForCreature();
}
if (WaypointList.empty())
{
sLog->outErrorDb("TSCR: EscortAI (script: %s, creature entry: %u) starts with 0 waypoints (possible missing entry in script_waypoint. Quest: %u).",
me->GetScriptName().c_str(), me->GetEntry(), quest ? quest->GetQuestId() : 0);
return;
}
//set variables
m_bIsActiveAttacker = isActiveAttacker;
m_bIsRunning = run;
m_uiPlayerGUID = playerGUID;
m_pQuestForEscort = quest;
m_bCanInstantRespawn = instantRespawn;
m_bCanReturnToStart = canLoopPath;
//if (m_bCanReturnToStart && m_bCanInstantRespawn)
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: EscortAI is set to return home after waypoint end and instant respawn at waypoint end. Creature will never despawn.");
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
{
me->GetMotionMaster()->MovementExpired();
me->GetMotionMaster()->MoveIdle();
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: EscortAI start with WAYPOINT_MOTION_TYPE, changed to MoveIdle.");
}
//disable npcflags
me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC))
{
HasImmuneToNPCFlags = true;
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
}
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: EscortAI started with " UI64FMTD " waypoints. ActiveAttacker = %d, Run = %d, PlayerGUID = " UI64FMTD "", uint64(WaypointList.size()), m_bIsActiveAttacker, m_bIsRunning, m_uiPlayerGUID);
CurrentWP = WaypointList.begin();
//Set initial speed
if (m_bIsRunning)
me->SetWalk(false);
else
me->SetWalk(true);
AddEscortState(STATE_ESCORT_ESCORTING);
if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == ESCORT_MOTION_TYPE)
me->GetMotionMaster()->MovementExpired();
me->DisableSpline();
me->GetMotionMaster()->MoveIdle();
}
void npc_escortAI::SetEscortPaused(bool on)
{
if (!HasEscortState(STATE_ESCORT_ESCORTING))
return;
if (on)
AddEscortState(STATE_ESCORT_PAUSED);
else
RemoveEscortState(STATE_ESCORT_PAUSED);
}
bool npc_escortAI::SetNextWaypoint(uint32 pointId, float x, float y, float z, float orientation)
{
me->UpdatePosition(x, y, z, orientation);
return SetNextWaypoint(pointId, false);
}
bool npc_escortAI::SetNextWaypoint(uint32 pointId, bool setPosition)
{
if (!WaypointList.empty())
WaypointList.clear();
FillPointMovementListForCreature();
if (WaypointList.empty())
return false;
size_t const size = WaypointList.size();
Escort_Waypoint waypoint(0, 0, 0, 0, 0);
for (CurrentWP = WaypointList.begin(); CurrentWP != WaypointList.end(); ++CurrentWP)
{
if (CurrentWP->id == pointId)
{
if (setPosition)
me->UpdatePosition(CurrentWP->x, CurrentWP->y, CurrentWP->z, me->GetOrientation());
return true;
}
}
return false;
}
bool npc_escortAI::GetWaypointPosition(uint32 pointId, float& x, float& y, float& z)
{
ScriptPointVector const& waypoints = sScriptSystemMgr->GetPointMoveList(me->GetEntry());
if (waypoints.empty())
return false;
for (ScriptPointVector::const_iterator itr = waypoints.begin(); itr != waypoints.end(); ++itr)
{
if (itr->uiPointId == pointId)
{
x = itr->fX;
y = itr->fY;
z = itr->fZ;
return true;
}
}
return false;
}
void npc_escortAI::GenerateWaypointArray(Movement::PointsArray* points)
{
if (WaypointList.empty())
return;
uint32 startingWaypointId = CurrentWP->id;
// Flying unit, just fill array
if (me->m_movementInfo.HasMovementFlag((MovementFlags)(MOVEMENTFLAG_CAN_FLY|MOVEMENTFLAG_DISABLE_GRAVITY)))
{
// xinef: first point in vector is unit real position
points->clear();
points->push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
for (std::list<Escort_Waypoint>::const_iterator itr = CurrentWP; itr != WaypointList.end(); ++itr)
points->push_back(G3D::Vector3(itr->x, itr->y, itr->z));
}
else
{
for (float size = 1.0f; size; size *= 0.5f)
{
std::vector<G3D::Vector3> pVector;
// xinef: first point in vector is unit real position
pVector.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
uint32 length = (WaypointList.size() - startingWaypointId)*size;
uint32 cnt = 0;
for (std::list<Escort_Waypoint>::const_iterator itr = CurrentWP; itr != WaypointList.end() && cnt <= length; ++itr, ++cnt)
pVector.push_back(G3D::Vector3(itr->x, itr->y, itr->z));
if (pVector.size() > 2) // more than source + dest
{
G3D::Vector3 middle = (pVector[0] + pVector[pVector.size()-1]) / 2.f;
G3D::Vector3 offset;
bool continueLoop = false;
for (uint32 i = 1; i < pVector.size()-1; ++i)
{
offset = middle - pVector[i];
if (fabs(offset.x) >= 0xFF || fabs(offset.y) >= 0xFF || fabs(offset.z) >= 0x7F)
{
// offset is too big, split points
continueLoop = true;
break;
}
}
if (continueLoop)
continue;
}
// everything ok
*points = pVector;
break;
}
}
}

View File

@@ -1,128 +0,0 @@
/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* This program is free software licensed under GPL version 2
* Please see the included DOCS/LICENSE.TXT for more information */
#ifndef SC_ESCORTAI_H
#define SC_ESCORTAI_H
#include "ScriptSystem.h"
#define DEFAULT_MAX_PLAYER_DISTANCE 50
struct Escort_Waypoint
{
Escort_Waypoint(uint32 _id, float _x, float _y, float _z, uint32 _w)
{
id = _id;
x = _x;
y = _y;
z = _z;
WaitTimeMs = _w;
}
uint32 id;
float x;
float y;
float z;
uint32 WaitTimeMs;
};
enum eEscortState
{
STATE_ESCORT_NONE = 0x000, //nothing in progress
STATE_ESCORT_ESCORTING = 0x001, //escort are in progress
STATE_ESCORT_RETURNING = 0x002, //escort is returning after being in combat
STATE_ESCORT_PAUSED = 0x004 //will not proceed with waypoints before state is removed
};
struct npc_escortAI : public ScriptedAI
{
public:
explicit npc_escortAI(Creature* creature);
~npc_escortAI() {}
// CreatureAI functions
void AttackStart(Unit* who);
void MoveInLineOfSight(Unit* who);
void JustDied(Unit*);
void JustRespawned();
void ReturnToLastPoint();
void EnterEvadeMode();
void UpdateAI(uint32 diff); //the "internal" update, calls UpdateEscortAI()
virtual void UpdateEscortAI(uint32 diff); //used when it's needed to add code in update (abilities, scripted events, etc)
void MovementInform(uint32, uint32);
// EscortAI functions
void AddWaypoint(uint32 id, float x, float y, float z, uint32 waitTime = 0); // waitTime is in ms
//this will set the current position to x/y/z/o, and the current WP to pointId.
bool SetNextWaypoint(uint32 pointId, float x, float y, float z, float orientation);
//this will set the current position to WP start position (if setPosition == true),
//and the current WP to pointId
bool SetNextWaypoint(uint32 pointId, bool setPosition = true);
bool GetWaypointPosition(uint32 pointId, float& x, float& y, float& z);
void GenerateWaypointArray(Movement::PointsArray* points);
virtual void WaypointReached(uint32 pointId) = 0;
virtual void WaypointStart(uint32 /*pointId*/) {}
void Start(bool isActiveAttacker = true, bool run = false, uint64 playerGUID = 0, Quest const* quest = NULL, bool instantRespawn = false, bool canLoopPath = false, bool resetWaypoints = true);
void SetRun(bool on = true);
void SetEscortPaused(bool on);
bool HasEscortState(uint32 escortState) { return (m_uiEscortState & escortState); }
virtual bool IsEscorted() { return (m_uiEscortState & STATE_ESCORT_ESCORTING); }
void SetMaxPlayerDistance(float newMax) { MaxPlayerDistance = newMax; }
float GetMaxPlayerDistance() { return MaxPlayerDistance; }
void SetDespawnAtEnd(bool despawn) { DespawnAtEnd = despawn; }
void SetDespawnAtFar(bool despawn) { DespawnAtFar = despawn; }
bool GetAttack() { return m_bIsActiveAttacker; }//used in EnterEvadeMode override
void SetCanAttack(bool attack) { m_bIsActiveAttacker = attack; }
uint64 GetEventStarterGUID() { return m_uiPlayerGUID; }
void AddEscortState(uint32 escortState) { m_uiEscortState |= escortState; }
void RemoveEscortState(uint32 escortState) { m_uiEscortState &= ~escortState; }
protected:
Player* GetPlayerForEscort() { return ObjectAccessor::GetPlayer(*me, m_uiPlayerGUID); }
private:
bool AssistPlayerInCombat(Unit* who);
bool IsPlayerOrGroupInRange();
void FillPointMovementListForCreature();
uint64 m_uiPlayerGUID;
uint32 m_uiWPWaitTimer;
uint32 m_uiPlayerCheckTimer;
uint32 m_uiEscortState;
float MaxPlayerDistance;
Quest const* m_pQuestForEscort; //generally passed in Start() when regular escort script.
std::list<Escort_Waypoint> WaypointList;
std::list<Escort_Waypoint>::iterator CurrentWP;
bool m_bIsActiveAttacker; //obsolete, determined by faction.
bool m_bIsRunning; //all creatures are walking by default (has flag MOVEMENTFLAG_WALK)
bool m_bCanInstantRespawn; //if creature should respawn instantly after escort over (if not, database respawntime are used)
bool m_bCanReturnToStart; //if creature can walk same path (loop) without despawn. Not for regular escort quests.
bool DespawnAtEnd;
bool DespawnAtFar;
bool ScriptWP;
bool HasImmuneToNPCFlags;
};
#endif

View File

@@ -1,362 +0,0 @@
/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* This program is free software licensed under GPL version 2
* Please see the included DOCS/LICENSE.TXT for more information */
/* ScriptData
SDName: FollowerAI
SD%Complete: 50
SDComment: This AI is under development
SDCategory: Npc
EndScriptData */
#include "ScriptedCreature.h"
#include "ScriptedFollowerAI.h"
#include "Group.h"
#include "Player.h"
const float MAX_PLAYER_DISTANCE = 100.0f;
enum ePoints
{
POINT_COMBAT_START = 0xFFFFFF
};
FollowerAI::FollowerAI(Creature* creature) : ScriptedAI(creature),
m_uiLeaderGUID(0),
m_uiUpdateFollowTimer(2500),
m_uiFollowState(STATE_FOLLOW_NONE),
m_pQuestForFollow(NULL)
{}
void FollowerAI::AttackStart(Unit* who)
{
if (!who)
return;
if (me->Attack(who, true))
{
// This is done in Unit::Attack function which wont bug npcs by not adding threat upon combat start...
//me->AddThreat(who, 0.0f);
//me->SetInCombatWith(who);
//who->SetInCombatWith(me);
if (me->HasUnitState(UNIT_STATE_FOLLOW))
me->ClearUnitState(UNIT_STATE_FOLLOW);
if (IsCombatMovementAllowed())
me->GetMotionMaster()->MoveChase(who);
}
}
//This part provides assistance to a player that are attacked by who, even if out of normal aggro range
//It will cause me to attack who that are attacking _any_ player (which has been confirmed may happen also on offi)
//The flag (type_flag) is unconfirmed, but used here for further research and is a good candidate.
bool FollowerAI::AssistPlayerInCombat(Unit* who)
{
if (!who || !who->GetVictim())
return false;
//experimental (unknown) flag not present
if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_AID_PLAYERS))
return false;
//not a player
if (!who->GetVictim()->GetCharmerOrOwnerPlayerOrPlayerItself())
return false;
//never attack friendly
if (me->IsFriendlyTo(who))
return false;
//too far away and no free sight?
if (me->IsWithinDistInMap(who, MAX_PLAYER_DISTANCE) && me->IsWithinLOSInMap(who))
{
AttackStart(who);
return true;
}
return false;
}
void FollowerAI::MoveInLineOfSight(Unit* who)
{
if (me->GetVictim())
return;
if (!me->HasUnitState(UNIT_STATE_STUNNED) && who->isTargetableForAttack(true, me) && who->isInAccessiblePlaceFor(me))
if (HasFollowState(STATE_FOLLOW_INPROGRESS) && AssistPlayerInCombat(who))
return;
if (me->CanStartAttack(who))
AttackStart(who);
}
void FollowerAI::JustDied(Unit* /*pKiller*/)
{
if (!HasFollowState(STATE_FOLLOW_INPROGRESS) || !m_uiLeaderGUID || !m_pQuestForFollow)
return;
//TODO: need a better check for quests with time limit.
if (Player* player = GetLeaderForFollower())
{
if (Group* group = player->GetGroup())
{
for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next())
{
if (Player* member = groupRef->GetSource())
{
if (member->IsInMap(player) && member->GetQuestStatus(m_pQuestForFollow->GetQuestId()) == QUEST_STATUS_INCOMPLETE)
member->FailQuest(m_pQuestForFollow->GetQuestId());
}
}
}
else
{
if (player->GetQuestStatus(m_pQuestForFollow->GetQuestId()) == QUEST_STATUS_INCOMPLETE)
player->FailQuest(m_pQuestForFollow->GetQuestId());
}
}
}
void FollowerAI::JustRespawned()
{
m_uiFollowState = STATE_FOLLOW_NONE;
if (!IsCombatMovementAllowed())
SetCombatMovement(true);
if (me->getFaction() != me->GetCreatureTemplate()->faction)
me->setFaction(me->GetCreatureTemplate()->faction);
Reset();
}
void FollowerAI::EnterEvadeMode()
{
me->RemoveAllAuras();
me->DeleteThreatList();
me->CombatStop(true);
me->SetLootRecipient(NULL);
if (HasFollowState(STATE_FOLLOW_INPROGRESS))
{
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: FollowerAI left combat, returning to CombatStartPosition.");
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
{
float fPosX, fPosY, fPosZ;
me->GetPosition(fPosX, fPosY, fPosZ);
me->GetMotionMaster()->MovePoint(POINT_COMBAT_START, fPosX, fPosY, fPosZ);
}
}
else
{
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
me->GetMotionMaster()->MoveTargetedHome();
}
Reset();
}
void FollowerAI::UpdateAI(uint32 uiDiff)
{
if (HasFollowState(STATE_FOLLOW_INPROGRESS) && !me->GetVictim())
{
if (m_uiUpdateFollowTimer <= uiDiff)
{
if (HasFollowState(STATE_FOLLOW_COMPLETE) && !HasFollowState(STATE_FOLLOW_POSTEVENT))
{
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: FollowerAI is set completed, despawns.");
me->DespawnOrUnsummon();
return;
}
bool bIsMaxRangeExceeded = true;
if (Player* player = GetLeaderForFollower())
{
if (HasFollowState(STATE_FOLLOW_RETURNING))
{
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: FollowerAI is returning to leader.");
RemoveFollowState(STATE_FOLLOW_RETURNING);
me->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
return;
}
if (Group* group = player->GetGroup())
{
for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next())
{
Player* member = groupRef->GetSource();
if (member && me->IsWithinDistInMap(member, MAX_PLAYER_DISTANCE))
{
bIsMaxRangeExceeded = false;
break;
}
}
}
else
{
if (me->IsWithinDistInMap(player, MAX_PLAYER_DISTANCE))
bIsMaxRangeExceeded = false;
}
}
if (bIsMaxRangeExceeded)
{
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: FollowerAI failed because player/group was to far away or not found");
me->DespawnOrUnsummon();
return;
}
m_uiUpdateFollowTimer = 1000;
}
else
m_uiUpdateFollowTimer -= uiDiff;
}
UpdateFollowerAI(uiDiff);
}
void FollowerAI::UpdateFollowerAI(uint32 /*uiDiff*/)
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
void FollowerAI::MovementInform(uint32 motionType, uint32 pointId)
{
if (motionType != POINT_MOTION_TYPE || !HasFollowState(STATE_FOLLOW_INPROGRESS))
return;
if (pointId == POINT_COMBAT_START)
{
if (GetLeaderForFollower())
{
if (!HasFollowState(STATE_FOLLOW_PAUSED))
AddFollowState(STATE_FOLLOW_RETURNING);
}
else
me->DespawnOrUnsummon();
}
}
void FollowerAI::StartFollow(Player* player, uint32 factionForFollower, const Quest* quest)
{
if (me->GetVictim())
{
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: FollowerAI attempt to StartFollow while in combat.");
return;
}
if (HasFollowState(STATE_FOLLOW_INPROGRESS))
{
sLog->outError("TSCR: FollowerAI attempt to StartFollow while already following.");
return;
}
//set variables
m_uiLeaderGUID = player->GetGUID();
if (factionForFollower)
me->setFaction(factionForFollower);
m_pQuestForFollow = quest;
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
{
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: FollowerAI start with WAYPOINT_MOTION_TYPE, set to MoveIdle.");
}
me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
AddFollowState(STATE_FOLLOW_INPROGRESS);
me->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: FollowerAI start follow %s (GUID " UI64FMTD ")", player->GetName().c_str(), m_uiLeaderGUID);
}
Player* FollowerAI::GetLeaderForFollower()
{
if (Player* player = ObjectAccessor::GetPlayer(*me, m_uiLeaderGUID))
{
if (player->IsAlive())
return player;
else
{
if (Group* group = player->GetGroup())
{
for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next())
{
Player* member = groupRef->GetSource();
if (member && me->IsWithinDistInMap(member, MAX_PLAYER_DISTANCE) && member->IsAlive())
{
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: FollowerAI GetLeader changed and returned new leader.");
m_uiLeaderGUID = member->GetGUID();
return member;
}
}
}
}
}
;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: FollowerAI GetLeader can not find suitable leader.");
return NULL;
}
void FollowerAI::SetFollowComplete(bool bWithEndEvent)
{
if (me->HasUnitState(UNIT_STATE_FOLLOW))
{
me->ClearUnitState(UNIT_STATE_FOLLOW);
me->StopMoving();
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
}
if (bWithEndEvent)
AddFollowState(STATE_FOLLOW_POSTEVENT);
else
{
if (HasFollowState(STATE_FOLLOW_POSTEVENT))
RemoveFollowState(STATE_FOLLOW_POSTEVENT);
}
AddFollowState(STATE_FOLLOW_COMPLETE);
}
void FollowerAI::SetFollowPaused(bool paused)
{
if (!HasFollowState(STATE_FOLLOW_INPROGRESS) || HasFollowState(STATE_FOLLOW_COMPLETE))
return;
if (paused)
{
AddFollowState(STATE_FOLLOW_PAUSED);
if (me->HasUnitState(UNIT_STATE_FOLLOW))
{
me->ClearUnitState(UNIT_STATE_FOLLOW);
me->StopMoving();
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
}
}
else
{
RemoveFollowState(STATE_FOLLOW_PAUSED);
if (Player* leader = GetLeaderForFollower())
me->GetMotionMaster()->MoveFollow(leader, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
}
}

View File

@@ -1,67 +0,0 @@
/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* This program is free software licensed under GPL version 2
* Please see the included DOCS/LICENSE.TXT for more information */
#ifndef SC_FOLLOWERAI_H
#define SC_FOLLOWERAI_H
#include "ScriptSystem.h"
enum eFollowState
{
STATE_FOLLOW_NONE = 0x000,
STATE_FOLLOW_INPROGRESS = 0x001, //must always have this state for any follow
STATE_FOLLOW_RETURNING = 0x002, //when returning to combat start after being in combat
STATE_FOLLOW_PAUSED = 0x004, //disables following
STATE_FOLLOW_COMPLETE = 0x008, //follow is completed and may end
STATE_FOLLOW_PREEVENT = 0x010, //not implemented (allow pre event to run, before follow is initiated)
STATE_FOLLOW_POSTEVENT = 0x020 //can be set at complete and allow post event to run
};
class FollowerAI : public ScriptedAI
{
public:
explicit FollowerAI(Creature* creature);
~FollowerAI() {}
//virtual void WaypointReached(uint32 uiPointId) = 0;
void MovementInform(uint32 motionType, uint32 pointId);
void AttackStart(Unit*);
void MoveInLineOfSight(Unit*);
void EnterEvadeMode();
void JustDied(Unit*);
void JustRespawned();
void UpdateAI(uint32); //the "internal" update, calls UpdateFollowerAI()
virtual void UpdateFollowerAI(uint32); //used when it's needed to add code in update (abilities, scripted events, etc)
void StartFollow(Player* player, uint32 factionForFollower = 0, const Quest* quest = NULL);
void SetFollowPaused(bool bPaused); //if special event require follow mode to hold/resume during the follow
void SetFollowComplete(bool bWithEndEvent = false);
bool HasFollowState(uint32 uiFollowState) { return (m_uiFollowState & uiFollowState); }
protected:
Player* GetLeaderForFollower();
private:
void AddFollowState(uint32 uiFollowState) { m_uiFollowState |= uiFollowState; }
void RemoveFollowState(uint32 uiFollowState) { m_uiFollowState &= ~uiFollowState; }
bool AssistPlayerInCombat(Unit* who);
uint64 m_uiLeaderGUID;
uint32 m_uiUpdateFollowTimer;
uint32 m_uiFollowState;
const Quest* m_pQuestForFollow; //normally we have a quest
};
#endif

View File

@@ -1,90 +0,0 @@
/* Copyright (C)
*
*
*
* This program is free software licensed under GPL version 2
* Please see the included DOCS/LICENSE.TXT for more information */
#ifndef SC_GOSSIP_H
#define SC_GOSSIP_H
#include "GossipDef.h"
#include "QuestDef.h"
// Gossip Item Text
#define GOSSIP_TEXT_BROWSE_GOODS "I'd like to browse your goods."
#define GOSSIP_TEXT_TRAIN "Train me!"
enum eTradeskill
{
// Skill defines
TRADESKILL_ALCHEMY = 1,
TRADESKILL_BLACKSMITHING = 2,
TRADESKILL_COOKING = 3,
TRADESKILL_ENCHANTING = 4,
TRADESKILL_ENGINEERING = 5,
TRADESKILL_FIRSTAID = 6,
TRADESKILL_HERBALISM = 7,
TRADESKILL_LEATHERWORKING = 8,
TRADESKILL_POISONS = 9,
TRADESKILL_TAILORING = 10,
TRADESKILL_MINING = 11,
TRADESKILL_FISHING = 12,
TRADESKILL_SKINNING = 13,
TRADESKILL_JEWLCRAFTING = 14,
TRADESKILL_INSCRIPTION = 15,
TRADESKILL_LEVEL_NONE = 0,
TRADESKILL_LEVEL_APPRENTICE = 1,
TRADESKILL_LEVEL_JOURNEYMAN = 2,
TRADESKILL_LEVEL_EXPERT = 3,
TRADESKILL_LEVEL_ARTISAN = 4,
TRADESKILL_LEVEL_MASTER = 5,
TRADESKILL_LEVEL_GRAND_MASTER = 6,
// Gossip defines
GOSSIP_ACTION_TRADE = 1,
GOSSIP_ACTION_TRAIN = 2,
GOSSIP_ACTION_TAXI = 3,
GOSSIP_ACTION_GUILD = 4,
GOSSIP_ACTION_BATTLE = 5,
GOSSIP_ACTION_BANK = 6,
GOSSIP_ACTION_INN = 7,
GOSSIP_ACTION_HEAL = 8,
GOSSIP_ACTION_TABARD = 9,
GOSSIP_ACTION_AUCTION = 10,
GOSSIP_ACTION_INN_INFO = 11,
GOSSIP_ACTION_UNLEARN = 12,
GOSSIP_ACTION_INFO_DEF = 1000,
GOSSIP_SENDER_MAIN = 1,
GOSSIP_SENDER_INN_INFO = 2,
GOSSIP_SENDER_INFO = 3,
GOSSIP_SENDER_SEC_PROFTRAIN = 4,
GOSSIP_SENDER_SEC_CLASSTRAIN = 5,
GOSSIP_SENDER_SEC_BATTLEINFO = 6,
GOSSIP_SENDER_SEC_BANK = 7,
GOSSIP_SENDER_SEC_INN = 8,
GOSSIP_SENDER_SEC_MAILBOX = 9,
GOSSIP_SENDER_SEC_STABLEMASTER = 10
};
// Defined fuctions to use with player.
// This fuction add's a menu item,
// a - Icon Id
// b - Text
// c - Sender(this is to identify the current Menu with this item)
// d - Action (identifys this Menu Item)
// e - Text to be displayed in pop up box
// f - Money value in pop up box
#define ADD_GOSSIP_ITEM(a, b, c, d) PlayerTalkClass->GetGossipMenu().AddMenuItem(-1, a, b, c, d, "", 0)
#define ADD_GOSSIP_ITEM_EXTENDED(a, b, c, d, e, f, g) PlayerTalkClass->GetGossipMenu().AddMenuItem(-1, a, b, c, d, e, f, g)
// This fuction Sends the current menu to show to client, a - NPCTEXTID(uint32), b - npc guid(uint64)
#define SEND_GOSSIP_MENU(a, b) PlayerTalkClass->SendGossipMenu(a, b)
// Closes the Menu
#define CLOSE_GOSSIP_MENU() PlayerTalkClass->SendCloseGossip()
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,274 +0,0 @@
/*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_SMARTAI_H
#define TRINITY_SMARTAI_H
#include "Common.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "Unit.h"
#include "Spell.h"
#include "SmartScript.h"
#include "SmartScriptMgr.h"
#include "GameObjectAI.h"
enum SmartEscortState
{
SMART_ESCORT_NONE = 0x000, //nothing in progress
SMART_ESCORT_ESCORTING = 0x001, //escort is in progress
SMART_ESCORT_RETURNING = 0x002, //escort is returning after being in combat
SMART_ESCORT_PAUSED = 0x004 //will not proceed with waypoints before state is removed
};
enum SmartEscortVars
{
SMART_ESCORT_MAX_PLAYER_DIST = 60,
SMART_MAX_AID_DIST = SMART_ESCORT_MAX_PLAYER_DIST / 2,
};
class SmartAI : public CreatureAI
{
public:
~SmartAI(){};
explicit SmartAI(Creature* c);
// Start moving to the desired MovePoint
void StartPath(bool run = false, uint32 path = 0, bool repeat = false, Unit* invoker = NULL);
bool LoadPath(uint32 entry);
void PausePath(uint32 delay, bool forced = false);
void StopPath(uint32 DespawnTime = 0, uint32 quest = 0, bool fail = false);
void EndPath(bool fail = false);
void ResumePath();
WayPoint* GetNextWayPoint();
void GenerateWayPointArray(Movement::PointsArray* points);
bool HasEscortState(uint32 uiEscortState) { return (mEscortState & uiEscortState); }
void AddEscortState(uint32 uiEscortState) { mEscortState |= uiEscortState; }
virtual bool IsEscorted() { return (mEscortState & SMART_ESCORT_ESCORTING); }
void RemoveEscortState(uint32 uiEscortState) { mEscortState &= ~uiEscortState; }
void SetAutoAttack(bool on) { mCanAutoAttack = on; }
void SetCombatMove(bool on);
bool CanCombatMove() { return mCanCombatMove; }
void SetFollow(Unit* target, float dist = 0.0f, float angle = 0.0f, uint32 credit = 0, uint32 end = 0, uint32 creditType = 0, bool aliveState = true);
void StopFollow(bool complete);
void SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker);
SmartScript* GetScript() { return &mScript; }
bool IsEscortInvokerInRange();
// Called when creature is spawned or respawned
void JustRespawned();
// Called at reaching home after evade, InitializeAI(), EnterEvadeMode() for resetting variables
void JustReachedHome();
// Called for reaction at enter to combat if not in combat yet (enemy can be NULL)
void EnterCombat(Unit* enemy);
// Called for reaction at stopping attack at no attackers or targets
void EnterEvadeMode();
// Called when the creature is killed
void JustDied(Unit* killer);
// Called when the creature kills a unit
void KilledUnit(Unit* victim);
// Called when the creature summon successfully other creature
void JustSummoned(Creature* creature);
// Tell creature to attack and follow the victim
void AttackStart(Unit* who);
// Called if IsVisible(Unit* who) is true at each *who move, reaction at visibility zone enter
void MoveInLineOfSight(Unit* who);
// Called when hit by a spell
void SpellHit(Unit* unit, const SpellInfo* spellInfo);
// Called when spell hits a target
void SpellHitTarget(Unit* target, const SpellInfo* spellInfo);
// Called at any Damage from any attacker (before damage apply)
void DamageTaken(Unit* done_by, uint32 &damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask);
// Called when the creature receives heal
void HealReceived(Unit* doneBy, uint32& addhealth);
// Called at World update tick
void UpdateAI(uint32 diff);
// Called at text emote receive from player
void ReceiveEmote(Player* player, uint32 textEmote);
// Called at waypoint reached or point movement finished
void MovementInform(uint32 MovementType, uint32 Data);
// Called when creature is summoned by another unit
void IsSummonedBy(Unit* summoner);
// Called at any Damage to any victim (before damage apply)
void DamageDealt(Unit* doneTo, uint32& damage, DamageEffectType damagetyp);
// Called when a summoned creature dissapears (UnSommoned)
void SummonedCreatureDespawn(Creature* unit);
// called when the corpse of this creature gets removed
void CorpseRemoved(uint32& respawnDelay);
// Called at World update tick if creature is charmed
void UpdateAIWhileCharmed(const uint32 diff);
// Called when a Player/Creature enters the creature (vehicle)
void PassengerBoarded(Unit* who, int8 seatId, bool apply);
// Called when gets initialized, when creature is added to world
void InitializeAI();
// Called when creature gets charmed by another unit
void OnCharmed(bool apply);
// Called when victim is in line of sight
bool CanAIAttack(const Unit* who) const;
// Used in scripts to share variables
void DoAction(int32 param = 0);
// Used in scripts to share variables
uint32 GetData(uint32 id = 0) const;
// Used in scripts to share variables
void SetData(uint32 id, uint32 value);
// Used in scripts to share variables
void SetGUID(uint64 guid, int32 id = 0);
// Used in scripts to share variables
uint64 GetGUID(int32 id = 0) const;
//core related
static int32 Permissible(const Creature*);
// Called at movepoint reached
void MovepointReached(uint32 id);
// Makes the creature run/walk
void SetRun(bool run = true);
void SetFly(bool fly = true);
void SetSwim(bool swim = true);
void SetInvincibilityHpLevel(uint32 level) { mInvincibilityHpLevel = level; }
void sGossipHello(Player* player);
void sGossipSelect(Player* player, uint32 sender, uint32 action);
void sGossipSelectCode(Player* player, uint32 sender, uint32 action, const char* code);
void sQuestAccept(Player* player, Quest const* quest);
//void sQuestSelect(Player* player, Quest const* quest);
//void sQuestComplete(Player* player, Quest const* quest);
void sQuestReward(Player* player, Quest const* quest, uint32 opt);
void sOnGameEvent(bool start, uint16 eventId);
uint32 mEscortQuestID;
void SetDespawnTime (uint32 t)
{
mDespawnTime = t;
mDespawnState = t ? 1 : 0;
}
void StartDespawn() { mDespawnState = 2; }
void OnSpellClick(Unit* clicker, bool& result);
// Xinef
void SetWPPauseTimer(uint32 time) { mWPPauseTimer = time; }
void SetForcedCombatMove(float dist);
private:
uint32 mFollowCreditType;
uint32 mFollowArrivedTimer;
uint32 mFollowCredit;
uint32 mFollowArrivedEntry;
bool mFollowArrivedAlive;
uint64 mFollowGuid;
float mFollowDist;
float mFollowAngle;
void ReturnToLastOOCPos();
void UpdatePath(const uint32 diff);
SmartScript mScript;
WPPath* mWayPoints;
uint32 mEscortState;
uint32 mCurrentWPID;
bool mWPReached;
bool mOOCReached;
uint32 mWPPauseTimer;
WayPoint* mLastWP;
uint32 mEscortNPCFlags;
uint32 GetWPCount() { return mWayPoints ? mWayPoints->size() : 0; }
bool mCanRepeatPath;
bool mRun;
bool mCanAutoAttack;
bool mCanCombatMove;
bool mForcedPaused;
uint32 mInvincibilityHpLevel;
bool AssistPlayerInCombat(Unit* who);
uint32 mDespawnTime;
uint32 mDespawnState;
void UpdateDespawn(const uint32 diff);
uint32 mEscortInvokerCheckTimer;
bool mJustReset;
// Xinef: Vehicle conditions
void CheckConditions(const uint32 diff);
ConditionList conditions;
uint32 m_ConditionsTimer;
};
class SmartGameObjectAI : public GameObjectAI
{
public:
SmartGameObjectAI(GameObject* g) : GameObjectAI(g) {}
~SmartGameObjectAI() {}
void UpdateAI(uint32 diff);
void InitializeAI();
void Reset();
SmartScript* GetScript() { return &mScript; }
static int32 Permissible(const GameObject* g);
bool GossipHello(Player* player, bool reportUse);
bool GossipSelect(Player* player, uint32 sender, uint32 action);
bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/);
bool QuestAccept(Player* player, Quest const* quest);
bool QuestReward(Player* player, Quest const* quest, uint32 opt);
void Destroyed(Player* player, uint32 eventId);
void SetData(uint32 id, uint32 value);
void SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker);
void OnGameEvent(bool start, uint16 eventId);
void OnStateChanged(uint32 state, Unit* unit);
void EventInform(uint32 eventId);
void SpellHit(Unit* unit, const SpellInfo* spellInfo);
protected:
SmartScript mScript;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,343 +0,0 @@
/*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRINITY_SMARTSCRIPT_H
#define TRINITY_SMARTSCRIPT_H
#include "Common.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "Unit.h"
#include "Spell.h"
#include "GridNotifiers.h"
#include "SmartScriptMgr.h"
//#include "SmartAI.h"
class SmartScript
{
public:
SmartScript();
~SmartScript();
void OnInitialize(WorldObject* obj, AreaTriggerEntry const* at = NULL);
void GetScript();
void FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at);
void ProcessEventsFor(SMART_EVENT e, Unit* unit = NULL, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = NULL, GameObject* gob = NULL);
void ProcessEvent(SmartScriptHolder& e, Unit* unit = NULL, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = NULL, GameObject* gob = NULL);
bool CheckTimer(SmartScriptHolder const& e) const;
void RecalcTimer(SmartScriptHolder& e, uint32 min, uint32 max);
void UpdateTimer(SmartScriptHolder& e, uint32 const diff);
void InitTimer(SmartScriptHolder& e);
void ProcessAction(SmartScriptHolder& e, Unit* unit = NULL, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = NULL, GameObject* gob = NULL);
void ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit = NULL, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = NULL, GameObject* gob = NULL);
ObjectList* GetTargets(SmartScriptHolder const& e, Unit* invoker = NULL);
ObjectList* GetWorldObjectsInDist(float dist);
void InstallTemplate(SmartScriptHolder const& e);
SmartScriptHolder CreateEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 phaseMask = 0);
void AddEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 phaseMask = 0);
void SetPathId(uint32 id) { mPathId = id; }
uint32 GetPathId() const { return mPathId; }
WorldObject* GetBaseObject()
{
WorldObject* obj = NULL;
if (me)
obj = me;
else if (go)
obj = go;
return obj;
}
bool IsUnit(WorldObject* obj)
{
return obj && obj->IsInWorld() && (obj->GetTypeId() == TYPEID_UNIT || obj->GetTypeId() == TYPEID_PLAYER);
}
bool IsPlayer(WorldObject* obj)
{
return obj && obj->IsInWorld() && obj->GetTypeId() == TYPEID_PLAYER;
}
bool IsCreature(WorldObject* obj)
{
return obj && obj->IsInWorld() && obj->GetTypeId() == TYPEID_UNIT;
}
bool IsGameObject(WorldObject* obj)
{
return obj && obj->IsInWorld() && obj->GetTypeId() == TYPEID_GAMEOBJECT;
}
void OnUpdate(const uint32 diff);
void OnMoveInLineOfSight(Unit* who);
Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff);
void DoFindFriendlyCC(std::list<Creature*>& _list, float range);
void DoFindFriendlyMissingBuff(std::list<Creature*>& list, float range, uint32 spellid);
Unit* DoFindClosestFriendlyInRange(float range, bool playerOnly);
void StoreTargetList(ObjectList* targets, uint32 id)
{
if (!targets)
return;
if (mTargetStorage->find(id) != mTargetStorage->end())
{
// check if already stored
if ((*mTargetStorage)[id]->Equals(targets))
return;
delete (*mTargetStorage)[id];
}
(*mTargetStorage)[id] = new ObjectGuidList(targets, GetBaseObject());
}
bool IsSmart(Creature* c = NULL)
{
bool smart = true;
if (c && c->GetAIName() != "SmartAI")
smart = false;
if (!me || me->GetAIName() != "SmartAI")
smart = false;
if (!smart)
sLog->outErrorDb("SmartScript: Action target Creature(entry: %u) is not using SmartAI, action skipped to prevent crash.", c ? c->GetEntry() : (me ? me->GetEntry() : 0));
return smart;
}
bool IsSmartGO(GameObject* g = NULL)
{
bool smart = true;
if (g && g->GetAIName() != "SmartGameObjectAI")
smart = false;
if (!go || go->GetAIName() != "SmartGameObjectAI")
smart = false;
if (!smart)
sLog->outErrorDb("SmartScript: Action target GameObject(entry: %u) is not using SmartGameObjectAI, action skipped to prevent crash.", g ? g->GetEntry() : (go ? go->GetEntry() : 0));
return smart;
}
ObjectList* GetTargetList(uint32 id)
{
ObjectListMap::iterator itr = mTargetStorage->find(id);
if (itr != mTargetStorage->end())
return (*itr).second->GetObjectList();
return NULL;
}
void StoreCounter(uint32 id, uint32 value, uint32 reset)
{
CounterMap::iterator itr = mCounterList.find(id);
if (itr != mCounterList.end())
{
if (reset == 0)
itr->second += value;
else
itr->second = value;
}
else
mCounterList.insert(std::make_pair(id, value));
ProcessEventsFor(SMART_EVENT_COUNTER_SET, NULL, id);
}
uint32 GetCounterValue(uint32 id)
{
CounterMap::iterator itr = mCounterList.find(id);
if (itr != mCounterList.end())
return itr->second;
return 0;
}
GameObject* FindGameObjectNear(WorldObject* searchObject, uint32 guid) const
{
GameObject* gameObject = NULL;
CellCoord p(Trinity::ComputeCellCoord(searchObject->GetPositionX(), searchObject->GetPositionY()));
Cell cell(p);
Trinity::GameObjectWithDbGUIDCheck goCheck(*searchObject, guid);
Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(searchObject, gameObject, goCheck);
TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > objectChecker(checker);
cell.Visit(p, objectChecker, *searchObject->GetMap(), *searchObject, searchObject->GetVisibilityRange());
return gameObject;
}
Creature* FindCreatureNear(WorldObject* searchObject, uint32 guid) const
{
Creature* creature = NULL;
CellCoord p(Trinity::ComputeCellCoord(searchObject->GetPositionX(), searchObject->GetPositionY()));
Cell cell(p);
Trinity::CreatureWithDbGUIDCheck target_check(searchObject, guid);
Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(searchObject, creature, target_check);
TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker);
cell.Visit(p, unit_checker, *searchObject->GetMap(), *searchObject, searchObject->GetVisibilityRange());
return creature;
}
ObjectListMap* mTargetStorage;
void OnReset();
void ResetBaseObject()
{
if (meOrigGUID)
{
if (Creature* m = HashMapHolder<Creature>::Find(meOrigGUID))
{
me = m;
go = NULL;
}
}
if (goOrigGUID)
{
if (GameObject* o = HashMapHolder<GameObject>::Find(goOrigGUID))
{
me = NULL;
go = o;
}
}
goOrigGUID = 0;
meOrigGUID = 0;
}
//TIMED_ACTIONLIST (script type 9 aka script9)
void SetScript9(SmartScriptHolder& e, uint32 entry);
Unit* GetLastInvoker(Unit* invoker = NULL);
uint64 mLastInvoker;
typedef UNORDERED_MAP<uint32, uint32> CounterMap;
CounterMap mCounterList;
// Xinef: Fix Combat Movement
void SetActualCombatDist(uint32 dist) { mActualCombatDist = dist; }
void RestoreMaxCombatDist() { mActualCombatDist = mMaxCombatDist; }
uint32 GetActualCombatDist() const { return mActualCombatDist; }
uint32 GetMaxCombatDist() const { return mMaxCombatDist; }
// Xinef: SmartCasterAI, replace above
void SetCasterActualDist(float dist) { smartCasterActualDist = dist; }
void RestoreCasterMaxDist() { smartCasterActualDist = smartCasterMaxDist; }
Powers GetCasterPowerType() const { return smartCasterPowerType; }
float GetCasterActualDist() const { return smartCasterActualDist; }
float GetCasterMaxDist() const { return smartCasterMaxDist; }
bool AllowPhaseReset() const { return _allowPhaseReset; }
void SetPhaseReset(bool allow) { _allowPhaseReset = allow; }
private:
void IncPhase(uint32 p)
{
// Xinef: protect phase from overflowing
mEventPhase = std::min<uint32>(SMART_EVENT_PHASE_12, mEventPhase + p);
}
void DecPhase(uint32 p)
{
if (p >= mEventPhase)
mEventPhase = 0;
else
mEventPhase -= p;
}
bool IsInPhase(uint32 p) const
{
if (mEventPhase == 0)
return false;
return (1 << (mEventPhase - 1)) & p;
}
void SetPhase(uint32 p = 0) { mEventPhase = p; }
SmartAIEventList mEvents;
SmartAIEventList mInstallEvents;
SmartAIEventList mTimedActionList;
bool isProcessingTimedActionList;
Creature* me;
uint64 meOrigGUID;
GameObject* go;
uint64 goOrigGUID;
AreaTriggerEntry const* trigger;
SmartScriptType mScriptType;
uint32 mEventPhase;
UNORDERED_MAP<int32, int32> mStoredDecimals;
uint32 mPathId;
SmartAIEventStoredList mStoredEvents;
std::list<uint32> mRemIDs;
uint32 mTextTimer;
uint32 mLastTextID;
uint32 mTalkerEntry;
bool mUseTextTimer;
// Xinef: Fix Combat Movement
uint32 mActualCombatDist;
uint32 mMaxCombatDist;
// Xinef: SmartCasterAI, replace above in future
uint32 smartCasterActualDist;
uint32 smartCasterMaxDist;
Powers smartCasterPowerType;
// Xinef: misc
bool _allowPhaseReset;
SMARTAI_TEMPLATE mTemplate;
void InstallEvents();
void RemoveStoredEvent (uint32 id)
{
if (!mStoredEvents.empty())
{
for (SmartAIEventStoredList::iterator i = mStoredEvents.begin(); i != mStoredEvents.end(); ++i)
{
if (i->event_id == id)
{
mStoredEvents.erase(i);
return;
}
}
}
}
SmartScriptHolder FindLinkedEvent (uint32 link)
{
if (!mEvents.empty())
{
for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
{
if (i->event_id == link)
{
return (*i);
}
}
}
SmartScriptHolder s;
return s;
}
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,302 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AccountMgr.h"
#include "DatabaseEnv.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "Util.h"
#include "SHA1.h"
#include "WorldSession.h"
namespace AccountMgr
{
AccountOpResult CreateAccount(std::string username, std::string password)
{
if (utf8length(username) > MAX_ACCOUNT_STR)
return AOR_NAME_TOO_LONG; // username's too long
normalizeString(username);
normalizeString(password);
if (GetId(username))
return AOR_NAME_ALREDY_EXIST; // username does already exist
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT);
stmt->setString(0, username);
stmt->setString(1, CalculateShaPassHash(username, password));
LoginDatabase.Execute(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS_INIT);
LoginDatabase.Execute(stmt);
return AOR_OK; // everything's fine
}
AccountOpResult DeleteAccount(uint32 accountId)
{
// Check if accounts exists
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BY_ID);
stmt->setUInt32(0, accountId);
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (!result)
return AOR_NAME_NOT_EXIST;
// Obtain accounts characters
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID);
stmt->setUInt32(0, accountId);
result = CharacterDatabase.Query(stmt);
if (result)
{
do
{
uint32 guidLow = (*result)[0].GetUInt32();
uint64 guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER);
// Kick if player is online
if (Player* p = ObjectAccessor::FindPlayer(guid))
{
WorldSession* s = p->GetSession();
s->KickPlayer(); // mark session to remove at next session list update
s->LogoutPlayer(false); // logout player without waiting next session list update
}
Player::DeleteFromDB(guid, accountId, false, true); // no need to update realm characters
} while (result->NextRow());
}
// table realm specific but common for all characters of account for realm
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_TUTORIALS);
stmt->setUInt32(0, accountId);
CharacterDatabase.Execute(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ACCOUNT_DATA);
stmt->setUInt32(0, accountId);
CharacterDatabase.Execute(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_BAN);
stmt->setUInt32(0, accountId);
CharacterDatabase.Execute(stmt);
SQLTransaction trans = LoginDatabase.BeginTransaction();
stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT);
stmt->setUInt32(0, accountId);
trans->Append(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS);
stmt->setUInt32(0, accountId);
trans->Append(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS);
stmt->setUInt32(0, accountId);
trans->Append(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_BANNED);
stmt->setUInt32(0, accountId);
trans->Append(stmt);
LoginDatabase.CommitTransaction(trans);
return AOR_OK;
}
AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword)
{
// Check if accounts exists
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BY_ID);
stmt->setUInt32(0, accountId);
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (!result)
return AOR_NAME_NOT_EXIST;
if (utf8length(newUsername) > MAX_ACCOUNT_STR)
return AOR_NAME_TOO_LONG;
if (utf8length(newPassword) > MAX_ACCOUNT_STR)
return AOR_PASS_TOO_LONG;
normalizeString(newUsername);
normalizeString(newPassword);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_USERNAME);
stmt->setString(0, newUsername);
stmt->setString(1, CalculateShaPassHash(newUsername, newPassword));
stmt->setUInt32(2, accountId);
LoginDatabase.Execute(stmt);
return AOR_OK;
}
AccountOpResult ChangePassword(uint32 accountId, std::string newPassword)
{
std::string username;
if (!GetName(accountId, username))
return AOR_NAME_NOT_EXIST; // account doesn't exist
if (utf8length(newPassword) > MAX_ACCOUNT_STR)
return AOR_PASS_TOO_LONG;
normalizeString(username);
normalizeString(newPassword);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_PASSWORD);
stmt->setString(0, CalculateShaPassHash(username, newPassword));
stmt->setUInt32(1, accountId);
LoginDatabase.Execute(stmt);
return AOR_OK;
}
uint32 GetId(std::string const& username)
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME);
stmt->setString(0, username);
PreparedQueryResult result = LoginDatabase.Query(stmt);
return (result) ? (*result)[0].GetUInt32() : 0;
}
uint32 GetSecurity(uint32 accountId)
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL);
stmt->setUInt32(0, accountId);
PreparedQueryResult result = LoginDatabase.Query(stmt);
return (result) ? (*result)[0].GetUInt8() : uint32(SEC_PLAYER);
}
uint32 GetSecurity(uint32 accountId, int32 realmId)
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID);
stmt->setUInt32(0, accountId);
stmt->setInt32(1, realmId);
PreparedQueryResult result = LoginDatabase.Query(stmt);
return (result) ? (*result)[0].GetUInt8() : uint32(SEC_PLAYER);
}
bool GetName(uint32 accountId, std::string& name)
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_USERNAME_BY_ID);
stmt->setUInt32(0, accountId);
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (result)
{
name = (*result)[0].GetString();
return true;
}
return false;
}
bool CheckPassword(uint32 accountId, std::string password)
{
std::string username;
if (!GetName(accountId, username))
return false;
normalizeString(username);
normalizeString(password);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_CHECK_PASSWORD);
stmt->setUInt32(0, accountId);
stmt->setString(1, CalculateShaPassHash(username, password));
PreparedQueryResult result = LoginDatabase.Query(stmt);
return (result) ? true : false;
}
uint32 GetCharactersCount(uint32 accountId)
{
// check character count
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS);
stmt->setUInt32(0, accountId);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
return (result) ? (*result)[0].GetUInt64() : 0;
}
bool normalizeString(std::string& utf8String)
{
wchar_t buffer[MAX_ACCOUNT_STR + 1];
size_t maxLength = MAX_ACCOUNT_STR;
if (!Utf8toWStr(utf8String, buffer, maxLength))
return false;
#ifdef _MSC_VER
#pragma warning(disable: 4996)
#endif
std::transform(&buffer[0], buffer + maxLength, &buffer[0], wcharToUpperOnlyLatin);
#ifdef _MSC_VER
#pragma warning(default: 4996)
#endif
return WStrToUtf8(buffer, maxLength, utf8String);
}
std::string CalculateShaPassHash(std::string const& name, std::string const& password)
{
SHA1Hash sha;
sha.Initialize();
sha.UpdateData(name);
sha.UpdateData(":");
sha.UpdateData(password);
sha.Finalize();
return ByteArrayToHexStr(sha.GetDigest(), sha.GetLength());
}
bool IsPlayerAccount(uint32 gmlevel)
{
return gmlevel == SEC_PLAYER;
}
bool IsGMAccount(uint32 gmlevel)
{
return gmlevel >= SEC_GAMEMASTER && gmlevel <= SEC_CONSOLE;
}
bool IsAdminAccount(uint32 gmlevel)
{
return gmlevel >= SEC_ADMINISTRATOR && gmlevel <= SEC_CONSOLE;
}
bool IsConsoleAccount(uint32 gmlevel)
{
return gmlevel == SEC_CONSOLE;
}
} // Namespace AccountMgr

View File

@@ -1,59 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ACCMGR_H
#define _ACCMGR_H
#include "Define.h"
#include <string>
enum AccountOpResult
{
AOR_OK,
AOR_NAME_TOO_LONG,
AOR_PASS_TOO_LONG,
AOR_NAME_ALREDY_EXIST,
AOR_NAME_NOT_EXIST,
AOR_DB_INTERNAL_ERROR
};
#define MAX_ACCOUNT_STR 20
namespace AccountMgr
{
AccountOpResult CreateAccount(std::string username, std::string password);
AccountOpResult DeleteAccount(uint32 accountId);
AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword);
AccountOpResult ChangePassword(uint32 accountId, std::string newPassword);
bool CheckPassword(uint32 accountId, std::string password);
uint32 GetId(std::string const& username);
uint32 GetSecurity(uint32 accountId);
uint32 GetSecurity(uint32 accountId, int32 realmId);
bool GetName(uint32 accountId, std::string& name);
uint32 GetCharactersCount(uint32 accountId);
std::string CalculateShaPassHash(std::string const& name, std::string const& password);
bool normalizeString(std::string& utf8String);
bool IsPlayerAccount(uint32 gmlevel);
bool IsGMAccount(uint32 gmlevel);
bool IsAdminAccount(uint32 gmlevel);
bool IsConsoleAccount(uint32 gmlevel);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,403 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __TRINITY_ACHIEVEMENTMGR_H
#define __TRINITY_ACHIEVEMENTMGR_H
#include <map>
#include <string>
#include "Common.h"
#include <ace/Singleton.h>
#include "DatabaseEnv.h"
#include "DBCEnums.h"
#include "DBCStores.h"
typedef std::list<AchievementCriteriaEntry const*> AchievementCriteriaEntryList;
typedef std::list<AchievementEntry const*> AchievementEntryList;
typedef UNORDERED_MAP<uint32, AchievementCriteriaEntryList> AchievementCriteriaListByAchievement;
typedef std::map<uint32, AchievementEntryList> AchievementListByReferencedId;
struct CriteriaProgress
{
uint32 counter;
time_t date; // latest update time.
bool changed;
};
enum AchievementCriteriaDataType
{ // value1 value2 comment
ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE = 0, // 0 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE = 1, // creature_id 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2, // class_id race_id
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH= 3, // health_percent 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD = 4, // own_team 0 not corpse (not released body), own_team == false if enemy team expected
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA = 5, // spell_id effect_idx
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA = 6, // area id 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA = 7, // spell_id effect_idx
ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE = 8, // minvalue value provided with achievement update must be not less that limit
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL = 9, // minlevel minlevel of target
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER = 10, // gender 0=male; 1=female
ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT = 11, // scripted requirement
ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY = 12, // difficulty normal/heroic difficulty for current event map
ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT = 13, // count "with less than %u people in the zone"
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM = 14, // team HORDE(67), ALLIANCE(469)
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK = 15, // drunken_state 0 (enum DrunkenState) of player
ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY = 16, // holiday_id 0 event in holiday time
ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE = 17, // min_score max_score player's team win bg and opposition team have team score in range
ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT = 18, // 0 0 maker instance script call for check current criteria requirements fit
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19, // item_level item_quality for equipped item in slot to check item level and quality
ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID = 20, // map_id 0 player must be on map with id in map_id
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE = 21, // class_id race_id
ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY = 22, // N login on day of N-th Birthday
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE = 23 // title_id known (pvp) title, values from dbc
};
#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 24 // maximum value in AchievementCriteriaDataType enum
class Player;
class Unit;
struct AchievementCriteriaData
{
AchievementCriteriaDataType dataType;
union
{
// ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE = 0 (no data)
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE = 1
struct
{
uint32 id;
} creature;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2
// ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE = 21
struct
{
uint32 class_id;
uint32 race_id;
} classRace;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH = 3
struct
{
uint32 percent;
} health;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD = 4
struct
{
uint32 own_team_flag;
} player_dead;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA = 5
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA = 7
struct
{
uint32 spell_id;
uint32 effect_idx;
} aura;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA = 6
struct
{
uint32 id;
} area;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE = 8
struct
{
uint32 value;
uint32 compType;
} value;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL = 9
struct
{
uint32 minlevel;
} level;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER = 10
struct
{
uint32 gender;
} gender;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT = 11 (no data)
// ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY = 12
struct
{
uint32 difficulty;
} difficulty;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT = 13
struct
{
uint32 maxcount;
} map_players;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM = 14
struct
{
uint32 team;
} team;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK = 15
struct
{
uint32 state;
} drunk;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY = 16
struct
{
uint32 id;
} holiday;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE= 17
struct
{
uint32 min_score;
uint32 max_score;
} bg_loss_team_score;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT = 18 (no data)
// ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19
struct
{
uint32 item_level;
uint32 item_quality;
} equipped_item;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID = 20
struct
{
uint32 mapId;
} map_id;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY = 21
struct
{
uint32 nth_birthday;
} birthday_login;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_KNOWN_TITLE = 22
struct
{
uint32 title_id;
} known_title;
// ...
struct
{
uint32 value1;
uint32 value2;
} raw;
};
uint32 ScriptId;
AchievementCriteriaData() : dataType(ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE)
{
raw.value1 = 0;
raw.value2 = 0;
ScriptId = 0;
}
AchievementCriteriaData(uint32 _dataType, uint32 _value1, uint32 _value2, uint32 _scriptId) : dataType(AchievementCriteriaDataType(_dataType))
{
raw.value1 = _value1;
raw.value2 = _value2;
ScriptId = _scriptId;
}
bool IsValid(AchievementCriteriaEntry const* criteria);
bool Meets(uint32 criteria_id, Player const* source, Unit const* target, uint32 miscvalue1 = 0) const;
};
struct AchievementCriteriaDataSet
{
AchievementCriteriaDataSet() : criteria_id(0) {}
typedef std::vector<AchievementCriteriaData> Storage;
void Add(AchievementCriteriaData const& data) { storage.push_back(data); }
bool Meets(Player const* source, Unit const* target, uint32 miscvalue = 0) const;
void SetCriteriaId(uint32 id) {criteria_id = id;}
private:
uint32 criteria_id;
Storage storage;
};
typedef std::map<uint32, AchievementCriteriaDataSet> AchievementCriteriaDataMap;
struct AchievementReward
{
uint32 titleId[2];
uint32 itemId;
uint32 sender;
std::string subject;
std::string text;
uint32 mailTemplate;
};
typedef std::map<uint32, AchievementReward> AchievementRewards;
struct AchievementRewardLocale
{
StringVector subject;
StringVector text;
};
typedef std::map<uint32, AchievementRewardLocale> AchievementRewardLocales;
struct CompletedAchievementData
{
time_t date;
bool changed;
};
typedef UNORDERED_MAP<uint32, CriteriaProgress> CriteriaProgressMap;
typedef UNORDERED_MAP<uint32, CompletedAchievementData> CompletedAchievementMap;
class Unit;
class Player;
class WorldPacket;
class AchievementMgr
{
public:
AchievementMgr(Player* player);
~AchievementMgr();
void Reset();
static void DeleteFromDB(uint32 lowguid);
void LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult);
void SaveToDB(SQLTransaction& trans);
void ResetAchievementCriteria(AchievementCriteriaCondition condition, uint32 value, bool evenIfCriteriaComplete = false);
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, Unit* unit = NULL);
void CompletedAchievement(AchievementEntry const* entry);
void CheckAllAchievementCriteria();
void SendAllAchievementData() const;
void SendRespondInspectAchievements(Player* player) const;
bool HasAchieved(uint32 achievementId) const;
Player* GetPlayer() const { return m_player; }
void UpdateTimedAchievements(uint32 timeDiff);
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
void RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry); // used for quest and scripted timed achievements
void RemoveCriteriaProgress(AchievementCriteriaEntry const* entry);
private:
enum ProgressType { PROGRESS_SET, PROGRESS_ACCUMULATE, PROGRESS_HIGHEST, PROGRESS_RESET };
void SendAchievementEarned(AchievementEntry const* achievement) const;
void SendCriteriaUpdate(AchievementCriteriaEntry const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const;
CriteriaProgress* GetCriteriaProgress(AchievementCriteriaEntry const* entry);
void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, ProgressType ptype = PROGRESS_SET);
void CompletedCriteriaFor(AchievementEntry const* achievement);
bool IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement);
bool IsCompletedAchievement(AchievementEntry const* entry);
bool CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement);
void BuildAllDataPacket(WorldPacket* data, bool inspect = false) const;
Player* m_player;
CriteriaProgressMap m_criteriaProgress;
CompletedAchievementMap m_completedAchievements;
typedef std::map<uint32, uint32> TimedAchievementMap;
TimedAchievementMap m_timedAchievements; // Criteria id/time left in MS
};
class AchievementGlobalMgr
{
friend class ACE_Singleton<AchievementGlobalMgr, ACE_Null_Mutex>;
AchievementGlobalMgr() {}
~AchievementGlobalMgr() {}
public:
AchievementCriteriaEntryList const* GetAchievementCriteriaByType(AchievementCriteriaTypes type) const
{
return &m_AchievementCriteriasByType[type];
}
AchievementCriteriaEntryList const* GetSpecialAchievementCriteriaByType(AchievementCriteriaTypes type, uint32 val)
{
if (m_SpecialList[type].find(val) != m_SpecialList[type].end())
return &m_SpecialList[type][val];
return NULL;
}
AchievementCriteriaEntryList const* GetAchievementCriteriaByCondition(AchievementCriteriaCondition condition, uint32 val)
{
if (m_AchievementCriteriasByCondition[condition].find(val) != m_AchievementCriteriasByCondition[condition].end())
return &m_AchievementCriteriasByCondition[condition][val];
return NULL;
}
AchievementCriteriaEntryList const& GetTimedAchievementCriteriaByType(AchievementCriteriaTimedTypes type) const
{
return m_AchievementCriteriasByTimedType[type];
}
AchievementCriteriaEntryList const* GetAchievementCriteriaByAchievement(uint32 id) const
{
AchievementCriteriaListByAchievement::const_iterator itr = m_AchievementCriteriaListByAchievement.find(id);
return itr != m_AchievementCriteriaListByAchievement.end() ? &itr->second : NULL;
}
AchievementEntryList const* GetAchievementByReferencedId(uint32 id) const
{
AchievementListByReferencedId::const_iterator itr = m_AchievementListByReferencedId.find(id);
return itr != m_AchievementListByReferencedId.end() ? &itr->second : NULL;
}
AchievementReward const* GetAchievementReward(AchievementEntry const* achievement) const
{
AchievementRewards::const_iterator iter = m_achievementRewards.find(achievement->ID);
return iter != m_achievementRewards.end() ? &iter->second : NULL;
}
AchievementRewardLocale const* GetAchievementRewardLocale(AchievementEntry const* achievement) const
{
AchievementRewardLocales::const_iterator iter = m_achievementRewardLocales.find(achievement->ID);
return iter != m_achievementRewardLocales.end() ? &iter->second : NULL;
}
AchievementCriteriaDataSet const* GetCriteriaDataSet(AchievementCriteriaEntry const* achievementCriteria) const
{
AchievementCriteriaDataMap::const_iterator iter = m_criteriaDataMap.find(achievementCriteria->ID);
return iter != m_criteriaDataMap.end() ? &iter->second : NULL;
}
bool IsRealmCompleted(AchievementEntry const* achievement) const
{
return m_allCompletedAchievements.find(achievement->ID) != m_allCompletedAchievements.end();
}
void SetRealmCompleted(AchievementEntry const* achievement)
{
m_allCompletedAchievements.insert(achievement->ID);
}
void LoadAchievementCriteriaList();
void LoadAchievementCriteriaData();
void LoadAchievementReferenceList();
void LoadCompletedAchievements();
void LoadRewards();
void LoadRewardLocales();
private:
AchievementCriteriaDataMap m_criteriaDataMap;
// store achievement criterias by type to speed up lookup
AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
AchievementCriteriaEntryList m_AchievementCriteriasByTimedType[ACHIEVEMENT_TIMED_TYPE_MAX];
// store achievement criterias by achievement to speed up lookup
AchievementCriteriaListByAchievement m_AchievementCriteriaListByAchievement;
// store achievements by referenced achievement id to speed up lookup
AchievementListByReferencedId m_AchievementListByReferencedId;
typedef std::set<uint32> AllCompletedAchievements;
AllCompletedAchievements m_allCompletedAchievements;
AchievementRewards m_achievementRewards;
AchievementRewardLocales m_achievementRewardLocales;
// pussywizard:
std::map<uint32, AchievementCriteriaEntryList> m_SpecialList[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
std::map<uint32, AchievementCriteriaEntryList> m_AchievementCriteriasByCondition[ACHIEVEMENT_CRITERIA_CONDITION_TOTAL];
};
#define sAchievementMgr ACE_Singleton<AchievementGlobalMgr, ACE_Null_Mutex>::instance()
#endif

View File

@@ -1,96 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AddonMgr.h"
#include "DatabaseEnv.h"
#include "Log.h"
#include "Timer.h"
#include <list>
namespace AddonMgr
{
// Anonymous namespace ensures file scope of all the stuff inside it, even
// if you add something more to this namespace somewhere else.
namespace
{
// List of saved addons (in DB).
typedef std::list<SavedAddon> SavedAddonsList;
SavedAddonsList m_knownAddons;
}
void LoadFromDB()
{
uint32 oldMSTime = getMSTime();
QueryResult result = CharacterDatabase.Query("SELECT name, crc FROM addons");
if (!result)
{
sLog->outString(">> Loaded 0 known addons. DB table `addons` is empty!");
sLog->outString();
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
std::string name = fields[0].GetString();
uint32 crc = fields[1].GetUInt32();
m_knownAddons.push_back(SavedAddon(name, crc));
++count;
}
while (result->NextRow());
sLog->outString(">> Loaded %u known addons in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
sLog->outString();
}
void SaveAddon(AddonInfo const& addon)
{
std::string name = addon.Name;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ADDON);
stmt->setString(0, name);
stmt->setUInt32(1, addon.CRC);
CharacterDatabase.Execute(stmt);
m_knownAddons.push_back(SavedAddon(addon.Name, addon.CRC));
}
SavedAddon const* GetAddonInfo(const std::string& name)
{
for (SavedAddonsList::const_iterator it = m_knownAddons.begin(); it != m_knownAddons.end(); ++it)
{
SavedAddon const& addon = (*it);
if (addon.Name == name)
return &addon;
}
return NULL;
}
} // Namespace

View File

@@ -1,58 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ADDONMGR_H
#define _ADDONMGR_H
#include "Define.h"
#include <string>
struct AddonInfo
{
AddonInfo(const std::string& name, uint8 enabled, uint32 crc, uint8 state, bool crcOrPubKey)
: Name(name), Enabled(enabled), CRC(crc), State(state), UsePublicKeyOrCRC(crcOrPubKey) {}
std::string Name;
uint8 Enabled;
uint32 CRC;
uint8 State;
bool UsePublicKeyOrCRC;
};
struct SavedAddon
{
SavedAddon(const std::string& name, uint32 crc) : Name(name)
{
CRC = crc;
}
std::string Name;
uint32 CRC;
};
#define STANDARD_ADDON_CRC 0x4c1c776d
namespace AddonMgr
{
void LoadFromDB();
void SaveAddon(AddonInfo const& addon);
SavedAddon const* GetAddonInfo(const std::string& name);
}
#endif

View File

@@ -1,217 +0,0 @@
#ifndef AZEROTHCORE_ARENASPECTATOR_H
#define AZEROTHCORE_ARENASPECTATOR_H
#include "Player.h"
#include "World.h"
#include "Map.h"
#include "Battleground.h"
#include "Pet.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
#include "Chat.h"
#include "LFGMgr.h"
#define SPECTATOR_ADDON_VERSION 27
#define SPECTATOR_BUFFER_LEN 150
#define SPECTATOR_ADDON_PREFIX "ASSUN\x09"
#define SPECTATOR_COOLDOWN_MIN 20
#define SPECTATOR_COOLDOWN_MAX 900
#define SPECTATOR_SPELL_BINDSIGHT 6277
#define SPECTATOR_SPELL_SPEED 1557
namespace ArenaSpectator
{
template<class T> inline void SendCommand(T* o, const char* format, ...) ATTR_PRINTF(2, 3);
inline void CreatePacket(WorldPacket& data, const char* m);
inline void SendPacketTo(const Player* p, const char* m);
inline void SendPacketTo(const Map* map, const char* m);
inline void HandleResetCommand(Player* p);
inline bool ShouldSendAura(Aura* aura, uint8 effMask, uint64 targetGUID, bool remove);
template<class T> inline void SendCommand_String(T* p, uint64 targetGUID, const char* prefix, const std::string& c);
template<class T> inline void SendCommand_UInt32Value(T* o, uint64 targetGUID, const char* prefix, uint32 t);
template<class T> inline void SendCommand_GUID(T* o, uint64 targetGUID, const char* prefix, uint64 t);
template<class T> inline void SendCommand_Spell(T* o, uint64 targetGUID, const char* prefix, uint32 id, int32 casttime);
template<class T> inline void SendCommand_Cooldown(T* o, uint64 targetGUID, const char* prefix, uint32 id, uint32 dur, uint32 maxdur);
template<class T> inline void SendCommand_Aura(T* o, uint64 targetGUID, const char* prefix, uint64 caster, uint32 id, bool isDebuff, uint32 dispel, int32 dur, int32 maxdur, uint32 stack, bool remove);
bool HandleSpectatorSpectateCommand(ChatHandler* handler, char const* args);
bool HandleSpectatorWatchCommand(ChatHandler* handler, char const* args);
// definitions below:
template<class T>
void SendCommand(T* o, const char* format, ...)
{
if (!format)
return;
char buffer[SPECTATOR_BUFFER_LEN];
va_list ap;
va_start(ap, format);
vsnprintf(buffer, SPECTATOR_BUFFER_LEN, format, ap);
va_end(ap);
SendPacketTo(o, buffer);
}
void CreatePacket(WorldPacket& data, const char* m)
{
size_t len = strlen(m);
data.Initialize(SMSG_MESSAGECHAT, 1+4+8+4+8+4+1+len+1);
data << uint8(CHAT_MSG_WHISPER);
data << uint32(LANG_ADDON);
data << uint64(0);
data << uint32(0);
data << uint64(0);
data << uint32(len + 1);
data << m;
data << uint8(0);
}
void SendPacketTo(const Player* p, const char* m)
{
WorldPacket data;
CreatePacket(data, m);
p->GetSession()->SendPacket(&data);
}
void SendPacketTo(const Map* map, const char* m)
{
if (!map->IsBattleArena())
return;
Battleground* bg = ((BattlegroundMap*)map)->GetBG();
if (!bg || bg->GetStatus() != STATUS_IN_PROGRESS)
return;
WorldPacket data;
CreatePacket(data, m);
bg->SpectatorsSendPacket(data);
}
template<class T>
void SendCommand_String(T* o, uint64 targetGUID, const char* prefix, const char* c)
{
if (!IS_PLAYER_GUID(targetGUID))
return;
SendCommand(o, "%s0x%016llX;%s=%s;", SPECTATOR_ADDON_PREFIX, targetGUID, prefix, c);
}
template<class T>
void SendCommand_UInt32Value(T* o, uint64 targetGUID, const char* prefix, uint32 t)
{
if (!IS_PLAYER_GUID(targetGUID))
return;
SendCommand(o, "%s0x%016llX;%s=%u;", SPECTATOR_ADDON_PREFIX, targetGUID, prefix, t);
}
template<class T>
void SendCommand_GUID(T* o, uint64 targetGUID, const char* prefix, uint64 t)
{
if (!IS_PLAYER_GUID(targetGUID))
return;
SendCommand(o, "%s0x%016llX;%s=0x%016llX;", SPECTATOR_ADDON_PREFIX, targetGUID, prefix, t);
}
template<class T>
void SendCommand_Spell(T* o, uint64 targetGUID, const char* prefix, uint32 id, int32 casttime)
{
if (!IS_PLAYER_GUID(targetGUID))
return;
SendCommand(o, "%s0x%016llX;%s=%u,%i;", SPECTATOR_ADDON_PREFIX, targetGUID, prefix, id, casttime);
}
template<class T>
void SendCommand_Cooldown(T* o, uint64 targetGUID, const char* prefix, uint32 id, uint32 dur, uint32 maxdur)
{
if (!IS_PLAYER_GUID(targetGUID))
return;
if (const SpellInfo* si = sSpellMgr->GetSpellInfo(id))
if (si->SpellIconID == 1)
return;
SendCommand(o, "%s0x%016llX;%s=%u,%u,%u;", SPECTATOR_ADDON_PREFIX, targetGUID, prefix, id, dur, maxdur);
}
template<class T>
void SendCommand_Aura(T* o, uint64 targetGUID, const char* prefix, uint64 caster, uint32 id, bool isDebuff, uint32 dispel, int32 dur, int32 maxdur, uint32 stack, bool remove)
{
if (!IS_PLAYER_GUID(targetGUID))
return;
SendCommand(o, "%s0x%016llX;%s=%u,%u,%i,%i,%u,%u,%u,0x%016llX;", SPECTATOR_ADDON_PREFIX, targetGUID, prefix, remove ? 1 : 0, stack, dur, maxdur, id, dispel, isDebuff ? 1 : 0, caster);
}
void HandleResetCommand(Player* p)
{
if (!p->FindMap() || !p->IsInWorld() || !p->FindMap()->IsBattleArena())
return;
Battleground* bg = ((BattlegroundMap*)p->FindMap())->GetBG();
if (!bg || bg->GetStatus() != STATUS_IN_PROGRESS)
return;
Battleground::BattlegroundPlayerMap const& pl = bg->GetPlayers();
for (Battleground::BattlegroundPlayerMap::const_iterator itr = pl.begin(); itr != pl.end(); ++itr)
{
if (p->HasReceivedSpectatorResetFor(GUID_LOPART(itr->first)))
continue;
Player* plr = itr->second;
p->AddReceivedSpectatorResetFor(GUID_LOPART(itr->first));
SendCommand_String(p, itr->first, "NME", plr->GetName().c_str());
// Xinef: addon compatibility
SendCommand_UInt32Value(p, itr->first, "TEM", plr->GetBgTeamId() == TEAM_ALLIANCE ? ALLIANCE : HORDE);
SendCommand_UInt32Value(p, itr->first, "CLA", plr->getClass());
SendCommand_UInt32Value(p, itr->first, "MHP", plr->GetMaxHealth());
SendCommand_UInt32Value(p, itr->first, "CHP", plr->GetHealth());
SendCommand_UInt32Value(p, itr->first, "STA", plr->IsAlive() ? 1 : 0);
Powers ptype = plr->getPowerType();
SendCommand_UInt32Value(p, itr->first, "PWT", ptype);
SendCommand_UInt32Value(p, itr->first, "MPW", ptype == POWER_RAGE || ptype == POWER_RUNIC_POWER ? plr->GetMaxPower(ptype)/10 : plr->GetMaxPower(ptype));
SendCommand_UInt32Value(p, itr->first, "CPW", ptype == POWER_RAGE || ptype == POWER_RUNIC_POWER ? plr->GetPower(ptype)/10 : plr->GetPower(ptype));
Pet* pet = plr->GetPet();
SendCommand_UInt32Value(p, itr->first, "PHP", pet && pet->GetCreatureTemplate()->family ? (uint32)pet->GetHealthPct() : 0);
SendCommand_UInt32Value(p, itr->first, "PET", pet ? pet->GetCreatureTemplate()->family : 0);
SendCommand_GUID(p, itr->first, "TRG", plr->GetTarget());
SendCommand_UInt32Value(p, itr->first, "RES", 1);
SendCommand_UInt32Value(p, itr->first, "CDC", 1);
SendCommand_UInt32Value(p, itr->first, "TIM", (bg->GetStartTime() < 46*MINUTE*IN_MILLISECONDS) ? (46*MINUTE*IN_MILLISECONDS-bg->GetStartTime())/IN_MILLISECONDS : 0);
// "SPE" not here (only possible to send starting a new cast)
// send all "CD"
SpellCooldowns const& sc = plr->GetSpellCooldownMap();
for (SpellCooldowns::const_iterator itrc = sc.begin(); itrc != sc.end(); ++itrc)
if (itrc->second.sendToSpectator && itrc->second.maxduration >= SPECTATOR_COOLDOWN_MIN*IN_MILLISECONDS && itrc->second.maxduration <= SPECTATOR_COOLDOWN_MAX*IN_MILLISECONDS)
if (uint32 cd = (getMSTimeDiff(World::GetGameTimeMS(), itrc->second.end)/1000))
SendCommand_Cooldown(p, itr->first, "ACD", itrc->first, cd, itrc->second.maxduration/1000);
// send all visible "AUR"
Unit::VisibleAuraMap const *visibleAuras = plr->GetVisibleAuras();
for (Unit::VisibleAuraMap::const_iterator aitr = visibleAuras->begin(); aitr != visibleAuras->end(); ++aitr)
{
Aura *aura = aitr->second->GetBase();
if (ShouldSendAura(aura, aitr->second->GetEffectMask(), plr->GetGUID(), false))
SendCommand_Aura(p, itr->first, "AUR", aura->GetCasterGUID(), aura->GetSpellInfo()->Id, aura->GetSpellInfo()->IsPositive(), aura->GetSpellInfo()->Dispel, aura->GetDuration(), aura->GetMaxDuration(), (aura->GetCharges() > 1 ? aura->GetCharges() : aura->GetStackAmount()), false);
}
}
}
bool ShouldSendAura(Aura* aura, uint8 effMask, uint64 targetGUID, bool remove)
{
if (aura->GetSpellInfo()->SpellIconID == 1 || aura->GetSpellInfo()->HasAttribute(SPELL_ATTR1_DONT_DISPLAY_IN_AURA_BAR))
return false;
if (remove || aura->GetSpellInfo()->HasAttribute(SPELL_ATTR0_CU_AURA_CC) || aura->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_GENERIC)
return true;
for(uint8 i=EFFECT_0; i<MAX_SPELL_EFFECTS; ++i)
{
if (effMask & (1<<i))
{
AuraType at = aura->GetEffect(i)->GetAuraType();
if (aura->GetEffect(i)->GetAmount() && (aura->GetSpellInfo()->IsPositive() || targetGUID != aura->GetCasterGUID()) ||
at == SPELL_AURA_MECHANIC_IMMUNITY || at == SPELL_AURA_EFFECT_IMMUNITY || at == SPELL_AURA_STATE_IMMUNITY || at == SPELL_AURA_SCHOOL_IMMUNITY || at == SPELL_AURA_DISPEL_IMMUNITY)
return true;
}
}
return false;
}
}
#endif

View File

@@ -1,823 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Common.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "DatabaseEnv.h"
#include "DBCStores.h"
#include "ScriptMgr.h"
#include "AccountMgr.h"
#include "AuctionHouseMgr.h"
#include "Item.h"
#include "Language.h"
#include "Logging/Log.h"
#include <vector>
#include "AvgDiffTracker.h"
#include "AsyncAuctionListing.h"
enum eAuctionHouse
{
AH_MINIMUM_DEPOSIT = 100,
};
AuctionHouseMgr::AuctionHouseMgr()
{
}
AuctionHouseMgr::~AuctionHouseMgr()
{
for (ItemMap::iterator itr = mAitems.begin(); itr != mAitems.end(); ++itr)
delete itr->second;
}
AuctionHouseObject* AuctionHouseMgr::GetAuctionsMap(uint32 factionTemplateId)
{
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION))
return &mNeutralAuctions;
// team have linked auction houses
FactionTemplateEntry const* u_entry = sFactionTemplateStore.LookupEntry(factionTemplateId);
if (!u_entry)
return &mNeutralAuctions;
else if (u_entry->ourMask & FACTION_MASK_ALLIANCE)
return &mAllianceAuctions;
else if (u_entry->ourMask & FACTION_MASK_HORDE)
return &mHordeAuctions;
else
return &mNeutralAuctions;
}
uint32 AuctionHouseMgr::GetAuctionDeposit(AuctionHouseEntry const* entry, uint32 time, Item* pItem, uint32 count)
{
uint32 MSV = pItem->GetTemplate()->SellPrice;
if (MSV <= 0)
return AH_MINIMUM_DEPOSIT;
float multiplier = CalculatePct(float(entry->depositPercent), 3);
uint32 timeHr = (((time / 60) / 60) / 12);
uint32 deposit = uint32(((multiplier * MSV * count / 3) * timeHr * 3) * sWorld->getRate(RATE_AUCTION_DEPOSIT));
;//sLog->outDebug(LOG_FILTER_AUCTIONHOUSE, "MSV: %u", MSV);
;//sLog->outDebug(LOG_FILTER_AUCTIONHOUSE, "Items: %u", count);
;//sLog->outDebug(LOG_FILTER_AUCTIONHOUSE, "Multiplier: %f", multiplier);
;//sLog->outDebug(LOG_FILTER_AUCTIONHOUSE, "Deposit: %u", deposit);
if (deposit < AH_MINIMUM_DEPOSIT)
return AH_MINIMUM_DEPOSIT;
else
return deposit;
}
//does not clear ram
void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction& trans)
{
Item* pItem = GetAItem(auction->item_guidlow);
if (!pItem)
return;
uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER);
uint32 bidder_accId = 0;
Player* bidder = ObjectAccessor::FindPlayerInOrOutOfWorld(bidder_guid);
if (bidder)
bidder_accId = bidder->GetSession()->GetAccountId();
else
bidder_accId = sObjectMgr->GetPlayerAccountIdByGUID(bidder_guid);
// receiver exist
if (bidder || bidder_accId)
{
// set owner to bidder (to prevent delete item with sender char deleting)
// owner in `data` will set at mail receive and item extracting
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ITEM_OWNER);
stmt->setUInt32(0, auction->bidder);
stmt->setUInt32(1, pItem->GetGUIDLow());
trans->Append(stmt);
if (bidder)
{
bidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, bidder_guid, 0, 0, auction->item_template);
// FIXME: for offline player need also
bidder->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS, 1);
}
MailDraft(auction->BuildAuctionMailSubject(AUCTION_WON), AuctionEntry::BuildAuctionMailBody(auction->owner, auction->bid, auction->buyout, 0, 0))
.AddItem(pItem)
.SendMailTo(trans, MailReceiver(bidder, auction->bidder), auction, MAIL_CHECK_MASK_COPIED);
}
else
sAuctionMgr->RemoveAItem(auction->item_guidlow, true);
}
void AuctionHouseMgr::SendAuctionSalePendingMail(AuctionEntry* auction, SQLTransaction& trans)
{
uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER);
Player* owner = ObjectAccessor::FindPlayerInOrOutOfWorld(owner_guid);
uint32 owner_accId = sObjectMgr->GetPlayerAccountIdByGUID(owner_guid);
// owner exist (online or offline)
if (owner || owner_accId)
MailDraft(auction->BuildAuctionMailSubject(AUCTION_SALE_PENDING), AuctionEntry::BuildAuctionMailBody(auction->bidder, auction->bid, auction->buyout, auction->deposit, auction->GetAuctionCut()))
.SendMailTo(trans, MailReceiver(owner, auction->owner), auction, MAIL_CHECK_MASK_COPIED);
}
//call this method to send mail to auction owner, when auction is successful, it does not clear ram
void AuctionHouseMgr::SendAuctionSuccessfulMail(AuctionEntry* auction, SQLTransaction& trans)
{
uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER);
Player* owner = ObjectAccessor::FindPlayerInOrOutOfWorld(owner_guid);
uint32 owner_accId = sObjectMgr->GetPlayerAccountIdByGUID(owner_guid);
// owner exist
if (owner || owner_accId)
{
uint32 profit = auction->bid + auction->deposit - auction->GetAuctionCut();
if (owner)
{
owner->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS, profit);
owner->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD, auction->bid);
owner->GetSession()->SendAuctionOwnerNotification(auction);
}
MailDraft(auction->BuildAuctionMailSubject(AUCTION_SUCCESSFUL), AuctionEntry::BuildAuctionMailBody(auction->bidder, auction->bid, auction->buyout, auction->deposit, auction->GetAuctionCut()))
.AddMoney(profit)
.SendMailTo(trans, MailReceiver(owner, auction->owner), auction, MAIL_CHECK_MASK_COPIED, sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY));
if (auction->bid >= 500*GOLD)
if (const GlobalPlayerData* gpd = sWorld->GetGlobalPlayerData(auction->bidder))
{
uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER);
Player* bidder = ObjectAccessor::FindPlayerInOrOutOfWorld(bidder_guid);
std::string owner_name = "";
uint8 owner_level = 0;
if (const GlobalPlayerData* gpd_owner = sWorld->GetGlobalPlayerData(auction->owner))
{
owner_name = gpd_owner->name;
owner_level = gpd_owner->level;
}
CharacterDatabase.PExecute("INSERT INTO log_money VALUES(%u, %u, \"%s\", \"%s\", %u, \"%s\", %u, \"<AH> profit: %ug, bidder: %s %u lvl (guid: %u), seller: %s %u lvl (guid: %u), item %u (%u)\", NOW())", gpd->accountId, auction->bidder, gpd->name.c_str(), bidder ? bidder->GetSession()->GetRemoteAddress().c_str() : "", owner_accId, owner_name.c_str(), auction->bid, (profit/GOLD), gpd->name.c_str(), gpd->level, auction->bidder, owner_name.c_str(), owner_level, auction->owner, auction->item_template, auction->itemCount);
}
}
}
//does not clear ram
void AuctionHouseMgr::SendAuctionExpiredMail(AuctionEntry* auction, SQLTransaction& trans)
{
//return an item in auction to its owner by mail
Item* pItem = GetAItem(auction->item_guidlow);
if (!pItem)
return;
uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER);
Player* owner = ObjectAccessor::FindPlayerInOrOutOfWorld(owner_guid);
uint32 owner_accId = sObjectMgr->GetPlayerAccountIdByGUID(owner_guid);
// owner exist
if (owner || owner_accId)
{
if (owner)
owner->GetSession()->SendAuctionOwnerNotification(auction);
MailDraft(auction->BuildAuctionMailSubject(AUCTION_EXPIRED), AuctionEntry::BuildAuctionMailBody(0, 0, auction->buyout, auction->deposit, 0))
.AddItem(pItem)
.SendMailTo(trans, MailReceiver(owner, auction->owner), auction, MAIL_CHECK_MASK_COPIED, 0);
}
else
sAuctionMgr->RemoveAItem(auction->item_guidlow, true);
}
//this function sends mail to old bidder
void AuctionHouseMgr::SendAuctionOutbiddedMail(AuctionEntry* auction, uint32 newPrice, Player* newBidder, SQLTransaction& trans)
{
uint64 oldBidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER);
Player* oldBidder = ObjectAccessor::FindPlayerInOrOutOfWorld(oldBidder_guid);
uint32 oldBidder_accId = 0;
if (!oldBidder)
oldBidder_accId = sObjectMgr->GetPlayerAccountIdByGUID(oldBidder_guid);
// old bidder exist
if (oldBidder || oldBidder_accId)
{
if (oldBidder && newBidder)
oldBidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, newBidder->GetGUID(), newPrice, auction->GetAuctionOutBid(), auction->item_template);
MailDraft(auction->BuildAuctionMailSubject(AUCTION_OUTBIDDED), AuctionEntry::BuildAuctionMailBody(auction->owner, auction->bid, auction->buyout, auction->deposit, auction->GetAuctionCut()))
.AddMoney(auction->bid)
.SendMailTo(trans, MailReceiver(oldBidder, auction->bidder), auction, MAIL_CHECK_MASK_COPIED);
}
}
//this function sends mail, when auction is cancelled to old bidder
void AuctionHouseMgr::SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans)
{
uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER);
Player* bidder = ObjectAccessor::FindPlayerInOrOutOfWorld(bidder_guid);
uint32 bidder_accId = 0;
if (!bidder)
bidder_accId = sObjectMgr->GetPlayerAccountIdByGUID(bidder_guid);
// bidder exist
if (bidder || bidder_accId)
MailDraft(auction->BuildAuctionMailSubject(AUCTION_CANCELLED_TO_BIDDER), AuctionEntry::BuildAuctionMailBody(auction->owner, auction->bid, auction->buyout, auction->deposit, 0))
.AddMoney(auction->bid)
.SendMailTo(trans, MailReceiver(bidder, auction->bidder), auction, MAIL_CHECK_MASK_COPIED);
}
void AuctionHouseMgr::LoadAuctionItems()
{
uint32 oldMSTime = getMSTime();
// need to clear in case we are reloading
if (!mAitems.empty())
{
for (ItemMap::iterator itr = mAitems.begin(); itr != mAitems.end(); ++itr)
delete itr->second;
mAitems.clear();
}
// data needs to be at first place for Item::LoadFromDB
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_AUCTION_ITEMS);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (!result)
{
sLog->outString(">> Loaded 0 auction items. DB table `auctionhouse` or `item_instance` is empty!");
sLog->outString();
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
uint32 item_guid = fields[11].GetUInt32();
uint32 item_template = fields[12].GetUInt32();
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item_template);
if (!proto)
{
sLog->outError("AuctionHouseMgr::LoadAuctionItems: Unknown item (GUID: %u id: #%u) in auction, skipped.", item_guid, item_template);
continue;
}
Item* item = NewItemOrBag(proto);
if (!item->LoadFromDB(item_guid, 0, fields, item_template))
{
delete item;
continue;
}
AddAItem(item);
++count;
}
while (result->NextRow());
sLog->outString(">> Loaded %u auction items in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
sLog->outString();
}
void AuctionHouseMgr::LoadAuctions()
{
uint32 oldMSTime = getMSTime();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_AUCTIONS);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (!result)
{
sLog->outString(">> Loaded 0 auctions. DB table `auctionhouse` is empty.");
sLog->outString();
return;
}
uint32 count = 0;
SQLTransaction trans = CharacterDatabase.BeginTransaction();
do
{
Field* fields = result->Fetch();
AuctionEntry* aItem = new AuctionEntry();
if (!aItem->LoadFromDB(fields))
{
aItem->DeleteFromDB(trans);
delete aItem;
continue;
}
GetAuctionsMap(aItem->factionTemplateId)->AddAuction(aItem);
count++;
} while (result->NextRow());
CharacterDatabase.CommitTransaction(trans);
sLog->outString(">> Loaded %u auctions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
sLog->outString();
}
void AuctionHouseMgr::AddAItem(Item* it)
{
ASSERT(it);
ASSERT(mAitems.find(it->GetGUIDLow()) == mAitems.end());
mAitems[it->GetGUIDLow()] = it;
}
bool AuctionHouseMgr::RemoveAItem(uint32 id, bool deleteFromDB)
{
ItemMap::iterator i = mAitems.find(id);
if (i == mAitems.end())
return false;
if (deleteFromDB)
{
SQLTransaction trans = CharacterDatabase.BeginTransaction();
i->second->FSetState(ITEM_REMOVED);
i->second->SaveToDB(trans);
CharacterDatabase.CommitTransaction(trans);
}
mAitems.erase(i);
return true;
}
void AuctionHouseMgr::Update()
{
mHordeAuctions.Update();
mAllianceAuctions.Update();
mNeutralAuctions.Update();
}
AuctionHouseEntry const* AuctionHouseMgr::GetAuctionHouseEntry(uint32 factionTemplateId)
{
uint32 houseid = 7; // goblin auction house
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION))
{
//FIXME: found way for proper auctionhouse selection by another way
// AuctionHouse.dbc have faction field with _player_ factions associated with auction house races.
// but no easy way convert creature faction to player race faction for specific city
switch (factionTemplateId)
{
case 12: houseid = 1; break; // human
case 29: houseid = 6; break; // orc, and generic for horde
case 55: houseid = 2; break; // dwarf, and generic for alliance
case 68: houseid = 4; break; // undead
case 80: houseid = 3; break; // n-elf
case 104: houseid = 5; break; // trolls
case 120: houseid = 7; break; // booty bay, neutral
case 474: houseid = 7; break; // gadgetzan, neutral
case 855: houseid = 7; break; // everlook, neutral
case 1604: houseid = 6; break; // b-elfs,
default: // for unknown case
{
FactionTemplateEntry const* u_entry = sFactionTemplateStore.LookupEntry(factionTemplateId);
if (!u_entry)
houseid = 7; // goblin auction house
else if (u_entry->ourMask & FACTION_MASK_ALLIANCE)
houseid = 1; // human auction house
else if (u_entry->ourMask & FACTION_MASK_HORDE)
houseid = 6; // orc auction house
else
houseid = 7; // goblin auction house
break;
}
}
}
return sAuctionHouseStore.LookupEntry(houseid);
}
void AuctionHouseObject::AddAuction(AuctionEntry* auction)
{
ASSERT(auction);
AuctionsMap[auction->Id] = auction;
sScriptMgr->OnAuctionAdd(this, auction);
}
bool AuctionHouseObject::RemoveAuction(AuctionEntry* auction)
{
bool wasInMap = AuctionsMap.erase(auction->Id) ? true : false;
sScriptMgr->OnAuctionRemove(this, auction);
// we need to delete the entry, it is not referenced any more
delete auction;
auction = NULL;
return wasInMap;
}
void AuctionHouseObject::Update()
{
time_t checkTime = sWorld->GetGameTime() + 60;
///- Handle expired auctions
// If storage is empty, no need to update. next == NULL in this case.
if (AuctionsMap.empty())
return;
SQLTransaction trans = CharacterDatabase.BeginTransaction();
for (AuctionEntryMap::iterator itr, iter = AuctionsMap.begin(); iter != AuctionsMap.end(); )
{
itr = iter++;
AuctionEntry* auction = (*itr).second;
if (auction->expire_time > checkTime)
continue;
///- Either cancel the auction if there was no bidder
if (auction->bidder == 0)
{
sAuctionMgr->SendAuctionExpiredMail(auction, trans);
sScriptMgr->OnAuctionExpire(this, auction);
}
///- Or perform the transaction
else
{
//we should send an "item sold" message if the seller is online
//we send the item to the winner
//we send the money to the seller
sAuctionMgr->SendAuctionSuccessfulMail(auction, trans);
sAuctionMgr->SendAuctionWonMail(auction, trans);
sScriptMgr->OnAuctionSuccessful(this, auction);
}
///- In any case clear the auction
auction->DeleteFromDB(trans);
sAuctionMgr->RemoveAItem(auction->item_guidlow);
RemoveAuction(auction);
}
CharacterDatabase.CommitTransaction(trans);
}
void AuctionHouseObject::BuildListBidderItems(WorldPacket& data, Player* player, uint32& count, uint32& totalcount)
{
for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr)
{
AuctionEntry* Aentry = itr->second;
if (Aentry && Aentry->bidder == player->GetGUIDLow())
{
if (itr->second->BuildAuctionInfo(data))
++count;
++totalcount;
}
}
}
void AuctionHouseObject::BuildListOwnerItems(WorldPacket& data, Player* player, uint32& count, uint32& totalcount)
{
for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr)
{
AuctionEntry* Aentry = itr->second;
if (Aentry && Aentry->owner == player->GetGUIDLow())
{
if (Aentry->BuildAuctionInfo(data))
++count;
++totalcount;
}
}
}
bool AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player,
std::wstring const& wsearchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
uint32& count, uint32& totalcount, uint8 getAll)
{
uint32 itrcounter = 0;
// pussywizard: optimization, this is a simplified case
if (itemClass == 0xffffffff && itemSubClass == 0xffffffff && inventoryType == 0xffffffff && quality == 0xffffffff && levelmin == 0x00 && levelmax == 0x00 && usable == 0x00 && wsearchedname.empty())
{
totalcount = Getcount();
if (listfrom < totalcount)
{
AuctionEntryMap::iterator itr = AuctionsMap.begin();
std::advance(itr, listfrom);
for (; itr != AuctionsMap.end(); ++itr)
{
itr->second->BuildAuctionInfo(data);
if ((++count) >= 50)
break;
}
}
return true;
}
time_t curTime = sWorld->GetGameTime();
for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr)
{
if (AsyncAuctionListingMgr::IsAuctionListingAllowed() == false) // pussywizard: World::Update is waiting for us...
if ((itrcounter++) % 100 == 0) // check condition every 100 iterations
if (avgDiffTracker.getAverage() >= 30 || getMSTimeDiff(World::GetGameTimeMS(), getMSTime()) >= 10) // pussywizard: stop immediately if diff is high or waiting too long
return false;
AuctionEntry* Aentry = itr->second;
// Skip expired auctions
if (Aentry->expire_time < curTime)
continue;
Item* item = sAuctionMgr->GetAItem(Aentry->item_guidlow);
if (!item)
continue;
ItemTemplate const* proto = item->GetTemplate();
if (itemClass != 0xffffffff && proto->Class != itemClass)
continue;
if (itemSubClass != 0xffffffff && proto->SubClass != itemSubClass)
continue;
if (inventoryType != 0xffffffff && proto->InventoryType != inventoryType)
{
// xinef: exception, robes are counted as chests
if (inventoryType != INVTYPE_CHEST || proto->InventoryType != INVTYPE_ROBE)
continue;
}
if (quality != 0xffffffff && proto->Quality != quality)
continue;
if (levelmin != 0x00 && (proto->RequiredLevel < levelmin || (levelmax != 0x00 && proto->RequiredLevel > levelmax)))
continue;
if (usable != 0x00)
{
if (player->CanUseItem(item) != EQUIP_ERR_OK)
continue;
// xinef: check already learded recipes and pets
if (proto->Spells[1].SpellTrigger == ITEM_SPELLTRIGGER_LEARN_SPELL_ID && player->HasSpell(proto->Spells[1].SpellId))
continue;
}
// Allow search by suffix (ie: of the Monkey) or partial name (ie: Monkey)
// No need to do any of this if no search term was entered
if (!wsearchedname.empty())
{
std::string name = proto->Name1;
if (name.empty())
continue;
// DO NOT use GetItemEnchantMod(proto->RandomProperty) as it may return a result
// that matches the search but it may not equal item->GetItemRandomPropertyId()
// used in BuildAuctionInfo() which then causes wrong items to be listed
int32 propRefID = item->GetItemRandomPropertyId();
if (propRefID)
{
// Append the suffix to the name (ie: of the Monkey) if one exists
// These are found in ItemRandomSuffix.dbc and ItemRandomProperties.dbc
// even though the DBC name seems misleading
char* const* suffix = NULL;
if (propRefID < 0)
{
const ItemRandomSuffixEntry* itemRandEntry = sItemRandomSuffixStore.LookupEntry(-item->GetItemRandomPropertyId());
if (itemRandEntry)
suffix = itemRandEntry->nameSuffix;
}
else
{
const ItemRandomPropertiesEntry* itemRandEntry = sItemRandomPropertiesStore.LookupEntry(item->GetItemRandomPropertyId());
if (itemRandEntry)
suffix = itemRandEntry->nameSuffix;
}
// dbc local name
if (suffix)
{
// Append the suffix (ie: of the Monkey) to the name using localization
// or default enUS if localization is invalid
name += ' ';
name += suffix[LOCALE_enUS];
}
}
// Perform the search (with or without suffix)
if (!Utf8FitTo(name, wsearchedname))
continue;
}
// Add the item if no search term or if entered search term was found
if (count < 50 && totalcount >= listfrom)
{
++count;
Aentry->BuildAuctionInfo(data);
}
++totalcount;
}
return true;
}
//this function inserts to WorldPacket auction's data
bool AuctionEntry::BuildAuctionInfo(WorldPacket& data) const
{
Item* item = sAuctionMgr->GetAItem(item_guidlow);
if (!item)
{
sLog->outError("AuctionEntry::BuildAuctionInfo: Auction %u has a non-existent item: %u", Id, item_guidlow);
return false;
}
data << uint32(Id);
data << uint32(item->GetEntry());
for (uint8 i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; ++i)
{
data << uint32(item->GetEnchantmentId(EnchantmentSlot(i)));
data << uint32(item->GetEnchantmentDuration(EnchantmentSlot(i)));
data << uint32(item->GetEnchantmentCharges(EnchantmentSlot(i)));
}
data << int32(item->GetItemRandomPropertyId()); // Random item property id
data << uint32(item->GetItemSuffixFactor()); // SuffixFactor
data << uint32(item->GetCount()); // item->count
data << uint32(item->GetSpellCharges()); // item->charge FFFFFFF
data << uint32(0); // Unknown
data << uint64(owner); // Auction->owner
data << uint32(startbid); // Auction->startbid (not sure if useful)
data << uint32(bid ? GetAuctionOutBid() : 0);
// Minimal outbid
data << uint32(buyout); // Auction->buyout
data << uint32((expire_time - time(NULL)) * IN_MILLISECONDS); // time left
data << uint64(bidder); // auction->bidder current
data << uint32(bid); // current bid
return true;
}
uint32 AuctionEntry::GetAuctionCut() const
{
int32 cut = int32(CalculatePct(bid, auctionHouseEntry->cutPercent) * sWorld->getRate(RATE_AUCTION_CUT));
return std::max(cut, 0);
}
/// the sum of outbid is (1% from current bid)*5, if bid is very small, it is 1c
uint32 AuctionEntry::GetAuctionOutBid() const
{
uint32 outbid = CalculatePct(bid, 5);
return outbid ? outbid : 1;
}
void AuctionEntry::DeleteFromDB(SQLTransaction& trans) const
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_AUCTION);
stmt->setUInt32(0, Id);
trans->Append(stmt);
}
void AuctionEntry::SaveToDB(SQLTransaction& trans) const
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_AUCTION);
stmt->setUInt32(0, Id);
stmt->setUInt32(1, auctioneer);
stmt->setUInt32(2, item_guidlow);
stmt->setUInt32(3, owner);
stmt->setUInt32 (4, buyout);
stmt->setUInt32(5, uint32(expire_time));
stmt->setUInt32(6, bidder);
stmt->setUInt32 (7, bid);
stmt->setUInt32 (8, startbid);
stmt->setUInt32 (9, deposit);
trans->Append(stmt);
}
bool AuctionEntry::LoadFromDB(Field* fields)
{
Id = fields[0].GetUInt32();
auctioneer = fields[1].GetUInt32();
item_guidlow = fields[2].GetUInt32();
item_template = fields[3].GetUInt32();
itemCount = fields[4].GetUInt32();
owner = fields[5].GetUInt32();
buyout = fields[6].GetUInt32();
expire_time = fields[7].GetUInt32();
bidder = fields[8].GetUInt32();
bid = fields[9].GetUInt32();
startbid = fields[10].GetUInt32();
deposit = fields[11].GetUInt32();
CreatureData const* auctioneerData = sObjectMgr->GetCreatureData(auctioneer);
if (!auctioneerData)
{
sLog->outError("Auction %u has not a existing auctioneer (GUID : %u)", Id, auctioneer);
return false;
}
CreatureTemplate const* auctioneerInfo = sObjectMgr->GetCreatureTemplate(auctioneerData->id);
if (!auctioneerInfo)
{
sLog->outError("Auction %u has not a existing auctioneer (GUID : %u Entry: %u)", Id, auctioneer, auctioneerData->id);
return false;
}
factionTemplateId = auctioneerInfo->faction;
auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(factionTemplateId);
if (!auctionHouseEntry)
{
sLog->outError("Auction %u has auctioneer (GUID : %u Entry: %u) with wrong faction %u", Id, auctioneer, auctioneerData->id, factionTemplateId);
return false;
}
// check if sold item exists for guid
// and item_template in fact (GetAItem will fail if problematic in result check in AuctionHouseMgr::LoadAuctionItems)
if (!sAuctionMgr->GetAItem(item_guidlow))
{
sLog->outError("Auction %u has not a existing item : %u", Id, item_guidlow);
return false;
}
return true;
}
bool AuctionEntry::LoadFromFieldList(Field* fields)
{
// Loads an AuctionEntry item from a field list. Unlike "LoadFromDB()", this one
// does not require the AuctionEntryMap to have been loaded with items. It simply
// acts as a wrapper to fill out an AuctionEntry struct from a field list
Id = fields[0].GetUInt32();
auctioneer = fields[1].GetUInt32();
item_guidlow = fields[2].GetUInt32();
item_template = fields[3].GetUInt32();
itemCount = fields[4].GetUInt32();
owner = fields[5].GetUInt32();
buyout = fields[6].GetUInt32();
expire_time = fields[7].GetUInt32();
bidder = fields[8].GetUInt32();
bid = fields[9].GetUInt32();
startbid = fields[10].GetUInt32();
deposit = fields[11].GetUInt32();
CreatureData const* auctioneerData = sObjectMgr->GetCreatureData(auctioneer);
if (!auctioneerData)
{
sLog->outError("AuctionEntry::LoadFromFieldList() - Auction %u has not a existing auctioneer (GUID : %u)", Id, auctioneer);
return false;
}
CreatureTemplate const* auctioneerInfo = sObjectMgr->GetCreatureTemplate(auctioneerData->id);
if (!auctioneerInfo)
{
sLog->outError("AuctionEntry::LoadFromFieldList() - Auction %u has not a existing auctioneer (GUID : %u Entry: %u)", Id, auctioneer, auctioneerData->id);
return false;
}
factionTemplateId = auctioneerInfo->faction;
auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(factionTemplateId);
if (!auctionHouseEntry)
{
sLog->outError("AuctionEntry::LoadFromFieldList() - Auction %u has auctioneer (GUID : %u Entry: %u) with wrong faction %u", Id, auctioneer, auctioneerData->id, factionTemplateId);
return false;
}
return true;
}
std::string AuctionEntry::BuildAuctionMailSubject(MailAuctionAnswers response) const
{
std::ostringstream strm;
strm << item_template << ":0:" << response << ':' << Id << ':' << itemCount;
return strm.str();
}
std::string AuctionEntry::BuildAuctionMailBody(uint32 lowGuid, uint32 bid, uint32 buyout, uint32 deposit, uint32 cut)
{
std::ostringstream strm;
strm.width(16);
strm << std::right << std::hex << MAKE_NEW_GUID(lowGuid, 0, HIGHGUID_PLAYER); // HIGHGUID_PLAYER always present, even for empty guids
strm << std::dec << ':' << bid << ':' << buyout;
strm << ':' << deposit << ':' << cut;
return strm.str();
}

View File

@@ -1,201 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _AUCTION_HOUSE_MGR_H
#define _AUCTION_HOUSE_MGR_H
#include <ace/Singleton.h>
#include "Common.h"
#include "DatabaseEnv.h"
#include "DBCStructure.h"
#include "EventProcessor.h"
#include "WorldPacket.h"
class Item;
class Player;
#define MIN_AUCTION_TIME (12*HOUR)
#define MAX_AUCTION_ITEMS 160
enum AuctionError
{
ERR_AUCTION_OK = 0,
ERR_AUCTION_INVENTORY = 1,
ERR_AUCTION_DATABASE_ERROR = 2,
ERR_AUCTION_NOT_ENOUGHT_MONEY = 3,
ERR_AUCTION_ITEM_NOT_FOUND = 4,
ERR_AUCTION_HIGHER_BID = 5,
ERR_AUCTION_BID_INCREMENT = 7,
ERR_AUCTION_BID_OWN = 10,
ERR_AUCTION_RESTRICTED_ACCOUNT = 13
};
enum AuctionAction
{
AUCTION_SELL_ITEM = 0,
AUCTION_CANCEL = 1,
AUCTION_PLACE_BID = 2
};
enum MailAuctionAnswers
{
AUCTION_OUTBIDDED = 0,
AUCTION_WON = 1,
AUCTION_SUCCESSFUL = 2,
AUCTION_EXPIRED = 3,
AUCTION_CANCELLED_TO_BIDDER = 4,
AUCTION_CANCELED = 5,
AUCTION_SALE_PENDING = 6
};
struct AuctionEntry
{
uint32 Id;
uint32 auctioneer; // creature low guid
uint32 item_guidlow;
uint32 item_template;
uint32 itemCount;
uint32 owner;
uint32 startbid; //maybe useless
uint32 bid;
uint32 buyout;
time_t expire_time;
uint32 bidder;
uint32 deposit; //deposit can be calculated only when creating auction
AuctionHouseEntry const* auctionHouseEntry; // in AuctionHouse.dbc
uint32 factionTemplateId;
// helpers
uint32 GetHouseId() const { return auctionHouseEntry->houseId; }
uint32 GetHouseFaction() const { return auctionHouseEntry->faction; }
uint32 GetAuctionCut() const;
uint32 GetAuctionOutBid() const;
bool BuildAuctionInfo(WorldPacket & data) const;
void DeleteFromDB(SQLTransaction& trans) const;
void SaveToDB(SQLTransaction& trans) const;
bool LoadFromDB(Field* fields);
bool LoadFromFieldList(Field* fields);
std::string BuildAuctionMailSubject(MailAuctionAnswers response) const;
static std::string BuildAuctionMailBody(uint32 lowGuid, uint32 bid, uint32 buyout, uint32 deposit, uint32 cut);
};
//this class is used as auctionhouse instance
class AuctionHouseObject
{
public:
// Initialize storage
AuctionHouseObject() { next = AuctionsMap.begin(); }
~AuctionHouseObject()
{
for (AuctionEntryMap::iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr)
delete itr->second;
}
typedef std::map<uint32, AuctionEntry*> AuctionEntryMap;
uint32 Getcount() const { return AuctionsMap.size(); }
AuctionEntryMap::iterator GetAuctionsBegin() {return AuctionsMap.begin();}
AuctionEntryMap::iterator GetAuctionsEnd() {return AuctionsMap.end();}
AuctionEntry* GetAuction(uint32 id) const
{
AuctionEntryMap::const_iterator itr = AuctionsMap.find(id);
return itr != AuctionsMap.end() ? itr->second : NULL;
}
void AddAuction(AuctionEntry* auction);
bool RemoveAuction(AuctionEntry* auction);
void Update();
void BuildListBidderItems(WorldPacket& data, Player* player, uint32& count, uint32& totalcount);
void BuildListOwnerItems(WorldPacket& data, Player* player, uint32& count, uint32& totalcount);
bool BuildListAuctionItems(WorldPacket& data, Player* player,
std::wstring const& searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
uint32& count, uint32& totalcount, uint8 getAll);
private:
AuctionEntryMap AuctionsMap;
// storage for "next" auction item for next Update()
AuctionEntryMap::const_iterator next;
};
class AuctionHouseMgr
{
friend class ACE_Singleton<AuctionHouseMgr, ACE_Null_Mutex>;
private:
AuctionHouseMgr();
~AuctionHouseMgr();
public:
typedef UNORDERED_MAP<uint32, Item*> ItemMap;
AuctionHouseObject* GetAuctionsMap(uint32 factionTemplateId);
AuctionHouseObject* GetBidsMap(uint32 factionTemplateId);
Item* GetAItem(uint32 id)
{
ItemMap::const_iterator itr = mAitems.find(id);
if (itr != mAitems.end())
return itr->second;
return NULL;
}
//auction messages
void SendAuctionWonMail(AuctionEntry* auction, SQLTransaction& trans);
void SendAuctionSalePendingMail(AuctionEntry* auction, SQLTransaction& trans);
void SendAuctionSuccessfulMail(AuctionEntry* auction, SQLTransaction& trans);
void SendAuctionExpiredMail(AuctionEntry* auction, SQLTransaction& trans);
void SendAuctionOutbiddedMail(AuctionEntry* auction, uint32 newPrice, Player* newBidder, SQLTransaction& trans);
void SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans);
static uint32 GetAuctionDeposit(AuctionHouseEntry const* entry, uint32 time, Item* pItem, uint32 count);
static AuctionHouseEntry const* GetAuctionHouseEntry(uint32 factionTemplateId);
public:
//load first auction items, because of check if item exists, when loading
void LoadAuctionItems();
void LoadAuctions();
void AddAItem(Item* it);
bool RemoveAItem(uint32 id, bool deleteFromDB = false);
void Update();
private:
AuctionHouseObject mHordeAuctions;
AuctionHouseObject mAllianceAuctions;
AuctionHouseObject mNeutralAuctions;
ItemMap mAitems;
};
#define sAuctionMgr ACE_Singleton<AuctionHouseMgr, ACE_Null_Mutex>::instance()
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,436 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BATTLEFIELD_H_
#define BATTLEFIELD_H_
#include "Utilities/Util.h"
#include "SharedDefines.h"
#include "ZoneScript.h"
#include "WorldPacket.h"
#include "GameObject.h"
#include "Battleground.h"
#include "ObjectAccessor.h"
enum BattlefieldTypes
{
BATTLEFIELD_WG, // Wintergrasp
BATTLEFIELD_TB, // Tol Barad (cataclysm)
};
enum BattlefieldIDs
{
BATTLEFIELD_BATTLEID_WG = 1, // Wintergrasp battle
};
enum BattlefieldObjectiveStates
{
BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL = 0,
BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE,
BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE,
BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE,
BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE,
BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE,
BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE,
};
enum BattlefieldSounds
{
BF_HORDE_WINS = 8454,
BF_ALLIANCE_WINS = 8455,
BF_START = 3439
};
enum BattlefieldTimers
{
BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL = 1000
};
const uint32 BattlefieldFactions[BG_TEAMS_COUNT] =
{
1732, // Alliance
1735 // Horde
};
// some class predefs
class Player;
class GameObject;
class WorldPacket;
class Creature;
class Unit;
class Battlefield;
class BfGraveyard;
typedef UNORDERED_SET<uint64> GuidSet;
typedef std::vector<BfGraveyard*> GraveyardVect;
typedef std::map<uint64, time_t> PlayerTimerMap;
class BfCapturePoint
{
public:
BfCapturePoint(Battlefield* bf);
virtual void FillInitialWorldStates(WorldPacket& /*data*/) {}
// Send world state update to all players present
void SendUpdateWorldState(uint32 field, uint32 value);
// Send kill notify to players in the controlling faction
void SendObjectiveComplete(uint32 id, uint64 guid);
// Used when player is activated/inactivated in the area
virtual bool HandlePlayerEnter(Player* player);
virtual GuidSet::iterator HandlePlayerLeave(Player* player);
//virtual void HandlePlayerActivityChanged(Player* player);
// Checks if player is in range of a capture credit marker
bool IsInsideObjective(Player* player) const;
// Returns true if the state of the objective has changed, in this case, the OutdoorPvP must send a world state ui update.
virtual bool Update(uint32 diff);
virtual void ChangeTeam(TeamId /*oldTeam*/) {}
virtual void SendChangePhase();
bool SetCapturePointData(GameObject* capturePoint);
GameObject* GetCapturePointGo() { return ObjectAccessor::GetObjectInWorld(m_capturePoint, (GameObject*)NULL); }
GameObject* GetCapturePointGo(WorldObject* obj) { return ObjectAccessor::GetGameObject(*obj, m_capturePoint); }
TeamId GetTeamId() { return m_team; }
protected:
bool DelCapturePoint();
// active Players in the area of the objective, 0 - alliance, 1 - horde
GuidSet m_activePlayers[2];
// Total shift needed to capture the objective
float m_maxValue;
float m_minValue;
// Maximum speed of capture
float m_maxSpeed;
// The status of the objective
float m_value;
TeamId m_team;
// Objective states
BattlefieldObjectiveStates m_OldState;
BattlefieldObjectiveStates m_State;
// Neutral value on capture bar
uint32 m_neutralValuePct;
// Pointer to the Battlefield this objective belongs to
Battlefield* m_Bf;
// Capture point entry
uint32 m_capturePointEntry;
// Gameobject related to that capture point
uint64 m_capturePoint;
};
class BfGraveyard
{
public:
BfGraveyard(Battlefield* Bf);
// Method to changing who controls the graveyard
void GiveControlTo(TeamId team);
TeamId GetControlTeamId() const { return m_ControlTeam; }
// Find the nearest graveyard to a player
float GetDistance(Player* player);
// Initialize the graveyard
void Initialize(TeamId startcontrol, uint32 gy);
// Set spirit service for the graveyard
void SetSpirit(Creature* spirit, TeamId team);
// Add a player to the graveyard
void AddPlayer(uint64 player_guid);
// Remove a player from the graveyard
void RemovePlayer(uint64 player_guid);
// Resurrect players
void Resurrect();
// Move players waiting to that graveyard on the nearest one
void RelocateDeadPlayers();
// Check if this graveyard has a spirit guide
bool HasNpc(uint64 guid)
{
if (!m_SpiritGuide[0] && !m_SpiritGuide[1])
return false;
// performance
/*if (!ObjectAccessor::FindUnit(m_SpiritGuide[0]) &&
!ObjectAccessor::FindUnit(m_SpiritGuide[1]))
return false;*/
return (m_SpiritGuide[0] == guid || m_SpiritGuide[1] == guid);
}
// Check if a player is in this graveyard's resurrect queue
bool HasPlayer(uint64 guid) const { return m_ResurrectQueue.find(guid) != m_ResurrectQueue.end(); }
// Get the graveyard's ID.
uint32 GetGraveyardId() const { return m_GraveyardId; }
protected:
TeamId m_ControlTeam;
uint32 m_GraveyardId;
uint64 m_SpiritGuide[2];
GuidSet m_ResurrectQueue;
Battlefield* m_Bf;
};
class Battlefield : public ZoneScript
{
friend class BattlefieldMgr;
public:
/// Constructor
Battlefield();
/// Destructor
virtual ~Battlefield();
/// typedef of map witch store capturepoint and the associate gameobject entry
typedef std::map<uint32 /*lowguid */, BfCapturePoint*> BfCapturePointMap;
/// Call this to init the Battlefield
virtual bool SetupBattlefield() { return true; }
/// Update data of a worldstate to all players present in zone
void SendUpdateWorldState(uint32 field, uint32 value);
/**
* \brief Called every time for update bf data and time
* - Update timer for start/end battle
* - Invite player in zone to queue m_StartGroupingTimer minutes before start
* - Kick Afk players
* \param diff : time ellapsed since last call (in ms)
*/
virtual bool Update(uint32 diff);
/// Invite all players in zone to join the queue, called x minutes before battle start in Update()
void InvitePlayersInZoneToQueue();
/// Invite all players in queue to join battle on battle start
void InvitePlayersInQueueToWar();
/// Invite all players in zone to join battle on battle start
void InvitePlayersInZoneToWar();
/// Called when a Unit is kill in battlefield zone
virtual void HandleKill(Player* /*killer*/, Unit* /*killed*/) {};
uint32 GetTypeId() { return m_TypeId; }
uint32 GetZoneId() { return m_ZoneId; }
void TeamApplyBuff(TeamId team, uint32 spellId, uint32 spellId2 = 0);
/// Return true if battle is start, false if battle is not started
bool IsWarTime() { return m_isActive; }
/// Enable or Disable battlefield
void ToggleBattlefield(bool enable) { m_IsEnabled = enable; }
/// Return if battlefield is enable
bool IsEnabled() { return m_IsEnabled; }
/**
* \brief Kick player from battlefield and teleport him to kick-point location
* \param guid : guid of player who must be kick
*/
void KickPlayerFromBattlefield(uint64 guid);
/// Called when player (player) enter in zone
void HandlePlayerEnterZone(Player* player, uint32 zone);
/// Called when player (player) leave the zone
void HandlePlayerLeaveZone(Player* player, uint32 zone);
// All-purpose data storage 64 bit
virtual uint64 GetData64(uint32 dataId) const { return m_Data64[dataId]; }
virtual void SetData64(uint32 dataId, uint64 value) { m_Data64[dataId] = value; }
// All-purpose data storage 32 bit
virtual uint32 GetData(uint32 dataId) const { return m_Data32[dataId]; }
virtual void SetData(uint32 dataId, uint32 value) { m_Data32[dataId] = value; }
virtual void UpdateData(uint32 index, int32 pad) { m_Data32[index] += pad; }
// Battlefield - generic methods
TeamId GetDefenderTeam() { return m_DefenderTeam; }
TeamId GetAttackerTeam() { return TeamId(1 - m_DefenderTeam); }
TeamId GetOtherTeam(TeamId team) { return (team == TEAM_HORDE ? TEAM_ALLIANCE : TEAM_HORDE); }
void SetDefenderTeam(TeamId team) { m_DefenderTeam = team; }
// Group methods
/**
* \brief Find a not full battlefield group, if there is no, create one
* \param TeamId : Id of player team for who we search a group (player->GetTeamId())
*/
Group* GetFreeBfRaid(TeamId TeamId);
/// Return battlefield group where player is.
Group* GetGroupPlayer(uint64 guid, TeamId TeamId);
/// Force player to join a battlefield group
bool AddOrSetPlayerToCorrectBfGroup(Player* player);
// Graveyard methods
// Find which graveyard the player must be teleported to to be resurrected by spiritguide
WorldSafeLocsEntry const * GetClosestGraveyard(Player* player);
virtual void AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid);
void RemovePlayerFromResurrectQueue(uint64 player_guid);
void SetGraveyardNumber(uint32 number) { m_GraveyardList.resize(number); }
BfGraveyard* GetGraveyardById(uint32 id) const;
// Misc methods
Creature* SpawnCreature(uint32 entry, float x, float y, float z, float o, TeamId teamId);
Creature* SpawnCreature(uint32 entry, Position pos, TeamId teamId);
GameObject* SpawnGameObject(uint32 entry, float x, float y, float z, float o);
// Script-methods
/// Called on start
virtual void OnBattleStart() {};
/// Called at the end of battle
virtual void OnBattleEnd(bool /*endByTimer*/) {};
/// Called x minutes before battle start when player in zone are invite to join queue
virtual void OnStartGrouping() {};
/// Called when a player accept to join the battle
virtual void OnPlayerJoinWar(Player* /*player*/) {};
/// Called when a player leave the battle
virtual void OnPlayerLeaveWar(Player* /*player*/) {};
/// Called when a player leave battlefield zone
virtual void OnPlayerLeaveZone(Player* /*player*/) {};
/// Called when a player enter in battlefield zone
virtual void OnPlayerEnterZone(Player* /*player*/) {};
void SendWarningToAllInZone(uint32 entry);
void SendWarningToPlayer(Player* player, uint32 entry);
void PlayerAcceptInviteToQueue(Player* player);
void PlayerAcceptInviteToWar(Player* player);
uint32 GetBattleId() { return m_BattleId; }
void AskToLeaveQueue(Player* player);
//virtual void DoCompleteOrIncrementAchievement(uint32 /*achievement*/, Player* /*player*/, uint8 /*incrementNumber = 1*/) {};
/// Send all worldstate data to all player in zone.
virtual void SendInitWorldStatesToAll() = 0;
virtual void FillInitialWorldStates(WorldPacket& /*data*/) = 0;
/// Return if we can use mount in battlefield
bool CanFlyIn() { return !m_isActive; }
void SendAreaSpiritHealerQueryOpcode(Player* player, const uint64 & guid);
void StartBattle();
void EndBattle(bool endByTimer);
void HideNpc(Creature* creature);
void ShowNpc(Creature* creature, bool aggressive);
GraveyardVect GetGraveyardVector() { return m_GraveyardList; }
uint32 GetTimer() { return m_Timer; }
void SetTimer(uint32 timer) { m_Timer = timer; }
void DoPlaySoundToAll(uint32 SoundID);
void InvitePlayerToQueue(Player* player);
void InvitePlayerToWar(Player* player);
void InitStalker(uint32 entry, float x, float y, float z, float o);
protected:
uint64 StalkerGuid;
uint32 m_Timer; // Global timer for event
bool m_IsEnabled;
bool m_isActive;
TeamId m_DefenderTeam;
// Map of the objectives belonging to this OutdoorPvP
BfCapturePointMap m_capturePoints;
// Players info maps
GuidSet m_players[BG_TEAMS_COUNT]; // Players in zone
GuidSet m_PlayersInQueue[BG_TEAMS_COUNT]; // Players in the queue
GuidSet m_PlayersInWar[BG_TEAMS_COUNT]; // Players in WG combat
PlayerTimerMap m_InvitedPlayers[BG_TEAMS_COUNT];
PlayerTimerMap m_PlayersWillBeKick[BG_TEAMS_COUNT];
// Variables that must exist for each battlefield
uint32 m_TypeId; // See enum BattlefieldTypes
uint32 m_BattleId; // BattleID (for packet)
uint32 m_ZoneId; // ZoneID of Wintergrasp = 4197
uint32 m_MapId; // MapId where is Battlefield
uint32 m_MaxPlayer; // Maximum number of player that participated to Battlefield
uint32 m_MinPlayer; // Minimum number of player for Battlefield start
uint32 m_MinLevel; // Required level to participate at Battlefield
uint32 m_BattleTime; // Length of a battle
uint32 m_NoWarBattleTime; // Time between two battles
uint32 m_RestartAfterCrash; // Delay to restart Wintergrasp if the server crashed during a running battle.
uint32 m_TimeForAcceptInvite;
uint32 m_uiKickDontAcceptTimer;
WorldLocation KickPosition; // Position where players are teleported if they switch to afk during the battle or if they don't accept invitation
uint32 m_uiKickAfkPlayersTimer; // Timer for check Afk in war
// Graveyard variables
GraveyardVect m_GraveyardList; // Vector witch contain the different GY of the battle
uint32 m_LastResurectTimer; // Timer for resurect player every 30 sec
uint32 m_StartGroupingTimer; // Timer for invite players in area 15 minute before start battle
bool m_StartGrouping; // bool for know if all players in area has been invited
GuidSet m_Groups[BG_TEAMS_COUNT]; // Contain different raid group
std::vector<uint64> m_Data64;
std::vector<uint32> m_Data32;
void KickAfkPlayers();
// use for switch off all worldstate for client
virtual void SendRemoveWorldStates(Player* /*player*/) {}
// use for send a packet for all player list
void BroadcastPacketToZone(WorldPacket& data) const;
void BroadcastPacketToQueue(WorldPacket& data) const;
void BroadcastPacketToWar(WorldPacket& data) const;
// CapturePoint system
void AddCapturePoint(BfCapturePoint* cp, GameObject* go) { m_capturePoints[go->GetEntry()] = cp; }
BfCapturePoint* GetCapturePoint(uint32 lowguid) const
{
Battlefield::BfCapturePointMap::const_iterator itr = m_capturePoints.find(lowguid);
if (itr != m_capturePoints.end())
return itr->second;
return NULL;
}
void RegisterZone(uint32 zoneid);
bool HasPlayer(Player* player) const;
void TeamCastSpell(TeamId team, int32 spellId);
};
#endif

View File

@@ -1,151 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Common.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
#include "Opcodes.h"
#include "Player.h"
//This send to player windows for invite player to join the war
//Param1:(BattleId) the BattleId of Bf
//Param2:(ZoneId) the zone where the battle is (4197 for wg)
//Param3:(time) Time in second that the player have for accept
void WorldSession::SendBfInvitePlayerToWar(uint32 BattleId, uint32 ZoneId, uint32 p_time)
{
//Send packet
WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTRY_INVITE, 12);
data << uint32(BattleId);
data << uint32(ZoneId);
data << uint32((time(NULL) + p_time));
//Sending the packet to player
SendPacket(&data);
}
//This send invitation to player to join the queue
//Param1:(BattleId) the BattleId of Bf
void WorldSession::SendBfInvitePlayerToQueue(uint32 BattleId)
{
WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_INVITE, 5);
data << uint32(BattleId);
data << uint8(1); //warmup ? used ?
//Sending packet to player
SendPacket(&data);
}
//This send packet for inform player that he join queue
//Param1:(BattleId) the BattleId of Bf
//Param2:(ZoneId) the zone where the battle is (4197 for wg)
//Param3:(CanQueue) if able to queue
//Param4:(Full) on log in is full
void WorldSession::SendBfQueueInviteResponse(uint32 BattleId,uint32 ZoneId, bool CanQueue, bool Full)
{
WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE, 11);
data << uint32(BattleId);
data << uint32(ZoneId);
data << uint8((CanQueue ? 1 : 0)); //Accepted //0 you cannot queue wg //1 you are queued
data << uint8((Full ? 0 : 1)); //Logging In //0 wg full //1 queue for upcoming
data << uint8(1); //Warmup
SendPacket(&data);
}
//This is call when player accept to join war
//Param1:(BattleId) the BattleId of Bf
void WorldSession::SendBfEntered(uint32 BattleId)
{
// m_PlayerInWar[player->GetTeamId()].insert(player->GetGUID());
WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTERED, 7);
data << uint32(BattleId);
data << uint8(1); //unk
data << uint8(1); //unk
data << uint8(_player->isAFK() ? 1 : 0); //Clear AFK
SendPacket(&data);
}
void WorldSession::SendBfLeaveMessage(uint32 BattleId, BFLeaveReason reason)
{
WorldPacket data(SMSG_BATTLEFIELD_MGR_EJECTED, 7);
data << uint32(BattleId);
data << uint8(reason);//byte Reason
data << uint8(2);//byte BattleStatus
data << uint8(0);//bool Relocated
SendPacket(&data);
}
//Send by client when he click on accept for queue
void WorldSession::HandleBfQueueInviteResponse(WorldPacket & recvData)
{
uint32 BattleId;
uint8 Accepted;
recvData >> BattleId >> Accepted;
//sLog->outError("HandleQueueInviteResponse: BattleID:%u Accepted:%u", BattleId, Accepted);
Battlefield* Bf = sBattlefieldMgr->GetBattlefieldByBattleId(BattleId);
if (!Bf)
return;
if (Accepted)
{
Bf->PlayerAcceptInviteToQueue(_player);
}
}
//Send by client on clicking in accept or refuse of invitation windows for join game
void WorldSession::HandleBfEntryInviteResponse(WorldPacket & recvData)
{
uint32 BattleId;
uint8 Accepted;
recvData >> BattleId >> Accepted;
//sLog->outError("HandleBattlefieldInviteResponse: BattleID:%u Accepted:%u", BattleId, Accepted);
Battlefield* Bf = sBattlefieldMgr->GetBattlefieldByBattleId(BattleId);
if (!Bf)
return;
//If player accept invitation
if (Accepted)
{
Bf->PlayerAcceptInviteToWar(_player);
}
else
{
if (_player->GetZoneId() == Bf->GetZoneId())
Bf->KickPlayerFromBattlefield(_player->GetGUID());
}
}
void WorldSession::HandleBfExitRequest(WorldPacket & recvData)
{
uint32 BattleId;
recvData >> BattleId;
//sLog->outError("HandleBfExitRequest: BattleID:%u ", BattleId);
Battlefield* Bf = sBattlefieldMgr->GetBattlefieldByBattleId(BattleId);
if (!Bf)
return;
Bf->AskToLeaveQueue(_player);
}

View File

@@ -1,142 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlefieldMgr.h"
#include "Zones/BattlefieldWG.h"
#include "ObjectMgr.h"
#include "Player.h"
BattlefieldMgr::BattlefieldMgr()
{
m_UpdateTimer = 0;
//sLog->outDebug(LOG_FILTER_BATTLEFIELD, "Instantiating BattlefieldMgr");
}
BattlefieldMgr::~BattlefieldMgr()
{
//sLog->outDebug(LOG_FILTER_BATTLEFIELD, "Deleting BattlefieldMgr");
for (BattlefieldSet::iterator itr = m_BattlefieldSet.begin(); itr != m_BattlefieldSet.end(); ++itr)
delete *itr;
}
void BattlefieldMgr::InitBattlefield()
{
Battlefield* pBf = new BattlefieldWG;
// respawn, init variables
if (!pBf->SetupBattlefield())
{
sLog->outString();
sLog->outString("Battlefield : Wintergrasp init failed.");
delete pBf;
}
else
{
m_BattlefieldSet.push_back(pBf);
sLog->outString();
sLog->outString("Battlefield : Wintergrasp successfully initiated.");
}
/* For Cataclysm: Tol Barad
pBf = new BattlefieldTB;
// respawn, init variables
if(!pBf->SetupBattlefield())
{
;//sLog->outDebug(LOG_FILTER_BATTLEFIELD, "Battlefield : Tol Barad init failed.");
delete pBf;
}
else
{
m_BattlefieldSet.push_back(pBf);
;//sLog->outDebug(LOG_FILTER_BATTLEFIELD, "Battlefield : Tol Barad successfully initiated.");
} */
}
void BattlefieldMgr::AddZone(uint32 zoneid, Battlefield *handle)
{
m_BattlefieldMap[zoneid] = handle;
}
void BattlefieldMgr::HandlePlayerEnterZone(Player * player, uint32 zoneid)
{
BattlefieldMap::iterator itr = m_BattlefieldMap.find(zoneid);
if (itr == m_BattlefieldMap.end())
return;
if (itr->second->HasPlayer(player) || !itr->second->IsEnabled())
return;
itr->second->HandlePlayerEnterZone(player, zoneid);
;//sLog->outDebug(LOG_FILTER_BATTLEFIELD, "Player %u entered outdoorpvp id %u", player->GetGUIDLow(), itr->second->GetTypeId());
}
void BattlefieldMgr::HandlePlayerLeaveZone(Player * player, uint32 zoneid)
{
BattlefieldMap::iterator itr = m_BattlefieldMap.find(zoneid);
if (itr == m_BattlefieldMap.end())
return;
// teleport: remove once in removefromworld, once in updatezone
if (!itr->second->HasPlayer(player))
return;
itr->second->HandlePlayerLeaveZone(player, zoneid);
;//sLog->outDebug(LOG_FILTER_BATTLEFIELD, "Player %u left outdoorpvp id %u", player->GetGUIDLow(), itr->second->GetTypeId());
}
Battlefield *BattlefieldMgr::GetBattlefieldToZoneId(uint32 zoneid)
{
BattlefieldMap::iterator itr = m_BattlefieldMap.find(zoneid);
if (itr == m_BattlefieldMap.end())
{
// no handle for this zone, return
return NULL;
}
if (!itr->second->IsEnabled())
return NULL;
return itr->second;
}
Battlefield *BattlefieldMgr::GetBattlefieldByBattleId(uint32 battleid)
{
for (BattlefieldSet::iterator itr = m_BattlefieldSet.begin(); itr != m_BattlefieldSet.end(); ++itr)
{
if ((*itr)->GetBattleId() == battleid)
return (*itr);
}
return NULL;
}
void BattlefieldMgr::Update(uint32 diff)
{
m_UpdateTimer += diff;
if (m_UpdateTimer > BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL)
{
for (BattlefieldSet::iterator itr = m_BattlefieldSet.begin(); itr != m_BattlefieldSet.end(); ++itr)
//if ((*itr)->IsEnabled())
(*itr)->Update(m_UpdateTimer);
m_UpdateTimer = 0;
}
}
ZoneScript *BattlefieldMgr::GetZoneScript(uint32 zoneId)
{
BattlefieldMap::iterator itr = m_BattlefieldMap.find(zoneId);
if (itr != m_BattlefieldMap.end())
return itr->second;
else
return NULL;
}

View File

@@ -1,79 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BATTLEFIELD_MGR_H_
#define BATTLEFIELD_MGR_H_
#include "Battlefield.h"
#include "ace/Singleton.h"
class Player;
class GameObject;
class Creature;
class ZoneScript;
struct GossipMenuItems;
// class to handle player enter / leave / areatrigger / GO use events
class BattlefieldMgr
{
public:
// ctor
BattlefieldMgr();
// dtor
~BattlefieldMgr();
// create battlefield events
void InitBattlefield();
// called when a player enters an battlefield area
void HandlePlayerEnterZone(Player * player, uint32 areaflag);
// called when player leaves an battlefield area
void HandlePlayerLeaveZone(Player * player, uint32 areaflag);
// called when player resurrects
void HandlePlayerResurrects(Player * player, uint32 areaflag);
// return assigned battlefield
Battlefield* GetBattlefieldToZoneId(uint32 zoneid);
Battlefield* GetBattlefieldByBattleId(uint32 battleid);
ZoneScript* GetZoneScript(uint32 zoneId);
void AddZone(uint32 zoneid, Battlefield * handle);
void Update(uint32 diff);
void HandleGossipOption(Player * player, uint64 guid, uint32 gossipid);
bool CanTalkTo(Player * player, Creature * creature, GossipMenuItems gso);
void HandleDropFlag(Player * player, uint32 spellId);
typedef std::vector < Battlefield * >BattlefieldSet;
typedef std::map < uint32 /* zoneid */ , Battlefield * >BattlefieldMap;
private:
// contains all initiated battlefield events
// used when initing / cleaning up
BattlefieldSet m_BattlefieldSet;
// maps the zone ids to an battlefield event
// used in player event handling
BattlefieldMap m_BattlefieldMap;
// update interval
uint32 m_UpdateTimer;
};
#define sBattlefieldMgr ACE_Singleton<BattlefieldMgr, ACE_Null_Mutex>::instance()
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,916 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ObjectMgr.h"
#include "WorldPacket.h"
#include "ArenaTeam.h"
#include "World.h"
#include "Group.h"
#include "ArenaTeamMgr.h"
#include "Player.h"
#include "WorldSession.h"
#include "Opcodes.h"
#include <Config.h>
ArenaTeam::ArenaTeam()
: TeamId(0), Type(0), TeamName(), CaptainGuid(0), BackgroundColor(0), EmblemStyle(0), EmblemColor(0),
BorderStyle(0), BorderColor(0)
{
Stats.WeekGames = 0;
Stats.SeasonGames = 0;
Stats.Rank = 0;
Stats.Rating = sWorld->getIntConfig(CONFIG_ARENA_START_RATING);
Stats.WeekWins = 0;
Stats.SeasonWins = 0;
}
ArenaTeam::~ArenaTeam()
{
}
bool ArenaTeam::Create(uint64 captainGuid, uint8 type, std::string const& teamName, uint32 backgroundColor, uint8 emblemStyle, uint32 emblemColor, uint8 borderStyle, uint32 borderColor)
{
// Check if captain is present
if (!ObjectAccessor::FindPlayerInOrOutOfWorld(captainGuid))
return false;
// Check if arena team name is already taken
if (sArenaTeamMgr->GetArenaTeamByName(TeamName))
return false;
// Generate new arena team id
TeamId = sArenaTeamMgr->GenerateArenaTeamId();
// Assign member variables
CaptainGuid = captainGuid;
Type = type;
TeamName = teamName;
BackgroundColor = backgroundColor;
EmblemStyle = emblemStyle;
EmblemColor = emblemColor;
BorderStyle = borderStyle;
BorderColor = borderColor;
uint32 captainLowGuid = GUID_LOPART(captainGuid);
// Save arena team to db
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_TEAM);
stmt->setUInt32(0, TeamId);
stmt->setString(1, TeamName);
stmt->setUInt32(2, captainLowGuid);
stmt->setUInt8(3, Type);
stmt->setUInt16(4, Stats.Rating);
stmt->setUInt32(5, BackgroundColor);
stmt->setUInt8(6, EmblemStyle);
stmt->setUInt32(7, EmblemColor);
stmt->setUInt8(8, BorderStyle);
stmt->setUInt32(9, BorderColor);
CharacterDatabase.Execute(stmt);
// Add captain as member
AddMember(CaptainGuid);
return true;
}
bool ArenaTeam::AddMember(uint64 playerGuid)
{
std::string playerName;
uint8 playerClass;
// Check if arena team is full (Can't have more than type * 2 players)
if (GetMembersSize() >= GetType() * 2)
return false;
// xinef: Get player name and class from player storage or global data storage
Player* player = ObjectAccessor::FindPlayerInOrOutOfWorld(playerGuid);
if (player)
{
playerClass = player->getClass();
playerName = player->GetName();
}
else
{
GlobalPlayerData const* playerData = sWorld->GetGlobalPlayerData(GUID_LOPART(playerGuid));
if (!playerData)
return false;
playerName = playerData->name;
playerClass = playerData->playerClass;
}
// Check if player is already in a similar arena team
if ((player && player->GetArenaTeamId(GetSlot())) || Player::GetArenaTeamIdFromStorage(GUID_LOPART(playerGuid), GetSlot()) != 0)
{
sLog->outError("Arena: Player %s (guid: %u) already has an arena team of type %u", playerName.c_str(), GUID_LOPART(playerGuid), GetType());
return false;
}
// Set player's personal rating
uint32 personalRating = 0;
if (sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING) > 0)
personalRating = sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING);
else if (GetRating() >= 1000)
personalRating = 1000;
// xinef: zomg! sync query
// Try to get player's match maker rating from db and fall back to config setting if not found
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MATCH_MAKER_RATING);
stmt->setUInt32(0, GUID_LOPART(playerGuid));
stmt->setUInt8(1, GetSlot());
PreparedQueryResult result = CharacterDatabase.Query(stmt);
uint16 matchMakerRating;
uint16 maxMMR;
if (result)
{
matchMakerRating = (*result)[0].GetUInt16();
uint16 Max = (*result)[1].GetUInt16();
maxMMR = std::max(Max, matchMakerRating);
}
else
{
matchMakerRating = sWorld->getIntConfig(CONFIG_ARENA_START_MATCHMAKER_RATING);
maxMMR = matchMakerRating;
}
// Remove all player signatures from other petitions
// This will prevent player from joining too many arena teams and corrupt arena team data integrity
Player::RemovePetitionsAndSigns(playerGuid, GetType());
// Feed data to the struct
ArenaTeamMember newMember;
//newMember.Name = playerName;
newMember.Guid = playerGuid;
newMember.Class = playerClass;
newMember.SeasonGames = 0;
newMember.WeekGames = 0;
newMember.SeasonWins = 0;
newMember.WeekWins = 0;
newMember.PersonalRating = personalRating;
newMember.MatchMakerRating = matchMakerRating;
newMember.MaxMMR = maxMMR;
Members.push_back(newMember);
sWorld->UpdateGlobalPlayerArenaTeam(GUID_LOPART(playerGuid), GetSlot(), GetId());
// Save player's arena team membership to db
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_TEAM_MEMBER);
stmt->setUInt32(0, TeamId);
stmt->setUInt32(1, GUID_LOPART(playerGuid));
CharacterDatabase.Execute(stmt);
// Inform player if online
if (player)
{
player->SetInArenaTeam(TeamId, GetSlot(), GetType());
player->SetArenaTeamIdInvited(0);
// Hide promote/remove buttons
if (CaptainGuid != playerGuid)
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1);
}
return true;
}
bool ArenaTeam::LoadArenaTeamFromDB(QueryResult result)
{
if (!result)
return false;
Field* fields = result->Fetch();
TeamId = fields[0].GetUInt32();
TeamName = fields[1].GetString();
CaptainGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER);
Type = fields[3].GetUInt8();
BackgroundColor = fields[4].GetUInt32();
EmblemStyle = fields[5].GetUInt8();
EmblemColor = fields[6].GetUInt32();
BorderStyle = fields[7].GetUInt8();
BorderColor = fields[8].GetUInt32();
Stats.Rating = fields[9].GetUInt16();
Stats.WeekGames = fields[10].GetUInt16();
Stats.WeekWins = fields[11].GetUInt16();
Stats.SeasonGames = fields[12].GetUInt16();
Stats.SeasonWins = fields[13].GetUInt16();
Stats.Rank = fields[14].GetUInt32();
return true;
}
bool ArenaTeam::LoadMembersFromDB(QueryResult result)
{
if (!result)
return false;
bool captainPresentInTeam = false;
do
{
Field* fields = result->Fetch();
// Prevent crash if db records are broken when all members in result are already processed and current team doesn't have any members
if (!fields)
break;
uint32 arenaTeamId = fields[0].GetUInt32();
// We loaded all members for this arena_team already, break cycle
if (arenaTeamId > TeamId)
break;
ArenaTeamMember newMember;
newMember.Guid = MAKE_NEW_GUID(fields[1].GetUInt32(), 0, HIGHGUID_PLAYER);
newMember.WeekGames = fields[2].GetUInt16();
newMember.WeekWins = fields[3].GetUInt16();
newMember.SeasonGames = fields[4].GetUInt16();
newMember.SeasonWins = fields[5].GetUInt16();
//newMember.Name = fields[6].GetString();
newMember.Class = fields[7].GetUInt8();
newMember.PersonalRating = fields[8].GetUInt16();
newMember.MatchMakerRating = fields[9].GetUInt16() > 0 ? fields[9].GetUInt16() : sWorld->getIntConfig(CONFIG_ARENA_START_MATCHMAKER_RATING);;
newMember.MaxMMR = std::max(fields[10].GetUInt16(), newMember.MatchMakerRating);
// Delete member if character information is missing
if (fields[6].GetString().empty())
{
sLog->outErrorDb("ArenaTeam %u has member with empty name - probably player %u doesn't exist, deleting him from memberlist!", arenaTeamId, GUID_LOPART(newMember.Guid));
this->DelMember(newMember.Guid, true);
continue;
}
// Check if team team has a valid captain
if (newMember.Guid == GetCaptain())
captainPresentInTeam = true;
// Put the player in the team
Members.push_back(newMember);
sWorld->UpdateGlobalPlayerArenaTeam(GUID_LOPART(newMember.Guid), GetSlot(), GetId());
}
while (result->NextRow());
if (Empty() || !captainPresentInTeam)
{
// Arena team is empty or captain is not in team, delete from db
;//sLog->outDebug(LOG_FILTER_BATTLEGROUND, "ArenaTeam %u does not have any members or its captain is not in team, disbanding it...", TeamId);
return false;
}
return true;
}
void ArenaTeam::SetCaptain(uint64 guid)
{
// Disable remove/promote buttons
Player* oldCaptain = ObjectAccessor::FindPlayerInOrOutOfWorld(GetCaptain());
if (oldCaptain)
oldCaptain->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1);
// Set new captain
CaptainGuid = guid;
// Update database
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ARENA_TEAM_CAPTAIN);
stmt->setUInt32(0, GUID_LOPART(guid));
stmt->setUInt32(1, GetId());
CharacterDatabase.Execute(stmt);
// Enable remove/promote buttons
if (Player* newCaptain = ObjectAccessor::FindPlayerInOrOutOfWorld(guid))
{
newCaptain->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 0);
/*if (oldCaptain)
{
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Player: %s [GUID: %u] promoted player: %s [GUID: %u] to leader of arena team [Id: %u] [Type: %u].",
oldCaptain->GetName().c_str(), oldCaptain->GetGUIDLow(), newCaptain->GetName().c_str(),
newCaptain->GetGUIDLow(), GetId(), GetType());
}*/
}
}
void ArenaTeam::DelMember(uint64 guid, bool cleanDb)
{
// Remove member from team
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (itr->Guid == guid)
{
Members.erase(itr);
sWorld->UpdateGlobalPlayerArenaTeam(GUID_LOPART(guid), GetSlot(), 0);
break;
}
// Inform player and remove arena team info from player data
if (Player* player = ObjectAccessor::FindPlayerInOrOutOfWorld(guid))
{
player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0);
// delete all info regarding this team
for (uint32 i = 0; i < ARENA_TEAM_END; ++i)
player->SetArenaTeamInfoField(GetSlot(), ArenaTeamInfoType(i), 0);
}
// Only used for single member deletion, for arena team disband we use a single query for more efficiency
if (cleanDb)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ARENA_TEAM_MEMBER);
stmt->setUInt32(0, GetId());
stmt->setUInt32(1, GUID_LOPART(guid));
CharacterDatabase.Execute(stmt);
}
}
void ArenaTeam::Disband(WorldSession* session)
{
// Remove all members from arena team
while (!Members.empty())
DelMember(Members.front().Guid, false);
// Broadcast update
if (session)
{
BroadcastEvent(ERR_ARENA_TEAM_DISBANDED_S, 0, 2, session->GetPlayerName(), GetName(), "");
}
// Update database
SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ARENA_TEAM);
stmt->setUInt32(0, TeamId);
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ARENA_TEAM_MEMBERS);
stmt->setUInt32(0, TeamId);
trans->Append(stmt);
CharacterDatabase.CommitTransaction(trans);
// Remove arena team from ObjectMgr
sArenaTeamMgr->RemoveArenaTeam(TeamId);
}
void ArenaTeam::Roster(WorldSession* session)
{
Player* player = NULL;
uint8 unk308 = 0;
std::string tempName;
WorldPacket data(SMSG_ARENA_TEAM_ROSTER, 100);
data << uint32(GetId()); // team id
data << uint8(unk308); // 308 unknown value but affect packet structure
data << uint32(GetMembersSize()); // members count
data << uint32(GetType()); // arena team type?
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
player = ObjectAccessor::FindPlayerInOrOutOfWorld(itr->Guid);
data << uint64(itr->Guid); // guid
data << uint8((player ? 1 : 0)); // online flag
tempName = "";
sObjectMgr->GetPlayerNameByGUID(itr->Guid, tempName);
data << tempName; // member name
data << uint32((itr->Guid == GetCaptain() ? 0 : 1));// captain flag 0 captain 1 member
data << uint8((player ? player->getLevel() : 0)); // unknown, level?
data << uint8(itr->Class); // class
data << uint32(itr->WeekGames); // played this week
data << uint32(itr->WeekWins); // wins this week
data << uint32(itr->SeasonGames); // played this season
data << uint32(itr->SeasonWins); // wins this season
data << uint32(itr->PersonalRating); // personal rating
if (unk308)
{
data << float(0.0f); // 308 unk
data << float(0.0f); // 308 unk
}
}
session->SendPacket(&data);
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_ARENA_TEAM_ROSTER");
}
void ArenaTeam::Query(WorldSession* session)
{
WorldPacket data(SMSG_ARENA_TEAM_QUERY_RESPONSE, 4*7+GetName().size()+1);
data << uint32(GetId()); // team id
data << GetName(); // team name
data << uint32(GetType()); // arena team type (2=2x2, 3=3x3 or 5=5x5)
data << uint32(BackgroundColor); // background color
data << uint32(EmblemStyle); // emblem style
data << uint32(EmblemColor); // emblem color
data << uint32(BorderStyle); // border style
data << uint32(BorderColor); // border color
session->SendPacket(&data);
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_ARENA_TEAM_QUERY_RESPONSE");
}
void ArenaTeam::SendStats(WorldSession* session)
{
WorldPacket data(SMSG_ARENA_TEAM_STATS, 4*7);
data << uint32(GetId()); // team id
data << uint32(Stats.Rating); // rating
data << uint32(Stats.WeekGames); // games this week
data << uint32(Stats.WeekWins); // wins this week
data << uint32(Stats.SeasonGames); // played this season
data << uint32(Stats.SeasonWins); // wins this season
data << uint32(Stats.Rank); // rank
session->SendPacket(&data);
}
void ArenaTeam::NotifyStatsChanged()
{
// This is called after a rated match ended
// Updates arena team stats for every member of the team (not only the ones who participated!)
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayerInOrOutOfWorld(itr->Guid))
SendStats(player->GetSession());
}
void ArenaTeam::Inspect(WorldSession* session, uint64 guid)
{
ArenaTeamMember* member = GetMember(guid);
if (!member)
return;
WorldPacket data(MSG_INSPECT_ARENA_TEAMS, 8+1+4*6);
data << uint64(guid); // player guid
data << uint8(GetSlot()); // slot (0...2)
data << uint32(GetId()); // arena team id
data << uint32(Stats.Rating); // rating
data << uint32(Stats.SeasonGames); // season played
data << uint32(Stats.SeasonWins); // season wins
data << uint32(member->SeasonGames); // played (count of all games, that the inspected member participated...)
data << uint32(member->PersonalRating); // personal rating
session->SendPacket(&data);
}
void ArenaTeamMember::ModifyPersonalRating(Player* player, int32 mod, uint32 type)
{
if (int32(PersonalRating) + mod < 0)
PersonalRating = 0;
else
PersonalRating += mod;
if (player)
{
player->SetArenaTeamInfoField(ArenaTeam::GetSlotByType(type), ARENA_TEAM_PERSONAL_RATING, PersonalRating);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING, PersonalRating, type);
}
}
void ArenaTeamMember::ModifyMatchmakerRating(int32 mod, uint32 /*slot*/)
{
if (mod < 0)
{
// pussywizard: prevent lowering MMR too much from max achieved MMR
int32 maxAllowedDrop = (int32)sWorld->getIntConfig(CONFIG_MAX_ALLOWED_MMR_DROP);
mod = std::min<int32>(std::max<int32>(-((int32)MatchMakerRating - (int32)MaxMMR + maxAllowedDrop), mod), 0);
}
if (int32(MatchMakerRating) + mod < 0)
MatchMakerRating = 0;
else
MatchMakerRating += mod;
if (MatchMakerRating > MaxMMR)
MaxMMR = MatchMakerRating;
}
void ArenaTeam::BroadcastPacket(WorldPacket* packet)
{
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayerInOrOutOfWorld(itr->Guid))
player->GetSession()->SendPacket(packet);
}
void ArenaTeam::BroadcastEvent(ArenaTeamEvents event, uint64 guid, uint8 strCount, std::string const& str1, std::string const& str2, std::string const& str3)
{
WorldPacket data(SMSG_ARENA_TEAM_EVENT, 1+1+1);
data << uint8(event);
data << uint8(strCount);
switch (strCount)
{
case 0:
break;
case 1:
data << str1;
break;
case 2:
data << str1 << str2;
break;
case 3:
data << str1 << str2 << str3;
break;
default:
sLog->outError("Unhandled strCount %u in ArenaTeam::BroadcastEvent", strCount);
return;
}
if (guid)
data << uint64(guid);
BroadcastPacket(&data);
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_ARENA_TEAM_EVENT");
}
void ArenaTeam::MassInviteToEvent(WorldSession* session)
{
WorldPacket data(SMSG_CALENDAR_ARENA_TEAM, (Members.size() - 1) * (4 + 8 + 1));
data << uint32(Members.size() - 1);
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
if (itr->Guid != session->GetPlayer()->GetGUID())
{
data.appendPackGUID(itr->Guid);
data << uint8(0); // unk
}
}
session->SendPacket(&data);
}
uint8 ArenaTeam::GetSlotByType(uint32 type)
{
switch (type)
{
case ARENA_TEAM_2v2: return 0;
case ARENA_TEAM_3v3: return 1;
case ARENA_TEAM_5v5: return 2;
default:
break;
}
sLog->outError("FATAL: Unknown arena team type %u for some arena team", type);
return 0xFF;
}
bool ArenaTeam::IsMember(uint64 guid) const
{
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (itr->Guid == guid)
return true;
return false;
}
uint32 ArenaTeam::GetPoints(uint32 memberRating)
{
// Returns how many points would be awarded with this team type with this rating
float points;
uint32 rating = memberRating + 150 < Stats.Rating ? memberRating : Stats.Rating;
if (rating <= 1500)
{
if (sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) < 6)
points = (float)rating * 0.22f + 14.0f;
else
points = 344;
}
else
points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating));
// Type penalties for teams < 5v5
if (Type == ARENA_TEAM_2v2)
points *= 0.76f;
else if (Type == ARENA_TEAM_3v3)
points *= 0.88f;
points *= sWorld->getRate(RATE_ARENA_POINTS);
return (uint32) points;
}
uint32 ArenaTeam::GetAverageMMR(Group* group) const
{
if (!group)
return 0;
uint32 matchMakerRating = 0;
uint32 playerDivider = 0;
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
// Skip if player is not online
if (!ObjectAccessor::FindPlayerInOrOutOfWorld(itr->Guid))
continue;
// Skip if player is not member of group
if (!group->IsMember(itr->Guid))
continue;
matchMakerRating += itr->MatchMakerRating;
++playerDivider;
}
// x/0 = crash
if (playerDivider == 0)
playerDivider = 1;
matchMakerRating /= playerDivider;
return matchMakerRating;
}
float ArenaTeam::GetChanceAgainst(uint32 ownRating, uint32 opponentRating)
{
// Returns the chance to win against a team with the given rating, used in the rating adjustment calculation
// ELO system
return 1.0f / (1.0f + exp(log(10.0f) * (float)((float)opponentRating - (float)ownRating) / 650.0f));
}
int32 ArenaTeam::GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won /*, float& confidence_factor*/)
{
// 'Chance' calculation - to beat the opponent
// This is a simulation. Not much info on how it really works
float chance = GetChanceAgainst(ownRating, opponentRating);
float won_mod = (won) ? 1.0f : 0.0f;
float mod = won_mod - chance;
// Work in progress:
/*
// This is a simulation, as there is not much info on how it really works
float confidence_mod = min(1.0f - fabs(mod), 0.5f);
// Apply confidence factor to the mod:
mod *= confidence_factor
// And only after that update the new confidence factor
confidence_factor -= ((confidence_factor - 1.0f) * confidence_mod) / confidence_factor;
*/
// Real rating modification
mod *= 24.0f;
return (int32)ceil(mod);
}
int32 ArenaTeam::GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won /*, float confidence_factor*/)
{
// 'Chance' calculation - to beat the opponent
// This is a simulation. Not much info on how it really works
float chance = GetChanceAgainst(ownRating, opponentRating);
float won_mod = (won) ? 1.0f : 0.0f;
// Calculate the rating modification
float mod;
// TODO: Replace this hack with using the confidence factor (limiting the factor to 2.0f)
if (won && ownRating < 1300)
{
if (ownRating < 1000)
mod = 48.0f * (won_mod - chance);
else
mod = (24.0f + (24.0f * (1300.0f - float(ownRating)) / 300.0f)) * (won_mod - chance);
}
else
mod = 24.0f * (won_mod - chance);
return (int32)ceil(mod);
}
void ArenaTeam::FinishGame(int32 mod, const Map* bgMap)
{
// Rating can only drop to 0
if (int32(Stats.Rating) + mod < 0)
Stats.Rating = 0;
else
{
Stats.Rating += mod;
// Check if rating related achivements are met
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (Player* member = ObjectAccessor::FindPlayerInOrOutOfWorld(itr->Guid))
if (member->FindMap() == bgMap)
member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING, Stats.Rating, Type);
}
// Update number of games played per season or week
Stats.WeekGames += 1;
Stats.SeasonGames += 1;
// Update team's rank, start with rank 1 and increase until no team with more rating was found
Stats.Rank = 1;
ArenaTeamMgr::ArenaTeamContainer::const_iterator i = sArenaTeamMgr->GetArenaTeamMapBegin();
for (; i != sArenaTeamMgr->GetArenaTeamMapEnd(); ++i)
{
if (i->second->GetType() == Type && i->second->GetStats().Rating > Stats.Rating)
++Stats.Rank;
}
}
int32 ArenaTeam::WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change, const Map* bgMap)
{
// Called when the team has won
// Change in Matchmaker rating
int32 mod = GetMatchmakerRatingMod(Own_MMRating, Opponent_MMRating, true);
// Change in Team Rating
rating_change = GetRatingMod(Stats.Rating, Opponent_MMRating, true);
// Modify the team stats accordingly
FinishGame(rating_change, bgMap);
// Update number of wins per season and week
Stats.WeekWins += 1;
Stats.SeasonWins += 1;
// Return the rating change, used to display it on the results screen
return mod;
}
int32 ArenaTeam::LostAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change, const Map* bgMap)
{
// Called when the team has lost
// Change in Matchmaker Rating
int32 mod = GetMatchmakerRatingMod(Own_MMRating, Opponent_MMRating, false);
// Change in Team Rating
rating_change = GetRatingMod(Stats.Rating, Opponent_MMRating, false);
// Modify the team stats accordingly
FinishGame(rating_change, bgMap);
// return the rating change, used to display it on the results screen
return mod;
}
void ArenaTeam::MemberLost(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange)
{
// Called for each participant of a match after losing
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
if (itr->Guid == player->GetGUID())
{
// Update personal rating
int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, false);
itr->ModifyPersonalRating(player, mod, GetType());
// Update matchmaker rating
itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot());
// Update personal played stats
itr->WeekGames +=1;
itr->SeasonGames +=1;
// update the unit fields
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_WEEK, itr->WeekGames);
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_SEASON, itr->SeasonGames);
return;
}
}
}
void ArenaTeam::MemberWon(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange)
{
// called for each participant after winning a match
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
if (itr->Guid == player->GetGUID())
{
// update personal rating
int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, true);
itr->ModifyPersonalRating(player, mod, GetType());
// update matchmaker rating (pussywizard: but don't allow it to go over team rating)
if (itr->MatchMakerRating < Stats.Rating)
{
mod = std::min(MatchmakerRatingChange, Stats.Rating - itr->MatchMakerRating);
itr->ModifyMatchmakerRating(mod, GetSlot());
}
// update personal stats
itr->WeekGames +=1;
itr->SeasonGames +=1;
itr->SeasonWins += 1;
itr->WeekWins += 1;
// update unit fields
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_WEEK, itr->WeekGames);
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_SEASON, itr->SeasonGames);
return;
}
}
}
void ArenaTeam::UpdateArenaPointsHelper(std::map<uint32, uint32>& playerPoints)
{
// Called after a match has ended and the stats are already modified
// Helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons)
// 10 played games per week is a minimum
if (Stats.WeekGames < 10)
return;
// To get points, a player has to participate in at least 30% of the matches
uint32 requiredGames = (uint32)ceil(Stats.WeekGames * 0.3f);
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
// The player participated in enough games, update his points
uint32 pointsToAdd = 0;
if (itr->WeekGames >= requiredGames)
pointsToAdd = GetPoints(itr->PersonalRating);
std::map<uint32, uint32>::iterator plr_itr = playerPoints.find(GUID_LOPART(itr->Guid));
if (plr_itr != playerPoints.end())
{
// Check if there is already more points
if (plr_itr->second < pointsToAdd)
playerPoints[GUID_LOPART(itr->Guid)] = pointsToAdd;
}
else
playerPoints[GUID_LOPART(itr->Guid)] = pointsToAdd;
}
}
void ArenaTeam::SaveToDB()
{
// Save team and member stats to db
// Called after a match has ended or when calculating arena_points
SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ARENA_TEAM_STATS);
stmt->setUInt16(0, Stats.Rating);
stmt->setUInt16(1, Stats.WeekGames);
stmt->setUInt16(2, Stats.WeekWins);
stmt->setUInt16(3, Stats.SeasonGames);
stmt->setUInt16(4, Stats.SeasonWins);
stmt->setUInt32(5, Stats.Rank);
stmt->setUInt32(6, GetId());
trans->Append(stmt);
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ARENA_TEAM_MEMBER);
stmt->setUInt16(0, itr->PersonalRating);
stmt->setUInt16(1, itr->WeekGames);
stmt->setUInt16(2, itr->WeekWins);
stmt->setUInt16(3, itr->SeasonGames);
stmt->setUInt16(4, itr->SeasonWins);
stmt->setUInt32(5, GetId());
stmt->setUInt32(6, GUID_LOPART(itr->Guid));
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CHARACTER_ARENA_STATS);
stmt->setUInt32(0, GUID_LOPART(itr->Guid));
stmt->setUInt8(1, GetSlot());
stmt->setUInt16(2, itr->MatchMakerRating);
stmt->setUInt16(3, itr->MaxMMR);
trans->Append(stmt);
}
CharacterDatabase.CommitTransaction(trans);
}
void ArenaTeam::FinishWeek()
{
// Reset team stats
Stats.WeekGames = 0;
Stats.WeekWins = 0;
// Reset member stats
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
itr->WeekGames = 0;
itr->WeekWins = 0;
}
}
bool ArenaTeam::IsFighting() const
{
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(itr->Guid))
if (player->GetMap()->IsBattleArena())
return true;
return false;
}
ArenaTeamMember* ArenaTeam::GetMember(const std::string& name)
{
return GetMember(sObjectMgr->GetPlayerGUIDByName(name));
}
ArenaTeamMember* ArenaTeam::GetMember(uint64 guid)
{
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (itr->Guid == guid)
return &(*itr);
return NULL;
}

View File

@@ -1,205 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AZEROTHCORE_ARENATEAM_H
#define AZEROTHCORE_ARENATEAM_H
#include "QueryResult.h"
#include "Map.h"
#include <ace/Singleton.h>
#include <list>
#include <map>
class WorldSession;
class WorldPacket;
class Player;
class Group;
enum ArenaTeamCommandTypes
{
ERR_ARENA_TEAM_CREATE_S = 0x00,
ERR_ARENA_TEAM_INVITE_SS = 0x01,
ERR_ARENA_TEAM_QUIT_S = 0x03,
ERR_ARENA_TEAM_FOUNDER_S = 0x0E
};
enum ArenaTeamCommandErrors
{
ERR_ARENA_TEAM_INTERNAL = 0x01,
ERR_ALREADY_IN_ARENA_TEAM = 0x02,
ERR_ALREADY_IN_ARENA_TEAM_S = 0x03,
ERR_INVITED_TO_ARENA_TEAM = 0x04,
ERR_ALREADY_INVITED_TO_ARENA_TEAM_S = 0x05,
ERR_ARENA_TEAM_NAME_INVALID = 0x06,
ERR_ARENA_TEAM_NAME_EXISTS_S = 0x07,
ERR_ARENA_TEAM_LEADER_LEAVE_S = 0x08,
ERR_ARENA_TEAM_PERMISSIONS = 0x08,
ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM = 0x09,
ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM_SS = 0x0A,
ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S = 0x0B,
ERR_ARENA_TEAM_NOT_ALLIED = 0x0C,
ERR_ARENA_TEAM_IGNORING_YOU_S = 0x13,
ERR_ARENA_TEAM_TARGET_TOO_LOW_S = 0x15,
ERR_ARENA_TEAM_TARGET_TOO_HIGH_S = 0x16,
ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S = 0x17,
ERR_ARENA_TEAM_NOT_FOUND = 0x1B,
ERR_ARENA_TEAMS_LOCKED = 0x1E
};
enum ArenaTeamEvents
{
ERR_ARENA_TEAM_JOIN_SS = 3, // player name + arena team name
ERR_ARENA_TEAM_LEAVE_SS = 4, // player name + arena team name
ERR_ARENA_TEAM_REMOVE_SSS = 5, // player name + arena team name + captain name
ERR_ARENA_TEAM_LEADER_IS_SS = 6, // player name + arena team name
ERR_ARENA_TEAM_LEADER_CHANGED_SSS = 7, // old captain + new captain + arena team name
ERR_ARENA_TEAM_DISBANDED_S = 8 // captain name + arena team name
};
/*
need info how to send these ones:
ERR_ARENA_TEAM_YOU_JOIN_S - client show it automatically when accept invite
ERR_ARENA_TEAM_TARGET_TOO_LOW_S
ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S
ERR_ARENA_TEAM_LEVEL_TOO_LOW_I
*/
enum ArenaTeamTypes
{
ARENA_TEAM_2v2 = 2,
ARENA_TEAM_3v3 = 3,
ARENA_TEAM_5v5 = 5
};
struct ArenaTeamMember
{
uint64 Guid;
//std::string Name;
uint8 Class;
uint16 WeekGames;
uint16 WeekWins;
uint16 SeasonGames;
uint16 SeasonWins;
uint16 PersonalRating;
uint16 MatchMakerRating;
uint16 MaxMMR;
void ModifyPersonalRating(Player* player, int32 mod, uint32 type);
void ModifyMatchmakerRating(int32 mod, uint32 slot);
};
struct ArenaTeamStats
{
uint16 Rating;
uint16 WeekGames;
uint16 WeekWins;
uint16 SeasonGames;
uint16 SeasonWins;
uint32 Rank;
};
#define MAX_ARENA_SLOT 3 // 0..2 slots
class ArenaTeam
{
public:
ArenaTeam();
~ArenaTeam();
bool Create(uint64 captainGuid, uint8 type, std::string const& teamName, uint32 backgroundColor, uint8 emblemStyle, uint32 emblemColor, uint8 borderStyle, uint32 borderColor);
void Disband(WorldSession* session);
typedef std::list<ArenaTeamMember> MemberList;
uint32 GetId() const { return TeamId; }
uint32 GetType() const { return Type; }
uint8 GetSlot() const { return GetSlotByType(GetType()); }
static uint8 GetSlotByType(uint32 type);
uint64 GetCaptain() const { return CaptainGuid; }
std::string const& GetName() const { return TeamName; }
const ArenaTeamStats& GetStats() const { return Stats; }
uint32 GetRating() const { return Stats.Rating; }
uint32 GetAverageMMR(Group* group) const;
void SetCaptain(uint64 guid);
bool AddMember(uint64 playerGuid);
// Shouldn't be uint64 ed, because than can reference guid from members on Disband
// and this method removes given record from list. So invalid reference can happen.
void DelMember(uint64 guid, bool cleanDb);
size_t GetMembersSize() const { return Members.size(); }
bool Empty() const { return Members.empty(); }
MemberList::iterator m_membersBegin() { return Members.begin(); }
MemberList::iterator m_membersEnd() { return Members.end(); }
bool IsMember(uint64 guid) const;
ArenaTeamMember* GetMember(uint64 guid);
ArenaTeamMember* GetMember(std::string const& name);
bool IsFighting() const;
bool LoadArenaTeamFromDB(QueryResult arenaTeamDataResult);
bool LoadMembersFromDB(QueryResult arenaTeamMembersResult);
void LoadStatsFromDB(uint32 ArenaTeamId);
void SaveToDB();
void BroadcastPacket(WorldPacket* packet);
void BroadcastEvent(ArenaTeamEvents event, uint64 guid, uint8 strCount, std::string const& str1, std::string const& str2, std::string const& str3);
void NotifyStatsChanged();
void MassInviteToEvent(WorldSession* session);
void Roster(WorldSession* session);
void Query(WorldSession* session);
void SendStats(WorldSession* session);
void Inspect(WorldSession* session, uint64 guid);
uint32 GetPoints(uint32 MemberRating);
int32 GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
int32 GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
float GetChanceAgainst(uint32 ownRating, uint32 opponentRating);
int32 WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change, const Map* bgMap);
void MemberWon(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange);
int32 LostAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change, const Map* bgMap);
void MemberLost(Player* player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange = -12);
void UpdateArenaPointsHelper(std::map<uint32, uint32> & PlayerPoints);
void FinishWeek();
void FinishGame(int32 mod, const Map* bgMap);
protected:
uint32 TeamId;
uint8 Type;
std::string TeamName;
uint64 CaptainGuid;
uint32 BackgroundColor; // ARGB format
uint8 EmblemStyle; // icon id
uint32 EmblemColor; // ARGB format
uint8 BorderStyle; // border image id
uint32 BorderColor; // ARGB format
MemberList Members;
ArenaTeamStats Stats;
};
#endif

View File

@@ -1,195 +0,0 @@
/*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Define.h"
#include "ArenaTeamMgr.h"
#include "World.h"
#include "Log.h"
#include "DatabaseEnv.h"
#include "Language.h"
#include "ObjectAccessor.h"
#include "Player.h"
ArenaTeamMgr::ArenaTeamMgr()
{
NextArenaTeamId = 1;
LastArenaLogId = 0;
}
ArenaTeamMgr::~ArenaTeamMgr()
{
for (ArenaTeamContainer::iterator itr = ArenaTeamStore.begin(); itr != ArenaTeamStore.end(); ++itr)
delete itr->second;
}
// Arena teams collection
ArenaTeam* ArenaTeamMgr::GetArenaTeamById(uint32 arenaTeamId) const
{
ArenaTeamContainer::const_iterator itr = ArenaTeamStore.find(arenaTeamId);
if (itr != ArenaTeamStore.end())
return itr->second;
return NULL;
}
ArenaTeam* ArenaTeamMgr::GetArenaTeamByName(const std::string& arenaTeamName) const
{
std::string search = arenaTeamName;
std::transform(search.begin(), search.end(), search.begin(), ::toupper);
for (ArenaTeamContainer::const_iterator itr = ArenaTeamStore.begin(); itr != ArenaTeamStore.end(); ++itr)
{
std::string teamName = itr->second->GetName();
std::transform(teamName.begin(), teamName.end(), teamName.begin(), ::toupper);
if (search == teamName)
return itr->second;
}
return NULL;
}
ArenaTeam* ArenaTeamMgr::GetArenaTeamByCaptain(uint64 guid) const
{
for (ArenaTeamContainer::const_iterator itr = ArenaTeamStore.begin(); itr != ArenaTeamStore.end(); ++itr)
if (itr->second->GetCaptain() == guid)
return itr->second;
return NULL;
}
void ArenaTeamMgr::AddArenaTeam(ArenaTeam* arenaTeam)
{
ArenaTeamStore[arenaTeam->GetId()] = arenaTeam;
}
void ArenaTeamMgr::RemoveArenaTeam(uint32 arenaTeamId)
{
ArenaTeamStore.erase(arenaTeamId);
}
uint32 ArenaTeamMgr::GenerateArenaTeamId()
{
if (NextArenaTeamId >= 0xFFFFFFFE)
{
sLog->outError("Arena team ids overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
return NextArenaTeamId++;
}
void ArenaTeamMgr::LoadArenaTeams()
{
uint32 oldMSTime = getMSTime();
// Clean out the trash before loading anything
CharacterDatabase.Execute("DELETE FROM arena_team_member WHERE arenaTeamId NOT IN (SELECT arenaTeamId FROM arena_team)"); // One-time query
// 0 1 2 3 4 5 6 7 8
QueryResult result = CharacterDatabase.Query("SELECT arenaTeamId, name, captainGuid, type, backgroundColor, emblemStyle, emblemColor, borderStyle, borderColor, "
// 9 10 11 12 13 14
"rating, weekGames, weekWins, seasonGames, seasonWins, rank FROM arena_team ORDER BY arenaTeamId ASC");
if (!result)
{
sLog->outString(">> Loaded 0 arena teams. DB table `arena_team` is empty!");
sLog->outString();
return;
}
QueryResult result2 = CharacterDatabase.Query(
// 0 1 2 3 4 5 6 7 8 9 10
"SELECT arenaTeamId, atm.guid, atm.weekGames, atm.weekWins, atm.seasonGames, atm.seasonWins, c.name, class, personalRating, matchMakerRating, maxMMR FROM arena_team_member atm"
" INNER JOIN arena_team ate USING (arenaTeamId)"
" LEFT JOIN characters AS c ON atm.guid = c.guid"
" LEFT JOIN character_arena_stats AS cas ON c.guid = cas.guid AND (cas.slot = 0 AND ate.type = 2 OR cas.slot = 1 AND ate.type = 3 OR cas.slot = 2 AND ate.type = 5)"
" ORDER BY atm.arenateamid ASC");
uint32 count = 0;
do
{
ArenaTeam* newArenaTeam = new ArenaTeam;
if (!newArenaTeam->LoadArenaTeamFromDB(result) || !newArenaTeam->LoadMembersFromDB(result2))
{
newArenaTeam->Disband(NULL);
delete newArenaTeam;
continue;
}
AddArenaTeam(newArenaTeam);
++count;
}
while (result->NextRow());
sLog->outString(">> Loaded %u arena teams in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
sLog->outString();
}
void ArenaTeamMgr::DistributeArenaPoints()
{
// Used to distribute arena points based on last week's stats
sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_START);
sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_START);
// Temporary structure for storing maximum points to add values for all players
std::map<uint32, uint32> PlayerPoints;
// At first update all points for all team members
for (ArenaTeamContainer::iterator teamItr = GetArenaTeamMapBegin(); teamItr != GetArenaTeamMapEnd(); ++teamItr)
if (ArenaTeam* at = teamItr->second)
at->UpdateArenaPointsHelper(PlayerPoints);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt;
// Cycle that gives points to all players
for (std::map<uint32, uint32>::iterator playerItr = PlayerPoints.begin(); playerItr != PlayerPoints.end(); ++playerItr)
{
// Add points to player if online
if (Player* player = HashMapHolder<Player>::Find(playerItr->first))
player->ModifyArenaPoints(playerItr->second, &trans);
else // Update database
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ARENA_POINTS);
stmt->setUInt32(0, playerItr->second);
stmt->setUInt32(1, playerItr->first);
trans->Append(stmt);
}
}
CharacterDatabase.CommitTransaction(trans);
PlayerPoints.clear();
sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_END);
sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_START);
for (ArenaTeamContainer::iterator titr = GetArenaTeamMapBegin(); titr != GetArenaTeamMapEnd(); ++titr)
{
if (ArenaTeam* at = titr->second)
{
at->FinishWeek();
at->SaveToDB();
at->NotifyStatsChanged();
}
}
sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_END);
sWorld->SendWorldText(LANG_DIST_ARENA_POINTS_END);
}

View File

@@ -1,59 +0,0 @@
/*
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ARENATEAMMGR_H
#define _ARENATEAMMGR_H
#include "ArenaTeam.h"
class ArenaTeamMgr
{
friend class ACE_Singleton<ArenaTeamMgr, ACE_Null_Mutex>;
ArenaTeamMgr();
~ArenaTeamMgr();
public:
typedef UNORDERED_MAP<uint32, ArenaTeam*> ArenaTeamContainer;
ArenaTeam* GetArenaTeamById(uint32 arenaTeamId) const;
ArenaTeam* GetArenaTeamByName(std::string const& arenaTeamName) const;
ArenaTeam* GetArenaTeamByCaptain(uint64 guid) const;
void LoadArenaTeams();
void AddArenaTeam(ArenaTeam* arenaTeam);
void RemoveArenaTeam(uint32 Id);
ArenaTeamContainer::iterator GetArenaTeamMapBegin() { return ArenaTeamStore.begin(); }
ArenaTeamContainer::iterator GetArenaTeamMapEnd() { return ArenaTeamStore.end(); }
void DistributeArenaPoints();
uint32 GenerateArenaTeamId();
void SetNextArenaTeamId(uint32 Id) { NextArenaTeamId = Id; }
uint32 GetNextArenaLogId() { return ++LastArenaLogId; }
void SetLastArenaLogId(uint32 id) { LastArenaLogId = id; }
protected:
uint32 NextArenaTeamId;
ArenaTeamContainer ArenaTeamStore;
uint32 LastArenaLogId;
};
#define sArenaTeamMgr ACE_Singleton<ArenaTeamMgr, ACE_Null_Mutex>::instance()
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,764 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUND_H
#define __BATTLEGROUND_H
#include "Common.h"
#include "SharedDefines.h"
#include "DBCEnums.h"
#include "GameObject.h"
class Creature;
class GameObject;
class Group;
class Player;
class WorldPacket;
class BattlegroundMap;
class BattlegroundAV;
class BattlegroundWS;
class BattlegroundAB;
class BattlegroundNA;
class BattlegroundBE;
class BattlegroundEY;
class BattlegroundRL;
class BattlegroundSA;
class BattlegroundDS;
class BattlegroundRV;
class BattlegroundIC;
struct PvPDifficultyEntry;
struct WorldSafeLocsEntry;
enum BattlegroundDesertionType
{
BG_DESERTION_TYPE_LEAVE_BG = 0, // player leaves the BG
BG_DESERTION_TYPE_OFFLINE = 1, // player is kicked from BG because offline
BG_DESERTION_TYPE_LEAVE_QUEUE = 2, // player is invited to join and refuses to do it
BG_DESERTION_TYPE_NO_ENTER_BUTTON = 3, // player is invited to join and do nothing (time expires)
BG_DESERTION_TYPE_INVITE_LOGOUT = 4, // player is invited to join and logs out
};
enum BattlegroundSounds
{
SOUND_HORDE_WINS = 8454,
SOUND_ALLIANCE_WINS = 8455,
SOUND_BG_START = 3439,
SOUND_BG_START_L70ETC = 11803,
};
enum BattlegroundQuests
{
SPELL_WS_QUEST_REWARD = 43483,
SPELL_AB_QUEST_REWARD = 43484,
SPELL_AV_QUEST_REWARD = 43475,
SPELL_AV_QUEST_KILLED_BOSS = 23658,
SPELL_EY_QUEST_REWARD = 43477,
SPELL_SA_QUEST_REWARD = 61213,
SPELL_AB_QUEST_REWARD_4_BASES = 24061,
SPELL_AB_QUEST_REWARD_5_BASES = 24064
};
enum BattlegroundMarks
{
SPELL_WS_MARK_LOSER = 24950,
SPELL_WS_MARK_WINNER = 24951,
SPELL_AB_MARK_LOSER = 24952,
SPELL_AB_MARK_WINNER = 24953,
SPELL_AV_MARK_LOSER = 24954,
SPELL_AV_MARK_WINNER = 24955,
SPELL_SA_MARK_WINNER = 61160,
SPELL_SA_MARK_LOSER = 61159,
SPELL_WG_MARK_WINNER = 56902,
ITEM_AV_MARK_OF_HONOR = 20560,
ITEM_WS_MARK_OF_HONOR = 20558,
ITEM_AB_MARK_OF_HONOR = 20559,
ITEM_EY_MARK_OF_HONOR = 29024,
ITEM_SA_MARK_OF_HONOR = 42425,
ITEM_IC_MARK_OF_HONOR = 47395,
};
enum BattlegroundMarksCount
{
ITEM_WINNER_COUNT = 3,
ITEM_LOSER_COUNT = 1
};
enum BattlegroundCreatures
{
BG_CREATURE_ENTRY_A_SPIRITGUIDE = 13116, // alliance
BG_CREATURE_ENTRY_H_SPIRITGUIDE = 13117, // horde
};
enum BattlegroundSpells
{
SPELL_WAITING_FOR_RESURRECT = 2584, // Waiting to Resurrect
SPELL_SPIRIT_HEAL_CHANNEL = 22011, // Spirit Heal Channel
SPELL_SPIRIT_HEAL = 22012, // Spirit Heal
SPELL_RESURRECTION_VISUAL = 24171, // Resurrection Impact Visual
SPELL_ARENA_PREPARATION = 32727, // use this one, 32728 not correct
SPELL_ALLIANCE_GOLD_FLAG = 32724,
SPELL_ALLIANCE_GREEN_FLAG = 32725,
SPELL_HORDE_GOLD_FLAG = 35774,
SPELL_HORDE_GREEN_FLAG = 35775,
SPELL_PREPARATION = 44521, // Preparation
SPELL_SPIRIT_HEAL_MANA = 44535, // Spirit Heal
SPELL_RECENTLY_DROPPED_FLAG = 42792, // Recently Dropped Flag
SPELL_AURA_PLAYER_INACTIVE = 43681, // Inactive
SPELL_HONORABLE_DEFENDER_25Y = 68652, // +50% honor when standing at a capture point that you control, 25yards radius (added in 3.2)
SPELL_HONORABLE_DEFENDER_60Y = 66157, // +50% honor when standing at a capture point that you control, 60yards radius (added in 3.2), probably for 40+ player battlegrounds
SPELL_THE_LAST_STANDING = 26549, // Arena achievement related
};
enum BattlegroundReputations
{
BG_REP_AV_HORDE = 729,
BG_REP_AV_ALLIANCE = 730,
BG_REP_AB_HORDE = 510,
BG_REP_AB_ALLIANCE = 509,
BG_REP_WS_HORDE = 889,
BG_REP_WS_ALLIANCE = 890,
};
enum BattlegroundTimeIntervals
{
CHECK_PLAYER_POSITION_INVERVAL = 9000, // ms
RESURRECTION_INTERVAL = 30000, // ms
//REMIND_INTERVAL = 10000, // ms
INVITATION_REMIND_TIME = 20000, // ms
INVITE_ACCEPT_WAIT_TIME = 60000, // ms
TIME_TO_AUTOREMOVE = 120000, // ms
MAX_OFFLINE_TIME = 300, // secs
RESPAWN_ONE_DAY = 86400, // secs
RESPAWN_IMMEDIATELY = 0, // secs
BUFF_RESPAWN_TIME = 180, // secs
};
enum BattlegroundStartTimeIntervals
{
BG_START_DELAY_2M = 120000, // ms (2 minutes)
BG_START_DELAY_1M = 60000, // ms (1 minute)
BG_START_DELAY_30S = 30000, // ms (30 seconds)
BG_START_DELAY_15S = 15000, // ms (15 seconds) Used only in arena
BG_START_DELAY_NONE = 0, // ms
};
#define BATTLEGROUND_UPDATE_INTERVAL 1000
enum BattlegroundBuffObjects
{
BG_OBJECTID_SPEEDBUFF_ENTRY = 179871,
BG_OBJECTID_REGENBUFF_ENTRY = 179904,
BG_OBJECTID_BERSERKERBUFF_ENTRY = 179905
};
enum BattlegroundRandomRewards
{
BG_REWARD_WINNER_HONOR_FIRST = 30,
BG_REWARD_WINNER_ARENA_FIRST = 25,
BG_REWARD_WINNER_HONOR_LAST = 15,
BG_REWARD_WINNER_ARENA_LAST = 0,
BG_REWARD_LOSER_HONOR_FIRST = 5,
BG_REWARD_LOSER_HONOR_LAST = 5
};
const uint32 Buff_Entries[3] = { BG_OBJECTID_SPEEDBUFF_ENTRY, BG_OBJECTID_REGENBUFF_ENTRY, BG_OBJECTID_BERSERKERBUFF_ENTRY };
enum BattlegroundStatus
{
STATUS_NONE = 0, // first status, should mean bg is not instance
STATUS_WAIT_QUEUE = 1, // means bg is empty and waiting for queue
STATUS_WAIT_JOIN = 2, // this means, that BG has already started and it is waiting for more players
STATUS_IN_PROGRESS = 3, // means bg is running
STATUS_WAIT_LEAVE = 4 // means some faction has won BG and it is ending
};
enum BattlegroundTeams
{
BG_TEAMS_COUNT = 2
};
struct BattlegroundObjectInfo
{
BattlegroundObjectInfo() : object(NULL), timer(0), spellid(0) {}
GameObject *object;
int32 timer;
uint32 spellid;
};
enum ScoreType
{
SCORE_KILLING_BLOWS = 1,
SCORE_DEATHS = 2,
SCORE_HONORABLE_KILLS = 3,
SCORE_BONUS_HONOR = 4,
//EY, but in MSG_PVP_LOG_DATA opcode!
SCORE_DAMAGE_DONE = 5,
SCORE_HEALING_DONE = 6,
//WS
SCORE_FLAG_CAPTURES = 7,
SCORE_FLAG_RETURNS = 8,
//AB and IC
SCORE_BASES_ASSAULTED = 9,
SCORE_BASES_DEFENDED = 10,
//AV
SCORE_GRAVEYARDS_ASSAULTED = 11,
SCORE_GRAVEYARDS_DEFENDED = 12,
SCORE_TOWERS_ASSAULTED = 13,
SCORE_TOWERS_DEFENDED = 14,
SCORE_MINES_CAPTURED = 15,
SCORE_LEADERS_KILLED = 16,
SCORE_SECONDARY_OBJECTIVES = 17,
//SOTA
SCORE_DESTROYED_DEMOLISHER = 18,
SCORE_DESTROYED_WALL = 19,
};
enum ArenaType
{
ARENA_TYPE_2v2 = 2,
ARENA_TYPE_3v3 = 3,
ARENA_TYPE_5v5 = 5
};
enum BattlegroundType
{
TYPE_BATTLEGROUND = 3,
TYPE_ARENA = 4
};
enum BattlegroundStartingEvents
{
BG_STARTING_EVENT_NONE = 0x00,
BG_STARTING_EVENT_1 = 0x01,
BG_STARTING_EVENT_2 = 0x02,
BG_STARTING_EVENT_3 = 0x04,
BG_STARTING_EVENT_4 = 0x08
};
enum BattlegroundStartingEventsIds
{
BG_STARTING_EVENT_FIRST = 0,
BG_STARTING_EVENT_SECOND = 1,
BG_STARTING_EVENT_THIRD = 2,
BG_STARTING_EVENT_FOURTH = 3
};
#define BG_STARTING_EVENT_COUNT 4
struct BattlegroundScore
{
BattlegroundScore(Player* player) : KillingBlows(0), Deaths(0), HonorableKills(0), BonusHonor(0),
DamageDone(0), HealingDone(0), player(player)
{ }
virtual ~BattlegroundScore() { } //virtual destructor is used when deleting score from scores map
uint32 KillingBlows;
uint32 Deaths;
uint32 HonorableKills;
uint32 BonusHonor;
uint32 DamageDone;
uint32 HealingDone;
Player* player;
uint32 GetKillingBlows() const { return KillingBlows; }
uint32 GetDeaths() const { return Deaths; }
uint32 GetHonorableKills() const { return HonorableKills; }
uint32 GetBonusHonor() const { return BonusHonor; }
uint32 GetDamageDone() const { return DamageDone; }
uint32 GetHealingDone() const { return HealingDone; }
virtual uint32 GetAttr1() const { return 0; }
virtual uint32 GetAttr2() const { return 0; }
virtual uint32 GetAttr3() const { return 0; }
virtual uint32 GetAttr4() const { return 0; }
virtual uint32 GetAttr5() const { return 0; }
};
class ArenaLogEntryData
{
public:
ArenaLogEntryData() : Guid(0), ArenaTeamId(0), DamageDone(0), HealingDone(0), KillingBlows(0) {}
void Fill(const char* name, uint32 guid, uint32 acc, uint32 arenaTeamId, std::string ip)
{
Name = std::string(name);
Guid = guid;
Acc = acc;
ArenaTeamId = arenaTeamId;
IP = ip;
}
std::string Name;
uint32 Guid;
uint32 Acc;
uint32 ArenaTeamId;
std::string IP;
uint32 DamageDone;
uint32 HealingDone;
uint32 KillingBlows;
};
enum BGHonorMode
{
BG_NORMAL = 0,
BG_HOLIDAY,
BG_HONOR_MODE_NUM
};
#define BG_AWARD_ARENA_POINTS_MIN_LEVEL 71
#define ARENA_TIMELIMIT_POINTS_LOSS -16
#define ARENA_READY_MARKER_ENTRY 301337
/*
This class is used to:
1. Add player to battleground
2. Remove player from battleground
3. some certain cases, same for all battlegrounds
4. It has properties same for all battlegrounds
*/
enum BattlegroundQueueInvitationType
{
BG_QUEUE_INVITATION_TYPE_NO_BALANCE = 0, // no balance: N+M vs N players
BG_QUEUE_INVITATION_TYPE_BALANCED = 1, // teams balanced: N+1 vs N players
BG_QUEUE_INVITATION_TYPE_EVEN = 2 // teams even: N vs N players
};
class Battleground
{
public:
Battleground();
virtual ~Battleground();
void Update(uint32 diff);
virtual bool SetupBattleground() // must be implemented in BG subclass
{
return true;
}
virtual void Init();
virtual void StartingEventCloseDoors() { }
virtual void StartingEventOpenDoors() { }
virtual void ResetBGSubclass() { } // must be implemented in BG subclass
virtual void DestroyGate(Player* /*player*/, GameObject* /*go*/) {}
/* achievement req. */
virtual bool AllNodesConrolledByTeam(TeamId /*teamId*/) const { return false; }
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry);
/* Battleground */
// Get methods:
char const* GetName() const { return m_Name; }
BattlegroundTypeId GetBgTypeID() const { return m_RealTypeID; }
uint32 GetInstanceID() const { return m_InstanceID; }
BattlegroundStatus GetStatus() const { return m_Status; }
uint32 GetClientInstanceID() const { return m_ClientInstanceID; }
uint32 GetStartTime() const { return m_StartTime; }
uint32 GetEndTime() const { return m_EndTime; }
uint32 GetLastResurrectTime() const { return m_LastResurrectTime; }
uint32 GetMinLevel() const { return m_LevelMin; }
uint32 GetMaxLevel() const { return m_LevelMax; }
uint32 GetMaxPlayersPerTeam() const { return m_MaxPlayersPerTeam; }
uint32 GetMinPlayersPerTeam() const { return m_MinPlayersPerTeam; }
int32 GetStartDelayTime() const { return m_StartDelayTime; }
uint8 GetArenaType() const { return m_ArenaType; }
TeamId GetWinner() const { return m_WinnerId; }
uint32 GetScriptId() const { return ScriptId; }
uint32 GetBonusHonorFromKill(uint32 kills) const;
// Set methods:
void SetName(char const* Name) { m_Name = Name; }
void SetBgTypeID(BattlegroundTypeId TypeID) { m_RealTypeID = TypeID; }
void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; }
void SetStatus(BattlegroundStatus Status) { m_Status = Status; }
void SetClientInstanceID(uint32 InstanceID) { m_ClientInstanceID = InstanceID; }
void SetStartTime(uint32 Time) { m_StartTime = Time; }
void SetEndTime(uint32 Time) { m_EndTime = Time; }
void SetLastResurrectTime(uint32 Time) { m_LastResurrectTime = Time; }
void SetLevelRange(uint32 min, uint32 max) { m_LevelMin = min; m_LevelMax = max; }
void SetRated(bool state) { m_IsRated = state; }
void SetArenaType(uint8 type) { m_ArenaType = type; }
void SetArenaorBGType(bool _isArena) { m_IsArena = _isArena; }
void SetWinner(TeamId winner) { m_WinnerId = winner; }
void SetScriptId(uint32 scriptId) { ScriptId = scriptId; }
void ModifyStartDelayTime(int32 diff) { m_StartDelayTime -= diff; }
void SetStartDelayTime(int32 Time) { m_StartDelayTime = Time; }
void SetMaxPlayersPerTeam(uint32 MaxPlayers) { m_MaxPlayersPerTeam = MaxPlayers; }
void SetMinPlayersPerTeam(uint32 MinPlayers) { m_MinPlayersPerTeam = MinPlayers; }
void DecreaseInvitedCount(TeamId teamId) { ASSERT(m_BgInvitedPlayers[teamId] > 0); --m_BgInvitedPlayers[teamId]; }
void IncreaseInvitedCount(TeamId teamId) { ++m_BgInvitedPlayers[teamId]; }
uint32 GetInvitedCount(TeamId teamId) const { return m_BgInvitedPlayers[teamId]; }
bool HasFreeSlots() const;
uint32 GetFreeSlotsForTeam(TeamId teamId) const;
uint32 GetMaxFreeSlots() const;
typedef std::set<Player*> SpectatorList;
typedef std::map<uint64, uint64> ToBeTeleportedMap;
void AddSpectator(Player* p) { m_Spectators.insert(p); }
void RemoveSpectator(Player* p) { m_Spectators.erase(p); }
bool HaveSpectators() { return !m_Spectators.empty(); }
const SpectatorList& GetSpectators() const { return m_Spectators; }
void AddToBeTeleported(uint64 spectator, uint64 participant) { m_ToBeTeleported[spectator] = participant; }
void RemoveToBeTeleported(uint64 spectator) { ToBeTeleportedMap::iterator itr = m_ToBeTeleported.find(spectator); if (itr != m_ToBeTeleported.end()) m_ToBeTeleported.erase(itr); }
void SpectatorsSendPacket(WorldPacket& data);
bool isArena() const { return m_IsArena; }
bool isBattleground() const { return !m_IsArena; }
bool isRated() const { return m_IsRated; }
typedef std::map<uint64, Player*> BattlegroundPlayerMap;
BattlegroundPlayerMap const& GetPlayers() const { return m_Players; }
uint32 GetPlayersSize() const { return m_Players.size(); }
void ReadyMarkerClicked(Player* p); // pussywizard
std::set<uint32> readyMarkerClickedSet; // pussywizard
typedef std::map<uint64, BattlegroundScore*> BattlegroundScoreMap;
typedef std::map<uint64, ArenaLogEntryData> ArenaLogEntryDataMap;// pussywizard
ArenaLogEntryDataMap ArenaLogEntries; // pussywizard
BattlegroundScoreMap::const_iterator GetPlayerScoresBegin() const { return PlayerScores.begin(); }
BattlegroundScoreMap::const_iterator GetPlayerScoresEnd() const { return PlayerScores.end(); }
uint32 GetPlayerScoresSize() const { return PlayerScores.size(); }
uint32 GetReviveQueueSize() const { return m_ReviveQueue.size(); }
void AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid);
void RemovePlayerFromResurrectQueue(Player* player);
/// Relocate all players in ReviveQueue to the closest graveyard
void RelocateDeadPlayers(uint64 queueIndex);
void StartBattleground();
GameObject* GetBGObject(uint32 type);
Creature* GetBGCreature(uint32 type);
// Location
void SetMapId(uint32 MapID) { m_MapId = MapID; }
uint32 GetMapId() const { return m_MapId; }
// Map pointers
void SetBgMap(BattlegroundMap* map) { m_Map = map; }
BattlegroundMap* GetBgMap() const { ASSERT(m_Map); return m_Map; }
BattlegroundMap* FindBgMap() const { return m_Map; }
void SetTeamStartLoc(TeamId teamId, float X, float Y, float Z, float O);
void GetTeamStartLoc(TeamId teamId, float &X, float &Y, float &Z, float &O) const
{
X = m_TeamStartLocX[teamId];
Y = m_TeamStartLocY[teamId];
Z = m_TeamStartLocZ[teamId];
O = m_TeamStartLocO[teamId];
}
void SetStartMaxDist(float startMaxDist) { m_StartMaxDist = startMaxDist; }
float GetStartMaxDist() const { return m_StartMaxDist; }
// Packet Transfer
// method that should fill worldpacket with actual world states (not yet implemented for all battlegrounds!)
virtual void FillInitialWorldStates(WorldPacket& /*data*/) {}
void SendPacketToTeam(TeamId teamId, WorldPacket* packet, Player* sender = NULL, bool self = true);
void SendPacketToAll(WorldPacket* packet);
void YellToAll(Creature* creature, const char* text, uint32 language);
template<class Do>
void BroadcastWorker(Do& _do);
void PlaySoundToAll(uint32 soundId);
void CastSpellOnTeam(uint32 spellId, TeamId teamId);
void RemoveAuraOnTeam(uint32 spellId, TeamId teamId);
void RewardHonorToTeam(uint32 honor, TeamId teamId);
void RewardReputationToTeam(uint32 factionId, uint32 reputation, TeamId teamId);
uint32 GetRealRepFactionForPlayer(uint32 factionId, Player* player);
void UpdateWorldState(uint32 Field, uint32 Value);
void UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player* player);
void EndBattleground(TeamId winnerTeamId);
void BlockMovement(Player* player);
void SendWarningToAll(int32 entry, ...);
void SendMessageToAll(int32 entry, ChatMsg type, Player const* source = NULL);
void PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ...);
// specialized version with 2 string id args
void SendMessage2ToAll(int32 entry, ChatMsg type, Player const* source, int32 strId1 = 0, int32 strId2 = 0);
// Raid Group
Group* GetBgRaid(TeamId teamId) const { return m_BgRaids[teamId]; }
void SetBgRaid(TeamId teamId, Group* bg_raid);
virtual void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
uint32 GetPlayersCountByTeam(TeamId teamId) const { return m_PlayersCount[teamId]; }
uint32 GetAlivePlayersCountByTeam(TeamId teamId) const; // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases
void UpdatePlayersCountByTeam(TeamId teamId, bool remove)
{
if (remove)
--m_PlayersCount[teamId];
else
++m_PlayersCount[teamId];
}
// used for rated arena battles
void SetArenaTeamIdForTeam(TeamId teamId, uint32 ArenaTeamId) { m_ArenaTeamIds[teamId] = ArenaTeamId; }
uint32 GetArenaTeamIdForTeam(TeamId teamId) const { return m_ArenaTeamIds[teamId]; }
void SetArenaTeamRatingChangeForTeam(TeamId teamId, int32 RatingChange) { m_ArenaTeamRatingChanges[teamId] = RatingChange; }
int32 GetArenaTeamRatingChangeForTeam(TeamId teamId) const { return m_ArenaTeamRatingChanges[teamId]; }
void SetArenaMatchmakerRating(TeamId teamId, uint32 MMR) { m_ArenaTeamMMR[teamId] = MMR; }
uint32 GetArenaMatchmakerRating(TeamId teamId) const { return m_ArenaTeamMMR[teamId]; }
void CheckArenaAfterTimerConditions();
void CheckArenaWinConditions();
virtual void UpdateArenaWorldState();
// Triggers handle
// must be implemented in BG subclass
virtual void HandleAreaTrigger(Player* /*player*/, uint32 /*trigger*/) {}
// must be implemented in BG subclass if need AND call base class generic code
virtual void HandleKillPlayer(Player* player, Player* killer);
virtual void HandleKillUnit(Creature* /*unit*/, Player* /*killer*/);
// Battleground events
virtual void EventPlayerDroppedFlag(Player* /*player*/) {}
virtual void EventPlayerClickedOnFlag(Player* /*player*/, GameObject* /*gameObject*/) {}
virtual void EventPlayerDamagedGO(Player* /*player*/, GameObject* /*go*/, uint32 /*eventType*/) {}
virtual void EventPlayerUsedGO(Player* /*player*/, GameObject* /*go*/){}
// this function can be used by spell to interact with the BG map
virtual void DoAction(uint32 /*action*/, uint64 /*var*/) {}
virtual void HandlePlayerResurrect(Player* /*player*/) {}
// Death related
virtual WorldSafeLocsEntry const* GetClosestGraveyard(Player* player);
virtual void AddPlayer(Player* player); // must be implemented in BG subclass
void AddOrSetPlayerToCorrectBgGroup(Player* player, TeamId teamId);
void RemovePlayerAtLeave(Player* player);
// can be extended in in BG subclass
void HandleTriggerBuff(GameObject* gameObject);
void SetHoliday(bool is_holiday);
// TODO: make this protected:
typedef std::vector<uint64> BGObjects;
typedef std::vector<uint64> BGCreatures;
BGObjects BgObjects;
BGCreatures BgCreatures;
void SpawnBGObject(uint32 type, uint32 respawntime);
bool AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime = 0, GOState goState = GO_STATE_READY);
Creature* AddCreature(uint32 entry, uint32 type, float x, float y, float z, float o, uint32 respawntime = 0, MotionTransport* transport = NULL);
bool DelCreature(uint32 type);
bool DelObject(uint32 type);
bool AddSpiritGuide(uint32 type, float x, float y, float z, float o, TeamId teamId);
int32 GetObjectType(uint64 guid);
void DoorOpen(uint32 type);
void DoorClose(uint32 type);
//to be removed
const char* GetTrinityString(int32 entry);
virtual bool HandlePlayerUnderMap(Player* /*player*/) { return false; }
// since arenas can be AvA or Hvh, we have to get the "temporary" team of a player
static TeamId GetOtherTeamId(TeamId teamId);
bool IsPlayerInBattleground(uint64 guid) const;
bool ToBeDeleted() const { return m_SetDeleteThis; }
//void SetDeleteThis() { m_SetDeleteThis = true; }
void RewardXPAtKill(Player* killer, Player* victim);
virtual uint64 GetFlagPickerGUID(TeamId /*teamId*/ = TEAM_NEUTRAL) const { return 0; }
virtual void SetDroppedFlagGUID(uint64 /*guid*/, TeamId /*teamId*/ = TEAM_NEUTRAL) {}
uint32 GetTeamScore(TeamId teamId) const;
virtual TeamId GetPrematureWinner();
// because BattleGrounds with different types and same level range has different m_BracketId
uint8 GetUniqueBracketId() const;
BattlegroundAV* ToBattlegroundAV() { if (GetBgTypeID() == BATTLEGROUND_AV) return reinterpret_cast<BattlegroundAV*>(this); else return NULL; }
BattlegroundAV const* ToBattlegroundAV() const { if (GetBgTypeID() == BATTLEGROUND_AV) return reinterpret_cast<const BattlegroundAV*>(this); else return NULL; }
BattlegroundWS* ToBattlegroundWS() { if (GetBgTypeID() == BATTLEGROUND_WS) return reinterpret_cast<BattlegroundWS*>(this); else return NULL; }
BattlegroundWS const* ToBattlegroundWS() const { if (GetBgTypeID() == BATTLEGROUND_WS) return reinterpret_cast<const BattlegroundWS*>(this); else return NULL; }
BattlegroundAB* ToBattlegroundAB() { if (GetBgTypeID() == BATTLEGROUND_AB) return reinterpret_cast<BattlegroundAB*>(this); else return NULL; }
BattlegroundAB const* ToBattlegroundAB() const { if (GetBgTypeID() == BATTLEGROUND_AB) return reinterpret_cast<const BattlegroundAB*>(this); else return NULL; }
BattlegroundNA* ToBattlegroundNA() { if (GetBgTypeID() == BATTLEGROUND_NA) return reinterpret_cast<BattlegroundNA*>(this); else return NULL; }
BattlegroundNA const* ToBattlegroundNA() const { if (GetBgTypeID() == BATTLEGROUND_NA) return reinterpret_cast<const BattlegroundNA*>(this); else return NULL; }
BattlegroundBE* ToBattlegroundBE() { if (GetBgTypeID() == BATTLEGROUND_BE) return reinterpret_cast<BattlegroundBE*>(this); else return NULL; }
BattlegroundBE const* ToBattlegroundBE() const { if (GetBgTypeID() == BATTLEGROUND_BE) return reinterpret_cast<const BattlegroundBE*>(this); else return NULL; }
BattlegroundEY* ToBattlegroundEY() { if (GetBgTypeID() == BATTLEGROUND_EY) return reinterpret_cast<BattlegroundEY*>(this); else return NULL; }
BattlegroundEY const* ToBattlegroundEY() const { if (GetBgTypeID() == BATTLEGROUND_EY) return reinterpret_cast<const BattlegroundEY*>(this); else return NULL; }
BattlegroundRL* ToBattlegroundRL() { if (GetBgTypeID() == BATTLEGROUND_RL) return reinterpret_cast<BattlegroundRL*>(this); else return NULL; }
BattlegroundRL const* ToBattlegroundRL() const { if (GetBgTypeID() == BATTLEGROUND_RL) return reinterpret_cast<const BattlegroundRL*>(this); else return NULL; }
BattlegroundSA* ToBattlegroundSA() { if (GetBgTypeID() == BATTLEGROUND_SA) return reinterpret_cast<BattlegroundSA*>(this); else return NULL; }
BattlegroundSA const* ToBattlegroundSA() const { if (GetBgTypeID() == BATTLEGROUND_SA) return reinterpret_cast<const BattlegroundSA*>(this); else return NULL; }
BattlegroundDS* ToBattlegroundDS() { if (GetBgTypeID() == BATTLEGROUND_DS) return reinterpret_cast<BattlegroundDS*>(this); else return NULL; }
BattlegroundDS const* ToBattlegroundDS() const { if (GetBgTypeID() == BATTLEGROUND_DS) return reinterpret_cast<const BattlegroundDS*>(this); else return NULL; }
BattlegroundRV* ToBattlegroundRV() { if (GetBgTypeID() == BATTLEGROUND_RV) return reinterpret_cast<BattlegroundRV*>(this); else return NULL; }
BattlegroundRV const* ToBattlegroundRV() const { if (GetBgTypeID() == BATTLEGROUND_RV) return reinterpret_cast<const BattlegroundRV*>(this); else return NULL; }
BattlegroundIC* ToBattlegroundIC() { if (GetBgTypeID() == BATTLEGROUND_IC) return reinterpret_cast<BattlegroundIC*>(this); else return NULL; }
BattlegroundIC const* ToBattlegroundIC() const { if (GetBgTypeID() == BATTLEGROUND_IC) return reinterpret_cast<const BattlegroundIC*>(this); else return NULL; }
protected:
// this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends Battleground
void EndNow();
void PlayerAddedToBGCheckIfBGIsRunning(Player* player);
void _ProcessResurrect(uint32 diff);
void _ProcessProgress(uint32 diff);
void _ProcessLeave(uint32 diff);
void _ProcessJoin(uint32 diff);
void _CheckSafePositions(uint32 diff);
// Scorekeeping
BattlegroundScoreMap PlayerScores; // Player scores
// must be implemented in BG subclass
virtual void RemovePlayer(Player* /*player*/) {}
// Player lists, those need to be accessible by inherited classes
BattlegroundPlayerMap m_Players;
// Spirit Guide guid + Player list GUIDS
std::map<uint64, std::vector<uint64> > m_ReviveQueue;
// these are important variables used for starting messages
uint8 m_Events;
BattlegroundStartTimeIntervals StartDelayTimes[BG_STARTING_EVENT_COUNT];
// this must be filled in constructors!
uint32 StartMessageIds[BG_STARTING_EVENT_COUNT];
bool m_BuffChange;
BGHonorMode m_HonorMode;
int32 m_TeamScores[BG_TEAMS_COUNT];
// pussywizard:
uint32 m_UpdateTimer;
private:
// Battleground
BattlegroundTypeId m_RealTypeID;
uint32 m_InstanceID; // Battleground Instance's GUID!
BattlegroundStatus m_Status;
uint32 m_ClientInstanceID; // the instance-id which is sent to the client and without any other internal use
uint32 m_StartTime;
uint32 m_ResetStatTimer;
uint32 m_ValidStartPositionTimer;
int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself
uint32 m_LastResurrectTime;
uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5
bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave
bool m_IsArena;
TeamId m_WinnerId;
int32 m_StartDelayTime;
bool m_IsRated; // is this battle rated?
bool m_PrematureCountDown;
uint32 m_PrematureCountDownTimer;
char const* m_Name;
/* Pre- and post-update hooks */
/**
* @brief Pre-update hook.
*
* Will be called before battleground update is started. Depending on
* the result of this call actual update body may be skipped.
*
* @param diff a time difference between two worldserver update loops in
* milliseconds.
*
* @return @c true if update must be performed, @c false otherwise.
*
* @see Update(), PostUpdateImpl().
*/
virtual bool PreUpdateImpl(uint32 /* diff */) { return true; }
/**
* @brief Post-update hook.
*
* Will be called after battleground update has passed. May be used to
* implement custom update effects in subclasses.
*
* @param diff a time difference between two worldserver update loops in
* milliseconds.
*
* @see Update(), PreUpdateImpl().
*/
virtual void PostUpdateImpl(uint32 /* diff */) { }
// Player lists
std::vector<uint64> m_ResurrectQueue; // Player GUID
std::deque<uint64> m_OfflineQueue; // Player GUID
// Invited counters are useful for player invitation to BG - do not allow, if BG is started to one faction to have 2 more players than another faction
// Invited counters will be changed only when removing already invited player from queue, removing player from battleground and inviting player to BG
// Invited players counters
uint32 m_BgInvitedPlayers[BG_TEAMS_COUNT];
// Raid Group
Group* m_BgRaids[BG_TEAMS_COUNT]; // 0 - alliance, 1 - horde
SpectatorList m_Spectators;
ToBeTeleportedMap m_ToBeTeleported;
// Players count by team
uint32 m_PlayersCount[BG_TEAMS_COUNT];
// Arena team ids by team
uint32 m_ArenaTeamIds[BG_TEAMS_COUNT];
int32 m_ArenaTeamRatingChanges[BG_TEAMS_COUNT];
uint32 m_ArenaTeamMMR[BG_TEAMS_COUNT];
// Limits
uint32 m_LevelMin;
uint32 m_LevelMax;
uint32 m_MaxPlayersPerTeam;
uint32 m_MinPlayersPerTeam;
// Start location
uint32 m_MapId;
BattlegroundMap* m_Map;
float m_TeamStartLocX[BG_TEAMS_COUNT];
float m_TeamStartLocY[BG_TEAMS_COUNT];
float m_TeamStartLocZ[BG_TEAMS_COUNT];
float m_TeamStartLocO[BG_TEAMS_COUNT];
float m_StartMaxDist;
uint32 ScriptId;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,168 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDMGR_H
#define __BATTLEGROUNDMGR_H
#include "Common.h"
#include "DBCEnums.h"
#include "Battleground.h"
#include "BattlegroundQueue.h"
#include "CreatureAIImpl.h"
#include <ace/Singleton.h>
typedef std::map<uint32, Battleground*> BattlegroundContainer;
typedef UNORDERED_MAP<uint32, BattlegroundTypeId> BattleMastersMap;
#define WS_ARENA_DISTRIBUTION_TIME 20001 // Custom worldstate
struct CreateBattlegroundData
{
BattlegroundTypeId bgTypeId;
bool IsArena;
uint32 MinPlayersPerTeam;
uint32 MaxPlayersPerTeam;
uint32 LevelMin;
uint32 LevelMax;
char* BattlegroundName;
uint32 MapID;
float Team1StartLocX;
float Team1StartLocY;
float Team1StartLocZ;
float Team1StartLocO;
float Team2StartLocX;
float Team2StartLocY;
float Team2StartLocZ;
float Team2StartLocO;
float StartMaxDist;
uint32 scriptId;
};
struct GroupQueueInfo;
// pussywizard
class RandomBattlegroundSystem
{
public:
RandomBattlegroundSystem();
void Update(uint32 diff);
BattlegroundTypeId GetCurrentRandomBg() const { return m_CurrentRandomBg; }
void BattlegroundCreated(BattlegroundTypeId bgTypeId);
private:
BattlegroundTypeId m_CurrentRandomBg;
uint32 m_SwitchTimer;
std::vector<BattlegroundTypeId> m_BgOrder;
};
class BattlegroundMgr
{
friend class ACE_Singleton<BattlegroundMgr, ACE_Null_Mutex>;
private:
BattlegroundMgr();
~BattlegroundMgr();
public:
void Update(uint32 diff);
/* Packet Building */
void BuildPlayerJoinedBattlegroundPacket(WorldPacket* data, Player* player);
void BuildPlayerLeftBattlegroundPacket(WorldPacket* data, uint64 guid);
void BuildBattlegroundListPacket(WorldPacket* data, uint64 guid, Player* player, BattlegroundTypeId bgTypeId, uint8 fromWhere);
void BuildGroupJoinedBattlegroundPacket(WorldPacket* data, GroupJoinBattlegroundResult result);
void BuildUpdateWorldStatePacket(WorldPacket* data, uint32 field, uint32 value);
void BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg);
void BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, uint8 queueSlot, uint8 statusId, uint32 time1, uint32 time2, uint8 arenaType, TeamId teamId, bool isRated = false, BattlegroundTypeId forceBgTypeId = BATTLEGROUND_TYPE_NONE);
void BuildPlaySoundPacket(WorldPacket* data, uint32 soundid);
void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, uint64 guid);
/* Battlegrounds */
Battleground* GetBattleground(uint32 InstanceID);
Battleground* GetBattlegroundTemplate(BattlegroundTypeId bgTypeId);
Battleground* CreateNewBattleground(BattlegroundTypeId bgTypeId, uint32 minLevel, uint32 maxLevel, uint8 arenaType, bool isRated);
void AddBattleground(Battleground* bg);
void RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId);
void CreateInitialBattlegrounds();
void DeleteAllBattlegrounds();
void SendToBattleground(Player* player, uint32 InstanceID, BattlegroundTypeId bgTypeId);
/* Battleground queues */
BattlegroundQueue& GetBattlegroundQueue(BattlegroundQueueTypeId bgQueueTypeId) { return m_BattlegroundQueues[bgQueueTypeId]; }
void ScheduleArenaQueueUpdate(uint32 arenaRatedTeamId, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundBracketId bracket_id);
uint32 GetPrematureFinishTime() const;
static void InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, TeamId teamId);
void ToggleArenaTesting();
void ToggleTesting();
void SetHolidayWeekends(uint32 mask);
bool isArenaTesting() const { return m_ArenaTesting; }
bool isTesting() const { return m_Testing; }
static BattlegroundQueueTypeId BGQueueTypeId(BattlegroundTypeId bgTypeId, uint8 arenaType);
static BattlegroundTypeId BGTemplateId(BattlegroundQueueTypeId bgQueueTypeId);
static bool IsArenaType(BattlegroundTypeId bgTypeId);
static uint8 BGArenaType(BattlegroundQueueTypeId bgQueueTypeId);
static HolidayIds BGTypeToWeekendHolidayId(BattlegroundTypeId bgTypeId);
static BattlegroundTypeId WeekendHolidayIdToBGType(HolidayIds holiday);
static bool IsBGWeekend(BattlegroundTypeId bgTypeId);
PvPDifficultyEntry randomBgDifficultyEntry;
uint32 GetRatingDiscardTimer() const;
void InitAutomaticArenaPointDistribution();
void LoadBattleMastersEntry();
void CheckBattleMasters();
BattlegroundTypeId GetBattleMasterBG(uint32 entry) const
{
BattleMastersMap::const_iterator itr = mBattleMastersMap.find(entry);
if (itr != mBattleMastersMap.end())
return itr->second;
return BATTLEGROUND_TYPE_NONE;
}
const BattlegroundContainer& GetBattlegroundList() { return m_Battlegrounds; } // pussywizard
RandomBattlegroundSystem RandomSystem; // pussywizard
private:
bool CreateBattleground(CreateBattlegroundData& data);
uint32 GetNextClientVisibleInstanceId();
typedef std::map<BattlegroundTypeId, Battleground*> BattlegroundTemplateContainer;
BattlegroundTemplateContainer m_BattlegroundTemplates;
BattlegroundContainer m_Battlegrounds;
BattlegroundQueue m_BattlegroundQueues[MAX_BATTLEGROUND_QUEUE_TYPES];
std::vector<uint64> m_ArenaQueueUpdateScheduler;
uint32 m_lastClientVisibleInstanceId;
uint32 m_NextPeriodicQueueUpdateTime;
time_t m_NextAutoDistributionTime;
bool m_ArenaTesting;
bool m_Testing;
BattleMastersMap mBattleMastersMap;
};
#define sBattlegroundMgr ACE_Singleton<BattlegroundMgr, ACE_Null_Mutex>::instance()
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,177 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDQUEUE_H
#define __BATTLEGROUNDQUEUE_H
#include "Common.h"
#include "DBCEnums.h"
#include "Battleground.h"
#include "EventProcessor.h"
#include <deque>
#define COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME 10
struct GroupQueueInfo // stores information about the group in queue (also used when joined as solo!)
{
std::set<uint64> Players; // player guid set
TeamId teamId; // Player team (TEAM_ALLIANCE/TEAM_HORDE)
BattlegroundTypeId BgTypeId; // battleground type id
bool IsRated; // rated
uint8 ArenaType; // 2v2, 3v3, 5v5 or 0 when BG
uint32 ArenaTeamId; // team id if rated match
uint32 JoinTime; // time when group was added
uint32 RemoveInviteTime; // time when we will remove invite for players in group
uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG
uint32 ArenaTeamRating; // if rated match, inited to the rating of the team
uint32 ArenaMatchmakerRating; // if rated match, inited to the rating of the team
uint32 OpponentsTeamRating; // for rated arena matches
uint32 OpponentsMatchmakerRating; // for rated arena matches
// pussywizard: for internal use
uint8 _bracketId;
uint8 _groupType;
};
enum BattlegroundQueueGroupTypes
{
BG_QUEUE_PREMADE_ALLIANCE = 0,
BG_QUEUE_PREMADE_HORDE = 1,
BG_QUEUE_NORMAL_ALLIANCE = 2,
BG_QUEUE_NORMAL_HORDE = 3
};
#define BG_QUEUE_GROUP_TYPES_COUNT 4
class Battleground;
class BattlegroundQueue
{
public:
BattlegroundQueue();
~BattlegroundQueue();
void BattlegroundQueueUpdate(BattlegroundBracketId bracket_id, uint8 actionMask, bool isRated, uint32 arenaRatedTeamId);
void UpdateEvents(uint32 diff);
void FillPlayersToBG(const int32 aliFree, const int32 hordeFree, BattlegroundBracketId bracket_id);
void FillPlayersToBGWithSpecific(const int32 aliFree, const int32 hordeFree, BattlegroundBracketId thisBracketId, BattlegroundQueue* specificQueue, BattlegroundBracketId specificBracketId);
bool CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam);
bool CheckNormalMatch(Battleground* bgTemplate, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers);
bool CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam);
GroupQueueInfo* AddGroup(Player* leader, Group* group, PvPDifficultyEntry const* bracketEntry, bool isRated, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating, uint32 ArenaTeamId);
void RemovePlayer(uint64 guid, bool sentToBg, uint32 playerQueueSlot);
bool IsPlayerInvitedToRatedArena(uint64 pl_guid);
bool IsPlayerInvited(uint64 pl_guid, const uint32 bgInstanceGuid, const uint32 removeTime);
bool GetPlayerGroupInfoData(uint64 guid, GroupQueueInfo* ginfo);
void PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo);
uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo) const;
void SetBgTypeIdAndArenaType(BattlegroundTypeId b, uint8 a) { m_bgTypeId = b; m_arenaType = ArenaType(a); } // pussywizard
void AddEvent(BasicEvent* Event, uint64 e_time);
typedef std::map<uint64, GroupQueueInfo*> QueuedPlayersMap;
QueuedPlayersMap m_QueuedPlayers;
//do NOT use deque because deque.erase() invalidates ALL iterators
typedef std::list<GroupQueueInfo*> GroupsQueueType;
/*
This two dimensional array is used to store All queued groups
First dimension specifies the bgTypeId
Second dimension specifies the player's group types -
BG_QUEUE_PREMADE_ALLIANCE is used for premade alliance groups and alliance rated arena teams
BG_QUEUE_PREMADE_HORDE is used for premade horde groups and horde rated arena teams
BG_QUEUE_NORMAL_ALLIANCE is used for normal (or small) alliance groups or non-rated arena matches
BG_QUEUE_NORMAL_HORDE is used for normal (or small) horde groups or non-rated arena matches
*/
GroupsQueueType m_QueuedGroups[MAX_BATTLEGROUND_BRACKETS][BG_QUEUE_GROUP_TYPES_COUNT];
// class to select and invite groups to bg
class SelectionPool
{
public:
SelectionPool(): PlayerCount(0) {};
void Init();
bool AddGroup(GroupQueueInfo* ginfo, uint32 desiredCount);
bool KickGroup(const uint32 size);
uint32 GetPlayerCount() const {return PlayerCount;}
public:
GroupsQueueType SelectedGroups;
private:
uint32 PlayerCount;
};
//one selection pool for horde, other one for alliance
SelectionPool m_SelectionPools[BG_TEAMS_COUNT];
private:
BattlegroundTypeId m_bgTypeId;
ArenaType m_arenaType;
uint32 m_WaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME];
uint32 m_WaitTimeLastIndex[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS];
// Event handler
EventProcessor m_events;
};
/*
This class is used to invite player to BG again, when minute lasts from his first invitation
it is capable to solve all possibilities
*/
class BGQueueInviteEvent : public BasicEvent
{
public:
BGQueueInviteEvent(uint64 pl_guid, uint32 BgInstanceGUID, BattlegroundTypeId BgTypeId, uint8 arenaType, uint32 removeTime) :
m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID), m_BgTypeId(BgTypeId), m_ArenaType(arenaType), m_RemoveTime(removeTime)
{ }
virtual ~BGQueueInviteEvent() { }
virtual bool Execute(uint64 e_time, uint32 p_time);
virtual void Abort(uint64 e_time);
private:
uint64 m_PlayerGuid;
uint32 m_BgInstanceGUID;
BattlegroundTypeId m_BgTypeId;
uint8 m_ArenaType;
uint32 m_RemoveTime;
};
/*
This class is used to remove player from BG queue after 1 minute 20 seconds from first invitation
We must store removeInvite time in case player left queue and joined and is invited again
We must store bgQueueTypeId, because battleground can be deleted already, when player entered it
*/
class BGQueueRemoveEvent : public BasicEvent
{
public:
BGQueueRemoveEvent(uint64 pl_guid, uint32 bgInstanceGUID, BattlegroundQueueTypeId bgQueueTypeId, uint32 removeTime)
: m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_RemoveTime(removeTime), m_BgQueueTypeId(bgQueueTypeId)
{}
virtual ~BGQueueRemoveEvent() {}
virtual bool Execute(uint64 e_time, uint32 p_time);
virtual void Abort(uint64 e_time);
private:
uint64 m_PlayerGuid;
uint32 m_BgInstanceGUID;
uint32 m_RemoveTime;
BattlegroundQueueTypeId m_BgQueueTypeId;
};
#endif

View File

@@ -1,492 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#include "BattlegroundAB.h"
#include "World.h"
#include "WorldPacket.h"
#include "ObjectMgr.h"
#include "BattlegroundMgr.h"
#include "Creature.h"
#include "Language.h"
#include "Object.h"
#include "Player.h"
#include "Util.h"
#include "WorldSession.h"
BattlegroundAB::BattlegroundAB()
{
m_BuffChange = true;
BgObjects.resize(BG_AB_OBJECT_MAX);
BgCreatures.resize(BG_AB_ALL_NODES_COUNT + BG_AB_DYNAMIC_NODES_COUNT); // xinef: +BG_AB_DYNAMIC_NODES_COUNT buff triggers
_controlledPoints[TEAM_ALLIANCE] = 0;
_controlledPoints[TEAM_HORDE] = 0;
_teamScores500Disadvantage[TEAM_ALLIANCE] = false;
_teamScores500Disadvantage[TEAM_HORDE] = false;
_honorTics = 0;
_reputationTics = 0;
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AB_START_TWO_MINUTES;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AB_START_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AB_START_HALF_MINUTE;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AB_HAS_BEGUN;
}
BattlegroundAB::~BattlegroundAB()
{
}
void BattlegroundAB::PostUpdateImpl(uint32 diff)
{
if (GetStatus() == STATUS_IN_PROGRESS)
{
_bgEvents.Update(diff);
while (uint32 eventId =_bgEvents.ExecuteEvent())
switch (eventId)
{
case BG_AB_EVENT_UPDATE_BANNER_STABLE:
case BG_AB_EVENT_UPDATE_BANNER_FARM:
case BG_AB_EVENT_UPDATE_BANNER_BLACKSMITH:
case BG_AB_EVENT_UPDATE_BANNER_LUMBERMILL:
case BG_AB_EVENT_UPDATE_BANNER_GOLDMINE:
CreateBanner(eventId - BG_AB_EVENT_UPDATE_BANNER_STABLE, false);
break;
case BG_AB_EVENT_CAPTURE_STABLE:
case BG_AB_EVENT_CAPTURE_FARM:
case BG_AB_EVENT_CAPTURE_BLACKSMITH:
case BG_AB_EVENT_CAPTURE_LUMBERMILL:
case BG_AB_EVENT_CAPTURE_GOLDMINE:
{
uint8 node = eventId - BG_AB_EVENT_CAPTURE_STABLE;
TeamId teamId = _capturePointInfo[node]._state == BG_AB_NODE_STATE_ALLY_CONTESTED ? TEAM_ALLIANCE : TEAM_HORDE;
DeleteBanner(node);
_capturePointInfo[node]._ownerTeamId = teamId;
_capturePointInfo[node]._state = teamId == TEAM_ALLIANCE ? BG_AB_NODE_STATE_ALLY_OCCUPIED : BG_AB_NODE_STATE_HORDE_OCCUPIED;
_capturePointInfo[node]._captured = true;
CreateBanner(node, false);
NodeOccupied(node);
SendNodeUpdate(node);
SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN, teamId == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE, NULL, teamId == TEAM_ALLIANCE ? LANG_BG_AB_ALLY : LANG_BG_AB_HORDE, LANG_BG_AB_NODE_STABLES + node);
PlaySoundToAll(teamId == TEAM_ALLIANCE ? BG_AB_SOUND_NODE_CAPTURED_ALLIANCE : BG_AB_SOUND_NODE_CAPTURED_HORDE);
break;
}
case BG_AB_EVENT_ALLIANCE_TICK:
case BG_AB_EVENT_HORDE_TICK:
{
TeamId teamId = TeamId(eventId - BG_AB_EVENT_ALLIANCE_TICK);
uint8 controlledPoints = _controlledPoints[teamId];
if (controlledPoints == 0)
{
_bgEvents.ScheduleEvent(eventId, 3000);
break;
}
uint8 honorRewards = uint8(m_TeamScores[teamId] / _honorTics);
uint8 reputationRewards = uint8(m_TeamScores[teamId] / _reputationTics);
uint8 information = uint8(m_TeamScores[teamId] / BG_AB_WARNING_NEAR_VICTORY_SCORE);
m_TeamScores[teamId] += BG_AB_TickPoints[controlledPoints];
if (m_TeamScores[teamId] > BG_AB_MAX_TEAM_SCORE)
m_TeamScores[teamId] = BG_AB_MAX_TEAM_SCORE;
if (honorRewards < uint8(m_TeamScores[teamId] / _honorTics))
RewardHonorToTeam(GetBonusHonorFromKill(1), teamId);
if (reputationRewards < uint8(m_TeamScores[teamId] / _reputationTics))
RewardReputationToTeam(teamId == TEAM_ALLIANCE ? 509 : 510, 10, teamId);
if (information < uint8(m_TeamScores[teamId] / BG_AB_WARNING_NEAR_VICTORY_SCORE))
{
SendMessageToAll(teamId == TEAM_ALLIANCE ? LANG_BG_AB_A_NEAR_VICTORY : LANG_BG_AB_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_AB_SOUND_NEAR_VICTORY);
}
UpdateWorldState(teamId == TEAM_ALLIANCE ? BG_AB_OP_RESOURCES_ALLY : BG_AB_OP_RESOURCES_HORDE, m_TeamScores[teamId]);
if (m_TeamScores[teamId] > m_TeamScores[GetOtherTeamId(teamId)] + 500)
_teamScores500Disadvantage[GetOtherTeamId(teamId)] = true;
if (m_TeamScores[teamId] >= BG_AB_MAX_TEAM_SCORE)
EndBattleground(teamId);
_bgEvents.ScheduleEvent(eventId, BG_AB_TickIntervals[controlledPoints]);
break;
}
}
}
}
void BattlegroundAB::StartingEventCloseDoors()
{
for (uint32 obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * BG_AB_OBJECTS_PER_NODE; ++obj)
SpawnBGObject(obj, RESPAWN_ONE_DAY);
for (uint32 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i)
SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY);
// Starting doors
SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY);
DoorClose(BG_AB_OBJECT_GATE_A);
DoorClose(BG_AB_OBJECT_GATE_H);
}
void BattlegroundAB::StartingEventOpenDoors()
{
for (uint32 banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; banner += BG_AB_OBJECTS_PER_NODE, ++i)
SpawnBGObject(banner, RESPAWN_IMMEDIATELY);
for (uint32 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + urand(0, 2) + i * 3, RESPAWN_IMMEDIATELY);
DoorOpen(BG_AB_OBJECT_GATE_A);
DoorOpen(BG_AB_OBJECT_GATE_H);
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, BG_AB_EVENT_START_BATTLE);
_bgEvents.ScheduleEvent(BG_AB_EVENT_ALLIANCE_TICK, 3000);
_bgEvents.ScheduleEvent(BG_AB_EVENT_HORDE_TICK, 3000);
}
void BattlegroundAB::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundABScore(player);
}
void BattlegroundAB::RemovePlayer(Player* player)
{
player->SetPhaseMask(1, false);
}
void BattlegroundAB::HandleAreaTrigger(Player* player, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
switch (trigger)
{
case 3948: // Arathi Basin Alliance Exit.
if (player->GetTeamId() != TEAM_ALLIANCE)
player->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal");
else
player->LeaveBattleground();
break;
case 3949: // Arathi Basin Horde Exit.
if (player->GetTeamId() != TEAM_HORDE)
player->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal");
else
player->LeaveBattleground();
break;
case 3866: // Stables
case 3869: // Gold Mine
case 3867: // Farm
case 3868: // Lumber Mill
case 3870: // Black Smith
case 4020: // Unk1
case 4021: // Unk2
break;
}
}
void BattlegroundAB::CreateBanner(uint8 node, bool delay)
{
// Just put it into the queue
if (delay)
{
_bgEvents.RescheduleEvent(BG_AB_EVENT_UPDATE_BANNER_STABLE+node, BG_AB_BANNER_UPDATE_TIME);
return;
}
SpawnBGObject(node*BG_AB_OBJECTS_PER_NODE + _capturePointInfo[node]._state, RESPAWN_IMMEDIATELY);
SpawnBGObject(node*BG_AB_OBJECTS_PER_NODE + BG_AB_OBJECT_AURA_ALLY + _capturePointInfo[node]._ownerTeamId, RESPAWN_IMMEDIATELY);
}
void BattlegroundAB::DeleteBanner(uint8 node)
{
SpawnBGObject(node*BG_AB_OBJECTS_PER_NODE + _capturePointInfo[node]._state, RESPAWN_ONE_DAY);
SpawnBGObject(node*BG_AB_OBJECTS_PER_NODE + BG_AB_OBJECT_AURA_ALLY + _capturePointInfo[node]._ownerTeamId, RESPAWN_ONE_DAY);
}
void BattlegroundAB::FillInitialWorldStates(WorldPacket& data)
{
for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node)
{
if (_capturePointInfo[node]._state == BG_AB_NODE_STATE_NEUTRAL)
data << uint32(_capturePointInfo[node]._iconNone) << uint32(1);
for (uint8 i = BG_AB_NODE_STATE_ALLY_OCCUPIED; i <= BG_AB_NODE_STATE_HORDE_CONTESTED; ++i)
data << uint32(_capturePointInfo[node]._iconCapture + i-1) << uint32(_capturePointInfo[node]._state == i);
}
data << uint32(BG_AB_OP_OCCUPIED_BASES_ALLY) << uint32(_controlledPoints[TEAM_ALLIANCE]);
data << uint32(BG_AB_OP_OCCUPIED_BASES_HORDE) << uint32(_controlledPoints[TEAM_HORDE]);
data << uint32(BG_AB_OP_RESOURCES_MAX) << uint32(BG_AB_MAX_TEAM_SCORE);
data << uint32(BG_AB_OP_RESOURCES_WARNING) << uint32(BG_AB_WARNING_NEAR_VICTORY_SCORE);
data << uint32(BG_AB_OP_RESOURCES_ALLY) << uint32(m_TeamScores[TEAM_ALLIANCE]);
data << uint32(BG_AB_OP_RESOURCES_HORDE) << uint32(m_TeamScores[TEAM_HORDE]);
data << uint32(0x745) << uint32(0x2); // 37 1861 unk
}
void BattlegroundAB::SendNodeUpdate(uint8 node)
{
UpdateWorldState(_capturePointInfo[node]._iconNone, 0);
for (uint8 i = BG_AB_NODE_STATE_ALLY_OCCUPIED; i <= BG_AB_NODE_STATE_HORDE_CONTESTED; ++i)
UpdateWorldState(_capturePointInfo[node]._iconCapture + i-1, _capturePointInfo[node]._state == i);
UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_ALLY, _controlledPoints[TEAM_ALLIANCE]);
UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_HORDE, _controlledPoints[TEAM_HORDE]);
}
void BattlegroundAB::NodeOccupied(uint8 node)
{
ApplyPhaseMask();
AddSpiritGuide(node, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], _capturePointInfo[node]._ownerTeamId);
++_controlledPoints[_capturePointInfo[node]._ownerTeamId];
if (_controlledPoints[_capturePointInfo[node]._ownerTeamId] >= 5)
CastSpellOnTeam(SPELL_AB_QUEST_REWARD_5_BASES, _capturePointInfo[node]._ownerTeamId);
if (_controlledPoints[_capturePointInfo[node]._ownerTeamId] >= 4)
CastSpellOnTeam(SPELL_AB_QUEST_REWARD_4_BASES, _capturePointInfo[node]._ownerTeamId);
Creature* trigger = GetBgMap()->GetCreature(BgCreatures[BG_AB_ALL_NODES_COUNT + node]);
if (!trigger)
trigger = AddCreature(WORLD_TRIGGER, BG_AB_ALL_NODES_COUNT + node, BG_AB_NodePositions[node][0], BG_AB_NodePositions[node][1], BG_AB_NodePositions[node][2], BG_AB_NodePositions[node][3]);
if (trigger)
{
trigger->setFaction(_capturePointInfo[node]._ownerTeamId == TEAM_ALLIANCE ? 84 : 83);
trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false);
}
}
void BattlegroundAB::NodeDeoccupied(uint8 node)
{
--_controlledPoints[_capturePointInfo[node]._ownerTeamId];
_capturePointInfo[node]._ownerTeamId = TEAM_NEUTRAL;
RelocateDeadPlayers(BgCreatures[node]);
DelCreature(node); // Delete spirit healer
DelCreature(BG_AB_ALL_NODES_COUNT + node); // Delete aura trigger
}
void BattlegroundAB::EventPlayerClickedOnFlag(Player* player, GameObject* gameObject)
{
if (GetStatus() != STATUS_IN_PROGRESS || !player->IsWithinDistInMap(gameObject, 10.0f))
return;
uint8 node = BG_AB_NODE_STABLES;
for (; node < BG_AB_DYNAMIC_NODES_COUNT; ++node)
if (player->GetDistance2d(BG_AB_NodePositions[node][0], BG_AB_NodePositions[node][1]) < 10.0f)
break;
if (node == BG_AB_DYNAMIC_NODES_COUNT || _capturePointInfo[node]._ownerTeamId == player->GetTeamId() ||
(_capturePointInfo[node]._state == BG_AB_NODE_STATE_ALLY_CONTESTED && player->GetTeamId() == TEAM_ALLIANCE) ||
(_capturePointInfo[node]._state == BG_AB_NODE_STATE_HORDE_CONTESTED && player->GetTeamId() == TEAM_HORDE))
return;
player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
uint32 sound = 0;
uint32 message = 0;
uint32 message2 = 0;
DeleteBanner(node);
CreateBanner(node, true);
if (_capturePointInfo[node]._state == BG_AB_NODE_STATE_NEUTRAL)
{
player->KilledMonsterCredit(BG_AB_QUEST_CREDIT_BASE + node, 0);
UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1);
_capturePointInfo[node]._state = BG_AB_NODE_STATE_ALLY_CONTESTED + player->GetTeamId();
_capturePointInfo[node]._ownerTeamId = TEAM_NEUTRAL;
_bgEvents.RescheduleEvent(BG_AB_EVENT_CAPTURE_STABLE + node, BG_AB_FLAG_CAPTURING_TIME);
sound = BG_AB_SOUND_NODE_CLAIMED;
message = LANG_BG_AB_NODE_CLAIMED;
message2 = player->GetTeamId() == TEAM_ALLIANCE ? LANG_BG_AB_ALLY : LANG_BG_AB_HORDE;
}
else if (_capturePointInfo[node]._state == BG_AB_NODE_STATE_ALLY_CONTESTED || _capturePointInfo[node]._state == BG_AB_NODE_STATE_HORDE_CONTESTED)
{
if (!_capturePointInfo[node]._captured)
{
player->KilledMonsterCredit(BG_AB_QUEST_CREDIT_BASE + node, 0);
UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1);
_capturePointInfo[node]._state = BG_AB_NODE_STATE_ALLY_CONTESTED + player->GetTeamId();
_capturePointInfo[node]._ownerTeamId = TEAM_NEUTRAL;
_bgEvents.RescheduleEvent(BG_AB_EVENT_CAPTURE_STABLE + node, BG_AB_FLAG_CAPTURING_TIME);
message = LANG_BG_AB_NODE_ASSAULTED;
}
else
{
UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1);
_capturePointInfo[node]._state = BG_AB_NODE_STATE_ALLY_OCCUPIED + player->GetTeamId();
_capturePointInfo[node]._ownerTeamId = player->GetTeamId();
_bgEvents.CancelEvent(BG_AB_EVENT_CAPTURE_STABLE + node);
NodeOccupied(node); // after setting team owner
message = LANG_BG_AB_NODE_DEFENDED;
}
sound = player->GetTeamId() == TEAM_ALLIANCE ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
}
else
{
player->KilledMonsterCredit(BG_AB_QUEST_CREDIT_BASE + node, 0);
UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1);
NodeDeoccupied(node); // before setting team owner to neutral
_capturePointInfo[node]._state = BG_AB_NODE_STATE_ALLY_CONTESTED + player->GetTeamId();
ApplyPhaseMask();
_bgEvents.RescheduleEvent(BG_AB_EVENT_CAPTURE_STABLE + node, BG_AB_FLAG_CAPTURING_TIME);
message = LANG_BG_AB_NODE_ASSAULTED;
sound = player->GetTeamId() == TEAM_ALLIANCE ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE;
}
SendNodeUpdate(node);
PlaySoundToAll(sound);
SendMessage2ToAll(message, player->GetTeamId() == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE, player, LANG_BG_AB_NODE_STABLES + node, message2);
}
TeamId BattlegroundAB::GetPrematureWinner()
{
if (_controlledPoints[TEAM_ALLIANCE] > _controlledPoints[TEAM_HORDE])
return TEAM_ALLIANCE;
return _controlledPoints[TEAM_HORDE] > _controlledPoints[TEAM_ALLIANCE] ? TEAM_HORDE : Battleground::GetPrematureWinner();
}
bool BattlegroundAB::SetupBattleground()
{
for (uint32 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
AddObject(BG_AB_OBJECT_BANNER_NEUTRAL + BG_AB_OBJECTS_PER_NODE*i, BG_AB_OBJECTID_NODE_BANNER_0 + i, BG_AB_NodePositions[i][0], BG_AB_NodePositions[i][1], BG_AB_NodePositions[i][2], BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2), RESPAWN_ONE_DAY);
AddObject(BG_AB_OBJECT_BANNER_ALLY + BG_AB_OBJECTS_PER_NODE*i, BG_AB_OBJECTID_BANNER_A, BG_AB_NodePositions[i][0], BG_AB_NodePositions[i][1], BG_AB_NodePositions[i][2], BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2), RESPAWN_ONE_DAY);
AddObject(BG_AB_OBJECT_BANNER_HORDE + BG_AB_OBJECTS_PER_NODE*i, BG_AB_OBJECTID_BANNER_H, BG_AB_NodePositions[i][0], BG_AB_NodePositions[i][1], BG_AB_NodePositions[i][2], BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2), RESPAWN_ONE_DAY);
AddObject(BG_AB_OBJECT_BANNER_CONT_A + BG_AB_OBJECTS_PER_NODE*i, BG_AB_OBJECTID_BANNER_CONT_A, BG_AB_NodePositions[i][0], BG_AB_NodePositions[i][1], BG_AB_NodePositions[i][2], BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2), RESPAWN_ONE_DAY);
AddObject(BG_AB_OBJECT_BANNER_CONT_H + BG_AB_OBJECTS_PER_NODE*i, BG_AB_OBJECTID_BANNER_CONT_H, BG_AB_NodePositions[i][0], BG_AB_NodePositions[i][1], BG_AB_NodePositions[i][2], BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2), RESPAWN_ONE_DAY);
AddObject(BG_AB_OBJECT_AURA_ALLY + BG_AB_OBJECTS_PER_NODE*i, BG_AB_OBJECTID_AURA_A, BG_AB_NodePositions[i][0], BG_AB_NodePositions[i][1], BG_AB_NodePositions[i][2], BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2), RESPAWN_ONE_DAY);
AddObject(BG_AB_OBJECT_AURA_HORDE + BG_AB_OBJECTS_PER_NODE*i, BG_AB_OBJECTID_AURA_H, BG_AB_NodePositions[i][0], BG_AB_NodePositions[i][1], BG_AB_NodePositions[i][2], BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2), RESPAWN_ONE_DAY);
AddObject(BG_AB_OBJECT_AURA_CONTESTED + BG_AB_OBJECTS_PER_NODE*i, BG_AB_OBJECTID_AURA_C, BG_AB_NodePositions[i][0], BG_AB_NodePositions[i][1], BG_AB_NodePositions[i][2], BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2), RESPAWN_ONE_DAY);
}
AddObject(BG_AB_OBJECT_GATE_A, BG_AB_OBJECTID_GATE_A, BG_AB_DoorPositions[0][0], BG_AB_DoorPositions[0][1], BG_AB_DoorPositions[0][2], BG_AB_DoorPositions[0][3], BG_AB_DoorPositions[0][4], BG_AB_DoorPositions[0][5], BG_AB_DoorPositions[0][6], BG_AB_DoorPositions[0][7], RESPAWN_IMMEDIATELY);
AddObject(BG_AB_OBJECT_GATE_H, BG_AB_OBJECTID_GATE_H, BG_AB_DoorPositions[1][0], BG_AB_DoorPositions[1][1], BG_AB_DoorPositions[1][2], BG_AB_DoorPositions[1][3], BG_AB_DoorPositions[1][4], BG_AB_DoorPositions[1][5], BG_AB_DoorPositions[1][6], BG_AB_DoorPositions[1][7], RESPAWN_IMMEDIATELY);
for (uint32 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i, Buff_Entries[0], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY);
AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 1, Buff_Entries[1], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY);
AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 2, Buff_Entries[2], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY);
}
AddSpiritGuide(BG_AB_SPIRIT_ALIANCE, BG_AB_SpiritGuidePos[BG_AB_SPIRIT_ALIANCE][0], BG_AB_SpiritGuidePos[BG_AB_SPIRIT_ALIANCE][1], BG_AB_SpiritGuidePos[BG_AB_SPIRIT_ALIANCE][2], BG_AB_SpiritGuidePos[BG_AB_SPIRIT_ALIANCE][3], TEAM_ALLIANCE);
AddSpiritGuide(BG_AB_SPIRIT_HORDE, BG_AB_SpiritGuidePos[BG_AB_SPIRIT_HORDE][0], BG_AB_SpiritGuidePos[BG_AB_SPIRIT_HORDE][1], BG_AB_SpiritGuidePos[BG_AB_SPIRIT_HORDE][2], BG_AB_SpiritGuidePos[BG_AB_SPIRIT_HORDE][3], TEAM_HORDE);
for (uint32 i = BG_AB_OBJECT_BANNER_NEUTRAL; i < BG_AB_OBJECT_MAX; ++i)
if (BgObjects[i] == 0)
{
sLog->outErrorDb("BatteGroundAB: Failed to spawn some object Battleground not created!");
return false;
}
for (uint32 i = BG_AB_SPIRIT_ALIANCE; i <= BG_AB_SPIRIT_HORDE; ++i)
if (BgCreatures[i] == 0)
{
sLog->outErrorDb("BatteGroundAB: Failed to spawn spirit guides Battleground not created!");
return false;
}
return true;
}
void BattlegroundAB::Init()
{
//call parent's class reset
Battleground::Init();
_bgEvents.Reset();
_honorTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID()) ? BG_AB_HONOR_TICK_WEEKEND : BG_AB_HONOR_TICK_NORMAL;
_reputationTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID()) ? BG_AB_REP_TICK_WEEKEND : BG_AB_REP_TICK_NORMAL;
_capturePointInfo[BG_AB_NODE_STABLES]._iconNone = BG_AB_OP_STABLE_ICON;
_capturePointInfo[BG_AB_NODE_FARM]._iconNone = BG_AB_OP_FARM_ICON;
_capturePointInfo[BG_AB_NODE_BLACKSMITH]._iconNone = BG_AB_OP_BLACKSMITH_ICON;
_capturePointInfo[BG_AB_NODE_LUMBER_MILL]._iconNone = BG_AB_OP_LUMBERMILL_ICON;
_capturePointInfo[BG_AB_NODE_GOLD_MINE]._iconNone = BG_AB_OP_GOLDMINE_ICON;
_capturePointInfo[BG_AB_NODE_STABLES]._iconCapture = BG_AB_OP_STABLE_STATE_ALIENCE;
_capturePointInfo[BG_AB_NODE_FARM]._iconCapture = BG_AB_OP_FARM_STATE_ALIENCE;
_capturePointInfo[BG_AB_NODE_BLACKSMITH]._iconCapture = BG_AB_OP_BLACKSMITH_STATE_ALIENCE;
_capturePointInfo[BG_AB_NODE_LUMBER_MILL]._iconCapture = BG_AB_OP_LUMBERMILL_STATE_ALIENCE;
_capturePointInfo[BG_AB_NODE_GOLD_MINE]._iconCapture = BG_AB_OP_GOLDMINE_STATE_ALIENCE;
}
void BattlegroundAB::EndBattleground(TeamId winnerTeamId)
{
RewardHonorToTeam(GetBonusHonorFromKill(1), winnerTeamId);
RewardHonorToTeam(GetBonusHonorFromKill(1), TEAM_HORDE);
RewardHonorToTeam(GetBonusHonorFromKill(1), TEAM_ALLIANCE);
Battleground::EndBattleground(winnerTeamId);
_bgEvents.Reset();
}
WorldSafeLocsEntry const* BattlegroundAB::GetClosestGraveyard(Player* player)
{
WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(BG_AB_GraveyardIds[BG_AB_SPIRIT_ALIANCE + player->GetTeamId()]);
WorldSafeLocsEntry const* nearestEntry = entry;
float pX = player->GetPositionX();
float pY = player->GetPositionY();
float dist = (entry->x - pX)*(entry->x - pX)+(entry->y - pY)*(entry->y - pY);
float minDist = dist;
for (uint8 i = BG_AB_NODE_STABLES; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
if (_capturePointInfo[i]._ownerTeamId == player->GetTeamId())
{
entry = sWorldSafeLocsStore.LookupEntry(BG_AB_GraveyardIds[i]);
dist = (entry->x - pX)*(entry->x - pX) + (entry->y - pY)*(entry->y - pY);
if (dist < minDist)
{
minDist = dist;
nearestEntry = entry;
}
}
return nearestEntry;
}
void BattlegroundAB::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
BattlegroundScoreMap::iterator itr = PlayerScores.find(player->GetGUID());
if (itr == PlayerScores.end())
return;
switch (type)
{
case SCORE_BASES_ASSAULTED:
((BattlegroundABScore*)itr->second)->BasesAssaulted += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_AB_OBJECTIVE_ASSAULT_BASE);
break;
case SCORE_BASES_DEFENDED:
((BattlegroundABScore*)itr->second)->BasesDefended += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_AB_OBJECTIVE_DEFEND_BASE);
break;
default:
Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
break;
}
}
bool BattlegroundAB::AllNodesConrolledByTeam(TeamId teamId) const
{
return _controlledPoints[teamId] == BG_AB_DYNAMIC_NODES_COUNT;
}
void BattlegroundAB::ApplyPhaseMask()
{
uint32 phaseMask = 1;
for (uint32 i = BG_AB_NODE_STABLES; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
if (_capturePointInfo[i]._ownerTeamId != TEAM_NEUTRAL)
phaseMask |= 1 << (i*2+1 + _capturePointInfo[i]._ownerTeamId);
const BattlegroundPlayerMap& bgPlayerMap = GetPlayers();
for (BattlegroundPlayerMap::const_iterator itr = bgPlayerMap.begin(); itr != bgPlayerMap.end(); ++itr)
{
itr->second->SetPhaseMask(phaseMask, false);
itr->second->UpdateObjectVisibility(true, false);
}
}

View File

@@ -1,279 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#ifndef __BATTLEGROUNDAB_H
#define __BATTLEGROUNDAB_H
#include "Battleground.h"
enum BG_AB_Events
{
BG_AB_EVENT_UPDATE_BANNER_STABLE = 1,
BG_AB_EVENT_UPDATE_BANNER_FARM = 2,
BG_AB_EVENT_UPDATE_BANNER_BLACKSMITH = 3,
BG_AB_EVENT_UPDATE_BANNER_LUMBERMILL = 4,
BG_AB_EVENT_UPDATE_BANNER_GOLDMINE = 5,
BG_AB_EVENT_CAPTURE_STABLE = 6,
BG_AB_EVENT_CAPTURE_FARM = 7,
BG_AB_EVENT_CAPTURE_BLACKSMITH = 8,
BG_AB_EVENT_CAPTURE_LUMBERMILL = 9,
BG_AB_EVENT_CAPTURE_GOLDMINE = 10,
BG_AB_EVENT_ALLIANCE_TICK = 11,
BG_AB_EVENT_HORDE_TICK = 12
};
enum BG_AB_WorldStates
{
BG_AB_OP_OCCUPIED_BASES_HORDE = 1778,
BG_AB_OP_OCCUPIED_BASES_ALLY = 1779,
BG_AB_OP_RESOURCES_ALLY = 1776,
BG_AB_OP_RESOURCES_HORDE = 1777,
BG_AB_OP_RESOURCES_MAX = 1780,
BG_AB_OP_RESOURCES_WARNING = 1955,
BG_AB_OP_STABLE_ICON = 1842, //Stable map icon (NONE)
BG_AB_OP_STABLE_STATE_ALIENCE = 1767, //Stable map state (ALIENCE)
BG_AB_OP_STABLE_STATE_HORDE = 1768, //Stable map state (HORDE)
BG_AB_OP_STABLE_STATE_CON_ALI = 1769, //Stable map state (CON ALIENCE)
BG_AB_OP_STABLE_STATE_CON_HOR = 1770, //Stable map state (CON HORDE)
BG_AB_OP_FARM_ICON = 1845, //Farm map icon (NONE)
BG_AB_OP_FARM_STATE_ALIENCE = 1772, //Farm state (ALIENCE)
BG_AB_OP_FARM_STATE_HORDE = 1773, //Farm state (HORDE)
BG_AB_OP_FARM_STATE_CON_ALI = 1774, //Farm state (CON ALIENCE)
BG_AB_OP_FARM_STATE_CON_HOR = 1775, //Farm state (CON HORDE)
BG_AB_OP_BLACKSMITH_ICON = 1846, //Blacksmith map icon (NONE)
BG_AB_OP_BLACKSMITH_STATE_ALIENCE = 1782, //Blacksmith map state (ALIENCE)
BG_AB_OP_BLACKSMITH_STATE_HORDE = 1783, //Blacksmith map state (HORDE)
BG_AB_OP_BLACKSMITH_STATE_CON_ALI = 1784, //Blacksmith map state (CON ALIENCE)
BG_AB_OP_BLACKSMITH_STATE_CON_HOR = 1785, //Blacksmith map state (CON HORDE)
BG_AB_OP_LUMBERMILL_ICON = 1844, //Lumber Mill map icon (NONE)
BG_AB_OP_LUMBERMILL_STATE_ALIENCE = 1792, //Lumber Mill map state (ALIENCE)
BG_AB_OP_LUMBERMILL_STATE_HORDE = 1793, //Lumber Mill map state (HORDE)
BG_AB_OP_LUMBERMILL_STATE_CON_ALI = 1794, //Lumber Mill map state (CON ALIENCE)
BG_AB_OP_LUMBERMILL_STATE_CON_HOR = 1795, //Lumber Mill map state (CON HORDE)
BG_AB_OP_GOLDMINE_ICON = 1843, //Gold Mine map icon (NONE)
BG_AB_OP_GOLDMINE_STATE_ALIENCE = 1787, //Gold Mine map state (ALIENCE)
BG_AB_OP_GOLDMINE_STATE_HORDE = 1788, //Gold Mine map state (HORDE)
BG_AB_OP_GOLDMINE_STATE_CON_ALI = 1789, //Gold Mine map state (CON ALIENCE
BG_AB_OP_GOLDMINE_STATE_CON_HOR = 1790, //Gold Mine map state (CON HORDE)
};
enum BG_AB_ObjectIds
{
BG_AB_OBJECTID_NODE_BANNER_0 = 180087, // Stables banner
BG_AB_OBJECTID_NODE_BANNER_1 = 180088, // Blacksmith banner
BG_AB_OBJECTID_NODE_BANNER_2 = 180089, // Farm banner
BG_AB_OBJECTID_NODE_BANNER_3 = 180090, // Lumber mill banner
BG_AB_OBJECTID_NODE_BANNER_4 = 180091, // Gold mine banner
BG_AB_OBJECTID_BANNER_A = 180058,
BG_AB_OBJECTID_BANNER_CONT_A = 180059,
BG_AB_OBJECTID_BANNER_H = 180060,
BG_AB_OBJECTID_BANNER_CONT_H = 180061,
BG_AB_OBJECTID_AURA_A = 180100,
BG_AB_OBJECTID_AURA_H = 180101,
BG_AB_OBJECTID_AURA_C = 180102,
BG_AB_OBJECTID_GATE_A = 180255,
BG_AB_OBJECTID_GATE_H = 180256
};
enum BG_AB_ObjectType
{
BG_AB_OBJECT_BANNER_NEUTRAL = 0,
BG_AB_OBJECT_BANNER_ALLY = 1,
BG_AB_OBJECT_BANNER_HORDE = 2,
BG_AB_OBJECT_BANNER_CONT_A = 3,
BG_AB_OBJECT_BANNER_CONT_H = 4,
BG_AB_OBJECT_AURA_ALLY = 5,
BG_AB_OBJECT_AURA_HORDE = 6,
BG_AB_OBJECT_AURA_CONTESTED = 7,
BG_AB_OBJECTS_PER_NODE = 8,
BG_AB_OBJECT_GATE_A = 40,
BG_AB_OBJECT_GATE_H = 41,
BG_AB_OBJECT_SPEEDBUFF_STABLES = 42,
BG_AB_OBJECT_REGENBUFF_STABLES = 43,
BG_AB_OBJECT_BERSERKBUFF_STABLES = 44,
BG_AB_OBJECT_SPEEDBUFF_BLACKSMITH = 45,
BG_AB_OBJECT_REGENBUFF_BLACKSMITH = 46,
BG_AB_OBJECT_BERSERKBUFF_BLACKSMITH = 47,
BG_AB_OBJECT_SPEEDBUFF_FARM = 48,
BG_AB_OBJECT_REGENBUFF_FARM = 49,
BG_AB_OBJECT_BERSERKBUFF_FARM = 50,
BG_AB_OBJECT_SPEEDBUFF_LUMBER_MILL = 51,
BG_AB_OBJECT_REGENBUFF_LUMBER_MILL = 52,
BG_AB_OBJECT_BERSERKBUFF_LUMBER_MILL = 53,
BG_AB_OBJECT_SPEEDBUFF_GOLD_MINE = 54,
BG_AB_OBJECT_REGENBUFF_GOLD_MINE = 55,
BG_AB_OBJECT_BERSERKBUFF_GOLD_MINE = 56,
BG_AB_OBJECT_MAX = 57,
};
enum BG_AB_BattlegroundNodes
{
BG_AB_NODE_STABLES = 0,
BG_AB_NODE_BLACKSMITH = 1,
BG_AB_NODE_FARM = 2,
BG_AB_NODE_LUMBER_MILL = 3,
BG_AB_NODE_GOLD_MINE = 4,
BG_AB_DYNAMIC_NODES_COUNT = 5, // dynamic nodes that can be captured
BG_AB_SPIRIT_ALIANCE = 5,
BG_AB_SPIRIT_HORDE = 6,
BG_AB_ALL_NODES_COUNT = 7, // all nodes (dynamic and static)
};
enum BG_AB_NodeStatus
{
BG_AB_NODE_STATE_NEUTRAL = 0,
BG_AB_NODE_STATE_ALLY_OCCUPIED = 1,
BG_AB_NODE_STATE_HORDE_OCCUPIED = 2,
BG_AB_NODE_STATE_ALLY_CONTESTED = 3,
BG_AB_NODE_STATE_HORDE_CONTESTED = 4
};
enum BG_AB_Sounds
{
BG_AB_SOUND_NODE_CLAIMED = 8192,
BG_AB_SOUND_NODE_CAPTURED_ALLIANCE = 8173,
BG_AB_SOUND_NODE_CAPTURED_HORDE = 8213,
BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE = 8212,
BG_AB_SOUND_NODE_ASSAULTED_HORDE = 8174,
BG_AB_SOUND_NEAR_VICTORY = 8456
};
enum BG_AB_Misc
{
BG_AB_OBJECTIVE_ASSAULT_BASE = 122,
BG_AB_OBJECTIVE_DEFEND_BASE = 123,
BG_AB_EVENT_START_BATTLE = 9158, // Achievement: Let's Get This Done
BG_AB_QUEST_CREDIT_BASE = 15001,
BG_AB_HONOR_TICK_NORMAL = 260,
BG_AB_HONOR_TICK_WEEKEND = 160,
BG_AB_REP_TICK_NORMAL = 160,
BG_AB_REP_TICK_WEEKEND = 120,
BG_AB_WARNING_NEAR_VICTORY_SCORE = 1400,
BG_AB_MAX_TEAM_SCORE = 1600,
BG_AB_FLAG_CAPTURING_TIME = 60000,
BG_AB_BANNER_UPDATE_TIME = 2000
};
const uint32 BG_AB_TickIntervals[BG_AB_DYNAMIC_NODES_COUNT+1] = {0, 12000, 9000, 6000, 3000, 1000};
const uint32 BG_AB_TickPoints[BG_AB_DYNAMIC_NODES_COUNT+1] = {0, 10, 10, 10, 10, 30};
const uint32 BG_AB_GraveyardIds[BG_AB_ALL_NODES_COUNT] = {895, 894, 893, 897, 896, 898, 899};
const float BG_AB_BuffPositions[BG_AB_DYNAMIC_NODES_COUNT][4] =
{
{1185.71f, 1185.24f, -56.36f, 2.56f}, // stables
{990.75f, 1008.18f, -42.60f, 2.43f}, // blacksmith
{817.66f, 843.34f, -56.54f, 3.01f}, // farm
{807.46f, 1189.16f, 11.92f, 5.44f}, // lumber mill
{1146.62f, 816.94f, -98.49f, 6.14f} // gold mine
};
const float BG_AB_NodePositions[BG_AB_DYNAMIC_NODES_COUNT][4] =
{
{1166.785f, 1200.132f, -56.70859f, 0.9075713f}, // stables
{977.0156f, 1046.616f, -44.80923f, -2.600541f}, // blacksmith
{806.1821f, 874.2723f, -55.99371f, -2.303835f}, // farm
{856.1419f, 1148.902f, 11.18469f, -2.303835f}, // lumber mill
{1146.923f, 848.1782f, -110.917f, -0.7330382f} // gold mine
};
const float BG_AB_DoorPositions[2][8] =
{
{1284.597f, 1281.167f, -15.97792f, 0.7068594f, 0.012957f, -0.060288f, 0.344959f, 0.93659f},
{708.0903f, 708.4479f, -17.8342f, -2.391099f, 0.050291f, 0.015127f, 0.929217f, -0.365784f}
};
const float BG_AB_SpiritGuidePos[BG_AB_ALL_NODES_COUNT][4] =
{
{1200.03f, 1171.09f, -56.47f, 5.15f}, // stables
{1017.43f, 960.61f, -42.95f, 4.88f}, // blacksmith
{833.00f, 793.00f, -57.25f, 5.27f}, // farm
{775.17f, 1206.40f, 15.79f, 1.90f}, // lumber mill
{1207.48f, 787.00f, -83.36f, 5.51f}, // gold mine
{1354.05f, 1275.48f, -11.30f, 4.77f}, // alliance starting base
{714.61f, 646.15f, -10.87f, 4.34f} // horde starting base
};
struct BattlegroundABScore : public BattlegroundScore
{
BattlegroundABScore(Player* player) : BattlegroundScore(player), BasesAssaulted(0), BasesDefended(0) { }
~BattlegroundABScore() { }
uint32 BasesAssaulted;
uint32 BasesDefended;
uint32 GetAttr1() const final override { return BasesAssaulted; }
uint32 GetAttr2() const final override { return BasesDefended; }
};
class BattlegroundAB : public Battleground
{
public:
BattlegroundAB();
~BattlegroundAB();
void AddPlayer(Player* player);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
void RemovePlayer(Player* player);
void HandleAreaTrigger(Player* player, uint32 trigger);
bool SetupBattleground();
void Init();
void EndBattleground(TeamId winnerTeamId);
WorldSafeLocsEntry const* GetClosestGraveyard(Player* player);
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
void FillInitialWorldStates(WorldPacket& data);
void EventPlayerClickedOnFlag(Player* source, GameObject* gameObject);
bool AllNodesConrolledByTeam(TeamId teamId) const;
bool IsTeamScores500Disadvantage(TeamId teamId) const { return _teamScores500Disadvantage[teamId]; }
TeamId GetPrematureWinner();
private:
void PostUpdateImpl(uint32 diff);
void DeleteBanner(uint8 node);
void CreateBanner(uint8 node, bool delay);
void SendNodeUpdate(uint8 node);
void NodeOccupied(uint8 node);
void NodeDeoccupied(uint8 node);
void ApplyPhaseMask();
struct CapturePointInfo
{
CapturePointInfo() : _ownerTeamId(TEAM_NEUTRAL), _iconNone(0), _iconCapture(0), _state(BG_AB_NODE_STATE_NEUTRAL), _captured(false)
{
}
uint8 _state;
uint32 _iconNone;
uint32 _iconCapture;
TeamId _ownerTeamId;
bool _captured;
};
CapturePointInfo _capturePointInfo[BG_AB_DYNAMIC_NODES_COUNT];
EventMap _bgEvents;
uint32 _honorTics;
uint32 _reputationTics;
uint8 _controlledPoints[BG_TEAMS_COUNT];
bool _teamScores500Disadvantage[BG_TEAMS_COUNT];
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,178 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlegroundBE.h"
#include "Language.h"
#include "Object.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "WorldPacket.h"
#include "WorldSession.h"
BattlegroundBE::BattlegroundBE()
{
BgObjects.resize(BG_BE_OBJECT_MAX);
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattlegroundBE::~BattlegroundBE()
{
}
void BattlegroundBE::StartingEventCloseDoors()
{
for (uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
for (uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; ++i)
SpawnBGObject(i, RESPAWN_ONE_DAY);
}
void BattlegroundBE::StartingEventOpenDoors()
{
for (uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_2; ++i)
DoorOpen(i);
for (uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; ++i)
SpawnBGObject(i, 60);
}
void BattlegroundBE::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
Battleground::UpdateArenaWorldState();
}
void BattlegroundBE::RemovePlayer(Player* /*player*/)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundBE::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
{
sLog->outError("Killer player not found");
return;
}
Battleground::HandleKillPlayer(player, killer);
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
bool BattlegroundBE::HandlePlayerUnderMap(Player* player)
{
player->NearTeleportTo(6238.930176f, 262.963470f, 0.889519f, player->GetOrientation());
return true;
}
void BattlegroundBE::HandleAreaTrigger(Player* player, uint32 trigger)
{
// this is wrong way to implement these things. On official it done by gameobject spell cast.
if (GetStatus() != STATUS_IN_PROGRESS)
return;
switch (trigger)
{
case 4538: // buff trigger?
//buff_guid = BgObjects[BG_BE_OBJECT_BUFF_1];
break;
case 4539: // buff trigger?
//buff_guid = BgObjects[BG_BE_OBJECT_BUFF_2];
break;
// OUTSIDE OF ARENA, TELEPORT!
case 4919:
player->NearTeleportTo(6220.90f, 318.94f, 5.1f, 5.3f);
break;
case 4921:
player->NearTeleportTo(6250.27f, 208.50f, 4.77f, 1.9f);
break;
case 4922:
player->NearTeleportTo(6214.4f, 227.12f, 4.28f, 0.8f);
break;
case 4923:
player->NearTeleportTo(6180.98f, 265.28f, 4.27f, 6.06f);
break;
case 4924:
player->NearTeleportTo(6269.0f, 295.06f, 4.46f, 3.98f);
break;
case 4944: // under arena -20
case 5039: // under arena -40
case 5040: // under arena -60
player->NearTeleportTo(6238.930176f, 262.963470f, 0.889519f, player->GetOrientation());
break;
}
}
void BattlegroundBE::FillInitialWorldStates(WorldPacket &data)
{
data << uint32(0x9f3) << uint32(1); // 9
Battleground::UpdateArenaWorldState();
}
void BattlegroundBE::Init()
{
//call parent's class reset
Battleground::Init();
}
bool BattlegroundBE::SetupBattleground()
{
// gates
if (!AddObject(BG_BE_OBJECT_DOOR_1, BG_BE_OBJECT_TYPE_DOOR_1, 6287.277f, 282.1877f, 3.810925f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_BE_OBJECT_DOOR_2, BG_BE_OBJECT_TYPE_DOOR_2, 6189.546f, 241.7099f, 3.101481f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_BE_OBJECT_DOOR_3, BG_BE_OBJECT_TYPE_DOOR_3, 6299.116f, 296.5494f, 3.308032f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_BE_OBJECT_DOOR_4, BG_BE_OBJECT_TYPE_DOOR_4, 6177.708f, 227.3481f, 3.604374f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY)
// buffs
|| !AddObject(BG_BE_OBJECT_BUFF_1, BG_BE_OBJECT_TYPE_BUFF_1, 6249.042f, 275.3239f, 11.22033f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120)
|| !AddObject(BG_BE_OBJECT_BUFF_2, BG_BE_OBJECT_TYPE_BUFF_2, 6228.26f, 249.566f, 11.21812f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120)
// Arena Ready Marker
|| !AddObject(BG_BE_OBJECT_READY_MARKER_1, ARENA_READY_MARKER_ENTRY, 6189.47f, 235.54f, 5.52f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300)
|| !AddObject(BG_BE_OBJECT_READY_MARKER_2, ARENA_READY_MARKER_ENTRY, 6287.19f, 288.25f, 5.33f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300))
{
sLog->outErrorDb("BatteGroundBE: Failed to spawn some object!");
return false;
}
return true;
}
void BattlegroundBE::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
}

View File

@@ -1,69 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDBE_H
#define __BATTLEGROUNDBE_H
#include "Battleground.h"
enum BattlegroundBEObjectTypes
{
BG_BE_OBJECT_DOOR_1 = 0,
BG_BE_OBJECT_DOOR_2 = 1,
BG_BE_OBJECT_DOOR_3 = 2,
BG_BE_OBJECT_DOOR_4 = 3,
BG_BE_OBJECT_BUFF_1 = 4,
BG_BE_OBJECT_BUFF_2 = 5,
BG_BE_OBJECT_READY_MARKER_1 = 6,
BG_BE_OBJECT_READY_MARKER_2 = 7,
BG_BE_OBJECT_MAX = 8
};
enum BattlegroundBEObjects
{
BG_BE_OBJECT_TYPE_DOOR_1 = 183971,
BG_BE_OBJECT_TYPE_DOOR_2 = 183973,
BG_BE_OBJECT_TYPE_DOOR_3 = 183970,
BG_BE_OBJECT_TYPE_DOOR_4 = 183972,
BG_BE_OBJECT_TYPE_BUFF_1 = 184663,
BG_BE_OBJECT_TYPE_BUFF_2 = 184664
};
class BattlegroundBE : public Battleground
{
public:
BattlegroundBE();
~BattlegroundBE();
/* inherited from BattlegroundClass */
void AddPlayer(Player* player);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
void RemovePlayer(Player* player);
void HandleAreaTrigger(Player* player, uint32 trigger);
bool SetupBattleground();
void Init();
void FillInitialWorldStates(WorldPacket &d);
void HandleKillPlayer(Player* player, Player* killer);
bool HandlePlayerUnderMap(Player* player);
/* Scorekeeping */
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
};
#endif

View File

@@ -1,267 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlegroundDS.h"
#include "Creature.h"
#include "GameObject.h"
#include "Language.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "WorldPacket.h"
#include "WorldSession.h"
BattlegroundDS::BattlegroundDS()
{
BgObjects.resize(BG_DS_OBJECT_MAX);
BgCreatures.resize(BG_DS_NPC_MAX);
_waterfallTimer = 0;
_waterfallStatus = 0;
_waterfallKnockbackTimer = 0;
_pipeKnockBackTimer = 0;
_pipeKnockBackCount = 0;
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattlegroundDS::~BattlegroundDS()
{
}
void BattlegroundDS::PostUpdateImpl(uint32 diff)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (getPipeKnockBackCount() < BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT)
{
if (getPipeKnockBackTimer() < diff)
{
for (uint32 i = BG_DS_NPC_PIPE_KNOCKBACK_1; i <= BG_DS_NPC_PIPE_KNOCKBACK_2; ++i)
if (Creature* waterSpout = GetBgMap()->GetCreature(BgCreatures[i]))
waterSpout->CastSpell(waterSpout, BG_DS_SPELL_FLUSH, true);
setPipeKnockBackCount(getPipeKnockBackCount() + 1);
setPipeKnockBackTimer(BG_DS_PIPE_KNOCKBACK_DELAY);
}
else
setPipeKnockBackTimer(getPipeKnockBackTimer() - diff);
}
if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_ON) // Repeat knockback while the waterfall still active
{
if (getWaterFallKnockbackTimer() < diff)
{
if (Creature* waterSpout = GetBgMap()->GetCreature(BgCreatures[BG_DS_NPC_WATERFALL_KNOCKBACK]))
waterSpout->CastSpell(waterSpout, BG_DS_SPELL_WATER_SPOUT, true);
setWaterFallKnockbackTimer(BG_DS_WATERFALL_KNOCKBACK_TIMER);
}
else
setWaterFallKnockbackTimer(getWaterFallKnockbackTimer() - diff);
}
if (getWaterFallTimer() < diff)
{
if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_OFF) // Add the water
{
DoorClose(BG_DS_OBJECT_WATER_2);
setWaterFallTimer(BG_DS_WATERFALL_WARNING_DURATION);
setWaterFallStatus(BG_DS_WATERFALL_STATUS_WARNING);
}
else if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_WARNING) // Active collision and perform knockback
{
if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[BG_DS_OBJECT_WATER_1]))
gob->SetGoState(GO_STATE_READY);
setWaterFallTimer(BG_DS_WATERFALL_DURATION);
setWaterFallStatus(BG_DS_WATERFALL_STATUS_ON);
setWaterFallKnockbackTimer(BG_DS_WATERFALL_KNOCKBACK_TIMER);
}
else //if (getWaterFallStatus() == BG_DS_WATERFALL_STATUS_ON) // Remove collision and water
{
// turn off collision
if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[BG_DS_OBJECT_WATER_1]))
gob->SetGoState(GO_STATE_ACTIVE);
DoorOpen(BG_DS_OBJECT_WATER_2);
setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX));
setWaterFallStatus(BG_DS_WATERFALL_STATUS_OFF);
}
}
else
setWaterFallTimer(getWaterFallTimer() - diff);
}
void BattlegroundDS::StartingEventCloseDoors()
{
for (uint32 i = BG_DS_OBJECT_DOOR_1; i <= BG_DS_OBJECT_DOOR_2; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
void BattlegroundDS::StartingEventOpenDoors()
{
for (uint32 i = BG_DS_OBJECT_DOOR_1; i <= BG_DS_OBJECT_DOOR_2; ++i)
DoorOpen(i);
for (uint32 i = BG_DS_OBJECT_BUFF_1; i <= BG_DS_OBJECT_BUFF_2; ++i)
SpawnBGObject(i, 60);
setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX));
setWaterFallStatus(BG_DS_WATERFALL_STATUS_OFF);
setPipeKnockBackTimer(BG_DS_PIPE_KNOCKBACK_FIRST_DELAY);
setPipeKnockBackCount(0);
SpawnBGObject(BG_DS_OBJECT_WATER_2, RESPAWN_IMMEDIATELY);
DoorOpen(BG_DS_OBJECT_WATER_2);
// Turn off collision
if (GameObject* gob = GetBgMap()->GetGameObject(BgObjects[BG_DS_OBJECT_WATER_1]))
gob->SetGoState(GO_STATE_ACTIVE);
// Remove effects of Demonic Circle Summon
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if (itr->second->HasAura(48018))
itr->second->RemoveAurasDueToSpell(48018);
}
void BattlegroundDS::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
Battleground::UpdateArenaWorldState();
}
void BattlegroundDS::RemovePlayer(Player* /*player*/)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundDS::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
{
sLog->outError("BattlegroundDS: Killer player not found");
return;
}
Battleground::HandleKillPlayer(player, killer);
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundDS::HandleAreaTrigger(Player* player, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
switch (trigger)
{
case 5347:
case 5348:
// Remove effects of Demonic Circle Summon
if (player->HasAura(48018))
player->RemoveAurasDueToSpell(48018);
// Someone has get back into the pipes and the knockback has already been performed,
// so we reset the knockback count for kicking the player again into the arena.
if (getPipeKnockBackCount() >= BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT)
setPipeKnockBackCount(0);
break;
// OUTSIDE OF ARENA, TELEPORT!
case 5328:
player->NearTeleportTo(1290.44f, 744.96f, 3.16f, 1.6f);
break;
case 5329:
player->NearTeleportTo(1292.6f, 837.07f, 3.161f, 4.7f);
break;
case 5330:
player->NearTeleportTo(1250.68f, 790.86f, 3.16f, 0.0f);
break;
case 5331:
player->NearTeleportTo(1332.50f, 790.9f, 3.16f, 3.14f);
break;
case 5326: // -10
case 5343: // -40
case 5344: // -60
player->NearTeleportTo(1330.0f, 800.0f, 3.16f, player->GetOrientation());
break;
}
}
bool BattlegroundDS::HandlePlayerUnderMap(Player* player)
{
player->NearTeleportTo(1299.046f, 784.825f, 9.338f, 2.422f);
return true;
}
void BattlegroundDS::FillInitialWorldStates(WorldPacket &data)
{
data << uint32(3610) << uint32(1); // 9 show
Battleground::UpdateArenaWorldState();
}
void BattlegroundDS::Init()
{
//call parent's class reset
Battleground::Init();
}
bool BattlegroundDS::SetupBattleground()
{
// gates
if (!AddObject(BG_DS_OBJECT_DOOR_1, BG_DS_OBJECT_TYPE_DOOR_1, 1350.95f, 817.2f, 20.8096f, 3.15f, 0, 0, 0.99627f, 0.0862864f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_DS_OBJECT_DOOR_2, BG_DS_OBJECT_TYPE_DOOR_2, 1232.65f, 764.913f, 20.0729f, 6.3f, 0, 0, 0.0310211f, -0.999519f, RESPAWN_IMMEDIATELY)
// water
|| !AddObject(BG_DS_OBJECT_WATER_1, BG_DS_OBJECT_TYPE_WATER_1, 1291.56f, 790.837f, 7.1f, 3.14238f, 0, 0, 0.694215f, -0.719768f, 120)
|| !AddObject(BG_DS_OBJECT_WATER_2, BG_DS_OBJECT_TYPE_WATER_2, 1291.56f, 790.837f, 7.1f, 3.14238f, 0, 0, 0.694215f, -0.719768f, 120)
// buffs
|| !AddObject(BG_DS_OBJECT_BUFF_1, BG_DS_OBJECT_TYPE_BUFF_1, 1291.7f, 813.424f, 7.11472f, 4.64562f, 0, 0, 0.730314f, -0.683111f, 120)
|| !AddObject(BG_DS_OBJECT_BUFF_2, BG_DS_OBJECT_TYPE_BUFF_2, 1291.7f, 768.911f, 7.11472f, 1.55194f, 0, 0, 0.700409f, 0.713742f, 120)
// knockback creatures
|| !AddCreature(BG_DS_NPC_TYPE_WATER_SPOUT, BG_DS_NPC_WATERFALL_KNOCKBACK, 1291.76f, 791.02f, 7.115f, 3.054326f, RESPAWN_IMMEDIATELY)
|| !AddCreature(BG_DS_NPC_TYPE_WATER_SPOUT, BG_DS_NPC_PIPE_KNOCKBACK_1, 1369.977f, 817.2882f, 16.08718f, 3.106686f, RESPAWN_IMMEDIATELY)
|| !AddCreature(BG_DS_NPC_TYPE_WATER_SPOUT, BG_DS_NPC_PIPE_KNOCKBACK_2, 1212.833f, 765.3871f, 16.09484f, 0.0f, RESPAWN_IMMEDIATELY)
// Arena Ready Marker
|| !AddObject(BG_DS_OBJECT_READY_MARKER_1, ARENA_READY_MARKER_ENTRY, 1229.44f, 759.35f, 17.89f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300)
|| !AddObject(BG_DS_OBJECT_READY_MARKER_2, ARENA_READY_MARKER_ENTRY, 1352.90f, 822.77f, 17.96f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300))
{
sLog->outErrorDb("BatteGroundDS: Failed to spawn some object!");
return false;
}
return true;
}

View File

@@ -1,122 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDDS_H
#define __BATTLEGROUNDDS_H
#include "Battleground.h"
enum BattlegroundDSObjectTypes
{
BG_DS_OBJECT_DOOR_1 = 0,
BG_DS_OBJECT_DOOR_2 = 1,
BG_DS_OBJECT_WATER_1 = 2, // Collision
BG_DS_OBJECT_WATER_2 = 3,
BG_DS_OBJECT_BUFF_1 = 4,
BG_DS_OBJECT_BUFF_2 = 5,
BG_DS_OBJECT_READY_MARKER_1 = 6,
BG_DS_OBJECT_READY_MARKER_2 = 7,
BG_DS_OBJECT_MAX = 8
};
enum BattlegroundDSObjects
{
BG_DS_OBJECT_TYPE_DOOR_1 = 192642,
BG_DS_OBJECT_TYPE_DOOR_2 = 192643,
BG_DS_OBJECT_TYPE_WATER_1 = 194395, // Collision
BG_DS_OBJECT_TYPE_WATER_2 = 191877,
BG_DS_OBJECT_TYPE_BUFF_1 = 184663,
BG_DS_OBJECT_TYPE_BUFF_2 = 184664
};
enum BattlegroundDSCreatureTypes
{
BG_DS_NPC_WATERFALL_KNOCKBACK = 0,
BG_DS_NPC_PIPE_KNOCKBACK_1 = 1,
BG_DS_NPC_PIPE_KNOCKBACK_2 = 2,
BG_DS_NPC_MAX = 3
};
enum BattlegroundDSCreatures
{
BG_DS_NPC_TYPE_WATER_SPOUT = 28567,
};
enum BattlegroundDSSpells
{
BG_DS_SPELL_FLUSH = 57405, // Visual and target selector for the starting knockback from the pipe
BG_DS_SPELL_FLUSH_KNOCKBACK = 61698, // Knockback effect for previous spell (triggered, not need to be casted)
BG_DS_SPELL_WATER_SPOUT = 58873, // Knockback effect of the central waterfall
};
enum BattlegroundDSData
{ // These values are NOT blizzlike... need the correct data!
BG_DS_WATERFALL_TIMER_MIN = 30000,
BG_DS_WATERFALL_TIMER_MAX = 60000,
BG_DS_WATERFALL_WARNING_DURATION = 5000,
BG_DS_WATERFALL_DURATION = 30000,
BG_DS_WATERFALL_KNOCKBACK_TIMER = 1500,
BG_DS_PIPE_KNOCKBACK_FIRST_DELAY = 5000,
BG_DS_PIPE_KNOCKBACK_DELAY = 3000,
BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT = 2,
BG_DS_WATERFALL_STATUS_WARNING = 1, // Water starting to fall, but no LoS Blocking nor movement blocking
BG_DS_WATERFALL_STATUS_ON = 2, // LoS and Movement blocking active
BG_DS_WATERFALL_STATUS_OFF = 3,
};
class BattlegroundDS : public Battleground
{
public:
BattlegroundDS();
~BattlegroundDS();
/* inherited from BattlegroundClass */
void AddPlayer(Player* player);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
void RemovePlayer(Player* player);
void HandleAreaTrigger(Player* player, uint32 trigger);
bool SetupBattleground();
void Init();
void FillInitialWorldStates(WorldPacket &d);
void HandleKillPlayer(Player* player, Player* killer);
bool HandlePlayerUnderMap(Player* player);
private:
uint32 _waterfallTimer;
uint8 _waterfallStatus;
uint32 _waterfallKnockbackTimer;
uint32 _pipeKnockBackTimer;
uint8 _pipeKnockBackCount;
void PostUpdateImpl(uint32 diff);
protected:
uint32 getWaterFallStatus() { return _waterfallStatus; };
void setWaterFallStatus(uint8 status) { _waterfallStatus = status; };
uint32 getWaterFallTimer() { return _waterfallTimer; };
void setWaterFallTimer(uint32 timer) { _waterfallTimer = timer; };
uint32 getWaterFallKnockbackTimer() { return _waterfallKnockbackTimer; };
void setWaterFallKnockbackTimer(uint32 timer) { _waterfallKnockbackTimer = timer; };
uint8 getPipeKnockBackCount() { return _pipeKnockBackCount; };
void setPipeKnockBackCount(uint8 count) { _pipeKnockBackCount = count; };
uint32 getPipeKnockBackTimer() { return _pipeKnockBackTimer; };
void setPipeKnockBackTimer(uint32 timer) { _pipeKnockBackTimer = timer; };
};
#endif

View File

@@ -1,610 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#include "BattlegroundEY.h"
#include "ObjectMgr.h"
#include "World.h"
#include "WorldPacket.h"
#include "BattlegroundMgr.h"
#include "Creature.h"
#include "Language.h"
#include "Object.h"
#include "Player.h"
#include "Util.h"
#include "WorldSession.h"
BattlegroundEY::BattlegroundEY()
{
m_BuffChange = true;
BgObjects.resize(BG_EY_OBJECT_MAX);
BgCreatures.resize(BG_EY_CREATURES_MAX);
_capturePointInfo[POINT_FEL_REAVER]._areaTrigger = AT_FEL_REAVER_BUFF;
_capturePointInfo[POINT_BLOOD_ELF]._areaTrigger = AT_BLOOD_ELF_BUFF;
_capturePointInfo[POINT_DRAENEI_RUINS]._areaTrigger = AT_DRAENEI_RUINS_BUFF;
_capturePointInfo[POINT_MAGE_TOWER]._areaTrigger = AT_MAGE_TOWER_BUFF;
_honorTics = 0;
_ownedPointsCount[TEAM_ALLIANCE] = 0;
_ownedPointsCount[TEAM_HORDE] = 0;
_flagKeeperGUID = 0;
_droppedFlagGUID = 0;
_flagState = BG_EY_FLAG_STATE_ON_BASE;
_flagCapturedObject = 0;
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN;
}
BattlegroundEY::~BattlegroundEY()
{
}
void BattlegroundEY::PostUpdateImpl(uint32 diff)
{
if (GetStatus() == STATUS_IN_PROGRESS)
{
_bgEvents.Update(diff);
while (uint32 eventId = _bgEvents.ExecuteEvent())
switch (eventId)
{
case BG_EY_EVENT_ADD_POINTS:
if (_ownedPointsCount[TEAM_ALLIANCE] > 0)
AddPoints(TEAM_ALLIANCE, BG_EY_TickPoints[_ownedPointsCount[TEAM_ALLIANCE] - 1]);
if (_ownedPointsCount[TEAM_HORDE] > 0)
AddPoints(TEAM_HORDE, BG_EY_TickPoints[_ownedPointsCount[TEAM_HORDE] - 1]);
_bgEvents.ScheduleEvent(BG_EY_EVENT_ADD_POINTS, BG_EY_FPOINTS_TICK_TIME - (World::GetGameTimeMS() % BG_EY_FPOINTS_TICK_TIME));
break;
case BG_EY_EVENT_FLAG_ON_GROUND:
RespawnFlagAfterDrop();
break;
case BG_EY_EVENT_RESPAWN_FLAG:
RespawnFlag();
break;
case BG_EY_EVENT_CHECK_CPOINTS:
UpdatePointsState();
_bgEvents.ScheduleEvent(BG_EY_EVENT_CHECK_CPOINTS, BG_EY_FPOINTS_CHECK_TIME - (World::GetGameTimeMS() % BG_EY_FPOINTS_CHECK_TIME));
break;
}
}
}
void BattlegroundEY::StartingEventCloseDoors()
{
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY);
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY);
for (uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER; i < BG_EY_OBJECT_MAX; ++i)
SpawnBGObject(i, RESPAWN_ONE_DAY);
}
void BattlegroundEY::StartingEventOpenDoors()
{
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_ONE_DAY);
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_ONE_DAY);
for (uint32 i = BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER; i <= BG_EY_OBJECT_FLAG_NETHERSTORM; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
for (uint32 i = 0; i < EY_POINTS_MAX; ++i)
SpawnBGObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REAVER + i*3 + urand(0, 2), RESPAWN_IMMEDIATELY);
// Achievement: Flurry
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, BG_EY_EVENT_START_BATTLE);
_bgEvents.ScheduleEvent(BG_EY_EVENT_ADD_POINTS, 0);
_bgEvents.ScheduleEvent(BG_EY_EVENT_CHECK_CPOINTS, 0);
}
void BattlegroundEY::AddPoints(TeamId teamId, uint32 points)
{
uint8 honorRewards = uint8(m_TeamScores[teamId] / _honorTics);
m_TeamScores[teamId] += points;
for (; honorRewards < uint8(m_TeamScores[teamId] / _honorTics); ++honorRewards)
RewardHonorToTeam(GetBonusHonorFromKill(1), teamId);
UpdateWorldState(teamId == TEAM_ALLIANCE ? EY_ALLIANCE_RESOURCES : EY_HORDE_RESOURCES, std::min<uint32>(m_TeamScores[teamId], BG_EY_MAX_TEAM_SCORE));
if (m_TeamScores[teamId] >= BG_EY_MAX_TEAM_SCORE)
EndBattleground(teamId);
}
void BattlegroundEY::UpdatePointsState()
{
std::vector<GameObject*> pointsVec;
for (uint8 point = 0; point < EY_POINTS_MAX; ++point)
{
pointsVec.push_back(GetBGObject(BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + point));
_capturePointInfo[point]._playersCount[TEAM_ALLIANCE] = 0;
_capturePointInfo[point]._playersCount[TEAM_HORDE] = 0;
}
const BattlegroundPlayerMap& bgPlayerMap = GetPlayers();
for (BattlegroundPlayerMap::const_iterator itr = bgPlayerMap.begin(); itr != bgPlayerMap.end(); ++itr)
{
UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_DONT_SHOW, itr->second);
for (uint8 point = 0; point < EY_POINTS_MAX; ++point)
if (GameObject* pointObject = pointsVec[point])
if (itr->second->CanCaptureTowerPoint() && itr->second->IsWithinDistInMap(pointObject, BG_EY_POINT_RADIUS))
{
UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_SHOW, itr->second);
UpdateWorldStateForPlayer(PROGRESS_BAR_PERCENT_GREY, BG_EY_PROGRESS_BAR_PERCENT_GREY, itr->second);
UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, _capturePointInfo[point]._barStatus, itr->second);
++_capturePointInfo[point]._playersCount[itr->second->GetTeamId()];
// Xinef: ugly hax... area trigger is no longer called by client...
if (pointObject->GetEntry() == BG_OBJECT_FR_TOWER_CAP_EY_ENTRY && itr->second->GetDistance2d(2043.96f, 1729.68f) < 3.0f)
HandleAreaTrigger(itr->second, AT_FEL_REAVER_POINT);
}
}
for (uint8 point = 0; point < EY_POINTS_MAX; ++point)
{
_capturePointInfo[point]._barStatus += std::max<int8>(std::min<int8>(_capturePointInfo[point]._playersCount[TEAM_ALLIANCE] - _capturePointInfo[point]._playersCount[TEAM_HORDE], BG_EY_POINT_MAX_CAPTURERS_COUNT), -BG_EY_POINT_MAX_CAPTURERS_COUNT);
_capturePointInfo[point]._barStatus = std::max<int8>(std::min<int8>(_capturePointInfo[point]._barStatus, BG_EY_PROGRESS_BAR_ALI_CONTROLLED), BG_EY_PROGRESS_BAR_HORDE_CONTROLLED);
TeamId pointOwnerTeamId = TEAM_NEUTRAL;
if (_capturePointInfo[point]._barStatus <= BG_EY_PROGRESS_BAR_NEUTRAL_LOW)
pointOwnerTeamId = TEAM_HORDE;
else if (_capturePointInfo[point]._barStatus >= BG_EY_PROGRESS_BAR_NEUTRAL_HIGH)
pointOwnerTeamId = TEAM_ALLIANCE;
if (pointOwnerTeamId != _capturePointInfo[point]._ownerTeamId)
{
if (_capturePointInfo[point].IsUncontrolled())
EventTeamCapturedPoint(pointOwnerTeamId, point);
if (pointOwnerTeamId == TEAM_NEUTRAL && _capturePointInfo[point].IsUnderControl())
EventTeamLostPoint(pointOwnerTeamId, point);
}
}
}
void BattlegroundEY::EndBattleground(TeamId winnerTeamId)
{
RewardHonorToTeam(GetBonusHonorFromKill(1), winnerTeamId);
RewardHonorToTeam(GetBonusHonorFromKill(1), TEAM_ALLIANCE);
RewardHonorToTeam(GetBonusHonorFromKill(1), TEAM_HORDE);
Battleground::EndBattleground(winnerTeamId);
}
void BattlegroundEY::UpdatePointsCount()
{
UpdateWorldState(EY_ALLIANCE_BASE, _ownedPointsCount[TEAM_ALLIANCE]);
UpdateWorldState(EY_HORDE_BASE, _ownedPointsCount[TEAM_HORDE]);
}
void BattlegroundEY::UpdatePointsIcons(uint32 point)
{
if (_capturePointInfo[point].IsUnderControl())
{
UpdateWorldState(m_PointsIconStruct[point].WorldStateControlIndex, 0);
UpdateWorldState(m_PointsIconStruct[point].WorldStateAllianceControlledIndex, _capturePointInfo[point].IsUnderControl(TEAM_ALLIANCE));
UpdateWorldState(m_PointsIconStruct[point].WorldStateHordeControlledIndex, _capturePointInfo[point].IsUnderControl(TEAM_HORDE));
}
else
{
UpdateWorldState(m_PointsIconStruct[point].WorldStateAllianceControlledIndex, 0);
UpdateWorldState(m_PointsIconStruct[point].WorldStateHordeControlledIndex, 0);
UpdateWorldState(m_PointsIconStruct[point].WorldStateControlIndex, 1);
}
}
void BattlegroundEY::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundEYScore(player);
}
void BattlegroundEY::RemovePlayer(Player* player)
{
if (GetFlagPickerGUID() == player->GetGUID())
EventPlayerDroppedFlag(player);
}
void BattlegroundEY::HandleAreaTrigger(Player* player, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS || !player->IsAlive())
return;
switch (trigger)
{
case AT_BLOOD_ELF_POINT:
if (_capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(player->GetTeamId()))
if (_flagState == BG_EY_FLAG_STATE_ON_PLAYER && GetFlagPickerGUID() == player->GetGUID())
EventPlayerCapturedFlag(player, BG_EY_OBJECT_FLAG_BLOOD_ELF);
break;
case AT_FEL_REAVER_POINT:
if (_capturePointInfo[POINT_FEL_REAVER].IsUnderControl(player->GetTeamId()))
if (_flagState == BG_EY_FLAG_STATE_ON_PLAYER && GetFlagPickerGUID() == player->GetGUID())
EventPlayerCapturedFlag(player, BG_EY_OBJECT_FLAG_FEL_REAVER);
break;
case AT_MAGE_TOWER_POINT:
if (_capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(player->GetTeamId()))
if (_flagState == BG_EY_FLAG_STATE_ON_PLAYER && GetFlagPickerGUID() == player->GetGUID())
EventPlayerCapturedFlag(player, BG_EY_OBJECT_FLAG_MAGE_TOWER);
break;
case AT_DRAENEI_RUINS_POINT:
if (_capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(player->GetTeamId()))
if (_flagState == BG_EY_FLAG_STATE_ON_PLAYER && GetFlagPickerGUID() == player->GetGUID())
EventPlayerCapturedFlag(player, BG_EY_OBJECT_FLAG_DRAENEI_RUINS);
break;
case 4512:
case 4515:
case 4517:
case 4519:
case 4530:
case 4531:
case 5866:
case AT_BLOOD_ELF_BUFF:
case AT_FEL_REAVER_BUFF:
case AT_MAGE_TOWER_BUFF:
case AT_DRAENEI_RUINS_BUFF:
break;
}
}
bool BattlegroundEY::SetupBattleground()
{
// doors
AddObject(BG_EY_OBJECT_DOOR_A, BG_OBJECT_A_DOOR_EY_ENTRY, 2527.6f, 1596.91f, 1262.13f, -3.12414f, -0.173642f, -0.001515f, 0.98477f, -0.008594f, RESPAWN_IMMEDIATELY);
AddObject(BG_EY_OBJECT_DOOR_H, BG_OBJECT_H_DOOR_EY_ENTRY, 1803.21f, 1539.49f, 1261.09f, 3.14159f, 0.173648f, 0, 0.984808f, 0, RESPAWN_IMMEDIATELY);
// banners (alliance)
AddObject(BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_FEL_REAVER_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_FEL_REAVER_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY);
// banners (horde)
AddObject(BG_EY_OBJECT_H_BANNER_FEL_REAVER_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_FEL_REAVER_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_FEL_REAVER_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY);
// banners (natural)
AddObject(BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_FEL_REAVER_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_FEL_REAVER_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY);
// flags
AddObject(BG_EY_OBJECT_FLAG_NETHERSTORM, BG_OBJECT_FLAG2_EY_ENTRY, 2174.782227f, 1569.054688f, 1160.361938f, -1.448624f, 0, 0, 0.662620f, -0.748956f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_FLAG_FEL_REAVER, BG_OBJECT_FLAG1_EY_ENTRY, 2044.28f, 1729.68f, 1189.96f, -0.017453f, 0, 0, 0.008727f, -0.999962f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_FLAG_BLOOD_ELF, BG_OBJECT_FLAG1_EY_ENTRY, 2048.83f, 1393.65f, 1194.49f, 0.20944f, 0, 0, 0.104528f, 0.994522f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_FLAG_DRAENEI_RUINS, BG_OBJECT_FLAG1_EY_ENTRY, 2286.56f, 1402.36f, 1197.11f, 3.72381f, 0, 0, 0.957926f, -0.287016f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_FLAG_MAGE_TOWER, BG_OBJECT_FLAG1_EY_ENTRY, 2284.48f, 1731.23f, 1189.99f, 2.89725f, 0, 0, 0.992546f, 0.121869f, RESPAWN_ONE_DAY);
// tower cap
AddObject(BG_EY_OBJECT_TOWER_CAP_FEL_REAVER, BG_OBJECT_FR_TOWER_CAP_EY_ENTRY, 2024.600708f, 1742.819580f, 1195.157715f, 2.443461f, 0, 0, 0.939693f, 0.342020f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_TOWER_CAP_BLOOD_ELF, BG_OBJECT_BE_TOWER_CAP_EY_ENTRY, 2050.493164f, 1372.235962f, 1194.563477f, 1.710423f, 0, 0, 0.754710f, 0.656059f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_TOWER_CAP_DRAENEI_RUINS, BG_OBJECT_DR_TOWER_CAP_EY_ENTRY, 2301.010498f, 1386.931641f, 1197.183472f, 1.570796f, 0, 0, 0.707107f, 0.707107f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_TOWER_CAP_MAGE_TOWER, BG_OBJECT_HU_TOWER_CAP_EY_ENTRY, 2282.121582f, 1760.006958f, 1189.707153f, 1.919862f, 0, 0, 0.819152f, 0.573576f, RESPAWN_ONE_DAY);
for (uint8 i = 0; i < EY_POINTS_MAX; ++i)
{
AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(_capturePointInfo[i]._areaTrigger);
AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REAVER + i * 3 + 0, Buff_Entries[0], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REAVER + i * 3 + 1, Buff_Entries[1], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY);
AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REAVER + i * 3 + 2, Buff_Entries[2], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY);
}
WorldSafeLocsEntry const* sg = NULL;
sg = sWorldSafeLocsStore.LookupEntry(BG_EY_GRAVEYARD_MAIN_ALLIANCE);
AddSpiritGuide(BG_EY_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, TEAM_ALLIANCE);
sg = sWorldSafeLocsStore.LookupEntry(BG_EY_GRAVEYARD_MAIN_HORDE);
AddSpiritGuide(BG_EY_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, TEAM_HORDE);
for (uint32 i = BG_EY_OBJECT_DOOR_A; i < BG_EY_OBJECT_MAX; ++i)
if (BgObjects[i] == 0)
{
sLog->outErrorDb("BatteGroundEY: Failed to spawn some object Battleground not created!");
return false;
}
for (uint32 i = BG_EY_SPIRIT_MAIN_ALLIANCE; i <= BG_EY_SPIRIT_MAIN_HORDE; ++i)
if (BgCreatures[i] == 0)
{
sLog->outErrorDb("BatteGroundEY: Failed to spawn spirit guides Battleground not created!");
return false;
}
return true;
}
void BattlegroundEY::Init()
{
//call parent's class reset
Battleground::Init();
_bgEvents.Reset();
_honorTics = BattlegroundMgr::IsBGWeekend(GetBgTypeID()) ? BG_EY_HONOR_TICK_WEEKEND : BG_EY_HONOR_TICK_NORMAL;
_ownedPointsCount[TEAM_ALLIANCE] = 0;
_ownedPointsCount[TEAM_HORDE] = 0;
_flagKeeperGUID = 0;
_droppedFlagGUID = 0;
_flagState = BG_EY_FLAG_STATE_ON_BASE;
_flagCapturedObject = 0;
}
void BattlegroundEY::RespawnFlag()
{
if (_flagState != BG_EY_FLAG_STATE_ON_BASE)
return;
if (_flagCapturedObject > 0)
SpawnBGObject(_flagCapturedObject, RESPAWN_ONE_DAY);
_flagCapturedObject = 0;
SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_IMMEDIATELY);
SendMessageToAll(LANG_BG_EY_RESETED_FLAG, CHAT_MSG_BG_SYSTEM_NEUTRAL);
PlaySoundToAll(BG_EY_SOUND_FLAG_RESET);
UpdateWorldState(NETHERSTORM_FLAG, 1);
}
void BattlegroundEY::RespawnFlagAfterDrop()
{
if (_flagState != BG_EY_FLAG_STATE_ON_GROUND)
return;
_flagState = BG_EY_FLAG_STATE_ON_BASE;
RespawnFlag();
if (GameObject* flag = ObjectAccessor::GetObjectInMap(GetDroppedFlagGUID(), FindBgMap(), (GameObject*)NULL))
flag->Delete();
SetDroppedFlagGUID(0);
}
void BattlegroundEY::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
Battleground::HandleKillPlayer(player, killer);
EventPlayerDroppedFlag(player);
}
void BattlegroundEY::EventPlayerDroppedFlag(Player* player)
{
if (GetFlagPickerGUID() != player->GetGUID())
return;
SetFlagPicker(0);
player->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL);
if (GetStatus() != STATUS_IN_PROGRESS)
return;
_flagState = BG_EY_FLAG_STATE_ON_GROUND;
_bgEvents.RescheduleEvent(BG_EY_EVENT_FLAG_ON_GROUND, BG_EY_FLAG_ON_GROUND_TIME);
player->CastSpell(player, SPELL_RECENTLY_DROPPED_FLAG, true);
player->CastSpell(player, BG_EY_PLAYER_DROPPED_FLAG_SPELL, true);
SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, player->GetTeamId() == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE);
}
void BattlegroundEY::EventPlayerClickedOnFlag(Player* player, GameObject* gameObject)
{
if (GetStatus() != STATUS_IN_PROGRESS || GetFlagPickerGUID() || !player->IsWithinDistInMap(gameObject, 10.0f))
return;
_flagState = BG_EY_FLAG_STATE_ON_PLAYER;
SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_ONE_DAY);
SetFlagPicker(player->GetGUID());
SetDroppedFlagGUID(0);
player->CastSpell(player, BG_EY_NETHERSTORM_FLAG_SPELL, true);
player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
PSendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG, player->GetTeamId() == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE, NULL, player->GetName().c_str());
PlaySoundToAll(player->GetTeamId() == TEAM_ALLIANCE ? BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE : BG_EY_SOUND_FLAG_PICKED_UP_HORDE);
UpdateWorldState(NETHERSTORM_FLAG, 0);
}
void BattlegroundEY::EventTeamLostPoint(TeamId teamId, uint32 point)
{
TeamId oldTeamId = _capturePointInfo[point]._ownerTeamId;
if (oldTeamId == TEAM_ALLIANCE)
{
_ownedPointsCount[TEAM_ALLIANCE]--;
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeAlliance, RESPAWN_ONE_DAY);
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeAlliance + 1, RESPAWN_ONE_DAY);
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeAlliance + 2, RESPAWN_ONE_DAY);
SendMessageToAll(m_LosingPointTypes[point].MessageIdAlliance, CHAT_MSG_BG_SYSTEM_ALLIANCE);
}
else
{
_ownedPointsCount[TEAM_HORDE]--;
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde, RESPAWN_ONE_DAY);
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde + 1, RESPAWN_ONE_DAY);
SpawnBGObject(m_LosingPointTypes[point].DespawnObjectTypeHorde + 2, RESPAWN_ONE_DAY);
SendMessageToAll(m_LosingPointTypes[point].MessageIdHorde, CHAT_MSG_BG_SYSTEM_HORDE);
}
SpawnBGObject(m_LosingPointTypes[point].SpawnNeutralObjectType, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_LosingPointTypes[point].SpawnNeutralObjectType + 1, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_LosingPointTypes[point].SpawnNeutralObjectType + 2, RESPAWN_IMMEDIATELY);
_capturePointInfo[point]._ownerTeamId = TEAM_NEUTRAL;
UpdatePointsIcons(point);
UpdatePointsCount();
DelCreature(BG_EY_TRIGGER_FEL_REAVER + point);
}
void BattlegroundEY::EventTeamCapturedPoint(TeamId teamId, uint32 point)
{
SpawnBGObject(m_CapturingPointTypes[point].DespawnNeutralObjectType, RESPAWN_ONE_DAY);
SpawnBGObject(m_CapturingPointTypes[point].DespawnNeutralObjectType + 1, RESPAWN_ONE_DAY);
SpawnBGObject(m_CapturingPointTypes[point].DespawnNeutralObjectType + 2, RESPAWN_ONE_DAY);
if (teamId == TEAM_ALLIANCE)
{
_ownedPointsCount[TEAM_ALLIANCE]++;
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeAlliance, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeAlliance + 1, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeAlliance + 2, RESPAWN_IMMEDIATELY);
SendMessageToAll(m_CapturingPointTypes[point].MessageIdAlliance, CHAT_MSG_BG_SYSTEM_ALLIANCE);
}
else
{
_ownedPointsCount[TEAM_HORDE]++;
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde + 1, RESPAWN_IMMEDIATELY);
SpawnBGObject(m_CapturingPointTypes[point].SpawnObjectTypeHorde + 2, RESPAWN_IMMEDIATELY);
SendMessageToAll(m_CapturingPointTypes[point].MessageIdHorde, CHAT_MSG_BG_SYSTEM_HORDE);
}
_capturePointInfo[point]._ownerTeamId = teamId;
if (BgCreatures[point])
DelCreature(point);
WorldSafeLocsEntry const* sg = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[point].GraveYardId);
AddSpiritGuide(point, sg->x, sg->y, sg->z, 3.124139f, teamId);
UpdatePointsIcons(point);
UpdatePointsCount();
// Xinef: done this way to avoid errors in console
Creature* trigger = GetBgMap()->GetCreature(BgCreatures[BG_EY_TRIGGER_FEL_REAVER + point]);
if (!trigger)
trigger = AddCreature(WORLD_TRIGGER, BG_EY_TRIGGER_FEL_REAVER + point, BG_EY_TriggerPositions[point][0], BG_EY_TriggerPositions[point][1], BG_EY_TriggerPositions[point][2], BG_EY_TriggerPositions[point][3]);
if (trigger)
{
trigger->setFaction(teamId == TEAM_ALLIANCE ? 84 : 83);
trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, true);
}
}
void BattlegroundEY::EventPlayerCapturedFlag(Player* player, uint32 BgObjectType)
{
SetFlagPicker(0);
_flagState = BG_EY_FLAG_STATE_ON_BASE;
player->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL);
player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
SpawnBGObject(BgObjectType, RESPAWN_IMMEDIATELY);
_bgEvents.RescheduleEvent(BG_EY_EVENT_RESPAWN_FLAG, BG_EY_FLAG_RESPAWN_TIME);
_flagCapturedObject = BgObjectType;
if (player->GetTeamId() == TEAM_ALLIANCE)
{
PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE);
SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_A, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
}
else
{
PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_HORDE);
SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_H, CHAT_MSG_BG_SYSTEM_HORDE, player);
}
UpdatePlayerScore(player, SCORE_FLAG_CAPTURES, 1);
if (_ownedPointsCount[player->GetTeamId()] > 0)
AddPoints(player->GetTeamId(), BG_EY_FlagPoints[_ownedPointsCount[player->GetTeamId()] - 1]);
}
void BattlegroundEY::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
{
if (type == SCORE_FLAG_CAPTURES)
{
BattlegroundScoreMap::iterator itr = PlayerScores.find(player->GetGUID());
if (itr != PlayerScores.end())
((BattlegroundEYScore*)itr->second)->FlagCaptures += value;
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, BG_EY_OBJECTIVE_CAPTURE_FLAG);
return;
}
Battleground::UpdatePlayerScore(player, type, value, doAddHonor);
}
void BattlegroundEY::FillInitialWorldStates(WorldPacket& data)
{
data << uint32(EY_HORDE_BASE) << uint32(_ownedPointsCount[TEAM_HORDE]);
data << uint32(EY_ALLIANCE_BASE) << uint32(_ownedPointsCount[TEAM_ALLIANCE]);
data << uint32(DRAENEI_RUINS_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_HORDE));
data << uint32(DRAENEI_RUINS_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_ALLIANCE));
data << uint32(DRAENEI_RUINS_UNCONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUncontrolled());
data << uint32(MAGE_TOWER_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_HORDE));
data << uint32(MAGE_TOWER_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_ALLIANCE));
data << uint32(MAGE_TOWER_UNCONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUncontrolled());
data << uint32(FEL_REAVER_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_HORDE));
data << uint32(FEL_REAVER_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_ALLIANCE));
data << uint32(FEL_REAVER_UNCONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUncontrolled());
data << uint32(BLOOD_ELF_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_HORDE));
data << uint32(BLOOD_ELF_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_ALLIANCE));
data << uint32(BLOOD_ELF_UNCONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUncontrolled());
data << uint32(NETHERSTORM_FLAG) << uint32(_flagState == BG_EY_FLAG_STATE_ON_BASE);
data << uint32(NETHERSTORM_FLAG_STATE_HORDE) << uint32(1);
data << uint32(NETHERSTORM_FLAG_STATE_ALLIANCE) << uint32(1);
data << uint32(EY_HORDE_RESOURCES) << uint32(GetTeamScore(TEAM_HORDE));
data << uint32(EY_ALLIANCE_RESOURCES) << uint32(GetTeamScore(TEAM_ALLIANCE));
data << uint32(PROGRESS_BAR_SHOW) << uint32(0);
data << uint32(PROGRESS_BAR_PERCENT_GREY) << uint32(0);
data << uint32(PROGRESS_BAR_STATUS) << uint32(0);
}
WorldSafeLocsEntry const* BattlegroundEY::GetClosestGraveyard(Player* player)
{
WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(BG_EY_GRAVEYARD_MAIN_ALLIANCE + player->GetTeamId());
WorldSafeLocsEntry const* nearestEntry = entry;
float pX = player->GetPositionX();
float pY = player->GetPositionY();
float pZ = player->GetPositionZ();
float dist = (entry->x - pX)*(entry->x - pX) + (entry->y - pY)*(entry->y - pY) + (entry->z - pZ)*(entry->z - pZ);
float minDist = dist;
for (uint8 i = 0; i < EY_POINTS_MAX; ++i)
if (_capturePointInfo[i].IsUnderControl(player->GetTeamId()))
{
entry = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[i].GraveYardId);
dist = (entry->x - pX)*(entry->x - pX) + (entry->y - pY)*(entry->y - pY) + (entry->z - pZ)*(entry->z - pZ);
if (dist < minDist)
{
minDist = dist;
nearestEntry = entry;
}
}
return nearestEntry;
}
bool BattlegroundEY::AllNodesConrolledByTeam(TeamId teamId) const
{
uint32 count = 0;
for (uint8 i = 0; i < EY_POINTS_MAX; ++i)
if (_capturePointInfo[i].IsUnderControl(teamId))
++count;
return count == EY_POINTS_MAX;
}
TeamId BattlegroundEY::GetPrematureWinner()
{
if (GetTeamScore(TEAM_ALLIANCE) > GetTeamScore(TEAM_HORDE))
return TEAM_ALLIANCE;
return GetTeamScore(TEAM_HORDE) > GetTeamScore(TEAM_ALLIANCE) ? TEAM_HORDE : Battleground::GetPrematureWinner();
}

View File

@@ -1,399 +0,0 @@
/*
REWRITTEN BY XINEF
*/
#ifndef __BATTLEGROUNDEY_H
#define __BATTLEGROUNDEY_H
#include "Language.h"
#include "Battleground.h"
enum BG_EY_Events
{
BG_EY_EVENT_ADD_POINTS = 1,
BG_EY_EVENT_FLAG_ON_GROUND = 2,
BG_EY_EVENT_RESPAWN_FLAG = 3,
BG_EY_EVENT_CHECK_CPOINTS = 4
};
enum BG_EY_Timers
{
BG_EY_FLAG_RESPAWN_TIME = 20*IN_MILLISECONDS,
BG_EY_FLAG_ON_GROUND_TIME = 10*IN_MILLISECONDS,
BG_EY_FPOINTS_CHECK_TIME = 2*IN_MILLISECONDS,
BG_EY_FPOINTS_TICK_TIME = 1*IN_MILLISECONDS
};
enum BG_EY_WorldStates
{
EY_ALLIANCE_RESOURCES = 2749,
EY_HORDE_RESOURCES = 2750,
EY_ALLIANCE_BASE = 2752,
EY_HORDE_BASE = 2753,
DRAENEI_RUINS_HORDE_CONTROL = 2733,
DRAENEI_RUINS_ALLIANCE_CONTROL = 2732,
DRAENEI_RUINS_UNCONTROL = 2731,
MAGE_TOWER_ALLIANCE_CONTROL = 2730,
MAGE_TOWER_HORDE_CONTROL = 2729,
MAGE_TOWER_UNCONTROL = 2728,
FEL_REAVER_HORDE_CONTROL = 2727,
FEL_REAVER_ALLIANCE_CONTROL = 2726,
FEL_REAVER_UNCONTROL = 2725,
BLOOD_ELF_HORDE_CONTROL = 2724,
BLOOD_ELF_ALLIANCE_CONTROL = 2723,
BLOOD_ELF_UNCONTROL = 2722,
PROGRESS_BAR_PERCENT_GREY = 2720, //100 = empty (only grey), 0 = blue|red (no grey)
PROGRESS_BAR_STATUS = 2719, //50 init!, 48 ... hordak bere .. 33 .. 0 = full 100% hordacky, 100 = full alliance
PROGRESS_BAR_SHOW = 2718, //1 init, 0 druhy send - bez messagu, 1 = controlled aliance
NETHERSTORM_FLAG = 2757,
//set to 2 when flag is picked up, and to 1 if it is dropped
NETHERSTORM_FLAG_STATE_ALLIANCE = 2769,
NETHERSTORM_FLAG_STATE_HORDE = 2770
};
enum BG_EY_ProgressBarConsts
{
BG_EY_POINT_MAX_CAPTURERS_COUNT = 5,
BG_EY_POINT_RADIUS = 50,
BG_EY_PROGRESS_BAR_DONT_SHOW = 0,
BG_EY_PROGRESS_BAR_SHOW = 1,
BG_EY_PROGRESS_BAR_PERCENT_GREY = 40,
BG_EY_PROGRESS_BAR_STATE_MIDDLE = 50,
BG_EY_PROGRESS_BAR_HORDE_CONTROLLED = 0,
BG_EY_PROGRESS_BAR_NEUTRAL_LOW = 30,
BG_EY_PROGRESS_BAR_NEUTRAL_HIGH = 70,
BG_EY_PROGRESS_BAR_ALI_CONTROLLED = 100
};
enum BG_EY_Sounds
{
BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE = 8212,
BG_EY_SOUND_FLAG_CAPTURED_HORDE = 8213,
BG_EY_SOUND_FLAG_PICKED_UP_HORDE = 8174,
BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE = 8173,
BG_EY_SOUND_FLAG_RESET = 8192
};
enum BG_EY_Spells
{
BG_EY_NETHERSTORM_FLAG_SPELL = 34976,
BG_EY_PLAYER_DROPPED_FLAG_SPELL = 34991
};
enum BG_EY_ObjectEntry
{
BG_OBJECT_A_DOOR_EY_ENTRY = 184719, //Alliance door
BG_OBJECT_H_DOOR_EY_ENTRY = 184720, //Horde door
BG_OBJECT_FLAG1_EY_ENTRY = 184493, //Netherstorm flag (generic)
BG_OBJECT_FLAG2_EY_ENTRY = 184141, //Netherstorm flag (flagstand)
BG_OBJECT_FLAG3_EY_ENTRY = 184142, //Netherstorm flag (flagdrop)
BG_OBJECT_A_BANNER_EY_ENTRY = 184381, //Visual Banner (Alliance)
BG_OBJECT_H_BANNER_EY_ENTRY = 184380, //Visual Banner (Horde)
BG_OBJECT_N_BANNER_EY_ENTRY = 184382, //Visual Banner (Neutral)
BG_OBJECT_BE_TOWER_CAP_EY_ENTRY = 184080, //BE Tower Cap Pt
BG_OBJECT_FR_TOWER_CAP_EY_ENTRY = 184081, //Fel Reaver Cap Pt
BG_OBJECT_HU_TOWER_CAP_EY_ENTRY = 184082, //Human Tower Cap Pt
BG_OBJECT_DR_TOWER_CAP_EY_ENTRY = 184083 //Draenei Tower Cap Pt
};
enum BG_EY_AreaTriggers
{
AT_BLOOD_ELF_POINT = 4476,
AT_FEL_REAVER_POINT = 4514,
AT_MAGE_TOWER_POINT = 4516,
AT_DRAENEI_RUINS_POINT = 4518,
AT_BLOOD_ELF_BUFF = 4568,
AT_FEL_REAVER_BUFF = 4569,
AT_MAGE_TOWER_BUFF = 4570,
AT_DRAENEI_RUINS_BUFF = 4571
};
enum BG_EY_Graveyards
{
BG_EY_GRAVEYARD_MAIN_ALLIANCE = 1103,
BG_EY_GRAVEYARD_MAIN_HORDE = 1104,
BG_EY_GRAVEYARD_FEL_REAVER = 1105,
BG_EY_GRAVEYARD_BLOOD_ELF = 1106,
BG_EY_GRAVEYARD_DRAENEI_RUINS = 1107,
BG_EY_GRAVEYARD_MAGE_TOWER = 1108
};
enum BG_EY_Points
{
POINT_FEL_REAVER = 0,
POINT_BLOOD_ELF = 1,
POINT_DRAENEI_RUINS = 2,
POINT_MAGE_TOWER = 3,
EY_POINTS_MAX = 4
};
enum BG_EY_CreatureTypes
{
BG_EY_SPIRIT_FEL_REAVER = 0,
BG_EY_SPIRIT_BLOOD_ELF = 1,
BG_EY_SPIRIT_DRAENEI_RUINS = 2,
BG_EY_SPIRIT_MAGE_TOWER = 3,
BG_EY_SPIRIT_MAIN_ALLIANCE = 4,
BG_EY_SPIRIT_MAIN_HORDE = 5,
BG_EY_TRIGGER_FEL_REAVER = 6,
BG_EY_TRIGGER_BLOOD_ELF = 7,
BG_EY_TRIGGER_DRAENEI_RUINS = 8,
BG_EY_TRIGGER_MAGE_TOWER = 9,
BG_EY_CREATURES_MAX = 10
};
enum BG_EY_ObjectTypes
{
BG_EY_OBJECT_DOOR_A = 0,
BG_EY_OBJECT_DOOR_H = 1,
BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER = 2,
BG_EY_OBJECT_A_BANNER_FEL_REAVER_LEFT = 3,
BG_EY_OBJECT_A_BANNER_FEL_REAVER_RIGHT = 4,
BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER = 5,
BG_EY_OBJECT_A_BANNER_BLOOD_ELF_LEFT = 6,
BG_EY_OBJECT_A_BANNER_BLOOD_ELF_RIGHT = 7,
BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER = 8,
BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_LEFT = 9,
BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_RIGHT = 10,
BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER = 11,
BG_EY_OBJECT_A_BANNER_MAGE_TOWER_LEFT = 12,
BG_EY_OBJECT_A_BANNER_MAGE_TOWER_RIGHT = 13,
BG_EY_OBJECT_H_BANNER_FEL_REAVER_CENTER = 14,
BG_EY_OBJECT_H_BANNER_FEL_REAVER_LEFT = 15,
BG_EY_OBJECT_H_BANNER_FEL_REAVER_RIGHT = 16,
BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER = 17,
BG_EY_OBJECT_H_BANNER_BLOOD_ELF_LEFT = 18,
BG_EY_OBJECT_H_BANNER_BLOOD_ELF_RIGHT = 19,
BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER = 20,
BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_LEFT = 21,
BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_RIGHT = 22,
BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER = 23,
BG_EY_OBJECT_H_BANNER_MAGE_TOWER_LEFT = 24,
BG_EY_OBJECT_H_BANNER_MAGE_TOWER_RIGHT = 25,
BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER = 26,
BG_EY_OBJECT_N_BANNER_FEL_REAVER_LEFT = 27,
BG_EY_OBJECT_N_BANNER_FEL_REAVER_RIGHT = 28,
BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER = 29,
BG_EY_OBJECT_N_BANNER_BLOOD_ELF_LEFT = 30,
BG_EY_OBJECT_N_BANNER_BLOOD_ELF_RIGHT = 31,
BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER = 32,
BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_LEFT = 33,
BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_RIGHT = 34,
BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER = 35,
BG_EY_OBJECT_N_BANNER_MAGE_TOWER_LEFT = 36,
BG_EY_OBJECT_N_BANNER_MAGE_TOWER_RIGHT = 37,
BG_EY_OBJECT_TOWER_CAP_FEL_REAVER = 38,
BG_EY_OBJECT_TOWER_CAP_BLOOD_ELF = 39,
BG_EY_OBJECT_TOWER_CAP_DRAENEI_RUINS = 40,
BG_EY_OBJECT_TOWER_CAP_MAGE_TOWER = 41,
BG_EY_OBJECT_FLAG_NETHERSTORM = 42,
BG_EY_OBJECT_FLAG_FEL_REAVER = 43,
BG_EY_OBJECT_FLAG_BLOOD_ELF = 44,
BG_EY_OBJECT_FLAG_DRAENEI_RUINS = 45,
BG_EY_OBJECT_FLAG_MAGE_TOWER = 46,
//buffs
BG_EY_OBJECT_SPEEDBUFF_FEL_REAVER = 47,
BG_EY_OBJECT_REGENBUFF_FEL_REAVER = 48,
BG_EY_OBJECT_BERSERKBUFF_FEL_REAVER = 49,
BG_EY_OBJECT_SPEEDBUFF_BLOOD_ELF = 50,
BG_EY_OBJECT_REGENBUFF_BLOOD_ELF = 51,
BG_EY_OBJECT_BERSERKBUFF_BLOOD_ELF = 52,
BG_EY_OBJECT_SPEEDBUFF_DRAENEI_RUINS = 53,
BG_EY_OBJECT_REGENBUFF_DRAENEI_RUINS = 54,
BG_EY_OBJECT_BERSERKBUFF_DRAENEI_RUINS = 55,
BG_EY_OBJECT_SPEEDBUFF_MAGE_TOWER = 56,
BG_EY_OBJECT_REGENBUFF_MAGE_TOWER = 57,
BG_EY_OBJECT_BERSERKBUFF_MAGE_TOWER = 58,
BG_EY_OBJECT_MAX = 59
};
enum BG_EY_Score
{
BG_EY_WARNING_NEAR_VICTORY_SCORE = 1400,
BG_EY_MAX_TEAM_SCORE = 1600,
BG_EY_HONOR_TICK_WEEKEND = 160,
BG_EY_HONOR_TICK_NORMAL = 260,
BG_EY_EVENT_START_BATTLE = 13180, // Achievement: Flurry
BG_EY_OBJECTIVE_CAPTURE_FLAG = 183
};
enum BG_EY_FlagState
{
BG_EY_FLAG_STATE_ON_BASE = 1,
BG_EY_FLAG_STATE_ON_PLAYER = 2,
BG_EY_FLAG_STATE_ON_GROUND = 3
};
struct BattlegroundEYPointIconsStruct
{
BattlegroundEYPointIconsStruct(uint32 _WorldStateControlIndex, uint32 _WorldStateAllianceControlledIndex, uint32 _WorldStateHordeControlledIndex)
: WorldStateControlIndex(_WorldStateControlIndex), WorldStateAllianceControlledIndex(_WorldStateAllianceControlledIndex), WorldStateHordeControlledIndex(_WorldStateHordeControlledIndex) {}
uint32 WorldStateControlIndex;
uint32 WorldStateAllianceControlledIndex;
uint32 WorldStateHordeControlledIndex;
};
const float BG_EY_TriggerPositions[EY_POINTS_MAX][4] =
{
{2044.28f, 1729.68f, 1189.96f, 0.017453f}, // FEL_REAVER center
{2048.83f, 1393.65f, 1194.49f, 0.20944f}, // BLOOD_ELF center
{2286.56f, 1402.36f, 1197.11f, 3.72381f}, // DRAENEI_RUINS center
{2284.48f, 1731.23f, 1189.99f, 2.89725f} // MAGE_TOWER center
};
struct BattlegroundEYLosingPointStruct
{
BattlegroundEYLosingPointStruct(uint32 _SpawnNeutralObjectType, uint32 _DespawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _DespawnObjectTypeHorde, uint32 _MessageIdHorde)
: SpawnNeutralObjectType(_SpawnNeutralObjectType),
DespawnObjectTypeAlliance(_DespawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance),
DespawnObjectTypeHorde(_DespawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde)
{}
uint32 SpawnNeutralObjectType;
uint32 DespawnObjectTypeAlliance;
uint32 MessageIdAlliance;
uint32 DespawnObjectTypeHorde;
uint32 MessageIdHorde;
};
struct BattlegroundEYCapturingPointStruct
{
BattlegroundEYCapturingPointStruct(uint32 _DespawnNeutralObjectType, uint32 _SpawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _SpawnObjectTypeHorde, uint32 _MessageIdHorde, uint32 _GraveYardId)
: DespawnNeutralObjectType(_DespawnNeutralObjectType),
SpawnObjectTypeAlliance(_SpawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance),
SpawnObjectTypeHorde(_SpawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde),
GraveYardId(_GraveYardId)
{}
uint32 DespawnNeutralObjectType;
uint32 SpawnObjectTypeAlliance;
uint32 MessageIdAlliance;
uint32 SpawnObjectTypeHorde;
uint32 MessageIdHorde;
uint32 GraveYardId;
};
const uint32 BG_EY_TickPoints[EY_POINTS_MAX] = {1, 2, 5, 10};
const uint32 BG_EY_FlagPoints[EY_POINTS_MAX] = {75, 85, 100, 500};
//constant arrays:
const BattlegroundEYPointIconsStruct m_PointsIconStruct[EY_POINTS_MAX] =
{
BattlegroundEYPointIconsStruct(FEL_REAVER_UNCONTROL, FEL_REAVER_ALLIANCE_CONTROL, FEL_REAVER_HORDE_CONTROL),
BattlegroundEYPointIconsStruct(BLOOD_ELF_UNCONTROL, BLOOD_ELF_ALLIANCE_CONTROL, BLOOD_ELF_HORDE_CONTROL),
BattlegroundEYPointIconsStruct(DRAENEI_RUINS_UNCONTROL, DRAENEI_RUINS_ALLIANCE_CONTROL, DRAENEI_RUINS_HORDE_CONTROL),
BattlegroundEYPointIconsStruct(MAGE_TOWER_UNCONTROL, MAGE_TOWER_ALLIANCE_CONTROL, MAGE_TOWER_HORDE_CONTROL)
};
const BattlegroundEYLosingPointStruct m_LosingPointTypes[EY_POINTS_MAX] =
{
BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER, LANG_BG_EY_HAS_LOST_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REAVER_CENTER, LANG_BG_EY_HAS_LOST_H_F_RUINS),
BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_H_B_TOWER),
BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_H_D_RUINS),
BattlegroundEYLosingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_H_M_TOWER)
};
const BattlegroundEYCapturingPointStruct m_CapturingPointTypes[EY_POINTS_MAX] =
{
BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REAVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REAVER_CENTER, LANG_BG_EY_HAS_TAKEN_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REAVER_CENTER, LANG_BG_EY_HAS_TAKEN_H_F_RUINS, BG_EY_GRAVEYARD_FEL_REAVER),
BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_H_B_TOWER, BG_EY_GRAVEYARD_BLOOD_ELF),
BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_H_D_RUINS, BG_EY_GRAVEYARD_DRAENEI_RUINS),
BattlegroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_H_M_TOWER, BG_EY_GRAVEYARD_MAGE_TOWER)
};
struct BattlegroundEYScore : public BattlegroundScore
{
BattlegroundEYScore(Player* player) : BattlegroundScore(player), FlagCaptures(0) { }
~BattlegroundEYScore() { }
uint32 FlagCaptures;
uint32 GetAttr1() const final override { return FlagCaptures; }
};
class BattlegroundEY : public Battleground
{
public:
BattlegroundEY();
~BattlegroundEY();
/* inherited from BattlegroundClass */
void AddPlayer(Player* player);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
/* BG Flags */
uint64 GetFlagPickerGUID(TeamId /*teamId*/ = TEAM_NEUTRAL) const { return _flagKeeperGUID; }
void SetFlagPicker(uint64 guid) { _flagKeeperGUID = guid; }
uint8 GetFlagState() const { return _flagState; }
void RespawnFlag();
void RespawnFlagAfterDrop();
void RemovePlayer(Player* player);
void HandleBuffUse(uint64 buff_guid);
void HandleAreaTrigger(Player* player, uint32 trigger);
void HandleKillPlayer(Player* player, Player* killer);
WorldSafeLocsEntry const* GetClosestGraveyard(Player* player);
bool SetupBattleground();
void Init();
void EndBattleground(TeamId winnerTeamId);
void UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true);
void FillInitialWorldStates(WorldPacket& data);
void SetDroppedFlagGUID(uint64 guid, TeamId /*teamId*/ = TEAM_NEUTRAL) { _droppedFlagGUID = guid; }
uint64 GetDroppedFlagGUID() const { return _droppedFlagGUID; }
/* Battleground Events */
void EventPlayerClickedOnFlag(Player* player, GameObject* gameObject);
void EventPlayerDroppedFlag(Player* player);
/* achievement req. */
bool AllNodesConrolledByTeam(TeamId teamId) const;
TeamId GetPrematureWinner();
private:
void PostUpdateImpl(uint32 diff);
void EventPlayerCapturedFlag(Player* Source, uint32 BgObjectType);
void EventTeamLostPoint(TeamId teamId, uint32 point);
void EventTeamCapturedPoint(TeamId teamId, uint32 point);
void UpdatePointsCount();
void UpdatePointsIcons(uint32 point);
/* Point status updating procedures */
void UpdatePointsState();
/* Scorekeeping */
void AddPoints(TeamId teamId, uint32 points);
struct CapturePointInfo
{
CapturePointInfo() : _ownerTeamId(TEAM_NEUTRAL), _barStatus(BG_EY_PROGRESS_BAR_STATE_MIDDLE), _areaTrigger(0)
{
_playersCount[TEAM_ALLIANCE] = 0;
_playersCount[TEAM_HORDE] = 0;
}
TeamId _ownerTeamId;
uint32 _areaTrigger;
int8 _barStatus;
int8 _playersCount[BG_TEAMS_COUNT];
bool IsUnderControl(TeamId teamId) const { return _ownerTeamId == teamId; }
bool IsUnderControl() const { return _ownerTeamId != TEAM_NEUTRAL; }
bool IsUncontrolled() const { return _ownerTeamId == TEAM_NEUTRAL; }
};
CapturePointInfo _capturePointInfo[EY_POINTS_MAX];
EventMap _bgEvents;
uint32 _honorTics;
uint8 _ownedPointsCount[BG_TEAMS_COUNT];
uint64 _flagKeeperGUID;
uint64 _droppedFlagGUID;
uint8 _flagState;
uint32 _flagCapturedObject;
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,151 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlegroundNA.h"
#include "Language.h"
#include "Object.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "WorldPacket.h"
#include "WorldSession.h"
BattlegroundNA::BattlegroundNA()
{
BgObjects.resize(BG_NA_OBJECT_MAX);
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattlegroundNA::~BattlegroundNA()
{
}
void BattlegroundNA::StartingEventCloseDoors()
{
for (uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
void BattlegroundNA::StartingEventOpenDoors()
{
for (uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; ++i)
DoorOpen(i);
for (uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; ++i)
SpawnBGObject(i, 60);
}
void BattlegroundNA::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
Battleground::UpdateArenaWorldState();
}
void BattlegroundNA::RemovePlayer(Player* /*player*/)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundNA::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
{
sLog->outError("BattlegroundNA: Killer player not found");
return;
}
Battleground::HandleKillPlayer(player, killer);
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
bool BattlegroundNA::HandlePlayerUnderMap(Player* player)
{
player->NearTeleportTo(4055.504395f, 2919.660645f, 13.611241f, player->GetOrientation());
return true;
}
void BattlegroundNA::HandleAreaTrigger(Player* player, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
switch (trigger)
{
case 4536: // buff trigger?
case 4537: // buff trigger?
break;
// OUTSIDE OF ARENA, TELEPORT!
case 4917:
case 5006:
case 5008:
player->NearTeleportTo(4054.15f, 2923.7f, 13.4f, player->GetOrientation());
break;
}
}
void BattlegroundNA::FillInitialWorldStates(WorldPacket &data)
{
data << uint32(0xa11) << uint32(1); // 9
Battleground::UpdateArenaWorldState();
}
void BattlegroundNA::Init()
{
//call parent's class reset
Battleground::Init();
}
bool BattlegroundNA::SetupBattleground()
{
// gates
if (!AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854f, 2966.833f, 12.6462f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179f, 2874.97f, 12.39171f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709f, 2981.777f, 10.70117f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064f, 2858.438f, 10.23631f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY)
// buffs
|| !AddObject(BG_NA_OBJECT_BUFF_1, BG_NA_OBJECT_TYPE_BUFF_1, 4009.189941f, 2895.250000f, 13.052700f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120)
|| !AddObject(BG_NA_OBJECT_BUFF_2, BG_NA_OBJECT_TYPE_BUFF_2, 4103.330078f, 2946.350098f, 13.051300f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120)
// Arena Ready Marker
|| !AddObject(BG_NA_OBJECT_READY_MARKER_1, ARENA_READY_MARKER_ENTRY, 4090.46f, 2875.43f, 12.16f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300)
|| !AddObject(BG_NA_OBJECT_READY_MARKER_2, ARENA_READY_MARKER_ENTRY, 4022.82f, 2966.61f, 12.17f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300))
{
sLog->outErrorDb("BatteGroundNA: Failed to spawn some object!");
return false;
}
return true;
}

View File

@@ -1,65 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDNA_H
#define __BATTLEGROUNDNA_H
#include "Battleground.h"
enum BattlegroundNAObjectTypes
{
BG_NA_OBJECT_DOOR_1 = 0,
BG_NA_OBJECT_DOOR_2 = 1,
BG_NA_OBJECT_DOOR_3 = 2,
BG_NA_OBJECT_DOOR_4 = 3,
BG_NA_OBJECT_BUFF_1 = 4,
BG_NA_OBJECT_BUFF_2 = 5,
BG_NA_OBJECT_READY_MARKER_1 = 6,
BG_NA_OBJECT_READY_MARKER_2 = 7,
BG_NA_OBJECT_MAX = 8
};
enum BattlegroundNAObjects
{
BG_NA_OBJECT_TYPE_DOOR_1 = 183978,
BG_NA_OBJECT_TYPE_DOOR_2 = 183980,
BG_NA_OBJECT_TYPE_DOOR_3 = 183977,
BG_NA_OBJECT_TYPE_DOOR_4 = 183979,
BG_NA_OBJECT_TYPE_BUFF_1 = 184663,
BG_NA_OBJECT_TYPE_BUFF_2 = 184664
};
class BattlegroundNA : public Battleground
{
public:
BattlegroundNA();
~BattlegroundNA();
/* inherited from BattlegroundClass */
void AddPlayer(Player* player);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
void RemovePlayer(Player* player);
void HandleAreaTrigger(Player* player, uint32 trigger);
bool SetupBattleground();
void Init();
void FillInitialWorldStates(WorldPacket &d);
void HandleKillPlayer(Player* player, Player* killer);
bool HandlePlayerUnderMap(Player* player);
};
#endif

View File

@@ -1,175 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlegroundRL.h"
#include "Language.h"
#include "Object.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "WorldPacket.h"
#include "WorldSession.h"
BattlegroundRL::BattlegroundRL()
{
BgObjects.resize(BG_RL_OBJECT_MAX);
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
//we must set messageIds
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
}
BattlegroundRL::~BattlegroundRL()
{
}
void BattlegroundRL::StartingEventCloseDoors()
{
for (uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; ++i)
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
}
void BattlegroundRL::StartingEventOpenDoors()
{
for (uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; ++i)
DoorOpen(i);
for (uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; ++i)
SpawnBGObject(i, 60);
}
void BattlegroundRL::AddPlayer(Player* player)
{
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
Battleground::UpdateArenaWorldState();
}
void BattlegroundRL::RemovePlayer(Player* /*player*/)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundRL::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
{
sLog->outError("Killer player not found");
return;
}
Battleground::HandleKillPlayer(player, killer);
Battleground::UpdateArenaWorldState();
CheckArenaWinConditions();
}
bool BattlegroundRL::HandlePlayerUnderMap(Player* player)
{
player->NearTeleportTo(1285.810547f, 1667.896851f, 39.957642f, player->GetOrientation());
return true;
}
void BattlegroundRL::HandleAreaTrigger(Player* player, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
switch (trigger)
{
case 4696: // buff trigger?
case 4697: // buff trigger?
break;
// OUTSIDE OF ARENA, TELEPORT!
case 4927:
case 4928:
player->NearTeleportTo(1230.77f, 1662.42f, 34.56f, 0.0f);
break;
case 4929:
case 4930:
player->NearTeleportTo(1341.16f, 1673.52f, 34.43f, 3.5f);
break;
case 4931:
player->NearTeleportTo(1294.74f, 1584.5f, 31.62f, 1.66f);
break;
case 4932:
player->NearTeleportTo(1277.5f, 1751.07f, 31.61f, 4.7f);
break;
case 4933:
player->NearTeleportTo(1269.14f, 1713.85f, 34.46f, 5.23f);
break;
case 4934:
player->NearTeleportTo(1298.14f, 1713.8f, 33.58f, 4.55f);
break;
case 4935:
player->NearTeleportTo(1306.32f, 1620.75f, 34.25f, 1.97f);
break;
case 4936:
player->NearTeleportTo(1277.97f, 1615.51f, 34.56f, 1.15f);
break;
case 4941: // under arena +10
case 5041: // under arena -10
case 5042: // under arena -30
player->NearTeleportTo(1285.810547f, 1667.896851f, 39.957642f, player->GetOrientation());
break;
}
}
void BattlegroundRL::FillInitialWorldStates(WorldPacket &data)
{
data << uint32(0xbba) << uint32(1); // 9
Battleground::UpdateArenaWorldState();
}
void BattlegroundRL::Init()
{
//call parent's reset
Battleground::Init();
}
bool BattlegroundRL::SetupBattleground()
{
// gates
if (!AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561f, 1601.938f, 31.60557f, -1.457349f, 0, 0, -0.6658813f, 0.7460576f, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648f, 1730.557f, 31.60557f, 1.684245f, 0, 0, 0.7460582f, 0.6658807f, RESPAWN_IMMEDIATELY)
// buffs
|| !AddObject(BG_RL_OBJECT_BUFF_1, BG_RL_OBJECT_TYPE_BUFF_1, 1328.719971f, 1632.719971f, 36.730400f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120)
|| !AddObject(BG_RL_OBJECT_BUFF_2, BG_RL_OBJECT_TYPE_BUFF_2, 1243.300049f, 1699.170044f, 34.872601f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120)
// Arena Ready Marker
|| !AddObject(BG_RL_OBJECT_READY_MARKER_1, ARENA_READY_MARKER_ENTRY, 1298.61f, 1598.59f, 31.62f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300)
|| !AddObject(BG_RL_OBJECT_READY_MARKER_2, ARENA_READY_MARKER_ENTRY, 1273.71f, 1734.05f, 31.61f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300))
{
sLog->outErrorDb("BatteGroundRL: Failed to spawn some object!");
return false;
}
return true;
}

View File

@@ -1,61 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDRL_H
#define __BATTLEGROUNDRL_H
#include "Battleground.h"
enum BattlegroundRLObjectTypes
{
BG_RL_OBJECT_DOOR_1 = 0,
BG_RL_OBJECT_DOOR_2 = 1,
BG_RL_OBJECT_BUFF_1 = 2,
BG_RL_OBJECT_BUFF_2 = 3,
BG_RL_OBJECT_READY_MARKER_1 = 4,
BG_RL_OBJECT_READY_MARKER_2 = 5,
BG_RL_OBJECT_MAX = 6
};
enum BattlegroundRLObjects
{
BG_RL_OBJECT_TYPE_DOOR_1 = 185918,
BG_RL_OBJECT_TYPE_DOOR_2 = 185917,
BG_RL_OBJECT_TYPE_BUFF_1 = 184663,
BG_RL_OBJECT_TYPE_BUFF_2 = 184664
};
class BattlegroundRL : public Battleground
{
public:
BattlegroundRL();
~BattlegroundRL();
/* inherited from BattlegroundClass */
void AddPlayer(Player* player);
void Init();
void FillInitialWorldStates(WorldPacket &d);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
void RemovePlayer(Player* player);
void HandleAreaTrigger(Player* player, uint32 trigger);
bool SetupBattleground();
void HandleKillPlayer(Player* player, Player* killer);
bool HandlePlayerUnderMap(Player* player);
};
#endif

View File

@@ -1,351 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Battleground.h"
#include "BattlegroundRV.h"
#include "ObjectAccessor.h"
#include "Language.h"
#include "Player.h"
#include "WorldPacket.h"
#include "GameObject.h"
#include "WorldSession.h"
#include "Pet.h"
BattlegroundRV::BattlegroundRV()
{
BgObjects.resize(BG_RV_OBJECT_MAX);
StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M;
StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S;
StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S;
StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE;
StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS;
StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS;
StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN;
CheckPlayersTimer = 0;
}
BattlegroundRV::~BattlegroundRV() { }
void BattlegroundRV::TeleportUnitToNewZ(Unit* unit, float newZ, bool casting)
{
if (!unit->IsAlive())
return;
unit->NearTeleportTo(unit->GetPositionX(), unit->GetPositionY(), newZ, unit->GetOrientation(), casting);
unit->m_positionZ = newZ;
}
void BattlegroundRV::CheckPositionForUnit(Unit* unit)
{
// get height at current pos, if something is wrong (below or high above) - teleport
if (!unit->IsFalling() && unit->IsAlive())
{
float groundZ_vmap = unit->GetMap()->GetHeight(unit->GetPositionX(), unit->GetPositionY(), 37.0f, true, 50.0f);
float groundZ_dyntree = unit->GetMap()->GetDynamicMapTree().getHeight(unit->GetPositionX(), unit->GetPositionY(), 37.0f, 50.0f, unit->GetPhaseMask());
if (groundZ_vmap > 28.0f && groundZ_vmap < 29.0f || groundZ_dyntree > 28.0f && groundZ_dyntree < 37.0f)
{
float groundZ = std::max<float>(groundZ_vmap, groundZ_dyntree);
if (unit->GetPositionZ() < groundZ - 0.2f || unit->GetPositionZ() > groundZ + 3.5f)
TeleportUnitToNewZ(unit, groundZ+1.0f, true);
}
}
}
void BattlegroundRV::PostUpdateImpl(uint32 diff)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (getTimer() < diff)
{
switch (getState())
{
case BG_RV_STATE_OPEN_FENCES:
for (uint8 i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++i)
DoorOpen(i);
setTimer(BG_RV_CLOSE_FIRE_TIMER);
setState(BG_RV_STATE_CLOSE_FIRE);
for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
if (Player* player = itr->second)
{
// Demonic Circle Summon
if (GameObject* gObj = player->GetGameObject(48018))
{
gObj->Relocate(gObj->GetPositionX(), gObj->GetPositionY(), 28.28f);
gObj->UpdateObjectVisibility(true);
}
if (player->GetPositionZ() < 27.0f)
TeleportUnitToNewZ(player, 28.28f, true);
for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
if (player->m_SummonSlot[i])
if (Creature* totem = GetBgMap()->GetCreature(player->m_SummonSlot[i]))
if (totem->GetPositionZ() < 28.0f)
TeleportUnitToNewZ(totem, 28.28f, true);
for (Unit::ControlSet::const_iterator itr = player->m_Controlled.begin(); itr != player->m_Controlled.end(); ++itr)
{
if ((*itr)->GetPositionZ() < 28.0f)
TeleportUnitToNewZ((*itr), 28.28f, true);
// Xinef: override stay position
if (CharmInfo* charmInfo = (*itr)->GetCharmInfo())
if (charmInfo->IsAtStay())
{
(*itr)->StopMovingOnCurrentPos();
charmInfo->SaveStayPosition(false);
}
}
}
// fix ground on elevators (so aoe spells can be casted there)
{
uint32 objects[2] = {BG_RV_OBJECT_ELEVATOR_1, BG_RV_OBJECT_ELEVATOR_2};
for (uint8 i=0; i<2; ++i)
if (GameObject* go = GetBGObject(objects[i]))
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_TRANSPORT);
}
break;
case BG_RV_STATE_CLOSE_FIRE:
for (uint8 i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++i)
DoorClose(i);
// Fire got closed after five seconds, leaves twenty seconds before toggling pillars
setTimer(BG_RV_FIRE_TO_PILLAR_TIMER);
setState(BG_RV_STATE_SWITCH_PILLARS);
break;
case BG_RV_STATE_SWITCH_PILLARS:
UpdatePillars();
setTimer(BG_RV_PILLAR_SWITCH_TIMER);
break;
}
}
else
setTimer(getTimer() - diff);
if (getState() == BG_RV_STATE_OPEN_FENCES)
return;
if (CheckPlayersTimer <= diff)
{
CheckPlayersTimer = 0;
for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
CheckPositionForUnit(itr->second);
// maybe for pets and m_Controlled also, but not really necessary
}
else
CheckPlayersTimer -= diff;
}
void BattlegroundRV::StartingEventCloseDoors()
{
}
void BattlegroundRV::StartingEventOpenDoors()
{
for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
itr->second->SetPhaseMask(1, true);
// Buff respawn
SpawnBGObject(BG_RV_OBJECT_BUFF_1, 90);
SpawnBGObject(BG_RV_OBJECT_BUFF_2, 90);
// Elevators
DoorOpen(BG_RV_OBJECT_ELEVATOR_1);
DoorOpen(BG_RV_OBJECT_ELEVATOR_2);
setState(BG_RV_STATE_OPEN_FENCES);
setTimer(BG_RV_FIRST_TIMER);
}
void BattlegroundRV::AddPlayer(Player* player)
{
if (GetStatus() == STATUS_WAIT_JOIN && player->GetBgTeamId() == TEAM_HORDE)
player->SetPhaseMask(2, true);
Battleground::AddPlayer(player);
PlayerScores[player->GetGUID()] = new BattlegroundScore(player);
BattlegroundRV::UpdateArenaWorldState();
}
void BattlegroundRV::RemovePlayer(Player* player)
{
if (GetStatus() == STATUS_WAIT_LEAVE)
return;
if (GetStatus() == STATUS_WAIT_JOIN)
player->SetPhaseMask(1, true);
BattlegroundRV::UpdateArenaWorldState();
CheckArenaWinConditions();
}
void BattlegroundRV::HandleKillPlayer(Player* player, Player* killer)
{
if (GetStatus() != STATUS_IN_PROGRESS)
return;
if (!killer)
return;
Battleground::HandleKillPlayer(player, killer);
BattlegroundRV::UpdateArenaWorldState();
CheckArenaWinConditions();
}
bool BattlegroundRV::HandlePlayerUnderMap(Player* player)
{
player->NearTeleportTo(763.5f, -284, 28.276f, 2.422f);
return true;
}
void BattlegroundRV::HandleAreaTrigger(Player* player, uint32 trigger)
{
if (GetStatus() != STATUS_IN_PROGRESS || getState() == BG_RV_STATE_OPEN_FENCES /*during elevator rising it's possible to jump and cause areatrigger*/)
return;
switch (trigger)
{
// fire was removed in 3.2.0
case 5473:
case 5474:
break;
// OUTSIDE OF ARENA, TELEPORT!
case 5224:
player->NearTeleportTo(765.0f, -294.0f, 28.3f, player->GetOrientation());
break;
case 5226:
player->NearTeleportTo(765.0f, -272.0f, 28.3f, player->GetOrientation());
break;
case 5447:
player->NearTeleportTo(763.5f, -284, 28.276f, 2.422f);
break;
}
}
void BattlegroundRV::FillInitialWorldStates(WorldPacket &data)
{
data << uint32(BG_RV_WORLD_STATE) << uint32(1);
BattlegroundRV::UpdateArenaWorldState();
}
void BattlegroundRV::UpdateArenaWorldState()
{
UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(TEAM_ALLIANCE));
UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(TEAM_HORDE));
}
void BattlegroundRV::Init()
{
//call parent's class reset
Battleground::Init();
}
bool BattlegroundRV::SetupBattleground()
{
// elevators
if (!AddObject(BG_RV_OBJECT_ELEVATOR_1, BG_RV_OBJECT_TYPE_ELEVATOR_1, 763.536377f, -294.535767f, 0.505383f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_ELEVATOR_2, BG_RV_OBJECT_TYPE_ELEVATOR_2, 763.506348f, -273.873352f, 0.505383f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY)
// buffs
|| !AddObject(BG_RV_OBJECT_BUFF_1, BG_RV_OBJECT_TYPE_BUFF_1, 735.551819f, -284.794678f, 28.276682f, 0.034906f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_BUFF_2, BG_RV_OBJECT_TYPE_BUFF_2, 791.224487f, -284.794464f, 28.276682f, 2.600535f, 0, 0, 0, RESPAWN_IMMEDIATELY)
// fire
|| !AddObject(BG_RV_OBJECT_FIRE_1, BG_RV_OBJECT_TYPE_FIRE_1, 743.543457f, -283.799469f, 28.286655f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_FIRE_2, BG_RV_OBJECT_TYPE_FIRE_2, 782.971802f, -283.799469f, 28.286655f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_FIREDOOR_1, BG_RV_OBJECT_TYPE_FIREDOOR_1, 743.711060f, -284.099609f, 27.542587f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_FIREDOOR_2, BG_RV_OBJECT_TYPE_FIREDOOR_2, 783.221252f, -284.133362f, 27.535686f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY)
// Gear
|| !AddObject(BG_RV_OBJECT_GEAR_1, BG_RV_OBJECT_TYPE_GEAR_1, 763.664551f, -261.872986f, 26.686588f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_GEAR_2, BG_RV_OBJECT_TYPE_GEAR_2, 763.578979f, -306.146149f, 26.665222f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
// Pulley
|| !AddObject(BG_RV_OBJECT_PULLEY_1, BG_RV_OBJECT_TYPE_PULLEY_1, 700.722290f, -283.990662f, 39.517582f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_PULLEY_2, BG_RV_OBJECT_TYPE_PULLEY_2, 826.303833f, -283.996429f, 39.517582f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY)
// Pilars
|| !AddObject(BG_RV_OBJECT_PILAR_1, BG_RV_OBJECT_TYPE_PILAR_1, 763.632385f, -306.162384f, 25.909504f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_PILAR_2, BG_RV_OBJECT_TYPE_PILAR_2, 723.644287f, -284.493256f, 24.648525f, 3.141593f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_PILAR_3, BG_RV_OBJECT_TYPE_PILAR_3, 763.611145f, -261.856750f, 25.909504f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY)
|| !AddObject(BG_RV_OBJECT_PILAR_4, BG_RV_OBJECT_TYPE_PILAR_4, 802.211609f, -284.493256f, 24.648525f, 0.000000f, 0, 0, 0, RESPAWN_IMMEDIATELY)
// Arena Ready Marker
|| !AddObject(BG_RV_OBJECT_READY_MARKER_1, ARENA_READY_MARKER_ENTRY, 769.93f, -301.04f, 2.80f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300)
|| !AddObject(BG_RV_OBJECT_READY_MARKER_2, ARENA_READY_MARKER_ENTRY, 757.02f, -267.30f, 2.80f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 300)
)
{
sLog->outErrorDb("BatteGroundRV: Failed to spawn some object!");
return false;
}
for (uint8 i=0; i<BG_RV_OBJECT_MAX; ++i)
if (GameObject* go = GetBGObject(i))
go->SetPhaseMask(3, true);
return true;
}
void BattlegroundRV::UpdatePillars()
{
GameObject* test = GetBgMap()->GetGameObject(BgObjects[BG_RV_OBJECT_PILAR_1]);
if (!test)
return;
if (test->GetGoState() == GO_STATE_READY)
{
for (uint8 i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_GEAR_2; ++i)
if (GameObject* go = GetBgMap()->GetGameObject(BgObjects[i]))
go->SetGoState(GO_STATE_ACTIVE);
for (uint8 i = BG_RV_OBJECT_PILAR_2; i <= BG_RV_OBJECT_PULLEY_2; ++i)
if (GameObject* go = GetBgMap()->GetGameObject(BgObjects[i]))
go->SetGoState(GO_STATE_READY);
}
else
{
for (uint8 i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_GEAR_2; ++i)
if (GameObject* go = GetBgMap()->GetGameObject(BgObjects[i]))
go->SetGoState(GO_STATE_READY);
for (uint8 i = BG_RV_OBJECT_PILAR_2; i <= BG_RV_OBJECT_PULLEY_2; ++i)
if (GameObject* go = GetBgMap()->GetGameObject(BgObjects[i]))
go->SetGoState(GO_STATE_ACTIVE);
}
}
uint32 BattlegroundRV::GetPillarIdForPos(Position* p)
{
float range = 1.75f;
if (p->GetExactDist2d(763.632385f, -306.162384f) < range)
return BG_RV_OBJECT_PILAR_1;
if (p->GetExactDist2d(723.644287f, -284.493256f) < 2.0f*range)
return BG_RV_OBJECT_PILAR_2;
if (p->GetExactDist2d(763.611145f, -261.856750f) < range)
return BG_RV_OBJECT_PILAR_3;
if (p->GetExactDist2d(802.211609f, -284.493256f) < 2.0f*range)
return BG_RV_OBJECT_PILAR_4;
return 0;
}
GameObject* BattlegroundRV::GetPillarAtPosition(Position* p)
{
uint32 pillar = GetPillarIdForPos(p);
if (!pillar)
return NULL;
return GetBgMap()->GetGameObject(BgObjects[pillar]);
}

View File

@@ -1,128 +0,0 @@
/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BATTLEGROUNDRV_H
#define __BATTLEGROUNDRV_H
#include "Battleground.h"
enum BattlegroundRVObjectTypes
{
BG_RV_OBJECT_BUFF_1,
BG_RV_OBJECT_BUFF_2,
BG_RV_OBJECT_FIRE_1,
BG_RV_OBJECT_FIRE_2,
BG_RV_OBJECT_FIREDOOR_1,
BG_RV_OBJECT_FIREDOOR_2,
BG_RV_OBJECT_PILAR_1,
BG_RV_OBJECT_PILAR_3,
BG_RV_OBJECT_GEAR_1,
BG_RV_OBJECT_GEAR_2,
BG_RV_OBJECT_PILAR_2,
BG_RV_OBJECT_PILAR_4,
BG_RV_OBJECT_PULLEY_1,
BG_RV_OBJECT_PULLEY_2,
BG_RV_OBJECT_ELEVATOR_1,
BG_RV_OBJECT_ELEVATOR_2,
BG_RV_OBJECT_READY_MARKER_1,
BG_RV_OBJECT_READY_MARKER_2,
BG_RV_OBJECT_MAX,
};
enum BattlegroundRVObjects
{
BG_RV_OBJECT_TYPE_BUFF_1 = 184663,
BG_RV_OBJECT_TYPE_BUFF_2 = 184664,
BG_RV_OBJECT_TYPE_FIRE_1 = 192704,
BG_RV_OBJECT_TYPE_FIRE_2 = 192705,
BG_RV_OBJECT_TYPE_FIREDOOR_2 = 192387,
BG_RV_OBJECT_TYPE_FIREDOOR_1 = 192388,
BG_RV_OBJECT_TYPE_PULLEY_1 = 192389,
BG_RV_OBJECT_TYPE_PULLEY_2 = 192390,
BG_RV_OBJECT_TYPE_GEAR_1 = 192393,
BG_RV_OBJECT_TYPE_GEAR_2 = 192394,
BG_RV_OBJECT_TYPE_ELEVATOR_1 = 194582,
BG_RV_OBJECT_TYPE_ELEVATOR_2 = 194586,
BG_RV_OBJECT_TYPE_PILAR_1 = 194583, // axe
BG_RV_OBJECT_TYPE_PILAR_2 = 194584, // arena
BG_RV_OBJECT_TYPE_PILAR_3 = 194585, // lightning
BG_RV_OBJECT_TYPE_PILAR_4 = 194587, // ivory
};
enum BattlegroundRVData
{
BG_RV_STATE_OPEN_FENCES,
BG_RV_STATE_SWITCH_PILLARS,
BG_RV_STATE_CLOSE_FIRE,
BG_RV_PILLAR_SWITCH_TIMER = 25000,
BG_RV_FIRE_TO_PILLAR_TIMER = 20000,
BG_RV_CLOSE_FIRE_TIMER = 5000,
BG_RV_FIRST_TIMER = 20500, // elevators rise in 20133ms
BG_RV_WORLD_STATE_A = 0xe11,
BG_RV_WORLD_STATE_H = 0xe10,
BG_RV_WORLD_STATE = 0xe1a,
};
class BattlegroundRV : public Battleground
{
public:
BattlegroundRV();
~BattlegroundRV();
/* inherited from BattlegroundClass */
void AddPlayer(Player* player);
void RemovePlayer(Player* player);
void StartingEventCloseDoors();
void StartingEventOpenDoors();
void Init();
void FillInitialWorldStates(WorldPacket &d);
void UpdateArenaWorldState();
void HandleAreaTrigger(Player* player, uint32 trigger);
bool SetupBattleground();
void HandleKillPlayer(Player* player, Player* killer);
bool HandlePlayerUnderMap(Player* player);
GameObject* GetPillarAtPosition(Position* p);
private:
uint32 Timer;
uint32 State;
uint16 CheckPlayersTimer;
void PostUpdateImpl(uint32 diff);
protected:
uint32 getTimer() { return Timer; }
void setTimer(uint32 timer) { Timer = timer; }
uint32 getState() { return State; };
void setState(uint32 state) { State = state; }
void TeleportUnitToNewZ(Unit* unit, float newZ, bool casting);
void CheckPositionForUnit(Unit* unit);
void UpdatePillars();
uint32 GetPillarIdForPos(Position* p);
};
#endif

Some files were not shown because too many files have changed in this diff Show More