Implement area guards system.
Done without using the guard post gameobjects, since spawning them crashes the 1.12 client.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "ReactorAI.h"
|
||||
#include "Creature.h"
|
||||
#include "GuardMgr.h"
|
||||
|
||||
int ReactorAI::Permissible(const Creature *creature)
|
||||
{
|
||||
@@ -30,6 +31,27 @@ int ReactorAI::Permissible(const Creature *creature)
|
||||
return PERMIT_BASE_NO;
|
||||
}
|
||||
|
||||
void ReactorAI::JustRespawned()
|
||||
{
|
||||
m_bCanSummonGuards = m_creature->CanSummonGuards();
|
||||
}
|
||||
|
||||
void ReactorAI::MoveInLineOfSight(Unit* pWho)
|
||||
{
|
||||
if (!CanSummonGuards() || m_creature->isInCombat())
|
||||
return;
|
||||
|
||||
if (!pWho->IsPlayer())
|
||||
return;
|
||||
|
||||
if (!m_creature->IsWithinDistInMap(pWho, m_creature->GetDetectionRange()))
|
||||
return;
|
||||
|
||||
if (m_creature->IsHostileTo(pWho) && pWho->isTargetableForAttack() && m_creature->IsWithinLOSInMap(pWho))
|
||||
if (sGuardMgr.SummonGuard(m_creature, static_cast<Player*>(pWho)))
|
||||
m_bCanSummonGuards = false;
|
||||
}
|
||||
|
||||
void ReactorAI::AttackStart(Unit *p)
|
||||
{
|
||||
if (!p)
|
||||
|
||||
@@ -28,13 +28,18 @@ class MANGOS_DLL_DECL ReactorAI : public CreatureAI
|
||||
{
|
||||
public:
|
||||
|
||||
explicit ReactorAI(Creature *c) : CreatureAI(c) {}
|
||||
explicit ReactorAI(Creature* c) : CreatureAI(c), m_bCanSummonGuards(c->CanSummonGuards()) {}
|
||||
|
||||
void MoveInLineOfSight(Unit *) override { };
|
||||
void AttackStart(Unit *) override;
|
||||
void MoveInLineOfSight(Unit*) override;
|
||||
void AttackStart(Unit*) override;
|
||||
void UpdateAI(const uint32) override;
|
||||
void JustRespawned() override;
|
||||
|
||||
static int Permissible(const Creature *);
|
||||
bool CanSummonGuards() const { return m_bCanSummonGuards; }
|
||||
|
||||
static int Permissible(const Creature*);
|
||||
private:
|
||||
bool m_bCanSummonGuards;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,6 +25,7 @@ set (game_SRCS
|
||||
Conditions.cpp
|
||||
CreatureGroups.cpp
|
||||
GameEventMgr.cpp
|
||||
GuardMgr.cpp
|
||||
GMTicketMgr.cpp
|
||||
GossipDef.cpp
|
||||
HardcodedEvents.cpp
|
||||
@@ -236,6 +237,7 @@ set (game_SRCS
|
||||
CreatureGroups.h
|
||||
Formulas.h
|
||||
GameEventMgr.h
|
||||
GuardMgr.h
|
||||
GMTicketMgr.h
|
||||
GossipDef.h
|
||||
HardcodedEvents.h
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "GuardMgr.h"
|
||||
#include "Creature.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "Log.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
|
||||
INSTANTIATE_SINGLETON_1(GuardMgr);
|
||||
|
||||
#define GUARD_POST_USE_COOLDOWN 10000
|
||||
#define GUARD_POST_RECHARGE_TIME 60000
|
||||
|
||||
enum GuardAreas
|
||||
{
|
||||
AREA_NORTHSHIRE = 9,
|
||||
AREA_WETLANDS = 11,
|
||||
AREA_DUSTWALLOW_MARSH = 15,
|
||||
AREA_DARKSHIRE = 42,
|
||||
AREA_ARATHI_HIGHLANDS = 45,
|
||||
AREA_LAKESHIRE = 69,
|
||||
AREA_STONARD = 75,
|
||||
AREA_TIRISFAL_GLADES = 85,
|
||||
AREA_GOLDSHIRE = 87,
|
||||
AREA_SENTINEL_HILL = 108,
|
||||
AREA_GROMGOL = 117,
|
||||
AREA_SILVERPINE = 130,
|
||||
AREA_KHARANOS = 131,
|
||||
AREA_COLDRIDGE_VALLEY = 132,
|
||||
AREA_TELDRASSIL = 141,
|
||||
AREA_THELSAMAR = 144,
|
||||
AREA_MENETHIL = 150,
|
||||
AREA_DEATHKNELL = 154,
|
||||
AREA_BRILL = 159,
|
||||
AREA_DOLANAAR = 186,
|
||||
AREA_SHADOWGLEN = 188,
|
||||
AREA_MULGORE = 215,
|
||||
AREA_CAMP_NARACHE = 221,
|
||||
AREA_BLOODHOOF_VILLAGE = 222,
|
||||
AREA_SEPULCHER = 228,
|
||||
AREA_HILLSBRAD_FOOTHILLS = 267,
|
||||
AREA_SOUTHSHORE = 271,
|
||||
AREA_TARREN_MILL = 272,
|
||||
AREA_REFUGE_POINTE = 320,
|
||||
AREA_HAMERFALL = 321,
|
||||
AREA_KARGATH = 340,
|
||||
AREA_RAZOR_HILL = 362,
|
||||
AREA_VALLEY_OF_TRIALS = 363,
|
||||
AREA_SENJIN_VILLAGE = 367,
|
||||
AREA_CROSSROADS = 380,
|
||||
AREA_STONETALON = 406,
|
||||
AREA_ASTRANAAR = 415,
|
||||
AREA_AUBERDINE = 442,
|
||||
AREA_FREEWIND_POST = 484,
|
||||
AREA_BRACKENWALL_VILLAGE = 496,
|
||||
AREA_THERAMORE = 513,
|
||||
AREA_RUTHERAN_VILLAGE = 702,
|
||||
AREA_CAMP_MOJACHE = 1099,
|
||||
AREA_FEATHERMOON = 1116,
|
||||
AREA_UNDERCITY = 1497,
|
||||
AREA_STORMWIND = 1519,
|
||||
AREA_IRONFORGE = 1537,
|
||||
AREA_ORGRIMMAR = 1637,
|
||||
AREA_THUNDERBLUFF = 1638,
|
||||
AREA_DARNASSUS = 1657,
|
||||
AREA_LIGHTS_HOPE_CHAPEL = 2268,
|
||||
AREA_NIGHTHAVEN = 2361,
|
||||
AREA_REVANTUSK_VILLAGE = 3317,
|
||||
};
|
||||
|
||||
enum GuardTexts
|
||||
{
|
||||
TEXT_NONE = 0,
|
||||
TEXT_GUARD_HUMAN = 4403, // Guards! Help me!
|
||||
TEXT_GUARD_NIGHT_ELF = 4564, // Sentinels, come to my defense!
|
||||
TEXT_GUARD_ORC = 4561, // Guards!
|
||||
TEXT_GUARD_ORC_2 = 4558, // Grunts! Attack!
|
||||
TEXT_GUARD_TAUREN = 4560, // You will not defile our sacred land!
|
||||
TEXT_GUARD_TROLL = 4559, // Guardians! Defend Sen'jin!
|
||||
TEXT_GUARD_DWARF = 4583, // Guards!
|
||||
TEXT_GUARD_UNDEAD = 4484, // Intruders! Attack the intruders!
|
||||
};
|
||||
|
||||
enum GuardIds
|
||||
{
|
||||
NPC_NONE = 0,
|
||||
NPC_STORMWIND_CITY_GUARD = 68,
|
||||
NPC_IRONFORGE_MOUNTAINEER = 727,
|
||||
NPC_COLDRIDGE_MOUNTAINEER = 853,
|
||||
NPC_STONARD_GRUNT = 866,
|
||||
NPC_GROMGOL_GRUNT = 1064,
|
||||
NPC_MENETHIL_GUARD = 1475,
|
||||
NPC_NORTHSHIRE_GUARD = 1642,
|
||||
NPC_SOUTHSHORE_GUARD = 2386,
|
||||
NPC_TARREN_MILL_DEATHGUARD = 2405,
|
||||
NPC_HAMERFALL_GUARDIAN = 2621,
|
||||
NPC_BLUFFWATCHER = 3084,
|
||||
NPC_ORGRIMMAR_GRUNT = 3296,
|
||||
NPC_HORDE_GUARD = 3501,
|
||||
NPC_TELDRASSIL_SENTINEL = 3571,
|
||||
NPC_DARNASSUS_SENTINEL = 4262,
|
||||
NPC_THERAMORE_GUARD = 4979,
|
||||
NPC_IRONFORGE_GUARD = 5595,
|
||||
NPC_DEN_GRUNT = 5952,
|
||||
NPC_RAZOR_HILL_GRUNT = 5953,
|
||||
NPC_AUBERDINE_SENTINEL = 6086,
|
||||
NPC_ASTRANAAR_SENTINEL = 6087,
|
||||
NPC_SILVERPINE_DEATHGUARD = 7489,
|
||||
NPC_STONETALON_GRUNT = 7730,
|
||||
NPC_FEATHERMOON_SENTINEL = 7939,
|
||||
NPC_MULGORE_PROTECTOR = 7975,
|
||||
NPC_DEATHGUARD_ELITE = 7980,
|
||||
NPC_SENJIN_GUARDIAN = 8017,
|
||||
NPC_THELSAMAR_MOUNTAINEER = 8055,
|
||||
NPC_PROTECTOR_OF_THE_PEOPLE = 8096,
|
||||
NPC_CAMP_MOJACHE_BRAVE = 8147,
|
||||
NPC_KARGATH_GRUNT = 8155,
|
||||
NPC_FREEWIND_BRAVE = 9525,
|
||||
NPC_BRACKENWALL_ENFORCER = 10036,
|
||||
NPC_LAKESHIRE_GUARD = 10037,
|
||||
NPC_NIGHT_WATCH_GUARD = 10038,
|
||||
NPC_REFUGE_POINTE_DEFENDER = 10696,
|
||||
NPC_MOONGLADE_WARDEN = 11822,
|
||||
NPC_SHADOWGLEN_SENTINEL = 12160,
|
||||
NPC_REVANTUSK_WATCHER = 14730,
|
||||
NPC_HAMERFALL_ELITE = 15136,
|
||||
NPC_MENETHIL_ELITE = 15137,
|
||||
NPC_SILVERPINE_ELITE = 15138,
|
||||
NPC_ARGENT_SENTRY = 16378,
|
||||
};
|
||||
|
||||
GuardMgr::GuardMgr()
|
||||
{
|
||||
m_mAreaGuardInfo = {
|
||||
// Area Id Alliance NPC Horde NPC Alliance Text Horde Text
|
||||
{ AREA_STORMWIND, AreaGuardInfo(NPC_STORMWIND_CITY_GUARD, NPC_NONE, TEXT_GUARD_HUMAN, TEXT_NONE) },
|
||||
{ AREA_ASTRANAAR, AreaGuardInfo(NPC_ASTRANAAR_SENTINEL, NPC_NONE, TEXT_GUARD_NIGHT_ELF, TEXT_NONE) },
|
||||
{ AREA_AUBERDINE, AreaGuardInfo(NPC_AUBERDINE_SENTINEL, NPC_NONE, TEXT_GUARD_NIGHT_ELF, TEXT_NONE) },
|
||||
{ AREA_CROSSROADS, AreaGuardInfo(NPC_NONE, NPC_HORDE_GUARD, TEXT_NONE, TEXT_GUARD_ORC) },
|
||||
{ AREA_RAZOR_HILL, AreaGuardInfo(NPC_NONE, NPC_RAZOR_HILL_GRUNT, TEXT_NONE, TEXT_GUARD_ORC_2) },
|
||||
{ AREA_THERAMORE, AreaGuardInfo(NPC_THERAMORE_GUARD, NPC_NONE, TEXT_GUARD_HUMAN, TEXT_NONE) },
|
||||
{ AREA_FEATHERMOON, AreaGuardInfo(NPC_FEATHERMOON_SENTINEL, NPC_NONE, TEXT_GUARD_NIGHT_ELF, TEXT_NONE) },
|
||||
{ AREA_THUNDERBLUFF, AreaGuardInfo(NPC_NONE, NPC_BLUFFWATCHER, TEXT_NONE, TEXT_GUARD_TAUREN) },
|
||||
{ AREA_CAMP_NARACHE, AreaGuardInfo(NPC_NONE, NPC_MULGORE_PROTECTOR, TEXT_NONE, TEXT_GUARD_TAUREN) },
|
||||
{ AREA_BLOODHOOF_VILLAGE, AreaGuardInfo(NPC_NONE, NPC_MULGORE_PROTECTOR, TEXT_NONE, TEXT_GUARD_TAUREN) },
|
||||
{ AREA_MULGORE, AreaGuardInfo(NPC_NONE, NPC_MULGORE_PROTECTOR, TEXT_NONE, TEXT_GUARD_TAUREN) },
|
||||
{ AREA_CAMP_MOJACHE, AreaGuardInfo(NPC_NONE, NPC_CAMP_MOJACHE_BRAVE, TEXT_NONE, TEXT_GUARD_TAUREN) },
|
||||
{ AREA_FREEWIND_POST, AreaGuardInfo(NPC_NONE, NPC_FREEWIND_BRAVE, TEXT_NONE, TEXT_GUARD_TAUREN) },
|
||||
{ AREA_SENJIN_VILLAGE, AreaGuardInfo(NPC_NONE, NPC_SENJIN_GUARDIAN, TEXT_NONE, TEXT_GUARD_TROLL) },
|
||||
{ AREA_SENTINEL_HILL, AreaGuardInfo(NPC_PROTECTOR_OF_THE_PEOPLE, NPC_NONE, TEXT_GUARD_HUMAN, TEXT_NONE) },
|
||||
{ AREA_THELSAMAR, AreaGuardInfo(NPC_THELSAMAR_MOUNTAINEER, NPC_NONE, TEXT_GUARD_DWARF, TEXT_NONE) },
|
||||
{ AREA_SILVERPINE, AreaGuardInfo(NPC_NONE, NPC_SILVERPINE_DEATHGUARD, TEXT_NONE, TEXT_GUARD_UNDEAD) },
|
||||
{ AREA_SEPULCHER, AreaGuardInfo(NPC_NONE, NPC_SILVERPINE_ELITE, TEXT_NONE, TEXT_GUARD_UNDEAD) },
|
||||
{ AREA_UNDERCITY, AreaGuardInfo(NPC_NONE, NPC_DEATHGUARD_ELITE, TEXT_NONE, TEXT_GUARD_UNDEAD) },
|
||||
{ AREA_KHARANOS, AreaGuardInfo(NPC_IRONFORGE_MOUNTAINEER, NPC_NONE, TEXT_GUARD_DWARF, TEXT_NONE) },
|
||||
{ AREA_IRONFORGE, AreaGuardInfo(NPC_IRONFORGE_GUARD, NPC_NONE, TEXT_GUARD_DWARF, TEXT_NONE) },
|
||||
{ AREA_DARNASSUS, AreaGuardInfo(NPC_DARNASSUS_SENTINEL, NPC_NONE, TEXT_GUARD_NIGHT_ELF, TEXT_NONE) },
|
||||
{ AREA_ORGRIMMAR, AreaGuardInfo(NPC_NONE, NPC_ORGRIMMAR_GRUNT, TEXT_NONE, TEXT_GUARD_ORC) },
|
||||
{ AREA_WETLANDS, AreaGuardInfo(NPC_MENETHIL_GUARD, NPC_NONE, TEXT_GUARD_HUMAN, TEXT_NONE) },
|
||||
{ AREA_MENETHIL, AreaGuardInfo(NPC_MENETHIL_ELITE, NPC_NONE, TEXT_GUARD_HUMAN, TEXT_NONE) },
|
||||
{ AREA_DUSTWALLOW_MARSH, AreaGuardInfo(NPC_THERAMORE_GUARD, NPC_BRACKENWALL_ENFORCER, TEXT_GUARD_HUMAN, TEXT_NONE) },
|
||||
{ AREA_BRACKENWALL_VILLAGE,AreaGuardInfo(NPC_NONE, NPC_BRACKENWALL_ENFORCER, TEXT_NONE, TEXT_NONE) },
|
||||
{ AREA_ARATHI_HIGHLANDS, AreaGuardInfo(NPC_REFUGE_POINTE_DEFENDER, NPC_HAMERFALL_GUARDIAN, TEXT_GUARD_HUMAN, TEXT_GUARD_ORC) },
|
||||
{ AREA_REFUGE_POINTE, AreaGuardInfo(NPC_REFUGE_POINTE_DEFENDER, NPC_NONE, TEXT_GUARD_HUMAN, TEXT_NONE) },
|
||||
{ AREA_HAMERFALL, AreaGuardInfo(NPC_NONE, NPC_HAMERFALL_ELITE, TEXT_NONE, TEXT_GUARD_ORC) },
|
||||
{ AREA_BRILL, AreaGuardInfo(NPC_NONE, NPC_DEATHGUARD_ELITE, TEXT_NONE, TEXT_GUARD_UNDEAD) },
|
||||
{ AREA_TIRISFAL_GLADES, AreaGuardInfo(NPC_NONE, NPC_DEATHGUARD_ELITE, TEXT_NONE, TEXT_GUARD_UNDEAD) },
|
||||
{ AREA_DEATHKNELL, AreaGuardInfo(NPC_NONE, NPC_DEATHGUARD_ELITE, TEXT_NONE, TEXT_GUARD_UNDEAD) },
|
||||
{ AREA_HILLSBRAD_FOOTHILLS,AreaGuardInfo(NPC_SOUTHSHORE_GUARD, NPC_TARREN_MILL_DEATHGUARD,TEXT_GUARD_HUMAN, TEXT_GUARD_UNDEAD) },
|
||||
{ AREA_SOUTHSHORE, AreaGuardInfo(NPC_SOUTHSHORE_GUARD, NPC_NONE, TEXT_GUARD_HUMAN, TEXT_NONE) },
|
||||
{ AREA_TARREN_MILL, AreaGuardInfo(NPC_NONE, NPC_TARREN_MILL_DEATHGUARD,TEXT_NONE, TEXT_GUARD_UNDEAD) },
|
||||
{ AREA_STONETALON, AreaGuardInfo(NPC_NONE, NPC_STONETALON_GRUNT, TEXT_GUARD_NIGHT_ELF, TEXT_GUARD_ORC) },
|
||||
{ AREA_GROMGOL, AreaGuardInfo(NPC_NONE, NPC_GROMGOL_GRUNT, TEXT_NONE, TEXT_GUARD_ORC) },
|
||||
{ AREA_GOLDSHIRE, AreaGuardInfo(NPC_STORMWIND_CITY_GUARD, NPC_NONE, TEXT_GUARD_HUMAN, TEXT_NONE) },
|
||||
{ AREA_STONARD, AreaGuardInfo(NPC_NONE, NPC_STONARD_GRUNT, TEXT_NONE, TEXT_GUARD_ORC) },
|
||||
{ AREA_KARGATH, AreaGuardInfo(NPC_NONE, NPC_KARGATH_GRUNT, TEXT_NONE, TEXT_GUARD_ORC) },
|
||||
{ AREA_LAKESHIRE, AreaGuardInfo(NPC_LAKESHIRE_GUARD, NPC_NONE, TEXT_GUARD_HUMAN, TEXT_NONE) },
|
||||
{ AREA_DARKSHIRE, AreaGuardInfo(NPC_NIGHT_WATCH_GUARD, NPC_NONE, TEXT_GUARD_HUMAN, TEXT_NONE) },
|
||||
{ AREA_DOLANAAR, AreaGuardInfo(NPC_TELDRASSIL_SENTINEL, NPC_NONE, TEXT_GUARD_NIGHT_ELF, TEXT_NONE) },
|
||||
{ AREA_TELDRASSIL, AreaGuardInfo(NPC_TELDRASSIL_SENTINEL, NPC_NONE, TEXT_GUARD_NIGHT_ELF, TEXT_NONE) },
|
||||
{ AREA_RUTHERAN_VILLAGE, AreaGuardInfo(NPC_DARNASSUS_SENTINEL, NPC_NONE, TEXT_GUARD_NIGHT_ELF, TEXT_NONE) },
|
||||
{ AREA_NIGHTHAVEN, AreaGuardInfo(NPC_MOONGLADE_WARDEN, NPC_MOONGLADE_WARDEN, TEXT_GUARD_NIGHT_ELF, TEXT_GUARD_NIGHT_ELF) },
|
||||
{ AREA_REVANTUSK_VILLAGE, AreaGuardInfo(NPC_NONE, NPC_REVANTUSK_WATCHER, TEXT_NONE, TEXT_NONE) },
|
||||
{ AREA_LIGHTS_HOPE_CHAPEL, AreaGuardInfo(NPC_ARGENT_SENTRY, NPC_ARGENT_SENTRY, TEXT_NONE, TEXT_NONE) },
|
||||
{ AREA_SHADOWGLEN, AreaGuardInfo(NPC_SHADOWGLEN_SENTINEL, NPC_NONE, TEXT_GUARD_NIGHT_ELF, TEXT_NONE) },
|
||||
{ AREA_NORTHSHIRE, AreaGuardInfo(NPC_NORTHSHIRE_GUARD, NPC_NONE, TEXT_GUARD_HUMAN, TEXT_NONE) },
|
||||
{ AREA_COLDRIDGE_VALLEY, AreaGuardInfo(NPC_COLDRIDGE_MOUNTAINEER, NPC_NONE, TEXT_GUARD_DWARF, TEXT_NONE) },
|
||||
{ AREA_VALLEY_OF_TRIALS, AreaGuardInfo(NPC_NONE, NPC_DEN_GRUNT, TEXT_NONE, TEXT_GUARD_ORC) },
|
||||
};
|
||||
}
|
||||
|
||||
void GuardMgr::Update(uint32 diff)
|
||||
{
|
||||
bool bIncreaseCharges = false;
|
||||
|
||||
if (m_uiRechargeTimer < diff)
|
||||
{
|
||||
bIncreaseCharges = true;
|
||||
m_uiRechargeTimer = GUARD_POST_RECHARGE_TIME;
|
||||
}
|
||||
else
|
||||
m_uiRechargeTimer -= diff;
|
||||
|
||||
for (auto& itr : m_mAreaGuardInfo)
|
||||
{
|
||||
if (itr.second.cooldown)
|
||||
{
|
||||
if (itr.second.cooldown >= diff)
|
||||
itr.second.cooldown -= diff;
|
||||
else
|
||||
itr.second.cooldown = 0;
|
||||
}
|
||||
if (bIncreaseCharges && (itr.second.charges < GUARD_POST_MAX_CHARGES))
|
||||
itr.second.charges++;
|
||||
}
|
||||
}
|
||||
|
||||
bool GuardMgr::SummonGuard(Creature* pCivilian, Player* pEnemy)
|
||||
{
|
||||
if (!pCivilian || !pEnemy)
|
||||
return false;
|
||||
|
||||
uint32 areaId = pCivilian->GetAreaId();
|
||||
|
||||
auto itr = m_mAreaGuardInfo.find(areaId);
|
||||
|
||||
if (itr == m_mAreaGuardInfo.end())
|
||||
{;
|
||||
pCivilian->CallNearestGuard(pEnemy);
|
||||
return true;
|
||||
}
|
||||
|
||||
AreaGuardInfo& guardInfo = itr->second;
|
||||
|
||||
if (guardInfo.cooldown || !guardInfo.charges)
|
||||
return false;
|
||||
|
||||
guardInfo.charges--;
|
||||
guardInfo.cooldown = GUARD_POST_USE_COOLDOWN;
|
||||
|
||||
if (uint32 textId = pEnemy->GetTeamId() == TEAM_ALLIANCE ? guardInfo.textIdHorde : guardInfo.textIdAlliance)
|
||||
DoScriptText(textId, pCivilian, pEnemy, CHAT_TYPE_SAY);
|
||||
|
||||
if (uint32 creatureId = pEnemy->GetTeamId() == TEAM_ALLIANCE ? guardInfo.creatureIdHorde : guardInfo.creatureIdAlliance)
|
||||
{
|
||||
float x, y, z;
|
||||
pCivilian->GetNearPoint(pCivilian, x, y, z, 0, 5, 0);
|
||||
Creature* pGuard = pCivilian->SummonCreature(creatureId, x, y, z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 2 * MINUTE * IN_MILLISECONDS);
|
||||
if (pGuard && pGuard->AI())
|
||||
pGuard->AI()->AttackStart(pEnemy);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef MANGOS_GUARD_MGR_H
|
||||
#define MANGOS_GUARD_MGR_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "Platform/Define.h"
|
||||
#include "Policies/Singleton.h"
|
||||
#include <unordered_map>
|
||||
|
||||
#define GUARD_POST_MAX_CHARGES 10
|
||||
|
||||
class Creature;
|
||||
class Player;
|
||||
|
||||
struct AreaGuardInfo
|
||||
{
|
||||
AreaGuardInfo(uint32 creature_id_ally, uint32 creature_id_horde, uint32 text_id_alliance, uint32 text_id_horde) : creatureIdAlliance(creature_id_ally), creatureIdHorde(creature_id_horde), textIdAlliance(text_id_alliance), textIdHorde(text_id_horde), cooldown(0), charges(GUARD_POST_MAX_CHARGES) {}
|
||||
uint32 const creatureIdAlliance;
|
||||
uint32 const creatureIdHorde;
|
||||
uint32 const textIdAlliance;
|
||||
uint32 const textIdHorde;
|
||||
uint32 cooldown;
|
||||
uint32 charges;
|
||||
};
|
||||
|
||||
class GuardMgr
|
||||
{
|
||||
public:
|
||||
GuardMgr();
|
||||
~GuardMgr() {}
|
||||
void Update(uint32 diff);
|
||||
bool SummonGuard(Creature* pCivilian, Player* pEnemy);
|
||||
private:
|
||||
std::unordered_map<uint32, AreaGuardInfo> m_mAreaGuardInfo;
|
||||
uint32 m_uiRechargeTimer;
|
||||
};
|
||||
|
||||
#define sGuardMgr MaNGOS::Singleton<GuardMgr>::Instance()
|
||||
|
||||
#endif
|
||||
@@ -1112,6 +1112,47 @@ namespace MaNGOS
|
||||
NearestAssistCreatureInCreatureRangeCheck(NearestAssistCreatureInCreatureRangeCheck const&);
|
||||
};
|
||||
|
||||
class NearestFriendlyGuardInRangeCheck
|
||||
{
|
||||
public:
|
||||
NearestFriendlyGuardInRangeCheck(Creature const* obj, float range)
|
||||
: i_obj(obj), i_range(range) {}
|
||||
WorldObject const& GetFocusObject() const { return *i_obj; }
|
||||
bool operator()(Creature const* u)
|
||||
{
|
||||
if (u == i_obj)
|
||||
return false;
|
||||
|
||||
if (!u->isAlive())
|
||||
return false;
|
||||
|
||||
if (u->isInCombat())
|
||||
return false;
|
||||
|
||||
if (!u->IsGuard())
|
||||
return false;
|
||||
|
||||
if (!u->IsFriendlyTo(i_obj))
|
||||
return false;
|
||||
|
||||
if (!i_obj->IsWithinDistInMap(u, i_range))
|
||||
return false;
|
||||
|
||||
if (!i_obj->IsWithinLOSInMap(u))
|
||||
return false;
|
||||
|
||||
i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check
|
||||
return true;
|
||||
}
|
||||
float GetLastRange() const { return i_range; }
|
||||
private:
|
||||
Creature const* const i_obj;
|
||||
float i_range;
|
||||
|
||||
// prevent clone this object
|
||||
NearestFriendlyGuardInRangeCheck(NearestFriendlyGuardInRangeCheck const&);
|
||||
};
|
||||
|
||||
// Success at unit in range, range update for next check (this can be use with CreatureLastSearcher to find nearest creature)
|
||||
class NearestCreatureEntryWithLiveStateInObjectRangeCheck
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@ bool Map::ScriptCommand_Talk(const ScriptInfo& script, WorldObject* source, Worl
|
||||
textId = script.talk.textId[rand() % i];
|
||||
}
|
||||
|
||||
DoScriptText(textId, pSource, unitTarget, script.talk.chatType);
|
||||
DoScriptText(textId, pSource, unitTarget, script.talk.chatType > 0 ? script.talk.chatType : -1);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include "CreatureLinkingMgr.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "ScriptedEscortAI.h"
|
||||
#include "GuardMgr.h"
|
||||
|
||||
// apply implementation of the singletons
|
||||
#include "Policies/SingletonImp.h"
|
||||
@@ -3263,6 +3264,9 @@ void Creature::OnEnterCombat(Unit* pWho, bool notInCombat)
|
||||
if (pPlayer->GetReputationMgr().SetAtWar(GetReputationId(), true))
|
||||
pPlayer->SendFactionAtWar(GetReputationId(), true);
|
||||
}
|
||||
|
||||
if (pWho->IsPlayer() && CanSummonGuards())
|
||||
sGuardMgr.SummonGuard(this, static_cast<Player*>(pWho));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3576,6 +3580,25 @@ Unit* Creature::DoFindFriendlyCC(float range) const
|
||||
return pUnit;
|
||||
}
|
||||
|
||||
Creature* Creature::GetNearestGuard(float range) const
|
||||
{
|
||||
Creature* pGuard = nullptr;
|
||||
|
||||
MaNGOS::NearestFriendlyGuardInRangeCheck u_check(this, range);
|
||||
MaNGOS::CreatureLastSearcher<MaNGOS::NearestFriendlyGuardInRangeCheck> searcher(pGuard, u_check);
|
||||
|
||||
Cell::VisitGridObjects(this, searcher, range);
|
||||
|
||||
return pGuard;
|
||||
}
|
||||
|
||||
void Creature::CallNearestGuard(Unit* pEnemy) const
|
||||
{
|
||||
if (Creature* pGuard = GetNearestGuard(50.0f))
|
||||
if (pGuard->AI() && pGuard->IsValidAttackTarget(pEnemy))
|
||||
pGuard->AI()->AttackStart(pEnemy);
|
||||
}
|
||||
|
||||
SpellCastResult Creature::TryToCast(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags, uint8 uiChance)
|
||||
{
|
||||
if (IsNonMeleeSpellCasted(false) && !(uiCastFlags & (CF_TRIGGERED | CF_INTERRUPT_PREVIOUS)))
|
||||
|
||||
@@ -52,7 +52,7 @@ enum CreatureFlagsExtra
|
||||
CREATURE_FLAG_EXTRA_INSTANCE_BIND = 0x00000001, // creature kill bind instance with killer and killer's group
|
||||
CREATURE_FLAG_EXTRA_NO_AGGRO = 0x00000002, // not aggro (ignore faction/reputation hostility)
|
||||
CREATURE_FLAG_EXTRA_NO_PARRY = 0x00000004, // creature can't parry
|
||||
CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN = 0x00000008, // creature can't counter-attack at parry
|
||||
CREATURE_FLAG_EXTRA_SUMMON_GUARD = 0x00000008, // creature summons a guard if an opposite faction player gets near or attacks
|
||||
CREATURE_FLAG_EXTRA_NO_BLOCK = 0x00000010, // creature can't block
|
||||
CREATURE_FLAG_EXTRA_NO_CRUSH = 0x00000020, // creature can't do crush attacks
|
||||
CREATURE_FLAG_EXTRA_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP
|
||||
@@ -764,6 +764,8 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
||||
Unit* DoSelectLowestHpFriendly(float fRange, uint32 uiMinHPDiff = 1, bool bPercent = false, Unit* except = nullptr) const;
|
||||
Unit* DoFindFriendlyMissingBuff(float range, uint32 spellid, Unit* except = nullptr) const;
|
||||
Unit* DoFindFriendlyCC(float range) const;
|
||||
Creature* GetNearestGuard(float range) const;
|
||||
void CallNearestGuard(Unit* pEnemy) const;
|
||||
|
||||
// Used by Creature Spells system to always know result of cast
|
||||
SpellCastResult TryToCast(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags, uint8 uiChance);
|
||||
@@ -919,6 +921,8 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
||||
void SetEscortable(bool escortable) { _isEscortable = escortable; }
|
||||
bool IsEscortable() const { return _isEscortable; }
|
||||
|
||||
bool CanSummonGuards() { return GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_SUMMON_GUARD; }
|
||||
|
||||
protected:
|
||||
bool MeetsSelectAttackingRequirement(Unit* pTarget, SpellEntry const* pSpellInfo, uint32 selectFlags) const;
|
||||
|
||||
|
||||
@@ -2335,7 +2335,7 @@ void ScriptMgr::CollectPossibleEventIds(std::set<uint32>& eventIds)
|
||||
}
|
||||
}
|
||||
|
||||
void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget, uint32 chatTypeOverride)
|
||||
void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget, int32 chatTypeOverride)
|
||||
{
|
||||
if (!pSource)
|
||||
{
|
||||
@@ -2379,7 +2379,7 @@ void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget, uint32
|
||||
}
|
||||
}
|
||||
|
||||
if (chatTypeOverride)
|
||||
if (chatTypeOverride >= 0)
|
||||
Type = chatTypeOverride;
|
||||
|
||||
DEBUG_LOG("DoScriptText: text entry=%i, Sound=%u, Type=%u, Language=%u, Emote=%u",
|
||||
|
||||
@@ -1121,7 +1121,7 @@ enum ScriptTarget
|
||||
};
|
||||
|
||||
//Generic scripting functions
|
||||
void DoScriptText(int32 textEntry, WorldObject* pSource, Unit* target = nullptr, uint32 chatTypeOverride = 0);
|
||||
void DoScriptText(int32 textEntry, WorldObject* pSource, Unit* target = nullptr, int32 chatTypeOverride = -1);
|
||||
void DoOrSimulateScriptTextForMap(int32 iTextEntry, uint32 uiCreatureEntry, Map* pMap, Creature* pCreatureSource = nullptr, Unit* pTarget = nullptr);
|
||||
|
||||
// Returns a target based on the type specified.
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
#include "Anticheat/Anticheat.h"
|
||||
#include "AuraRemovalMgr.h"
|
||||
#include "InstanceStatistics.h"
|
||||
#include "GuardMgr.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
@@ -1776,6 +1777,7 @@ void World::Update(uint32 diff)
|
||||
sMapMgr.Update(diff);
|
||||
sBattleGroundMgr.Update(diff);
|
||||
sLFGMgr.Update(diff);
|
||||
sGuardMgr.Update(diff);
|
||||
sZoneScriptMgr.Update(diff);
|
||||
sAutoTestingMgr->Update(diff);
|
||||
sNodesMgr->OnWorldUpdate(diff);
|
||||
|
||||
Reference in New Issue
Block a user