aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/AI/CoreAI/PetAI.cpp16
-rwxr-xr-xsrc/server/game/AI/CoreAI/PetAI.h2
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.cpp23
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.h109
-rwxr-xr-xsrc/server/game/Battlegrounds/Battleground.cpp29
-rwxr-xr-xsrc/server/game/Conditions/ConditionMgr.cpp48
-rwxr-xr-xsrc/server/game/Conditions/ConditionMgr.h6
-rw-r--r--src/server/game/DataStores/DBCStructure.h4
-rwxr-xr-xsrc/server/game/Entities/GameObject/GameObject.cpp1
-rw-r--r--src/server/game/Entities/Player/Player.cpp84
-rw-r--r--[-rwxr-xr-x]src/server/game/Entities/Player/Player.h9
-rwxr-xr-xsrc/server/game/Entities/Unit/StatSystem.cpp10
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp99
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.h13
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp4
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp47
-rwxr-xr-xsrc/server/game/Instances/InstanceScript.cpp11
-rwxr-xr-xsrc/server/game/Instances/InstanceScript.h3
-rw-r--r--src/server/game/Maps/PhaseMgr.cpp371
-rw-r--r--src/server/game/Maps/PhaseMgr.h173
-rwxr-xr-xsrc/server/game/Miscellaneous/Language.h10
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rwxr-xr-xsrc/server/game/Server/WorldSession.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp26
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp2
-rw-r--r--src/server/game/Spells/SpellMgr.cpp4
-rw-r--r--src/server/game/World/World.cpp14
-rw-r--r--src/server/game/World/World.h2
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp29
-rw-r--r--src/server/scripts/Commands/cs_gobject.cpp4
-rw-r--r--src/server/scripts/Commands/cs_modify.cpp46
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp4
-rw-r--r--src/server/scripts/Commands/cs_reload.cpp10
-rw-r--r--src/server/scripts/Commands/cs_wp.cpp16
-rw-r--r--src/server/scripts/Spells/spell_item.cpp2
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp83
-rw-r--r--src/server/scripts/Spells/spell_warlock.cpp75
-rw-r--r--src/server/scripts/World/npcs_special.cpp2
-rwxr-xr-xsrc/server/shared/Utilities/Util.cpp31
-rwxr-xr-xsrc/server/shared/Utilities/Util.h2
40 files changed, 1074 insertions, 354 deletions
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index 99cf1cda4fc..6802c109401 100755
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -71,6 +71,8 @@ void PetAI::_stopAttack()
}
me->AttackStop();
+ me->InterruptNonMeleeSpells(false);
+ me->SendMeleeAttackStop(); // Should stop pet's attack button from flashing
me->GetCharmInfo()->SetIsCommandAttack(false);
HandleReturnMovement();
}
@@ -89,7 +91,8 @@ void PetAI::UpdateAI(const uint32 diff)
m_updateAlliesTimer -= diff;
// me->getVictim() can't be used for check in case stop fighting, me->getVictim() clear at Unit death etc.
- if (me->getVictim())
+ // Must also check if victim is alive
+ if (me->getVictim() && me->getVictim()->isAlive())
{
// is only necessary to stop casting, the pet must not exit combat
if (me->getVictim()->HasBreakableByDamageCrowdControlAura(me))
@@ -121,10 +124,16 @@ void PetAI::UpdateAI(const uint32 diff)
if (nextTarget)
AttackStart(nextTarget);
else
+ {
+ me->GetCharmInfo()->SetIsCommandAttack(false);
HandleReturnMovement();
+ }
}
else
+ {
+ me->GetCharmInfo()->SetIsCommandAttack(false);
HandleReturnMovement();
+ }
}
else if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW)) // no charm info and no victim
HandleReturnMovement();
@@ -301,7 +310,7 @@ void PetAI::KilledUnit(Unit* victim)
// Can't use _stopAttack() because that activates movement handlers and ignores
// next target selection
me->AttackStop();
- me->GetCharmInfo()->SetIsCommandAttack(false);
+ me->InterruptNonMeleeSpells(false);
me->SendMeleeAttackStop(); // Stops the pet's 'Attack' button from flashing
Unit* nextTarget = SelectNextTarget();
@@ -309,7 +318,10 @@ void PetAI::KilledUnit(Unit* victim)
if (nextTarget)
AttackStart(nextTarget);
else
+ {
+ me->GetCharmInfo()->SetIsCommandAttack(false);
HandleReturnMovement(); // Return
+ }
}
void PetAI::AttackStart(Unit* target)
diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h
index 8e5311fa000..d7f1dca3fbf 100755
--- a/src/server/game/AI/CoreAI/PetAI.h
+++ b/src/server/game/AI/CoreAI/PetAI.h
@@ -32,8 +32,6 @@ class PetAI : public CreatureAI
explicit PetAI(Creature* c);
void EnterEvadeMode();
- void JustDied(Unit* /*who*/) { _stopAttack(); }
-
void UpdateAI(const uint32);
static int Permissible(const Creature*);
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
index 119880bae8d..59dc6761583 100644
--- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
@@ -188,29 +188,6 @@ bool BattlefieldWG::SetupBattlefield()
go->SetUInt32Value(GAMEOBJECT_FACTION, WintergraspFaction[GetDefenderTeam()]);
}
- // Spawn banners in the keep
- for (uint8 i = 0; i < WG_KEEPGAMEOBJECT_MAX; i++)
- {
- if (GameObject* go = SpawnGameObject(WGKeepGameObject[i].entryHorde, WGKeepGameObject[i].x, WGKeepGameObject[i].y, WGKeepGameObject[i].z, WGKeepGameObject[i].o))
- {
- go->SetRespawnTime(GetDefenderTeam()? RESPAWN_ONE_DAY : RESPAWN_IMMEDIATELY);
- m_KeepGameObject[1].insert(go);
- }
- if (GameObject* go = SpawnGameObject(WGKeepGameObject[i].entryAlliance, WGKeepGameObject[i].x, WGKeepGameObject[i].y, WGKeepGameObject[i].z, WGKeepGameObject[i].o))
- {
- go->SetRespawnTime(GetDefenderTeam()? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY);
- m_KeepGameObject[0].insert(go);
- }
- }
-
- // Show defender banner in keep
- for (GameObjectSet::const_iterator itr = m_KeepGameObject[GetDefenderTeam()].begin(); itr != m_KeepGameObject[GetDefenderTeam()].end(); ++itr)
- (*itr)->SetRespawnTime(RESPAWN_IMMEDIATELY);
-
- // Hide attackant banner in keep
- for (GameObjectSet::const_iterator itr = m_KeepGameObject[GetAttackerTeam()].begin(); itr != m_KeepGameObject[GetAttackerTeam()].end(); ++itr)
- (*itr)->SetRespawnTime(RESPAWN_ONE_DAY);
-
UpdateCounterVehicle(true);
return true;
}
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h
index 323f7f2b13d..49ea25a5e04 100644
--- a/src/server/game/Battlefield/Zones/BattlefieldWG.h
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h
@@ -440,10 +440,9 @@ uint32 const VehNumWorldState[] = { 3680, 3490 };
uint32 const MaxVehNumWorldState[] = { 3681, 3491 };
uint32 const ClockWorldState[] = { 3781, 4354 };
uint32 const WintergraspFaction[] = { 1732, 1735, 35 };
-float const WintergraspStalkerPos[] = { 0, 0, 0, 0 };
+float const WintergraspStalkerPos[] = { 4948.985f, 2937.789f, 550.5172f, 1.815142f };
uint8 const WG_MAX_OBJ = 32;
-uint8 const WG_KEEPGAMEOBJECT_MAX = 44;
uint8 const WG_MAX_TURRET = 15;
uint8 const WG_MAX_KEEP_NPC = 39;
uint8 const WG_MAX_OUTSIDE_NPC = 14;
@@ -580,6 +579,19 @@ struct WintergraspBuildingSpawnData
uint32 nameId;
};
+struct WintergraspRebuildableBuildingData
+{
+ uint32 entry;
+ uint64 Guid;
+ uint32 WorldState;
+ float x;
+ float y;
+ float z;
+ float o;
+ uint32 type;
+ uint32 nameId;
+};
+
const WintergraspBuildingSpawnData WGGameObjectBuilding[WG_MAX_OBJ] =
{
// Wall (Not spawned in db)
@@ -628,99 +640,6 @@ const WintergraspBuildingSpawnData WGGameObjectBuilding[WG_MAX_OBJ] =
{ GO_WINTERGRASP_VAULT_GATE, 3773, 5397.11f, 2841.54f, 425.899f, 3.14159f, BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST, 0 },
};
-
-// *********************************************************
-// **********Keep Element(GameObject,Creature)**************
-// *********************************************************
-
-// Keep gameobject
-// 192488 : 10 in sql, 19 in header
-// 192501 : 12 in sql, 17 in header
-// 192416 : 1 in sql, 33 in header
-// 192374 : 1 in sql, 1 in header
-// 192375 : 1 in sql, 1 in header
-// 192336 : 1 in sql, 1 in header
-// 192255 : 1 in sql, 1 in header
-// 192269 : 1 in sql, 7 in header
-// 192254 : 1 in sql, 1 in header
-// 192349 : 1 in sql, 1 in header
-// 192366 : 1 in sql, 3 in header
-// 192367 : 1 in sql, 1 in header
-// 192364 : 1 in sql, 1 in header
-// 192370 : 1 in sql, 1 in header
-// 192369 : 1 in sql, 1 in header
-// 192368 : 1 in sql, 1 in header
-// 192362 : 1 in sql, 1 in header
-// 192363 : 1 in sql, 1 in header
-// 192379 : 1 in sql, 1 in header
-// 192378 : 1 in sql, 1 in header
-// 192355 : 1 in sql, 1 in header
-// 192354 : 1 in sql, 1 in header
-// 192358 : 1 in sql, 1 in header
-// 192359 : 1 in sql, 1 in header
-// 192338 : 1 in sql, 1 in header
-// 192339 : 1 in sql, 1 in header
-// 192284 : 1 in sql, 1 in header
-// 192285 : 1 in sql, 1 in header
-// 192371 : 1 in sql, 1 in header
-// 192372 : 1 in sql, 1 in header
-// 192373 : 1 in sql, 1 in header
-// 192360 : 1 in sql, 1 in header
-// 192361 : 1 in sql, 1 in header
-// 192356 : 1 in sql, 1 in header
-// 192352 : 1 in sql, 1 in header
-// 192353 : 1 in sql, 1 in header
-// 192357 : 1 in sql, 1 in header
-// 192350 : 1 in sql, 1 in header
-// 192351 : 1 in sql, 1 in header
-const WintergraspObjectPositionData WGKeepGameObject[WG_KEEPGAMEOBJECT_MAX] =
-{
- { 5262.540039f, 3047.949951f, 432.054993f, 3.106650f, 192488, 192501 }, // Flag on tower
- { 5272.939941f, 2976.550049f, 444.492004f, 3.124120f, 192374, 192416 }, // Flag on Wall Intersect
- { 5235.189941f, 2941.899902f, 444.278015f, 1.588250f, 192375, 192416 }, // Flag on Wall Intersect
- { 5163.129883f, 2952.590088f, 433.502991f, 1.535890f, 192488, 192501 }, // Flag on tower
- { 5145.109863f, 2935.000000f, 433.385986f, 3.141590f, 192488, 192501 }, // Flag on tower
- { 5158.810059f, 2883.129883f, 431.618011f, 3.141590f, 192488, 192416 }, // Flag on wall
- { 5154.490234f, 2862.149902f, 445.011993f, 3.141590f, 192336, 192416 }, // Flag on Wall Intersect
- { 5154.520020f, 2853.310059f, 409.183014f, 3.141590f, 192255, 192269 }, // Flag on the floor
- { 5154.459961f, 2828.939941f, 409.188995f, 3.141590f, 192254, 192269 }, // Flag on the floor
- { 5155.310059f, 2820.739990f, 444.979004f, -3.13286f, 192349, 192416 }, // Flag on wall intersect
- { 5160.339844f, 2798.610107f, 430.769012f, 3.141590f, 192488, 192416 }, // Flag on wall
- { 5146.040039f, 2747.209961f, 433.584015f, 3.071770f, 192488, 192501 }, // Flag on tower
- { 5163.779785f, 2729.679932f, 433.394012f, -1.58825f, 192488, 192501 }, // Flag on tower
- { 5236.270020f, 2739.459961f, 444.992004f, -1.59698f, 192366, 192416 }, // Flag on wall intersect
- { 5271.799805f, 2704.870117f, 445.183014f, -3.13286f, 192367, 192416 }, // Flag on wall intersect
- { 5260.819824f, 2631.800049f, 433.324005f, 3.054330f, 192488, 192501 }, // Flag on tower
- { 5278.379883f, 2613.830078f, 433.408997f, -1.58825f, 192488, 192501 }, // Flag on tower
- { 5350.879883f, 2622.719971f, 444.686005f, -1.57080f, 192364, 192416 }, // Flag on wall intersect
- { 5392.270020f, 2639.739990f, 435.330994f, 1.509710f, 192370, 192416 }, // Flag on wall intersect
- { 5350.950195f, 2640.360107f, 435.407990f, 1.570800f, 192369, 192416 }, // Flag on wall intersect
- { 5289.459961f, 2704.679932f, 435.875000f, -0.01745f, 192368, 192416 }, // Flag on wall intersect
- { 5322.120117f, 2763.610107f, 444.973999f, -1.55334f, 192362, 192416 }, // Flag on wall intersect
- { 5363.609863f, 2763.389893f, 445.023987f, -1.54462f, 192363, 192416 }, // Flag on wall intersect
- { 5363.419922f, 2781.030029f, 435.763000f, 1.570800f, 192379, 192416 }, // Flag on wall intersect
- { 5322.020020f, 2781.129883f, 435.811005f, 1.570800f, 192378, 192416 }, // Flag on wall intersect
- { 5288.919922f, 2820.219971f, 435.721008f, 0.017452f, 192355, 192416 }, // Flag on wall intersect
- { 5288.410156f, 2861.790039f, 435.721008f, 0.017452f, 192354, 192416 }, // Flag on wall intersect
- { 5322.229980f, 2899.429932f, 435.808014f, -1.58825f, 192358, 192416 }, // Flag on wall intersect
- { 5364.350098f, 2899.399902f, 435.838989f, -1.57080f, 192359, 192416 }, // Flag on wall intersect
- { 5397.759766f, 2873.080078f, 455.460999f, 3.106650f, 192338, 192416 }, // Flag on keep
- { 5397.390137f, 2809.330078f, 455.343994f, 3.106650f, 192339, 192416 }, // Flag on keep
- { 5372.479980f, 2862.500000f, 409.049011f, 3.141590f, 192284, 192269 }, // Flag on floor
- { 5371.490234f, 2820.800049f, 409.177002f, 3.141590f, 192285, 192269 }, // Flag on floor
- { 5364.290039f, 2916.939941f, 445.330994f, 1.579520f, 192371, 192416 }, // Flag on wall intersect
- { 5322.859863f, 2916.949951f, 445.153992f, 1.562070f, 192372, 192416 }, // Flag on wall intersect
- { 5290.350098f, 2976.560059f, 435.221008f, 0.017452f, 192373, 192416 }, // Flag on wall intersect
- { 5352.370117f, 3037.090088f, 435.252014f, -1.57080f, 192360, 192416 }, // Flag on wall intersect
- { 5392.649902f, 3037.110107f, 433.713013f, -1.52716f, 192361, 192416 }, // Flag on wall intersect
- { 5237.069824f, 2757.030029f, 435.795990f, 1.518440f, 192356, 192416 }, // Flag on wall intersect
- { 5173.020020f, 2820.929932f, 435.720001f, 0.017452f, 192352, 192416 }, // Flag on wall intersect
- { 5172.109863f, 2862.570068f, 435.721008f, 0.017452f, 192353, 192416 }, // Flag on wall intersect
- { 5235.339844f, 2924.340088f, 435.040009f, -1.57080f, 192357, 192416 }, // Flag on wall intersect
- { 5270.689941f, 2861.780029f, 445.058014f, -3.11539f, 192350, 192416 }, // Flag on wall intersect
- { 5271.279785f, 2820.159912f, 445.200989f, -3.13286f, 192351, 192416 } // Flag on wall intersect
-};
-
const Position WGTurret[WG_MAX_TURRET] =
{
{ 5391.19f, 3060.8f, 419.616f, 1.69557f },
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 1b303760095..699445f8ccc 100755
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -530,20 +530,23 @@ inline void Battleground::_ProcessJoin(uint32 diff)
player->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
player->ResetAllPowers();
- // remove auras with duration lower than 30s
- Unit::AuraApplicationMap & auraMap = player->GetAppliedAuras();
- for (Unit::AuraApplicationMap::iterator iter = auraMap.begin(); iter != auraMap.end();)
+ if (!player->isGameMaster())
{
- AuraApplication * aurApp = iter->second;
- Aura* aura = aurApp->GetBase();
- if (!aura->IsPermanent()
- && aura->GetDuration() <= 30*IN_MILLISECONDS
- && aurApp->IsPositive()
- && (!(aura->GetSpellInfo()->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
- && (!aura->HasEffectType(SPELL_AURA_MOD_INVISIBILITY)))
- player->RemoveAura(iter);
- else
- ++iter;
+ // remove auras with duration lower than 30s
+ Unit::AuraApplicationMap & auraMap = player->GetAppliedAuras();
+ for (Unit::AuraApplicationMap::iterator iter = auraMap.begin(); iter != auraMap.end();)
+ {
+ AuraApplication * aurApp = iter->second;
+ Aura* aura = aurApp->GetBase();
+ if (!aura->IsPermanent()
+ && aura->GetDuration() <= 30*IN_MILLISECONDS
+ && aurApp->IsPositive()
+ && (!(aura->GetSpellInfo()->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
+ && (!aura->HasEffectType(SPELL_AURA_MOD_INVISIBILITY)))
+ player->RemoveAura(iter);
+ else
+ ++iter;
+ }
}
}
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 917c4cd7f90..406fb7cb753 100755
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -611,7 +611,8 @@ bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) const
sourceType == CONDITION_SOURCE_TYPE_VEHICLE_SPELL ||
sourceType == CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET ||
sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT ||
- sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT);
+ sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT ||
+ sourceType == CONDITION_SOURCE_TYPE_PHASE_DEFINITION);
}
bool ConditionMgr::CanHaveSourceIdSet(ConditionSourceType sourceType) const
@@ -687,6 +688,23 @@ ConditionList ConditionMgr::GetConditionsForSmartEvent(int32 entryOrGuid, uint32
return cond;
}
+ConditionList ConditionMgr::GetConditionsForPhaseDefinition(uint32 zone, uint32 entry)
+{
+ ConditionList cond;
+ PhaseDefinitionConditionContainer::const_iterator itr = PhaseDefinitionsConditionStore.find(zone);
+ if (itr != PhaseDefinitionsConditionStore.end())
+ {
+ ConditionTypeContainer::const_iterator i = (*itr).second.find(entry);
+ if (i != (*itr).second.end())
+ {
+ cond = (*i).second;
+ sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForPhaseDefinition: found conditions for zone %u entry %u spell %u", zone, entry);
+ }
+ }
+
+ return cond;
+}
+
void ConditionMgr::LoadConditions(bool isReload)
{
uint32 oldMSTime = getMSTime();
@@ -898,6 +916,13 @@ void ConditionMgr::LoadConditions(bool isReload)
++count;
continue;
}
+ case CONDITION_SOURCE_TYPE_PHASE_DEFINITION:
+ {
+ PhaseDefinitionsConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
+ valid = true;
+ ++count;
+ continue;
+ }
default:
break;
}
@@ -1389,6 +1414,13 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
return false;
}
break;
+ case CONDITION_SOURCE_TYPE_PHASE_DEFINITION:
+ if (!PhaseMgr::IsConditionTypeSupported(cond->ConditionType))
+ {
+ sLog->outError(LOG_FILTER_SQL, "Condition source type `CONDITION_SOURCE_TYPE_PHASE_DEFINITION` does not support condition type %u, ignoring.", cond->ConditionType);
+ return false;
+ }
+ break;
case CONDITION_SOURCE_TYPE_GOSSIP_MENU:
case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
case CONDITION_SOURCE_TYPE_SMART_EVENT:
@@ -1399,6 +1431,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
return true;
}
+
bool ConditionMgr::isConditionTypeValid(Condition* cond)
{
if (cond->ConditionType == CONDITION_NONE || cond->ConditionType >= CONDITION_MAX)
@@ -1940,6 +1973,19 @@ void ConditionMgr::Clean()
SpellClickEventConditionStore.clear();
+ for (PhaseDefinitionConditionContainer::iterator itr = PhaseDefinitionsConditionStore.begin(); itr != PhaseDefinitionsConditionStore.end(); ++itr)
+ {
+ for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
+ {
+ for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
+ delete *i;
+ it->second.clear();
+ }
+ itr->second.clear();
+ }
+
+ PhaseDefinitionsConditionStore.clear();
+
// this is a BIG hack, feel free to fix it if you can figure out the ConditionMgr ;)
for (std::list<Condition*>::const_iterator itr = AllocatedMemoryStore.begin(); itr != AllocatedMemoryStore.end(); ++itr)
delete *itr;
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index 57af0562dcd..fe7f6a18af8 100755
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -124,7 +124,8 @@ enum ConditionSourceType
CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK = 20,
CONDITION_SOURCE_TYPE_VEHICLE_SPELL = 21,
CONDITION_SOURCE_TYPE_SMART_EVENT = 22,
- CONDITION_SOURCE_TYPE_MAX = 23 //MAX
+ CONDITION_SOURCE_TYPE_PHASE_DEFINITION = 23,
+ CONDITION_SOURCE_TYPE_MAX = 24 //MAX
};
enum ComparisionType
@@ -211,6 +212,7 @@ typedef std::map<uint32, ConditionList> ConditionTypeContainer;
typedef std::map<ConditionSourceType, ConditionTypeContainer> ConditionContainer;
typedef std::map<uint32, ConditionTypeContainer> CreatureSpellConditionContainer;
typedef std::map<std::pair<int32, uint32 /*SAI source_type*/>, ConditionTypeContainer> SmartEventConditionContainer;
+typedef std::map<int32 /*zoneId*/, ConditionTypeContainer> PhaseDefinitionConditionContainer;
typedef std::map<uint32, ConditionList> ConditionReferenceContainer;//only used for references
@@ -237,6 +239,7 @@ class ConditionMgr
ConditionList GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId);
ConditionList GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType);
ConditionList GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId);
+ ConditionList GetConditionsForPhaseDefinition(uint32 zone, uint32 entry);
private:
bool isSourceTypeValid(Condition* cond);
@@ -254,6 +257,7 @@ class ConditionMgr
CreatureSpellConditionContainer VehicleSpellConditionStore;
CreatureSpellConditionContainer SpellClickEventConditionStore;
SmartEventConditionContainer SmartEventConditionStore;
+ PhaseDefinitionConditionContainer PhaseDefinitionsConditionStore;
};
template <class T> bool CompareValues(ComparisionType type, T val1, T val2)
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 308b9fa1a60..a1a0931dc5a 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -1408,8 +1408,8 @@ struct LockEntry
struct PhaseEntry
{
uint32 ID; // 0
- char* Name; // 1
- uint32 phaseShift; // 2
+ char* Name; // 1
+ uint32 flag; // 2
};
struct MailTemplateEntry
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 5a5e4c5c848..d152dc5642f 100755
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -217,6 +217,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
SetDisplayId(goinfo->displayId);
+ m_model = GameObjectModel::Create(*this);
// GAMEOBJECT_BYTES_1, index at 0, 1, 2 and 3
SetGoType(GameobjectTypes(goinfo->type));
SetGoState(go_state);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index ddd52ff352f..0582a879d5f 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -649,7 +649,7 @@ void KillRewarder::Reward()
#ifdef _MSC_VER
#pragma warning(disable:4355)
#endif
-Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_reputationMgr(this)
+Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_reputationMgr(this), phaseMgr(this)
{
#ifdef _MSC_VER
#pragma warning(default:4355)
@@ -1564,6 +1564,16 @@ void Player::Update(uint32 p_time)
// check every second
if (now > m_Last_tick + 1)
UpdateSoulboundTradeItems();
+
+ // If mute expired, remove it from the DB
+ if (GetSession()->m_muteTime && GetSession()->m_muteTime < now)
+ {
+ GetSession()->m_muteTime = 0;
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_MUTE_TIME);
+ stmt->setInt64(0, 0); // Set the mute time to 0
+ stmt->setUInt32(1, GetSession()->GetAccountId());
+ LoginDatabase.Execute(stmt);
+ }
if (!m_timedquests.empty())
{
@@ -2928,18 +2938,6 @@ void Player::SetGameMaster(bool on)
}
else
{
- // restore phase
- uint32 newPhase = 0;
- AuraEffectList const& phases = GetAuraEffectsByType(SPELL_AURA_PHASE);
- if (!phases.empty())
- for (AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
- newPhase |= (*itr)->GetMiscValue();
-
- if (!newPhase)
- newPhase = PHASEMASK_NORMAL;
-
- SetPhaseMask(newPhase, false);
-
m_ExtraFlags &= ~ PLAYER_EXTRA_GM_ON;
setFactionForRace(getRace());
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM);
@@ -2960,6 +2958,9 @@ void Player::SetGameMaster(bool on)
getHostileRefManager().setOnlineOfflineState(true);
m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GM, SEC_PLAYER);
+
+ phaseMgr.AddUpdateFlag(PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED);
+ phaseMgr.Update();
}
UpdateObjectVisibility();
@@ -3192,6 +3193,11 @@ void Player::GiveLevel(uint8 level)
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL);
+ PhaseUpdateData phaseUdateData;
+ phaseUdateData.AddConditionType(CONDITION_LEVEL);
+
+ phaseMgr.NotifyConditionChanged(phaseUdateData);
+
// Refer-A-Friend
if (GetSession()->GetRecruiterId())
if (level < sWorld->getIntConfig(CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL))
@@ -7618,6 +7624,8 @@ void Player::UpdateArea(uint32 newArea)
// so apply them accordingly
m_areaUpdateId = newArea;
+ phaseMgr.AddUpdateFlag(PHASE_UPDATE_FLAG_AREA_UPDATE);
+
AreaTableEntry const* area = GetAreaEntryByAreaID(newArea);
pvpInfo.inFFAPvPArea = area && (area->flags & AREA_FLAG_ARENA);
UpdatePvPState(true);
@@ -7634,10 +7642,14 @@ void Player::UpdateArea(uint32 newArea)
}
else
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
+
+ phaseMgr.RemoveUpdateFlag(PHASE_UPDATE_FLAG_AREA_UPDATE);
}
void Player::UpdateZone(uint32 newZone, uint32 newArea)
{
+ phaseMgr.AddUpdateFlag(PHASE_UPDATE_FLAG_ZONE_UPDATE);
+
if (m_zoneUpdateId != newZone)
{
sOutdoorPvPMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId);
@@ -7747,6 +7759,8 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
UpdateLocalChannels(newZone);
UpdateZoneDependentAuras(newZone);
+
+ phaseMgr.RemoveUpdateFlag(PHASE_UPDATE_FLAG_ZONE_UPDATE);
}
//If players are too far away from the duel flag... they lose the duel
@@ -15000,6 +15014,11 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
CastSpell(this, itr->second->spellId, true);
}
+ PhaseUpdateData phaseUdateData;
+ phaseUdateData.AddQuestUpdate(quest_id);
+
+ phaseMgr.NotifyConditionChanged(phaseUdateData);
+
UpdateForQuestWorldObjects();
}
@@ -15168,6 +15187,11 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
m_RewardedQuests.insert(quest_id);
m_RewardedQuestsSave[quest_id] = true;
+ PhaseUpdateData phaseUdateData;
+ phaseUdateData.AddQuestUpdate(quest_id);
+
+ phaseMgr.NotifyConditionChanged(phaseUdateData);
+
// StoreNewItem, mail reward, etc. save data directly to the database
// to prevent exploitable data desynchronisation we save the quest status to the database too
// (to prevent rewarding this quest another time while rewards were already given out)
@@ -15757,6 +15781,11 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status)
m_QuestStatusSave[quest_id] = true;
}
+ PhaseUpdateData phaseUdateData;
+ phaseUdateData.AddQuestUpdate(quest_id);
+
+ phaseMgr.NotifyConditionChanged(phaseUdateData);
+
UpdateForQuestWorldObjects();
}
@@ -15767,6 +15796,11 @@ void Player::RemoveActiveQuest(uint32 quest_id)
{
m_QuestStatus.erase(itr);
m_QuestStatusSave[quest_id] = false;
+
+ PhaseUpdateData phaseUdateData;
+ phaseUdateData.AddQuestUpdate(quest_id);
+
+ phaseMgr.NotifyConditionChanged(phaseUdateData);
return;
}
}
@@ -15778,6 +15812,11 @@ void Player::RemoveRewardedQuest(uint32 quest_id)
{
m_RewardedQuests.erase(rewItr);
m_RewardedQuestsSave[quest_id] = false;
+
+ PhaseUpdateData phaseUdateData;
+ phaseUdateData.AddQuestUpdate(quest_id);
+
+ phaseMgr.NotifyConditionChanged(phaseUdateData);
}
}
@@ -24410,25 +24449,6 @@ void Player::_LoadSkills(PreparedQueryResult result)
}
}
-uint32 Player::GetPhaseMaskForSpawn() const
-{
- uint32 phase = PHASEMASK_NORMAL;
- if (!isGameMaster())
- phase = GetPhaseMask();
- else
- {
- AuraEffectList const& phases = GetAuraEffectsByType(SPELL_AURA_PHASE);
- if (!phases.empty())
- phase = phases.front()->GetMiscValue();
- }
-
- // some aura phases include 1 normal map in addition to phase itself
- if (uint32 n_phase = phase & ~PHASEMASK_NORMAL)
- return n_phase;
-
- return PHASEMASK_NORMAL;
-}
-
InventoryResult Player::CanEquipUniqueItem(Item* pItem, uint8 eslot, uint32 limit_count) const
{
ItemTemplate const* pProto = pItem->GetTemplate();
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 4d91ac42879..f1f58231bef 100755..100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -37,6 +37,9 @@
#include "Unit.h"
#include "Util.h" // for Tokens typedef
#include "WorldSession.h"
+#include "PhaseMgr.h"
+
+// for template
#include "SpellMgr.h"
#include<string>
@@ -54,6 +57,7 @@ class PlayerMenu;
class PlayerSocial;
class SpellCastTargets;
class UpdateMask;
+class PhaseMgr;
typedef std::deque<Mail*> PlayerMails;
@@ -1342,7 +1346,8 @@ class Player : public Unit, public GridObject<Player>
Pet* GetPet() const;
Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 despwtime);
void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false);
- uint32 GetPhaseMaskForSpawn() const; // used for proper set phase for DB at GM-mode creature/GO spawn
+
+ PhaseMgr& GetPhaseMgr() { return phaseMgr; }
void Say(const std::string& text, const uint32 language);
void Yell(const std::string& text, const uint32 language);
@@ -3083,6 +3088,8 @@ class Player : public Unit, public GridObject<Player>
uint32 _pendingBindTimer;
uint32 _activeCheats;
+
+ PhaseMgr phaseMgr;
};
void AddItemsSetItem(Player*player, Item* item);
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index f2266f03ae9..eac2b531805 100755
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -1101,8 +1101,8 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
//demons benefit from warlocks shadow or fire damage
else if (isPet())
{
- int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
- int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW);
+ int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) + owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
+ int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) + owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW);
int32 maximum = (fire > shadow) ? fire : shadow;
if (maximum < 0)
maximum = 0;
@@ -1112,7 +1112,7 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
//water elementals benefit from mage's frost damage
else if (GetEntry() == ENTRY_WATER_ELEMENTAL)
{
- int32 frost = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FROST)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FROST);
+ int32 frost = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FROST)) + owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FROST);
if (frost < 0)
frost = 0;
SetBonusDamage(int32(frost * 0.4f));
@@ -1145,14 +1145,14 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType)
//force of nature
if (GetEntry() == ENTRY_TREANT)
{
- int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_NATURE)) - m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_NATURE);
+ int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_NATURE)) + m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_NATURE);
if (spellDmg > 0)
bonusDamage = spellDmg * 0.09f;
}
//greater fire elemental
else if (GetEntry() == ENTRY_FIRE_ELEMENTAL)
{
- int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
+ int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) + m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE);
if (spellDmg > 0)
bonusDamage = spellDmg * 0.4f;
}
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 669f89a1b8d..dd2afa44a07 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -7565,7 +7565,7 @@ SpellScriptsBounds ObjectMgr::GetSpellScriptsBounds(uint32 spell_id)
}
// this allows calculating base reputations to offline players, just by race and class
-int32 ObjectMgr::GetBaseReputation(FactionEntry const* factionEntry, uint8 race, uint8 playerClass)
+int32 ObjectMgr::GetBaseReputationOff(FactionEntry const* factionEntry, uint8 race, uint8 playerClass)
{
if (!factionEntry)
return 0;
@@ -8652,7 +8652,7 @@ void ObjectMgr::LoadFactionChangeTitles()
}
uint32 count = 0;
-
+
do
{
Field* fields = result->Fetch();
@@ -8666,7 +8666,7 @@ void ObjectMgr::LoadFactionChangeTitles()
sLog->outError(LOG_FILTER_SQL, "Title %u referenced in `player_factionchange_title` does not exist, pair skipped!", horde);
else
FactionChange_Titles[alliance] = horde;
-
+
++count;
}
while (result->NextRow());
@@ -8674,6 +8674,99 @@ void ObjectMgr::LoadFactionChangeTitles()
sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u faction change title pairs in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+void ObjectMgr::LoadPhaseDefinitions()
+{
+ _PhaseDefinitionStore.clear();
+
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2 3 4 5
+ QueryResult result = WorldDatabase.Query("SELECT zoneId, entry, phasemask, phaseId, terrainswapmap, flags FROM `phase_definitions` ORDER BY `entry` ASC");
+
+ if (!result)
+ {
+ sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 phasing definitions. DB table `phase_definitions` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ Field *fields = result->Fetch();
+
+ PhaseDefinition PhaseDefinition;
+
+ PhaseDefinition.zoneId = fields[0].GetUInt32();
+ PhaseDefinition.entry = fields[1].GetUInt32();
+ PhaseDefinition.phasemask = fields[2].GetUInt32();
+ PhaseDefinition.phaseId = fields[3].GetUInt32();
+ PhaseDefinition.terrainswapmap = fields[4].GetUInt32();
+ PhaseDefinition.flags = fields[5].GetUInt32();
+
+ // Checks
+ if ((PhaseDefinition.flags & PHASE_FLAG_OVERWRITE_EXISTING) && (PhaseDefinition.flags & PHASE_FLAG_NEGATE_PHASE))
+ {
+ sLog->outError(LOG_FILTER_SQL, "Flags defined in phase_definitions in zoneId %d and entry %u does contain PHASE_FLAG_OVERWRITE_EXISTING and PHASE_FLAG_NEGATE_PHASE. Setting flags to PHASE_FLAG_OVERWRITE_EXISTING", PhaseDefinition.zoneId, PhaseDefinition.entry);
+ PhaseDefinition.flags &= ~PHASE_FLAG_NEGATE_PHASE;
+ }
+
+ _PhaseDefinitionStore[PhaseDefinition.zoneId].push_back(PhaseDefinition);
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u phasing definitions in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void ObjectMgr::LoadSpellPhaseInfo()
+{
+ _SpellPhaseStore.clear();
+
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2
+ QueryResult result = WorldDatabase.Query("SELECT id, phasemask, terrainswapmap FROM `spell_phase`");
+
+ if (!result)
+ {
+ sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 spell dbc infos. DB table `spell_phase` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ do
+ {
+ Field *fields = result->Fetch();
+
+ SpellPhaseInfo spellPhaseInfo;
+ spellPhaseInfo.spellId = fields[0].GetUInt32();
+
+ SpellInfo const* spell = sSpellMgr->GetSpellInfo(spellPhaseInfo.spellId);
+ if (!spell)
+ {
+ sLog->outError(LOG_FILTER_SQL, "Spell %u defined in `spell_phase` does not exists, skipped.", spellPhaseInfo.spellId);
+ continue;
+ }
+
+ if (!spell->HasAura(SPELL_AURA_PHASE))
+ {
+ sLog->outError(LOG_FILTER_SQL, "Spell %u defined in `spell_phase` does not have aura effect type SPELL_AURA_PHASE, useless value.", spellPhaseInfo.spellId);
+ continue;
+ }
+
+ spellPhaseInfo.phasemask = fields[1].GetUInt32();
+ spellPhaseInfo.terrainswapmap = fields[2].GetUInt32();
+
+ _SpellPhaseStore[spellPhaseInfo.spellId] = spellPhaseInfo;
+
+ ++count;
+ }
+ while (result->NextRow());
+ sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u spell dbc infos in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
GameObjectTemplate const* ObjectMgr::GetGameObjectTemplate(uint32 entry)
{
GameObjectTemplateContainer::const_iterator itr = _gameObjectTemplateStore.find(entry);
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index e727b9724e5..496d5ae224f 100755
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -42,8 +42,10 @@
#include <limits>
#include "ConditionMgr.h"
#include <functional>
+#include "PhaseMgr.h"
class Item;
+class PhaseMgr;
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push, N), also any gcc version not support it at some platform
#if defined(__GNUC__)
@@ -743,7 +745,7 @@ class ObjectMgr
return NULL;
}
- int32 GetBaseReputation(FactionEntry const* factionEntry, uint8 race, uint8 playerClass);
+ int32 GetBaseReputationOff(FactionEntry const* factionEntry, uint8 race, uint8 playerClass);
RepSpilloverTemplate const* GetRepSpilloverTemplate(uint32 factionId) const
{
@@ -906,6 +908,12 @@ class ObjectMgr
void LoadTrainerSpell();
void AddSpellToTrainer(uint32 entry, uint32 spell, uint32 spellCost, uint32 reqSkill, uint32 reqSkillValue, uint32 reqLevel);
+ void LoadPhaseDefinitions();
+ void LoadSpellPhaseInfo();
+
+ PhaseDefinitionStore const* GetPhaseDefinitionStore() { return &_PhaseDefinitionStore; }
+ SpellPhaseStore const* GetSpellPhaseStore() { return &_SpellPhaseStore; }
+
std::string GeneratePetName(uint32 entry);
uint32 GetBaseXP(uint8 level);
uint32 GetXPForLevel(uint8 level) const;
@@ -1222,6 +1230,9 @@ class ObjectMgr
PageTextContainer _pageTextStore;
InstanceTemplateContainer _instanceTemplateStore;
+ PhaseDefinitionStore _PhaseDefinitionStore;
+ SpellPhaseStore _SpellPhaseStore;
+
private:
void LoadScripts(ScriptsType type);
void CheckScripts(ScriptsType type, std::set<int32>& ids);
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index a37362ce7bc..77d1c05abf2 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -2122,10 +2122,10 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
FactionEntry const* factionEntry = sFactionStore.LookupEntry(oldReputation);
// old base reputation
- int32 oldBaseRep = sObjectMgr->GetBaseReputation(factionEntry, oldRace, playerClass);
+ int32 oldBaseRep = sObjectMgr->GetBaseReputationOff(factionEntry, oldRace, playerClass);
// new base reputation
- int32 newBaseRep = sObjectMgr->GetBaseReputation(sFactionStore.LookupEntry(newReputation), race, playerClass);
+ int32 newBaseRep = sObjectMgr->GetBaseReputationOff(sFactionStore.LookupEntry(newReputation), race, playerClass);
// final reputation shouldnt change
int32 FinalRep = oldDBRep + oldBaseRep;
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 2acc8ffcf7b..1947baa43b6 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -1753,10 +1753,51 @@ void WorldSession::HandleReadyForAccountDataTimes(WorldPacket& /*recvData*/)
SendAccountDataTimes(GLOBAL_CACHE_MASK);
}
-void WorldSession::SendSetPhaseShift(uint32 PhaseShift)
+void WorldSession::SendSetPhaseShift(std::set<uint32> const& phaseIds, std::set<uint32> const& terrainswaps)
{
- WorldPacket data(SMSG_SET_PHASE_SHIFT, 4);
- data << uint32(PhaseShift);
+ ObjectGuid guid = _player->GetGUID();
+
+ WorldPacket data(SMSG_SET_PHASE_SHIFT, 1 + 8 + 4 + 4 + 4 + 4 + 2 * phaseIds.size() + 4 + terrainswaps.size() * 2);
+ data.WriteBit(guid[2]);
+ data.WriteBit(guid[3]);
+ data.WriteBit(guid[1]);
+ data.WriteBit(guid[6]);
+ data.WriteBit(guid[4]);
+ data.WriteBit(guid[5]);
+ data.WriteBit(guid[0]);
+ data.WriteBit(guid[7]);
+
+ data.WriteByteSeq(guid[7]);
+ data.WriteByteSeq(guid[4]);
+
+ data << uint32(0);
+ //for (uint8 i = 0; i < worldMapAreaCount; ++i)
+ // data << uint16(0); // WorldMapArea.dbc id (controls map display)
+
+ data.WriteByteSeq(guid[1]);
+
+ data << uint32(0); // flags (not phasemask)
+
+ data.WriteByteSeq(guid[2]);
+ data.WriteByteSeq(guid[6]);
+
+ data << uint32(0); // Inactive terrain swaps
+ //for (uint8 i = 0; i < inactiveSwapsCount; ++i)
+ // data << uint16(0);
+
+ data << uint32(phaseIds.size()) * 2; // Phase.dbc ids
+ for (std::set<uint32>::const_iterator itr = phaseIds.begin(); itr != phaseIds.end(); ++itr)
+ data << uint16(*itr);
+
+ data.WriteByteSeq(guid[3]);
+ data.WriteByteSeq(guid[0]);
+
+ data << uint32(terrainswaps.size()) * 2; // Active terrain swaps
+ for (std::set<uint32>::const_iterator itr = terrainswaps.begin(); itr != terrainswaps.end(); ++itr)
+ data << uint16(*itr);
+
+ data.WriteByteSeq(guid[5]);
+
SendPacket(&data);
}
diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp
index d967ece9cf2..f14dc3c8b14 100755
--- a/src/server/game/Instances/InstanceScript.cpp
+++ b/src/server/game/Instances/InstanceScript.cpp
@@ -450,3 +450,14 @@ void InstanceScript::UpdateEncounterState(EncounterCreditType type, uint32 credi
}
}
}
+
+void InstanceScript::UpdatePhasing()
+{
+ PhaseUpdateData phaseUdateData;
+ phaseUdateData.AddConditionType(CONDITION_INSTANCE_DATA);
+
+ Map::PlayerList const& players = instance->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player* player = itr->getSource())
+ player->GetPhaseMgr().NotifyConditionChanged(phaseUdateData);
+}
diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h
index ab37c1ab5e9..291ba3be52f 100755
--- a/src/server/game/Instances/InstanceScript.h
+++ b/src/server/game/Instances/InstanceScript.h
@@ -217,6 +217,9 @@ class InstanceScript : public ZoneScript
virtual void FillInitialWorldStates(WorldPacket& /*data*/) {}
+ // ReCheck PhaseTemplate related conditions
+ void UpdatePhasing();
+
protected:
void SetBossNumber(uint32 number) { bosses.resize(number); }
void LoadDoorData(DoorData const* data);
diff --git a/src/server/game/Maps/PhaseMgr.cpp b/src/server/game/Maps/PhaseMgr.cpp
new file mode 100644
index 00000000000..63bdff2d094
--- /dev/null
+++ b/src/server/game/Maps/PhaseMgr.cpp
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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 "PhaseMgr.h"
+#include "Chat.h"
+
+//////////////////////////////////////////////////////////////////
+// Updating
+
+PhaseMgr::PhaseMgr(Player* _player) : player(_player), phaseData(_player), _UpdateFlags(0)
+{
+ _PhaseDefinitionStore = sObjectMgr->GetPhaseDefinitionStore();
+ _SpellPhaseStore = sObjectMgr->GetSpellPhaseStore();
+}
+
+void PhaseMgr::Update()
+{
+ if (IsUpdateInProgress())
+ return;
+
+ if (_UpdateFlags & PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED)
+ phaseData.SendPhaseshiftToPlayer();
+
+ if (_UpdateFlags & PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED)
+ phaseData.SendPhaseMaskToPlayer();
+
+ _UpdateFlags = 0;
+}
+
+void PhaseMgr::RemoveUpdateFlag(PhaseUpdateFlag updateFlag)
+{
+ _UpdateFlags &= ~updateFlag;
+
+ if (updateFlag == PHASE_UPDATE_FLAG_ZONE_UPDATE)
+ {
+ // Update zone changes
+ if (phaseData.HasActiveDefinitions())
+ {
+ phaseData.ResetDefinitions();
+ _UpdateFlags |= (PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED | PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED);
+ }
+
+ if (_PhaseDefinitionStore->find(player->GetZoneId()) != _PhaseDefinitionStore->end())
+ Recalculate();
+ }
+
+ Update();
+}
+
+/////////////////////////////////////////////////////////////////
+// Notifier
+
+void PhaseMgr::NotifyConditionChanged(PhaseUpdateData const& updateData)
+{
+ if (NeedsPhaseUpdateWithData(updateData))
+ {
+ Recalculate();
+ Update();
+ }
+}
+
+//////////////////////////////////////////////////////////////////
+// Phasing Definitions
+
+void PhaseMgr::Recalculate()
+{
+ if (phaseData.HasActiveDefinitions())
+ {
+ phaseData.ResetDefinitions();
+ _UpdateFlags |= (PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED | PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED);
+ }
+
+ PhaseDefinitionStore::const_iterator itr = _PhaseDefinitionStore->find(player->GetZoneId());
+ if (itr != _PhaseDefinitionStore->end())
+ for (PhaseDefinitionContainer::const_iterator phase = itr->second.begin(); phase != itr->second.end(); ++phase)
+ if (CheckDefinition(&(*phase)))
+ {
+ phaseData.AddPhaseDefinition(&(*phase));
+
+ if (phase->phasemask)
+ _UpdateFlags |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED;
+
+ if (phase->phaseId || phase->terrainswapmap)
+ _UpdateFlags |= PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED;
+
+ if (phase->IsLastDefinition())
+ break;
+ }
+}
+
+inline bool PhaseMgr::CheckDefinition(PhaseDefinition const* phaseDefinition)
+{
+ return sConditionMgr->IsObjectMeetToConditions(player, sConditionMgr->GetConditionsForPhaseDefinition(phaseDefinition->zoneId, phaseDefinition->entry));
+}
+
+bool PhaseMgr::NeedsPhaseUpdateWithData(PhaseUpdateData const updateData) const
+{
+ PhaseDefinitionStore::const_iterator itr = _PhaseDefinitionStore->find(player->GetZoneId());
+ if (itr != _PhaseDefinitionStore->end())
+ {
+ for (PhaseDefinitionContainer::const_iterator phase = itr->second.begin(); phase != itr->second.end(); ++phase)
+ {
+ ConditionList conditionList = sConditionMgr->GetConditionsForPhaseDefinition(phase->zoneId, phase->entry);
+ for (ConditionList::const_iterator condition = conditionList.begin(); condition != conditionList.end(); ++condition)
+ if (updateData.IsConditionRelated(*condition))
+ return true;
+ }
+ }
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////
+// Auras
+
+void PhaseMgr::RegisterPhasingAuraEffect(AuraEffect const* auraEffect)
+{
+ PhaseInfo phaseInfo;
+
+ if (auraEffect->GetMiscValue())
+ {
+ _UpdateFlags |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED;
+ phaseInfo.phasemask = auraEffect->GetMiscValue();
+ }
+ else
+ {
+ SpellPhaseStore::const_iterator itr = _SpellPhaseStore->find(auraEffect->GetId());
+ if (itr != _SpellPhaseStore->end())
+ {
+ if (itr->second.phasemask)
+ {
+ _UpdateFlags |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED;
+ phaseInfo.phasemask = itr->second.phasemask;
+ }
+
+ if (itr->second.terrainswapmap)
+ phaseInfo.terrainswapmap = itr->second.terrainswapmap;
+ }
+ }
+
+ phaseInfo.phaseId = auraEffect->GetMiscValueB();
+
+ if (phaseInfo.NeedsClientSideUpdate())
+ _UpdateFlags |= PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED;
+
+ phaseData.AddAuraInfo(auraEffect->GetId(), phaseInfo);
+
+ Update();
+}
+
+void PhaseMgr::UnRegisterPhasingAuraEffect(AuraEffect const* auraEffect)
+{
+ _UpdateFlags |= phaseData.RemoveAuraInfo(auraEffect->GetId());
+
+ Update();
+}
+
+//////////////////////////////////////////////////////////////////
+// Commands
+
+void PhaseMgr::SendDebugReportToPlayer(Player* const debugger)
+{
+ ChatHandler(debugger).PSendSysMessage(LANG_PHASING_REPORT_STATUS, player->GetName(), player->GetZoneId(), player->getLevel(), player->GetTeamId(), _UpdateFlags);
+
+ PhaseDefinitionStore::const_iterator itr = _PhaseDefinitionStore->find(player->GetZoneId());
+ if (itr == _PhaseDefinitionStore->end())
+ ChatHandler(debugger).PSendSysMessage(LANG_PHASING_NO_DEFINITIONS, player->GetZoneId());
+ else
+ {
+ for (PhaseDefinitionContainer::const_iterator phase = itr->second.begin(); phase != itr->second.end(); ++phase)
+ {
+ if (CheckDefinition(&(*phase)))
+ ChatHandler(debugger).PSendSysMessage(LANG_PHASING_SUCCESS, phase->entry, phase->IsNegatingPhasemask() ? "negated Phase" : "Phase", phase->phasemask);
+ else
+ ChatHandler(debugger).PSendSysMessage(LANG_PHASING_FAILED, phase->phasemask, phase->entry, phase->zoneId);
+
+ if (phase->IsLastDefinition())
+ {
+ ChatHandler(debugger).PSendSysMessage(LANG_PHASING_LAST_PHASE, phase->phasemask, phase->entry, phase->zoneId);
+ break;
+ }
+ }
+ }
+
+ ChatHandler(debugger).PSendSysMessage(LANG_PHASING_LIST, phaseData._PhasemaskThroughDefinitions, phaseData._PhasemaskThroughAuras, phaseData._CustomPhasemask);
+
+ ChatHandler(debugger).PSendSysMessage(LANG_PHASING_PHASEMASK, phaseData.GetPhaseMaskForSpawn(), player->GetPhaseMask());
+}
+
+void PhaseMgr::SetCustomPhase(uint32 const phaseMask)
+{
+ phaseData._CustomPhasemask = phaseMask;
+
+ _UpdateFlags |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED;
+
+ Update();
+}
+
+//////////////////////////////////////////////////////////////////
+// Phase Data
+
+uint32 PhaseData::GetCurrentPhasemask() const
+{
+ if (player->isGameMaster())
+ return PHASEMASK_ANYWHERE;
+
+ if (_CustomPhasemask)
+ return _CustomPhasemask;
+
+ return GetPhaseMaskForSpawn();
+}
+
+inline uint32 PhaseData::GetPhaseMaskForSpawn() const
+{
+ uint32 const phase = (_PhasemaskThroughDefinitions | _PhasemaskThroughAuras);
+ return (phase ? phase : PHASEMASK_NORMAL);
+}
+
+void PhaseData::SendPhaseMaskToPlayer()
+{
+ // Server side update
+ uint32 const phasemask = GetCurrentPhasemask();
+ if (player->GetPhaseMask() == phasemask)
+ return;
+
+ player->SetPhaseMask(phasemask, false);
+
+ if (player->IsVisible())
+ player->UpdateObjectVisibility();
+}
+
+void PhaseData::SendPhaseshiftToPlayer()
+{
+ // Client side update
+ std::set<uint32> phaseIds;
+ std::set<uint32> terrainswaps;
+
+ for (PhaseInfoContainer::const_iterator itr = spellPhaseInfo.begin(); itr != spellPhaseInfo.end(); ++itr)
+ {
+ if (itr->second.terrainswapmap)
+ terrainswaps.insert(itr->second.terrainswapmap);
+
+ if (itr->second.phaseId)
+ phaseIds.insert(itr->second.phaseId);
+ }
+
+ // Phase Definitions
+ for (std::list<PhaseDefinition const*>::const_iterator itr = activePhaseDefinitions.begin(); itr != activePhaseDefinitions.end(); ++itr)
+ {
+ if ((*itr)->phaseId)
+ phaseIds.insert((*itr)->phaseId);
+
+ if ((*itr)->terrainswapmap)
+ terrainswaps.insert((*itr)->terrainswapmap);
+ }
+
+ player->GetSession()->SendSetPhaseShift(phaseIds, terrainswaps);
+}
+
+void PhaseData::AddPhaseDefinition(PhaseDefinition const* phaseDefinition)
+{
+ if (phaseDefinition->IsOverwritingExistingPhases())
+ {
+ activePhaseDefinitions.clear();
+ _PhasemaskThroughDefinitions = phaseDefinition->phasemask;
+ }
+ else
+ {
+ if (phaseDefinition->IsNegatingPhasemask())
+ _PhasemaskThroughDefinitions &= ~phaseDefinition->phasemask;
+ else
+ _PhasemaskThroughDefinitions |= phaseDefinition->phasemask;
+ }
+
+ activePhaseDefinitions.push_back(phaseDefinition);
+}
+
+void PhaseData::AddAuraInfo(uint32 const spellId, PhaseInfo phaseInfo)
+{
+ if (phaseInfo.phasemask)
+ _PhasemaskThroughAuras |= phaseInfo.phasemask;
+
+ spellPhaseInfo[spellId] = phaseInfo;
+}
+
+uint32 PhaseData::RemoveAuraInfo(uint32 const spellId)
+{
+ PhaseInfoContainer::const_iterator rAura = spellPhaseInfo.find(spellId);
+ if (rAura != spellPhaseInfo.end())
+ {
+ uint32 updateflag = 0;
+
+ if (rAura->second.NeedsClientSideUpdate())
+ updateflag |= PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED;
+
+ if (rAura->second.NeedsServerSideUpdate())
+ {
+ _PhasemaskThroughAuras = 0;
+
+ updateflag |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED;
+
+ spellPhaseInfo.erase(rAura);
+
+ for (PhaseInfoContainer::const_iterator itr = spellPhaseInfo.begin(); itr != spellPhaseInfo.end(); ++itr)
+ _PhasemaskThroughAuras |= itr->second.phasemask;
+ }
+
+ return updateflag;
+ }
+ else
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////
+// Phase Update Data
+
+void PhaseUpdateData::AddQuestUpdate(uint32 const questId)
+{
+ AddConditionType(CONDITION_QUESTREWARDED);
+ AddConditionType(CONDITION_QUESTTAKEN);
+ AddConditionType(CONDITION_QUEST_COMPLETE);
+ AddConditionType(CONDITION_QUEST_NONE);
+
+ _questId = questId;
+}
+
+bool PhaseUpdateData::IsConditionRelated(Condition const* condition) const
+{
+ switch (condition->ConditionType)
+ {
+ case CONDITION_QUESTREWARDED:
+ case CONDITION_QUESTTAKEN:
+ case CONDITION_QUEST_COMPLETE:
+ case CONDITION_QUEST_NONE:
+ return condition->ConditionValue1 == _questId && ((1 << condition->ConditionType) & _conditionTypeFlags);
+ default:
+ return (1 << condition->ConditionType) & _conditionTypeFlags;
+ }
+}
+
+bool PhaseMgr::IsConditionTypeSupported(ConditionTypes const conditionType)
+{
+ switch (conditionType)
+ {
+ case CONDITION_QUESTREWARDED:
+ case CONDITION_QUESTTAKEN:
+ case CONDITION_QUEST_COMPLETE:
+ case CONDITION_QUEST_NONE:
+ case CONDITION_TEAM:
+ case CONDITION_CLASS:
+ case CONDITION_RACE:
+ case CONDITION_INSTANCE_DATA:
+ case CONDITION_LEVEL:
+ return true;
+ default:
+ return false;
+ }
+}
diff --git a/src/server/game/Maps/PhaseMgr.h b/src/server/game/Maps/PhaseMgr.h
new file mode 100644
index 00000000000..accb0cd3ea8
--- /dev/null
+++ b/src/server/game/Maps/PhaseMgr.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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_PHASEMGR_H
+#define TRINITY_PHASEMGR_H
+
+#include "SharedDefines.h"
+#include "SpellAuras.h"
+#include "SpellAuraEffects.h"
+
+class ObjectMgr;
+class Player;
+
+// Phasing (visibility)
+enum PhasingFlags
+{
+ PHASE_FLAG_OVERWRITE_EXISTING = 0x01, // don't stack with existing phases, overwrites existing phases
+ PHASE_FLAG_NO_MORE_PHASES = 0x02, // stop calculating phases after this phase was applied (no more phases will be applied)
+ PHASE_FLAG_NEGATE_PHASE = 0x04 // negate instead to add the phasemask
+};
+
+enum PhaseUpdateFlag
+{
+ PHASE_UPDATE_FLAG_ZONE_UPDATE = 0x01,
+ PHASE_UPDATE_FLAG_AREA_UPDATE = 0x02,
+
+ // Internal flags
+ PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED = 0x08,
+ PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED = 0x10,
+};
+
+struct PhaseDefinition
+{
+ uint32 zoneId;
+ uint32 entry;
+ uint32 phasemask;
+ uint32 phaseId;
+ uint32 terrainswapmap;
+ uint8 flags;
+
+ bool IsOverwritingExistingPhases() const { return flags & PHASE_FLAG_OVERWRITE_EXISTING; }
+ bool IsLastDefinition() const { return flags & PHASE_FLAG_NO_MORE_PHASES; }
+ bool IsNegatingPhasemask() const { return flags & PHASE_FLAG_NEGATE_PHASE; }
+};
+
+typedef std::list<PhaseDefinition> PhaseDefinitionContainer;
+typedef UNORDERED_MAP<uint32 /*zoneId*/, PhaseDefinitionContainer> PhaseDefinitionStore;
+
+struct SpellPhaseInfo
+{
+ uint32 spellId;
+ uint32 phasemask;
+ uint32 terrainswapmap;
+};
+
+typedef UNORDERED_MAP<uint32 /*spellId*/, SpellPhaseInfo> SpellPhaseStore;
+
+struct PhaseInfo
+{
+ PhaseInfo() : phasemask(0), terrainswapmap(0), phaseId(0) {}
+
+ uint32 phasemask;
+ uint32 terrainswapmap;
+ uint32 phaseId;
+
+ bool NeedsServerSideUpdate() const { return phasemask; }
+ bool NeedsClientSideUpdate() const { return terrainswapmap || phaseId; }
+};
+
+typedef UNORDERED_MAP<uint32 /*spellId*/, PhaseInfo> PhaseInfoContainer;
+
+struct PhaseData
+{
+ PhaseData(Player* _player) : player(_player), _PhasemaskThroughDefinitions(0), _PhasemaskThroughAuras(0), _CustomPhasemask(0) {}
+
+ uint32 _PhasemaskThroughDefinitions;
+ uint32 _PhasemaskThroughAuras;
+ uint32 _CustomPhasemask;
+
+ uint32 GetCurrentPhasemask() const;
+ inline uint32 GetPhaseMaskForSpawn() const;
+
+ void ResetDefinitions() { _PhasemaskThroughDefinitions = 0; activePhaseDefinitions.clear(); }
+ void AddPhaseDefinition(PhaseDefinition const* phaseDefinition);
+ bool HasActiveDefinitions() const { return !activePhaseDefinitions.empty(); }
+
+ void AddAuraInfo(uint32 const spellId, PhaseInfo phaseInfo);
+ uint32 RemoveAuraInfo(uint32 const spellId);
+
+ void SendPhaseMaskToPlayer();
+ void SendPhaseshiftToPlayer();
+
+private:
+ Player* player;
+ std::list<PhaseDefinition const*> activePhaseDefinitions;
+ PhaseInfoContainer spellPhaseInfo;
+};
+
+struct PhaseUpdateData
+{
+ void AddConditionType(ConditionTypes const conditionType) { _conditionTypeFlags |= (1 << conditionType); }
+ void AddQuestUpdate(uint32 const questId);
+
+ bool IsConditionRelated(Condition const* condition) const;
+
+private:
+ uint32 _conditionTypeFlags;
+ uint32 _questId;
+};
+
+class PhaseMgr
+{
+public:
+ PhaseMgr(Player* _player);
+ ~PhaseMgr() {}
+
+ uint32 GetCurrentPhasemask() { return phaseData.GetCurrentPhasemask(); };
+ inline uint32 GetPhaseMaskForSpawn() { return phaseData.GetCurrentPhasemask(); }
+
+ // Phase definitions update handling
+ void NotifyConditionChanged(PhaseUpdateData const& updateData);
+ void NotifyStoresReloaded() { Recalculate(); Update(); }
+
+ void Update();
+
+ // Aura phase effects
+ void RegisterPhasingAuraEffect(AuraEffect const* auraEffect);
+ void UnRegisterPhasingAuraEffect(AuraEffect const* auraEffect);
+
+ // Update flags (delayed phasing)
+ void AddUpdateFlag(PhaseUpdateFlag const updateFlag) { _UpdateFlags |= updateFlag; }
+ void RemoveUpdateFlag(PhaseUpdateFlag const updateFlag);
+
+ // Needed for modify phase command
+ void SetCustomPhase(uint32 const phaseMask);
+
+ // Debug
+ void SendDebugReportToPlayer(Player* const debugger);
+
+ static bool IsConditionTypeSupported(ConditionTypes const conditionType);
+
+private:
+ void Recalculate();
+
+ inline bool CheckDefinition(PhaseDefinition const* phaseDefinition);
+
+ bool NeedsPhaseUpdateWithData(PhaseUpdateData const updateData) const;
+
+ inline bool IsUpdateInProgress() const { return (_UpdateFlags & PHASE_UPDATE_FLAG_ZONE_UPDATE) || (_UpdateFlags & PHASE_UPDATE_FLAG_AREA_UPDATE); }
+
+ PhaseDefinitionStore const* _PhaseDefinitionStore;
+ SpellPhaseStore const* _SpellPhaseStore;
+
+ Player* player;
+ PhaseData phaseData;
+ uint8 _UpdateFlags;
+};
+
+#endif
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index 5893bbd6564..c55c57481f4 100755
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -174,7 +174,15 @@ enum TrinityStrings
LANG_YOU_CHANGE_RUNIC_POWER = 173,
LANG_YOURS_RUNIC_POWER_CHANGED = 174,
LANG_LIQUID_STATUS = 175,
- // Room for more level 1 176-199 not used
+
+ LANG_PHASING_REPORT_STATUS = 176,
+ LANG_PHASING_NO_DEFINITIONS = 177, // Phasing
+ LANG_PHASING_SUCCESS = 178,
+ LANG_PHASING_FAILED = 179,
+ LANG_PHASING_LAST_PHASE = 180,
+ LANG_PHASING_LIST = 181,
+ LANG_PHASING_PHASEMASK = 182,
+ // Room for more level 1 183-199 not used
// level 2 chat
LANG_NO_SELECTION = 200,
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 5b6af4b2de8..694b2cf2d7f 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -1157,7 +1157,7 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER(SMSG_SET_FLAT_SPELL_MODIFIER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_SET_FORCED_REACTIONS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_SET_PCT_SPELL_MODIFIER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
- DEFINE_OPCODE_HANDLER(SMSG_SET_PHASE_SHIFT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_SET_PHASE_SHIFT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_SET_PLAY_HOVER_ANIM, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_SET_PROFICIENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index e6c13557076..5c61385f537 100755
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -253,7 +253,7 @@ class WorldSession
void SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName);
void SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res, uint32 val = 0);
void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2, 3);
- void SendSetPhaseShift(uint32 phaseShift);
+ void SendSetPhaseShift(std::set<uint32> const& phaseIds, std::set<uint32> const& terrainswaps);
void SendQueryTimeResponse();
void SendAuthResponse(uint8 code, bool queued, uint32 queuePos = 0);
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 28ddaf05afc..d70c68b9be2 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1808,27 +1808,21 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app
Unit* target = aurApp->GetTarget();
- // no-phase is also phase state so same code for apply and remove
- uint32 newPhase = 0;
- Unit::AuraEffectList const& phases = target->GetAuraEffectsByType(SPELL_AURA_PHASE);
- if (!phases.empty())
- for (Unit::AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
- newPhase |= (*itr)->GetMiscValue();
-
if (Player* player = target->ToPlayer())
{
- if (!newPhase)
- newPhase = PHASEMASK_NORMAL;
-
- // GM-mode have mask 0xFFFFFFFF
- if (player->isGameMaster())
- newPhase = 0xFFFFFFFF;
-
- player->SetPhaseMask(newPhase, false);
- player->GetSession()->SendSetPhaseShift(newPhase);
+ if (apply)
+ player->GetPhaseMgr().RegisterPhasingAuraEffect(this);
+ else
+ player->GetPhaseMgr().UnRegisterPhasingAuraEffect(this);
}
else
{
+ uint32 newPhase = 0;
+ Unit::AuraEffectList const& phases = target->GetAuraEffectsByType(SPELL_AURA_PHASE);
+ if (!phases.empty())
+ for (Unit::AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
+ newPhase |= (*itr)->GetMiscValue();
+
if (!newPhase)
{
newPhase = PHASEMASK_NORMAL;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index c092776bc14..04a371ba776 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -5655,7 +5655,7 @@ SpellCastResult Spell::CheckCasterAuras() const
break;
}
}
- if (foundNotStun)
+ if (foundNotStun && m_spellInfo->Id != 22812)
prevented_reason = SPELL_FAILED_STUNNED;
}
else
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index ab6c2b1df8b..eb5c26a1c71 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3514,6 +3514,10 @@ void SpellMgr::LoadDbcDataCorrections()
case 71085: // Mana Void (periodic aura)
spellInfo->DurationIndex = 9; // 30 seconds (missing)
break;
+ case 72015: // Frostbolt Volley (only heroic)
+ case 72016: // Frostbolt Volley (only heroic)
+ spellInfo->EffectRadiusIndex[2] = EFFECT_RADIUS_40_YARDS;
+ break;
case 70936: // Summon Suppressor (needs target selection script)
spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_TARGET_ANY;
spellInfo->EffectImplicitTargetB[0] = 0;
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 94961b7b930..371668e73d9 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1368,6 +1368,9 @@ void World::SetInitialWorldSettings()
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Spell Group Stack Rules...");
sSpellMgr->LoadSpellGroupStackRules();
+ sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Spell Phase Dbc Info...");
+ sObjectMgr->LoadSpellPhaseInfo();
+
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading NPC Texts...");
sObjectMgr->LoadGossipText();
@@ -1616,6 +1619,9 @@ void World::SetInitialWorldSettings()
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading World States..."); // must be loaded before battleground, outdoor PvP and conditions
LoadWorldStates();
+ sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Phase definitions...");
+ sObjectMgr->LoadPhaseDefinitions();
+
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Conditions...");
sConditionMgr->LoadConditions();
@@ -3022,3 +3028,11 @@ CharacterNameData const* World::GetCharacterNameData(uint32 guid) const
else
return NULL;
}
+
+void World::UpdatePhaseDefinitions()
+{
+ SessionMap::const_iterator itr;
+ for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
+ if (itr->second && itr->second->GetPlayer() && itr->second->GetPlayer()->IsInWorld())
+ itr->second->GetPlayer()->GetPhaseMgr().NotifyStoresReloaded();
+}
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 33ec159ec81..e1465f4897d 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -784,6 +784,8 @@ class World
uint32 GetCleaningFlags() const { return m_CleaningFlags; }
void SetCleaningFlags(uint32 flags) { m_CleaningFlags = flags; }
void ResetEventSeasonalQuests(uint16 event_id);
+
+ void UpdatePhaseDefinitions();
protected:
void _UpdateGameTime();
// callback for UpdateRealmCharacters
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index 67b4d780942..363258648f6 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -90,6 +90,7 @@ public:
{ "areatriggers", SEC_ADMINISTRATOR, false, &HandleDebugAreaTriggersCommand, "", NULL },
{ "los", SEC_MODERATOR, false, &HandleDebugLoSCommand, "", NULL },
{ "moveflags", SEC_ADMINISTRATOR, false, &HandleDebugMoveflagsCommand, "", NULL },
+ { "phase", SEC_MODERATOR, false, &HandleDebugPhaseCommand, "", NULL },
{ NULL, SEC_PLAYER, false, NULL, "", NULL }
};
static ChatCommand commandTable[] =
@@ -948,8 +949,21 @@ public:
if (!*args)
return false;
- uint32 PhaseShift = atoi(args);
- handler->GetSession()->SendSetPhaseShift(PhaseShift);
+ char* t = strtok((char*)args, " ");
+ char* p = strtok(NULL, " ");
+
+ if (!t)
+ return false;
+
+ std::set<uint32> terrainswap;
+ std::set<uint32> phaseId;
+
+ terrainswap.insert((uint32)atoi(t));
+
+ if (p)
+ phaseId.insert((uint32)atoi(p));
+
+ handler->GetSession()->SendSetPhaseShift(phaseId, terrainswap);
return true;
}
@@ -1330,6 +1344,17 @@ public:
handler->PSendSysMessage("Waypoint SQL written to SQL Developer log");
return true;
}
+
+ static bool HandleDebugPhaseCommand(ChatHandler* handler, char const* args)
+ {
+ Unit* unit = handler->getSelectedUnit();
+ Player* player = handler->GetSession()->GetPlayer();
+ if(unit && unit->GetTypeId() == TYPEID_PLAYER)
+ player = unit->ToPlayer();
+
+ player->GetPhaseMgr().SendDebugReportToPlayer(handler->GetSession()->GetPlayer());
+ return true;
+ }
};
void AddSC_debug_commandscript()
diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp
index 6803354d29b..fd24e618ef0 100644
--- a/src/server/scripts/Commands/cs_gobject.cpp
+++ b/src/server/scripts/Commands/cs_gobject.cpp
@@ -149,7 +149,7 @@ public:
GameObject* object = new GameObject;
uint32 guidLow = sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT);
- if (!object->Create(guidLow, objectInfo->entry, map, player->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
+ if (!object->Create(guidLow, objectInfo->entry, map, player->GetPhaseMgr().GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
{
delete object;
return false;
@@ -162,7 +162,7 @@ public:
}
// fill the gameobject data and save to the db
- object->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), player->GetPhaseMaskForSpawn());
+ object->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), player->GetPhaseMgr().GetPhaseMaskForSpawn());
// this will generate a new guid if the object is in an instance
if (!object->LoadGameObjectFromDB(guidLow, map))
diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp
index f527d7fb275..9f13dd00fb8 100644
--- a/src/server/scripts/Commands/cs_modify.cpp
+++ b/src/server/scripts/Commands/cs_modify.cpp
@@ -1003,15 +1003,19 @@ public:
if (handler->HasLowerSecurity(target, 0))
return false;
- int32 addmoney = atoi((char*)args);
+ int64 moneyToAdd = 0;
+ if (strchr(args, 'g') || strchr(args, 's') || strchr(args, 'c'))
+ moneyToAdd = MoneyStringToMoney(std::string(args));
+ else
+ moneyToAdd = atol(args);
- uint64 moneyuser = target->GetMoney();
+ uint64 targetMoney = target->GetMoney();
- if (addmoney < 0)
+ if (moneyToAdd < 0)
{
- int64 newmoney = int32(moneyuser) + addmoney;
+ int64 newmoney = int64(targetMoney) + moneyToAdd;
- sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_CURRENT_MONEY), moneyuser, addmoney, newmoney);
+ sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_CURRENT_MONEY), uint32(targetMoney), int32(moneyToAdd), uint32(newmoney));
if (newmoney <= 0)
{
handler->PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, handler->GetNameLink(target).c_str());
@@ -1025,25 +1029,26 @@ public:
if (newmoney > MAX_MONEY_AMOUNT)
newmoney = MAX_MONEY_AMOUNT;
- handler->PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), handler->GetNameLink(target).c_str());
+ handler->PSendSysMessage(LANG_YOU_TAKE_MONEY, uint32(abs(moneyToAdd)), handler->GetNameLink(target).c_str());
if (handler->needReportToTarget(target))
- (ChatHandler(target)).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, handler->GetNameLink().c_str(), abs(addmoney));
+ (ChatHandler(target)).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, handler->GetNameLink().c_str(), uint32(abs(moneyToAdd)));
target->SetMoney(newmoney);
}
}
else
{
- handler->PSendSysMessage(LANG_YOU_GIVE_MONEY, uint32(addmoney), handler->GetNameLink(target).c_str());
+ handler->PSendSysMessage(LANG_YOU_GIVE_MONEY, uint32(moneyToAdd), handler->GetNameLink(target).c_str());
if (handler->needReportToTarget(target))
- (ChatHandler(target)).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, handler->GetNameLink().c_str(), uint32(addmoney));
+ (ChatHandler(target)).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, handler->GetNameLink().c_str(), uint32(moneyToAdd));
- if (addmoney >=MAX_MONEY_AMOUNT)
+ if (moneyToAdd >= MAX_MONEY_AMOUNT)
target->SetMoney(MAX_MONEY_AMOUNT);
else
- target->ModifyMoney(int64(addmoney));
+ target->ModifyMoney(moneyToAdd);
}
- sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_NEW_MONEY), moneyuser, uint32(addmoney), target->GetMoney());
+ sLog->outDebug(LOG_FILTER_GENERAL, handler->GetTrinityString(LANG_NEW_MONEY), uint32(targetMoney), int32(moneyToAdd), uint32(target->GetMoney()));
+
return true;
}
@@ -1272,14 +1277,15 @@ public:
uint32 phasemask = (uint32)atoi((char*)args);
Unit* target = handler->getSelectedUnit();
- if (!target)
- target = handler->GetSession()->GetPlayer();
-
- // check online security
- else if (target->GetTypeId() == TYPEID_PLAYER && handler->HasLowerSecurity(target->ToPlayer(), 0))
- return false;
-
- target->SetPhaseMask(phasemask, true);
+ if (target)
+ {
+ if (target->GetTypeId() == TYPEID_PLAYER)
+ target->ToPlayer()->GetPhaseMgr().SetCustomPhase(phasemask);
+ else
+ target->SetPhaseMask(phasemask, true);
+ }
+ else
+ handler->GetSession()->GetPlayer()->GetPhaseMgr().SetCustomPhase(phasemask);
return true;
}
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index e43760191df..30713728cf6 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -151,13 +151,13 @@ public:
}
Creature* creature = new Creature();
- if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, (uint32)teamval, x, y, z, o))
+ if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), id, 0, (uint32)teamval, x, y, z, o))
{
delete creature;
return false;
}
- creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
+ creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr().GetPhaseMaskForSpawn());
uint32 db_guid = creature->GetDBTableGUIDLow();
diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp
index ce0141290ff..14481884ec8 100644
--- a/src/server/scripts/Commands/cs_reload.cpp
+++ b/src/server/scripts/Commands/cs_reload.cpp
@@ -115,6 +115,7 @@ public:
{ "npc_trainer", SEC_ADMINISTRATOR, true, &HandleReloadNpcTrainerCommand, "", NULL },
{ "npc_vendor", SEC_ADMINISTRATOR, true, &HandleReloadNpcVendorCommand, "", NULL },
{ "page_text", SEC_ADMINISTRATOR, true, &HandleReloadPageTextsCommand, "", NULL },
+ { "phasedefinitions", SEC_ADMINISTRATOR, true, &HandleReloadPhaseDefinitionsCommand, "", NULL },
{ "pickpocketing_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesPickpocketingCommand, "", NULL},
{ "points_of_interest", SEC_ADMINISTRATOR, true, &HandleReloadPointsOfInterestCommand, "", NULL },
{ "prospecting_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesProspectingCommand, "", NULL },
@@ -1250,6 +1251,15 @@ public:
handler->SendGlobalGMSysMessage("Vehicle template accessories reloaded.");
return true;
}
+
+ static bool HandleReloadPhaseDefinitionsCommand(ChatHandler* handler, const char* /*args*/)
+ {
+ sLog->outInfo(LOG_FILTER_GENERAL, "Reloading phase_definitions table...");
+ sObjectMgr->LoadPhaseDefinitions();
+ sWorld->UpdatePhaseDefinitions();
+ handler->SendGlobalGMSysMessage("Phase Definitions reloaded.");
+ return true;
+ }
};
void AddSC_reload_commandscript()
diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp
index e3cd185e4a3..05226fb55aa 100644
--- a/src/server/scripts/Commands/cs_wp.cpp
+++ b/src/server/scripts/Commands/cs_wp.cpp
@@ -688,7 +688,7 @@ public:
}
// re-create
Creature* wpCreature2 = new Creature;
- if (!wpCreature2->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation()))
+ if (!wpCreature2->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation()))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
delete wpCreature2;
@@ -696,7 +696,7 @@ public:
return false;
}
- wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
+ wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr().GetPhaseMaskForSpawn());
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
//TODO: Should we first use "Create" then use "LoadFromDB"?
if (!wpCreature2->LoadCreatureFromDB(wpCreature2->GetDBTableGUIDLow(), map))
@@ -912,7 +912,7 @@ public:
float o = chr->GetOrientation();
Creature* wpCreature = new Creature;
- if (!wpCreature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
+ if (!wpCreature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete wpCreature;
@@ -928,7 +928,7 @@ public:
WorldDatabase.Execute(stmt);
- wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
+ wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr().GetPhaseMaskForSpawn());
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
if (!wpCreature->LoadCreatureFromDB(wpCreature->GetDBTableGUIDLow(), map))
{
@@ -976,14 +976,14 @@ public:
Map* map = chr->GetMap();
Creature* creature = new Creature;
- if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
+ if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
delete creature;
return false;
}
- creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
+ creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr().GetPhaseMaskForSpawn());
if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map))
{
handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
@@ -1025,14 +1025,14 @@ public:
Map* map = chr->GetMap();
Creature* creature = new Creature;
- if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
+ if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o))
{
handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
delete creature;
return false;
}
- creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
+ creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr().GetPhaseMaskForSpawn());
if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map))
{
handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp
index 0508d95a60b..ef810b50b6f 100644
--- a/src/server/scripts/Spells/spell_item.cpp
+++ b/src/server/scripts/Spells/spell_item.cpp
@@ -1844,7 +1844,7 @@ class spell_item_unusual_compass : public SpellScriptLoader
{
Unit* caster = GetCaster();
caster->SetOrientation(frand(0.0f, 62832.0f) / 10000.0f);
- caster->SendMovementFlagUpdate();
+ caster->SendMovementFlagUpdate(true);
}
void Register()
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index 23f09a88911..8b1fe6f38ba 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -31,7 +31,7 @@ enum ShamanSpells
{
SHAMAN_SPELL_GLYPH_OF_MANA_TIDE = 55441,
SHAMAN_SPELL_MANA_TIDE_TOTEM = 39609,
- SHAMAN_SPELL_FIRE_NOVA_R1 = 1535,
+ SHAMAN_SPELL_FLAME_SHOCK = 8050,
SHAMAN_SPELL_FIRE_NOVA_TRIGGERED_R1 = 8349,
SHAMAN_SPELL_SATED = 57724,
SHAMAN_SPELL_EXHAUSTION = 57723,
@@ -52,51 +52,8 @@ enum ShamanSpells
SHAMAN_LAVA_FLOWS_TRIGGERED_R1 = 64694,
};
-// 51474 - Astral shift
-class spell_sha_astral_shift : public SpellScriptLoader
-{
- public:
- spell_sha_astral_shift() : SpellScriptLoader("spell_sha_astral_shift") { }
-
- class spell_sha_astral_shift_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_sha_astral_shift_AuraScript);
-
- uint32 absorbPct;
-
- bool Load()
- {
- absorbPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster());
- return true;
- }
-
- void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/)
- {
- // Set absorbtion amount to unlimited
- amount = -1;
- }
-
- void Absorb(AuraEffect* /*aurEff*/, DamageInfo & dmgInfo, uint32 & absorbAmount)
- {
- // reduces all damage taken while stun, fear or silence
- if (GetTarget()->GetUInt32Value(UNIT_FIELD_FLAGS) & (UNIT_FLAG_FLEEING | UNIT_FLAG_SILENCED) || (GetTarget()->GetUInt32Value(UNIT_FIELD_FLAGS) & (UNIT_FLAG_STUNNED) && GetTarget()->HasAuraWithMechanic(1<<MECHANIC_STUN)))
- absorbAmount = CalculatePct(dmgInfo.GetDamage(), absorbPct);
- }
-
- void Register()
- {
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_sha_astral_shift_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
- OnEffectAbsorb += AuraEffectAbsorbFn(spell_sha_astral_shift_AuraScript::Absorb, EFFECT_0);
- }
- };
-
- AuraScript* GetAuraScript() const
- {
- return new spell_sha_astral_shift_AuraScript();
- }
-};
-
// 1535 Fire Nova
+/// Updated 4.3.4
class spell_sha_fire_nova : public SpellScriptLoader
{
public:
@@ -106,46 +63,21 @@ class spell_sha_fire_nova : public SpellScriptLoader
{
PrepareSpellScript(spell_sha_fire_nova_SpellScript);
- bool Validate(SpellInfo const* spellEntry)
- {
- if (!sSpellMgr->GetSpellInfo(SHAMAN_SPELL_FIRE_NOVA_R1) || sSpellMgr->GetFirstSpellInChain(SHAMAN_SPELL_FIRE_NOVA_R1) != sSpellMgr->GetFirstSpellInChain(spellEntry->Id))
- return false;
-
- uint8 rank = sSpellMgr->GetSpellRank(spellEntry->Id);
- if (!sSpellMgr->GetSpellWithRank(SHAMAN_SPELL_FIRE_NOVA_TRIGGERED_R1, rank, true))
- return false;
- return true;
- }
-
- SpellCastResult CheckFireTotem()
- {
- // fire totem
- if (!GetCaster()->m_SummonSlot[1])
- {
- SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_MUST_HAVE_FIRE_TOTEM);
- return SPELL_FAILED_CUSTOM_ERROR;
- }
-
- return SPELL_CAST_OK;
- }
-
void HandleDummy(SpellEffIndex /*effIndex*/)
{
- if (Unit* caster = GetCaster())
+ Unit* caster = GetCaster();
+ if (Unit* target = GetHitUnit())
{
- uint8 rank = sSpellMgr->GetSpellRank(GetSpellInfo()->Id);
- if (uint32 spellId = sSpellMgr->GetSpellWithRank(SHAMAN_SPELL_FIRE_NOVA_TRIGGERED_R1, rank))
+ if (target->HasAura(SHAMAN_SPELL_FLAME_SHOCK))
{
- Creature* totem = caster->GetMap()->GetCreature(caster->m_SummonSlot[1]);
- if (totem && totem->isTotem())
- caster->CastSpell(totem, spellId, true);
+ caster->CastSpell(target, SHAMAN_SPELL_FIRE_NOVA_TRIGGERED_R1, true);
+ target->RemoveAurasDueToSpell(SHAMAN_SPELL_FLAME_SHOCK);
}
}
}
void Register()
{
- OnCheckCast += SpellCheckCastFn(spell_sha_fire_nova_SpellScript::CheckFireTotem);
OnEffectHitTarget += SpellEffectFn(spell_sha_fire_nova_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
@@ -757,7 +689,6 @@ class spell_sha_sentry_totem : public SpellScriptLoader
void AddSC_shaman_spell_scripts()
{
- new spell_sha_astral_shift();
new spell_sha_fire_nova();
new spell_sha_mana_tide_totem();
new spell_sha_earthbind_totem();
diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp
index e7cca8fed36..42296154634 100644
--- a/src/server/scripts/Spells/spell_warlock.cpp
+++ b/src/server/scripts/Spells/spell_warlock.cpp
@@ -40,11 +40,16 @@ enum WarlockSpells
WARLOCK_HAUNT = 48181,
WARLOCK_HAUNT_HEAL = 48210,
WARLOCK_UNSTABLE_AFFLICTION_DISPEL = 31117,
- WARLOCK_CURSE_OF_DOOM_EFFECT = 18662,
+ WARLOCK_BANE_OF_DOOM_EFFECT = 18662,
WARLOCK_IMPROVED_HEALTH_FUNNEL_R1 = 18703,
WARLOCK_IMPROVED_HEALTH_FUNNEL_R2 = 18704,
WARLOCK_IMPROVED_HEALTH_FUNNEL_BUFF_R1 = 60955,
WARLOCK_IMPROVED_HEALTH_FUNNEL_BUFF_R2 = 60956,
+ WARLOCK_SOULSHATTER = 32835,
+ WARLOCK_LIFE_TAP_ENERGIZE = 31818,
+ WARLOCK_LIFE_TAP_ENERGIZE_2 = 32553,
+ WARLOCK_IMPROVED_LIFE_TAP_ICON_ID = 208,
+ WARLOCK_MANA_FEED_ICON_ID = 1982,
};
/// Updated 4.3.4
@@ -244,6 +249,7 @@ uint32 const spell_warl_create_healthstone::spell_warl_create_healthstone_SpellS
};
// 47422 Everlasting Affliction
+/// Updated 4.3.4
class spell_warl_everlasting_affliction : public SpellScriptLoader
{
public:
@@ -273,6 +279,8 @@ class spell_warl_everlasting_affliction : public SpellScriptLoader
}
};
+// 27285 Seed of Corruption
+/// Updated 4.3.4
class spell_warl_seed_of_corruption : public SpellScriptLoader
{
public:
@@ -300,11 +308,8 @@ class spell_warl_seed_of_corruption : public SpellScriptLoader
}
};
-enum Soulshatter
-{
- SPELL_SOULSHATTER = 32835,
-};
-
+// 29858 Soulshatter
+/// Updated 4.3.4
class spell_warl_soulshatter : public SpellScriptLoader
{
public:
@@ -316,7 +321,7 @@ class spell_warl_soulshatter : public SpellScriptLoader
bool Validate(SpellInfo const* /*spell*/)
{
- if (!sSpellMgr->GetSpellInfo(SPELL_SOULSHATTER))
+ if (!sSpellMgr->GetSpellInfo(WARLOCK_SOULSHATTER))
return false;
return true;
}
@@ -325,10 +330,8 @@ class spell_warl_soulshatter : public SpellScriptLoader
{
Unit* caster = GetCaster();
if (Unit* target = GetHitUnit())
- {
if (target->CanHaveThreatList() && target->getThreatManager().getThreat(caster) > 0.0f)
- caster->CastSpell(target, SPELL_SOULSHATTER, true);
- }
+ caster->CastSpell(target, WARLOCK_SOULSHATTER, true);
}
void Register()
@@ -343,14 +346,8 @@ class spell_warl_soulshatter : public SpellScriptLoader
}
};
-enum LifeTap
-{
- SPELL_LIFE_TAP_ENERGIZE = 31818,
- SPELL_LIFE_TAP_ENERGIZE_2 = 32553,
- ICON_ID_IMPROVED_LIFE_TAP = 208,
- ICON_ID_MANA_FEED = 1982,
-};
-
+// 1454 Life Tap
+/// Updated 4.3.4
class spell_warl_life_tap : public SpellScriptLoader
{
public:
@@ -367,7 +364,7 @@ class spell_warl_life_tap : public SpellScriptLoader
bool Validate(SpellInfo const* /*spell*/)
{
- if (!sSpellMgr->GetSpellInfo(SPELL_LIFE_TAP_ENERGIZE) || !sSpellMgr->GetSpellInfo(SPELL_LIFE_TAP_ENERGIZE_2))
+ if (!sSpellMgr->GetSpellInfo(WARLOCK_LIFE_TAP_ENERGIZE) || !sSpellMgr->GetSpellInfo(WARLOCK_LIFE_TAP_ENERGIZE_2))
return false;
return true;
}
@@ -377,34 +374,31 @@ class spell_warl_life_tap : public SpellScriptLoader
Player* caster = GetCaster()->ToPlayer();
if (Unit* target = GetHitUnit())
{
- int32 damage = GetEffectValue();
- int32 mana = int32(damage + (caster->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+SPELL_SCHOOL_SHADOW) * 0.5f));
+ int32 damage = caster->CountPctFromMaxHealth(GetSpellInfo()->Effects[EFFECT_2].CalcValue());
+ int32 mana = CalculatePct(damage, GetSpellInfo()->Effects[EFFECT_1].CalcValue());
// Shouldn't Appear in Combat Log
target->ModifyHealth(-damage);
// Improved Life Tap mod
- if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_WARLOCK, ICON_ID_IMPROVED_LIFE_TAP, 0))
+ if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_WARLOCK, WARLOCK_IMPROVED_LIFE_TAP_ICON_ID, 0))
AddPct(mana, aurEff->GetAmount());
- caster->CastCustomSpell(target, SPELL_LIFE_TAP_ENERGIZE, &mana, NULL, NULL, false);
+ caster->CastCustomSpell(target, WARLOCK_LIFE_TAP_ENERGIZE, &mana, NULL, NULL, false);
// Mana Feed
- int32 manaFeedVal = 0;
- if (AuraEffect const* aurEff = caster->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_WARLOCK, ICON_ID_MANA_FEED, 0))
- manaFeedVal = aurEff->GetAmount();
-
- if (manaFeedVal > 0)
+ if (AuraEffect const* aurEff = caster->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_WARLOCK, WARLOCK_MANA_FEED_ICON_ID, 0))
{
+ int32 manaFeedVal = aurEff->GetAmount();
ApplyPct(manaFeedVal, mana);
- caster->CastCustomSpell(caster, SPELL_LIFE_TAP_ENERGIZE_2, &manaFeedVal, NULL, NULL, true, NULL);
+ caster->CastCustomSpell(caster, WARLOCK_LIFE_TAP_ENERGIZE_2, &manaFeedVal, NULL, NULL, true, NULL);
}
}
}
SpellCastResult CheckCast()
{
- if ((int32(GetCaster()->GetHealth()) > int32(GetSpellInfo()->Effects[EFFECT_0].CalcValue() + (6.3875 * GetSpellInfo()->BaseLevel))))
+ if (int32(GetCaster()->GetHealth()) > int32(GetCaster()->CountPctFromMaxHealth(GetSpellInfo()->Effects[EFFECT_2].CalcValue())))
return SPELL_CAST_OK;
return SPELL_FAILED_FIZZLE;
}
@@ -422,6 +416,8 @@ class spell_warl_life_tap : public SpellScriptLoader
}
};
+// 48018 Demonic Circle: Summon
+/// Updated 4.3.4
class spell_warl_demonic_circle_summon : public SpellScriptLoader
{
public:
@@ -473,6 +469,8 @@ class spell_warl_demonic_circle_summon : public SpellScriptLoader
}
};
+// 48020 Demonic Circle: Teleport
+/// Updated 4.3.4
class spell_warl_demonic_circle_teleport : public SpellScriptLoader
{
public:
@@ -506,6 +504,8 @@ class spell_warl_demonic_circle_teleport : public SpellScriptLoader
}
};
+// 48181 Haunt
+/// Updated 4.3.4
class spell_warl_haunt : public SpellScriptLoader
{
public:
@@ -565,6 +565,7 @@ class spell_warl_haunt : public SpellScriptLoader
}
};
+/// Updated 4.3.4
class spell_warl_unstable_affliction : public SpellScriptLoader
{
public:
@@ -604,10 +605,12 @@ class spell_warl_unstable_affliction : public SpellScriptLoader
}
};
-class spell_warl_curse_of_doom : public SpellScriptLoader
+// 603 Bane of Doom
+/// Updated 4.3.4
+class spell_warl_bane_of_doom : public SpellScriptLoader
{
public:
- spell_warl_curse_of_doom() : SpellScriptLoader("spell_warl_curse_of_doom") { }
+ spell_warl_bane_of_doom() : SpellScriptLoader("spell_warl_bane_of_doom") { }
class spell_warl_curse_of_doom_AuraScript : public AuraScript
{
@@ -615,7 +618,7 @@ class spell_warl_curse_of_doom : public SpellScriptLoader
bool Validate(SpellInfo const* /*spell*/)
{
- if (!sSpellMgr->GetSpellInfo(WARLOCK_CURSE_OF_DOOM_EFFECT))
+ if (!sSpellMgr->GetSpellInfo(WARLOCK_BANE_OF_DOOM_EFFECT))
return false;
return true;
}
@@ -635,7 +638,7 @@ class spell_warl_curse_of_doom : public SpellScriptLoader
return;
if (GetCaster()->ToPlayer()->isHonorOrXPTarget(GetTarget()))
- GetCaster()->CastSpell(GetTarget(), WARLOCK_CURSE_OF_DOOM_EFFECT, true, NULL, aurEff);
+ GetCaster()->CastSpell(GetTarget(), WARLOCK_BANE_OF_DOOM_EFFECT, true, NULL, aurEff);
}
void Register()
@@ -650,6 +653,8 @@ class spell_warl_curse_of_doom : public SpellScriptLoader
}
};
+// 755 Health Funnel
+/// Updated 4.3.4
class spell_warl_health_funnel : public SpellScriptLoader
{
public:
@@ -705,6 +710,6 @@ void AddSC_warlock_spell_scripts()
new spell_warl_demonic_circle_teleport();
new spell_warl_haunt();
new spell_warl_unstable_affliction();
- new spell_warl_curse_of_doom();
+ new spell_warl_bane_of_doom();
new spell_warl_health_funnel();
}
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index 3e3e18b1c80..f689d2f29ac 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -2121,8 +2121,6 @@ class npc_shadowfiend : public CreatureScript
if (Unit* owner = me->ToTempSummon()->GetSummoner())
if (owner->HasAura(GLYPH_OF_SHADOWFIEND))
owner->CastSpell(owner, GLYPH_OF_SHADOWFIEND_MANA, true);
-
- PetAI::JustDied(killer);
}
};
diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp
index 0897c8814ab..b3176beb50b 100755
--- a/src/server/shared/Utilities/Util.cpp
+++ b/src/server/shared/Utilities/Util.cpp
@@ -150,6 +150,37 @@ std::string secsToTimeString(uint64 timeInSecs, bool shortText, bool hoursOnly)
return ss.str();
}
+int64 MoneyStringToMoney(const std::string& moneyString)
+{
+ int64 money = 0;
+
+ if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 ||
+ std::count(moneyString.begin(), moneyString.end(), 's') == 1 ||
+ std::count(moneyString.begin(), moneyString.end(), 'c') == 1))
+ return 0; // Bad format
+
+ Tokenizer tokens(moneyString, ' ');
+ for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr)
+ {
+ std::string tokenString(*itr);
+ uint32 gCount = std::count(tokenString.begin(), tokenString.end(), 'g');
+ uint32 sCount = std::count(tokenString.begin(), tokenString.end(), 's');
+ uint32 cCount = std::count(tokenString.begin(), tokenString.end(), 'c');
+ if (gCount + sCount + cCount != 1)
+ return 0;
+
+ uint64 amount = atol(*itr);
+ if (gCount == 1)
+ money += amount * 100 * 100;
+ else if (sCount == 1)
+ money += amount * 100;
+ else if (cCount == 1)
+ money += amount;
+ }
+
+ return money;
+}
+
uint32 TimeStringToSecs(const std::string& timestring)
{
uint32 secs = 0;
diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h
index f84e5155bb1..949fa67008f 100755
--- a/src/server/shared/Utilities/Util.h
+++ b/src/server/shared/Utilities/Util.h
@@ -66,6 +66,8 @@ private:
void stripLineInvisibleChars(std::string &src);
+int64 MoneyStringToMoney(const std::string& moneyString);
+
std::string secsToTimeString(uint64 timeInSecs, bool shortText = false, bool hoursOnly = false);
uint32 TimeStringToSecs(const std::string& timestring);
std::string TimeToTimestampStr(time_t t);