Weather system changed to that of the previous cores.

Weather system changed to that of the previous cores.

This is part of the current build errors fixes.
This commit is contained in:
Charles A Edwards 2016-02-07 10:45:43 +00:00 committed by Antz
parent 9e94234bdf
commit 165cfba9c4
28 changed files with 1650 additions and 859 deletions

View file

@ -314,7 +314,17 @@ class BattleGround
// Get methods: // Get methods:
ObjectGuid GetObjectGuid() { return ObjectGuid(HIGHGUID_BATTLEGROUND, uint32(m_ArenaType), uint32(m_TypeID)); } ObjectGuid GetObjectGuid() { return ObjectGuid(HIGHGUID_BATTLEGROUND, uint32(m_ArenaType), uint32(m_TypeID)); }
char const* GetName() const { return m_Name; } char const* GetName() const { return m_Name; }
BattleGroundTypeId GetTypeID() const { return m_TypeID; } /**
* @brief
*
* @return BattleGroundTypeId
*/
BattleGroundTypeId GetTypeID(bool GetRandom = false) const { return GetRandom ? m_RandomTypeID : m_TypeID; }
/**
* @brief
*
* @return BattleGroundBracketId
*/
BattleGroundBracketId GetBracketId() const { return m_BracketId; } BattleGroundBracketId GetBracketId() const { return m_BracketId; }
// the instanceId check is also used to determine a bg-template // the instanceId check is also used to determine a bg-template
// that's why the m_map hack is here.. // that's why the m_map hack is here..
@ -581,6 +591,7 @@ class BattleGround
private: private:
/* Battleground */ /* Battleground */
BattleGroundTypeId m_TypeID; BattleGroundTypeId m_TypeID;
BattleGroundTypeId m_RandomTypeID;
BattleGroundStatus m_Status; BattleGroundStatus m_Status;
uint32 m_ClientInstanceID; // the instance-id which is sent to the client and without any other internal use uint32 m_ClientInstanceID; // the instance-id which is sent to the client and without any other internal use
uint32 m_StartTime; uint32 m_StartTime;

View file

@ -1131,10 +1131,12 @@ void BGQueueRemoveEvent::Abort(uint64 /*e_time*/)
/*** BATTLEGROUND MANAGER ***/ /*** BATTLEGROUND MANAGER ***/
/*********************************************************/ /*********************************************************/
BattleGroundMgr::BattleGroundMgr() : m_ArenaTesting(false) BattleGroundMgr::BattleGroundMgr() : m_AutoDistributionTimeChecker(0), m_ArenaTesting(false)
{ {
for (uint8 i = BATTLEGROUND_TYPE_NONE; i < MAX_BATTLEGROUND_TYPE_ID; ++i) for (uint8 i = BATTLEGROUND_TYPE_NONE; i < MAX_BATTLEGROUND_TYPE_ID; ++i)
{
m_BattleGrounds[i].clear(); m_BattleGrounds[i].clear();
}
m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_UINT32_ARENA_RATING_DISCARD_TIMER); m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_UINT32_ARENA_RATING_DISCARD_TIMER);
m_Testing = false; m_Testing = false;
} }
@ -1973,6 +1975,80 @@ void BattleGroundMgr::CreateInitialBattleGrounds()
sLog.outString(">> Loaded %u battlegrounds", count); sLog.outString(">> Loaded %u battlegrounds", count);
} }
void BattleGroundMgr::InitAutomaticArenaPointDistribution()
{
if (sWorld.getConfig(CONFIG_BOOL_ARENA_AUTO_DISTRIBUTE_POINTS))
{
DEBUG_LOG("Initializing Automatic Arena Point Distribution");
QueryResult* result = CharacterDatabase.Query("SELECT NextArenaPointDistributionTime FROM saved_variables");
if (!result)
{
DEBUG_LOG("Battleground: Next arena point distribution time not found in SavedVariables, reseting it now.");
m_NextAutoDistributionTime = time_t(sWorld.GetGameTime() + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY * sWorld.getConfig(CONFIG_UINT32_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS));
CharacterDatabase.PExecute("INSERT INTO saved_variables (NextArenaPointDistributionTime) VALUES ('" UI64FMTD "')", uint64(m_NextAutoDistributionTime));
}
else
{
m_NextAutoDistributionTime = time_t((*result)[0].GetUInt64());
delete result;
}
DEBUG_LOG("Automatic Arena Point Distribution initialized.");
}
}
/*
* there does not appear to be a way to do this in Three
void BattleGroundMgr::DistributeArenaPoints()
{
// used to distribute arena points based on last week's stats
sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_START);
sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_START);
// temporary structure for storing maximum points to add values for all players
std::map<uint32, uint32> PlayerPoints;
// at first update all points for all team members
for (ObjectMgr::ArenaTeamMap::iterator team_itr = sObjectMgr.GetArenaTeamMapBegin(); team_itr != sObjectMgr.GetArenaTeamMapEnd(); ++team_itr)
{
if (ArenaTeam* at = team_itr->second)
{
at->UpdateArenaPointsHelper(PlayerPoints);
}
}
// cycle that gives points to all players
for (std::map<uint32, uint32>::iterator plr_itr = PlayerPoints.begin(); plr_itr != PlayerPoints.end(); ++plr_itr)
{
// update to database
CharacterDatabase.PExecute("UPDATE characters SET arenaPoints = arenaPoints + '%u' WHERE guid = '%u'", plr_itr->second, plr_itr->first);
// add points if player is online
if (Player* pl = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, plr_itr->first)))
pl->ModifyArenaPoints(plr_itr->second);
}
PlayerPoints.clear();
sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_END);
sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_START);
for (ObjectMgr::ArenaTeamMap::iterator titr = sObjectMgr.GetArenaTeamMapBegin(); titr != sObjectMgr.GetArenaTeamMapEnd(); ++titr)
{
if (ArenaTeam* at = titr->second)
{
at->FinishWeek(); // set played this week etc values to 0 in memory, too
at->SaveToDB(); // save changes
at->NotifyStatsChanged(); // notify the players of the changes
}
}
sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_END);
sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_END);
}
*/
void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket* data, ObjectGuid guid, Player* plr, BattleGroundTypeId bgTypeId) void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket* data, ObjectGuid guid, Player* plr, BattleGroundTypeId bgTypeId)
{ {
if (!plr) if (!plr)

View file

@ -42,6 +42,7 @@ typedef UNORDERED_MAP<uint32, BattleGroundTypeId> BattleMastersMap;
typedef UNORDERED_MAP<uint32, BattleGroundEventIdx> CreatureBattleEventIndexesMap; typedef UNORDERED_MAP<uint32, BattleGroundEventIdx> CreatureBattleEventIndexesMap;
typedef UNORDERED_MAP<uint32, BattleGroundEventIdx> GameObjectBattleEventIndexesMap; typedef UNORDERED_MAP<uint32, BattleGroundEventIdx> GameObjectBattleEventIndexesMap;
#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day
#define COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME 10 #define COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME 10
struct GroupQueueInfo; // type predefinition struct GroupQueueInfo; // type predefinition
@ -239,6 +240,8 @@ class BattleGroundMgr
uint32 GetRatingDiscardTimer() const; uint32 GetRatingDiscardTimer() const;
uint32 GetPrematureFinishTime() const; uint32 GetPrematureFinishTime() const;
void InitAutomaticArenaPointDistribution();
// void DistributeArenaPoints(); // there does not appear to be a way to do this in Three
void ToggleArenaTesting(); void ToggleArenaTesting();
void ToggleTesting(); void ToggleTesting();
@ -291,6 +294,8 @@ class BattleGroundMgr
typedef std::set<uint32> ClientBattleGroundIdSet; typedef std::set<uint32> ClientBattleGroundIdSet;
ClientBattleGroundIdSet m_ClientBattleGroundIds[MAX_BATTLEGROUND_TYPE_ID][MAX_BATTLEGROUND_BRACKETS]; // the instanceids just visible for the client ClientBattleGroundIdSet m_ClientBattleGroundIds[MAX_BATTLEGROUND_TYPE_ID][MAX_BATTLEGROUND_BRACKETS]; // the instanceids just visible for the client
uint32 m_NextRatingDiscardUpdate; uint32 m_NextRatingDiscardUpdate;
time_t m_NextAutoDistributionTime;
uint32 m_AutoDistributionTimeChecker;
bool m_ArenaTesting; bool m_ArenaTesting;
bool m_Testing; bool m_Testing;
}; };

View file

@ -4849,33 +4849,29 @@ bool ChatHandler::HandleChangeWeatherCommand(char* args)
if (!ExtractUInt32(&args, type)) if (!ExtractUInt32(&args, type))
return false; return false;
// 0 to 3, 0: fine, 1: rain, 2: snow, 3: sand // see enum WeatherType
if (type > 3) if (!Weather::IsValidWeatherType(type))
{
return false; return false;
}
float grade; float grade;
if (!ExtractFloat(&args, grade)) if (!ExtractFloat(&args, grade))
return false; return false;
// 0 to 1, sending -1 is instand good weather // 0 to 1, sending -1 is instant good weather
if (grade < 0.0f || grade > 1.0f) if (grade < 0.0f || grade > 1.0f)
return false; return false;
Player* player = m_session->GetPlayer(); Player* player = m_session->GetPlayer();
uint32 zoneid = player->GetZoneId(); uint32 zoneId = player->GetZoneId();
if (!sWeatherMgr.GetWeatherChances(zoneId))
Weather* wth = sWorld.FindWeather(zoneid);
if (!wth)
wth = sWorld.AddWeather(zoneid);
if (!wth)
{ {
SendSysMessage(LANG_NO_WEATHER); SendSysMessage(LANG_NO_WEATHER);
SetSentErrorMessage(true); SetSentErrorMessage(true);
return false;
} }
wth->SetWeather(WeatherType(type), grade); player->GetMap()->SetWeather(zoneId, (WeatherType)type, grade, false);
return true; return true;
} }

View file

@ -558,6 +558,33 @@ ArenaType ArenaTeam::GetTypeBySlot(uint8 slot)
return ArenaType(0xFF); return ArenaType(0xFF);
} }
uint32 ArenaTeam::GetPoints(uint32 MemberRating)
{
// returns how many points would be awarded with this team type with this rating
float points;
uint32 rating = MemberRating + 150 < m_stats.rating ? MemberRating : m_stats.rating;
if (rating <= 1500)
{
// As of Season 6 and later, all teams below 1500 rating will earn points as if they were a 1500 rated team
if (sWorld.getConfig(CONFIG_UINT32_ARENA_SEASON_ID) >= 6)
rating = 1500;
points = (float)rating * 0.22f + 14.0f;
}
else
points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating));
// type penalties for <5v5 teams
if (m_Type == ARENA_TYPE_2v2)
points *= 0.76f;
else if (m_Type == ARENA_TYPE_3v3)
points *= 0.88f;
return (uint32)points;
}
bool ArenaTeam::HaveMember(ObjectGuid guid) const bool ArenaTeam::HaveMember(ObjectGuid guid) const
{ {
for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
@ -703,6 +730,35 @@ void ArenaTeam::MemberWon(Player* plr, uint32 againstRating)
} }
} }
void ArenaTeam::UpdateArenaPointsHelper(std::map<uint32, uint32>& PlayerPoints)
{
// called after a match has ended and the stats are already modified
// helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons)
// 10 played games per week is a minimum
if (m_stats.games_week < 10)
return;
// to get points, a player has to participate in at least 30% of the matches
uint32 min_plays = (uint32)ceil(m_stats.games_week * 0.3);
for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
{
// the player participated in enough games, update his points
uint32 points_to_add = 0;
if (itr->games_week >= min_plays)
points_to_add = GetPoints(itr->personal_rating);
// OBSOLETE : CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", points_to_add, m_TeamId, itr->guid);
std::map<uint32, uint32>::iterator plr_itr = PlayerPoints.find(itr->guid.GetCounter());
if (plr_itr != PlayerPoints.end())
{
// check if there is already more points
if (plr_itr->second < points_to_add)
PlayerPoints[itr->guid.GetCounter()] = points_to_add;
}
else
PlayerPoints[itr->guid.GetCounter()] = points_to_add;
}
}
void ArenaTeam::SaveToDB() void ArenaTeam::SaveToDB()
{ {
// save team and member stats to db // save team and member stats to db

View file

@ -200,6 +200,7 @@ class ArenaTeam
void Stats(WorldSession* session); void Stats(WorldSession* session);
void InspectStats(WorldSession* session, ObjectGuid guid); void InspectStats(WorldSession* session, ObjectGuid guid);
uint32 GetPoints(uint32 MemberRating);
float GetChanceAgainst(uint32 own_rating, uint32 enemy_rating); float GetChanceAgainst(uint32 own_rating, uint32 enemy_rating);
int32 WonAgainst(uint32 againstRating); int32 WonAgainst(uint32 againstRating);
void MemberWon(Player* plr, uint32 againstRating); void MemberWon(Player* plr, uint32 againstRating);
@ -207,6 +208,8 @@ class ArenaTeam
void MemberLost(Player* plr, uint32 againstRating); void MemberLost(Player* plr, uint32 againstRating);
void OfflineMemberLost(ObjectGuid guid, uint32 againstRating); void OfflineMemberLost(ObjectGuid guid, uint32 againstRating);
void UpdateArenaPointsHelper(std::map<uint32, uint32> & PlayerPoints);
void NotifyStatsChanged(); void NotifyStatsChanged();
void FinishWeek(); void FinishWeek();

View file

@ -238,6 +238,17 @@ struct CreatureDataAddon
uint32 const* auras; // loaded as char* "spell1 spell2 ... " uint32 const* auras; // loaded as char* "spell1 spell2 ... "
}; };
// Bases values for given Level and UnitClass
struct CreatureClassLvlStats
{
uint32 BaseHealth;
uint32 BaseMana;
float BaseDamage;
float BaseMeleeAttackPower;
float BaseRangedAttackPower;
uint32 BaseArmor;
};
struct CreatureModelInfo struct CreatureModelInfo
{ {
uint32 modelid; uint32 modelid;

View file

@ -868,6 +868,82 @@ void ObjectMgr::LoadCreatureAddons()
sLog.outErrorDb("Creature (GUID: %u) does not exist but has a record in `creature_addon`", addon->guidOrEntry); sLog.outErrorDb("Creature (GUID: %u) does not exist but has a record in `creature_addon`", addon->guidOrEntry);
} }
void ObjectMgr::LoadCreatureClassLvlStats()
{
// initialize data array
memset(&m_creatureClassLvlStats, 0, sizeof(m_creatureClassLvlStats));
std::string queryStr = "SELECT Class, Level, BaseMana, BaseMeleeAttackPower, BaseRangedAttackPower, BaseArmor";
for (int i = 0; i <= MAX_EXPANSION; i++)
{
std::ostringstream str;
str << ", `BaseHealthExp" << i << "`, `BaseDamageExp" << i << "`";
queryStr.append(str.str().c_str());
}
queryStr.append(" FROM `creature_template_classlevelstats` ORDER BY `Class`, `Level`");
QueryResult* result = WorldDatabase.Query(queryStr.c_str());
if (!result)
{
BarGoLink bar(1);
bar.step();
sLog.outString();
sLog.outErrorDb("DB table `creature_template_classlevelstats` is empty.");
return;
}
BarGoLink bar(result->GetRowCount());
uint32 DataCount = 0;
do
{
Field* fields = result->Fetch();
bar.step();
uint32 creatureClass = fields[0].GetUInt32();
uint32 creatureLevel = fields[1].GetUInt32();
if (creatureLevel == 0 || creatureLevel > DEFAULT_MAX_CREATURE_LEVEL)
{
sLog.outErrorDb("Found stats for creature level [%u] with incorrect level. Skipping!", creatureLevel);
continue;
}
if (((1 << (creatureClass - 1)) & CLASSMASK_ALL_CREATURES) == 0)
{
sLog.outErrorDb("Found stats for creature class [%u] with incorrect class. Skipping!", creatureClass);
continue;
}
uint32 baseMana = fields[2].GetUInt32();
float baseMeleeAttackPower = fields[3].GetFloat();
float baseRangedAttackPower = fields[4].GetFloat();
uint32 baseArmor = fields[5].GetUInt32();
for (uint8 i = 0; i <= MAX_EXPANSION; ++i)
{
CreatureClassLvlStats &cCLS = m_creatureClassLvlStats[creatureLevel][classToIndex[creatureClass]][i - 1]; // values should start from 0
cCLS.BaseMana = baseMana;
cCLS.BaseMeleeAttackPower = baseMeleeAttackPower;
cCLS.BaseRangedAttackPower = baseRangedAttackPower;
cCLS.BaseArmor = baseArmor;
cCLS.BaseHealth = fields[6 + (i * 2)].GetUInt32();
cCLS.BaseDamage = fields[7 + (i * 2)].GetFloat();
}
++DataCount;
} while (result->NextRow());
delete result;
sLog.outString();
sLog.outString(">> Loaded %u creature class level stats definitions.", DataCount);
}
void ObjectMgr::LoadEquipmentTemplates() void ObjectMgr::LoadEquipmentTemplates()
{ {
sEquipmentStorage.Load(); sEquipmentStorage.Load();
@ -6993,6 +7069,112 @@ void ObjectMgr::LoadQuestPOI()
sLog.outString(">> Loaded %u quest POI definitions", count); sLog.outString(">> Loaded %u quest POI definitions", count);
} }
void ObjectMgr::LoadDungeonFinderRequirements()
{
uint32 count = 0;
mDungeonFinderRequirementsMap.clear(); // in case of a reload
// 0 1 2 3 4 5 6 7 8
QueryResult* result = WorldDatabase.Query("SELECT mapId, difficulty, min_item_level, item, item_2, alliance_quest, horde_quest, achievement, quest_incomplete_text FROM dungeonfinder_requirements");
if (!result)
{
BarGoLink bar(1);
bar.step();
sLog.outString();
sLog.outErrorDb(">> Loaded 0 dungeon finder requirements. DB table `dungeonfinder_requirements`, is empty!");
return;
}
BarGoLink bar(result->GetRowCount());
do
{
Field* fields = result->Fetch();
bar.step();
uint32 mapId = fields[0].GetUInt32();
uint32 difficulty = fields[1].GetUInt32();
uint32 dungeonKey = MAKE_PAIR32(mapId, difficulty); // for unique key
uint32 minItemLevel = fields[2].GetUInt32();
uint32 item = fields[3].GetUInt32();
uint32 item2 = fields[4].GetUInt32();
uint32 allianceQuest = fields[5].GetUInt32();
uint32 hordeQuest = fields[6].GetUInt32();
uint32 achievement = fields[7].GetUInt32();
const char* questText = fields[8].GetString();
// check that items, quests, & achievements are real
if (item)
{
ItemEntry const* dbcitem = sItemStore.LookupEntry(item);
if (!dbcitem)
{
sLog.outString();
sLog.outErrorDb("Table `dungeonfinder_requirements` has invalid item entry %u for map %u ! Removing requirement.", item, mapId);
item = 0;
}
}
if (item2)
{
ItemEntry const* dbcitem = sItemStore.LookupEntry(item2);
if (!dbcitem)
{
sLog.outString();
sLog.outErrorDb("Table `dungeonfinder_requirements` has invalid item entry %u for map %u ! Removing requirement.", item2, mapId);
item2 = 0;
}
}
if (allianceQuest)
{
QuestMap::iterator qReqItr = mQuestTemplates.find(allianceQuest);
if (qReqItr == mQuestTemplates.end())
{
sLog.outString();
sLog.outErrorDb("Table `dungeonfinder_requirements` has invalid quest requirement %u for map %u ! Removing requirement.", allianceQuest, mapId);
allianceQuest = 0;
}
}
if (hordeQuest)
{
QuestMap::iterator qReqItr = mQuestTemplates.find(hordeQuest);
if (qReqItr == mQuestTemplates.end())
{
sLog.outString();
sLog.outErrorDb("Table `dungeonfinder_requirements` has invalid quest requirement %u for map %u ! Removing requirement.", hordeQuest, mapId);
hordeQuest = 0;
}
}
if (achievement)
{
if (!sAchievementStore.LookupEntry(achievement))
{
sLog.outString();
sLog.outErrorDb("Table `dungeonfinder_requirements` has invalid achievement %u for map %u ! Removing requirement.", achievement, mapId);
achievement = 0;
}
}
// add to map after checks
DungeonFinderRequirements requirement(minItemLevel, item, item2, allianceQuest, hordeQuest, achievement, questText);
mDungeonFinderRequirementsMap[dungeonKey] = requirement;
++count;
} while (result->NextRow());
delete result;
sLog.outString();
sLog.outString(">> Loaded %u Dungeon Finder Requirements", count);
}
void ObjectMgr::LoadNPCSpellClickSpells() void ObjectMgr::LoadNPCSpellClickSpells()
{ {
uint32 count = 0; uint32 count = 0;
@ -7100,68 +7282,57 @@ void ObjectMgr::GetConditions(uint32 conditionId, std::vector<PlayerCondition co
out.push_back(condition); out.push_back(condition);
} }
void ObjectMgr::LoadWeatherZoneChances() static char SERVER_SIDE_SPELL[] = "MaNGOS server-side spell";
struct SQLSpellLoader : public SQLStorageLoaderBase<SQLSpellLoader, SQLHashStorage>
{ {
uint32 count = 0; template<class S, class D>
void default_fill(uint32 field_pos, S src, D& dst)
// 0 1 2 3 4 5 6 7 8 9 10 11 12
QueryResult* result = WorldDatabase.Query("SELECT zone, spring_rain_chance, spring_snow_chance, spring_storm_chance, summer_rain_chance, summer_snow_chance, summer_storm_chance, fall_rain_chance, fall_snow_chance, fall_storm_chance, winter_rain_chance, winter_snow_chance, winter_storm_chance FROM game_weather");
if (!result)
{ {
BarGoLink bar(1); if (field_pos == LOADED_SPELLDBC_FIELD_POS_EQUIPPED_ITEM_CLASS)
dst = D(-1);
bar.step(); else
dst = D(src);
sLog.outString();
sLog.outErrorDb(">> Loaded 0 weather definitions. DB table `game_weather` is empty.");
return;
} }
BarGoLink bar(result->GetRowCount()); void default_fill_to_str(uint32 field_pos, char const* /*src*/, char * & dst)
do
{ {
Field* fields = result->Fetch(); if (field_pos == LOADED_SPELLDBC_FIELD_POS_SPELLNAME_0)
bar.step();
uint32 zone_id = fields[0].GetUInt32();
WeatherZoneChances& wzc = mWeatherZoneMap[zone_id];
for (int season = 0; season < WEATHER_SEASONS; ++season)
{ {
wzc.data[season].rainChance = fields[season * (MAX_WEATHER_TYPE - 1) + 1].GetUInt32(); dst = SERVER_SIDE_SPELL;
wzc.data[season].snowChance = fields[season * (MAX_WEATHER_TYPE - 1) + 2].GetUInt32(); }
wzc.data[season].stormChance = fields[season * (MAX_WEATHER_TYPE - 1) + 3].GetUInt32(); else
{
if (wzc.data[season].rainChance > 100) dst = new char[1];
{ *dst = 0;
wzc.data[season].rainChance = 25;
sLog.outErrorDb("Weather for zone %u season %u has wrong rain chance > 100%%", zone_id, season);
}
if (wzc.data[season].snowChance > 100)
{
wzc.data[season].snowChance = 25;
sLog.outErrorDb("Weather for zone %u season %u has wrong snow chance > 100%%", zone_id, season);
}
if (wzc.data[season].stormChance > 100)
{
wzc.data[season].stormChance = 25;
sLog.outErrorDb("Weather for zone %u season %u has wrong storm chance > 100%%", zone_id, season);
}
} }
++count;
} }
while (result->NextRow()); };
delete result; void ObjectMgr::LoadSpellTemplate()
{
SQLSpellLoader loader;
loader.Load(sSpellTemplate);
sLog.outString(">> Loaded %u spell definitions", sSpellTemplate.GetRecordCount());
sLog.outString(); sLog.outString();
sLog.outString(">> Loaded %u weather definitions", count);
for (uint32 i = 1; i < sSpellTemplate.GetMaxEntry(); ++i)
{
// check data correctness
SpellEntry const* spellEntry = sSpellTemplate.LookupEntry<SpellEntry>(i);
if (!spellEntry)
continue;
// insert serverside spell data
if (sSpellStore.GetNumRows() <= i)
{
sLog.outErrorDb("Loading Spell Template for spell %u, index out of bounds (max = %u)", i, sSpellStore.GetNumRows());
continue;
}
else
sSpellStore.InsertEntry(const_cast<SpellEntry*>(spellEntry), i);
}
} }
void ObjectMgr::DeleteCreatureData(uint32 guid) void ObjectMgr::DeleteCreatureData(uint32 guid)
@ -7737,7 +7908,7 @@ bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min
{ {
data.SoundId = fields[10].GetUInt32(); data.SoundId = fields[10].GetUInt32();
data.Type = fields[11].GetUInt32(); data.Type = fields[11].GetUInt32();
data.Language = fields[12].GetUInt32(); data.LanguageId = (Language)fields[12].GetUInt32();
data.Emote = fields[13].GetUInt32(); data.Emote = fields[13].GetUInt32();
if (data.SoundId && !sSoundEntriesStore.LookupEntry(data.SoundId)) if (data.SoundId && !sSoundEntriesStore.LookupEntry(data.SoundId))
@ -7746,10 +7917,10 @@ bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min
data.SoundId = 0; data.SoundId = 0;
} }
if (!GetLanguageDescByID(data.Language)) if (!GetLanguageDescByID(data.LanguageId))
{ {
_DoStringError(entry, "Entry %i in table `%s` using Language %u but Language does not exist.", entry, table, data.Language); _DoStringError(entry, "Entry %i in table `%s` using Language %u but Language does not exist.", entry, table, data.LanguageId);
data.Language = LANG_UNIVERSAL; data.LanguageId = LANG_UNIVERSAL;
} }
if (data.Type > CHAT_TYPE_ZONE_YELL) if (data.Type > CHAT_TYPE_ZONE_YELL)
@ -10107,10 +10278,10 @@ bool DoDisplayText(WorldObject* source, int32 entry, Unit const* target /*=NULL*
switch (data->Type) switch (data->Type)
{ {
case CHAT_TYPE_SAY: case CHAT_TYPE_SAY:
source->MonsterSay(entry, data->Language, target); source->MonsterSay(entry, data->LanguageId, target);
break; break;
case CHAT_TYPE_YELL: case CHAT_TYPE_YELL:
source->MonsterYell(entry, data->Language, target); source->MonsterYell(entry, data->LanguageId, target);
break; break;
case CHAT_TYPE_TEXT_EMOTE: case CHAT_TYPE_TEXT_EMOTE:
source->MonsterTextEmote(entry, target); source->MonsterTextEmote(entry, target);
@ -10141,7 +10312,7 @@ bool DoDisplayText(WorldObject* source, int32 entry, Unit const* target /*=NULL*
break; break;
} }
case CHAT_TYPE_ZONE_YELL: case CHAT_TYPE_ZONE_YELL:
source->MonsterYellToZone(entry, data->Language, target); source->MonsterYellToZone(entry, data->LanguageId, target);
break; break;
} }

View file

@ -141,12 +141,12 @@ static_assert(MAX_DB_SCRIPT_STRING_ID < ACE_INT32_MAX, "Must scope with int32 ra
struct MangosStringLocale struct MangosStringLocale
{ {
MangosStringLocale() : SoundId(0), Type(0), Language(0), Emote(0) { } MangosStringLocale() : SoundId(0), Type(0), LanguageId(LANG_UNIVERSAL), Emote(0) { }
std::vector<std::string> Content; // 0 -> default, i -> i-1 locale index std::vector<std::string> Content; // 0 -> default, i -> i-1 locale index
uint32 SoundId; uint32 SoundId;
uint8 Type; uint8 Type;
uint32 Language; Language LanguageId;
uint32 Emote; // 0 -> default, i -> i-1 locale index uint32 Emote; // 0 -> default, i -> i-1 locale index
}; };
@ -333,19 +333,6 @@ struct QuestPOI
typedef std::vector<QuestPOI> QuestPOIVector; typedef std::vector<QuestPOI> QuestPOIVector;
typedef UNORDERED_MAP<uint32, QuestPOIVector> QuestPOIMap; typedef UNORDERED_MAP<uint32, QuestPOIVector> QuestPOIMap;
#define WEATHER_SEASONS 4
struct WeatherSeasonChances
{
uint32 rainChance;
uint32 snowChance;
uint32 stormChance;
};
struct WeatherZoneChances
{
WeatherSeasonChances data[WEATHER_SEASONS];
};
struct DungeonEncounter struct DungeonEncounter
{ {
DungeonEncounter(DungeonEncounterEntry const* _dbcEntry, EncounterCreditType _creditType, uint32 _creditEntry, uint32 _lastEncounterDungeon) DungeonEncounter(DungeonEncounterEntry const* _dbcEntry, EncounterCreditType _creditType, uint32 _creditEntry, uint32 _lastEncounterDungeon)
@ -359,6 +346,51 @@ struct DungeonEncounter
typedef std::multimap<uint32, DungeonEncounter const*> DungeonEncounterMap; typedef std::multimap<uint32, DungeonEncounter const*> DungeonEncounterMap;
typedef std::pair<DungeonEncounterMap::const_iterator, DungeonEncounterMap::const_iterator> DungeonEncounterMapBounds; typedef std::pair<DungeonEncounterMap::const_iterator, DungeonEncounterMap::const_iterator> DungeonEncounterMapBounds;
struct DungeonFinderRequirements
{
uint32 minItemLevel;
uint32 item;
uint32 item2;
uint32 allianceQuestId;
uint32 hordeQuestId;
uint32 achievement;
const char* questIncompleteText;
DungeonFinderRequirements()
: minItemLevel(0), item(0), item2(0), allianceQuestId(0), hordeQuestId(0), achievement(0) {}
DungeonFinderRequirements(uint32 MinItemLevel, uint32 Item, uint32 Item2, uint32 AllianceQuestId,
uint32 HordeQuestId, uint32 Achievement, const char* QuestIncompleteText)
: minItemLevel(MinItemLevel), item(Item), item2(Item2), allianceQuestId(AllianceQuestId),
hordeQuestId(HordeQuestId), achievement(Achievement), questIncompleteText(QuestIncompleteText) {}
};
struct DungeonFinderRewards
{
uint32 baseXPReward;
int32 baseMonetaryReward;
DungeonFinderRewards() : baseXPReward(0), baseMonetaryReward(0) {}
DungeonFinderRewards(uint32 BaseXPReward, int32 BaseMonetaryReward) : baseXPReward(BaseXPReward), baseMonetaryReward(BaseMonetaryReward) {}
};
struct DungeonFinderItems
{
// sorted by auto-incrementing id
uint32 minLevel;
uint32 maxLevel;
uint32 itemReward;
uint32 itemAmount;
uint32 dungeonType;
DungeonFinderItems() : minLevel(0), maxLevel(0), itemReward(0), itemAmount(0), dungeonType(0) {}
DungeonFinderItems(uint32 MinLevel, uint32 MaxLevel, uint32 ItemReward, uint32 ItemAmount, uint32 DungeonType)
: minLevel(MinLevel), maxLevel(MaxLevel), itemReward(ItemReward), itemAmount(ItemAmount), dungeonType(DungeonType) {}
};
typedef UNORDERED_MAP<uint32, DungeonFinderRequirements> DungeonFinderRequirementsMap;
typedef UNORDERED_MAP<uint32, DungeonFinderRewards> DungeonFinderRewardsMap;
typedef UNORDERED_MAP<uint32, DungeonFinderItems> DungeonFinderItemsMap;
struct GraveYardData struct GraveYardData
{ {
uint32 safeLocId; uint32 safeLocId;
@ -548,8 +580,6 @@ class ObjectMgr
typedef UNORDERED_MAP<uint32, PointOfInterest> PointOfInterestMap; typedef UNORDERED_MAP<uint32, PointOfInterest> PointOfInterestMap;
typedef UNORDERED_MAP<uint32, WeatherZoneChances> WeatherZoneMap;
void LoadGameobjectInfo(); void LoadGameobjectInfo();
void AddGameobjectInfo(GameObjectInfo* goinfo); void AddGameobjectInfo(GameObjectInfo* goinfo);
@ -713,6 +743,7 @@ class ObjectMgr
void LoadCreatureTemplates(); void LoadCreatureTemplates();
void LoadCreatures(); void LoadCreatures();
void LoadCreatureAddons(); void LoadCreatureAddons();
void LoadCreatureClassLvlStats();
void LoadCreatureModelInfo(); void LoadCreatureModelInfo();
void LoadCreatureModelRace(); void LoadCreatureModelRace();
void LoadEquipmentTemplates(); void LoadEquipmentTemplates();
@ -759,10 +790,14 @@ class ObjectMgr
void LoadPointsOfInterest(); void LoadPointsOfInterest();
void LoadQuestPOI(); void LoadQuestPOI();
void LoadDungeonFinderRequirements();
void LoadDungeonFinderRewards();
void LoadDungeonFinderItems();
void LoadNPCSpellClickSpells(); void LoadNPCSpellClickSpells();
void LoadSpellTemplate();
void LoadCreatureTemplateSpells(); void LoadCreatureTemplateSpells();
void LoadWeatherZoneChances();
void LoadGameTele(); void LoadGameTele();
void LoadNpcGossips(); void LoadNpcGossips();
@ -826,15 +861,6 @@ class ObjectMgr
return NULL; return NULL;
} }
WeatherZoneChances const* GetWeatherChances(uint32 zone_id) const
{
WeatherZoneMap::const_iterator itr = mWeatherZoneMap.find(zone_id);
if (itr != mWeatherZoneMap.end())
return &itr->second;
else
return NULL;
}
CreatureDataPair const* GetCreatureDataPair(uint32 guid) const CreatureDataPair const* GetCreatureDataPair(uint32 guid) const
{ {
CreatureDataMap::const_iterator itr = mCreatureDataMap.find(guid); CreatureDataMap::const_iterator itr = mCreatureDataMap.find(guid);
@ -1217,7 +1243,9 @@ class ObjectMgr
QuestPOIMap mQuestPOIMap; QuestPOIMap mQuestPOIMap;
WeatherZoneMap mWeatherZoneMap; DungeonFinderRequirementsMap mDungeonFinderRequirementsMap;
DungeonFinderRewardsMap mDungeonFinderRewardsMap;
DungeonFinderItemsMap mDungeonFinderItemsMap;
// character reserved names // character reserved names
typedef std::set<std::wstring> ReservedNamesMap; typedef std::set<std::wstring> ReservedNamesMap;
@ -1277,6 +1305,9 @@ class ObjectMgr
HalfNameMap PetHalfName0; HalfNameMap PetHalfName0;
HalfNameMap PetHalfName1; HalfNameMap PetHalfName1;
// Array to store creature stats, Max creature level + 1 (for data alignement with in game level)
CreatureClassLvlStats m_creatureClassLvlStats[DEFAULT_MAX_CREATURE_LEVEL + 1][MAX_CREATURE_CLASS][MAX_EXPANSION + 1];
MapObjectGuids mMapObjectGuids; MapObjectGuids mMapObjectGuids;
CreatureDataMap mCreatureDataMap; CreatureDataMap mCreatureDataMap;
CreatureLocaleMap mCreatureLocaleMap; CreatureLocaleMap mCreatureLocaleMap;

View file

@ -74,6 +74,9 @@
#include "Vehicle.h" #include "Vehicle.h"
#include "Calendar.h" #include "Calendar.h"
#include "PhaseMgr.h" #include "PhaseMgr.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /*ENABLE_ELUNA*/
#include <cmath> #include <cmath>
@ -1944,6 +1947,13 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
return true; return true;
} }
void Player::SetRandomWinner(bool isWinner)
{
m_IsBGRandomWinner = isWinner;
if (m_IsBGRandomWinner)
CharacterDatabase.PExecute("INSERT INTO character_battleground_random (guid) VALUES ('%u')", GetGUIDLow());
}
bool Player::TeleportToBGEntryPoint() bool Player::TeleportToBGEntryPoint()
{ {
ScheduleDelayedOperation(DELAYED_BG_MOUNT_RESTORE); ScheduleDelayedOperation(DELAYED_BG_MOUNT_RESTORE);
@ -6898,8 +6908,6 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
if (!zone) if (!zone)
return; return;
phaseMgr->AddUpdateFlag(PHASE_UPDATE_FLAG_ZONE_UPDATE);
if (m_zoneUpdateId != newZone) if (m_zoneUpdateId != newZone)
{ {
// handle outdoor pvp zones // handle outdoor pvp zones
@ -6910,17 +6918,16 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
if (sWorld.getConfig(CONFIG_BOOL_WEATHER)) if (sWorld.getConfig(CONFIG_BOOL_WEATHER))
{ {
if (Weather* wth = sWorld.FindWeather(zone->ID)) Weather* wth = GetMap()->GetWeatherSystem()->FindOrCreateWeather(newZone);
wth->SendWeatherUpdateToPlayer(this); wth->SendWeatherUpdateToPlayer(this);
else if (!sWorld.AddWeather(zone->ID))
{
// send fine weather packet to remove old zone's weather
Weather::SendFineWeatherUpdateToPlayer(this);
}
} }
} }
m_zoneUpdateId = newZone; #ifdef ENABLE_ELUNA
sEluna->OnUpdateZone(this, newZone, newArea);
#endif
m_zoneUpdateId = newZone;
m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL; m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL;
// zone changed, so area changed as well, update it // zone changed, so area changed as well, update it
@ -6930,19 +6937,19 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
// in PvE, only opposition team capital // in PvE, only opposition team capital
switch (zone->team) switch (zone->team)
{ {
case AREATEAM_ALLY: case AREATEAM_ALLY:
pvpInfo.inHostileArea = GetTeam() != ALLIANCE && (sWorld.IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL); pvpInfo.inHostileArea = GetTeam() != ALLIANCE && (sWorld.IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
break; break;
case AREATEAM_HORDE: case AREATEAM_HORDE:
pvpInfo.inHostileArea = GetTeam() != HORDE && (sWorld.IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL); pvpInfo.inHostileArea = GetTeam() != HORDE && (sWorld.IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
break; break;
case AREATEAM_NONE: case AREATEAM_NONE:
// overwrite for battlegrounds, maybe batter some zone flags but current known not 100% fit to this // overwrite for battlegrounds, maybe batter some zone flags but current known not 100% fit to this
pvpInfo.inHostileArea = sWorld.IsPvPRealm() || InBattleGround(); pvpInfo.inHostileArea = sWorld.IsPvPRealm() || InBattleGround();
break; break;
default: // 6 in fact default: // 6 in fact
pvpInfo.inHostileArea = false; pvpInfo.inHostileArea = false;
break; break;
} }
if (pvpInfo.inHostileArea) // in hostile area if (pvpInfo.inHostileArea) // in hostile area
@ -6990,8 +6997,6 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
UpdateZoneDependentAuras(); UpdateZoneDependentAuras();
UpdateZoneDependentPets(); UpdateZoneDependentPets();
phaseMgr->RemoveUpdateFlag(PHASE_UPDATE_FLAG_ZONE_UPDATE);
} }
// If players are too far way of duel flag... then player loose the duel // If players are too far way of duel flag... then player loose the duel
@ -14056,18 +14061,6 @@ void Player::CompleteQuest(uint32 quest_id)
} }
} }
void Player::IncompleteQuest(uint32 quest_id)
{
if (quest_id)
{
SetQuestStatus(quest_id, QUEST_STATUS_INCOMPLETE);
uint16 log_slot = FindQuestSlot(quest_id);
if (log_slot < MAX_QUEST_LOG_SIZE)
RemoveQuestSlotState(log_slot, QUEST_STATE_COMPLETE);
}
}
void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver, bool announce) void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver, bool announce)
{ {
uint32 quest_id = pQuest->GetQuestId(); uint32 quest_id = pQuest->GetQuestId();
@ -14075,7 +14068,9 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
{ {
if (pQuest->ReqItemId[i]) if (pQuest->ReqItemId[i])
{
DestroyItemCount(pQuest->ReqItemId[i], pQuest->ReqItemCount[i], true); DestroyItemCount(pQuest->ReqItemId[i], pQuest->ReqItemCount[i], true);
}
} }
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
@ -14088,18 +14083,13 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
} }
} }
// take currency
for (uint32 i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
{
if (pQuest->ReqCurrencyId[i])
ModifyCurrencyCount(pQuest->ReqCurrencyId[i], -int32(pQuest->ReqCurrencyCount[i] * GetCurrencyPrecision(pQuest->ReqCurrencyId[i])));
}
RemoveTimedQuest(quest_id); RemoveTimedQuest(quest_id);
if (BattleGround* bg = GetBattleGround()) if (BattleGround* bg = GetBattleGround())
if (bg->GetTypeID() == BATTLEGROUND_AV) if (bg->GetTypeID(true) == BATTLEGROUND_AV)
{
((BattleGroundAV*)bg)->HandleQuestComplete(pQuest->GetQuestId(), this); ((BattleGroundAV*)bg)->HandleQuestComplete(pQuest->GetQuestId(), this);
}
if (pQuest->GetRewChoiceItemsCount() > 0) if (pQuest->GetRewChoiceItemsCount() > 0)
{ {
@ -14134,7 +14124,9 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
uint16 log_slot = FindQuestSlot(quest_id); uint16 log_slot = FindQuestSlot(quest_id);
if (log_slot < MAX_QUEST_LOG_SIZE) if (log_slot < MAX_QUEST_LOG_SIZE)
{
SetQuestSlot(log_slot, 0); SetQuestSlot(log_slot, 0);
}
QuestStatusData& q_status = mQuestStatus[quest_id]; QuestStatusData& q_status = mQuestStatus[quest_id];
@ -14143,7 +14135,7 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
if (getLevel() < sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL)) if (getLevel() < sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL))
{ {
GiveXP(xp , NULL); GiveXP(xp, NULL);
// Give player extra money (for max level already included in pQuest->GetRewMoneyMaxLevel()) // Give player extra money (for max level already included in pQuest->GetRewMoneyMaxLevel())
if (pQuest->GetRewOrReqMoney() > 0) if (pQuest->GetRewOrReqMoney() > 0)
@ -14155,10 +14147,10 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
else else
{ {
// reward money for max level already included in pQuest->GetRewMoneyMaxLevel() // reward money for max level already included in pQuest->GetRewMoneyMaxLevel()
uint64 money = uint32(pQuest->GetRewMoneyMaxLevel() * sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_MONEY)); uint32 money = uint32(pQuest->GetRewMoneyMaxLevel() * sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_MONEY));
// reward money used if > xp replacement money // reward money used if > xp replacement money
if (pQuest->GetRewOrReqMoney() > int64(money)) if (pQuest->GetRewOrReqMoney() > int32(money))
money = pQuest->GetRewOrReqMoney(); money = pQuest->GetRewOrReqMoney();
ModifyMoney(money); ModifyMoney(money);
@ -14169,16 +14161,9 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
if (pQuest->GetRewOrReqMoney() < 0) if (pQuest->GetRewOrReqMoney() < 0)
ModifyMoney(pQuest->GetRewOrReqMoney()); ModifyMoney(pQuest->GetRewOrReqMoney());
// reward currency // honor reward
for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) if (uint32 honor = pQuest->CalculateRewardHonor(getLevel()))
{ RewardHonor(NULL, 0, honor);
if (pQuest->RewCurrencyId[i])
ModifyCurrencyCount(pQuest->RewCurrencyId[i], int32(pQuest->RewCurrencyCount[i] * GetCurrencyPrecision(pQuest->RewCurrencyId[i])));
}
// reward skill
if (uint32 skill = pQuest->GetRewSkill())
UpdateSkill(skill, pQuest->GetRewSkillValue());
// title reward // title reward
if (pQuest->GetCharTitleId()) if (pQuest->GetCharTitleId())
@ -14219,18 +14204,18 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
q_status.uState = QUEST_CHANGED; q_status.uState = QUEST_CHANGED;
if (announce) if (announce)
SendQuestReward(pQuest, xp, questGiver); SendQuestReward(pQuest, xp);
bool handled = false; bool handled = false;
switch (questGiver->GetTypeId()) switch (questGiver->GetTypeId())
{ {
case TYPEID_UNIT: case TYPEID_UNIT:
handled = sScriptMgr.OnQuestRewarded(this, (Creature*)questGiver, pQuest); handled = sScriptMgr.OnQuestRewarded(this, reinterpret_cast<Creature*>(questGiver), pQuest, reward);
break; break;
case TYPEID_GAMEOBJECT: case TYPEID_GAMEOBJECT:
handled = sScriptMgr.OnQuestRewarded(this, (GameObject*)questGiver, pQuest); handled = sScriptMgr.OnQuestRewarded(this, reinterpret_cast<GameObject*>(questGiver), pQuest, reward);
break; break;
} }
if (!handled && pQuest->GetQuestCompleteScript() != 0) if (!handled && pQuest->GetQuestCompleteScript() != 0)
@ -14248,8 +14233,6 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, pQuest->GetQuestId()); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, pQuest->GetQuestId());
UpdateForQuestWorldObjects();
// remove auras from spells with quest reward state limitations // remove auras from spells with quest reward state limitations
// Some spells applied at quest reward // Some spells applied at quest reward
uint32 zone, area; uint32 zone, area;
@ -14266,11 +14249,18 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
saBounds = sSpellMgr.GetSpellAreaForAreaMapBounds(0); saBounds = sSpellMgr.GetSpellAreaForAreaMapBounds(0);
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
itr->second->ApplyOrRemoveSpellIfCan(this, zone, area, false); itr->second->ApplyOrRemoveSpellIfCan(this, zone, area, false);
}
PhaseUpdateData phaseUdateData; void Player::IncompleteQuest(uint32 quest_id)
phaseUdateData.AddQuestUpdate(quest_id); {
if (quest_id)
{
SetQuestStatus(quest_id, QUEST_STATUS_INCOMPLETE);
phaseMgr->NotifyConditionChanged(phaseUdateData); uint16 log_slot = FindQuestSlot(quest_id);
if (log_slot < MAX_QUEST_LOG_SIZE)
RemoveQuestSlotState(log_slot, QUEST_STATE_COMPLETE);
}
} }
void Player::FailQuest(uint32 questId) void Player::FailQuest(uint32 questId)
@ -15418,7 +15408,34 @@ void Player::SendQuestCompleteEvent(uint32 quest_id)
} }
} }
void Player::SendQuestReward(Quest const* pQuest, uint32 XP, Object* /*questGiver*/) void Player::SendQuestReward(Quest const* pQuest, uint32 XP)
{
uint32 questid = pQuest->GetQuestId();
DEBUG_LOG("WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", questid);
WorldPacket data(SMSG_QUESTGIVER_QUEST_COMPLETE, (4 + 4 + 4 + 4 + 4));
data << uint32(questid);
if (getLevel() < sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL))
{
data << uint32(XP);
data << uint32(pQuest->GetRewOrReqMoney());
}
else
{
data << uint32(0);
data << uint32(pQuest->GetRewOrReqMoney() + int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_MONEY)));
}
data << uint32(10 * MaNGOS::Honor::hk_honor_at_level(getLevel(), pQuest->GetRewHonorAddition()));
data << uint32(pQuest->GetBonusTalents()); // bonus talents
data << uint32(0); // arena points
GetSession()->SendPacket(&data);
}
// Delete this if the above works
// the above was added for deve21 (chucky)
//void Player::SendQuestReward(Quest const* pQuest, uint32 XP, Object* /*questGiver*/)
/*
{ {
uint32 questid = pQuest->GetQuestId(); uint32 questid = pQuest->GetQuestId();
DEBUG_LOG("WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", questid); DEBUG_LOG("WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", questid);
@ -15436,7 +15453,6 @@ void Player::SendQuestReward(Quest const* pQuest, uint32 XP, Object* /*questGive
data << uint32(pQuest->GetRewOrReqMoney() + int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_MONEY))); data << uint32(pQuest->GetRewOrReqMoney() + int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getConfig(CONFIG_FLOAT_RATE_DROP_MONEY)));
data << uint32(0); data << uint32(0);
} }
data << uint32(questid); data << uint32(questid);
data << uint32(pQuest->GetRewSkill()); data << uint32(pQuest->GetRewSkill());
@ -15445,6 +15461,7 @@ void Player::SendQuestReward(Quest const* pQuest, uint32 XP, Object* /*questGive
GetSession()->SendPacket(&data); GetSession()->SendPacket(&data);
} }
*/
void Player::SendQuestFailed(uint32 quest_id, InventoryResult reason) void Player::SendQuestFailed(uint32 quest_id, InventoryResult reason)
{ {

View file

@ -1047,6 +1047,8 @@ class Player : public Unit
bool TeleportToBGEntryPoint(); bool TeleportToBGEntryPoint();
void SetRandomWinner(bool isWinner);
void SetSummonPoint(uint32 mapid, float x, float y, float z) void SetSummonPoint(uint32 mapid, float x, float y, float z)
{ {
m_summon_expire = time(NULL) + MAX_PLAYER_SUMMON_DELAY; m_summon_expire = time(NULL) + MAX_PLAYER_SUMMON_DELAY;
@ -1364,7 +1366,7 @@ class Player : public Unit
void AddQuest(Quest const* pQuest, Object* questGiver); void AddQuest(Quest const* pQuest, Object* questGiver);
void CompleteQuest(uint32 quest_id); void CompleteQuest(uint32 quest_id);
void IncompleteQuest(uint32 quest_id); void IncompleteQuest(uint32 quest_id);
void RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver, bool announce = true); void RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver, bool announce);
void FailQuest(uint32 quest_id); void FailQuest(uint32 quest_id);
bool SatisfyQuestSkill(Quest const* qInfo, bool msg) const; bool SatisfyQuestSkill(Quest const* qInfo, bool msg) const;
@ -1449,7 +1451,8 @@ class Player : public Unit
bool CanShareQuest(uint32 quest_id) const; bool CanShareQuest(uint32 quest_id) const;
void SendQuestCompleteEvent(uint32 quest_id); void SendQuestCompleteEvent(uint32 quest_id);
void SendQuestReward(Quest const* pQuest, uint32 XP, Object* questGiver); void SendQuestReward(Quest const* pQuest, uint32 XP);
// void SendQuestReward(Quest const* pQuest, uint32 XP, Object* questGiver); // delete this if the above works (chucky)
void SendQuestFailed(uint32 quest_id, InventoryResult reason = EQUIP_ERR_OK); void SendQuestFailed(uint32 quest_id, InventoryResult reason = EQUIP_ERR_OK);
void SendQuestTimerFailed(uint32 quest_id); void SendQuestTimerFailed(uint32 quest_id);
void SendCanTakeQuestResponse(uint32 msg) const; void SendCanTakeQuestResponse(uint32 msg) const;
@ -2192,6 +2195,8 @@ class Player : public Unit
// returns true if the player is in active state for capture point capturing // returns true if the player is in active state for capture point capturing
bool CanUseCapturePoint(); bool CanUseCapturePoint();
bool m_IsBGRandomWinner;
/*********************************************************/ /*********************************************************/
/*** REST SYSTEM ***/ /*** REST SYSTEM ***/
/*********************************************************/ /*********************************************************/

View file

@ -129,7 +129,7 @@ enum EUnitFields
UNIT_FIELD_HOVERHEIGHT = OBJECT_END + 0x87, UNIT_FIELD_HOVERHEIGHT = OBJECT_END + 0x87,
UNIT_FIELD_MAXITEMLEVEL = OBJECT_END + 0x88, UNIT_FIELD_MAXITEMLEVEL = OBJECT_END + 0x88,
UNIT_FIELD_PADDING = OBJECT_END + 0x89, UNIT_FIELD_PADDING = OBJECT_END + 0x89,
UNIT_END = OBJECT_END + 0x8A UNIT_END = OBJECT_END + 0x008E,
}; };
enum EItemFields enum EItemFields

View file

@ -2095,6 +2095,11 @@ struct SpellEntry
bool IsFitToFamilyMask(SpellFamily family, T t) const; bool IsFitToFamilyMask(SpellFamily family, T t) const;
}; };
// A few fields which are required for automated convertion
// NOTE that these fields are count by _skipping_ the fields that are unused!
#define LOADED_SPELLDBC_FIELD_POS_EQUIPPED_ITEM_CLASS 65 // Must be converted to -1
#define LOADED_SPELLDBC_FIELD_POS_SPELLNAME_0 132 // Links to "MaNGOS server-side spell"
struct SpellCastTimesEntry struct SpellCastTimesEntry
{ {
uint32 ID; // 0 m_ID uint32 ID; // 0 m_ID

View file

@ -42,6 +42,9 @@ const char WorldTemplatesrcfmt[] = "is";
const char WorldTemplatedstfmt[] = "ii"; const char WorldTemplatedstfmt[] = "ii";
const char ConditionsSrcFmt[] = "iiii"; const char ConditionsSrcFmt[] = "iiii";
const char ConditionsDstFmt[] = "iiii"; const char ConditionsDstFmt[] = "iiii";
const char SpellTemplatesrcfmt[] = "iiiiiiiiiiiiiiiix";
// 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 185
const char SpellTemplatedstfmt[] = "ixxxiiiixxxxxxxxxxxxxxxxxxxxxxxxiixxxxixxxxxxFxxxxxxxxxxxxxxxxxxxxxxixxxxxFFFxxxxxxixxixxixxixxxxxFFFxxxxxxixxixxixxFFFxxxxxxxxxxxxxppppppppppppppppppppppppppppppppxxxxxxxxxxxFFFxxxxxx";
const char VehicleAccessorySrcFmt[] = "iiix"; const char VehicleAccessorySrcFmt[] = "iiix";
const char VehicleAccessoryDstFmt[] = "iii"; const char VehicleAccessoryDstFmt[] = "iii";
const char CreatureTemplateSpellsFmt[] = "iiiiiiiiiii"; const char CreatureTemplateSpellsFmt[] = "iiiiiiiiiii";
@ -60,6 +63,7 @@ SQLStorage sConditionStorage(ConditionsSrcFmt, ConditionsDstFmt, "condition_entr
SQLHashStorage sGameObjectDataAddonStorage(GameObjectInfoAddonInfofmt, "guid", "gameobject_addon"); SQLHashStorage sGameObjectDataAddonStorage(GameObjectInfoAddonInfofmt, "guid", "gameobject_addon");
SQLHashStorage sGOStorage(GameObjectInfosrcfmt, GameObjectInfodstfmt, "entry", "gameobject_template"); SQLHashStorage sGOStorage(GameObjectInfosrcfmt, GameObjectInfodstfmt, "entry", "gameobject_template");
SQLHashStorage sSpellTemplate(SpellTemplatesrcfmt, SpellTemplatedstfmt, "id", "spell_template");
SQLHashStorage sCreatureTemplateSpellsStorage(CreatureTemplateSpellsFmt, "entry", "creature_template_spells"); SQLHashStorage sCreatureTemplateSpellsStorage(CreatureTemplateSpellsFmt, "entry", "creature_template_spells");
SQLMultiStorage sVehicleAccessoryStorage(VehicleAccessorySrcFmt, VehicleAccessoryDstFmt, "vehicle_entry", "vehicle_accessory"); SQLMultiStorage sVehicleAccessoryStorage(VehicleAccessorySrcFmt, VehicleAccessoryDstFmt, "vehicle_entry", "vehicle_accessory");

View file

@ -39,6 +39,7 @@ extern SQLStorage sInstanceTemplate;
extern SQLStorage sWorldTemplate; extern SQLStorage sWorldTemplate;
extern SQLStorage sConditionStorage; extern SQLStorage sConditionStorage;
extern SQLHashStorage sSpellTemplate;
extern SQLHashStorage sGOStorage; extern SQLHashStorage sGOStorage;
extern SQLHashStorage sGameObjectDataAddonStorage; extern SQLHashStorage sGameObjectDataAddonStorage;
extern SQLHashStorage sCreatureTemplateSpellsStorage; extern SQLHashStorage sCreatureTemplateSpellsStorage;

View file

@ -113,6 +113,11 @@ enum Classes
(1<<(CLASS_DEATH_KNIGHT-1)) ) (1<<(CLASS_DEATH_KNIGHT-1)) )
#define CLASSMASK_ALL_CREATURES ((1<<(CLASS_WARRIOR-1)) | (1<<(CLASS_PALADIN-1)) | (1<<(CLASS_ROGUE-1)) | (1<<(CLASS_MAGE-1)) ) #define CLASSMASK_ALL_CREATURES ((1<<(CLASS_WARRIOR-1)) | (1<<(CLASS_PALADIN-1)) | (1<<(CLASS_ROGUE-1)) | (1<<(CLASS_MAGE-1)) )
#define MAX_CREATURE_CLASS 4
// array index could be used to store class data only Warrior, Paladin, Rogue and Mage are indexed for creature
// W P R M
static const uint8 classToIndex[MAX_CLASSES] = { 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0 };
#define CLASSMASK_WAND_USERS ((1<<(CLASS_PRIEST-1))|(1<<(CLASS_MAGE-1))|(1<<(CLASS_WARLOCK-1))) #define CLASSMASK_WAND_USERS ((1<<(CLASS_PRIEST-1))|(1<<(CLASS_MAGE-1))|(1<<(CLASS_WARLOCK-1)))
@ -3774,7 +3779,16 @@ enum MaxLevel
static const MaxLevel maxLevelForExpansion[MAX_EXPANSION + 1] = { MAX_LEVEL_CLASSIC, MAX_LEVEL_TBC, MAX_LEVEL_WOTLK, MAX_LEVEL_CATACLYSM }; static const MaxLevel maxLevelForExpansion[MAX_EXPANSION + 1] = { MAX_LEVEL_CLASSIC, MAX_LEVEL_TBC, MAX_LEVEL_WOTLK, MAX_LEVEL_CATACLYSM };
// Max creature level (included some bosses and elite)
#define DEFAULT_MAX_CREATURE_LEVEL 85
// This spell is used for general boarding serverside // This spell is used for general boarding serverside
#define SPELL_RIDE_VEHICLE_HARDCODED 46598 #define SPELL_RIDE_VEHICLE_HARDCODED 46598
enum TeleportLocation
{
TELEPORT_LOCATION_HOMEBIND = 0,
TELEPORT_LOCATION_BG_ENTRY_POINT = 1,
};
#endif #endif

View file

@ -742,12 +742,13 @@ enum MangosStrings
LANG_DEBUG_ARENA_OFF = 738, LANG_DEBUG_ARENA_OFF = 738,
LANG_DEBUG_BG_ON = 739, LANG_DEBUG_BG_ON = 739,
LANG_DEBUG_BG_OFF = 740, LANG_DEBUG_BG_OFF = 740,
// = 741, not used
// = 742, not used LANG_DIST_ARENA_POINTS_START = 741,
// = 743, not used LANG_DIST_ARENA_POINTS_ONLINE_START = 742,
// = 744, not used LANG_DIST_ARENA_POINTS_ONLINE_END = 743,
// = 745, not used LANG_DIST_ARENA_POINTS_TEAM_START = 744,
// = 746, not used LANG_DIST_ARENA_POINTS_TEAM_END = 745,
LANG_DIST_ARENA_POINTS_END = 746,
// = 747, not used // = 747, not used
// = 748, not used // = 748, not used
// = 749, not used // = 749, not used

View file

@ -45,16 +45,27 @@
#include "BattleGround/BattleGroundMgr.h" #include "BattleGround/BattleGroundMgr.h"
#include "Weather.h" #include "Weather.h"
#include "Calendar.h" #include "Calendar.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /* ENABLE_ELUNA */
Map::~Map() Map::~Map()
{ {
#ifdef ENABLE_ELUNA
sEluna->OnDestroy(this);
#endif /* ENABLE_ELUNA */
UnloadAll(true); UnloadAll(true);
if (!m_scriptSchedule.empty()) if (!m_scriptSchedule.empty())
{
sScriptMgr.DecreaseScheduledScriptCount(m_scriptSchedule.size()); sScriptMgr.DecreaseScheduledScriptCount(m_scriptSchedule.size());
}
if (m_persistentState) if (m_persistentState)
m_persistentState->SetUsedByMapState(NULL); // field pointer can be deleted after this {
m_persistentState->SetUsedByMapState(NULL);
} // field pointer can be deleted after this
delete i_data; delete i_data;
i_data = NULL; i_data = NULL;
@ -64,7 +75,12 @@ Map::~Map()
// release reference count // release reference count
if (m_TerrainData->Release()) if (m_TerrainData->Release())
{
sTerrainMgr.UnloadTerrain(m_TerrainData->GetMapId()); sTerrainMgr.UnloadTerrain(m_TerrainData->GetMapId());
}
delete m_weatherSystem;
m_weatherSystem = NULL;
} }
void Map::LoadMapAndVMap(int gx, int gy) void Map::LoadMapAndVMap(int gx, int gy)
@ -667,8 +683,7 @@ Map::Remove(T* obj, bool remove)
} }
} }
void void Map::PlayerRelocation(Player* player, float x, float y, float z, float orientation)
Map::PlayerRelocation(Player* player, float x, float y, float z, float orientation)
{ {
MANGOS_ASSERT(player); MANGOS_ASSERT(player);
@ -788,7 +803,9 @@ bool Map::UnloadGrid(const uint32& x, const uint32& y, bool pForce)
{ {
if (!pForce && ActiveObjectsNearGrid(x, y)) if (!pForce && ActiveObjectsNearGrid(x, y))
{
return false; return false;
}
DEBUG_FILTER_LOG(LOG_FILTER_MAP_LOADING, "Unloading grid[%u,%u] for map %u", x, y, i_id); DEBUG_FILTER_LOG(LOG_FILTER_MAP_LOADING, "Unloading grid[%u,%u] for map %u", x, y, i_id);
ObjectGridUnloader unloader(*grid); ObjectGridUnloader unloader(*grid);
@ -1927,7 +1944,7 @@ class StaticMonsterChatBuilder
* @param language language of the text * @param language language of the text
* @param target, can be NULL * @param target, can be NULL
*/ */
void Map::MonsterYellToMap(ObjectGuid guid, int32 textId, uint32 language, Unit const* target) const void Map::MonsterYellToMap(ObjectGuid guid, int32 textId, Language language, Unit const* target) const
{ {
if (guid.IsAnyTypeCreature()) if (guid.IsAnyTypeCreature())
{ {
@ -1958,14 +1975,16 @@ void Map::MonsterYellToMap(ObjectGuid guid, int32 textId, uint32 language, Unit
* @param senderLowGuid provide way proper show yell for near spawned creature with known lowguid, * @param senderLowGuid provide way proper show yell for near spawned creature with known lowguid,
* 0 accepted by client else if this not important * 0 accepted by client else if this not important
*/ */
void Map::MonsterYellToMap(CreatureInfo const* cinfo, int32 textId, uint32 language, Unit const* target, uint32 senderLowGuid /*= 0*/) const void Map::MonsterYellToMap(CreatureInfo const* cinfo, int32 textId, Language language, Unit const* target, uint32 senderLowGuid /*= 0*/) const
{ {
StaticMonsterChatBuilder say_build(cinfo, CHAT_MSG_MONSTER_YELL, textId, language, target, senderLowGuid); StaticMonsterChatBuilder say_build(cinfo, CHAT_MSG_MONSTER_YELL, textId, language, target, senderLowGuid);
MaNGOS::LocalizedPacketDo<StaticMonsterChatBuilder> say_do(say_build); MaNGOS::LocalizedPacketDo<StaticMonsterChatBuilder> say_do(say_build);
Map::PlayerList const& pList = GetPlayers(); Map::PlayerList const& pList = GetPlayers();
for (PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr) for (PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
{
say_do(itr->getSource()); say_do(itr->getSource());
}
} }
/** /**

View file

@ -102,197 +102,217 @@ enum LevelRequirementVsMode
class Map : public GridRefManager<NGridType> class Map : public GridRefManager<NGridType>
{ {
friend class MapReference; friend class MapReference;
friend class ObjectGridLoader; friend class ObjectGridLoader;
friend class ObjectWorldLoader; friend class ObjectWorldLoader;
protected: protected:
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode); Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode);
public: public:
virtual ~Map(); virtual ~Map();
// currently unused for normal maps // currently unused for normal maps
bool CanUnload(uint32 diff) bool CanUnload(uint32 diff)
{ {
if (!m_unloadTimer) return false; if (!m_unloadTimer) { return false; }
if (m_unloadTimer <= diff) return true; if (m_unloadTimer <= diff) { return true; }
m_unloadTimer -= diff; m_unloadTimer -= diff;
return false; return false;
} }
virtual bool Add(Player*); virtual bool Add(Player*);
virtual void Remove(Player*, bool); virtual void Remove(Player*, bool);
template<class T> void Add(T*); template<class T> void Add(T*);
template<class T> void Remove(T*, bool); template<class T> void Remove(T*, bool);
static void DeleteFromWorld(Player* player); // player object will deleted at call static void DeleteFromWorld(Player* player); // player object will deleted at call
virtual void Update(const uint32&); virtual void Update(const uint32&);
void MessageBroadcast(Player const*, WorldPacket*, bool to_self); void MessageBroadcast(Player const*, WorldPacket*, bool to_self);
void MessageBroadcast(WorldObject const*, WorldPacket*); void MessageBroadcast(WorldObject const*, WorldPacket*);
void MessageDistBroadcast(Player const*, WorldPacket*, float dist, bool to_self, bool own_team_only = false); void MessageDistBroadcast(Player const*, WorldPacket*, float dist, bool to_self, bool own_team_only = false);
void MessageDistBroadcast(WorldObject const*, WorldPacket*, float dist); void MessageDistBroadcast(WorldObject const*, WorldPacket*, float dist);
float GetVisibilityDistance() const { return m_VisibleDistance; } float GetVisibilityDistance() const { return m_VisibleDistance; }
// function for setting up visibility distance for maps on per-type/per-Id basis // function for setting up visibility distance for maps on per-type/per-Id basis
virtual void InitVisibilityDistance(); virtual void InitVisibilityDistance();
void PlayerRelocation(Player*, float x, float y, float z, float angl); void PlayerRelocation(Player*, float x, float y, float z, float angl);
void CreatureRelocation(Creature* creature, float x, float y, float z, float orientation); void CreatureRelocation(Creature* creature, float x, float y, float z, float orientation);
template<class T, class CONTAINER> void Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER> &visitor); template<class T, class CONTAINER> void Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER>& visitor);
bool IsRemovalGrid(float x, float y) const bool IsRemovalGrid(float x, float y) const
{ {
GridPair p = MaNGOS::ComputeGridPair(x, y); GridPair p = MaNGOS::ComputeGridPair(x, y);
return (!getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL); return(!getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL);
} }
bool IsLoaded(float x, float y) const bool IsLoaded(float x, float y) const
{ {
GridPair p = MaNGOS::ComputeGridPair(x, y); GridPair p = MaNGOS::ComputeGridPair(x, y);
return loaded(p); return loaded(p);
} }
bool GetUnloadLock(const GridPair& p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); } bool GetUnloadLock(const GridPair& p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); }
void SetUnloadLock(const GridPair& p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); } void SetUnloadLock(const GridPair& p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); }
void LoadGrid(const Cell& cell, bool no_unload = false); void LoadGrid(const Cell& cell, bool no_unload = false);
bool UnloadGrid(const uint32& x, const uint32& y, bool pForce); bool UnloadGrid(const uint32& x, const uint32& y, bool pForce);
virtual void UnloadAll(bool pForce); virtual void UnloadAll(bool pForce);
void ResetGridExpiry(NGridType& grid, float factor = 1) const void ResetGridExpiry(NGridType& grid, float factor = 1) const
{ {
grid.ResetTimeTracker((time_t)((float)i_gridExpiry * factor)); grid.ResetTimeTracker((time_t)((float)i_gridExpiry * factor));
} }
time_t GetGridExpiry(void) const { return i_gridExpiry; } time_t GetGridExpiry(void) const { return i_gridExpiry; }
uint32 GetId(void) const { return i_id; } uint32 GetId(void) const { return i_id; }
// some calls like isInWater should not use vmaps due to processor power // some calls like isInWater should not use vmaps due to processor power
// can return INVALID_HEIGHT if under z+2 z coord not found height // can return INVALID_HEIGHT if under z+2 z coord not found height
virtual void RemoveAllObjectsInRemoveList(); virtual void RemoveAllObjectsInRemoveList();
bool CreatureRespawnRelocation(Creature* c); // used only in CreatureRelocation and ObjectGridUnloader bool CreatureRespawnRelocation(Creature* c); // used only in CreatureRelocation and ObjectGridUnloader
bool CheckGridIntegrity(Creature* c, bool moved) const; bool CheckGridIntegrity(Creature* c, bool moved) const;
uint32 GetInstanceId() const { return i_InstanceId; } uint32 GetInstanceId() const { return i_InstanceId; }
virtual bool CanEnter(Player* player); virtual bool CanEnter(Player* player);
const char* GetMapName() const; const char* GetMapName() const;
// have meaning only for instanced map (that have set real difficulty), NOT USE its for BaseMap // have meaning only for instanced map (that have set real difficulty), NOT USE its for BaseMap
// _currently_ spawnmode == difficulty, but this can be changes later, so use appropriate spawnmode/difficult functions // _currently_ spawnmode == difficulty, but this can be changes later, so use appropriate spawnmode/difficult functions
// for simplify later code support // for simplify later code support
// regular difficulty = continent/dungeon normal/first raid normal difficulty // regular difficulty = continent/dungeon normal/first raid normal difficulty
uint8 GetSpawnMode() const { return (i_spawnMode); } uint8 GetSpawnMode() const { return (i_spawnMode); }
Difficulty GetDifficulty() const { return Difficulty(GetSpawnMode()); } Difficulty GetDifficulty() const { return Difficulty(GetSpawnMode()); }
bool IsRegularDifficulty() const { return GetDifficulty() == REGULAR_DIFFICULTY; } bool IsRegularDifficulty() const { return GetDifficulty() == REGULAR_DIFFICULTY; }
uint32 GetMaxPlayers() const; // dependent from map difficulty uint32 GetMaxPlayers() const; // dependent from map difficulty
uint32 GetMaxResetDelay() const; // dependent from map difficulty uint32 GetMaxResetDelay() const; // dependent from map difficulty
MapDifficultyEntry const* GetMapDifficulty() const; // dependent from map difficulty MapDifficultyEntry const* GetMapDifficulty() const; // dependent from map difficulty
bool Instanceable() const { return i_mapEntry && i_mapEntry->Instanceable(); } bool Instanceable() const { return i_mapEntry && i_mapEntry->Instanceable(); }
// NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable // NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable
bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); } bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); }
bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); } bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); }
bool IsNonRaidDungeon() const { return i_mapEntry && i_mapEntry->IsNonRaidDungeon(); } bool IsHeroic() const { return IsRaid() ? i_spawnMode >= RAID_DIFFICULTY_10MAN_HEROIC : i_spawnMode >= DUNGEON_DIFFICULTY_HEROIC; }
bool IsRaidOrHeroicDungeon() const { return IsRaid() || GetDifficulty() > DUNGEON_DIFFICULTY_NORMAL; } bool IsNonRaidDungeon() const { return i_mapEntry && i_mapEntry->IsNonRaidDungeon(); }
bool IsHeroic() const { return IsRaid() || i_spawnMode >= DUNGEON_DIFFICULTY_HEROIC; } bool IsRaidOrHeroicDungeon() const { return IsRaid() || GetDifficulty() > DUNGEON_DIFFICULTY_NORMAL; }
bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); } bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); }
bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); } bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); }
bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); } bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); }
// can't be NULL for loaded map // can't be NULL for loaded map
MapPersistentState* GetPersistentState() const { return m_persistentState; } MapPersistentState* GetPersistentState() const { return m_persistentState; }
void AddObjectToRemoveList(WorldObject* obj); void AddObjectToRemoveList(WorldObject* obj);
void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair); void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair);
void resetMarkedCells() { marked_cells.reset(); } void resetMarkedCells() { marked_cells.reset(); }
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); } bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); }
void markCell(uint32 pCellId) { marked_cells.set(pCellId); } void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
bool HavePlayers() const { return !m_mapRefManager.isEmpty(); } bool HavePlayers() const { return !m_mapRefManager.isEmpty(); }
uint32 GetPlayersCountExceptGMs() const; uint32 GetPlayersCountExceptGMs() const;
bool ActiveObjectsNearGrid(uint32 x, uint32 y) const; bool ActiveObjectsNearGrid(uint32 x, uint32 y) const;
void SendToPlayers(WorldPacket const* data) const; /// Send a Packet to all players on a map
bool SendToPlayersInZone(WorldPacket const* data, uint32 zoneId) const; void SendToPlayers(WorldPacket const* data) const;
/// Send a Packet to all players in a zone. Return false if no player found
bool SendToPlayersInZone(WorldPacket const* data, uint32 zoneId) const;
typedef MapRefManager PlayerList; typedef MapRefManager PlayerList;
PlayerList const& GetPlayers() const { return m_mapRefManager; } PlayerList const& GetPlayers() const { return m_mapRefManager; }
// per-map script storage // per-map script storage
enum ScriptExecutionParam enum ScriptExecutionParam
{ {
SCRIPT_EXEC_PARAM_NONE = 0x00, // Start regardless if already started SCRIPT_EXEC_PARAM_NONE = 0x00, // Start regardless if already started
SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE = 0x01, // Start Script only if not yet started (uniqueness identified by id and source) SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE = 0x01, // Start Script only if not yet started (uniqueness identified by id and source)
SCRIPT_EXEC_PARAM_UNIQUE_BY_TARGET = 0x02, // Start Script only if not yet started (uniqueness identified by id and target) SCRIPT_EXEC_PARAM_UNIQUE_BY_TARGET = 0x02, // Start Script only if not yet started (uniqueness identified by id and target)
SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE_TARGET = 0x03, // Start Script only if not yet started (uniqueness identified by id, source and target) SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE_TARGET = 0x03, // Start Script only if not yet started (uniqueness identified by id, source and target)
}; };
bool ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* source, Object* target, ScriptExecutionParam execParams = SCRIPT_EXEC_PARAM_NONE); bool ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* source, Object* target, ScriptExecutionParam execParams = SCRIPT_EXEC_PARAM_NONE);
void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target); void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target);
// must called with AddToWorld // must called with AddToWorld
void AddToActive(WorldObject* obj); void AddToActive(WorldObject* obj);
// must called with RemoveFromWorld // must called with RemoveFromWorld
void RemoveFromActive(WorldObject* obj); void RemoveFromActive(WorldObject* obj);
Player* GetPlayer(ObjectGuid guid); Player* GetPlayer(ObjectGuid guid);
Creature* GetCreature(ObjectGuid guid); Creature* GetCreature(ObjectGuid guid);
Pet* GetPet(ObjectGuid guid); Pet* GetPet(ObjectGuid guid);
Creature* GetAnyTypeCreature(ObjectGuid guid); // normal creature or pet or vehicle Creature* GetAnyTypeCreature(ObjectGuid guid); // normal creature or pet or vehicle
GameObject* GetGameObject(ObjectGuid guid); GameObject* GetGameObject(ObjectGuid guid);
DynamicObject* GetDynamicObject(ObjectGuid guid); DynamicObject* GetDynamicObject(ObjectGuid guid);
Corpse* GetCorpse(ObjectGuid guid); // !!! find corpse can be not in world Corpse* GetCorpse(ObjectGuid guid); // !!! find corpse can be not in world
Unit* GetUnit(ObjectGuid guid); // only use if sure that need objects at current map, specially for player case Unit* GetUnit(ObjectGuid guid); // only use if sure that need objects at current map, specially for player case
WorldObject* GetWorldObject(ObjectGuid guid); // only use if sure that need objects at current map, specially for player case WorldObject* GetWorldObject(ObjectGuid guid); // only use if sure that need objects at current map, specially for player case
typedef TypeUnorderedMapContainer<AllMapStoredObjectTypes, ObjectGuid> MapStoredObjectTypesContainer; typedef TypeUnorderedMapContainer<AllMapStoredObjectTypes, ObjectGuid> MapStoredObjectTypesContainer;
MapStoredObjectTypesContainer& GetObjectsStore() { return m_objectsStore; } MapStoredObjectTypesContainer& GetObjectsStore() { return m_objectsStore; }
void AddUpdateObject(Object* obj) void AddUpdateObject(Object* obj)
{ {
i_objectsToClientUpdate.insert(obj); i_objectsToClientUpdate.insert(obj);
} }
void RemoveUpdateObject(Object* obj) void RemoveUpdateObject(Object* obj)
{ {
i_objectsToClientUpdate.erase(obj); i_objectsToClientUpdate.erase(obj);
} }
// DynObjects currently // DynObjects currently
uint32 GenerateLocalLowGuid(HighGuid guidhigh); uint32 GenerateLocalLowGuid(HighGuid guidhigh);
// get corresponding TerrainData object for this particular map // get corresponding TerrainData object for this particular map
const TerrainInfo* GetTerrain() const { return m_TerrainData; } const TerrainInfo* GetTerrain() const { return m_TerrainData; }
void CreateInstanceData(bool load); void CreateInstanceData(bool load);
InstanceData* GetInstanceData() const { return i_data; } InstanceData* GetInstanceData() const { return i_data; }
uint32 GetScriptId() const { return i_script_id; } virtual uint32 GetScriptId() const { return sScriptMgr.GetBoundScriptId(SCRIPTED_MAP, GetId()); }
void MonsterYellToMap(ObjectGuid guid, int32 textId, uint32 language, Unit const* target) const; void MonsterYellToMap(ObjectGuid guid, int32 textId, Language language, Unit const* target) const;
void MonsterYellToMap(CreatureInfo const* cinfo, int32 textId, uint32 language, Unit const* target, uint32 senderLowGuid = 0) const; void MonsterYellToMap(CreatureInfo const* cinfo, int32 textId, Language language, Unit const* target, uint32 senderLowGuid = 0) const;
void PlayDirectSoundToMap(uint32 soundId, uint32 zoneId = 0) const; void PlayDirectSoundToMap(uint32 soundId, uint32 zoneId = 0) const;
// Dynamic VMaps // Dynamic VMaps
float GetHeight(uint32 phasemask, float x, float y, float z) const; float GetHeight(uint32 phasemask, float x, float y, float z) const;
bool IsInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const; bool GetHeightInRange(uint32 phasemask, float x, float y, float& z, float maxSearchDist = 4.0f) const;
bool GetHitPosition(float srcX, float srcY, float srcZ, float& destX, float& destY, float& destZ, uint32 phasemask, float modifyDist) const; bool IsInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const;
bool GetHitPosition(float srcX, float srcY, float srcZ, float& destX, float& destY, float& destZ, uint32 phasemask, float modifyDist) const;
// Object Model insertion/remove/test for dynamic vmaps use // Object Model insertion/remove/test for dynamic vmaps use
void InsertGameObjectModel(const GameObjectModel& mdl); void InsertGameObjectModel(const GameObjectModel& mdl);
void RemoveGameObjectModel(const GameObjectModel& mdl); void RemoveGameObjectModel(const GameObjectModel& mdl);
bool ContainsGameObjectModel(const GameObjectModel& mdl) const; bool ContainsGameObjectModel(const GameObjectModel& mdl) const;
// Get Holder for Creature Linking // Get Holder for Creature Linking
CreatureLinkingHolder* GetCreatureLinkingHolder() { return &m_creatureLinkingHolder; } CreatureLinkingHolder* GetCreatureLinkingHolder() { return &m_creatureLinkingHolder; }
void SetWeather(uint32 zoneId, WeatherType type, float grade, bool permanently); // Teleport all players in that map to choosed location
void TeleportAllPlayersTo(TeleportLocation loc);
// WeatherSystem
WeatherSystem* GetWeatherSystem() const { return m_weatherSystem; }
/** Set the weather in a zone on this map
* @param zoneId set the weather for which zone
* @param type What weather to set
* @param grade how strong the weather should be
* @param permanently set the weather permanently?
*/
void SetWeather(uint32 zoneId, WeatherType type, float grade, bool permanently);
// Random on map generation
bool GetReachableRandomPosition(Unit* unit, float& x, float& y, float& z, float radius);
bool GetReachableRandomPointOnGround(uint32 phaseMask, float& x, float& y, float& z, float radius);
bool GetRandomPointInTheAir(uint32 phaseMask, float& x, float& y, float& z, float radius);
bool GetRandomPointUnderWater(uint32 phaseMask, float& x, float& y, float& z, float radius, GridMapLiquidData& liquid_status);
private: private:
void LoadMapAndVMap(int gx, int gy); void LoadMapAndVMap(int gx, int gy);
@ -392,72 +412,76 @@ class Map : public GridRefManager<NGridType>
WeatherSystem* m_weatherSystem; WeatherSystem* m_weatherSystem;
}; };
class WorldMap : public Map class WorldMap : public Map
{ {
private: private:
using Map::GetPersistentState; // hide in subclass for overwrite using Map::GetPersistentState; // hide in subclass for overwrite
public: public:
WorldMap(uint32 id, time_t expiry) : Map(id, expiry, 0, REGULAR_DIFFICULTY) {} WorldMap(uint32 id, time_t expiry) : Map(id, expiry, 0, REGULAR_DIFFICULTY) {}
~WorldMap() {} ~WorldMap() {}
// can't be NULL for loaded map // can't be NULL for loaded map
WorldPersistentState* GetPersistanceState() const; WorldPersistentState* GetPersistanceState() const;
}; };
class DungeonMap : public Map class DungeonMap : public Map
{ {
private: private:
using Map::GetPersistentState; // hide in subclass for overwrite using Map::GetPersistentState; // hide in subclass for overwrite
public: public:
DungeonMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode); DungeonMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode);
~DungeonMap(); ~DungeonMap();
bool Add(Player*) override; bool Add(Player*) override;
void Remove(Player*, bool) override; void Remove(Player*, bool) override;
void Update(const uint32&) override; void Update(const uint32&) override;
bool Reset(InstanceResetMethod method); bool Reset(InstanceResetMethod method);
void PermBindAllPlayers(Player* player); void PermBindAllPlayers(Player* player);
void UnloadAll(bool pForce) override; void UnloadAll(bool pForce) override;
void SendResetWarnings(uint32 timeLeft) const; void SendResetWarnings(uint32 timeLeft) const;
void SetResetSchedule(bool on); void SetResetSchedule(bool on);
// can't be NULL for loaded map uint32 GetScriptId() const override { return sScriptMgr.GetBoundScriptId(SCRIPTED_INSTANCE, GetId()); }
DungeonPersistentState* GetPersistanceState() const;
virtual void InitVisibilityDistance() override; // can't be NULL for loaded map
private: DungeonPersistentState* GetPersistanceState() const;
bool m_resetAfterUnload;
bool m_unloadWhenEmpty; virtual void InitVisibilityDistance() override;
private:
bool m_resetAfterUnload;
bool m_unloadWhenEmpty;
}; };
class BattleGroundMap : public Map class BattleGroundMap : public Map
{ {
private: private:
using Map::GetPersistentState; // hide in subclass for overwrite using Map::GetPersistentState; // hide in subclass for overwrite
public: public:
BattleGroundMap(uint32 id, time_t, uint32 InstanceId, uint8 spawnMode); BattleGroundMap(uint32 id, time_t, uint32 InstanceId, uint8 spawnMode);
~BattleGroundMap(); ~BattleGroundMap();
void Update(const uint32&) override; void Update(const uint32&) override;
bool Add(Player*) override; bool Add(Player*) override;
void Remove(Player*, bool) override; void Remove(Player*, bool) override;
bool CanEnter(Player* player) override; bool CanEnter(Player* player) override;
void SetUnload(); void SetUnload();
void UnloadAll(bool pForce) override; void UnloadAll(bool pForce) override;
virtual void InitVisibilityDistance() override; virtual void InitVisibilityDistance() override;
BattleGround* GetBG() { return m_bg; } BattleGround* GetBG() { return m_bg; }
void SetBG(BattleGround* bg) { m_bg = bg; } void SetBG(BattleGround* bg) { m_bg = bg; }
// can't be NULL for loaded map uint32 GetScriptId() const override { return sScriptMgr.GetBoundScriptId(SCRIPTED_BATTLEGROUND, GetId()); } //TODO bind BG scripts through script_binding, now these are broken!
BattleGroundPersistentState* GetPersistanceState() const;
private: // can't be NULL for loaded map
BattleGround* m_bg; BattleGroundPersistentState* GetPersistanceState() const;
private:
BattleGround* m_bg;
}; };
template<class T, class CONTAINER> template<class T, class CONTAINER>
inline void inline void
Map::Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER> &visitor) Map::Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER>& visitor)
{ {
const uint32 x = cell.GridX(); const uint32 x = cell.GridX();
const uint32 y = cell.GridY(); const uint32 y = cell.GridY();
@ -470,4 +494,4 @@ Map::Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER> &visitor)
getNGrid(x, y)->Visit(cell_x, cell_y, visitor); getNGrid(x, y)->Visit(cell_x, cell_y, visitor);
} }
} }
#endif #endif

View file

@ -265,7 +265,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recv_data)
{ {
if (_player->CanRewardQuest(pQuest, reward, true)) if (_player->CanRewardQuest(pQuest, reward, true))
{ {
_player->RewardQuest(pQuest, reward, pObject); _player->RewardQuest(pQuest, reward, pObject, false);
// Send next quest // Send next quest
if (Quest const* nextquest = _player->GetNextQuest(guid, pQuest)) if (Quest const* nextquest = _player->GetNextQuest(guid, pQuest))

View file

@ -38,6 +38,15 @@
#include "OutdoorPvP/OutdoorPvP.h" #include "OutdoorPvP/OutdoorPvP.h"
#include "WaypointMovementGenerator.h" #include "WaypointMovementGenerator.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
#include "system/ScriptDevMgr.h"
#endif
#include <cstring> /* std::strcmp */
#include "revision.h" #include "revision.h"
ScriptMapMapName sQuestEndScripts; ScriptMapMapName sQuestEndScripts;
@ -53,44 +62,12 @@ ScriptMapMapName sCreatureMovementScripts;
INSTANTIATE_SINGLETON_1(ScriptMgr); INSTANTIATE_SINGLETON_1(ScriptMgr);
ScriptMgr::ScriptMgr() : ScriptMgr::ScriptMgr() :
m_hScriptLib(NULL), m_scheduledScripts(0)
m_scheduledScripts(0),
m_pOnInitScriptLibrary(NULL),
m_pOnFreeScriptLibrary(NULL),
m_pGetScriptLibraryVersion(NULL),
m_pGetCreatureAI(NULL),
m_pCreateInstanceData(NULL),
m_pOnGossipHello(NULL),
m_pOnGOGossipHello(NULL),
m_pOnGossipSelect(NULL),
m_pOnGOGossipSelect(NULL),
m_pOnGossipSelectWithCode(NULL),
m_pOnGOGossipSelectWithCode(NULL),
m_pOnQuestAccept(NULL),
m_pOnGOQuestAccept(NULL),
m_pOnItemQuestAccept(NULL),
m_pOnQuestRewarded(NULL),
m_pOnGOQuestRewarded(NULL),
m_pGetNPCDialogStatus(NULL),
m_pGetGODialogStatus(NULL),
m_pOnGOUse(NULL),
m_pOnItemUse(NULL),
m_pOnAreaTrigger(NULL),
m_pOnProcessEvent(NULL),
m_pOnEffectDummyCreature(NULL),
m_pOnEffectDummyGO(NULL),
m_pOnEffectDummyItem(NULL),
m_pOnEffectScriptEffectCreature(NULL),
m_pOnAuraDummy(NULL)
{ {
} }
ScriptMgr::~ScriptMgr() ScriptMgr::~ScriptMgr()
{ {
UnloadScriptLibrary();
} }
// ///////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////
@ -1807,25 +1784,28 @@ bool ScriptAction::HandleScriptStep()
// Scripting Library Hooks // Scripting Library Hooks
// ///////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////
void ScriptMgr::LoadAreaTriggerScripts() void ScriptMgr::LoadScriptBinding()
{ {
m_AreaTriggerScripts.clear(); // need for reload case #ifdef ENABLE_SD3
QueryResult* result = WorldDatabase.Query("SELECT entry, ScriptName FROM scripted_areatrigger"); for (int i = 0; i < SCRIPTED_MAX_TYPE; ++i)
m_scriptBind[i].clear();
QueryResult* result = WorldDatabase.PQuery("SELECT type, bind, ScriptName, data FROM script_binding");
uint32 count = 0; uint32 count = 0;
if (!result) if (!result)
{ {
BarGoLink bar(1); BarGoLink bar(1);
bar.step(); bar.step();
sLog.outString(">> Loaded no script binding.");
sLog.outString(); sLog.outString();
sLog.outString(">> Loaded %u scripted areatrigger", count);
return; return;
} }
BarGoLink bar(result->GetRowCount()); std::set<uint32> eventIds; // Store possible event ids, for checking
CollectPossibleEventIds(eventIds);
BarGoLink bar(result->GetRowCount());
do do
{ {
++count; ++count;
@ -1833,96 +1813,107 @@ void ScriptMgr::LoadAreaTriggerScripts()
Field* fields = result->Fetch(); Field* fields = result->Fetch();
uint32 triggerId = fields[0].GetUInt32(); uint8 type = fields[0].GetUInt8();
const char* scriptName = fields[1].GetString(); int32 id = fields[1].GetInt32();
const char* scriptName = fields[2].GetString();
uint8 data = fields[3].GetUInt8();
if (!sAreaTriggerStore.LookupEntry(triggerId)) if (type >= SCRIPTED_MAX_TYPE)
{ {
sLog.outErrorDb("Table `scripted_areatrigger` has area trigger (ID: %u) not listed in `AreaTrigger.dbc`.", triggerId); sLog.outErrorScriptLib("script_binding table contains a script for non-existent type %u (bind %d), ignoring.", type, id);
continue;
}
uint32 scriptId = GetScriptId(scriptName);
if (!scriptId) //this should never happen! the script names are initialized from the same table
{
sLog.outErrorScriptLib("something is very bad with your script_binding table!");
continue; continue;
} }
m_AreaTriggerScripts[triggerId] = GetScriptId(scriptName); // checking if the scripted object actually exists
} bool exists = false;
while (result->NextRow()); switch (type)
{
case SCRIPTED_UNIT:
exists = id > 0 ? bool(sCreatureStorage.LookupEntry<CreatureInfo>(uint32(id))) : bool(sObjectMgr.GetCreatureData(uint32(-id)));
break;
case SCRIPTED_GAMEOBJECT:
exists = id > 0 ? bool(sGOStorage.LookupEntry<GameObjectInfo>(uint32(id))) : bool(sObjectMgr.GetGOData(uint32(-id)));
break;
case SCRIPTED_ITEM:
exists = bool(sItemStorage.LookupEntry<ItemPrototype>(uint32(id)));
break;
case SCRIPTED_AREATRIGGER:
exists = bool(sAreaTriggerStore.LookupEntry(uint32(id)));
break;
case SCRIPTED_SPELL:
case SCRIPTED_AURASPELL:
exists = bool(sSpellStore.LookupEntry(uint32(id)));
break;
case SCRIPTED_MAPEVENT:
exists = eventIds.count(uint32(id));
break;
case SCRIPTED_MAP:
exists = bool(sMapStore.LookupEntry(uint32(id)));
break;
case SCRIPTED_PVP_ZONE: // for now, no check on special zones
exists = bool(sAreaStore.LookupEntry(uint32(id)));
break;
case SCRIPTED_BATTLEGROUND:
if (MapEntry const* mapEntry = sMapStore.LookupEntry(uint32(id)))
exists = mapEntry->IsBattleGround();
break;
case SCRIPTED_INSTANCE:
if (MapEntry const* mapEntry = sMapStore.LookupEntry(uint32(id)))
exists = mapEntry->IsDungeon();
break;
case SCRIPTED_CONDITION:
exists = sConditionStorage.LookupEntry<PlayerCondition>(uint32(id));
break;
case SCRIPTED_ACHIEVEMENT:
break;
}
if (!exists)
{
sLog.outErrorScriptLib("script type %u (%s) is bound to non-existing entry %d, ignoring.", type, scriptName, id);
continue;
}
if (type == SCRIPTED_SPELL || type == SCRIPTED_AURASPELL)
id |= uint32(data) << 24; //incorporate spell effect number into the key
m_scriptBind[type][id] = scriptId;
} while (result->NextRow());
delete result; delete result;
sLog.outString("Of the total %u script bindings, loaded succesfully:", count);
for (uint8 i = 0; i < SCRIPTED_MAX_TYPE; ++i)
{
if (m_scriptBind[i].size()) //ignore missing script types to shorten the log
{
sLog.outString(".. type %u: %u binds", i, uint32(m_scriptBind[i].size()));
count -= m_scriptBind[i].size();
}
}
sLog.outString("Thus, %u script binds are found bad.", count);
sLog.outString(); sLog.outString();
sLog.outString(">> Loaded %u areatrigger scripts", count); #endif /* ENABLE_SD3 */
} return;
void ScriptMgr::LoadEventIdScripts()
{
m_EventIdScripts.clear(); // need for reload case
QueryResult* result = WorldDatabase.Query("SELECT id, ScriptName FROM scripted_event");
uint32 count = 0;
if (!result)
{
BarGoLink bar(1);
bar.step();
sLog.outString();
sLog.outString(">> Loaded %u scripted event id", count);
return;
}
BarGoLink bar(result->GetRowCount());
std::set<uint32> eventIds; // Store possible event ids
CollectPossibleEventIds(eventIds);
do
{
++count;
bar.step();
Field* fields = result->Fetch();
uint32 eventId = fields[0].GetUInt32();
const char* scriptName = fields[1].GetString();
std::set<uint32>::const_iterator itr = eventIds.find(eventId);
if (itr == eventIds.end())
sLog.outErrorDb("Table `scripted_event` has id %u not referring to any gameobject_template type 10 data2 field, type 3 data6 field, type 13 data 2 field, type 29 or any spell effect %u or path taxi node data",
eventId, SPELL_EFFECT_SEND_EVENT);
m_EventIdScripts[eventId] = GetScriptId(scriptName);
}
while (result->NextRow());
delete result;
sLog.outString();
sLog.outString(">> Loaded %u scripted event id", count);
} }
void ScriptMgr::LoadScriptNames() void ScriptMgr::LoadScriptNames()
{ {
m_scriptNames.push_back(""); m_scriptNames.push_back("");
QueryResult* result = WorldDatabase.Query( QueryResult* result = WorldDatabase.Query("SELECT DISTINCT(ScriptName) FROM script_binding");
"SELECT DISTINCT(ScriptName) FROM creature_template WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM scripted_areatrigger WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM scripted_event WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM instance_template WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM world_template WHERE ScriptName <> ''");
if (!result) if (!result)
{ {
BarGoLink bar(1); BarGoLink bar(1);
bar.step(); bar.step();
sLog.outString();
sLog.outErrorDb(">> Loaded empty set of Script Names!"); sLog.outErrorDb(">> Loaded empty set of Script Names!");
sLog.outString();
return; return;
} }
@ -1934,13 +1925,13 @@ void ScriptMgr::LoadScriptNames()
bar.step(); bar.step();
m_scriptNames.push_back((*result)[0].GetString()); m_scriptNames.push_back((*result)[0].GetString());
++count; ++count;
} } while (result->NextRow());
while (result->NextRow());
delete result; delete result;
std::sort(m_scriptNames.begin(), m_scriptNames.end()); std::sort(m_scriptNames.begin(), m_scriptNames.end());
sLog.outString(">> Loaded %d unique Script Names", count);
sLog.outString(); sLog.outString();
sLog.outString(">> Loaded %d Script Names", count);
} }
uint32 ScriptMgr::GetScriptId(const char* name) const uint32 ScriptMgr::GetScriptId(const char* name) const
@ -1948,281 +1939,410 @@ uint32 ScriptMgr::GetScriptId(const char* name) const
// use binary search to find the script name in the sorted vector // use binary search to find the script name in the sorted vector
// assume "" is the first element // assume "" is the first element
if (!name) if (!name)
{
return 0; return 0;
}
ScriptNameMap::const_iterator itr = ScriptNameMap::const_iterator itr =
std::lower_bound(m_scriptNames.begin(), m_scriptNames.end(), name); std::lower_bound(m_scriptNames.begin(), m_scriptNames.end(), name);
if (itr == m_scriptNames.end() || *itr != name) if (itr == m_scriptNames.end() || *itr != name)
{
return 0; return 0;
}
return uint32(itr - m_scriptNames.begin()); return uint32(itr - m_scriptNames.begin());
} }
uint32 ScriptMgr::GetAreaTriggerScriptId(uint32 triggerId) const
{
AreaTriggerScriptMap::const_iterator itr = m_AreaTriggerScripts.find(triggerId);
if (itr != m_AreaTriggerScripts.end())
return itr->second;
return 0;
}
uint32 ScriptMgr::GetEventIdScriptId(uint32 eventId) const
{
EventIdScriptMap::const_iterator itr = m_EventIdScripts.find(eventId);
if (itr != m_EventIdScripts.end())
return itr->second;
return 0;
}
char const* ScriptMgr::GetScriptLibraryVersion() const char const* ScriptMgr::GetScriptLibraryVersion() const
{ {
if (!m_pGetScriptLibraryVersion) #ifdef ENABLE_SD3
return ""; return SD3::GetScriptLibraryVersion();
#else
return NULL;
#endif
}
return m_pGetScriptLibraryVersion(); uint32 ScriptMgr::GetBoundScriptId(ScriptedObjectType entity, int32 entry)
{
uint32 id = 0;
if (entity < SCRIPTED_MAX_TYPE)
{
EntryToScriptIdMap::const_iterator it = m_scriptBind[entity].find(entry);
if (it != m_scriptBind[entity].end())
id = it->second;
}
else
sLog.outErrorScriptLib("asking a script for non-existing entity type %u!", entity);
return id;
} }
CreatureAI* ScriptMgr::GetCreatureAI(Creature* pCreature) CreatureAI* ScriptMgr::GetCreatureAI(Creature* pCreature)
{ {
if (!m_pGetCreatureAI) // Used by Eluna
return NULL; #ifdef ENABLE_ELUNA
if (CreatureAI* luaAI = sEluna->GetAI(pCreature))
return luaAI;
#endif /* ENABLE_ELUNA */
return m_pGetCreatureAI(pCreature); #ifdef ENABLE_SD3
return SD3::GetCreatureAI(pCreature);
#else
return NULL;
#endif
} }
InstanceData* ScriptMgr::CreateInstanceData(Map* pMap) InstanceData* ScriptMgr::CreateInstanceData(Map* pMap)
{ {
if (!m_pCreateInstanceData) #ifdef ENABLE_SD3
return NULL; return SD3::CreateInstanceData(pMap);
#else
return m_pCreateInstanceData(pMap); return NULL;
#endif
} }
bool ScriptMgr::OnGossipHello(Player* pPlayer, Creature* pCreature) bool ScriptMgr::OnGossipHello(Player* pPlayer, Creature* pCreature)
{ {
return m_pOnGossipHello != NULL && m_pOnGossipHello(pPlayer, pCreature); // Used by Eluna
#ifdef ENABLE_ELUNA
if (sEluna->OnGossipHello(pPlayer, pCreature))
return true;
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
return SD3::GossipHello(pPlayer, pCreature);
#else
return false;
#endif
} }
bool ScriptMgr::OnGossipHello(Player* pPlayer, GameObject* pGameObject) bool ScriptMgr::OnGossipHello(Player* pPlayer, GameObject* pGameObject)
{ {
return m_pOnGOGossipHello != NULL && m_pOnGOGossipHello(pPlayer, pGameObject); // Used by Eluna
#ifdef ENABLE_ELUNA
if (sEluna->OnGossipHello(pPlayer, pGameObject))
return true;
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
return SD3::GOGossipHello(pPlayer, pGameObject);
#else
return false;
#endif
} }
bool ScriptMgr::OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 sender, uint32 action, const char* code) bool ScriptMgr::OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 sender, uint32 action, const char* code)
{ {
#ifdef ENABLE_ELUNA
if (code) if (code)
return m_pOnGossipSelectWithCode != NULL && m_pOnGossipSelectWithCode(pPlayer, pCreature, sender, action, code); {
// Used by Eluna
if (sEluna->OnGossipSelectCode(pPlayer, pCreature, sender, action, code))
return true;
}
else else
return m_pOnGossipSelect != NULL && m_pOnGossipSelect(pPlayer, pCreature, sender, action); {
// Used by Eluna
if (sEluna->OnGossipSelect(pPlayer, pCreature, sender, action))
return true;
}
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
if (code)
{
return SD3::GossipSelectWithCode(pPlayer, pCreature, sender, action, code);
}
else
{
return SD3::GossipSelect(pPlayer, pCreature, sender, action);
}
#else
return false;
#endif
} }
bool ScriptMgr::OnGossipSelect(Player* pPlayer, GameObject* pGameObject, uint32 sender, uint32 action, const char* code) bool ScriptMgr::OnGossipSelect(Player* pPlayer, GameObject* pGameObject, uint32 sender, uint32 action, const char* code)
{ {
// Used by Eluna
#ifdef ENABLE_ELUNA
if (code) if (code)
return m_pOnGOGossipSelectWithCode != NULL && m_pOnGOGossipSelectWithCode(pPlayer, pGameObject, sender, action, code); {
if (sEluna->OnGossipSelectCode(pPlayer, pGameObject, sender, action, code))
return true;
}
else else
return m_pOnGOGossipSelect != NULL && m_pOnGOGossipSelect(pPlayer, pGameObject, sender, action); {
if (sEluna->OnGossipSelect(pPlayer, pGameObject, sender, action))
return true;
}
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
if (code)
{
return SD3::GOGossipSelectWithCode(pPlayer, pGameObject, sender, action, code);
}
else
{
return SD3::GOGossipSelect(pPlayer, pGameObject, sender, action);
}
#else
return false;
#endif
} }
bool ScriptMgr::OnQuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest) bool ScriptMgr::OnQuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest)
{ {
return m_pOnQuestAccept != NULL && m_pOnQuestAccept(pPlayer, pCreature, pQuest); // Used by Eluna
#ifdef ENABLE_ELUNA
if (sEluna->OnQuestAccept(pPlayer, pCreature, pQuest))
return true;
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
return SD3::QuestAccept(pPlayer, pCreature, pQuest);
#else
return false;
#endif
} }
bool ScriptMgr::OnQuestAccept(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest) bool ScriptMgr::OnQuestAccept(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest)
{ {
return m_pOnGOQuestAccept != NULL && m_pOnGOQuestAccept(pPlayer, pGameObject, pQuest); // Used by Eluna
#ifdef ENABLE_ELUNA
if (sEluna->OnQuestAccept(pPlayer, pGameObject, pQuest))
return true;
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
return SD3::GOQuestAccept(pPlayer, pGameObject, pQuest);
#else
return false;
#endif
} }
bool ScriptMgr::OnQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest) bool ScriptMgr::OnQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest)
{ {
return m_pOnItemQuestAccept != NULL && m_pOnItemQuestAccept(pPlayer, pItem, pQuest); // Used by Eluna
#ifdef ENABLE_ELUNA
if (sEluna->OnQuestAccept(pPlayer, pItem, pQuest))
return true;
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
return SD3::ItemQuestAccept(pPlayer, pItem, pQuest);
#else
return false;
#endif
} }
bool ScriptMgr::OnQuestRewarded(Player* pPlayer, Creature* pCreature, Quest const* pQuest) bool ScriptMgr::OnQuestRewarded(Player* pPlayer, Creature* pCreature, Quest const* pQuest, uint32 reward)
{ {
return m_pOnQuestRewarded != NULL && m_pOnQuestRewarded(pPlayer, pCreature, pQuest); // Used by Eluna
#ifdef ENABLE_ELUNA
if (sEluna->OnQuestReward(pPlayer, pCreature, pQuest, reward))
return true;
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
return SD3::QuestRewarded(pPlayer, pCreature, pQuest);
#else
return false;
#endif
} }
bool ScriptMgr::OnQuestRewarded(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest) bool ScriptMgr::OnQuestRewarded(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest, uint32 reward)
{ {
return m_pOnGOQuestRewarded != NULL && m_pOnGOQuestRewarded(pPlayer, pGameObject, pQuest); // Used by Eluna
#ifdef ENABLE_ELUNA
if (sEluna->OnQuestReward(pPlayer, pGameObject, pQuest, reward))
return true;
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
return SD3::GOQuestRewarded(pPlayer, pGameObject, pQuest);
#else
return false;
#endif
} }
uint32 ScriptMgr::GetDialogStatus(Player* pPlayer, Creature* pCreature) uint32 ScriptMgr::GetDialogStatus(Player* pPlayer, Creature* pCreature)
{ {
if (!m_pGetNPCDialogStatus) // Used by Eluna
return DIALOG_STATUS_UNDEFINED; #ifdef ENABLE_ELUNA
if (uint32 dialogId = sEluna->GetDialogStatus(pPlayer, pCreature))
return dialogId;
#endif /* ENABLE_ELUNA */
return m_pGetNPCDialogStatus(pPlayer, pCreature); #ifdef ENABLE_SD3
return SD3::GetNPCDialogStatus(pPlayer, pCreature);
#else
return DIALOG_STATUS_UNDEFINED;
#endif
} }
uint32 ScriptMgr::GetDialogStatus(Player* pPlayer, GameObject* pGameObject) uint32 ScriptMgr::GetDialogStatus(Player* pPlayer, GameObject* pGameObject)
{ {
if (!m_pGetGODialogStatus) // Used by Eluna
return DIALOG_STATUS_UNDEFINED; #ifdef ENABLE_ELUNA
if (uint32 dialogId = sEluna->GetDialogStatus(pPlayer, pGameObject))
return dialogId;
#endif /* ENABLE_ELUNA */
return m_pGetGODialogStatus(pPlayer, pGameObject); #ifdef ENABLE_SD3
return SD3::GetGODialogStatus(pPlayer, pGameObject);
#else
return DIALOG_STATUS_UNDEFINED;
#endif
} }
bool ScriptMgr::OnGameObjectUse(Player* pPlayer, GameObject* pGameObject) bool ScriptMgr::OnGameObjectUse(Player* pPlayer, GameObject* pGameObject)
{ {
return m_pOnGOUse != NULL && m_pOnGOUse(pPlayer, pGameObject); #ifdef ENABLE_ELUNA
if (sEluna->OnGameObjectUse(pPlayer, pGameObject))
return true;
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
return SD3::GOUse(pPlayer, pGameObject);
#else
return false;
#endif
} }
bool ScriptMgr::OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets) bool ScriptMgr::OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
{ {
return m_pOnItemUse != NULL && m_pOnItemUse(pPlayer, pItem, targets); // Used by Eluna
#ifdef ENABLE_ELUNA
if (!sEluna->OnUse(pPlayer, pItem, targets))
return true;
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
return SD3::ItemUse(pPlayer, pItem, targets);
#else
return false;
#endif
} }
bool ScriptMgr::OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* atEntry) bool ScriptMgr::OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* atEntry)
{ {
return m_pOnAreaTrigger != NULL && m_pOnAreaTrigger(pPlayer, atEntry); // Used by Eluna
#ifdef ENABLE_ELUNA
if (sEluna->OnAreaTrigger(pPlayer, atEntry))
return true;
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
return SD3::AreaTrigger(pPlayer, atEntry);
#else
return false;
#endif
}
bool ScriptMgr::OnNpcSpellClick(Player* pPlayer, Creature* pClickedCreature, uint32 spellId)
{
#ifdef ENABLE_SD3
return SD3::NpcSpellClick(pPlayer, pClickedCreature, spellId);
#else
return false;
#endif
} }
bool ScriptMgr::OnProcessEvent(uint32 eventId, Object* pSource, Object* pTarget, bool isStart) bool ScriptMgr::OnProcessEvent(uint32 eventId, Object* pSource, Object* pTarget, bool isStart)
{ {
return m_pOnProcessEvent != NULL && m_pOnProcessEvent(eventId, pSource, pTarget, isStart); #ifdef ENABLE_SD3
return SD3::ProcessEvent(eventId, pSource, pTarget, isStart);
#else
return false;
#endif
} }
bool ScriptMgr::OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Creature* pTarget, ObjectGuid originalCasterGuid) bool ScriptMgr::OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Creature* pTarget, ObjectGuid originalCasterGuid)
{ {
return m_pOnEffectDummyCreature != NULL && m_pOnEffectDummyCreature(pCaster, spellId, effIndex, pTarget, originalCasterGuid); // Used by Eluna
#ifdef ENABLE_ELUNA
if (sEluna->OnDummyEffect(pCaster, spellId, effIndex, pTarget))
return true;
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
return SD3::EffectDummyCreature(pCaster, spellId, effIndex, pTarget, originalCasterGuid);
#else
return false;
#endif
} }
bool ScriptMgr::OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, GameObject* pTarget, ObjectGuid originalCasterGuid) bool ScriptMgr::OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, GameObject* pTarget, ObjectGuid originalCasterGuid)
{ {
return m_pOnEffectDummyGO != NULL && m_pOnEffectDummyGO(pCaster, spellId, effIndex, pTarget, originalCasterGuid); // Used by Eluna
#ifdef ENABLE_ELUNA
if (sEluna->OnDummyEffect(pCaster, spellId, effIndex, pTarget))
return true;
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
return SD3::EffectDummyGameObject(pCaster, spellId, effIndex, pTarget, originalCasterGuid);
#else
return false;
#endif
} }
bool ScriptMgr::OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Item* pTarget, ObjectGuid originalCasterGuid) bool ScriptMgr::OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Item* pTarget, ObjectGuid originalCasterGuid)
{ {
return m_pOnEffectDummyItem != NULL && m_pOnEffectDummyItem(pCaster, spellId, effIndex, pTarget, originalCasterGuid); // Used by Eluna
#ifdef ENABLE_ELUNA
if (sEluna->OnDummyEffect(pCaster, spellId, effIndex, pTarget))
return true;
#endif /* ENABLE_ELUNA */
#ifdef ENABLE_SD3
return SD3::EffectDummyItem(pCaster, spellId, effIndex, pTarget, originalCasterGuid);
#else
return false;
#endif
} }
bool ScriptMgr::OnEffectScriptEffect(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Creature* pTarget, ObjectGuid originalCasterGuid) bool ScriptMgr::OnEffectScriptEffect(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Creature* pTarget, ObjectGuid originalCasterGuid)
{ {
return m_pOnEffectScriptEffectCreature != NULL && m_pOnEffectScriptEffectCreature(pCaster, spellId, effIndex, pTarget, originalCasterGuid); #ifdef ENABLE_SD3
return SD3::EffectScriptEffectCreature(pCaster, spellId, effIndex, pTarget, originalCasterGuid);
#else
return false;
#endif
} }
bool ScriptMgr::OnAuraDummy(Aura const* pAura, bool apply) bool ScriptMgr::OnAuraDummy(Aura const* pAura, bool apply)
{ {
return m_pOnAuraDummy != NULL && m_pOnAuraDummy(pAura, apply); #ifdef ENABLE_SD3
return SD3::AuraDummy(pAura, apply);
#else
return false;
#endif
} }
ScriptLoadResult ScriptMgr::LoadScriptLibrary(const char* libName) ScriptLoadResult ScriptMgr::LoadScriptLibrary(const char* libName)
{ {
UnloadScriptLibrary(); #ifdef ENABLE_SD3
if (std::strcmp(libName, MANGOS_SCRIPT_NAME) == 0)
std::string name = libName;
name = MANGOS_SCRIPT_PREFIX + name + MANGOS_SCRIPT_SUFFIX;
m_hScriptLib = MANGOS_LOAD_LIBRARY(name.c_str());
if (!m_hScriptLib)
return SCRIPT_LOAD_ERR_NOT_FOUND;
# define GET_SCRIPT_HOOK_PTR(P,N) \
GetScriptHookPtr((P), (N)); \
if (!(P)) \
{ \
/* prevent call before init */ \
m_pOnFreeScriptLibrary = NULL; \
UnloadScriptLibrary(); \
return SCRIPT_LOAD_ERR_WRONG_API; \
}
// let check used mangosd revision for build library (unsafe use with different revision because changes in inline functions, define and etc)
char const* (MANGOS_IMPORT * pGetMangosRevStr)();
GET_SCRIPT_HOOK_PTR(pGetMangosRevStr, "GetMangosRevStr");
GET_SCRIPT_HOOK_PTR(m_pOnInitScriptLibrary, "InitScriptLibrary");
GET_SCRIPT_HOOK_PTR(m_pOnFreeScriptLibrary, "FreeScriptLibrary");
GET_SCRIPT_HOOK_PTR(m_pGetScriptLibraryVersion, "GetScriptLibraryVersion");
GET_SCRIPT_HOOK_PTR(m_pGetCreatureAI, "GetCreatureAI");
GET_SCRIPT_HOOK_PTR(m_pCreateInstanceData, "CreateInstanceData");
GET_SCRIPT_HOOK_PTR(m_pOnGossipHello, "GossipHello");
GET_SCRIPT_HOOK_PTR(m_pOnGOGossipHello, "GOGossipHello");
GET_SCRIPT_HOOK_PTR(m_pOnGossipSelect, "GossipSelect");
GET_SCRIPT_HOOK_PTR(m_pOnGOGossipSelect, "GOGossipSelect");
GET_SCRIPT_HOOK_PTR(m_pOnGossipSelectWithCode, "GossipSelectWithCode");
GET_SCRIPT_HOOK_PTR(m_pOnGOGossipSelectWithCode, "GOGossipSelectWithCode");
GET_SCRIPT_HOOK_PTR(m_pOnQuestAccept, "QuestAccept");
GET_SCRIPT_HOOK_PTR(m_pOnGOQuestAccept, "GOQuestAccept");
GET_SCRIPT_HOOK_PTR(m_pOnItemQuestAccept, "ItemQuestAccept");
GET_SCRIPT_HOOK_PTR(m_pOnQuestRewarded, "QuestRewarded");
GET_SCRIPT_HOOK_PTR(m_pOnGOQuestRewarded, "GOQuestRewarded");
GET_SCRIPT_HOOK_PTR(m_pGetNPCDialogStatus, "GetNPCDialogStatus");
GET_SCRIPT_HOOK_PTR(m_pGetGODialogStatus, "GetGODialogStatus");
GET_SCRIPT_HOOK_PTR(m_pOnGOUse, "GOUse");
GET_SCRIPT_HOOK_PTR(m_pOnItemUse, "ItemUse");
GET_SCRIPT_HOOK_PTR(m_pOnAreaTrigger, "AreaTrigger");
GET_SCRIPT_HOOK_PTR(m_pOnProcessEvent, "ProcessEvent");
GET_SCRIPT_HOOK_PTR(m_pOnEffectDummyCreature, "EffectDummyCreature");
GET_SCRIPT_HOOK_PTR(m_pOnEffectDummyGO, "EffectDummyGameObject");
GET_SCRIPT_HOOK_PTR(m_pOnEffectDummyItem, "EffectDummyItem");
GET_SCRIPT_HOOK_PTR(m_pOnEffectScriptEffectCreature, "EffectScriptEffectCreature");
GET_SCRIPT_HOOK_PTR(m_pOnAuraDummy, "AuraDummy");
# undef GET_SCRIPT_HOOK_PTR
if (strcmp(pGetMangosRevStr(), REVISION_NR) != 0)
{ {
m_pOnFreeScriptLibrary = NULL; // prevent call before init SD3::FreeScriptLibrary();
UnloadScriptLibrary(); SD3::InitScriptLibrary();
return SCRIPT_LOAD_ERR_OUTDATED; return SCRIPT_LOAD_OK;
} }
#endif
m_pOnInitScriptLibrary(); return SCRIPT_LOAD_ERR_NOT_FOUND;
return SCRIPT_LOAD_OK;
} }
void ScriptMgr::UnloadScriptLibrary() void ScriptMgr::UnloadScriptLibrary()
{ {
if (!m_hScriptLib) #ifdef ENABLE_SD3
return; SD3::FreeScriptLibrary();
#else
if (m_pOnFreeScriptLibrary) return;
m_pOnFreeScriptLibrary(); #endif
MANGOS_CLOSE_LIBRARY(m_hScriptLib);
m_hScriptLib = NULL;
m_pOnInitScriptLibrary = NULL;
m_pOnFreeScriptLibrary = NULL;
m_pGetScriptLibraryVersion = NULL;
m_pGetCreatureAI = NULL;
m_pCreateInstanceData = NULL;
m_pOnGossipHello = NULL;
m_pOnGOGossipHello = NULL;
m_pOnGossipSelect = NULL;
m_pOnGOGossipSelect = NULL;
m_pOnGossipSelectWithCode = NULL;
m_pOnGOGossipSelectWithCode = NULL;
m_pOnQuestAccept = NULL;
m_pOnGOQuestAccept = NULL;
m_pOnItemQuestAccept = NULL;
m_pOnQuestRewarded = NULL;
m_pOnGOQuestRewarded = NULL;
m_pGetNPCDialogStatus = NULL;
m_pGetGODialogStatus = NULL;
m_pOnGOUse = NULL;
m_pOnItemUse = NULL;
m_pOnAreaTrigger = NULL;
m_pOnProcessEvent = NULL;
m_pOnEffectDummyCreature = NULL;
m_pOnEffectDummyGO = NULL;
m_pOnEffectDummyItem = NULL;
m_pOnEffectScriptEffectCreature = NULL;
m_pOnAuraDummy = NULL;
} }
void ScriptMgr::CollectPossibleEventIds(std::set<uint32>& eventIds) void ScriptMgr::CollectPossibleEventIds(std::set<uint32>& eventIds)

View file

@ -47,6 +47,24 @@ class SpellCastTargets;
class Unit; class Unit;
class WorldObject; class WorldObject;
enum ScriptedObjectType
{
SCRIPTED_UNIT = 0, //CreatureScript
SCRIPTED_GAMEOBJECT = 1, //GameObjectScript
SCRIPTED_ITEM = 2, //ItemScript
SCRIPTED_AREATRIGGER = 3, //AreaTriggerScript
SCRIPTED_SPELL = 4, //SpellScript
SCRIPTED_AURASPELL = 5, //AuraScript
SCRIPTED_MAPEVENT = 6, //MapEventScript
SCRIPTED_MAP = 7, //ZoneScript
SCRIPTED_BATTLEGROUND = 8, //BattleGroundScript
SCRIPTED_PVP_ZONE = 9, //OutdoorPvPScript
SCRIPTED_INSTANCE = 10, //InstanceScript
SCRIPTED_CONDITION = 11, //ConditionScript
SCRIPTED_ACHIEVEMENT = 12, //AchievementScript
SCRIPTED_MAX_TYPE
};
enum ScriptCommand // resSource, resTarget are the resulting Source/ Target after buddy search is done enum ScriptCommand // resSource, resTarget are the resulting Source/ Target after buddy search is done
{ {
SCRIPT_COMMAND_TALK = 0, // resSource = WorldObject, resTarget = Unit/none SCRIPT_COMMAND_TALK = 0, // resSource = WorldObject, resTarget = Unit/none
@ -477,24 +495,50 @@ class ScriptMgr
void LoadDbScriptStrings(); void LoadDbScriptStrings();
void LoadScriptNames(); void LoadScriptNames();
void LoadAreaTriggerScripts(); void LoadScriptBinding();
void LoadEventIdScripts();
uint32 GetAreaTriggerScriptId(uint32 triggerId) const; uint32 GetAreaTriggerScriptId(uint32 triggerId) const;
uint32 GetEventIdScriptId(uint32 eventId) const; uint32 GetEventIdScriptId(uint32 eventId) const;
const char* GetScriptName(uint32 id) const { return id < m_scriptNames.size() ? m_scriptNames[id].c_str() : ""; } uint32 GetBoundScriptId(ScriptedObjectType entity, int32 entry);
const char* GetScriptName(uint32 id) const
{
return id < m_scriptNames.size() ? m_scriptNames[id].c_str() : "";
}
uint32 GetScriptId(const char* name) const; uint32 GetScriptId(const char* name) const;
uint32 GetScriptIdsCount() const { return m_scriptNames.size(); } uint32 GetScriptIdsCount() const
{
return m_scriptNames.size();
}
ScriptLoadResult LoadScriptLibrary(const char* libName); ScriptLoadResult LoadScriptLibrary(const char* libName);
void UnloadScriptLibrary(); void UnloadScriptLibrary();
bool IsScriptLibraryLoaded() const { return m_hScriptLib != NULL; } bool IsScriptLibraryLoaded() const
{
#ifdef ENABLE_SD3
return true;
#else
return false;
#endif
}
uint32 IncreaseScheduledScriptsCount() { return (uint32)++m_scheduledScripts; } uint32 IncreaseScheduledScriptsCount()
uint32 DecreaseScheduledScriptCount() { return (uint32)--m_scheduledScripts; } {
uint32 DecreaseScheduledScriptCount(size_t count) { return (uint32)(m_scheduledScripts -= count); } return (uint32)++m_scheduledScripts;
bool IsScriptScheduled() const { return m_scheduledScripts > 0; } }
uint32 DecreaseScheduledScriptCount()
{
return (uint32)--m_scheduledScripts;
}
uint32 DecreaseScheduledScriptCount(size_t count)
{
return (uint32)(m_scheduledScripts -= count);
}
bool IsScriptScheduled() const
{
return m_scheduledScripts > 0;
}
static bool CanSpellEffectStartDBScript(SpellEntry const* spellinfo, SpellEffectIndex effIdx); static bool CanSpellEffectStartDBScript(SpellEntry const* spellinfo, SpellEffectIndex effIdx);
CreatureAI* GetCreatureAI(Creature* pCreature); CreatureAI* GetCreatureAI(Creature* pCreature);
@ -508,13 +552,14 @@ class ScriptMgr
bool OnQuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest); bool OnQuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest);
bool OnQuestAccept(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest); bool OnQuestAccept(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest);
bool OnQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest); bool OnQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest);
bool OnQuestRewarded(Player* pPlayer, Creature* pCreature, Quest const* pQuest); bool OnQuestRewarded(Player* pPlayer, Creature* pCreature, Quest const* pQuest, uint32 reward);
bool OnQuestRewarded(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest); bool OnQuestRewarded(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest, uint32 reward);
uint32 GetDialogStatus(Player* pPlayer, Creature* pCreature); uint32 GetDialogStatus(Player* pPlayer, Creature* pCreature);
uint32 GetDialogStatus(Player* pPlayer, GameObject* pGameObject); uint32 GetDialogStatus(Player* pPlayer, GameObject* pGameObject);
bool OnGameObjectUse(Player* pPlayer, GameObject* pGameObject); bool OnGameObjectUse(Player* pPlayer, GameObject* pGameObject);
bool OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets); bool OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets);
bool OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* atEntry); bool OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* atEntry);
bool OnNpcSpellClick(Player* pPlayer, Creature* pClickedCreature, uint32 spellId);
bool OnProcessEvent(uint32 eventId, Object* pSource, Object* pTarget, bool isStart); bool OnProcessEvent(uint32 eventId, Object* pSource, Object* pTarget, bool isStart);
bool OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Creature* pTarget, ObjectGuid originalCasterGuid); bool OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Creature* pTarget, ObjectGuid originalCasterGuid);
bool OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, GameObject* pTarget, ObjectGuid originalCasterGuid); bool OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, GameObject* pTarget, ObjectGuid originalCasterGuid);
@ -527,54 +572,15 @@ class ScriptMgr
void LoadScripts(ScriptMapMapName& scripts, const char* tablename); void LoadScripts(ScriptMapMapName& scripts, const char* tablename);
void CheckScriptTexts(ScriptMapMapName const& scripts, std::set<int32>& ids); void CheckScriptTexts(ScriptMapMapName const& scripts, std::set<int32>& ids);
template<class T>
void GetScriptHookPtr(T& ptr, const char* name)
{
ptr = (T)MANGOS_GET_PROC_ADDR(m_hScriptLib, name);
}
typedef std::vector<std::string> ScriptNameMap; typedef std::vector<std::string> ScriptNameMap;
typedef UNORDERED_MAP<uint32, uint32> AreaTriggerScriptMap; typedef UNORDERED_MAP<int32, uint32> EntryToScriptIdMap;
typedef UNORDERED_MAP<uint32, uint32> EventIdScriptMap;
AreaTriggerScriptMap m_AreaTriggerScripts; EntryToScriptIdMap m_scriptBind[SCRIPTED_MAX_TYPE];
EventIdScriptMap m_EventIdScripts;
ScriptNameMap m_scriptNames; ScriptNameMap m_scriptNames;
MANGOS_LIBRARY_HANDLE m_hScriptLib;
// atomic op counter for active scripts amount // atomic op counter for active scripts amount
ACE_Atomic_Op<ACE_Thread_Mutex, long> m_scheduledScripts; ACE_Atomic_Op<ACE_Thread_Mutex, long> m_scheduledScripts;
void (MANGOS_IMPORT* m_pOnInitScriptLibrary)();
void (MANGOS_IMPORT* m_pOnFreeScriptLibrary)();
const char* (MANGOS_IMPORT* m_pGetScriptLibraryVersion)();
CreatureAI* (MANGOS_IMPORT* m_pGetCreatureAI)(Creature*);
InstanceData* (MANGOS_IMPORT* m_pCreateInstanceData)(Map*);
bool (MANGOS_IMPORT* m_pOnGossipHello)(Player*, Creature*);
bool (MANGOS_IMPORT* m_pOnGOGossipHello)(Player*, GameObject*);
bool (MANGOS_IMPORT* m_pOnGossipSelect)(Player*, Creature*, uint32, uint32);
bool (MANGOS_IMPORT* m_pOnGOGossipSelect)(Player*, GameObject*, uint32, uint32);
bool (MANGOS_IMPORT* m_pOnGossipSelectWithCode)(Player*, Creature*, uint32, uint32, const char*);
bool (MANGOS_IMPORT* m_pOnGOGossipSelectWithCode)(Player*, GameObject*, uint32, uint32, const char*);
bool (MANGOS_IMPORT* m_pOnQuestAccept)(Player*, Creature*, Quest const*);
bool (MANGOS_IMPORT* m_pOnGOQuestAccept)(Player*, GameObject*, Quest const*);
bool (MANGOS_IMPORT* m_pOnItemQuestAccept)(Player*, Item*, Quest const*);
bool (MANGOS_IMPORT* m_pOnQuestRewarded)(Player*, Creature*, Quest const*);
bool (MANGOS_IMPORT* m_pOnGOQuestRewarded)(Player*, GameObject*, Quest const*);
uint32(MANGOS_IMPORT* m_pGetNPCDialogStatus)(Player*, Creature*);
uint32(MANGOS_IMPORT* m_pGetGODialogStatus)(Player*, GameObject*);
bool (MANGOS_IMPORT* m_pOnGOUse)(Player*, GameObject*);
bool (MANGOS_IMPORT* m_pOnItemUse)(Player*, Item*, SpellCastTargets const&);
bool (MANGOS_IMPORT* m_pOnAreaTrigger)(Player*, AreaTriggerEntry const*);
bool (MANGOS_IMPORT* m_pOnProcessEvent)(uint32, Object*, Object*, bool);
bool (MANGOS_IMPORT* m_pOnEffectDummyCreature)(Unit*, uint32, SpellEffectIndex, Creature*, ObjectGuid);
bool (MANGOS_IMPORT* m_pOnEffectDummyGO)(Unit*, uint32, SpellEffectIndex, GameObject*, ObjectGuid);
bool (MANGOS_IMPORT* m_pOnEffectDummyItem)(Unit*, uint32, SpellEffectIndex, Item*, ObjectGuid);
bool (MANGOS_IMPORT* m_pOnEffectScriptEffectCreature)(Unit*, uint32, SpellEffectIndex, Creature*, ObjectGuid);
bool (MANGOS_IMPORT* m_pOnAuraDummy)(Aura const*, bool);
}; };
// Starters for events // Starters for events

View file

@ -29,52 +29,56 @@
#include "Weather.h" #include "Weather.h"
#include "WorldPacket.h" #include "WorldPacket.h"
#include "Player.h" #include "Player.h"
#include "Map.h"
#include "World.h" #include "World.h"
#include "Log.h" #include "Log.h"
#include "ObjectMgr.h" // #include "ObjectMgr.h" // chucky delete ?
#include "Util.h" #include "Util.h"
#ifdef ENABLE_ELUNA #ifdef ENABLE_ELUNA
#include "LuaEngine.h" #include "LuaEngine.h"
#endif /* ENABLE_ELUNA */ #endif /* ENABLE_ELUNA */
/// Create the Weather object /// Create the Weather object
Weather::Weather(uint32 zone, WeatherZoneChances const* weatherChances) : m_zone(zone), m_weatherChances(weatherChances) Weather::Weather(uint32 zone, WeatherZoneChances const* weatherChances) :
m_zone(zone),
m_type(WEATHER_TYPE_FINE),
m_grade(0.0f),
m_weatherChances(weatherChances),
m_isPermanentWeather(false)
{ {
m_timer.SetInterval(sWorld.getConfig(CONFIG_UINT32_INTERVAL_CHANGEWEATHER)); m_timer.SetInterval(sWorld.getConfig(CONFIG_UINT32_INTERVAL_CHANGEWEATHER));
m_type = WEATHER_TYPE_FINE;
m_grade = 0;
DETAIL_FILTER_LOG(LOG_FILTER_WEATHER, "WORLD: Starting weather system for zone %u (change every %u minutes).", m_zone, (m_timer.GetInterval() / (MINUTE * IN_MILLISECONDS))); DETAIL_FILTER_LOG(LOG_FILTER_WEATHER, "WORLD: Starting weather system for zone %u (change every %u minutes).", m_zone, (m_timer.GetInterval() / (MINUTE * IN_MILLISECONDS)));
} }
/// Launch a weather update /// Launch a weather update
bool Weather::Update(time_t diff) bool Weather::Update(uint32 diff, Map const* _map)
{ {
m_timer.Update(diff); m_timer.Update(diff);
if (ReGenerate())
///- If the timer has passed, ReGenerate the weather
if (m_timer.Passed())
{ {
m_timer.Reset(); ///- Weather will be removed if not updated (no players in zone anymore)
// update only if Regenerate has changed the weather if (!SendWeatherForPlayersInZone(_map))
if (ReGenerate()) return false;
{
///- Weather will be removed if not updated (no players in zone anymore)
if (!UpdateWeather())
return false;
}
} }
return true; return true;
} }
/// Calculate the new weather /// Calculate the new weather, returns true if and only if the weather changed
bool Weather::ReGenerate() bool Weather::ReGenerate()
{ {
if (m_isPermanentWeather)
return false;
// remember old values
WeatherType old_type = m_type;
float old_grade = m_grade;
if (!m_weatherChances) if (!m_weatherChances)
{ {
m_type = WEATHER_TYPE_FINE; m_type = WEATHER_TYPE_FINE;
m_grade = 0.0f; m_grade = 0.0f;
return false; // No chanced calculation for this zone
return old_type != m_type || old_grade != m_grade;
} }
/// Weather statistics: /// Weather statistics:
@ -85,11 +89,9 @@ bool Weather::ReGenerate()
uint32 u = urand(0, 99); uint32 u = urand(0, 99);
if (u < 30) if (u < 30)
{
return false; return false;
}
// remember old values
WeatherType old_type = m_type;
float old_grade = m_grade;
// 78 days between January 1st and March 20nd; 365/4=91 days by season // 78 days between January 1st and March 20nd; 365/4=91 days by season
// season source http://aa.usno.navy.mil/data/docs/EarthSeasons.html // season source http://aa.usno.navy.mil/data/docs/EarthSeasons.html
@ -149,19 +151,27 @@ bool Weather::ReGenerate()
} }
// At this point, only weather that isn't doing anything remains but that have weather data // At this point, only weather that isn't doing anything remains but that have weather data
uint32 chance1 = m_weatherChances->data[season].rainChance; uint32 chance1 = m_weatherChances->data[season].rainChance;
uint32 chance2 = chance1 + m_weatherChances->data[season].snowChance; uint32 chance2 = chance1 + m_weatherChances->data[season].snowChance;
uint32 chance3 = chance2 + m_weatherChances->data[season].stormChance; uint32 chance3 = chance2 + m_weatherChances->data[season].stormChance;
uint32 rnd = urand(0, 99); uint32 rnd = urand(0, 99);
if (rnd <= chance1) if (rnd <= chance1)
{
m_type = WEATHER_TYPE_RAIN; m_type = WEATHER_TYPE_RAIN;
}
else if (rnd <= chance2) else if (rnd <= chance2)
{
m_type = WEATHER_TYPE_SNOW; m_type = WEATHER_TYPE_SNOW;
}
else if (rnd <= chance3) else if (rnd <= chance3)
{
m_type = WEATHER_TYPE_STORM; m_type = WEATHER_TYPE_STORM;
}
else else
{
m_type = WEATHER_TYPE_FINE; m_type = WEATHER_TYPE_FINE;
}
/// New weather statistics (if not fine): /// New weather statistics (if not fine):
///- 85% light ///- 85% light
@ -182,20 +192,28 @@ bool Weather::ReGenerate()
// Severe change, but how severe? // Severe change, but how severe?
rnd = urand(0, 99); rnd = urand(0, 99);
if (rnd < 50) if (rnd < 50)
{
m_grade = rand_norm_f() * 0.3333f + 0.3334f; m_grade = rand_norm_f() * 0.3333f + 0.3334f;
}
else else
{
m_grade = rand_norm_f() * 0.3333f + 0.6667f; m_grade = rand_norm_f() * 0.3333f + 0.6667f;
}
} }
NormalizeGrade();
// return true only in case weather changes // return true only in case weather changes
return m_type != old_type || m_grade != old_grade; return m_type != old_type || m_grade != old_grade;
} }
void Weather::SendWeatherUpdateToPlayer(Player* player) void Weather::SendWeatherUpdateToPlayer(Player* player)
{ {
WorldPacket data(SMSG_WEATHER, (4 + 4 + 1)); NormalizeGrade();
WorldPacket data(SMSG_WEATHER, (4 + 4 + 1));
data << uint32(GetWeatherState()) << (float)m_grade << uint8(0); data << uint32(GetWeatherState()) << (float)m_grade << uint8(0);
player->GetSession()->SendPacket(&data); player->GetSession()->SendPacket(&data);
} }
@ -206,10 +224,9 @@ bool Weather::SendWeatherForPlayersInZone(Map const* _map)
WeatherState state = GetWeatherState(); WeatherState state = GetWeatherState();
// To be sent packet
WorldPacket data(SMSG_WEATHER, 4 + 4 + 1); WorldPacket data(SMSG_WEATHER, 4 + 4 + 1);
data << uint32(state); data << uint32(state) << (float)m_grade << uint8(0);
data << float(m_grade);
data << uint8(0); // 1 = instant change, 0 = smooth change
///- Send the weather packet to all players in this zone ///- Send the weather packet to all players in this zone
if (!_map->SendToPlayersInZone(&data, m_zone)) if (!_map->SendToPlayersInZone(&data, m_zone))
@ -224,15 +241,7 @@ bool Weather::SendWeatherForPlayersInZone(Map const* _map)
return true; return true;
} }
void Weather::SendFineWeatherUpdateToPlayer(Player* player) /*
{
WorldPacket data(SMSG_WEATHER, (4 + 4 + 1));
data << (uint32)WEATHER_STATE_FINE << (float)0.0f << uint8(0); // no sound
player->GetSession()->SendPacket(&data);
}
/// Send the new weather to all players in the zone
bool Weather::UpdateWeather() bool Weather::UpdateWeather()
{ {
Player* player = sWorld.FindPlayerInZone(m_zone); Player* player = sWorld.FindPlayerInZone(m_zone);
@ -297,7 +306,7 @@ bool Weather::UpdateWeather()
DETAIL_FILTER_LOG(LOG_FILTER_WEATHER, "Change the weather of zone %u to %s.", m_zone, wthstr); DETAIL_FILTER_LOG(LOG_FILTER_WEATHER, "Change the weather of zone %u to %s.", m_zone, wthstr);
return true; return true;
} } */
// Set the weather // Set the weather
void Weather::SetWeather(WeatherType type, float grade, Map const* _map, bool isPermanent) void Weather::SetWeather(WeatherType type, float grade, Map const* _map, bool isPermanent)
@ -312,18 +321,6 @@ void Weather::SetWeather(WeatherType type, float grade, Map const* _map, bool is
SendWeatherForPlayersInZone(_map); SendWeatherForPlayersInZone(_map);
} }
/// Set the weather
// pre Dev21 version - delete if not required ?
void Weather::SetWeather(WeatherType type, float grade)
{
if (m_type == type && m_grade == grade)
return;
m_type = type;
m_grade = grade;
UpdateWeather();
}
/// Get the sound number associated with the current weather /// Get the sound number associated with the current weather
WeatherState Weather::GetWeatherState() const WeatherState Weather::GetWeatherState() const
{ {
@ -421,5 +418,115 @@ void Weather::LogWeatherState(WeatherState state) const
} }
DETAIL_FILTER_LOG(LOG_FILTER_WEATHER, "Change the weather of zone %u (type %u, grade %f) to state %s.", m_zone, m_type, m_grade, wthstr); DETAIL_FILTER_LOG(LOG_FILTER_WEATHER, "Change the weather of zone %u (type %u, grade %f) to state %s.", m_zone, m_type, m_grade, wthstr);
} }
// ---------------------------------------------------------
// Weather System
// ---------------------------------------------------------
WeatherSystem::WeatherSystem(Map const* _map) : m_map(_map)
{}
WeatherSystem::~WeatherSystem()
{
///- Empty the WeatherMap
for (WeatherMap::const_iterator itr = m_weathers.begin(); itr != m_weathers.end(); ++itr)
delete itr->second;
m_weathers.clear();
}
/// Find or Create a Weather object by the given zoneid
Weather* WeatherSystem::FindOrCreateWeather(uint32 zoneId)
{
WeatherMap::const_iterator itr = m_weathers.find(zoneId);
// Return if found
if (itr != m_weathers.end())
return itr->second;
// Create
Weather* w = new Weather(zoneId, sWeatherMgr.GetWeatherChances(zoneId));
m_weathers[zoneId] = w;
return w;
}
/// Update Weathers for the different zones
void WeatherSystem::UpdateWeathers(uint32 diff)
{
///- Send an update signal to Weather objects
for (WeatherMap::iterator itr = m_weathers.begin(); itr != m_weathers.end();)
{
///- and remove Weather objects for zones with no player
// As interval > WorldTick
if (!itr->second->Update(diff, m_map))
{
delete itr->second;
m_weathers.erase(itr++);
}
else
++itr;
}
}
/// Load Weather chanced from table game_weather
void WeatherMgr::LoadWeatherZoneChances()
{
uint32 count = 0;
// 0 1 2 3 4 5 6 7 8 9 10 11 12
QueryResult* result = WorldDatabase.Query("SELECT zone, spring_rain_chance, spring_snow_chance, spring_storm_chance, summer_rain_chance, summer_snow_chance, summer_storm_chance, fall_rain_chance, fall_snow_chance, fall_storm_chance, winter_rain_chance, winter_snow_chance, winter_storm_chance FROM game_weather");
if (!result)
{
BarGoLink bar(1);
bar.step();
sLog.outErrorDb(">> Loaded 0 weather definitions. DB table `game_weather` is empty.");
sLog.outString();
return;
}
BarGoLink bar(result->GetRowCount());
do
{
Field* fields = result->Fetch();
bar.step();
uint32 zone_id = fields[0].GetUInt32();
WeatherZoneChances& wzc = mWeatherZoneMap[zone_id];
for (int season = 0; season < WEATHER_SEASONS; ++season)
{
wzc.data[season].rainChance = fields[season * (MAX_WEATHER_TYPE - 1) + 1].GetUInt32();
wzc.data[season].snowChance = fields[season * (MAX_WEATHER_TYPE - 1) + 2].GetUInt32();
wzc.data[season].stormChance = fields[season * (MAX_WEATHER_TYPE - 1) + 3].GetUInt32();
if (wzc.data[season].rainChance > 100)
{
wzc.data[season].rainChance = 25;
sLog.outErrorDb("Weather for zone %u season %u has wrong rain chance > 100%%", zone_id, season);
}
if (wzc.data[season].snowChance > 100)
{
wzc.data[season].snowChance = 25;
sLog.outErrorDb("Weather for zone %u season %u has wrong snow chance > 100%%", zone_id, season);
}
if (wzc.data[season].stormChance > 100)
{
wzc.data[season].stormChance = 25;
sLog.outErrorDb("Weather for zone %u season %u has wrong storm chance > 100%%", zone_id, season);
}
}
++count;
} while (result->NextRow());
delete result;
sLog.outString(">> Loaded %u weather definitions", count);
sLog.outString();
}

View file

@ -58,18 +58,15 @@ class Weather
{ {
public: public:
Weather(uint32 zone, WeatherZoneChances const* weatherChances); Weather(uint32 zone, WeatherZoneChances const* weatherChances);
~Weather() { }; ~Weather() {};
bool ReGenerate(); /// Send Weather to one player
bool UpdateWeather();
void SendWeatherUpdateToPlayer(Player* player); void SendWeatherUpdateToPlayer(Player* player);
bool SendWeatherForPlayersInZone(Map const* _map); /// Set the weather
static void SendFineWeatherUpdateToPlayer(Player* player);
void SetWeather(WeatherType type, float grade, Map const* _map, bool isPermanent); void SetWeather(WeatherType type, float grade, Map const* _map, bool isPermanent);
void SetWeather(WeatherType type, float grade); /// Update the weather in this zone, when the timer is expired the weather will be rolled again
/// For which zone is this weather? bool Update(uint32 diff, Map const* _map);
uint32 GetZone() { return m_zone; }; /// Check if a type is valid
bool Update(time_t diff);
static bool IsValidWeatherType(uint32 type) static bool IsValidWeatherType(uint32 type)
{ {
switch (type) switch (type)
@ -85,14 +82,17 @@ class Weather
return false; return false;
} }
} }
private: private:
/// Send SMSG_WEATHER to all players in the zone
bool SendWeatherForPlayersInZone(Map const* _map);
/// Calculate new weather
bool ReGenerate();
/// Calculate state based on type and grade
WeatherState GetWeatherState() const;
// Helper to get the grade between 0..1 // Helper to get the grade between 0..1
void NormalizeGrade(); void NormalizeGrade();
// Helper to log recent state // Helper to log recent state
void LogWeatherState(WeatherState state) const; void LogWeatherState(WeatherState state) const;
WeatherState GetWeatherState() const;
uint32 m_zone; uint32 m_zone;
WeatherType m_type; WeatherType m_type;
float m_grade; float m_grade;
@ -108,17 +108,59 @@ class Weather
/// Weathers for one map /// Weathers for one map
class WeatherSystem class WeatherSystem
{ {
public: public:
WeatherSystem(Map const* _map); WeatherSystem(Map const* _map);
~WeatherSystem(); ~WeatherSystem();
Weather* FindOrCreateWeather(uint32 zoneId); Weather* FindOrCreateWeather(uint32 zoneId);
void UpdateWeathers(uint32 diff); void UpdateWeathers(uint32 diff);
private: private:
Map const* const m_map; Map const* const m_map;
typedef UNORDERED_MAP<uint32 /*zoneId*/, Weather*> WeatherMap; typedef UNORDERED_MAP<uint32 /*zoneId*/, Weather*> WeatherMap;
WeatherMap m_weathers; WeatherMap m_weathers;
}; };
// ---------------------------------------------------------
// Global Weather Information
// ---------------------------------------------------------
#define WEATHER_SEASONS 4
struct WeatherSeasonChances
{
uint32 rainChance;
uint32 snowChance;
uint32 stormChance;
};
struct WeatherZoneChances
{
WeatherSeasonChances data[WEATHER_SEASONS];
};
class WeatherMgr
{
public:
WeatherMgr() {};
~WeatherMgr() {};
void LoadWeatherZoneChances();
WeatherZoneChances const* GetWeatherChances(uint32 zone_id) const
{
WeatherZoneMap::const_iterator itr = mWeatherZoneMap.find(zone_id);
if (itr != mWeatherZoneMap.end())
return &itr->second;
else
return NULL;
}
private:
typedef UNORDERED_MAP<uint32 /*zoneId*/, WeatherZoneChances> WeatherZoneMap;
WeatherZoneMap mWeatherZoneMap;
};
#define sWeatherMgr MaNGOS::Singleton<WeatherMgr>::Instance()
#endif #endif

View file

@ -76,6 +76,9 @@
#include "CreatureLinkingMgr.h" #include "CreatureLinkingMgr.h"
#include "Calendar.h" #include "Calendar.h"
#include "PhaseMgr.h" #include "PhaseMgr.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /*ENABLE_ELUNA*/
INSTANTIATE_SINGLETON_1(World); INSTANTIATE_SINGLETON_1(World);
@ -428,6 +431,9 @@ void World::RemoveWeather(uint32 id)
} }
/// Add a Weather object to the list /// Add a Weather object to the list
/*
* chucky - delete this?
* this is not in Two
Weather* World::AddWeather(uint32 zone_id) Weather* World::AddWeather(uint32 zone_id)
{ {
WeatherZoneChances const* weatherChances = sObjectMgr.GetWeatherChances(zone_id); WeatherZoneChances const* weatherChances = sObjectMgr.GetWeatherChances(zone_id);
@ -442,6 +448,7 @@ Weather* World::AddWeather(uint32 zone_id)
w->UpdateWeather(); w->UpdateWeather();
return w; return w;
} }
*/
/// Initialize config values /// Initialize config values
void World::LoadConfigSettings(bool reload) void World::LoadConfigSettings(bool reload)
@ -958,16 +965,16 @@ void World::SetInitialWorldSettings()
///- Check the existence of the map files for all races start areas. ///- Check the existence of the map files for all races start areas.
if (!MapManager::ExistMapAndVMap(0, -6240.32f, 331.033f) || // Dwarf/ Gnome if (!MapManager::ExistMapAndVMap(0, -6240.32f, 331.033f) || // Dwarf/ Gnome
!MapManager::ExistMapAndVMap(0, -8949.95f, -132.493f) || // Human !MapManager::ExistMapAndVMap(0, -8949.95f, -132.493f) || // Human
!MapManager::ExistMapAndVMap(1, -618.518f, -4251.67f) || // Orc !MapManager::ExistMapAndVMap(1, -618.518f, -4251.67f) || // Orc
!MapManager::ExistMapAndVMap(0, 1676.35f, 1677.45f) || // Scourge !MapManager::ExistMapAndVMap(0, 1676.35f, 1677.45f) || // Scourge
!MapManager::ExistMapAndVMap(1, 10311.3f, 832.463f) || // NightElf !MapManager::ExistMapAndVMap(1, 10311.3f, 832.463f) || // NightElf
!MapManager::ExistMapAndVMap(1, -2917.58f, -257.98f) || // Tauren !MapManager::ExistMapAndVMap(1, -2917.58f, -257.98f) || // Tauren
(m_configUint32Values[CONFIG_UINT32_EXPANSION] >= EXPANSION_TBC && (m_configUint32Values[CONFIG_UINT32_EXPANSION] >= EXPANSION_TBC &&
(!MapManager::ExistMapAndVMap(530, 10349.6f, -6357.29f) || // BloodElf (!MapManager::ExistMapAndVMap(530, 10349.6f, -6357.29f) || // BloodElf
!MapManager::ExistMapAndVMap(530, -3961.64f, -13931.2f))) || // Draenei !MapManager::ExistMapAndVMap(530, -3961.64f, -13931.2f))) || // Draenei
(m_configUint32Values[CONFIG_UINT32_EXPANSION] >= EXPANSION_WOTLK && (m_configUint32Values[CONFIG_UINT32_EXPANSION] >= EXPANSION_WOTLK &&
!MapManager::ExistMapAndVMap(609, 2355.84f, -5664.77f))) // Death Knight !MapManager::ExistMapAndVMap(609, 2355.84f, -5664.77f))) // Death Knight
{ {
sLog.outError("Correct *.map files not found in path '%smaps' or *.vmtree/*.vmtile files in '%svmaps'. Please place *.map and vmap files in appropriate directories or correct the DataDir value in the mangosd.conf file.", m_dataPath.c_str(), m_dataPath.c_str()); sLog.outError("Correct *.map files not found in path '%smaps' or *.vmtree/*.vmtile files in '%svmaps'. Please place *.map and vmap files in appropriate directories or correct the DataDir value in the mangosd.conf file.", m_dataPath.c_str(), m_dataPath.c_str());
Log::WaitBeforeContinueIfNeed(); Log::WaitBeforeContinueIfNeed();
@ -997,16 +1004,15 @@ void World::SetInitialWorldSettings()
///- Load the DBC files ///- Load the DBC files
sLog.outString("Initialize data stores..."); sLog.outString("Initialize data stores...");
LoadDBCStores(m_dataPath); LoadDBCStores(m_dataPath);
LoadDB2Stores(m_dataPath);
DetectDBCLang(); DetectDBCLang();
sObjectMgr.SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts) sObjectMgr.SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts)
sLog.outString("Loading SpellTemplate...");
sObjectMgr.LoadSpellTemplate();
sLog.outString("Loading Script Names..."); sLog.outString("Loading Script Names...");
sScriptMgr.LoadScriptNames(); sScriptMgr.LoadScriptNames();
sLog.outString("Loading WorldTemplate...");
sObjectMgr.LoadWorldTemplate();
sLog.outString("Loading InstanceTemplate..."); sLog.outString("Loading InstanceTemplate...");
sObjectMgr.LoadInstanceTemplate(); sObjectMgr.LoadInstanceTemplate();
@ -1030,6 +1036,12 @@ void World::SetInitialWorldSettings()
sObjectMgr.SetHighestGuids(); // must be after PackInstances() and PackGroupIds() sObjectMgr.SetHighestGuids(); // must be after PackInstances() and PackGroupIds()
sLog.outString(); sLog.outString();
#ifdef ENABLE_ELUNA
///- Initialize Lua Engine
sLog.outString("Initialize Eluna Lua Engine...");
Eluna::Initialize();
#endif /* ENABLE_ELUNA */
sLog.outString("Loading Page Texts..."); sLog.outString("Loading Page Texts...");
sObjectMgr.LoadPageTexts(); sObjectMgr.LoadPageTexts();
@ -1084,6 +1096,9 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading Equipment templates..."); sLog.outString("Loading Equipment templates...");
sObjectMgr.LoadEquipmentTemplates(); sObjectMgr.LoadEquipmentTemplates();
sLog.outString("Loading Creature Stats...");
sObjectMgr.LoadCreatureClassLvlStats();
sLog.outString("Loading Creature templates..."); sLog.outString("Loading Creature templates...");
sObjectMgr.LoadCreatureTemplates(); sObjectMgr.LoadCreatureTemplates();
@ -1142,7 +1157,7 @@ void World::SetInitialWorldSettings()
sPoolMgr.LoadFromDB(); sPoolMgr.LoadFromDB();
sLog.outString("Loading Weather Data..."); sLog.outString("Loading Weather Data...");
sObjectMgr.LoadWeatherZoneChances(); sWeatherMgr.LoadWeatherZoneChances();
sLog.outString("Loading Quests..."); sLog.outString("Loading Quests...");
sObjectMgr.LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables sObjectMgr.LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables
@ -1166,12 +1181,6 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading Conditions..."); sLog.outString("Loading Conditions...");
sObjectMgr.LoadConditions(); sObjectMgr.LoadConditions();
sLog.outString("Loading Phase definitions...");
sObjectMgr.LoadPhaseDefinitions();
sLog.outString("Loading Spell Phase Dbc Info...");
sObjectMgr.LoadSpellPhaseInfo();
sLog.outString("Creating map persistent states for non-instanceable maps..."); // must be after PackInstances(), LoadCreatures(), sPoolMgr.LoadFromDB(), sGameEventMgr.LoadFromDB(); sLog.outString("Creating map persistent states for non-instanceable maps..."); // must be after PackInstances(), LoadCreatures(), sPoolMgr.LoadFromDB(), sGameEventMgr.LoadFromDB();
sMapPersistentStateMgr.InitWorldMaps(); sMapPersistentStateMgr.InitWorldMaps();
@ -1196,11 +1205,10 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading Tavern Area Triggers..."); sLog.outString("Loading Tavern Area Triggers...");
sObjectMgr.LoadTavernAreaTriggers(); sObjectMgr.LoadTavernAreaTriggers();
sLog.outString("Loading AreaTrigger script names..."); #ifdef ENABLE_SD3
sScriptMgr.LoadAreaTriggerScripts(); sLog.outString("Loading all script bindings...");
sScriptMgr.LoadScriptBinding();
sLog.outString("Loading event id script names..."); #endif /* ENABLE_SD3 */
sScriptMgr.LoadEventIdScripts();
sLog.outString("Loading Graveyard-zone links..."); sLog.outString("Loading Graveyard-zone links...");
sObjectMgr.LoadGraveyardZones(); sObjectMgr.LoadGraveyardZones();
@ -1339,8 +1347,14 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading GM tickets..."); sLog.outString("Loading GM tickets...");
sTicketMgr.LoadGMTickets(); sTicketMgr.LoadGMTickets();
sLog.outString("Loading hotfix data..."); sLog.outString("Loading Dungeon Finder Requirements...");
sObjectMgr.LoadHotfixData(); sObjectMgr.LoadDungeonFinderRequirements();
sLog.outString("Loading Dungeon Finder Rewards...");
sObjectMgr.LoadDungeonFinderRewards();
sLog.outString("Loading Dungeon Finder Items...");
sObjectMgr.LoadDungeonFinderItems();
///- Handle outdated emails (delete/return) ///- Handle outdated emails (delete/return)
sLog.outString("Returning old mails..."); sLog.outString("Returning old mails...");
@ -1372,21 +1386,25 @@ void World::SetInitialWorldSettings()
sEventAIMgr.LoadCreatureEventAI_Scripts(); sEventAIMgr.LoadCreatureEventAI_Scripts();
sLog.outString("Initializing Scripts..."); sLog.outString("Initializing Scripts...");
#ifdef ENABLE_SD3
switch (sScriptMgr.LoadScriptLibrary(MANGOS_SCRIPT_NAME)) switch (sScriptMgr.LoadScriptLibrary(MANGOS_SCRIPT_NAME))
{ {
case SCRIPT_LOAD_OK: case SCRIPT_LOAD_OK:
sLog.outString("Scripting library loaded."); sLog.outString("Scripting library loaded.");
break; break;
case SCRIPT_LOAD_ERR_NOT_FOUND: case SCRIPT_LOAD_ERR_NOT_FOUND:
sLog.outError("Scripting library not found or not accessible."); sLog.outError("Scripting library not found or not accessible.");
break; break;
case SCRIPT_LOAD_ERR_WRONG_API: case SCRIPT_LOAD_ERR_WRONG_API:
sLog.outError("Scripting library has wrong list functions (outdated?)."); sLog.outError("Scripting library has wrong list functions (outdated?).");
break; break;
case SCRIPT_LOAD_ERR_OUTDATED: case SCRIPT_LOAD_ERR_OUTDATED:
sLog.outError("Scripting library build for old mangosd revision. You need rebuild it."); sLog.outError("Scripting library build for old mangosd revision. You need rebuild it.");
break; break;
} }
#else /* ENABLE_SD3 */
sLog.outError("SD3 was not included in compilation, not using it.");
#endif /* ENABLE_SD3 */
///- Initialize game time and timers ///- Initialize game time and timers
sLog.outString("DEBUG:: Initialize game time and timers"); sLog.outString("DEBUG:: Initialize game time and timers");
@ -1399,12 +1417,11 @@ void World::SetInitialWorldSettings()
local = *(localtime(&curr)); // dereference and assign local = *(localtime(&curr)); // dereference and assign
char isoDate[128]; char isoDate[128];
sprintf(isoDate, "%04d-%02d-%02d %02d:%02d:%02d", sprintf(isoDate, "%04d-%02d-%02d %02d:%02d:%02d",
local.tm_year + 1900, local.tm_mon + 1, local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec); local.tm_year + 1900, local.tm_mon + 1, local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec);
LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, startstring, uptime) VALUES('%u', " UI64FMTD ", '%s', 0)", LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, startstring, uptime) VALUES('%u', " UI64FMTD ", '%s', 0)",
realmID, uint64(m_startTime), isoDate); realmID, uint64(m_startTime), isoDate);
m_timers[WUPDATE_WEATHERS].SetInterval(1 * IN_MILLISECONDS);
m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE * IN_MILLISECONDS); m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE * IN_MILLISECONDS);
m_timers[WUPDATE_UPTIME].SetInterval(getConfig(CONFIG_UINT32_UPTIME_UPDATE)*MINUTE * IN_MILLISECONDS); m_timers[WUPDATE_UPTIME].SetInterval(getConfig(CONFIG_UINT32_UPTIME_UPDATE)*MINUTE * IN_MILLISECONDS);
// Update "uptime" table based on configuration entry in minutes. // Update "uptime" table based on configuration entry in minutes.
@ -1414,6 +1431,9 @@ void World::SetInitialWorldSettings()
// for AhBot // for AhBot
m_timers[WUPDATE_AHBOT].SetInterval(20 * IN_MILLISECONDS); // every 20 sec m_timers[WUPDATE_AHBOT].SetInterval(20 * IN_MILLISECONDS); // every 20 sec
// for Dungeon Finder
m_timers[WUPDATE_LFGMGR].SetInterval(30 * IN_MILLISECONDS); // every 30 sec
// to set mailtimer to return mails every day between 4 and 5 am // to set mailtimer to return mails every day between 4 and 5 am
// mailtimer is increased when updating auctions // mailtimer is increased when updating auctions
// one second is 1000 -(tested on win system) // one second is 1000 -(tested on win system)
@ -1433,6 +1453,7 @@ void World::SetInitialWorldSettings()
///- Initialize Battlegrounds ///- Initialize Battlegrounds
sLog.outString("Starting BattleGround System"); sLog.outString("Starting BattleGround System");
sBattleGroundMgr.CreateInitialBattleGrounds(); sBattleGroundMgr.CreateInitialBattleGrounds();
sBattleGroundMgr.InitAutomaticArenaPointDistribution();
///- Initialize Outdoor PvP ///- Initialize Outdoor PvP
sLog.outString("Starting Outdoor PvP System"); sLog.outString("Starting Outdoor PvP System");
@ -1442,13 +1463,19 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading Transports..."); sLog.outString("Loading Transports...");
sMapMgr.LoadTransports(); sMapMgr.LoadTransports();
// Initialize Warden
sLog.outString("Loading Warden Checks...");
sWardenCheckMgr->LoadWardenChecks();
sLog.outString();
sLog.outString("Loading Warden Action Overrides...");
sWardenCheckMgr->LoadWardenOverrides();
sLog.outString();
sLog.outString("Deleting expired bans..."); sLog.outString("Deleting expired bans...");
LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
sLog.outString("Calculate next currency reset time..."); sLog.outString("Calculate next daily quest and dungeon reset time...");
InitCurrencyResetTime();
sLog.outString("Calculate next daily quest reset time...");
InitDailyQuestResetTime(); InitDailyQuestResetTime();
sLog.outString("Calculate next weekly quest reset time..."); sLog.outString("Calculate next weekly quest reset time...");
@ -1457,6 +1484,9 @@ void World::SetInitialWorldSettings()
sLog.outString("Calculate next monthly quest reset time..."); sLog.outString("Calculate next monthly quest reset time...");
SetMonthlyQuestResetTime(); SetMonthlyQuestResetTime();
sLog.outString("Calculate random battleground reset time...");
InitRandomBGResetTime();
sLog.outString("Starting Game Event system..."); sLog.outString("Starting Game Event system...");
uint32 nextGameEvent = sGameEventMgr.Initialize(); uint32 nextGameEvent = sGameEventMgr.Initialize();
m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent); // depend on next event m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent); // depend on next event
@ -1467,6 +1497,13 @@ void World::SetInitialWorldSettings()
sLog.outString("Initialize AuctionHouseBot..."); sLog.outString("Initialize AuctionHouseBot...");
sAuctionBot.Initialize(); sAuctionBot.Initialize();
#ifdef ENABLE_ELUNA
///- Run eluna scripts.
// in multithread foreach: run scripts
sEluna->RunScripts();
sEluna->OnConfigLoad(false); // Must be done after Eluna is initialized and scripts have run.
#endif
sLog.outString("WORLD: World initialized"); sLog.outString("WORLD: World initialized");
uint32 uStartInterval = WorldTimer::getMSTimeDiff(uStartTime, WorldTimer::getMSTime()); uint32 uStartInterval = WorldTimer::getMSTimeDiff(uStartTime, WorldTimer::getMSTime());
@ -1526,9 +1563,13 @@ void World::Update(uint32 diff)
for (int i = 0; i < WUPDATE_COUNT; ++i) for (int i = 0; i < WUPDATE_COUNT; ++i)
{ {
if (m_timers[i].GetCurrent() >= 0) if (m_timers[i].GetCurrent() >= 0)
{
m_timers[i].Update(diff); m_timers[i].Update(diff);
}
else else
{
m_timers[i].SetCurrent(0); m_timers[i].SetCurrent(0);
}
} }
///- Update the game time and check for shutdown time ///- Update the game time and check for shutdown time
@ -1537,9 +1578,12 @@ void World::Update(uint32 diff)
///-Update mass mailer tasks if any ///-Update mass mailer tasks if any
sMassMailMgr.Update(); sMassMailMgr.Update();
/// Handle daily quests reset time /// Handle daily quests and dungeon reset time
if (m_gameTime > m_NextDailyQuestReset) if (m_gameTime > m_NextDailyQuestReset)
{
ResetDailyQuests(); ResetDailyQuests();
sLFGMgr.ResetDailyRecords();
}
/// Handle weekly quests reset time /// Handle weekly quests reset time
if (m_gameTime > m_NextWeeklyQuestReset) if (m_gameTime > m_NextWeeklyQuestReset)
@ -1549,9 +1593,9 @@ void World::Update(uint32 diff)
if (m_gameTime > m_NextMonthlyQuestReset) if (m_gameTime > m_NextMonthlyQuestReset)
ResetMonthlyQuests(); ResetMonthlyQuests();
/// Handle monthly quests reset time /// Handle random battlegrounds reset time
if (m_gameTime > m_NextCurrencyReset) if (m_gameTime > m_NextRandomBGReset)
ResetCurrencyWeekCounts(); ResetRandomBG();
/// <ul><li> Handle auctions when the timer has passed /// <ul><li> Handle auctions when the timer has passed
if (m_timers[WUPDATE_AUCTIONS].Passed()) if (m_timers[WUPDATE_AUCTIONS].Passed())
@ -1577,28 +1621,16 @@ void World::Update(uint32 diff)
m_timers[WUPDATE_AHBOT].Reset(); m_timers[WUPDATE_AHBOT].Reset();
} }
/// <li> Update Dungeon Finder
if (m_timers[WUPDATE_LFGMGR].Passed())
{
sLFGMgr.Update();
m_timers[WUPDATE_LFGMGR].Reset();
}
/// <li> Handle session updates /// <li> Handle session updates
UpdateSessions(diff); UpdateSessions(diff);
/// <li> Handle weather updates when the timer has passed
if (m_timers[WUPDATE_WEATHERS].Passed())
{
///- Send an update signal to Weather objects
for (WeatherMap::iterator itr = m_weathers.begin(); itr != m_weathers.end();)
{
///- and remove Weather objects for zones with no player
// As interval > WorldTick
if (!itr->second->Update(m_timers[WUPDATE_WEATHERS].GetInterval()))
{
delete itr->second;
m_weathers.erase(itr++);
}
else
++itr;
}
m_timers[WUPDATE_WEATHERS].SetCurrent(0);
}
/// <li> Update uptime table /// <li> Update uptime table
if (m_timers[WUPDATE_UPTIME].Passed()) if (m_timers[WUPDATE_UPTIME].Passed())
{ {
@ -1615,6 +1647,11 @@ void World::Update(uint32 diff)
sBattleGroundMgr.Update(diff); sBattleGroundMgr.Update(diff);
sOutdoorPvPMgr.Update(diff); sOutdoorPvPMgr.Update(diff);
///- Used by Eluna
#ifdef ENABLE_ELUNA
sEluna->OnWorldUpdate(diff);
#endif
///- Delete all characters which have been deleted X days before ///- Delete all characters which have been deleted X days before
if (m_timers[WUPDATE_DELETECHARS].Passed()) if (m_timers[WUPDATE_DELETECHARS].Passed())
{ {
@ -1652,6 +1689,11 @@ void World::Update(uint32 diff)
// And last, but not least handle the issued cli commands // And last, but not least handle the issued cli commands
ProcessCliCommands(); ProcessCliCommands();
///- Used by Eluna
#ifdef ENABLE_ELUNA
sEluna->OnWorldUpdate(diff);
#endif /* ENABLE_ELUNA */
// cleanup unused GridMap objects as well as VMaps // cleanup unused GridMap objects as well as VMaps
sTerrainMgr.Update(diff); sTerrainMgr.Update(diff);
} }
@ -2241,6 +2283,18 @@ void World::ResetDailyQuests()
CharacterDatabase.PExecute("UPDATE saved_variables SET NextDailyQuestResetTime = '" UI64FMTD "'", uint64(m_NextDailyQuestReset)); CharacterDatabase.PExecute("UPDATE saved_variables SET NextDailyQuestResetTime = '" UI64FMTD "'", uint64(m_NextDailyQuestReset));
} }
void World::ResetRandomBG()
{
sLog.outDetail("Random BG status reset for all characters.");
CharacterDatabase.Execute("DELETE FROM character_battleground_random");
for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
if (itr->second->GetPlayer())
itr->second->GetPlayer()->SetRandomWinner(false);
m_NextRandomBGReset = time_t(m_NextRandomBGReset + DAY);
CharacterDatabase.PExecute("UPDATE saved_variables SET NextRandomBGResetTime = '" UI64FMTD "'", uint64(m_NextRandomBGReset));
}
void World::ResetWeeklyQuests() void World::ResetWeeklyQuests()
{ {
DETAIL_LOG("Weekly quests reset for all characters."); DETAIL_LOG("Weekly quests reset for all characters.");

View file

@ -78,13 +78,14 @@ enum ShutdownExitCode
enum WorldTimers enum WorldTimers
{ {
WUPDATE_AUCTIONS = 0, WUPDATE_AUCTIONS = 0,
WUPDATE_WEATHERS = 1, WUPDATE_UPTIME = 1,
WUPDATE_UPTIME = 2, WUPDATE_CORPSES = 2,
WUPDATE_CORPSES = 3, WUPDATE_EVENTS = 3,
WUPDATE_EVENTS = 4, WUPDATE_DELETECHARS = 4,
WUPDATE_DELETECHARS = 5, WUPDATE_AHBOT = 5,
WUPDATE_AHBOT = 6, WUPDATE_LFGMGR = 6,
WUPDATE_COUNT = 7 WUPDATE_WEATHERS = 7,
WUPDATE_COUNT = 8
}; };
/// Configuration elements /// Configuration elements
@ -126,6 +127,11 @@ enum eConfigUInt32Values
CONFIG_UINT32_MAX_PLAYER_LEVEL, CONFIG_UINT32_MAX_PLAYER_LEVEL,
CONFIG_UINT32_START_PLAYER_LEVEL, CONFIG_UINT32_START_PLAYER_LEVEL,
CONFIG_UINT32_START_HEROIC_PLAYER_LEVEL, CONFIG_UINT32_START_HEROIC_PLAYER_LEVEL,
CONFIG_UINT32_START_PLAYER_MONEY,
CONFIG_UINT32_MAX_HONOR_POINTS,
CONFIG_UINT32_START_HONOR_POINTS,
CONFIG_UINT32_MAX_ARENA_POINTS,
CONFIG_UINT32_START_ARENA_POINTS,
CONFIG_UINT32_CURRENCY_START_HONOR_POINTS, CONFIG_UINT32_CURRENCY_START_HONOR_POINTS,
CONFIG_UINT32_CURRENCY_START_CONQUEST_POINTS, CONFIG_UINT32_CURRENCY_START_CONQUEST_POINTS,
CONFIG_UINT32_CURRENCY_CONQUEST_POINTS_DEFAULT_WEEK_CAP, CONFIG_UINT32_CURRENCY_CONQUEST_POINTS_DEFAULT_WEEK_CAP,
@ -190,6 +196,7 @@ enum eConfigUInt32Values
CONFIG_UINT32_BATTLEGROUND_QUEUE_ANNOUNCER_JOIN, CONFIG_UINT32_BATTLEGROUND_QUEUE_ANNOUNCER_JOIN,
CONFIG_UINT32_ARENA_MAX_RATING_DIFFERENCE, CONFIG_UINT32_ARENA_MAX_RATING_DIFFERENCE,
CONFIG_UINT32_ARENA_RATING_DISCARD_TIMER, CONFIG_UINT32_ARENA_RATING_DISCARD_TIMER,
CONFIG_UINT32_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS,
CONFIG_UINT32_ARENA_SEASON_ID, CONFIG_UINT32_ARENA_SEASON_ID,
CONFIG_UINT32_ARENA_SEASON_PREVIOUS_ID, CONFIG_UINT32_ARENA_SEASON_PREVIOUS_ID,
CONFIG_UINT32_CLIENTCACHE_VERSION, CONFIG_UINT32_CLIENTCACHE_VERSION,
@ -347,6 +354,7 @@ enum eConfigBoolValues
CONFIG_BOOL_SKILL_FAIL_POSSIBLE_FISHINGPOOL, CONFIG_BOOL_SKILL_FAIL_POSSIBLE_FISHINGPOOL,
CONFIG_BOOL_BATTLEGROUND_CAST_DESERTER, CONFIG_BOOL_BATTLEGROUND_CAST_DESERTER,
CONFIG_BOOL_BATTLEGROUND_QUEUE_ANNOUNCER_START, CONFIG_BOOL_BATTLEGROUND_QUEUE_ANNOUNCER_START,
CONFIG_BOOL_ARENA_AUTO_DISTRIBUTE_POINTS,
CONFIG_BOOL_ARENA_QUEUE_ANNOUNCER_JOIN, CONFIG_BOOL_ARENA_QUEUE_ANNOUNCER_JOIN,
CONFIG_BOOL_ARENA_QUEUE_ANNOUNCER_EXIT, CONFIG_BOOL_ARENA_QUEUE_ANNOUNCER_EXIT,
CONFIG_BOOL_OUTDOORPVP_SI_ENABLED, CONFIG_BOOL_OUTDOORPVP_SI_ENABLED,
@ -636,6 +644,7 @@ class World
void SetMonthlyQuestResetTime(bool initialize = true); void SetMonthlyQuestResetTime(bool initialize = true);
void ResetCurrencyWeekCounts(); void ResetCurrencyWeekCounts();
void ResetDailyQuests(); void ResetDailyQuests();
void ResetRandomBG();
void ResetWeeklyQuests(); void ResetWeeklyQuests();
void ResetMonthlyQuests(); void ResetMonthlyQuests();
@ -714,7 +723,10 @@ class World
time_t m_NextCurrencyReset; time_t m_NextCurrencyReset;
time_t m_NextDailyQuestReset; time_t m_NextDailyQuestReset;
time_t m_NextWeeklyQuestReset; time_t m_NextWeeklyQuestReset;
time_t m_NextMonthlyQuestReset; time_t m_NextMonthlyQuestReset;
// next daily quests reset time
time_t m_NextRandomBGReset;
// Player Queue // Player Queue
Queue m_QueuedSessions; Queue m_QueuedSessions;

View file

@ -2104,7 +2104,7 @@ namespace LuaPlayer
if (!quest || player->GetQuestStatus(entry) != QUEST_STATUS_COMPLETE) if (!quest || player->GetQuestStatus(entry) != QUEST_STATUS_COMPLETE)
return 0; return 0;
player->RewardQuest(quest, 0, player); player->RewardQuest(quest, 0, player, false);
return 0; return 0;
} }

View file

@ -148,7 +148,7 @@ void DoOrSimulateScriptTextForMap(int32 iTextEntry, uint32 uiCreatureEntry, Map*
} }
debug_log("SD2: DoOrSimulateScriptTextForMap: text entry=%i, Sound=%u, Type=%u, Language=%u, Emote=%u", debug_log("SD2: DoOrSimulateScriptTextForMap: text entry=%i, Sound=%u, Type=%u, Language=%u, Emote=%u",
iTextEntry, pData->SoundId, pData->Type, pData->Language, pData->Emote); iTextEntry, pData->SoundId, pData->Type, pData->LanguageId, pData->Emote);
if (pData->Type != CHAT_TYPE_ZONE_YELL) if (pData->Type != CHAT_TYPE_ZONE_YELL)
{ {
@ -163,11 +163,11 @@ void DoOrSimulateScriptTextForMap(int32 iTextEntry, uint32 uiCreatureEntry, Map*
if (pCreatureSource) // If provided pointer for sayer, use direct version if (pCreatureSource) // If provided pointer for sayer, use direct version
{ {
pMap->MonsterYellToMap(pCreatureSource->GetObjectGuid(), iTextEntry, pData->Language, pTarget); pMap->MonsterYellToMap(pCreatureSource->GetObjectGuid(), iTextEntry, pData->LanguageId, pTarget);
} }
else // Simulate yell else // Simulate yell
{ {
pMap->MonsterYellToMap(pInfo, iTextEntry, pData->Language, pTarget); pMap->MonsterYellToMap(pInfo, iTextEntry, pData->LanguageId, pTarget);
} }
} }