aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bindings/scripts/scripts/npc/npcs_special.cpp2
-rw-r--r--src/game/AchievementMgr.cpp39
-rw-r--r--src/game/BattleGroundMgr.cpp2
-rw-r--r--src/game/Chat.cpp1
-rw-r--r--src/game/Chat.h1
-rw-r--r--src/game/ChatHandler.cpp64
-rw-r--r--src/game/Creature.cpp42
-rw-r--r--src/game/Creature.h7
-rw-r--r--src/game/CreatureAI.cpp6
-rw-r--r--src/game/CreatureAI.h8
-rw-r--r--src/game/GameEvent.cpp1615
-rw-r--r--src/game/GameEvent.h166
-rw-r--r--src/game/GridNotifiersImpl.h6
-rw-r--r--src/game/Level2.cpp30
-rw-r--r--src/game/Level3.cpp8
-rw-r--r--src/game/LootMgr.cpp15
-rw-r--r--src/game/LootMgr.h8
-rw-r--r--src/game/Makefile.am4
-rw-r--r--src/game/Map.h5
-rw-r--r--src/game/MapManager.cpp14
-rw-r--r--src/game/MiscHandler.cpp56
-rw-r--r--src/game/Object.cpp2
-rw-r--r--src/game/ObjectMgr.cpp168
-rw-r--r--src/game/ObjectMgr.h22
-rw-r--r--src/game/OutdoorPvP.cpp2
-rw-r--r--src/game/Pet.cpp10
-rw-r--r--src/game/PetAI.cpp3
-rw-r--r--src/game/PetHandler.cpp7
-rw-r--r--src/game/Player.cpp75
-rw-r--r--src/game/Player.h16
-rw-r--r--src/game/SharedDefines.h25
-rw-r--r--src/game/Spell.cpp10
-rw-r--r--src/game/SpellEffects.cpp10
-rw-r--r--src/game/TemporarySummon.cpp2
-rw-r--r--src/game/Unit.cpp66
-rw-r--r--src/game/Unit.h18
-rw-r--r--src/game/World.cpp7
-rw-r--r--src/shared/Database/DBCStores.cpp4
-rw-r--r--src/shared/Database/DBCStores.h1
-rw-r--r--src/shared/Database/DBCStructure.h37
-rw-r--r--src/shared/Database/DBCfmt.cpp1
-rw-r--r--src/shared/Database/SQLStorage.cpp4
-rw-r--r--src/shared/revision_nr.h2
43 files changed, 507 insertions, 2084 deletions
diff --git a/src/bindings/scripts/scripts/npc/npcs_special.cpp b/src/bindings/scripts/scripts/npc/npcs_special.cpp
index 07556ce46f4..be1986f3169 100644
--- a/src/bindings/scripts/scripts/npc/npcs_special.cpp
+++ b/src/bindings/scripts/scripts/npc/npcs_special.cpp
@@ -901,7 +901,7 @@ struct TRINITY_DLL_DECL npc_steam_tonkAI : public ScriptedAI
if (apply)
{
// Initialize the action bar without the melee attack command
- m_creature->InitCharmInfo(m_creature);
+ m_creature->InitCharmInfo();
m_creature->GetCharmInfo()->InitEmptyActionBar(false);
m_creature->SetReactState(REACT_PASSIVE);
diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp
index b06a2f1c758..6048c8ea78d 100644
--- a/src/game/AchievementMgr.cpp
+++ b/src/game/AchievementMgr.cpp
@@ -21,10 +21,10 @@
#include "Player.h"
#include "WorldPacket.h"
#include "Database/DBCEnums.h"
+#include "GameEventMgr.h"
#include "ObjectMgr.h"
#include "Guild.h"
#include "Database/DatabaseEnv.h"
-#include "GameEvent.h"
#include "World.h"
#include "SpellMgr.h"
#include "ArenaTeam.h"
@@ -606,8 +606,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
{
if(Player::GetDrunkenstateByValue(GetPlayer()->GetDrunkValue()) != DRUNKEN_SMASHED)
continue;
- // TODO: hardcoding eventid is bad, it can differ from DB to DB - maye implement something using HolidayNames.dbc?
- if(!gameeventmgr.IsActiveEvent(26))
+ if(!IsHolidayActive(HOLIDAY_BREWFEST))
continue;
}
// miscvalue1 is the ingame fallheight*100 as stored in dbc
@@ -730,6 +729,31 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
}
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
+ {
+ // miscvalue1 = emote
+ // miscvalue2 = achievement->ID for special requirement
+ if(!miscvalue1)
+ continue;
+ if(miscvalue1 != achievementCriteria->do_emote.emoteID)
+ continue;
+ if(achievementCriteria->do_emote.count)
+ {
+ // harcoded case
+ if(achievement->ID==247)
+ {
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER ||
+ unit->isAlive() || ((Player*)unit)->GetDeathTimer() == 0)
+ continue;
+ }
+ // expected as scripted case
+ else if(!miscvalue2 || !achievement->ID != miscvalue2)
+ continue;
+ }
+
+ SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
+ break;
+ }
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
{
uint32 spellCount = 0;
@@ -798,7 +822,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
- case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
@@ -927,6 +950,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
return progress->counter >= achievementCriteria->roll_greed_on_loot.count;
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
+ return progress->counter >= achievementCriteria->do_emote.count;
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
@@ -1024,8 +1049,12 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
newValue = changeValue;
break;
case PROGRESS_ACCUMULATE:
- newValue = progress->counter + changeValue;
+ {
+ // avoid overflow
+ uint32 max_value = std::numeric_limits<uint32>::max();
+ newValue = max_value - progress->counter > changeValue ? progress->counter + changeValue : max_value;
break;
+ }
case PROGRESS_HIGHEST:
newValue = progress->counter < changeValue ? changeValue : progress->counter;
break;
diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp
index a13a4e6de0b..06bdbf54c3f 100644
--- a/src/game/BattleGroundMgr.cpp
+++ b/src/game/BattleGroundMgr.cpp
@@ -1754,7 +1754,7 @@ void BattleGroundMgr::DistributeArenaPoints()
for (std::map<uint32, uint32>::iterator plr_itr = PlayerPoints.begin(); plr_itr != PlayerPoints.end(); ++plr_itr)
{
//update to database
- CharacterDatabase.PExecute("UPDATE characters SET arena_pending_points = '%u' WHERE `guid` = '%u'", plr_itr->second, plr_itr->first);
+ CharacterDatabase.PExecute("UPDATE characters SET arena_pending_points = '%u' WHERE guid = '%u'", plr_itr->second, plr_itr->first);
//add points if player is online
Player* pl = objmgr.GetPlayer(plr_itr->first);
if (pl)
diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp
index f30d4f76751..e894dc3e12f 100644
--- a/src/game/Chat.cpp
+++ b/src/game/Chat.cpp
@@ -271,6 +271,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "areatrigger_tavern", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTavernCommand, "", NULL },
{ "areatrigger_teleport", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTeleportCommand, "", NULL },
+ { "access_requirement", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAccessRequirementCommand, "", NULL },
{ "areatrigger_involvedrelation",SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestAreaTriggersCommand, "", NULL },
{ "event_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventScriptsCommand, "", NULL },
{ "command", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCommandCommand, "", NULL },
diff --git a/src/game/Chat.h b/src/game/Chat.h
index ebdd0c39726..21795671a35 100644
--- a/src/game/Chat.h
+++ b/src/game/Chat.h
@@ -225,6 +225,7 @@ class ChatHandler
bool HandleReloadWpScriptsCommand(const char* args);
bool HandleReloadAreaTriggerTavernCommand(const char* args);
bool HandleReloadAreaTriggerTeleportCommand(const char* args);
+ bool HandleReloadAccessRequirementCommand(const char* args);
bool HandleReloadEventScriptsCommand(const char* args);
bool HandleReloadCommandCommand(const char* args);
bool HandleReloadCreatureQuestRelationsCommand(const char* args);
diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp
index 97b980eea61..92489f8f510 100644
--- a/src/game/ChatHandler.cpp
+++ b/src/game/ChatHandler.cpp
@@ -524,44 +524,42 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
}
EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote);
- if (em)
- {
- uint32 emote_anim = em->textid;
+ if (!em)
+ return;
- WorldPacket data;
+ GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);
- switch(emote_anim)
- {
- case EMOTE_STATE_SLEEP:
- case EMOTE_STATE_SIT:
- case EMOTE_STATE_KNEEL:
- case EMOTE_ONESHOT_NONE:
- break;
- default:
- GetPlayer()->HandleEmoteCommand(emote_anim);
- break;
- }
+ uint32 emote_anim = em->textid;
- data.Initialize(SMSG_TEXT_EMOTE, (20+namlen));
- data << GetPlayer()->GetGUID();
- data << (uint32)text_emote;
- data << emoteNum;
- data << (uint32)namlen;
- if( namlen > 1 )
- {
- data.append(nam, namlen);
- }
- else
- {
- data << (uint8)0x00;
- }
-
- GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true);
+ WorldPacket data;
- //Send scripted event call
- if (pCreature && Script)
- Script->ReceiveEmote(GetPlayer(),pCreature,text_emote);
+ switch(emote_anim)
+ {
+ case EMOTE_STATE_SLEEP:
+ case EMOTE_STATE_SIT:
+ case EMOTE_STATE_KNEEL:
+ case EMOTE_ONESHOT_NONE:
+ break;
+ default:
+ GetPlayer()->HandleEmoteCommand(emote_anim);
+ break;
}
+
+ data.Initialize(SMSG_TEXT_EMOTE, (20+namlen));
+ data << GetPlayer()->GetGUID();
+ data << (uint32)text_emote;
+ data << emoteNum;
+ data << (uint32)namlen;
+ if( namlen > 1 )
+ data.append(nam, namlen);
+ else
+ data << (uint8)0x00;
+
+ GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true);
+
+ //Send scripted event call
+ if (pCreature && Script)
+ Script->ReceiveEmote(GetPlayer(),pCreature,text_emote);
}
void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data )
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 09e29591e66..0f1b0dd0efc 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -46,7 +46,7 @@
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "OutdoorPvPMgr.h"
-#include "GameEvent.h"
+#include "GameEventMgr.h"
#include "PossessedAI.h"
#include "CreatureGroups.h"
// apply implementation of the singletons
@@ -126,7 +126,7 @@ bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{
assistant->SetNoCallAssistance(true);
assistant->CombatStart(victim);
- if(assistant->AI())
+ if(assistant->IsAIEnabled)
assistant->AI()->AttackStart(victim);
}
}
@@ -135,7 +135,7 @@ bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
}
Creature::Creature() :
-Unit(), i_AI(NULL), i_AI_possessed(NULL),
+Unit(), i_AI(NULL),
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0),
m_lootMoney(0), m_lootRecipient(0),
m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
@@ -164,12 +164,6 @@ Creature::~Creature()
delete i_AI;
i_AI = NULL;
-
- if (i_AI_possessed)
- {
- delete i_AI_possessed;
- i_AI_possessed = NULL;
- }
}
void Creature::AddToWorld()
@@ -486,7 +480,7 @@ void Creature::Update(uint32 diff)
if(!isAlive())
break;
- if(!IsInEvadeMode() && m_AI_enabled)
+ if(!IsInEvadeMode() && IsAIEnabled)
{
// do not allow the AI to be changed during update
m_AI_locked = true;
@@ -603,36 +597,10 @@ bool Creature::AIM_Initialize(CreatureAI* ai)
i_AI = ai ? ai : FactorySelector::selectAI(this);
if (oldAI)
delete oldAI;
- m_AI_enabled = true;
+ IsAIEnabled = true;
return true;
}
-void Creature::InitPossessedAI()
-{
- if (!isPossessed()) return;
-
- if (!i_AI_possessed)
- i_AI_possessed = new PossessedAI(this);
-
- // Signal the old AI that it's been disabled
- i_AI->OnPossess(true);
-
- if(!(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_CHARM_AI))
- m_AI_enabled = false;
-}
-
-void Creature::DisablePossessedAI()
-{
- if (!i_AI_possessed) return;
-
- delete i_AI_possessed;
-
- // Signal the old AI that it's been re-enabled
- i_AI->OnPossess(false);
-
- m_AI_enabled = true;
-}
-
bool Creature::Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 team, const CreatureData *data)
{
SetMapId(map->GetId());
diff --git a/src/game/Creature.h b/src/game/Creature.h
index def2eebb2ae..8c448432cbe 100644
--- a/src/game/Creature.h
+++ b/src/game/Creature.h
@@ -132,7 +132,7 @@ enum CreatureFlagsExtra
CREATURE_FLAG_EXTRA_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP
CREATURE_FLAG_EXTRA_TRIGGER = 0x00000080, // trigger creature
CREATURE_FLAG_EXTRA_WORLDEVENT = 0x00004000, // custom flag for world event creatures (left room for merging)
- CREATURE_FLAG_EXTRA_CHARM_AI = 0x00008000, // use ai when charmed
+ //CREATURE_FLAG_EXTRA_CHARM_AI = 0x00008000, // use ai when charmed
CREATURE_FLAG_EXTRA_NO_TAUNT = 0x00010000, // cannot be taunted
};
@@ -417,7 +417,6 @@ typedef std::map<uint32,time_t> CreatureSpellCooldowns;
class TRINITY_DLL_SPEC Creature : public Unit
{
CreatureAI *i_AI;
- CreatureAI *i_AI_possessed;
public:
@@ -483,11 +482,9 @@ class TRINITY_DLL_SPEC Creature : public Unit
bool IsInEvadeMode() const;
bool AIM_Initialize(CreatureAI* ai = NULL);
- void InitPossessedAI();
- void DisablePossessedAI();
void AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type);
- CreatureAI* AI() { return isPossessed() && i_AI_possessed ? i_AI_possessed : i_AI; }
+ CreatureAI* AI() { return i_AI; }
uint32 GetShieldBlockValue() const //dunno mob block value
{
diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp
index 880522c20d2..06b2d382d8f 100644
--- a/src/game/CreatureAI.cpp
+++ b/src/game/CreatureAI.cpp
@@ -36,6 +36,12 @@ void UnitAI::AttackStart(Unit *victim)
}
}
+//Enable PlayerAI when charmed
+void PlayerAI::OnCharmed(bool apply) { me->IsAIEnabled = apply; }
+
+//Disable CreatureAI when charmed
+void CreatureAI::OnCharmed(bool apply) { me->IsAIEnabled = !apply; }
+
void CreatureAI::MoveInLineOfSight(Unit *who)
{
if(!me->getVictim() && me->canStartAttack(who))
diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h
index 6e291e2a604..78d856416ff 100644
--- a/src/game/CreatureAI.h
+++ b/src/game/CreatureAI.h
@@ -78,6 +78,9 @@ class TRINITY_DLL_SPEC UnitAI
UnitAI(Unit *u) : me(u) {}
virtual void AttackStart(Unit *);
virtual void UpdateAI(const uint32 diff) = 0;
+
+ // Called when unit is charmed
+ virtual void OnCharmed(bool apply) = 0;
};
class TRINITY_DLL_SPEC PlayerAI : public UnitAI
@@ -86,6 +89,8 @@ class TRINITY_DLL_SPEC PlayerAI : public UnitAI
Player *me;
public:
PlayerAI(Player *p) : UnitAI((Unit*)p), me(p) {}
+
+ void OnCharmed(bool apply);
};
class TRINITY_DLL_SPEC SimpleCharmedAI : public PlayerAI
@@ -140,8 +145,7 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI
// Called at waypoint reached or point movement finished
virtual void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) {}
- // Called when AI is temporarily replaced or put back when possess is applied or removed
- virtual void OnPossess(bool apply) {}
+ void OnCharmed(bool apply);
// Called at reaching home after evade
virtual void JustReachedHome() {}
diff --git a/src/game/GameEvent.cpp b/src/game/GameEvent.cpp
deleted file mode 100644
index 278ddbf0cf9..00000000000
--- a/src/game/GameEvent.cpp
+++ /dev/null
@@ -1,1615 +0,0 @@
-/*
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * Copyright (C) 2008-2009 Trinity <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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "GameEvent.h"
-#include "World.h"
-#include "ObjectMgr.h"
-#include "PoolHandler.h"
-#include "ProgressBar.h"
-#include "Language.h"
-#include "Log.h"
-#include "MapManager.h"
-#include "Policies/SingletonImp.h"
-#include "GossipDef.h"
-#include "Player.h"
-#include "BattleGroundMgr.h"
-
-INSTANTIATE_SINGLETON_1(GameEvent);
-
-bool GameEvent::CheckOneGameEvent(uint16 entry) const
-{
- time_t currenttime = time(NULL);
- // if the state is conditions or nextphase, then the event should be active
- if (mGameEvent[entry].state == GAMEEVENT_WORLD_CONDITIONS || mGameEvent[entry].state == GAMEEVENT_WORLD_NEXTPHASE)
- return true;
- // finished world events are inactive
- else if (mGameEvent[entry].state == GAMEEVENT_WORLD_FINISHED)
- return false;
- // if inactive world event, check the prerequisite events
- else if (mGameEvent[entry].state == GAMEEVENT_WORLD_INACTIVE)
- {
- for(std::set<uint16>::const_iterator itr = mGameEvent[entry].prerequisite_events.begin(); itr != mGameEvent[entry].prerequisite_events.end(); ++itr)
- {
- if( (mGameEvent[*itr].state != GAMEEVENT_WORLD_NEXTPHASE && mGameEvent[*itr].state != GAMEEVENT_WORLD_FINISHED) || // if prereq not in nextphase or finished state, then can't start this one
- mGameEvent[*itr].nextstart > currenttime) // if not in nextphase state for long enough, can't start this one
- return false;
- }
- // all prerequisite events are met
- // but if there are no prerequisites, this can be only activated through gm command
- return !(mGameEvent[entry].prerequisite_events.empty());
- }
- // Get the event information
- if( mGameEvent[entry].start < currenttime && currenttime < mGameEvent[entry].end &&
- ((currenttime - mGameEvent[entry].start) % (mGameEvent[entry].occurence * MINUTE)) < (mGameEvent[entry].length * MINUTE) )
- return true;
- else
- return false;
-}
-
-uint32 GameEvent::NextCheck(uint16 entry) const
-{
- time_t currenttime = time(NULL);
-
- // for NEXTPHASE state world events, return the delay to start the next event, so the followup event will be checked correctly
- if ((mGameEvent[entry].state == GAMEEVENT_WORLD_NEXTPHASE || mGameEvent[entry].state == GAMEEVENT_WORLD_FINISHED) && mGameEvent[entry].nextstart >= currenttime)
- return (mGameEvent[entry].nextstart - currenttime);
-
- // for CONDITIONS state world events, return the length of the wait period, so if the conditions are met, this check will be called again to set the timer as NEXTPHASE event
- if (mGameEvent[entry].state == GAMEEVENT_WORLD_CONDITIONS)
- return mGameEvent[entry].length ? mGameEvent[entry].length * 60 : max_ge_check_delay;
-
- // outdated event: we return max
- if (currenttime > mGameEvent[entry].end)
- return max_ge_check_delay;
-
- // never started event, we return delay before start
- if (mGameEvent[entry].start > currenttime)
- return (mGameEvent[entry].start - currenttime);
-
- uint32 delay;
- // in event, we return the end of it
- if ((((currenttime - mGameEvent[entry].start) % (mGameEvent[entry].occurence * 60)) < (mGameEvent[entry].length * 60)))
- // we return the delay before it ends
- delay = (mGameEvent[entry].length * MINUTE) - ((currenttime - mGameEvent[entry].start) % (mGameEvent[entry].occurence * MINUTE));
- else // not in window, we return the delay before next start
- delay = (mGameEvent[entry].occurence * MINUTE) - ((currenttime - mGameEvent[entry].start) % (mGameEvent[entry].occurence * MINUTE));
- // In case the end is before next check
- if (mGameEvent[entry].end < time_t(currenttime + delay))
- return (mGameEvent[entry].end - currenttime);
- else
- return delay;
-}
-
-bool GameEvent::StartEvent( uint16 event_id, bool overwrite )
-{
- if(mGameEvent[event_id].state == GAMEEVENT_NORMAL)
- {
- AddActiveEvent(event_id);
- ApplyNewEvent(event_id);
- if(overwrite)
- {
- mGameEvent[event_id].start = time(NULL);
- if(mGameEvent[event_id].end <= mGameEvent[event_id].start)
- mGameEvent[event_id].end = mGameEvent[event_id].start+mGameEvent[event_id].length;
- }
- return false;
- }
- else
- {
- if( mGameEvent[event_id].state == GAMEEVENT_WORLD_INACTIVE )
- // set to conditions phase
- mGameEvent[event_id].state = GAMEEVENT_WORLD_CONDITIONS;
-
- // add to active events
- AddActiveEvent(event_id);
- // add spawns
- ApplyNewEvent(event_id);
-
- // check if can go to next state
- bool conditions_met = CheckOneGameEventConditions(event_id);
- // save to db
- SaveWorldEventStateToDB(event_id);
- // force game event update to set the update timer if conditions were met from a command
- // this update is needed to possibly start events dependent on the started one
- // or to scedule another update where the next event will be started
- if(overwrite && conditions_met)
- sWorld.ForceGameEventUpdate();
-
- return conditions_met;
- }
-}
-
-void GameEvent::StopEvent( uint16 event_id, bool overwrite )
-{
- bool serverwide_evt = mGameEvent[event_id].state != GAMEEVENT_NORMAL;
-
- RemoveActiveEvent(event_id);
- UnApplyEvent(event_id);
-
- if(overwrite && !serverwide_evt)
- {
- mGameEvent[event_id].start = time(NULL) - mGameEvent[event_id].length * MINUTE;
- if(mGameEvent[event_id].end <= mGameEvent[event_id].start)
- mGameEvent[event_id].end = mGameEvent[event_id].start+mGameEvent[event_id].length;
- }
- else if(serverwide_evt)
- {
- // if finished world event, then only gm command can stop it
- if(overwrite || mGameEvent[event_id].state != GAMEEVENT_WORLD_FINISHED)
- {
- // reset conditions
- mGameEvent[event_id].nextstart = 0;
- mGameEvent[event_id].state = GAMEEVENT_WORLD_INACTIVE;
- std::map<uint32 /*condition id*/, GameEventFinishCondition>::iterator itr;
- for(itr = mGameEvent[event_id].conditions.begin(); itr != mGameEvent[event_id].conditions.end(); ++itr)
- itr->second.done = 0;
- CharacterDatabase.BeginTransaction();
- CharacterDatabase.PExecute("DELETE FROM game_event_save WHERE event_id = '%u'",event_id);
- CharacterDatabase.PExecute("DELETE FROM game_event_condition_save WHERE event_id = '%u'",event_id);
- CharacterDatabase.CommitTransaction();
- }
- }
-}
-
-void GameEvent::LoadFromDB()
-{
- {
- QueryResult *result = WorldDatabase.Query("SELECT MAX(entry) FROM game_event");
- if( !result )
- {
- sLog.outString(">> Table game_event is empty.");
- sLog.outString();
- return;
- }
-
- Field *fields = result->Fetch();
-
- uint32 max_event_id = fields[0].GetUInt16();
- delete result;
-
- mGameEvent.resize(max_event_id+1);
- }
-
- QueryResult *result = WorldDatabase.Query("SELECT entry,UNIX_TIMESTAMP(start_time),UNIX_TIMESTAMP(end_time),occurence,length,description,world_event FROM game_event");
- if( !result )
- {
- mGameEvent.clear();
- sLog.outString(">> Table game_event is empty!");
- sLog.outString();
- return;
- }
-
- uint32 count = 0;
-
- {
- barGoLink bar( result->GetRowCount() );
- do
- {
- ++count;
- Field *fields = result->Fetch();
-
- bar.step();
-
- uint16 event_id = fields[0].GetUInt16();
- if(event_id==0)
- {
- sLog.outErrorDb("`game_event` game event id (%i) is reserved and can't be used.",event_id);
- continue;
- }
-
- GameEventData& pGameEvent = mGameEvent[event_id];
- uint64 starttime = fields[1].GetUInt64();
- pGameEvent.start = time_t(starttime);
- uint64 endtime = fields[2].GetUInt64();
- pGameEvent.end = time_t(endtime);
- pGameEvent.occurence = fields[3].GetUInt32();
- pGameEvent.length = fields[4].GetUInt32();
- pGameEvent.description = fields[5].GetCppString();
- pGameEvent.state = (GameEventState)(fields[6].GetUInt8());
- pGameEvent.nextstart = 0;
-
- if(pGameEvent.length==0 && pGameEvent.state == GAMEEVENT_NORMAL) // length>0 is validity check
- {
- sLog.outErrorDb("`game_event` game event id (%i) isn't a world event and has length = 0, thus it can't be used.",event_id);
- continue;
- }
-
- } while( result->NextRow() );
- delete result;
-
- sLog.outString();
- sLog.outString( ">> Loaded %u game events", count );
- }
-
- // load game event saves
- // 0 1 2
- result = CharacterDatabase.Query("SELECT event_id, state, UNIX_TIMESTAMP(next_start) FROM game_event_save");
-
- count = 0;
- if( !result )
- {
- barGoLink bar2(1);
- bar2.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u game event saves in game events", count );
- }
- else
- {
-
- barGoLink bar2( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar2.step();
-
- uint16 event_id = fields[0].GetUInt16();
-
- if(event_id >= mGameEvent.size())
- {
- sLog.outErrorDb("`game_event_save` game event id (%i) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- if(mGameEvent[event_id].state != GAMEEVENT_NORMAL)
- {
- mGameEvent[event_id].state = (GameEventState)(fields[1].GetUInt8());
- mGameEvent[event_id].nextstart = time_t(fields[2].GetUInt64());
- }
- else
- {
- sLog.outErrorDb("game_event_save includes event save for non-worldevent id %u",event_id);
- continue;
- }
-
- ++count;
-
- } while( result->NextRow() );
- sLog.outString();
- sLog.outString( ">> Loaded %u game event saves in game events", count );
- delete result;
- }
-
- // load game event links (prerequisites)
- result = WorldDatabase.Query("SELECT event_id, prerequisite_event FROM game_event_prerequisite");
- if( !result )
- {
- barGoLink bar2(1);
- bar2.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u game event prerequisites in game events", count );
- }
- else
- {
-
- barGoLink bar2( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar2.step();
-
- uint16 event_id = fields[0].GetUInt16();
-
- if(event_id >= mGameEvent.size())
- {
- sLog.outErrorDb("`game_event_prerequisite` game event id (%i) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
-
- if(mGameEvent[event_id].state != GAMEEVENT_NORMAL)
- {
- uint16 prerequisite_event = fields[1].GetUInt16();
- if(prerequisite_event >= mGameEvent.size())
- {
- sLog.outErrorDb("`game_event_prerequisite` game event prerequisite id (%i) is out of range compared to max event id in `game_event`",prerequisite_event);
- continue;
- }
- mGameEvent[event_id].prerequisite_events.insert(prerequisite_event);
- }
- else
- {
- sLog.outErrorDb("game_event_prerequisiste includes event entry for non-worldevent id %u",event_id);
- continue;
- }
-
- ++count;
-
- } while( result->NextRow() );
- sLog.outString();
- sLog.outString( ">> Loaded %u game event prerequisites in game events", count );
- delete result;
- }
-
- mGameEventCreatureGuids.resize(mGameEvent.size()*2-1);
- // 1 2
- result = WorldDatabase.Query("SELECT creature.guid, game_event_creature.event "
- "FROM creature JOIN game_event_creature ON creature.guid = game_event_creature.guid");
-
- count = 0;
- if( !result )
- {
- barGoLink bar(1);
- bar.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u creatures in game events", count );
- }
- else
- {
-
- barGoLink bar( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar.step();
-
- uint32 guid = fields[0].GetUInt32();
- int16 event_id = fields[1].GetInt16();
-
- int32 internal_event_id = mGameEvent.size() + event_id - 1;
-
- if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size())
- {
- sLog.outErrorDb("`game_event_creature` game event id (%i) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- ++count;
- GuidList& crelist = mGameEventCreatureGuids[internal_event_id];
- crelist.push_back(guid);
-
- } while( result->NextRow() );
- delete result;
-
- sLog.outString();
- sLog.outString( ">> Loaded %u creatures in game events", count );
- }
-
- mGameEventGameobjectGuids.resize(mGameEvent.size()*2-1);
- // 1 2
- result = WorldDatabase.Query("SELECT gameobject.guid, game_event_gameobject.event "
- "FROM gameobject JOIN game_event_gameobject ON gameobject.guid=game_event_gameobject.guid");
-
- count = 0;
- if( !result )
- {
- barGoLink bar(1);
- bar.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u gameobjects in game events", count );
- }
- else
- {
-
- barGoLink bar( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar.step();
-
- uint32 guid = fields[0].GetUInt32();
- int16 event_id = fields[1].GetInt16();
-
- int32 internal_event_id = mGameEvent.size() + event_id - 1;
-
- if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size())
- {
- sLog.outErrorDb("`game_event_gameobject` game event id (%i) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- ++count;
- GuidList& golist = mGameEventGameobjectGuids[internal_event_id];
- golist.push_back(guid);
-
- } while( result->NextRow() );
- delete result;
-
- sLog.outString();
- sLog.outString( ">> Loaded %u gameobjects in game events", count );
- }
-
- mGameEventModelEquip.resize(mGameEvent.size());
- // 0 1 2
- result = WorldDatabase.Query("SELECT creature.guid, game_event_model_equip.event, game_event_model_equip.modelid,"
- // 3
- "game_event_model_equip.equipment_id "
- "FROM creature JOIN game_event_model_equip ON creature.guid=game_event_model_equip.guid");
-
- count = 0;
- if( !result )
- {
- barGoLink bar(1);
- bar.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u model/equipment changes in game events", count );
- }
- else
- {
-
- barGoLink bar( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar.step();
- uint32 guid = fields[0].GetUInt32();
- uint16 event_id = fields[1].GetUInt16();
-
- if(event_id >= mGameEventModelEquip.size())
- {
- sLog.outErrorDb("`game_event_model_equip` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- ++count;
- ModelEquipList& equiplist = mGameEventModelEquip[event_id];
- ModelEquip newModelEquipSet;
- newModelEquipSet.modelid = fields[2].GetUInt32();
- newModelEquipSet.equipment_id = fields[3].GetUInt32();
- newModelEquipSet.equipement_id_prev = 0;
- newModelEquipSet.modelid_prev = 0;
-
- if(newModelEquipSet.equipment_id > 0)
- {
- if(!objmgr.GetEquipmentInfo(newModelEquipSet.equipment_id))
- {
- sLog.outErrorDb("Table `game_event_model_equip` have creature (Guid: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", guid, newModelEquipSet.equipment_id);
- continue;
- }
- }
-
- equiplist.push_back(std::pair<uint32, ModelEquip>(guid, newModelEquipSet));
-
- } while( result->NextRow() );
- delete result;
-
- sLog.outString();
- sLog.outString( ">> Loaded %u model/equipment changes in game events", count );
- }
-
- mGameEventCreatureQuests.resize(mGameEvent.size());
- // 0 1 2
- result = WorldDatabase.Query("SELECT id, quest, event FROM game_event_creature_quest");
-
- count = 0;
- if( !result )
- {
- barGoLink bar(1);
- bar.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u quests additions in game events", count );
- }
- else
- {
-
- barGoLink bar( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar.step();
- uint32 id = fields[0].GetUInt32();
- uint32 quest = fields[1].GetUInt32();
- uint16 event_id = fields[2].GetUInt16();
-
- if(event_id >= mGameEventCreatureQuests.size())
- {
- sLog.outErrorDb("`game_event_creature_quest` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- ++count;
- QuestRelList& questlist = mGameEventCreatureQuests[event_id];
- questlist.push_back(QuestRelation(id, quest));
-
- } while( result->NextRow() );
- sLog.outString();
- sLog.outString( ">> Loaded %u quests additions in game events", count );
-
- delete result;
- }
-
- mGameEventGameObjectQuests.resize(mGameEvent.size());
- // 0 1 2
- result = WorldDatabase.Query("SELECT id, quest, event FROM game_event_gameobject_quest");
-
- count = 0;
- if( !result )
- {
- barGoLink bar3(1);
- bar3.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u go quests additions in game events", count );
- }
- else
- {
-
- barGoLink bar3( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar3.step();
- uint32 id = fields[0].GetUInt32();
- uint32 quest = fields[1].GetUInt32();
- uint16 event_id = fields[2].GetUInt16();
-
- if(event_id >= mGameEventGameObjectQuests.size())
- {
- sLog.outErrorDb("`game_event_gameobject_quest` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- ++count;
- QuestRelList& questlist = mGameEventGameObjectQuests[event_id];
- questlist.push_back(QuestRelation(id, quest));
-
- } while( result->NextRow() );
- delete result;
-
- sLog.outString();
- sLog.outString( ">> Loaded %u quests additions in game events", count );
- }
-
- // Load quest to (event,condition) mapping
- // 0 1 2 3
- result = WorldDatabase.Query("SELECT quest, event_id, condition_id, num FROM game_event_quest_condition");
-
- count = 0;
- if( !result )
- {
- barGoLink bar3(1);
- bar3.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u quest event conditions in game events", count );
- }
- else
- {
-
- barGoLink bar3( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar3.step();
- uint32 quest = fields[0].GetUInt32();
- uint16 event_id = fields[1].GetUInt16();
- uint32 condition = fields[2].GetUInt32();
- float num = fields[3].GetFloat();
-
- if(event_id >= mGameEvent.size())
- {
- sLog.outErrorDb("`game_event_quest_condition` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- ++count;
- mQuestToEventConditions[quest].event_id = event_id;
- mQuestToEventConditions[quest].condition = condition;
- mQuestToEventConditions[quest].num = num;
-
- } while( result->NextRow() );
- sLog.outString();
- sLog.outString( ">> Loaded %u quest event conditions in game events", count );
-
- delete result;
- }
-
- // load conditions of the events
- // 0 1 2 3 4
- result = WorldDatabase.Query("SELECT event_id, condition_id, req_num, max_world_state_field, done_world_state_field FROM game_event_condition");
-
- count = 0;
- if( !result )
- {
- barGoLink bar3(1);
- bar3.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u conditions in game events", count );
- }
- else
- {
-
- barGoLink bar3( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar3.step();
- uint16 event_id = fields[0].GetUInt16();
- uint32 condition = fields[1].GetUInt32();
-
- if(event_id >= mGameEvent.size())
- {
- sLog.outErrorDb("`game_event_condition` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- mGameEvent[event_id].conditions[condition].reqNum = fields[2].GetFloat();
- mGameEvent[event_id].conditions[condition].done = 0;
- mGameEvent[event_id].conditions[condition].max_world_state = fields[3].GetUInt32();
- mGameEvent[event_id].conditions[condition].done_world_state = fields[4].GetUInt32();
-
- ++count;
-
- } while( result->NextRow() );
- sLog.outString();
- sLog.outString( ">> Loaded %u conditions in game events", count );
-
- delete result;
- }
-
- // load condition saves
- // 0 1 2
- result = CharacterDatabase.Query("SELECT event_id, condition_id, done FROM game_event_condition_save");
-
- count = 0;
- if( !result )
- {
- barGoLink bar3(1);
- bar3.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u condition saves in game events", count );
- }
- else
- {
-
- barGoLink bar3( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar3.step();
- uint16 event_id = fields[0].GetUInt16();
- uint32 condition = fields[1].GetUInt32();
-
- if(event_id >= mGameEvent.size())
- {
- sLog.outErrorDb("`game_event_condition_save` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- std::map<uint32, GameEventFinishCondition>::iterator itr = mGameEvent[event_id].conditions.find(condition);
- if(itr != mGameEvent[event_id].conditions.end())
- {
- itr->second.done = fields[2].GetFloat();
- }
- else
- {
- sLog.outErrorDb("game_event_condition_save contains not present condition evt id %u cond id %u",event_id, condition);
- continue;
- }
-
- ++count;
-
- } while( result->NextRow() );
- sLog.outString();
- sLog.outString( ">> Loaded %u condition saves in game events", count );
-
- delete result;
- }
-
- mGameEventNPCFlags.resize(mGameEvent.size());
- // load game event npcflag
- // 0 1 2
- result = WorldDatabase.Query("SELECT guid, event_id, npcflag FROM game_event_npcflag");
-
- count = 0;
- if( !result )
- {
- barGoLink bar3(1);
- bar3.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u npcflags in game events", count );
- }
- else
- {
-
- barGoLink bar3( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar3.step();
- uint32 guid = fields[0].GetUInt32();
- uint16 event_id = fields[1].GetUInt16();
- uint32 npcflag = fields[2].GetUInt32();
-
- if(event_id >= mGameEvent.size())
- {
- sLog.outErrorDb("`game_event_npcflag` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- mGameEventNPCFlags[event_id].push_back(GuidNPCFlagPair(guid,npcflag));
-
- ++count;
-
- } while( result->NextRow() );
- sLog.outString();
- sLog.outString( ">> Loaded %u npcflags in game events", count );
-
- delete result;
- }
-
- mGameEventVendors.resize(mGameEvent.size());
- // 0 1 2 3 4 5
- result = WorldDatabase.Query("SELECT event, guid, item, maxcount, incrtime, ExtendedCost FROM game_event_npc_vendor");
-
- count = 0;
- if( !result )
- {
- barGoLink bar3(1);
- bar3.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u vendor additions in game events", count );
- }
- else
- {
-
- barGoLink bar3( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar3.step();
- uint16 event_id = fields[0].GetUInt16();
-
- if(event_id >= mGameEventVendors.size())
- {
- sLog.outErrorDb("`game_event_npc_vendor` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- NPCVendorList& vendors = mGameEventVendors[event_id];
- NPCVendorEntry newEntry;
- uint32 guid = fields[1].GetUInt32();
- newEntry.item = fields[2].GetUInt32();
- newEntry.maxcount = fields[3].GetUInt32();
- newEntry.incrtime = fields[4].GetUInt32();
- newEntry.ExtendedCost = fields[5].GetUInt32();
- // get the event npc flag for checking if the npc will be vendor during the event or not
- uint32 event_npc_flag = 0;
- NPCFlagList& flist = mGameEventNPCFlags[event_id];
- for(NPCFlagList::const_iterator itr = flist.begin(); itr != flist.end(); ++itr)
- {
- if(itr->first == guid)
- {
- event_npc_flag = itr->second;
- break;
- }
- }
- // get creature entry
- newEntry.entry = 0;
-
- if( CreatureData const* data = objmgr.GetCreatureData(guid) )
- newEntry.entry = data->id;
-
- // check validity with event's npcflag
- if(!objmgr.IsVendorItemValid(newEntry.entry, newEntry.item, newEntry.maxcount, newEntry.incrtime, newEntry.ExtendedCost, NULL, NULL, event_npc_flag))
- continue;
- ++count;
- vendors.push_back(newEntry);
-
- } while( result->NextRow() );
- sLog.outString();
- sLog.outString( ">> Loaded %u vendor additions in game events", count );
-
- delete result;
- }
-
- // load game event npc gossip ids
- // 0 1 2
- result = WorldDatabase.Query("SELECT guid, event_id, textid FROM game_event_npc_gossip");
-
- count = 0;
- if( !result )
- {
- barGoLink bar3(1);
- bar3.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u npc gossip textids in game events", count );
- }
- else
- {
-
- barGoLink bar3( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar3.step();
- uint32 guid = fields[0].GetUInt32();
- uint16 event_id = fields[1].GetUInt16();
- uint32 textid = fields[2].GetUInt32();
-
- if(event_id >= mGameEvent.size())
- {
- sLog.outErrorDb("`game_event_npc_gossip` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- mNPCGossipIds[guid]=EventNPCGossipIdPair(event_id, textid);
-
- ++count;
-
- } while( result->NextRow() );
- sLog.outString();
- sLog.outString( ">> Loaded %u npc gossip textids in game events", count );
-
- delete result;
- }
-
- // set all flags to 0
- mGameEventBattleGroundHolidays.resize(mGameEvent.size(),0);
- // load game event battleground flags
- // 0 1
- result = WorldDatabase.Query("SELECT event, bgflag FROM game_event_battleground_holiday");
-
- count = 0;
- if( !result )
- {
- barGoLink bar3(1);
- bar3.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u battleground holidays in game events", count );
- }
- else
- {
-
- barGoLink bar3( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar3.step();
-
- uint16 event_id = fields[0].GetUInt16();
-
- if(event_id >= mGameEvent.size())
- {
- sLog.outErrorDb("`game_event_battleground_holiday` game event id (%u) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- ++count;
-
- mGameEventBattleGroundHolidays[event_id] = fields[1].GetUInt32();
-
- } while( result->NextRow() );
- sLog.outString();
- sLog.outString( ">> Loaded %u battleground holidays in game events", count );
-
- delete result;
- }
-
- ////////////////////////
- // GameEventPool
- ////////////////////////
-
- mGameEventPoolIds.resize(mGameEvent.size()*2-1);
- // 1 2
- result = WorldDatabase.Query("SELECT pool_template.entry, game_event_pool.event "
- "FROM pool_template JOIN game_event_pool ON pool_template.entry = game_event_pool.pool_entry");
-
- count = 0;
- if( !result )
- {
- barGoLink bar2(1);
- bar2.step();
-
- sLog.outString();
- sLog.outString(">> Loaded %u pools in game events", count );
- }
- else
- {
-
- barGoLink bar2( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
-
- bar2.step();
-
- uint32 entry = fields[0].GetUInt16();
- int16 event_id = fields[1].GetInt16();
-
- int32 internal_event_id = mGameEvent.size() + event_id - 1;
-
- if(internal_event_id < 0 || internal_event_id >= mGameEventPoolIds.size())
- {
- sLog.outErrorDb("`game_event_pool` game event id (%i) is out of range compared to max event id in `game_event`",event_id);
- continue;
- }
-
- if (!poolhandler.CheckPool(entry))
- {
- sLog.outErrorDb("Pool Id (%u) has all creatures or gameobjects with explicit chance sum <>100 and no equal chance defined. The pool system cannot pick one to spawn.", entry);
- continue;
- }
-
- ++count;
- IdList& poollist = mGameEventPoolIds[internal_event_id];
- poollist.push_back(entry);
-
- } while( result->NextRow() );
- sLog.outString();
- sLog.outString( ">> Loaded %u pools in game events", count );
- delete result;
- }
-}
-
-uint32 GameEvent::GetNPCFlag(Creature * cr)
-{
- uint32 mask = 0;
- uint32 guid = cr->GetDBTableGUIDLow();
-
- for(ActiveEvents::iterator e_itr = m_ActiveEvents.begin(); e_itr != m_ActiveEvents.end(); ++e_itr)
- {
- for(NPCFlagList::iterator itr = mGameEventNPCFlags[*e_itr].begin();
- itr != mGameEventNPCFlags[*e_itr].end();
- ++ itr)
- if(itr->first == guid)
- mask |= itr->second;
- }
-
- return mask;
-}
-
-uint32 GameEvent::GetNpcTextId(uint32 guid)
-{
- GuidEventNpcGossipIdMap::iterator itr = mNPCGossipIds.find(guid);
- if(itr != mNPCGossipIds.end())
- if(IsActiveEvent(itr->second.first))
- return itr->second.second;
- return 0;
-}
-
-uint32 GameEvent::Initialize() // return the next event delay in ms
-{
- m_ActiveEvents.clear();
- uint32 delay = Update();
- sLog.outBasic("Game Event system initialized." );
- isSystemInit = true;
- return delay;
-}
-
-uint32 GameEvent::Update() // return the next event delay in ms
-{
- time_t currenttime = time(NULL);
- uint32 nextEventDelay = max_ge_check_delay; // 1 day
- uint32 calcDelay;
- std::set<uint16> activate, deactivate;
- for (uint16 itr = 1; itr < mGameEvent.size(); ++itr)
- {
- // must do the activating first, and after that the deactivating
- // so first queue it
- //sLog.outErrorDb("Checking event %u",itr);
- if (CheckOneGameEvent(itr))
- {
- // if the world event is in NEXTPHASE state, and the time has passed to finish this event, then do so
- if (mGameEvent[itr].state == GAMEEVENT_WORLD_NEXTPHASE && mGameEvent[itr].nextstart <= currenttime)
- {
- // set this event to finished, null the nextstart time
- mGameEvent[itr].state = GAMEEVENT_WORLD_FINISHED;
- mGameEvent[itr].nextstart = 0;
- // save the state of this gameevent
- SaveWorldEventStateToDB(itr);
- // queue for deactivation
- if(IsActiveEvent(itr))
- deactivate.insert(itr);
- // go to next event, this no longer needs an event update timer
- continue;
- }
- else if (mGameEvent[itr].state == GAMEEVENT_WORLD_CONDITIONS && CheckOneGameEventConditions(itr))
- // changed, save to DB the gameevent state, will be updated in next update cycle
- SaveWorldEventStateToDB(itr);
-
- //sLog.outDebug("GameEvent %u is active",itr->first);
- // queue for activation
- if (!IsActiveEvent(itr))
- activate.insert(itr);
- }
- else
- {
- //sLog.outDebug("GameEvent %u is not active",itr->first);
- if (IsActiveEvent(itr))
- deactivate.insert(itr);
- else
- {
- if (!isSystemInit)
- {
- int16 event_nid = (-1) * (itr);
- // spawn all negative ones for this event
- GameEventSpawn(event_nid);
- }
- }
- }
- calcDelay = NextCheck(itr);
- if (calcDelay < nextEventDelay)
- nextEventDelay = calcDelay;
- }
- // now activate the queue
- // a now activated event can contain a spawn of a to-be-deactivated one
- // following the activate - deactivate order, deactivating the first event later will leave the spawn in (wont disappear then reappear clientside)
- for(std::set<uint16>::iterator itr = activate.begin(); itr != activate.end(); ++itr)
- // start the event
- // returns true the started event completed
- // in that case, initiate next update in 1 second
- if(StartEvent(*itr))
- nextEventDelay = 0;
- for(std::set<uint16>::iterator itr = deactivate.begin(); itr != deactivate.end(); ++itr)
- StopEvent(*itr);
- sLog.outDetail("Next game event check in %u seconds.", nextEventDelay + 1);
- return (nextEventDelay + 1) * IN_MILISECONDS; // Add 1 second to be sure event has started/stopped at next call
-}
-
-void GameEvent::UnApplyEvent(uint16 event_id)
-{
- sLog.outString("GameEvent %u \"%s\" removed.", event_id, mGameEvent[event_id].description.c_str());
- // un-spawn positive event tagged objects
- GameEventUnspawn(event_id);
- // spawn negative event tagget objects
- int16 event_nid = (-1) * event_id;
- GameEventSpawn(event_nid);
- // restore equipment or model
- ChangeEquipOrModel(event_id, false);
- // Remove quests that are events only to non event npc
- UpdateEventQuests(event_id, false);
- // update npcflags in this event
- UpdateEventNPCFlags(event_id);
- // remove vendor items
- UpdateEventNPCVendor(event_id, false);
- // update bg holiday
- UpdateBattleGroundSettings();
-}
-
-void GameEvent::ApplyNewEvent(uint16 event_id)
-{
- switch(sWorld.getConfig(CONFIG_EVENT_ANNOUNCE))
- {
- case 0: // disable
- break;
- case 1: // announce events
- sWorld.SendWorldText(LANG_EVENTMESSAGE, mGameEvent[event_id].description.c_str());
- break;
- }
-
- sLog.outString("GameEvent %u \"%s\" started.", event_id, mGameEvent[event_id].description.c_str());
-
- // spawn positive event tagget objects
- GameEventSpawn(event_id);
- // un-spawn negative event tagged objects
- int16 event_nid = (-1) * event_id;
- GameEventUnspawn(event_nid);
- // Change equipement or model
- ChangeEquipOrModel(event_id, true);
- // Add quests that are events only to non event npc
- UpdateEventQuests(event_id, true);
- // update npcflags in this event
- UpdateEventNPCFlags(event_id);
- // add vendor items
- UpdateEventNPCVendor(event_id, true);
- // update bg holiday
- UpdateBattleGroundSettings();
-}
-
-void GameEvent::UpdateEventNPCFlags(uint16 event_id)
-{
- // go through the creatures whose npcflags are changed in the event
- for(NPCFlagList::iterator itr = mGameEventNPCFlags[event_id].begin(); itr != mGameEventNPCFlags[event_id].end(); ++itr)
- {
- // get the creature data from the low guid to get the entry, to be able to find out the whole guid
- if( CreatureData const* data = objmgr.GetCreatureData(itr->first) )
- {
- Creature * cr = HashMapHolder<Creature>::Find(MAKE_NEW_GUID(itr->first,data->id,HIGHGUID_UNIT));
- // if we found the creature, modify its npcflag
- if(cr)
- {
- uint32 npcflag = GetNPCFlag(cr);
- if(const CreatureInfo * ci = cr->GetCreatureInfo())
- npcflag |= ci->npcflag;
- cr->SetUInt32Value(UNIT_NPC_FLAGS,npcflag);
- // reset gossip options, since the flag change might have added / removed some
- cr->ResetGossipOptions();
- // update to world
- cr->SendUpdateObjectToAllExcept(NULL);
- }
- // if we didn't find it, then the npcflag will be updated when the creature is loaded
- }
- }
-}
-
-void GameEvent::UpdateBattleGroundSettings()
-{
- uint32 mask = 0;
- for(ActiveEvents::const_iterator itr = m_ActiveEvents.begin(); itr != m_ActiveEvents.end(); ++itr )
- mask |= mGameEventBattleGroundHolidays[*itr];
- sBattleGroundMgr.SetHolidayWeekends(mask);
-}
-
-void GameEvent::UpdateEventNPCVendor(uint16 event_id, bool activate)
-{
- for(NPCVendorList::iterator itr = mGameEventVendors[event_id].begin(); itr != mGameEventVendors[event_id].end(); ++itr)
- {
- if(activate)
- objmgr.AddVendorItem(itr->entry, itr->item, itr->maxcount, itr->incrtime, itr->ExtendedCost, false);
- else
- objmgr.RemoveVendorItem(itr->entry, itr->item, false);
- }
-}
-
-void GameEvent::GameEventSpawn(int16 event_id)
-{
- int32 internal_event_id = mGameEvent.size() + event_id - 1;
-
- if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size())
- {
- sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size());
- return;
- }
-
- for (GuidList::iterator itr = mGameEventCreatureGuids[internal_event_id].begin();itr != mGameEventCreatureGuids[internal_event_id].end();++itr)
- {
- // Add to correct cell
- CreatureData const* data = objmgr.GetCreatureData(*itr);
- if (data)
- {
- objmgr.AddCreatureToGrid(*itr, data);
-
- // Spawn if necessary (loaded grids only)
- Map* map = const_cast<Map*>(MapManager::Instance().GetBaseMap(data->mapid));
- // We use spawn coords to spawn
- if(!map->Instanceable() && !map->IsRemovalGrid(data->posX,data->posY))
- {
- Creature* pCreature = new Creature;
- //sLog.outDebug("Spawning creature %u",*itr);
- if (!pCreature->LoadFromDB(*itr, map))
- {
- delete pCreature;
- }
- else
- {
- map->Add(pCreature);
- }
- }
- }
- }
-
- if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size())
- {
- sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size());
- return;
- }
-
- for (GuidList::iterator itr = mGameEventGameobjectGuids[internal_event_id].begin();itr != mGameEventGameobjectGuids[internal_event_id].end();++itr)
- {
- // Add to correct cell
- GameObjectData const* data = objmgr.GetGOData(*itr);
- if (data)
- {
- objmgr.AddGameobjectToGrid(*itr, data);
- // Spawn if necessary (loaded grids only)
- // this base map checked as non-instanced and then only existed
- Map* map = const_cast<Map*>(MapManager::Instance().GetBaseMap(data->mapid));
- // We use current coords to unspawn, not spawn coords since creature can have changed grid
- if(!map->Instanceable() && !map->IsRemovalGrid(data->posX, data->posY))
- {
- GameObject* pGameobject = new GameObject;
- //sLog.outDebug("Spawning gameobject %u", *itr);
- if (!pGameobject->LoadFromDB(*itr, map))
- {
- delete pGameobject;
- }
- else
- {
- if(pGameobject->isSpawnedByDefault())
- map->Add(pGameobject);
- }
- }
- }
- }
-
- if(internal_event_id < 0 || internal_event_id >= mGameEventPoolIds.size())
- {
- sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size());
- return;
- }
-
- for (IdList::iterator itr = mGameEventPoolIds[internal_event_id].begin();itr != mGameEventPoolIds[internal_event_id].end();++itr)
- {
- poolhandler.SpawnPool(*itr);
- }
-}
-
-void GameEvent::GameEventUnspawn(int16 event_id)
-{
- int32 internal_event_id = mGameEvent.size() + event_id - 1;
-
- if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size())
- {
- sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventCreatureGuids element %i (size: %u)",internal_event_id,mGameEventCreatureGuids.size());
- return;
- }
-
- for (GuidList::iterator itr = mGameEventCreatureGuids[internal_event_id].begin();itr != mGameEventCreatureGuids[internal_event_id].end();++itr)
- {
- // check if it's needed by another event, if so, don't remove
- if( event_id > 0 && hasCreatureActiveEventExcept(*itr,event_id) )
- continue;
- // Remove the creature from grid
- if( CreatureData const* data = objmgr.GetCreatureData(*itr) )
- {
- objmgr.RemoveCreatureFromGrid(*itr, data);
-
- if( Creature* pCreature = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(*itr, data->id, HIGHGUID_UNIT), (Creature*)NULL) )
- {
- pCreature->CleanupsBeforeDelete();
- pCreature->AddObjectToRemoveList();
- }
- }
- }
-
- if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size())
- {
- sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventGameobjectGuids element %i (size: %u)",internal_event_id,mGameEventGameobjectGuids.size());
- return;
- }
-
- for (GuidList::iterator itr = mGameEventGameobjectGuids[internal_event_id].begin();itr != mGameEventGameobjectGuids[internal_event_id].end();++itr)
- {
- // check if it's needed by another event, if so, don't remove
- if( event_id >0 && hasGameObjectActiveEventExcept(*itr,event_id) )
- continue;
- // Remove the gameobject from grid
- if(GameObjectData const* data = objmgr.GetGOData(*itr))
- {
- objmgr.RemoveGameobjectFromGrid(*itr, data);
-
- if( GameObject* pGameobject = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(*itr, data->id, HIGHGUID_GAMEOBJECT), (GameObject*)NULL) )
- pGameobject->AddObjectToRemoveList();
- }
- }
- if(internal_event_id < 0 || internal_event_id >= mGameEventPoolIds.size())
- {
- sLog.outError("GameEvent::GameEventUnspawn attempt access to out of range mGameEventPoolIds element %i (size: %u)",internal_event_id,mGameEventPoolIds.size());
- return;
- }
-
- for (IdList::iterator itr = mGameEventPoolIds[internal_event_id].begin();itr != mGameEventPoolIds[internal_event_id].end();++itr)
- {
- poolhandler.DespawnPool(*itr);
- }
-}
-
-void GameEvent::ChangeEquipOrModel(int16 event_id, bool activate)
-{
- for(ModelEquipList::iterator itr = mGameEventModelEquip[event_id].begin();itr != mGameEventModelEquip[event_id].end();++itr)
- {
- // Remove the creature from grid
- CreatureData const* data = objmgr.GetCreatureData(itr->first);
- if(!data)
- continue;
-
- // Update if spawned
- Creature* pCreature = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(itr->first, data->id,HIGHGUID_UNIT), (Creature*)NULL);
- if (pCreature)
- {
- if (activate)
- {
- itr->second.equipement_id_prev = pCreature->GetCurrentEquipmentId();
- itr->second.modelid_prev = pCreature->GetDisplayId();
- pCreature->LoadEquipment(itr->second.equipment_id, true);
- if (itr->second.modelid >0 && itr->second.modelid_prev != itr->second.modelid)
- {
- CreatureModelInfo const *minfo = objmgr.GetCreatureModelInfo(itr->second.modelid);
- if (minfo)
- {
- pCreature->SetDisplayId(itr->second.modelid);
- pCreature->SetNativeDisplayId(itr->second.modelid);
- pCreature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS,minfo->bounding_radius);
- pCreature->SetFloatValue(UNIT_FIELD_COMBATREACH,minfo->combat_reach );
- }
- }
- }
- else
- {
- pCreature->LoadEquipment(itr->second.equipement_id_prev, true);
- if (itr->second.modelid_prev >0 && itr->second.modelid_prev != itr->second.modelid)
- {
- CreatureModelInfo const *minfo = objmgr.GetCreatureModelInfo(itr->second.modelid_prev);
- if (minfo)
- {
- pCreature->SetDisplayId(itr->second.modelid_prev);
- pCreature->SetNativeDisplayId(itr->second.modelid_prev);
- pCreature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS,minfo->bounding_radius);
- pCreature->SetFloatValue(UNIT_FIELD_COMBATREACH,minfo->combat_reach );
- }
- }
- }
- }
- else // If not spawned
- {
- CreatureData const* data = objmgr.GetCreatureData(itr->first);
- if (data && activate)
- {
- CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(data->id);
- uint32 display_id = objmgr.ChooseDisplayId(0,cinfo,data);
- CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
- if (minfo)
- display_id = minfo->modelid;
- if (data->equipmentId == 0)
- itr->second.equipement_id_prev = cinfo->equipmentId;
- else if (data->equipmentId != -1)
- itr->second.equipement_id_prev = data->equipmentId;
- itr->second.modelid_prev = display_id;
- }
- }
- // now last step: put in data
- // just to have write access to it
- CreatureData& data2 = objmgr.NewOrExistCreatureData(itr->first);
- if (activate)
- {
- data2.displayid = itr->second.modelid;
- data2.equipmentId = itr->second.equipment_id;
- }
- else
- {
- data2.displayid = itr->second.modelid_prev;
- data2.equipmentId = itr->second.equipement_id_prev;
- }
- }
-}
-
-bool GameEvent::hasCreatureQuestActiveEventExcept(uint32 quest_id, uint16 event_id)
-{
- for(ActiveEvents::iterator e_itr = m_ActiveEvents.begin(); e_itr != m_ActiveEvents.end(); ++e_itr)
- {
- if((*e_itr) != event_id)
- for(QuestRelList::iterator itr = mGameEventCreatureQuests[*e_itr].begin();
- itr != mGameEventCreatureQuests[*e_itr].end();
- ++ itr)
- if(itr->second == quest_id)
- return true;
- }
- return false;
-}
-
-bool GameEvent::hasGameObjectQuestActiveEventExcept(uint32 quest_id, uint16 event_id)
-{
- for(ActiveEvents::iterator e_itr = m_ActiveEvents.begin(); e_itr != m_ActiveEvents.end(); ++e_itr)
- {
- if((*e_itr) != event_id)
- for(QuestRelList::iterator itr = mGameEventGameObjectQuests[*e_itr].begin();
- itr != mGameEventGameObjectQuests[*e_itr].end();
- ++ itr)
- if(itr->second == quest_id)
- return true;
- }
- return false;
-}
-bool GameEvent::hasCreatureActiveEventExcept(uint32 creature_id, uint16 event_id)
-{
- for(ActiveEvents::iterator e_itr = m_ActiveEvents.begin(); e_itr != m_ActiveEvents.end(); ++e_itr)
- {
- if((*e_itr) != event_id)
- {
- int32 internal_event_id = mGameEvent.size() + (*e_itr) - 1;
- for(GuidList::iterator itr = mGameEventCreatureGuids[internal_event_id].begin();
- itr != mGameEventCreatureGuids[internal_event_id].end();
- ++ itr)
- if(*itr == creature_id)
- return true;
- }
- }
- return false;
-}
-bool GameEvent::hasGameObjectActiveEventExcept(uint32 go_id, uint16 event_id)
-{
- for(ActiveEvents::iterator e_itr = m_ActiveEvents.begin(); e_itr != m_ActiveEvents.end(); ++e_itr)
- {
- if((*e_itr) != event_id)
- {
- int32 internal_event_id = mGameEvent.size() + (*e_itr) - 1;
- for(GuidList::iterator itr = mGameEventGameobjectGuids[internal_event_id].begin();
- itr != mGameEventGameobjectGuids[internal_event_id].end();
- ++ itr)
- if(*itr == go_id)
- return true;
- }
- }
- return false;
-}
-
-void GameEvent::UpdateEventQuests(uint16 event_id, bool Activate)
-{
- QuestRelList::iterator itr;
- for (itr = mGameEventCreatureQuests[event_id].begin();itr != mGameEventCreatureQuests[event_id].end();++itr)
- {
- QuestRelations &CreatureQuestMap = objmgr.mCreatureQuestRelations;
- if (Activate) // Add the pair(id,quest) to the multimap
- CreatureQuestMap.insert(QuestRelations::value_type(itr->first, itr->second));
- else
- {
- if(!hasCreatureQuestActiveEventExcept(itr->second,event_id))
- {
- // Remove the pair(id,quest) from the multimap
- QuestRelations::iterator qitr = CreatureQuestMap.find(itr->first);
- if (qitr == CreatureQuestMap.end())
- continue;
- QuestRelations::iterator lastElement = CreatureQuestMap.upper_bound(itr->first);
- for ( ;qitr != lastElement;++qitr)
- {
- if (qitr->second == itr->second)
- {
- CreatureQuestMap.erase(qitr); // iterator is now no more valid
- break; // but we can exit loop since the element is found
- }
- }
- }
- }
- }
- for (itr = mGameEventGameObjectQuests[event_id].begin();itr != mGameEventGameObjectQuests[event_id].end();++itr)
- {
- QuestRelations &GameObjectQuestMap = objmgr.mGOQuestRelations;
- if (Activate) // Add the pair(id,quest) to the multimap
- GameObjectQuestMap.insert(QuestRelations::value_type(itr->first, itr->second));
- else
- {
- if(!hasGameObjectQuestActiveEventExcept(itr->second,event_id))
- {
- // Remove the pair(id,quest) from the multimap
- QuestRelations::iterator qitr = GameObjectQuestMap.find(itr->first);
- if (qitr == GameObjectQuestMap.end())
- continue;
- QuestRelations::iterator lastElement = GameObjectQuestMap.upper_bound(itr->first);
- for ( ;qitr != lastElement;++qitr)
- {
- if (qitr->second == itr->second)
- {
- GameObjectQuestMap.erase(qitr); // iterator is now no more valid
- break; // but we can exit loop since the element is found
- }
- }
- }
- }
- }}
-
-GameEvent::GameEvent()
-{
- isSystemInit = false;
-}
-
-void GameEvent::HandleQuestComplete(uint32 quest_id)
-{
- // translate the quest to event and condition
- QuestIdToEventConditionMap::iterator itr = mQuestToEventConditions.find(quest_id);
- // quest is registered
- if(itr != mQuestToEventConditions.end())
- {
- uint16 event_id = itr->second.event_id;
- uint32 condition = itr->second.condition;
- float num = itr->second.num;
-
- // the event is not active, so return, don't increase condition finishes
- if(!IsActiveEvent(event_id))
- return;
- // not in correct phase, return
- if(mGameEvent[event_id].state != GAMEEVENT_WORLD_CONDITIONS)
- return;
- std::map<uint32,GameEventFinishCondition>::iterator citr = mGameEvent[event_id].conditions.find(condition);
- // condition is registered
- if(citr != mGameEvent[event_id].conditions.end())
- {
- // increase the done count, only if less then the req
- if(citr->second.done < citr->second.reqNum)
- {
- citr->second.done += num;
- // check max limit
- if(citr->second.done > citr->second.reqNum)
- citr->second.done = citr->second.reqNum;
- // save the change to db
- CharacterDatabase.BeginTransaction();
- CharacterDatabase.PExecute("DELETE FROM game_event_condition_save WHERE event_id = '%u' AND condition_id = '%u'",event_id,condition);
- CharacterDatabase.PExecute("INSERT INTO game_event_condition_save (event_id, condition_id, done) VALUES (%u,%u,%f)",event_id,condition,citr->second.done);
- CharacterDatabase.CommitTransaction();
- // check if all conditions are met, if so, update the event state
- if(CheckOneGameEventConditions(event_id))
- {
- // changed, save to DB the gameevent state
- SaveWorldEventStateToDB(event_id);
- // force update events to set timer
- sWorld.ForceGameEventUpdate();
- }
- }
- }
- }
-}
-
-bool GameEvent::CheckOneGameEventConditions(uint16 event_id)
-{
- for(std::map<uint32,GameEventFinishCondition>::iterator itr = mGameEvent[event_id].conditions.begin(); itr != mGameEvent[event_id].conditions.end(); ++itr)
- if(itr->second.done < itr->second.reqNum)
- // return false if a condition doesn't match
- return false;
- // set the phase
- mGameEvent[event_id].state = GAMEEVENT_WORLD_NEXTPHASE;
- // set the followup events' start time
- if(!mGameEvent[event_id].nextstart)
- {
- time_t currenttime = time(NULL);
- mGameEvent[event_id].nextstart = currenttime + mGameEvent[event_id].length * 60;
- }
- return true;
-}
-
-void GameEvent::SaveWorldEventStateToDB(uint16 event_id)
-{
- CharacterDatabase.BeginTransaction();
- CharacterDatabase.PExecute("DELETE FROM game_event_save WHERE event_id = '%u'",event_id);
- if(mGameEvent[event_id].nextstart)
- CharacterDatabase.PExecute("INSERT INTO game_event_save (event_id, state, next_start) VALUES ('%u','%u',FROM_UNIXTIME("I64FMTD"))",event_id,mGameEvent[event_id].state,(uint64)(mGameEvent[event_id].nextstart));
- else
- CharacterDatabase.PExecute("INSERT INTO game_event_save (event_id, state, next_start) VALUES ('%u','%u','0000-00-00 00:00:00')",event_id,mGameEvent[event_id].state);
- CharacterDatabase.CommitTransaction();
-}
-
-void GameEvent::HandleWorldEventGossip(Player *plr, Creature *c)
-{
- // this function is used to send world state update before sending gossip menu
- // find the npc's gossip id (if set) in an active game event
- // if present, send the event's world states
- GuidEventNpcGossipIdMap::iterator itr = mNPCGossipIds.find(c->GetDBTableGUIDLow());
- if(itr != mNPCGossipIds.end())
- if(IsActiveEvent(itr->second.first))
- // send world state updates to the player about the progress
- SendWorldStateUpdate(plr, itr->second.first);
-}
-
-void GameEvent::SendWorldStateUpdate(Player * plr, uint16 event_id)
-{
- std::map<uint32,GameEventFinishCondition>::iterator itr;
- for(itr = mGameEvent[event_id].conditions.begin(); itr !=mGameEvent[event_id].conditions.end(); ++itr)
- {
- if(itr->second.done_world_state)
- plr->SendUpdateWorldState(itr->second.done_world_state, (uint32)(itr->second.done));
- if(itr->second.max_world_state)
- plr->SendUpdateWorldState(itr->second.max_world_state, (uint32)(itr->second.reqNum));
- }
-}
-
diff --git a/src/game/GameEvent.h b/src/game/GameEvent.h
deleted file mode 100644
index 184f4934b5d..00000000000
--- a/src/game/GameEvent.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * Copyright (C) 2008-2009 Trinity <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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef TRINITY_GAMEEVENT_H
-#define TRINITY_GAMEEVENT_H
-
-#include "Platform/Define.h"
-#include "Creature.h"
-#include "GameObject.h"
-
-#define max_ge_check_delay 86400 // 1 day in seconds
-
-enum GameEventState
-{
- GAMEEVENT_NORMAL = 0, // standard game events
- GAMEEVENT_WORLD_INACTIVE, // not yet started
- GAMEEVENT_WORLD_CONDITIONS, // condition matching phase
- GAMEEVENT_WORLD_NEXTPHASE, // conditions are met, now 'lenght' timer to start next event
- GAMEEVENT_WORLD_FINISHED // next events are started, unapply this one
-};
-
-struct GameEventFinishCondition
-{
- float reqNum; // required number // use float, since some events use percent
- float done; // done number
- uint32 max_world_state; // max resource count world state update id
- uint32 done_world_state; // done resource count world state update id
-};
-
-struct GameEventQuestToEventConditionNum
-{
- uint16 event_id;
- uint32 condition;
- float num;
-};
-
-struct GameEventData
-{
- GameEventData() : start(1),end(0),nextstart(0),occurence(0),length(0),state(GAMEEVENT_NORMAL) {}
- time_t start; // occurs after this time
- time_t end; // occurs before this time
- time_t nextstart; // after this time the follow-up events count this phase completed
- uint32 occurence; // time between end and start
- uint32 length; // length of the event (minutes) after finishing all conditions
- GameEventState state; // state of the game event, these are saved into the game_event table on change!
- std::map<uint32 /*condition id*/, GameEventFinishCondition> conditions; // conditions to finish
- std::set<uint16 /*gameevent id*/> prerequisite_events; // events that must be completed before starting this event
- std::string description;
-
- bool isValid() const { return ((length > 0) || (state > GAMEEVENT_NORMAL)); }
-};
-
-struct ModelEquip
-{
- uint32 modelid;
- uint32 equipment_id;
- uint32 modelid_prev;
- uint32 equipement_id_prev;
-};
-
-struct NPCVendorEntry
-{
- uint32 entry; // creature entry
- uint32 item; // item id
- uint32 maxcount; // 0 for infinite
- uint32 incrtime; // time for restore items amount if maxcount != 0
- uint32 ExtendedCost;
-};
-
-class Player;
-class GameEvent
-{
- public:
- GameEvent();
- ~GameEvent() {};
- typedef std::set<uint16> ActiveEvents;
- typedef std::vector<GameEventData> GameEventDataMap;
- ActiveEvents const& GetActiveEventList() const { return m_ActiveEvents; }
- GameEventDataMap const& GetEventMap() const { return mGameEvent; }
- bool CheckOneGameEvent(uint16 entry) const;
- uint32 NextCheck(uint16 entry) const;
- void LoadFromDB();
- uint32 Update();
- bool IsActiveEvent(uint16 event_id) { return ( m_ActiveEvents.find(event_id)!=m_ActiveEvents.end()); }
- uint32 Initialize();
- bool StartEvent(uint16 event_id, bool overwrite = false);
- void StopEvent(uint16 event_id, bool overwrite = false);
- void HandleQuestComplete(uint32 quest_id); // called on world event type quest completions
- void HandleWorldEventGossip(Player * plr, Creature * c);
- uint32 GetNPCFlag(Creature * cr);
- uint32 GetNpcTextId(uint32 guid);
- private:
- void SendWorldStateUpdate(Player * plr, uint16 event_id);
- void AddActiveEvent(uint16 event_id) { m_ActiveEvents.insert(event_id); }
- void RemoveActiveEvent(uint16 event_id) { m_ActiveEvents.erase(event_id); }
- void ApplyNewEvent(uint16 event_id);
- void UnApplyEvent(uint16 event_id);
- void GameEventSpawn(int16 event_id);
- void GameEventUnspawn(int16 event_id);
- void ChangeEquipOrModel(int16 event_id, bool activate);
- void UpdateEventQuests(uint16 event_id, bool Activate);
- void UpdateEventNPCFlags(uint16 event_id);
- void UpdateEventNPCVendor(uint16 event_id, bool activate);
- void UpdateBattleGroundSettings();
- bool CheckOneGameEventConditions(uint16 event_id);
- void SaveWorldEventStateToDB(uint16 event_id);
- bool hasCreatureQuestActiveEventExcept(uint32 quest_id, uint16 event_id);
- bool hasGameObjectQuestActiveEventExcept(uint32 quest_id, uint16 event_id);
- bool hasCreatureActiveEventExcept(uint32 creature_guid, uint16 event_id);
- bool hasGameObjectActiveEventExcept(uint32 go_guid, uint16 event_id);
- protected:
- typedef std::list<uint32> GuidList;
- typedef std::list<uint16> IdList;
- typedef std::vector<GuidList> GameEventGuidMap;
- typedef std::vector<IdList> GameEventIdMap;
- typedef std::pair<uint32, ModelEquip> ModelEquipPair;
- typedef std::list<ModelEquipPair> ModelEquipList;
- typedef std::vector<ModelEquipList> GameEventModelEquipMap;
- typedef std::pair<uint32, uint32> QuestRelation;
- typedef std::list<QuestRelation> QuestRelList;
- typedef std::vector<QuestRelList> GameEventQuestMap;
- typedef std::list<NPCVendorEntry> NPCVendorList;
- typedef std::vector<NPCVendorList> GameEventNPCVendorMap;
- typedef std::map<uint32 /*quest id*/, GameEventQuestToEventConditionNum> QuestIdToEventConditionMap;
- typedef std::pair<uint32 /*guid*/, uint32 /*npcflag*/> GuidNPCFlagPair;
- typedef std::list<GuidNPCFlagPair> NPCFlagList;
- typedef std::vector<NPCFlagList> GameEventNPCFlagMap;
- typedef std::pair<uint16 /*event id*/, uint32 /*gossip id*/> EventNPCGossipIdPair;
- typedef std::map<uint32 /*guid*/, EventNPCGossipIdPair> GuidEventNpcGossipIdMap;
- typedef std::vector<uint32> GameEventBitmask;
- GameEventQuestMap mGameEventCreatureQuests;
- GameEventQuestMap mGameEventGameObjectQuests;
- GameEventNPCVendorMap mGameEventVendors;
- GameEventModelEquipMap mGameEventModelEquip;
- GameEventGuidMap mGameEventCreatureGuids;
- GameEventGuidMap mGameEventGameobjectGuids;
- GameEventIdMap mGameEventPoolIds;
- GameEventDataMap mGameEvent;
- GameEventBitmask mGameEventBattleGroundHolidays;
- QuestIdToEventConditionMap mQuestToEventConditions;
- GameEventNPCFlagMap mGameEventNPCFlags;
- GuidEventNpcGossipIdMap mNPCGossipIds;
- ActiveEvents m_ActiveEvents;
- bool isSystemInit;
-};
-
-#define gameeventmgr Trinity::Singleton<GameEvent>::Instance()
-#endif
-
diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h
index 525402f0a1c..1704d26263c 100644
--- a/src/game/GridNotifiersImpl.h
+++ b/src/game/GridNotifiersImpl.h
@@ -74,7 +74,7 @@ inline void PlayerCreatureRelocationWorker(Player* pl, Creature* c)
// Creature AI reaction
if(c->HasReactState(REACT_AGGRESSIVE) && !c->hasUnitState(UNIT_STAT_SIGHTLESS))
{
- if( c->AI() && c->IsWithinSightDist(pl) && !c->IsInEvadeMode() )
+ if( c->IsAIEnabled && c->IsWithinSightDist(pl) && !c->IsInEvadeMode() )
c->AI()->MoveInLineOfSight(pl);
}
}
@@ -83,13 +83,13 @@ inline void CreatureCreatureRelocationWorker(Creature* c1, Creature* c2)
{
if(c1->HasReactState(REACT_AGGRESSIVE) && !c1->hasUnitState(UNIT_STAT_SIGHTLESS))
{
- if( c1->AI() && c1->IsWithinSightDist(c2) && !c1->IsInEvadeMode() )
+ if( c1->IsAIEnabled && c1->IsWithinSightDist(c2) && !c1->IsInEvadeMode() )
c1->AI()->MoveInLineOfSight(c2);
}
if(c2->HasReactState(REACT_AGGRESSIVE) && !c2->hasUnitState(UNIT_STAT_SIGHTLESS))
{
- if( c2->AI() && c1->IsWithinSightDist(c2) && !c2->IsInEvadeMode() )
+ if( c2->IsAIEnabled && c1->IsWithinSightDist(c2) && !c2->IsInEvadeMode() )
c2->AI()->MoveInLineOfSight(c1);
}
}
diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp
index 40b9cec6a2a..85b47e17da9 100644
--- a/src/game/Level2.cpp
+++ b/src/game/Level2.cpp
@@ -33,7 +33,7 @@
#include "MapManager.h"
#include "Language.h"
#include "World.h"
-#include "GameEvent.h"
+#include "GameEventMgr.h"
#include "SpellMgr.h"
#include "PoolHandler.h"
#include "AccountMgr.h"
@@ -164,7 +164,7 @@ bool ChatHandler::HandleTargetObjectCommand(const char* args)
{
Player* pl = m_session->GetPlayer();
QueryResult *result;
- GameEvent::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList();
+ GameEventMgr::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList();
if(*args)
{
int32 id = atoi((char*)args);
@@ -187,7 +187,7 @@ bool ChatHandler::HandleTargetObjectCommand(const char* args)
eventFilter << " AND (event IS NULL ";
bool initString = true;
- for (GameEvent::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr)
+ for (GameEventMgr::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr)
{
if (initString)
{
@@ -3509,8 +3509,8 @@ bool ChatHandler::HandleLookupEventCommand(const char* args)
uint32 counter = 0;
- GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
- GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
+ GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
+ GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
for(uint32 id = 0; id < events.size(); ++id )
{
@@ -3543,12 +3543,12 @@ bool ChatHandler::HandleEventActiveListCommand(const char* args)
{
uint32 counter = 0;
- GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
- GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
+ GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
+ GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
char const* active = GetTrinityString(LANG_ACTIVE);
- for(GameEvent::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr )
+ for(GameEventMgr::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr )
{
uint32 event_id = *itr;
GameEventData const& eventData = events[event_id];
@@ -3579,7 +3579,7 @@ bool ChatHandler::HandleEventInfoCommand(const char* args)
uint32 event_id = atoi(cId);
- GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
+ GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
if(event_id >=events.size())
{
@@ -3596,7 +3596,7 @@ bool ChatHandler::HandleEventInfoCommand(const char* args)
return false;
}
- GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
+ GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
bool active = activeEvents.find(event_id) != activeEvents.end();
char const* activeStr = active ? GetTrinityString(LANG_ACTIVE) : "";
@@ -3628,7 +3628,7 @@ bool ChatHandler::HandleEventStartCommand(const char* args)
int32 event_id = atoi(cId);
- GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
+ GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
if(event_id < 1 || event_id >=events.size())
{
@@ -3645,7 +3645,7 @@ bool ChatHandler::HandleEventStartCommand(const char* args)
return false;
}
- GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
+ GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
if(activeEvents.find(event_id) != activeEvents.end())
{
PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id);
@@ -3669,7 +3669,7 @@ bool ChatHandler::HandleEventStopCommand(const char* args)
int32 event_id = atoi(cId);
- GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
+ GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
if(event_id < 1 || event_id >=events.size())
{
@@ -3686,7 +3686,7 @@ bool ChatHandler::HandleEventStopCommand(const char* args)
return false;
}
- GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
+ GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
if(activeEvents.find(event_id) == activeEvents.end())
{
@@ -4119,7 +4119,7 @@ bool ChatHandler::HandleNpcTameCommand(const char* /*args*/)
pet->Relocate (x,y,z,M_PI-player->GetOrientation ());
// set pet to defensive mode by default (some classes can't control controlled pets in fact).
- pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
+ pet->SetReactState(REACT_DEFENSIVE);
// calculate proper level
uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel();
diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
index 781c9d1a0c6..ec487544d2f 100644
--- a/src/game/Level3.cpp
+++ b/src/game/Level3.cpp
@@ -666,6 +666,14 @@ bool ChatHandler::HandleReloadAreaTriggerTeleportCommand(const char*)
return true;
}
+bool ChatHandler::HandleReloadAccessRequirementCommand(const char*)
+{
+ sLog.outString( "Re-Loading Access Requirement definitions..." );
+ objmgr.LoadAccessRequirements();
+ SendGlobalGMSysMessage("DB table `access_requirement` reloaded.");
+ return true;
+ }
+
bool ChatHandler::HandleReloadCommandCommand(const char*)
{
load_command_table = true;
diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp
index da5b4343d24..046fa28f106 100644
--- a/src/game/LootMgr.cpp
+++ b/src/game/LootMgr.cpp
@@ -117,11 +117,18 @@ void LootStore::LoadLootTable()
float chanceOrQuestChance = fields[2].GetFloat();
uint8 group = fields[3].GetUInt8();
int32 mincountOrRef = fields[4].GetInt32();
- uint8 maxcount = fields[5].GetUInt8();
+ uint32 maxcount = fields[5].GetUInt32();
ConditionType condition = (ConditionType)fields[6].GetUInt8();
uint32 cond_value1 = fields[7].GetUInt32();
uint32 cond_value2 = fields[8].GetUInt32();
+ if(maxcount > std::numeric_limits<uint8>::max())
+ {
+ sLog.outErrorDb("Table '%s' entry %d item %d: maxcount value (%u) to large. must be less %u - skipped", GetName(), entry, maxcount,std::numeric_limits<uint8>::max());
+ continue; // error already printed to log/console.
+ }
+
+
if(!PlayerCondition::IsValid(condition,cond_value1, cond_value2))
{
sLog.outErrorDb("... in table '%s' entry %u item %u", GetName(), entry, item);
@@ -251,6 +258,12 @@ bool LootStoreItem::Roll(bool rate) const
// Checks correctness of values
bool LootStoreItem::IsValid(LootStore const& store, uint32 entry) const
{
+ if(group >= 1 << 7) // it stored in 7 bit field
+ {
+ sLog.outErrorDb("Table '%s' entry %d item %d: group (%u) must be less %u - skipped", store.GetName(), entry, itemid, group, 1 << 7);
+ return false;
+ }
+
if (mincountOrRef == 0)
{
sLog.outErrorDb("Table '%s' entry %d item %d: wrong mincountOrRef (%d) - skipped", store.GetName(), entry, itemid, mincountOrRef);
diff --git a/src/game/LootMgr.h b/src/game/LootMgr.h
index 7841a2e0d3b..79d292cf8d4 100644
--- a/src/game/LootMgr.h
+++ b/src/game/LootMgr.h
@@ -65,17 +65,17 @@ struct LootStoreItem
uint32 itemid; // id of the item
float chance; // always positive, chance to drop for both quest and non-quest items, chance to be used for refs
int32 mincountOrRef; // mincount for drop items (positive) or minus referenced TemplateleId (negative)
- uint8 group :8;
+ uint8 group :7;
+ bool needs_quest :1; // quest drop (negative ChanceOrQuestChance in DB)
uint8 maxcount :8; // max drop count for the item (mincountOrRef positive) or Ref multiplicator (mincountOrRef negative)
uint16 conditionId :16; // additional loot condition Id
- bool needs_quest :1; // quest drop (negative ChanceOrQuestChance in DB)
// Constructor, converting ChanceOrQuestChance -> (chance, needs_quest)
// displayid is filled in IsValid() which must be called after
LootStoreItem(uint32 _itemid, float _chanceOrQuestChance, int8 _group, uint8 _conditionId, int32 _mincountOrRef, uint8 _maxcount)
: itemid(_itemid), chance(fabs(_chanceOrQuestChance)), mincountOrRef(_mincountOrRef),
- group(_group), maxcount(_maxcount), conditionId(_conditionId),
- needs_quest(_chanceOrQuestChance < 0) {}
+ group(_group), needs_quest(_chanceOrQuestChance < 0), maxcount(_maxcount), conditionId(_conditionId)
+ {}
bool Roll(bool rate) const; // Checks if the entry takes it's chance (at loot generation)
bool IsValid(LootStore const& store, uint32 entry) const;
diff --git a/src/game/Makefile.am b/src/game/Makefile.am
index 95a2428541d..8482a8874ce 100644
--- a/src/game/Makefile.am
+++ b/src/game/Makefile.am
@@ -115,8 +115,8 @@ libmangosgame_a_SOURCES = \
FleeingMovementGenerator.cpp \
FleeingMovementGenerator.h \
Formulas.h \
- GameEvent.cpp \
- GameEvent.h \
+ GameEventMgr.cpp \
+ GameEventMgr.h \
GameObject.cpp \
GameObject.h \
GlobalEvents.cpp \
diff --git a/src/game/Map.h b/src/game/Map.h
index 17d9953aa19..22f015ad588 100644
--- a/src/game/Map.h
+++ b/src/game/Map.h
@@ -97,12 +97,11 @@ struct CreatureMover
struct InstanceTemplate
{
uint32 map;
- uint32 parent;
- uint32 levelMin;
- uint32 levelMax;
+ uint32 parent;
uint32 maxPlayers;
uint32 maxPlayersHeroic;
uint32 reset_delay; // FIX ME: now exist normal/heroic raids with possible different time of reset.
+ uint32 access_id;
float startLocX;
float startLocY;
float startLocZ;
diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp
index df8521be7d0..b2856b1fb1f 100644
--- a/src/game/MapManager.cpp
+++ b/src/game/MapManager.cpp
@@ -210,14 +210,12 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player)
}
}
- // TODO: move this to a map dependent location
- /*if(i_data && i_data->IsEncounterInProgress())
- {
- sLog.outDebug("MAP: Player '%s' can't enter instance '%s' while an encounter is in progress.", player->GetName(), GetMapName());
- player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT);
- return(false);
- }*/
- return true;
+ // Requirements
+ InstanceTemplate const* instance = objmgr.GetInstanceTemplate(mapid);
+ if(!instance)
+ return false;
+
+ return player->Satisfy(objmgr.GetAccessRequirement(instance->access_id), mapid, true);
}
else
return true;
diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp
index 3a582f96f27..7f48f2c20b8 100644
--- a/src/game/MiscHandler.cpp
+++ b/src/game/MiscHandler.cpp
@@ -856,60 +856,8 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
if(!at)
return;
- if(!GetPlayer()->isGameMaster())
- {
- uint32 missingLevel = 0;
- if(GetPlayer()->getLevel() < at->requiredLevel && !sWorld.getConfig(CONFIG_INSTANCE_IGNORE_LEVEL))
- missingLevel = at->requiredLevel;
-
- // must have one or the other, report the first one that's missing
- uint32 missingItem = 0;
- if(at->requiredItem)
- {
- if(!GetPlayer()->HasItemCount(at->requiredItem, 1) &&
- (!at->requiredItem2 || !GetPlayer()->HasItemCount(at->requiredItem2, 1)))
- missingItem = at->requiredItem;
- }
- else if(at->requiredItem2 && !GetPlayer()->HasItemCount(at->requiredItem2, 1))
- missingItem = at->requiredItem2;
-
- uint32 missingKey = 0;
- uint32 missingHeroicQuest = 0;
- if(GetPlayer()->GetDifficulty() == DIFFICULTY_HEROIC)
- {
- if(at->heroicKey)
- {
- if(!GetPlayer()->HasItemCount(at->heroicKey, 1) &&
- (!at->heroicKey2 || !GetPlayer()->HasItemCount(at->heroicKey2, 1)))
- missingKey = at->heroicKey;
- }
- else if(at->heroicKey2 && !GetPlayer()->HasItemCount(at->heroicKey2, 1))
- missingKey = at->heroicKey2;
-
- if(at->heroicQuest && !GetPlayer()->GetQuestRewardStatus(at->heroicQuest))
- missingHeroicQuest = at->heroicQuest;
- }
-
- uint32 missingQuest = 0;
- if(at->requiredQuest && !GetPlayer()->GetQuestRewardStatus(at->requiredQuest))
- missingQuest = at->requiredQuest;
-
- if(missingLevel || missingItem || missingKey || missingQuest || missingHeroicQuest)
- {
- // TODO: all this is probably wrong
- if(missingItem)
- SendAreaTriggerMessage(GetTrinityString(LANG_LEVEL_MINREQUIRED_AND_ITEM), at->requiredLevel, objmgr.GetItemPrototype(missingItem)->Name1);
- else if(missingKey)
- GetPlayer()->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY, DIFFICULTY_HEROIC);
- else if(missingHeroicQuest)
- SendAreaTriggerMessage(at->heroicQuestFailedText.c_str());
- else if(missingQuest)
- SendAreaTriggerMessage(at->requiredFailedText.c_str());
- else if(missingLevel)
- SendAreaTriggerMessage(GetTrinityString(LANG_LEVEL_MINREQUIRED), missingLevel);
- return;
- }
- }
+ if(!GetPlayer()->Satisfy(objmgr.GetAccessRequirement(at->access_id), at->target_mapId, true))
+ return;
GetPlayer()->TeleportTo(at->target_mapId,at->target_X,at->target_Y,at->target_Z,at->target_Orientation,TELE_TO_NOT_LEAVE_TRANSPORT);
}
diff --git a/src/game/Object.cpp b/src/game/Object.cpp
index ab79ca366e4..62f9c606b6b 100644
--- a/src/game/Object.cpp
+++ b/src/game/Object.cpp
@@ -1603,7 +1603,7 @@ Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, floa
pCreature->SetHomePosition(x, y, z, ang);
pCreature->Summon(spwtype, despwtime);
- if(GetTypeId()==TYPEID_UNIT && ((Creature*)this)->AI())
+ if(GetTypeId()==TYPEID_UNIT && ((Creature*)this)->IsAIEnabled)
((Creature*)this)->AI()->JustSummoned(pCreature);
if(pCreature->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER && pCreature->m_spells[0])
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index 5f7c9ae5b8b..91ead9fc09d 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -37,7 +37,7 @@
#include "Transports.h"
#include "ProgressBar.h"
#include "Language.h"
-#include "GameEvent.h"
+#include "GameEventMgr.h"
#include "Spell.h"
#include "Chat.h"
#include "AccountMgr.h"
@@ -5009,8 +5009,8 @@ void ObjectMgr::LoadAreaTriggerTeleports()
uint32 count = 0;
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13
- QueryResult *result = WorldDatabase.Query("SELECT id, required_level, required_item, required_item2, heroic_key, heroic_key2, heroic_required_quest_done, heroic_required_failed_quest_text, required_quest_done, required_failed_text, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport");
+ // 0 1 2 3 4 5 6
+ QueryResult *result = WorldDatabase.Query("SELECT id, access_id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport");
if( !result )
{
@@ -5037,20 +5037,12 @@ void ObjectMgr::LoadAreaTriggerTeleports()
AreaTrigger at;
- at.requiredLevel = fields[1].GetUInt8();
- at.requiredItem = fields[2].GetUInt32();
- at.requiredItem2 = fields[3].GetUInt32();
- at.heroicKey = fields[4].GetUInt32();
- at.heroicKey2 = fields[5].GetUInt32();
- at.heroicQuest = fields[6].GetUInt32();
- at.heroicQuestFailedText = fields[7].GetCppString();
- at.requiredQuest = fields[8].GetUInt32();
- at.requiredFailedText = fields[9].GetCppString();
- at.target_mapId = fields[10].GetUInt32();
- at.target_X = fields[11].GetFloat();
- at.target_Y = fields[12].GetFloat();
- at.target_Z = fields[13].GetFloat();
- at.target_Orientation = fields[14].GetFloat();
+ at.access_id = fields[1].GetUInt32();
+ at.target_mapId = fields[2].GetUInt32();
+ at.target_X = fields[3].GetFloat();
+ at.target_Y = fields[4].GetFloat();
+ at.target_Z = fields[5].GetFloat();
+ at.target_Orientation = fields[6].GetFloat();
AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID);
if(!atEntry)
@@ -5058,85 +5050,141 @@ void ObjectMgr::LoadAreaTriggerTeleports()
sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",Trigger_ID);
continue;
}
+
+ MapEntry const* mapEntry = sMapStore.LookupEntry(at.target_mapId);
+ if(!mapEntry)
+ {
+ sLog.outErrorDb("Area trigger (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.",Trigger_ID,at.target_mapId);
+ continue;
+ }
- if(at.requiredItem)
+ if(at.target_X==0 && at.target_Y==0 && at.target_Z==0)
{
- ItemPrototype const *pProto = GetItemPrototype(at.requiredItem);
- if(!pProto)
- {
- sLog.outError("Key item %u does not exist for trigger %u, removing key requirement.", at.requiredItem, Trigger_ID);
- at.requiredItem = 0;
- }
+ sLog.outErrorDb("Area trigger (ID:%u) target coordinates not provided.",Trigger_ID);
+ continue;
}
- if(at.requiredItem2)
+
+ mAreaTriggers[Trigger_ID] = at;
+
+ } while( result->NextRow() );
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u area trigger teleport definitions", count );
+}
+
+void ObjectMgr::LoadAccessRequirements()
+{
+ mAccessRequirements.clear(); // need for reload case
+
+ uint32 count = 0;
+
+ // 0 1 2 3 4 5 6 7 8 9 10
+ QueryResult *result = WorldDatabase.Query("SELECT id, level_min, level_max, item, item2, heroic_key, heroic_key2, quest_done, quest_failed_text, heroic_quest_done, heroic_quest_failed_text FROM access_requirement");
+ if( !result )
+ {
+
+ barGoLink bar( 1 );
+
+ bar.step();
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u access requirement definitions", count );
+ return;
+ }
+
+ barGoLink bar( result->GetRowCount() );
+
+ do
+ {
+ Field *fields = result->Fetch();
+
+ bar.step();
+
+ ++count;
+
+ uint32 requiremt_ID = fields[0].GetUInt32();
+
+ AccessRequirement ar;
+
+ ar.levelMin = fields[1].GetUInt8();
+ ar.levelMax = fields[2].GetUInt32();
+ ar.item = fields[3].GetUInt32();
+ ar.item2 = fields[4].GetUInt32();
+ ar.heroicKey = fields[5].GetUInt32();
+ ar.heroicKey2 = fields[6].GetUInt32();
+ ar.quest = fields[7].GetUInt32();
+ ar.questFailedText = fields[8].GetCppString();
+ ar.heroicQuest = fields[9].GetUInt32();
+ ar.heroicQuestFailedText = fields[10].GetCppString();
+
+ if(ar.item)
{
- ItemPrototype const *pProto = GetItemPrototype(at.requiredItem2);
+ ItemPrototype const *pProto = GetItemPrototype(ar.item);
if(!pProto)
{
- sLog.outError("Second item %u not exist for trigger %u, remove key requirement.", at.requiredItem2, Trigger_ID);
- at.requiredItem2 = 0;
+ sLog.outError("Key item %u does not exist for requirement %u, removing key requirement.", ar.item, requiremt_ID);
+ ar.item = 0;
}
}
- if(at.heroicKey)
+ if(ar.item2)
{
- ItemPrototype const *pProto = GetItemPrototype(at.heroicKey);
+ ItemPrototype const *pProto = GetItemPrototype(ar.item2);
if(!pProto)
{
- sLog.outError("Heroic key item %u not exist for trigger %u, remove key requirement.", at.heroicKey, Trigger_ID);
- at.heroicKey = 0;
+ sLog.outError("Second item %u does not exist for requirement %u, removing key requirement.", ar.item2, requiremt_ID);
+ ar.item2 = 0;
}
}
- if(at.heroicKey2)
+ if(ar.heroicKey)
{
- ItemPrototype const *pProto = GetItemPrototype(at.heroicKey2);
+ ItemPrototype const *pProto = GetItemPrototype(ar.heroicKey);
if(!pProto)
{
- sLog.outError("Heroic second key item %u not exist for trigger %u, remove key requirement.", at.heroicKey2, Trigger_ID);
- at.heroicKey2 = 0;
+ sLog.outError("Heroic key %u not exist for trigger %u, remove key requirement.", ar.heroicKey, requiremt_ID);
+ ar.heroicKey = 0;
}
}
- if(at.heroicQuest)
+ if(ar.heroicKey2)
{
- if(!mQuestTemplates[at.heroicQuest])
+ ItemPrototype const *pProto = GetItemPrototype(ar.heroicKey2);
+ if(!pProto)
{
- sLog.outErrorDb("Required Heroic Quest %u not exist for trigger %u, remove heroic quest done requirement.",at.heroicQuest,Trigger_ID);
- at.heroicQuest = 0;
+ sLog.outError("Second heroic key %u not exist for trigger %u, remove key requirement.", ar.heroicKey2, requiremt_ID);
+ ar.heroicKey2 = 0;
}
}
- if(at.requiredQuest)
+ if(ar.heroicQuest)
+ {
+ if(!mQuestTemplates[ar.heroicQuest])
+ {
+ sLog.outErrorDb("Required Heroic Quest %u not exist for trigger %u, remove heroic quest done requirement.",ar.heroicQuest,requiremt_ID);
+ ar.heroicQuest = 0;
+ }
+ }
+
+ if(ar.quest)
{
- if(!mQuestTemplates[at.requiredQuest])
+ if(!mQuestTemplates[ar.quest])
{
- sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",at.requiredQuest,Trigger_ID);
- at.requiredQuest = 0;
+ sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",ar.quest,requiremt_ID);
+ ar.quest = 0;
}
}
- MapEntry const* mapEntry = sMapStore.LookupEntry(at.target_mapId);
- if(!mapEntry)
- {
- sLog.outErrorDb("Area trigger (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.",Trigger_ID,at.target_mapId);
- continue;
- }
-
- if(at.target_X==0 && at.target_Y==0 && at.target_Z==0)
- {
- sLog.outErrorDb("Area trigger (ID:%u) target coordinates not provided.",Trigger_ID);
- continue;
- }
-
- mAreaTriggers[Trigger_ID] = at;
+ mAccessRequirements[requiremt_ID] = ar;
} while( result->NextRow() );
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %u area trigger teleport definitions", count );
+ sLog.outString( ">> Loaded %u access requirement definitions", count );
}
/*
@@ -6896,7 +6944,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
}
case CONDITION_ACTIVE_EVENT:
{
- GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
+ GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
if(value1 >=events.size() || !events[value1].isValid())
{
sLog.outErrorDb("Active event condition requires existed event id (%u), skipped", value1);
diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
index 3946f912b96..b33e2ac26e4 100644
--- a/src/game/ObjectMgr.h
+++ b/src/game/ObjectMgr.h
@@ -101,15 +101,7 @@ extern ScriptMapMap sWaypointScripts;
struct AreaTrigger
{
- uint8 requiredLevel;
- uint32 requiredItem;
- uint32 requiredItem2;
- uint32 heroicKey;
- uint32 heroicKey2;
- uint32 heroicQuest;
- std::string heroicQuestFailedText;
- uint32 requiredQuest;
- std::string requiredFailedText;
+ uint32 access_id;
uint32 target_mapId;
float target_X;
float target_Y;
@@ -327,6 +319,8 @@ class ObjectMgr
typedef UNORDERED_MAP<uint32, uint32> AreaTriggerScriptMap;
+ typedef UNORDERED_MAP<uint32, AccessRequirement> AccessRequirementMap;
+
typedef UNORDERED_MAP<uint32, ReputationOnKillEntry> RepOnKillMap;
typedef UNORDERED_MAP<uint32, PointOfInterest> PointOfInterestMap;
@@ -466,6 +460,14 @@ class ObjectMgr
return NULL;
}
+ AccessRequirement const* GetAccessRequirement(uint32 requirement) const
+ {
+ AccessRequirementMap::const_iterator itr = mAccessRequirements.find( requirement );
+ if( itr != mAccessRequirements.end( ) )
+ return &itr->second;
+ return NULL;
+ }
+
AreaTrigger const* GetGoBackTrigger(uint32 Map) const;
AreaTrigger const* GetMapEntranceTrigger(uint32 Map) const;
@@ -551,6 +553,7 @@ class ObjectMgr
void LoadGossipText();
void LoadAreaTriggerTeleports();
+ void LoadAccessRequirements();
void LoadQuestAreaTriggers();
void LoadAreaTriggerScripts();
void LoadTavernAreaTriggers();
@@ -840,6 +843,7 @@ class ObjectMgr
GossipTextMap mGossipText;
AreaTriggerMap mAreaTriggers;
AreaTriggerScriptMap mAreaTriggerScripts;
+ AccessRequirementMap mAccessRequirements;
RepOnKillMap mRepOnKill;
diff --git a/src/game/OutdoorPvP.cpp b/src/game/OutdoorPvP.cpp
index b48a226d6a4..8aa117b5c4a 100644
--- a/src/game/OutdoorPvP.cpp
+++ b/src/game/OutdoorPvP.cpp
@@ -56,7 +56,7 @@ void OutdoorPvPObjective::HandlePlayerActivityChanged(Player * plr)
{
if(m_CapturePointCreature)
if(Creature * c = HashMapHolder<Creature>::Find(m_CapturePointCreature))
- if(c->AI())
+ if(c->IsAIEnabled)
c->AI()->MoveInLineOfSight(plr);
}
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
index 77851ed6cbc..d722809f4c1 100644
--- a/src/game/Pet.cpp
+++ b/src/game/Pet.cpp
@@ -51,12 +51,12 @@ m_declinedname(NULL)
m_regenTimer = 4000;
// pets always have a charminfo, even if they are not actually charmed
- CharmInfo* charmInfo = InitCharmInfo(this);
+ CharmInfo* charmInfo = InitCharmInfo();
if(type == MINI_PET || type == POSSESSED_PET) // always passive
- charmInfo->SetReactState(REACT_PASSIVE);
+ SetReactState(REACT_PASSIVE);
else if(type == GUARDIAN_PET) // always aggressive
- charmInfo->SetReactState(REACT_AGGRESSIVE);
+ SetReactState(REACT_AGGRESSIVE);
//m_isActive = true;
}
@@ -213,7 +213,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32());
SetCreatorGUID(owner->GetGUID());
- m_charmInfo->SetReactState(ReactStates(fields[6].GetUInt8()));
+ SetReactState( ReactStates( fields[6].GetUInt8() ));
uint32 savedhealth = fields[11].GetUInt32();
uint32 savedmana = fields[12].GetUInt32();
@@ -404,7 +404,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
<< GetNativeDisplayId() << ", "
<< getLevel() << ", "
<< GetUInt32Value(UNIT_FIELD_PETEXPERIENCE) << ", "
- << uint32(m_charmInfo->GetReactState()) << ", "
+ << uint32(GetReactState()) << ", "
<< uint32(GetFreeTalentPoints()) << ", "
<< uint32(mode) << ", '"
<< name.c_str() << "', "
diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp
index 29450b549e1..6f43d511dd0 100644
--- a/src/game/PetAI.cpp
+++ b/src/game/PetAI.cpp
@@ -47,7 +47,6 @@ PetAI::PetAI(Creature *c) : CreatureAI(c), i_pet(*c), i_tracker(TIME_INTERVAL_LO
void PetAI::MoveInLineOfSight(Unit *u)
{
if( !i_pet.getVictim() && i_pet.GetCharmInfo() &&
- i_pet.GetCharmInfo()->HasReactState(REACT_AGGRESSIVE) &&
i_pet.IsHostileTo( u ) && i_pet.canAttack(u) &&
u->isInAccessiblePlaceFor(&i_pet))
{
@@ -181,7 +180,7 @@ void PetAI::UpdateAI(const uint32 diff)
}
else if(owner && i_pet.GetCharmInfo())
{
- if(owner->isInCombat() && !(i_pet.GetCharmInfo()->HasReactState(REACT_PASSIVE) || i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY)))
+ if(owner->isInCombat() && !(i_pet.HasReactState(REACT_PASSIVE) || i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY)))
{
AttackStart(owner->getAttackerForHelper());
}
diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp
index 17c2ba4275b..45fcbbb3219 100644
--- a/src/game/PetHandler.cpp
+++ b/src/game/PetHandler.cpp
@@ -127,7 +127,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
if(pet->GetTypeId() != TYPEID_PLAYER)
{
pet->GetMotionMaster()->Clear();
- if (((Creature*)pet)->AI())
+ if (((Creature*)pet)->IsAIEnabled)
((Creature*)pet)->AI()->AttackStart(TargetUnit);
//10% chance to play special pet attack talk, else growl
@@ -173,7 +173,8 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
case REACT_PASSIVE: //passive
case REACT_DEFENSIVE: //recovery
case REACT_AGGRESSIVE: //activete
- charmInfo->SetReactState( ReactStates(spellid) );
+ if(pet->GetTypeId() == TYPEID_UNIT)
+ ((Creature*)pet)->SetReactState( ReactStates(spellid) );
break;
}
break;
@@ -249,7 +250,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
if (pet->getVictim())
pet->AttackStop();
pet->GetMotionMaster()->Clear();
- if (((Creature*)pet)->AI())
+ if (((Creature*)pet)->IsAIEnabled)
((Creature*)pet)->AI()->AttackStart(unit_target);
}
}
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index cf1e79e687b..1fcfab152c3 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -63,7 +63,7 @@
#include "Database/DatabaseImpl.h"
#include "Spell.h"
#include "SocialMgr.h"
-#include "GameEvent.h"
+#include "GameEventMgr.h"
#include "AchievementMgr.h"
#include <cmath>
@@ -16008,6 +16008,70 @@ void Player::ConvertInstancesToGroup(Player *player, Group *group, uint64 player
if(!player || has_solo) CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%d' AND permanent = 0", GUID_LOPART(player_guid));
}
+bool Player::Satisfy(AccessRequirement const *ar, uint32 target_map, bool report)
+{
+ if(!isGameMaster() && ar)
+ {
+ uint32 LevelMin = 0;
+ if(getLevel() < ar->levelMin && !sWorld.getConfig(CONFIG_INSTANCE_IGNORE_LEVEL))
+ LevelMin = ar->levelMin;
+
+ uint32 LevelMax = 0;
+ if(ar->levelMax >= ar->levelMin && getLevel() > ar->levelMax && !sWorld.getConfig(CONFIG_INSTANCE_IGNORE_LEVEL))
+ LevelMax = ar->levelMax;
+
+ uint32 missingItem = 0;
+ if(ar->item)
+ {
+ if(!HasItemCount(ar->item, 1) &&
+ (!ar->item2 || !HasItemCount(ar->item2, 1)))
+ missingItem = ar->item;
+ }
+ else if(ar->item2 && !HasItemCount(ar->item2, 1))
+ missingItem = ar->item2;
+
+ uint32 missingKey = 0;
+ uint32 missingHeroicQuest = 0;
+ if(GetDifficulty() == DIFFICULTY_HEROIC)
+ {
+ if(ar->heroicKey)
+ {
+ if(!HasItemCount(ar->heroicKey, 1) &&
+ (!ar->heroicKey2 || !HasItemCount(ar->heroicKey2, 1)))
+ missingKey = ar->heroicKey;
+ }
+ else if(ar->heroicKey2 && !HasItemCount(ar->heroicKey2, 1))
+ missingKey = ar->heroicKey2;
+
+ if(ar->heroicQuest && !GetQuestRewardStatus(ar->heroicQuest))
+ missingHeroicQuest = ar->heroicQuest;
+ }
+
+ uint32 missingQuest = 0;
+ if(ar->quest && !GetQuestRewardStatus(ar->quest))
+ missingQuest = ar->quest;
+
+ if(LevelMin || LevelMax || missingItem || missingKey || missingQuest || missingHeroicQuest)
+ {
+ if(report)
+ {
+ if(missingItem)
+ GetSession()->SendAreaTriggerMessage(GetSession()->GetTrinityString(LANG_LEVEL_MINREQUIRED_AND_ITEM), ar->levelMin, objmgr.GetItemPrototype(missingItem)->Name1);
+ else if(missingKey)
+ SendTransferAborted(target_map, TRANSFER_ABORT_DIFFICULTY);
+ else if(missingHeroicQuest)
+ GetSession()->SendAreaTriggerMessage(ar->heroicQuestFailedText.c_str());
+ else if(missingQuest)
+ GetSession()->SendAreaTriggerMessage(ar->questFailedText.c_str());
+ else if(LevelMin)
+ GetSession()->SendAreaTriggerMessage(GetSession()->GetTrinityString(LANG_LEVEL_MINREQUIRED), LevelMin);
+ }
+ return false;
+ }
+ }
+ return true;
+}
+
bool Player::_LoadHomeBind(QueryResult *result)
{
PlayerInfo const *info = objmgr.GetPlayerInfo(getRace(), getClass());
@@ -17163,7 +17227,7 @@ void Player::PetSpellInitialize()
data << uint64(pet->GetGUID());
data << uint32(pet->GetCreatureInfo()->family); // creature family (required for pet talents)
data << uint32(0);
- data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0);
+ data << uint8(pet->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0);
// action bar loop
for(uint32 i = 0; i < 10; i++)
@@ -17300,7 +17364,7 @@ void Player::CharmSpellInitialize()
data << uint32(0x00000000);
data << uint32(0);
if(charm->GetTypeId() != TYPEID_PLAYER)
- data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState());
+ data << uint8(((Creature*)charm)->GetReactState()) << uint8(charmInfo->GetCommandState());
else
data << uint8(0) << uint8(0);
data << uint16(0);
@@ -20581,3 +20645,8 @@ void Player::HandleFall(MovementInfo const& movementInfo)
}
}
}
+
+void Player::UpdateAchievementCriteria( AchievementCriteriaTypes type, uint32 miscvalue1/*=0*/, uint32 miscvalue2/*=0*/, Unit *unit/*=NULL*/, uint32 time/*=0*/ )
+{
+ GetAchievementMgr().UpdateAchievementCriteria(type, miscvalue1,miscvalue2,unit,time);
+} \ No newline at end of file
diff --git a/src/game/Player.h b/src/game/Player.h
index f128dd4d422..b0a5f0e0e5a 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -864,6 +864,20 @@ struct InstancePlayerBind
InstancePlayerBind() : save(NULL), perm(false) {}
};
+struct AccessRequirement
+{
+ uint8 levelMin;
+ uint8 levelMax;
+ uint32 item;
+ uint32 item2;
+ uint32 heroicKey;
+ uint32 heroicKey2;
+ uint32 quest;
+ std::string questFailedText;
+ uint32 heroicQuest;
+ std::string heroicQuestFailedText;
+ };
+
class TRINITY_DLL_SPEC PlayerTaxi
{
public:
@@ -2127,6 +2141,7 @@ class TRINITY_DLL_SPEC Player : public Unit
void SendRaidInfo();
void SendSavedInstances();
static void ConvertInstancesToGroup(Player *player, Group *group = NULL, uint64 player_guid = 0);
+ bool Satisfy(AccessRequirement const*, uint32 target_map, bool report = false);
/*********************************************************/
/*** GROUP SYSTEM ***/
@@ -2166,6 +2181,7 @@ class TRINITY_DLL_SPEC Player : public Unit
void AddRunePower(uint8 index);
void InitRunes();
AchievementMgr& GetAchievementMgr() { return m_achievementMgr; }
+ void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, Unit *unit=NULL, uint32 time=0);
bool HasTitle(uint32 bitIndex);
bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); }
void SetTitle(CharTitlesEntry const* title);
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
index e86f537ab5a..333697926e1 100644
--- a/src/game/SharedDefines.h
+++ b/src/game/SharedDefines.h
@@ -1672,6 +1672,31 @@ enum CreatureEliteType
CREATURE_UNKNOWN = 5 // found in 2.2.3 for 2 mobs
};
+// values based at Holidays.dbc
+enum HolidayIds
+{
+ HOLIDAY_FIREWORKS_SPECTACULAR = 62,
+ HOLIDAY_FEAST_OF_WINTER_VEIL = 141,
+ HOLIDAY_NOBLEGARDEN = 181,
+ HOLIDAY_CHILDRENS_WEEK = 201,
+ HOLIDAY_CALL_TO_ARMS_AV = 283,
+ HOLIDAY_CALL_TO_ARMS_WG = 284,
+ HOLIDAY_CALL_TO_ARMS_AB = 285,
+ HOLIDAY_FISHING_EXTRAVAGANZA = 301,
+ HOLIDAY_HARVEST_FESTIVAL = 321,
+ HOLIDAY_HALLOWS_END = 324,
+ HOLIDAY_LUNAR_FESTIVAL = 327,
+ HOLIDAY_LOVE_IS_IN_THE_AIR = 335,
+ HOLIDAY_FIRE_FESTIVAL = 341,
+ HOLIDAY_CALL_TO_ARMS_ES = 353,
+ HOLIDAY_BREWFEST = 372,
+ HOLIDAY_DARKMOON_FAIRE_ELWYNN = 374,
+ HOLIDAY_DARKMOON_FAIRE_THUNDER = 375,
+ HOLIDAY_DARKMOON_FAIRE_SHATTRATH = 376,
+ HOLIDAY_CALL_TO_ARMS_SA = 400,
+ HOLIDAY_WOTLK_LAUNCH = 406
+};
+
// values based at QuestInfo.dbc
enum QuestTypes
{
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 66f2eded6ac..6d34d29b644 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -1164,10 +1164,10 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
}
}
- if(unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->AI())
+ if(unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->IsAIEnabled)
((Creature*)unit)->AI()->SpellHit(m_caster, m_spellInfo);
- if(m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->AI())
+ if(m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->IsAIEnabled)
((Creature*)m_caster)->AI()->SpellHitTarget(unit, m_spellInfo);
for(ChanceTriggerSpells::const_iterator i = m_ChanceTriggerSpells.begin(); i != m_ChanceTriggerSpells.end(); ++i)
@@ -4251,10 +4251,8 @@ uint8 Spell::CanCast(bool strict)
InstanceTemplate const* instance = ObjectMgr::GetInstanceTemplate(m_caster->GetMapId());
if(!instance)
return SPELL_FAILED_TARGET_NOT_IN_INSTANCE;
- if ( instance->levelMin > target->getLevel() )
- return SPELL_FAILED_LOWLEVEL;
- if ( instance->levelMax && instance->levelMax < target->getLevel() )
- return SPELL_FAILED_HIGHLEVEL;
+ if(!target->Satisfy(objmgr.GetAccessRequirement(instance->access_id), m_caster->GetMapId()))
+ return SPELL_FAILED_BAD_TARGETS;
}
break;
}
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index cf96a3cd19d..91a79b90493 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -1177,7 +1177,7 @@ void Spell::EffectDummy(uint32 i)
pCreature->SetHealth(health);
((Player*)m_caster)->KilledMonster(16992,pCreature->GetGUID());
- if (pCreature->AI())
+ if (pCreature->IsAIEnabled)
pCreature->AI()->AttackStart(m_caster);
return;
@@ -3403,7 +3403,7 @@ void Spell::EffectSummon(uint32 i)
name.append(petTypeSuffix[spawnCreature->getPetType()]);
spawnCreature->SetName( name );
- spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
+ spawnCreature->SetReactState( REACT_DEFENSIVE );
}
void Spell::EffectLearnSpell(uint32 i)
@@ -3618,7 +3618,7 @@ void Spell::EffectPickPocket(uint32 /*i*/)
{
// Reveal action + get attack
m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK);
- if (((Creature*)unitTarget)->AI())
+ if (((Creature*)unitTarget)->IsAIEnabled)
((Creature*)unitTarget)->AI()->AttackStart(m_caster);
}
}
@@ -4231,9 +4231,9 @@ void Spell::EffectSummonPet(uint32 i)
if(m_caster->GetTypeId() == TYPEID_UNIT)
{
if ( ((Creature*)m_caster)->isTotem() )
- pet->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
+ pet->SetReactState(REACT_AGGRESSIVE);
else
- pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
+ pet->SetReactState(REACT_DEFENSIVE);
}
pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
diff --git a/src/game/TemporarySummon.cpp b/src/game/TemporarySummon.cpp
index 147133bd362..f8daff972d8 100644
--- a/src/game/TemporarySummon.cpp
+++ b/src/game/TemporarySummon.cpp
@@ -176,7 +176,7 @@ void TemporarySummon::UnSummon()
AddObjectToRemoveList();
Unit* sum = m_summoner ? ObjectAccessor::GetUnit(*this, m_summoner) : NULL;
- if (sum && sum->GetTypeId() == TYPEID_UNIT && ((Creature*)sum)->AI())
+ if (sum && sum->GetTypeId() == TYPEID_UNIT && ((Creature*)sum)->IsAIEnabled)
{
((Creature*)sum)->AI()->SummonedCreatureDespawn(this);
}
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 6ef78377aff..53d0b06416f 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -75,7 +75,7 @@ static bool procPrepared = InitTriggerAuraData();
Unit::Unit()
: WorldObject(), i_motionMaster(this), m_ThreatManager(this), m_HostilRefManager(this)
-, m_IsInNotifyList(false), m_Notified(false), m_AI_enabled(false)
+, m_IsInNotifyList(false), m_Notified(false), IsAIEnabled(false)
{
m_objectType |= TYPEMASK_UNIT;
m_objectTypeId = TYPEID_UNIT;
@@ -608,7 +608,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
}
//Script Event damage taken
- if( pVictim->GetTypeId()== TYPEID_UNIT && ((Creature *)pVictim)->AI() )
+ if( pVictim->GetTypeId()== TYPEID_UNIT && ((Creature *)pVictim)->IsAIEnabled )
{
((Creature *)pVictim)->AI()->DamageTaken(this, damage);
@@ -920,7 +920,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
if(!getVictim())
/*{
// if have target and damage pVictim just call AI reaction
- if(pVictim != getVictim() && pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI())
+ if(pVictim != getVictim() && pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->IsAIEnabled)
((Creature*)pVictim)->AI()->AttackedBy(this);
}
else*/
@@ -7645,7 +7645,7 @@ bool Unit::Attack(Unit *victim, bool meleeAttack)
m_attacking = victim;
m_attacking->_addAttacker(this);
- //if(m_attacking->GetTypeId()==TYPEID_UNIT && ((Creature*)m_attacking)->AI())
+ //if(m_attacking->GetTypeId()==TYPEID_UNIT && ((Creature*)m_attacking)->IsAIEnabled)
// ((Creature*)m_attacking)->AI()->AttackedBy(this);
if(GetTypeId()==TYPEID_UNIT)
@@ -9472,7 +9472,7 @@ void Unit::CombatStart(Unit* target)
target->SetStandState(UNIT_STAND_STATE_STAND);
if(!target->isInCombat() && target->GetTypeId() != TYPEID_PLAYER
- && !((Creature*)target)->HasReactState(REACT_PASSIVE) && ((Creature*)target)->AI())
+ && !((Creature*)target)->HasReactState(REACT_PASSIVE) && ((Creature*)target)->IsAIEnabled)
((Creature*)target)->AI()->AttackStart(this);
SetInCombatWith(target);
@@ -10109,7 +10109,7 @@ void Unit::TauntApply(Unit* taunter)
return;
SetInFront(taunter);
- if (((Creature*)this)->AI())
+ if (((Creature*)this)->IsAIEnabled)
((Creature*)this)->AI()->AttackStart(taunter);
m_ThreatManager.tauntApply(taunter);
@@ -10133,7 +10133,7 @@ void Unit::TauntFadeOut(Unit *taunter)
if(m_ThreatManager.isThreatListEmpty())
{
- if(((Creature*)this)->AI())
+ if(((Creature*)this)->IsAIEnabled)
((Creature*)this)->AI()->EnterEvadeMode();
return;
}
@@ -10144,7 +10144,7 @@ void Unit::TauntFadeOut(Unit *taunter)
if (target && target != taunter)
{
SetInFront(target);
- if (((Creature*)this)->AI())
+ if (((Creature*)this)->IsAIEnabled)
((Creature*)this)->AI()->AttackStart(target);
}
}
@@ -10988,21 +10988,43 @@ void Unit::CleanupsBeforeDelete()
RemoveFromWorld();
}
-CharmInfo* Unit::InitCharmInfo(Unit *charm)
+CharmInfo* Unit::InitCharmInfo()
{
if(!m_charmInfo)
- m_charmInfo = new CharmInfo(charm);
+ m_charmInfo = new CharmInfo(this);
return m_charmInfo;
}
+void Unit::DeleteCharmInfo()
+{
+ if(!m_charmInfo)
+ return;
+
+ delete m_charmInfo;
+ m_charmInfo = NULL;
+}
+
CharmInfo::CharmInfo(Unit* unit)
-: m_unit(unit), m_CommandState(COMMAND_FOLLOW), m_reactState(REACT_PASSIVE), m_petnumber(0), m_barInit(false)
+: m_unit(unit), m_CommandState(COMMAND_FOLLOW), m_petnumber(0), m_barInit(false)
{
for(int i =0; i<4; ++i)
{
m_charmspells[i].spellId = 0;
m_charmspells[i].active = ACT_DISABLED;
}
+ if(m_unit->GetTypeId() == TYPEID_UNIT)
+ {
+ m_oldReactState = ((Creature*)m_unit)->GetReactState();
+ ((Creature*)m_unit)->SetReactState(REACT_PASSIVE);
+ }
+}
+
+CharmInfo::~CharmInfo()
+{
+ if(m_unit->GetTypeId() == TYPEID_UNIT)
+ {
+ ((Creature*)m_unit)->SetReactState(m_oldReactState);
+ }
}
void CharmInfo::InitPetActionBar()
@@ -11666,7 +11688,7 @@ void Unit::SetFeared(bool apply, uint64 casterGUID, uint32 spellID)
// attack caster if can
Unit* caster = ObjectAccessor::GetObjectInWorld(casterGUID, (Unit*)NULL);
- if(caster && caster != getVictim() && ((Creature*)this)->AI())
+ if(caster && caster != getVictim() && ((Creature*)this)->IsAIEnabled)
((Creature*)this)->AI()->AttackStart(caster);
}
}
@@ -12428,7 +12450,7 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss)
((Player*)pVictim)->GetSession()->SendPacket(&data);
}
// Call KilledUnit for creatures
- if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->AI())
+ if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->IsAIEnabled)
((Creature*)this)->AI()->KilledUnit(pVictim);
// last damage from non duel opponent or opponent controlled creature
@@ -12451,11 +12473,11 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss)
}
// Call KilledUnit for creatures, this needs to be called after the lootable flag is set
- if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->AI())
+ if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->IsAIEnabled)
((Creature*)this)->AI()->KilledUnit(pVictim);
// Call creature just died function
- if (cVictim->AI())
+ if (cVictim->IsAIEnabled)
cVictim->AI()->JustDied(this);
// Dungeon specific stuff, only applies to players killing creatures
@@ -12728,7 +12750,7 @@ void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess)
if(GetTypeId() == TYPEID_UNIT)
{
- ((Creature*)this)->InitPossessedAI();
+ ((Creature*)this)->AI()->OnCharmed(true);
StopMoving();
GetMotionMaster()->Clear(false);
GetMotionMaster()->MoveIdle();
@@ -12743,8 +12765,7 @@ void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess)
// Pets already have a properly initialized CharmInfo, don't overwrite it.
if(GetTypeId() == TYPEID_PLAYER || GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet())
{
- CharmInfo *charmInfo = InitCharmInfo(this);
- charmInfo->SetReactState(REACT_DEFENSIVE);
+ CharmInfo *charmInfo = InitCharmInfo();
if(possess)
charmInfo->InitPossessCreateSpells();
else
@@ -12815,8 +12836,8 @@ void Unit::RemoveCharmedOrPossessedBy(Unit *charmer)
if(!((Creature*)this)->isPet())
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
- ((Creature*)this)->DisablePossessedAI();
- if(isAlive() && ((Creature*)this)->AI())
+ ((Creature*)this)->AI()->OnCharmed(false);
+ if(isAlive() && ((Creature*)this)->IsAIEnabled)
{
if(charmer && !IsFriendlyTo(charmer))
{
@@ -12863,6 +12884,11 @@ void Unit::RemoveCharmedOrPossessedBy(Unit *charmer)
}
}
+ if(GetTypeId() == TYPEID_PLAYER || GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet())
+ {
+ DeleteCharmInfo();
+ }
+
if(possess || charmer->GetTypeId() == TYPEID_PLAYER)
{
// Remove pet spell action bar
diff --git a/src/game/Unit.h b/src/game/Unit.h
index 8d08f793eac..fa5faa4452a 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -778,15 +778,16 @@ struct TRINITY_DLL_SPEC CharmInfo
{
public:
explicit CharmInfo(Unit* unit);
+ ~CharmInfo();
uint32 GetPetNumber() const { return m_petnumber; }
void SetPetNumber(uint32 petnumber, bool statwindow);
void SetCommandState(CommandStates st) { m_CommandState = st; }
CommandStates GetCommandState() { return m_CommandState; }
bool HasCommandState(CommandStates state) { return (m_CommandState == state); }
- void SetReactState(ReactStates st) { m_reactState = st; }
- ReactStates GetReactState() { return m_reactState; }
- bool HasReactState(ReactStates state) { return (m_reactState == state); }
+ //void SetReactState(ReactStates st) { m_reactState = st; }
+ //ReactStates GetReactState() { return m_reactState; }
+ //bool HasReactState(ReactStates state) { return (m_reactState == state); }
void InitPossessCreateSpells();
void InitCharmCreateSpells();
@@ -803,9 +804,12 @@ struct TRINITY_DLL_SPEC CharmInfo
UnitActionBarEntry PetActionBar[10];
CharmSpellEntry m_charmspells[4];
CommandStates m_CommandState;
- ReactStates m_reactState;
+ //ReactStates m_reactState;
uint32 m_petnumber;
bool m_barInit;
+
+ //for restoration after charmed
+ ReactStates m_oldReactState;
};
// for clearing special attacks
@@ -1208,7 +1212,8 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
bool isPossessing(Unit* u) const { return u->isPossessed() && GetCharmGUID() == u->GetGUID(); }
CharmInfo* GetCharmInfo() { return m_charmInfo; }
- CharmInfo* InitCharmInfo(Unit* charm);
+ CharmInfo* InitCharmInfo();
+ void DeleteCharmInfo();
SharedVisionList const& GetSharedVisionList() { return m_sharedVision; }
void AddPlayerToVision(Player* plr);
void RemovePlayerFromVision(Player* plr);
@@ -1539,6 +1544,8 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
}
uint32 GetReducedThreatPercent() { return m_reducedThreatPercent; }
Unit *GetMisdirectionTarget() { return m_misdirectionTargetGUID ? GetUnit(*this, m_misdirectionTargetGUID) : NULL; }
+
+ bool IsAIEnabled;
protected:
explicit Unit ();
@@ -1594,7 +1601,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
ThreatManager m_ThreatManager;
- bool m_AI_enabled;
private:
void SendAttackStop(Unit* victim); // only from AttackStop(Unit*)
//void SendAttackStart(Unit* pVictim); // only from Unit::AttackStart(Unit*)
diff --git a/src/game/World.cpp b/src/game/World.cpp
index 9312667cefc..b1fdec28d69 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -56,7 +56,7 @@
#include "WaypointMovementGenerator.h"
#include "VMapFactory.h"
#include "GlobalEvents.h"
-#include "GameEvent.h"
+#include "GameEventMgr.h"
#include "PoolHandler.h"
#include "Database/DatabaseImpl.h"
#include "GridNotifiersImpl.h"
@@ -1270,7 +1270,10 @@ void World::SetInitialWorldSettings()
spellmgr.LoadSpellAreas();
sLog.outString( "Loading AreaTrigger definitions..." );
- objmgr.LoadAreaTriggerTeleports(); // must be after item template load
+ objmgr.LoadAreaTriggerTeleports();
+
+ sLog.outString( "Loading Access Requirements..." );
+ objmgr.LoadAccessRequirements(); // must be after item template load
sLog.outString( "Loading Quest Area Triggers..." );
objmgr.LoadQuestAreaTriggers(); // must be after LoadQuests
diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp
index 515b17b495b..23a2b8e6cd5 100644
--- a/src/shared/Database/DBCStores.cpp
+++ b/src/shared/Database/DBCStores.cpp
@@ -77,6 +77,7 @@ DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore(GtOCTRegenHPfmt);
//DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore(GtOCTRegenMPfmt); -- not used currently
DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore(GtRegenHPPerSptfmt);
DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore(GtRegenMPPerSptfmt);
+DBCStorage <HolidaysEntry> sHolidaysStore(Holidaysfmt);
DBCStorage <ItemEntry> sItemStore(Itemfmt);
//DBCStorage <ItemCondExtCostsEntry> sItemCondExtCostsStore(ItemCondExtCostsEntryfmt);
//DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); -- not used currently
@@ -195,7 +196,7 @@ void LoadDBCStores(const std::string& dataPath)
{
std::string dbcPath = dataPath+"dbc/";
- const uint32 DBCFilesCount = 72;
+ const uint32 DBCFilesCount = 73;
barGoLink bar( DBCFilesCount );
@@ -268,6 +269,7 @@ void LoadDBCStores(const std::string& dataPath)
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenMPStore, dbcPath,"gtOCTRegenMP.dbc"); -- not used currently
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenHPPerSptStore, dbcPath,"gtRegenHPPerSpt.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenMPPerSptStore, dbcPath,"gtRegenMPPerSpt.dbc");
+ LoadDBC(availableDbcLocales,bar,bad_dbc_files,sHolidaysStore, dbcPath,"Holidays.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemStore, dbcPath,"Item.dbc");
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemDisplayInfoStore, dbcPath,"ItemDisplayInfo.dbc"); -- not used currently
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemCondExtCostsStore, dbcPath,"ItemCondExtCosts.dbc");
diff --git a/src/shared/Database/DBCStores.h b/src/shared/Database/DBCStores.h
index 6b5f5990eea..f915a613b71 100644
--- a/src/shared/Database/DBCStores.h
+++ b/src/shared/Database/DBCStores.h
@@ -169,6 +169,7 @@ extern DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore;
//extern DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore; -- not used currently
extern DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore;
extern DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore;
+extern DBCStorage <HolidaysEntry> sHolidaysStore;
extern DBCStorage <ItemEntry> sItemStore;
//extern DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore; -- not used currently
extern DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore;
diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h
index 073772c7522..8f2fa87e17f 100644
--- a/src/shared/Database/DBCStructure.h
+++ b/src/shared/Database/DBCStructure.h
@@ -359,7 +359,8 @@ struct AchievementCriteriaEntry
// TODO: where is the information about the target stored?
struct
{
- uint32 emoteID; // 3
+ uint32 emoteID; // 3 enum TextEmotes
+ uint32 count; // 4 count of emotes, always required special target or requirements
} do_emote;
// ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13
// ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55
@@ -860,6 +861,40 @@ struct GtRegenMPPerSptEntry
float ratio;
};
+/* no used
+struct HolidayDescriptionsEntry
+{
+ uint32 ID; // 0, this is NOT holiday id
+ //char* name[16] // 1-16 m_name_lang
+ // 17 name flags
+};
+*/
+
+/* no used
+struct HolidayNamesEntry
+{
+ uint32 ID; // 0, this is NOT holiday id
+ //char* name[16] // 1-16 m_name_lang
+ // 17 name flags
+};
+*/
+
+struct HolidaysEntry
+{
+ uint32 ID; // 0, holiday id
+ //uint32 unk1; // 1
+ //uint32 unk2; // 2
+ //uint32 unk3[8] // 3-10, empty fields
+ //uint32 unk11[13] // 11-23, some unknown data (bit strings?)
+ //uint32 unk11[13] // 24-36, some empty fields (continue prev?)
+ //uint32 unk11[12] // 37-48, counters?
+ //uint32 holidayNameId; // 49, id for HolidayNames.dbc
+ //uint32 holidayDescriptionId; // 50, id for HolidayDescriptions.dbc
+ //uint32 unk51; // 51
+ //uint32 unk52; // 52
+ //uint32 unk53; // 53
+};
+
struct ItemEntry
{
uint32 ID; // 0
diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp
index 0420c2b9a85..62a69610ebd 100644
--- a/src/shared/Database/DBCfmt.cpp
+++ b/src/shared/Database/DBCfmt.cpp
@@ -55,6 +55,7 @@ const char GtOCTRegenHPfmt[]="f";
//const char GtOCTRegenMPfmt[]="f";
const char GtRegenHPPerSptfmt[]="f";
const char GtRegenMPPerSptfmt[]="f";
+const char Holidaysfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char Itemfmt[]="nixiiiii";
//const char ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx";
//const char ItemCondExtCostsEntryfmt[]="xiii";
diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp
index 8ffc42dccd3..83649e77641 100644
--- a/src/shared/Database/SQLStorage.cpp
+++ b/src/shared/Database/SQLStorage.cpp
@@ -39,8 +39,8 @@ const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiii";
const char PageTextfmt[]="isi";
const char SpellThreatfmt[]="ii";
-const char InstanceTemplatesrcfmt[]="iiiiiiiffffs";
-const char InstanceTemplatedstfmt[]="iiiiiiiffffi";
+const char InstanceTemplatesrcfmt[]="iiiiiiffffs";
+const char InstanceTemplatedstfmt[]="iiiiiiffffi";
SQLStorage sCreatureStorage(CreatureInfosrcfmt, CreatureInfodstfmt, "entry","creature_template");
SQLStorage sCreatureDataAddonStorage(CreatureDataAddonInfofmt,"guid","creature_addon");
diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h
index ee9321bdae8..d75e85c3f61 100644
--- a/src/shared/revision_nr.h
+++ b/src/shared/revision_nr.h
@@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
- #define REVISION_NR "7389"
+ #define REVISION_NR "7394"
#endif // __REVISION_NR_H__