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:
ObjectGuid GetObjectGuid() { return ObjectGuid(HIGHGUID_BATTLEGROUND, uint32(m_ArenaType), uint32(m_TypeID)); }
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; }
// the instanceId check is also used to determine a bg-template
// that's why the m_map hack is here..
@ -581,6 +591,7 @@ class BattleGround
private:
/* Battleground */
BattleGroundTypeId m_TypeID;
BattleGroundTypeId m_RandomTypeID;
BattleGroundStatus m_Status;
uint32 m_ClientInstanceID; // the instance-id which is sent to the client and without any other internal use
uint32 m_StartTime;

View file

@ -1131,10 +1131,12 @@ void BGQueueRemoveEvent::Abort(uint64 /*e_time*/)
/*** 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)
{
m_BattleGrounds[i].clear();
}
m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_UINT32_ARENA_RATING_DISCARD_TIMER);
m_Testing = false;
}
@ -1973,6 +1975,80 @@ void BattleGroundMgr::CreateInitialBattleGrounds()
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)
{
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> GameObjectBattleEventIndexesMap;
#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day
#define COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME 10
struct GroupQueueInfo; // type predefinition
@ -239,6 +240,8 @@ class BattleGroundMgr
uint32 GetRatingDiscardTimer() const;
uint32 GetPrematureFinishTime() const;
void InitAutomaticArenaPointDistribution();
// void DistributeArenaPoints(); // there does not appear to be a way to do this in Three
void ToggleArenaTesting();
void ToggleTesting();
@ -291,6 +294,8 @@ class BattleGroundMgr
typedef std::set<uint32> ClientBattleGroundIdSet;
ClientBattleGroundIdSet m_ClientBattleGroundIds[MAX_BATTLEGROUND_TYPE_ID][MAX_BATTLEGROUND_BRACKETS]; // the instanceids just visible for the client
uint32 m_NextRatingDiscardUpdate;
time_t m_NextAutoDistributionTime;
uint32 m_AutoDistributionTimeChecker;
bool m_ArenaTesting;
bool m_Testing;
};

View file

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

View file

@ -558,6 +558,33 @@ ArenaType ArenaTeam::GetTypeBySlot(uint8 slot)
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
{
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()
{
// save team and member stats to db

View file

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

View file

@ -238,6 +238,17 @@ struct CreatureDataAddon
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
{
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);
}
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()
{
sEquipmentStorage.Load();
@ -6993,6 +7069,112 @@ void ObjectMgr::LoadQuestPOI()
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()
{
uint32 count = 0;
@ -7100,68 +7282,57 @@ void ObjectMgr::GetConditions(uint32 conditionId, std::vector<PlayerCondition co
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;
// 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)
template<class S, class D>
void default_fill(uint32 field_pos, S src, D& dst)
{
BarGoLink bar(1);
bar.step();
sLog.outString();
sLog.outErrorDb(">> Loaded 0 weather definitions. DB table `game_weather` is empty.");
return;
if (field_pos == LOADED_SPELLDBC_FIELD_POS_EQUIPPED_ITEM_CLASS)
dst = D(-1);
else
dst = D(src);
}
BarGoLink bar(result->GetRowCount());
do
void default_fill_to_str(uint32 field_pos, char const* /*src*/, char * & dst)
{
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)
if (field_pos == LOADED_SPELLDBC_FIELD_POS_SPELLNAME_0)
{
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);
}
dst = SERVER_SIDE_SPELL;
}
else
{
dst = new char[1];
*dst = 0;
}
++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(">> 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)
@ -7737,7 +7908,7 @@ bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min
{
data.SoundId = fields[10].GetUInt32();
data.Type = fields[11].GetUInt32();
data.Language = fields[12].GetUInt32();
data.LanguageId = (Language)fields[12].GetUInt32();
data.Emote = fields[13].GetUInt32();
if (data.SoundId && !sSoundEntriesStore.LookupEntry(data.SoundId))
@ -7746,10 +7917,10 @@ bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min
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);
data.Language = LANG_UNIVERSAL;
_DoStringError(entry, "Entry %i in table `%s` using Language %u but Language does not exist.", entry, table, data.LanguageId);
data.LanguageId = LANG_UNIVERSAL;
}
if (data.Type > CHAT_TYPE_ZONE_YELL)
@ -10107,10 +10278,10 @@ bool DoDisplayText(WorldObject* source, int32 entry, Unit const* target /*=NULL*
switch (data->Type)
{
case CHAT_TYPE_SAY:
source->MonsterSay(entry, data->Language, target);
source->MonsterSay(entry, data->LanguageId, target);
break;
case CHAT_TYPE_YELL:
source->MonsterYell(entry, data->Language, target);
source->MonsterYell(entry, data->LanguageId, target);
break;
case CHAT_TYPE_TEXT_EMOTE:
source->MonsterTextEmote(entry, target);
@ -10141,7 +10312,7 @@ bool DoDisplayText(WorldObject* source, int32 entry, Unit const* target /*=NULL*
break;
}
case CHAT_TYPE_ZONE_YELL:
source->MonsterYellToZone(entry, data->Language, target);
source->MonsterYellToZone(entry, data->LanguageId, target);
break;
}

View file

@ -141,12 +141,12 @@ static_assert(MAX_DB_SCRIPT_STRING_ID < ACE_INT32_MAX, "Must scope with int32 ra
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
uint32 SoundId;
uint8 Type;
uint32 Language;
Language LanguageId;
uint32 Emote; // 0 -> default, i -> i-1 locale index
};
@ -333,19 +333,6 @@ struct QuestPOI
typedef std::vector<QuestPOI> QuestPOIVector;
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
{
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::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
{
uint32 safeLocId;
@ -548,8 +580,6 @@ class ObjectMgr
typedef UNORDERED_MAP<uint32, PointOfInterest> PointOfInterestMap;
typedef UNORDERED_MAP<uint32, WeatherZoneChances> WeatherZoneMap;
void LoadGameobjectInfo();
void AddGameobjectInfo(GameObjectInfo* goinfo);
@ -713,6 +743,7 @@ class ObjectMgr
void LoadCreatureTemplates();
void LoadCreatures();
void LoadCreatureAddons();
void LoadCreatureClassLvlStats();
void LoadCreatureModelInfo();
void LoadCreatureModelRace();
void LoadEquipmentTemplates();
@ -759,10 +790,14 @@ class ObjectMgr
void LoadPointsOfInterest();
void LoadQuestPOI();
void LoadDungeonFinderRequirements();
void LoadDungeonFinderRewards();
void LoadDungeonFinderItems();
void LoadNPCSpellClickSpells();
void LoadSpellTemplate();
void LoadCreatureTemplateSpells();
void LoadWeatherZoneChances();
void LoadGameTele();
void LoadNpcGossips();
@ -826,15 +861,6 @@ class ObjectMgr
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
{
CreatureDataMap::const_iterator itr = mCreatureDataMap.find(guid);
@ -1217,7 +1243,9 @@ class ObjectMgr
QuestPOIMap mQuestPOIMap;
WeatherZoneMap mWeatherZoneMap;
DungeonFinderRequirementsMap mDungeonFinderRequirementsMap;
DungeonFinderRewardsMap mDungeonFinderRewardsMap;
DungeonFinderItemsMap mDungeonFinderItemsMap;
// character reserved names
typedef std::set<std::wstring> ReservedNamesMap;
@ -1277,6 +1305,9 @@ class ObjectMgr
HalfNameMap PetHalfName0;
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;
CreatureDataMap mCreatureDataMap;
CreatureLocaleMap mCreatureLocaleMap;

View file

@ -74,6 +74,9 @@
#include "Vehicle.h"
#include "Calendar.h"
#include "PhaseMgr.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /*ENABLE_ELUNA*/
#include <cmath>
@ -1944,6 +1947,13 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
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()
{
ScheduleDelayedOperation(DELAYED_BG_MOUNT_RESTORE);
@ -6898,8 +6908,6 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
if (!zone)
return;
phaseMgr->AddUpdateFlag(PHASE_UPDATE_FLAG_ZONE_UPDATE);
if (m_zoneUpdateId != newZone)
{
// handle outdoor pvp zones
@ -6910,17 +6918,16 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
if (sWorld.getConfig(CONFIG_BOOL_WEATHER))
{
if (Weather* wth = sWorld.FindWeather(zone->ID))
wth->SendWeatherUpdateToPlayer(this);
else if (!sWorld.AddWeather(zone->ID))
{
// send fine weather packet to remove old zone's weather
Weather::SendFineWeatherUpdateToPlayer(this);
}
Weather* wth = GetMap()->GetWeatherSystem()->FindOrCreateWeather(newZone);
wth->SendWeatherUpdateToPlayer(this);
}
}
m_zoneUpdateId = newZone;
#ifdef ENABLE_ELUNA
sEluna->OnUpdateZone(this, newZone, newArea);
#endif
m_zoneUpdateId = newZone;
m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL;
// 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
switch (zone->team)
{
case AREATEAM_ALLY:
pvpInfo.inHostileArea = GetTeam() != ALLIANCE && (sWorld.IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
break;
case AREATEAM_HORDE:
pvpInfo.inHostileArea = GetTeam() != HORDE && (sWorld.IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
break;
case AREATEAM_NONE:
// overwrite for battlegrounds, maybe batter some zone flags but current known not 100% fit to this
pvpInfo.inHostileArea = sWorld.IsPvPRealm() || InBattleGround();
break;
default: // 6 in fact
pvpInfo.inHostileArea = false;
break;
case AREATEAM_ALLY:
pvpInfo.inHostileArea = GetTeam() != ALLIANCE && (sWorld.IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
break;
case AREATEAM_HORDE:
pvpInfo.inHostileArea = GetTeam() != HORDE && (sWorld.IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL);
break;
case AREATEAM_NONE:
// overwrite for battlegrounds, maybe batter some zone flags but current known not 100% fit to this
pvpInfo.inHostileArea = sWorld.IsPvPRealm() || InBattleGround();
break;
default: // 6 in fact
pvpInfo.inHostileArea = false;
break;
}
if (pvpInfo.inHostileArea) // in hostile area
@ -6990,8 +6997,6 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
UpdateZoneDependentAuras();
UpdateZoneDependentPets();
phaseMgr->RemoveUpdateFlag(PHASE_UPDATE_FLAG_ZONE_UPDATE);
}
// 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)
{
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)
{
if (pQuest->ReqItemId[i])
{
DestroyItemCount(pQuest->ReqItemId[i], pQuest->ReqItemCount[i], true);
}
}
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);
if (BattleGround* bg = GetBattleGround())
if (bg->GetTypeID() == BATTLEGROUND_AV)
if (bg->GetTypeID(true) == BATTLEGROUND_AV)
{
((BattleGroundAV*)bg)->HandleQuestComplete(pQuest->GetQuestId(), this);
}
if (pQuest->GetRewChoiceItemsCount() > 0)
{
@ -14134,7 +14124,9 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
uint16 log_slot = FindQuestSlot(quest_id);
if (log_slot < MAX_QUEST_LOG_SIZE)
{
SetQuestSlot(log_slot, 0);
}
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))
{
GiveXP(xp , NULL);
GiveXP(xp, NULL);
// Give player extra money (for max level already included in pQuest->GetRewMoneyMaxLevel())
if (pQuest->GetRewOrReqMoney() > 0)
@ -14155,10 +14147,10 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
else
{
// 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
if (pQuest->GetRewOrReqMoney() > int64(money))
if (pQuest->GetRewOrReqMoney() > int32(money))
money = pQuest->GetRewOrReqMoney();
ModifyMoney(money);
@ -14169,16 +14161,9 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
if (pQuest->GetRewOrReqMoney() < 0)
ModifyMoney(pQuest->GetRewOrReqMoney());
// reward currency
for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
{
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());
// honor reward
if (uint32 honor = pQuest->CalculateRewardHonor(getLevel()))
RewardHonor(NULL, 0, honor);
// title reward
if (pQuest->GetCharTitleId())
@ -14219,18 +14204,18 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
q_status.uState = QUEST_CHANGED;
if (announce)
SendQuestReward(pQuest, xp, questGiver);
SendQuestReward(pQuest, xp);
bool handled = false;
switch (questGiver->GetTypeId())
{
case TYPEID_UNIT:
handled = sScriptMgr.OnQuestRewarded(this, (Creature*)questGiver, pQuest);
break;
case TYPEID_GAMEOBJECT:
handled = sScriptMgr.OnQuestRewarded(this, (GameObject*)questGiver, pQuest);
break;
case TYPEID_UNIT:
handled = sScriptMgr.OnQuestRewarded(this, reinterpret_cast<Creature*>(questGiver), pQuest, reward);
break;
case TYPEID_GAMEOBJECT:
handled = sScriptMgr.OnQuestRewarded(this, reinterpret_cast<GameObject*>(questGiver), pQuest, reward);
break;
}
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, pQuest->GetQuestId());
UpdateForQuestWorldObjects();
// remove auras from spells with quest reward state limitations
// Some spells applied at quest reward
uint32 zone, area;
@ -14266,11 +14249,18 @@ void Player::RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver,
saBounds = sSpellMgr.GetSpellAreaForAreaMapBounds(0);
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
itr->second->ApplyOrRemoveSpellIfCan(this, zone, area, false);
}
PhaseUpdateData phaseUdateData;
phaseUdateData.AddQuestUpdate(quest_id);
void Player::IncompleteQuest(uint32 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)
@ -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();
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(0);
}
data << uint32(questid);
data << uint32(pQuest->GetRewSkill());
@ -15445,6 +15461,7 @@ void Player::SendQuestReward(Quest const* pQuest, uint32 XP, Object* /*questGive
GetSession()->SendPacket(&data);
}
*/
void Player::SendQuestFailed(uint32 quest_id, InventoryResult reason)
{

View file

@ -1047,6 +1047,8 @@ class Player : public Unit
bool TeleportToBGEntryPoint();
void SetRandomWinner(bool isWinner);
void SetSummonPoint(uint32 mapid, float x, float y, float z)
{
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 CompleteQuest(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);
bool SatisfyQuestSkill(Quest const* qInfo, bool msg) const;
@ -1449,7 +1451,8 @@ class Player : public Unit
bool CanShareQuest(uint32 quest_id) const;
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 SendQuestTimerFailed(uint32 quest_id);
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
bool CanUseCapturePoint();
bool m_IsBGRandomWinner;
/*********************************************************/
/*** REST SYSTEM ***/
/*********************************************************/

View file

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

View file

@ -2095,6 +2095,11 @@ struct SpellEntry
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
{
uint32 ID; // 0 m_ID

View file

@ -42,6 +42,9 @@ const char WorldTemplatesrcfmt[] = "is";
const char WorldTemplatedstfmt[] = "ii";
const char ConditionsSrcFmt[] = "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 VehicleAccessoryDstFmt[] = "iii";
const char CreatureTemplateSpellsFmt[] = "iiiiiiiiiii";
@ -60,6 +63,7 @@ SQLStorage sConditionStorage(ConditionsSrcFmt, ConditionsDstFmt, "condition_entr
SQLHashStorage sGameObjectDataAddonStorage(GameObjectInfoAddonInfofmt, "guid", "gameobject_addon");
SQLHashStorage sGOStorage(GameObjectInfosrcfmt, GameObjectInfodstfmt, "entry", "gameobject_template");
SQLHashStorage sSpellTemplate(SpellTemplatesrcfmt, SpellTemplatedstfmt, "id", "spell_template");
SQLHashStorage sCreatureTemplateSpellsStorage(CreatureTemplateSpellsFmt, "entry", "creature_template_spells");
SQLMultiStorage sVehicleAccessoryStorage(VehicleAccessorySrcFmt, VehicleAccessoryDstFmt, "vehicle_entry", "vehicle_accessory");

View file

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

View file

@ -113,6 +113,11 @@ enum Classes
(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 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)))
@ -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 };
// Max creature level (included some bosses and elite)
#define DEFAULT_MAX_CREATURE_LEVEL 85
// This spell is used for general boarding serverside
#define SPELL_RIDE_VEHICLE_HARDCODED 46598
enum TeleportLocation
{
TELEPORT_LOCATION_HOMEBIND = 0,
TELEPORT_LOCATION_BG_ENTRY_POINT = 1,
};
#endif

View file

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

View file

@ -45,16 +45,27 @@
#include "BattleGround/BattleGroundMgr.h"
#include "Weather.h"
#include "Calendar.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /* ENABLE_ELUNA */
Map::~Map()
{
#ifdef ENABLE_ELUNA
sEluna->OnDestroy(this);
#endif /* ENABLE_ELUNA */
UnloadAll(true);
if (!m_scriptSchedule.empty())
{
sScriptMgr.DecreaseScheduledScriptCount(m_scriptSchedule.size());
}
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;
i_data = NULL;
@ -64,7 +75,12 @@ Map::~Map()
// release reference count
if (m_TerrainData->Release())
{
sTerrainMgr.UnloadTerrain(m_TerrainData->GetMapId());
}
delete m_weatherSystem;
m_weatherSystem = NULL;
}
void Map::LoadMapAndVMap(int gx, int gy)
@ -667,8 +683,7 @@ Map::Remove(T* obj, bool remove)
}
}
void
Map::PlayerRelocation(Player* player, float x, float y, float z, float orientation)
void Map::PlayerRelocation(Player* player, float x, float y, float z, float orientation)
{
MANGOS_ASSERT(player);
@ -788,7 +803,9 @@ bool Map::UnloadGrid(const uint32& x, const uint32& y, bool pForce)
{
if (!pForce && ActiveObjectsNearGrid(x, y))
{
return false;
}
DEBUG_FILTER_LOG(LOG_FILTER_MAP_LOADING, "Unloading grid[%u,%u] for map %u", x, y, i_id);
ObjectGridUnloader unloader(*grid);
@ -1927,7 +1944,7 @@ class StaticMonsterChatBuilder
* @param language language of the text
* @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())
{
@ -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,
* 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);
MaNGOS::LocalizedPacketDo<StaticMonsterChatBuilder> say_do(say_build);
Map::PlayerList const& pList = GetPlayers();
for (PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
{
say_do(itr->getSource());
}
}
/**

View file

@ -102,197 +102,217 @@ enum LevelRequirementVsMode
class Map : public GridRefManager<NGridType>
{
friend class MapReference;
friend class ObjectGridLoader;
friend class ObjectWorldLoader;
friend class MapReference;
friend class ObjectGridLoader;
friend class ObjectWorldLoader;
protected:
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode);
protected:
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode);
public:
virtual ~Map();
public:
virtual ~Map();
// currently unused for normal maps
bool CanUnload(uint32 diff)
{
if (!m_unloadTimer) return false;
if (m_unloadTimer <= diff) return true;
m_unloadTimer -= diff;
return false;
}
// currently unused for normal maps
bool CanUnload(uint32 diff)
{
if (!m_unloadTimer) { return false; }
if (m_unloadTimer <= diff) { return true; }
m_unloadTimer -= diff;
return false;
}
virtual bool Add(Player*);
virtual void Remove(Player*, bool);
template<class T> void Add(T*);
template<class T> void Remove(T*, bool);
virtual bool Add(Player*);
virtual void Remove(Player*, bool);
template<class T> void Add(T*);
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(WorldObject const*, WorldPacket*);
void MessageDistBroadcast(Player const*, WorldPacket*, float dist, bool to_self, bool own_team_only = false);
void MessageDistBroadcast(WorldObject const*, WorldPacket*, float dist);
void MessageBroadcast(Player const*, WorldPacket*, bool to_self);
void MessageBroadcast(WorldObject const*, WorldPacket*);
void MessageDistBroadcast(Player const*, WorldPacket*, float dist, bool to_self, bool own_team_only = false);
void MessageDistBroadcast(WorldObject const*, WorldPacket*, float dist);
float GetVisibilityDistance() const { return m_VisibleDistance; }
// function for setting up visibility distance for maps on per-type/per-Id basis
virtual void InitVisibilityDistance();
float GetVisibilityDistance() const { return m_VisibleDistance; }
// function for setting up visibility distance for maps on per-type/per-Id basis
virtual void InitVisibilityDistance();
void PlayerRelocation(Player*, float x, float y, float z, float angl);
void CreatureRelocation(Creature* creature, float x, float y, float z, float orientation);
void PlayerRelocation(Player*, float x, float y, float z, float angl);
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
{
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);
}
bool IsRemovalGrid(float x, float y) const
{
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);
}
bool IsLoaded(float x, float y) const
{
GridPair p = MaNGOS::ComputeGridPair(x, y);
return loaded(p);
}
bool IsLoaded(float x, float y) const
{
GridPair p = MaNGOS::ComputeGridPair(x, y);
return loaded(p);
}
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 LoadGrid(const Cell& cell, bool no_unload = false);
bool UnloadGrid(const uint32& x, const uint32& y, bool pForce);
virtual void UnloadAll(bool pForce);
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 LoadGrid(const Cell& cell, bool no_unload = false);
bool UnloadGrid(const uint32& x, const uint32& y, bool pForce);
virtual void UnloadAll(bool pForce);
void ResetGridExpiry(NGridType& grid, float factor = 1) const
{
grid.ResetTimeTracker((time_t)((float)i_gridExpiry * factor));
}
void ResetGridExpiry(NGridType& grid, float factor = 1) const
{
grid.ResetTimeTracker((time_t)((float)i_gridExpiry * factor));
}
time_t GetGridExpiry(void) const { return i_gridExpiry; }
uint32 GetId(void) const { return i_id; }
time_t GetGridExpiry(void) const { return i_gridExpiry; }
uint32 GetId(void) const { return i_id; }
// 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
// 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
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; }
virtual bool CanEnter(Player* player);
const char* GetMapName() const;
uint32 GetInstanceId() const { return i_InstanceId; }
virtual bool CanEnter(Player* player);
const char* GetMapName() const;
// 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
// for simplify later code support
// regular difficulty = continent/dungeon normal/first raid normal difficulty
uint8 GetSpawnMode() const { return (i_spawnMode); }
Difficulty GetDifficulty() const { return Difficulty(GetSpawnMode()); }
bool IsRegularDifficulty() const { return GetDifficulty() == REGULAR_DIFFICULTY; }
uint32 GetMaxPlayers() const; // dependent from map difficulty
uint32 GetMaxResetDelay() const; // dependent from map difficulty
MapDifficultyEntry const* GetMapDifficulty() const; // dependent from map difficulty
// 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
// for simplify later code support
// regular difficulty = continent/dungeon normal/first raid normal difficulty
uint8 GetSpawnMode() const { return (i_spawnMode); }
Difficulty GetDifficulty() const { return Difficulty(GetSpawnMode()); }
bool IsRegularDifficulty() const { return GetDifficulty() == REGULAR_DIFFICULTY; }
uint32 GetMaxPlayers() const; // dependent from map difficulty
uint32 GetMaxResetDelay() const; // dependent from map difficulty
MapDifficultyEntry const* GetMapDifficulty() const; // dependent from map difficulty
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
bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); }
bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); }
bool IsNonRaidDungeon() const { return i_mapEntry && i_mapEntry->IsNonRaidDungeon(); }
bool IsRaidOrHeroicDungeon() const { return IsRaid() || GetDifficulty() > DUNGEON_DIFFICULTY_NORMAL; }
bool IsHeroic() const { return IsRaid() || i_spawnMode >= DUNGEON_DIFFICULTY_HEROIC; }
bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); }
bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); }
bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); }
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
bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); }
bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); }
bool IsHeroic() const { return IsRaid() ? i_spawnMode >= RAID_DIFFICULTY_10MAN_HEROIC : i_spawnMode >= DUNGEON_DIFFICULTY_HEROIC; }
bool IsNonRaidDungeon() const { return i_mapEntry && i_mapEntry->IsNonRaidDungeon(); }
bool IsRaidOrHeroicDungeon() const { return IsRaid() || GetDifficulty() > DUNGEON_DIFFICULTY_NORMAL; }
bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); }
bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); }
bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); }
// can't be NULL for loaded map
MapPersistentState* GetPersistentState() const { return m_persistentState; }
// can't be NULL for loaded map
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(); }
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); }
void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
void resetMarkedCells() { marked_cells.reset(); }
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); }
void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
bool HavePlayers() const { return !m_mapRefManager.isEmpty(); }
uint32 GetPlayersCountExceptGMs() const;
bool ActiveObjectsNearGrid(uint32 x, uint32 y) const;
bool HavePlayers() const { return !m_mapRefManager.isEmpty(); }
uint32 GetPlayersCountExceptGMs() const;
bool ActiveObjectsNearGrid(uint32 x, uint32 y) const;
void SendToPlayers(WorldPacket const* data) const;
bool SendToPlayersInZone(WorldPacket const* data, uint32 zoneId) const;
/// Send a Packet to all players on a map
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;
PlayerList const& GetPlayers() const { return m_mapRefManager; }
typedef MapRefManager PlayerList;
PlayerList const& GetPlayers() const { return m_mapRefManager; }
// per-map script storage
enum ScriptExecutionParam
{
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_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)
};
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);
// per-map script storage
enum ScriptExecutionParam
{
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_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)
};
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);
// must called with AddToWorld
void AddToActive(WorldObject* obj);
// must called with RemoveFromWorld
void RemoveFromActive(WorldObject* obj);
// must called with AddToWorld
void AddToActive(WorldObject* obj);
// must called with RemoveFromWorld
void RemoveFromActive(WorldObject* obj);
Player* GetPlayer(ObjectGuid guid);
Creature* GetCreature(ObjectGuid guid);
Pet* GetPet(ObjectGuid guid);
Creature* GetAnyTypeCreature(ObjectGuid guid); // normal creature or pet or vehicle
GameObject* GetGameObject(ObjectGuid guid);
DynamicObject* GetDynamicObject(ObjectGuid guid);
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
WorldObject* GetWorldObject(ObjectGuid guid); // only use if sure that need objects at current map, specially for player case
Player* GetPlayer(ObjectGuid guid);
Creature* GetCreature(ObjectGuid guid);
Pet* GetPet(ObjectGuid guid);
Creature* GetAnyTypeCreature(ObjectGuid guid); // normal creature or pet or vehicle
GameObject* GetGameObject(ObjectGuid guid);
DynamicObject* GetDynamicObject(ObjectGuid guid);
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
WorldObject* GetWorldObject(ObjectGuid guid); // only use if sure that need objects at current map, specially for player case
typedef TypeUnorderedMapContainer<AllMapStoredObjectTypes, ObjectGuid> MapStoredObjectTypesContainer;
MapStoredObjectTypesContainer& GetObjectsStore() { return m_objectsStore; }
typedef TypeUnorderedMapContainer<AllMapStoredObjectTypes, ObjectGuid> MapStoredObjectTypesContainer;
MapStoredObjectTypesContainer& GetObjectsStore() { return m_objectsStore; }
void AddUpdateObject(Object* obj)
{
i_objectsToClientUpdate.insert(obj);
}
void AddUpdateObject(Object* obj)
{
i_objectsToClientUpdate.insert(obj);
}
void RemoveUpdateObject(Object* obj)
{
i_objectsToClientUpdate.erase(obj);
}
void RemoveUpdateObject(Object* obj)
{
i_objectsToClientUpdate.erase(obj);
}
// DynObjects currently
uint32 GenerateLocalLowGuid(HighGuid guidhigh);
// DynObjects currently
uint32 GenerateLocalLowGuid(HighGuid guidhigh);
// get corresponding TerrainData object for this particular map
const TerrainInfo* GetTerrain() const { return m_TerrainData; }
// get corresponding TerrainData object for this particular map
const TerrainInfo* GetTerrain() const { return m_TerrainData; }
void CreateInstanceData(bool load);
InstanceData* GetInstanceData() const { return i_data; }
uint32 GetScriptId() const { return i_script_id; }
void CreateInstanceData(bool load);
InstanceData* GetInstanceData() const { return i_data; }
virtual uint32 GetScriptId() const { return sScriptMgr.GetBoundScriptId(SCRIPTED_MAP, GetId()); }
void MonsterYellToMap(ObjectGuid guid, int32 textId, uint32 language, Unit const* target) const;
void MonsterYellToMap(CreatureInfo const* cinfo, int32 textId, uint32 language, Unit const* target, uint32 senderLowGuid = 0) const;
void PlayDirectSoundToMap(uint32 soundId, uint32 zoneId = 0) const;
void MonsterYellToMap(ObjectGuid guid, int32 textId, Language language, Unit const* target) 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;
// Dynamic VMaps
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 GetHitPosition(float srcX, float srcY, float srcZ, float& destX, float& destY, float& destZ, uint32 phasemask, float modifyDist) const;
// Dynamic VMaps
float GetHeight(uint32 phasemask, float x, float y, float z) const;
bool GetHeightInRange(uint32 phasemask, float x, float y, float& z, float maxSearchDist = 4.0f) 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
void InsertGameObjectModel(const GameObjectModel& mdl);
void RemoveGameObjectModel(const GameObjectModel& mdl);
bool ContainsGameObjectModel(const GameObjectModel& mdl) const;
// Object Model insertion/remove/test for dynamic vmaps use
void InsertGameObjectModel(const GameObjectModel& mdl);
void RemoveGameObjectModel(const GameObjectModel& mdl);
bool ContainsGameObjectModel(const GameObjectModel& mdl) const;
// Get Holder for Creature Linking
CreatureLinkingHolder* GetCreatureLinkingHolder() { return &m_creatureLinkingHolder; }
// Get Holder for Creature Linking
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:
void LoadMapAndVMap(int gx, int gy);
@ -392,72 +412,76 @@ class Map : public GridRefManager<NGridType>
WeatherSystem* m_weatherSystem;
};
class WorldMap : public Map
class WorldMap : public Map
{
private:
using Map::GetPersistentState; // hide in subclass for overwrite
public:
WorldMap(uint32 id, time_t expiry) : Map(id, expiry, 0, REGULAR_DIFFICULTY) {}
~WorldMap() {}
private:
using Map::GetPersistentState; // hide in subclass for overwrite
public:
WorldMap(uint32 id, time_t expiry) : Map(id, expiry, 0, REGULAR_DIFFICULTY) {}
~WorldMap() {}
// can't be NULL for loaded map
WorldPersistentState* GetPersistanceState() const;
// can't be NULL for loaded map
WorldPersistentState* GetPersistanceState() const;
};
class DungeonMap : public Map
class DungeonMap : public Map
{
private:
using Map::GetPersistentState; // hide in subclass for overwrite
public:
DungeonMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode);
~DungeonMap();
bool Add(Player*) override;
void Remove(Player*, bool) override;
void Update(const uint32&) override;
bool Reset(InstanceResetMethod method);
void PermBindAllPlayers(Player* player);
void UnloadAll(bool pForce) override;
void SendResetWarnings(uint32 timeLeft) const;
void SetResetSchedule(bool on);
private:
using Map::GetPersistentState; // hide in subclass for overwrite
public:
DungeonMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode);
~DungeonMap();
bool Add(Player*) override;
void Remove(Player*, bool) override;
void Update(const uint32&) override;
bool Reset(InstanceResetMethod method);
void PermBindAllPlayers(Player* player);
void UnloadAll(bool pForce) override;
void SendResetWarnings(uint32 timeLeft) const;
void SetResetSchedule(bool on);
// can't be NULL for loaded map
DungeonPersistentState* GetPersistanceState() const;
uint32 GetScriptId() const override { return sScriptMgr.GetBoundScriptId(SCRIPTED_INSTANCE, GetId()); }
virtual void InitVisibilityDistance() override;
private:
bool m_resetAfterUnload;
bool m_unloadWhenEmpty;
// can't be NULL for loaded map
DungeonPersistentState* GetPersistanceState() const;
virtual void InitVisibilityDistance() override;
private:
bool m_resetAfterUnload;
bool m_unloadWhenEmpty;
};
class BattleGroundMap : public Map
class BattleGroundMap : public Map
{
private:
using Map::GetPersistentState; // hide in subclass for overwrite
public:
BattleGroundMap(uint32 id, time_t, uint32 InstanceId, uint8 spawnMode);
~BattleGroundMap();
private:
using Map::GetPersistentState; // hide in subclass for overwrite
public:
BattleGroundMap(uint32 id, time_t, uint32 InstanceId, uint8 spawnMode);
~BattleGroundMap();
void Update(const uint32&) override;
bool Add(Player*) override;
void Remove(Player*, bool) override;
bool CanEnter(Player* player) override;
void SetUnload();
void UnloadAll(bool pForce) override;
void Update(const uint32&) override;
bool Add(Player*) override;
void Remove(Player*, bool) override;
bool CanEnter(Player* player) override;
void SetUnload();
void UnloadAll(bool pForce) override;
virtual void InitVisibilityDistance() override;
BattleGround* GetBG() { return m_bg; }
void SetBG(BattleGround* bg) { m_bg = bg; }
virtual void InitVisibilityDistance() override;
BattleGround* GetBG() { return m_bg; }
void SetBG(BattleGround* bg) { m_bg = bg; }
// can't be NULL for loaded map
BattleGroundPersistentState* GetPersistanceState() const;
uint32 GetScriptId() const override { return sScriptMgr.GetBoundScriptId(SCRIPTED_BATTLEGROUND, GetId()); } //TODO bind BG scripts through script_binding, now these are broken!
private:
BattleGround* m_bg;
// can't be NULL for loaded map
BattleGroundPersistentState* GetPersistanceState() const;
private:
BattleGround* m_bg;
};
template<class T, class CONTAINER>
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 y = cell.GridY();

View file

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

View file

@ -38,6 +38,15 @@
#include "OutdoorPvP/OutdoorPvP.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"
ScriptMapMapName sQuestEndScripts;
@ -53,44 +62,12 @@ ScriptMapMapName sCreatureMovementScripts;
INSTANTIATE_SINGLETON_1(ScriptMgr);
ScriptMgr::ScriptMgr() :
m_hScriptLib(NULL),
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)
m_scheduledScripts(0)
{
}
ScriptMgr::~ScriptMgr()
{
UnloadScriptLibrary();
}
// /////////////////////////////////////////////////////////
@ -1807,25 +1784,28 @@ bool ScriptAction::HandleScriptStep()
// Scripting Library Hooks
// /////////////////////////////////////////////////////////
void ScriptMgr::LoadAreaTriggerScripts()
void ScriptMgr::LoadScriptBinding()
{
m_AreaTriggerScripts.clear(); // need for reload case
QueryResult* result = WorldDatabase.Query("SELECT entry, ScriptName FROM scripted_areatrigger");
#ifdef ENABLE_SD3
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;
if (!result)
{
BarGoLink bar(1);
bar.step();
sLog.outString(">> Loaded no script binding.");
sLog.outString();
sLog.outString(">> Loaded %u scripted areatrigger", count);
return;
}
BarGoLink bar(result->GetRowCount());
std::set<uint32> eventIds; // Store possible event ids, for checking
CollectPossibleEventIds(eventIds);
BarGoLink bar(result->GetRowCount());
do
{
++count;
@ -1833,96 +1813,107 @@ void ScriptMgr::LoadAreaTriggerScripts()
Field* fields = result->Fetch();
uint32 triggerId = fields[0].GetUInt32();
const char* scriptName = fields[1].GetString();
uint8 type = fields[0].GetUInt8();
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;
}
m_AreaTriggerScripts[triggerId] = GetScriptId(scriptName);
}
while (result->NextRow());
// checking if the scripted object actually exists
bool exists = false;
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;
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(">> Loaded %u areatrigger scripts", count);
}
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);
#endif /* ENABLE_SD3 */
return;
}
void ScriptMgr::LoadScriptNames()
{
m_scriptNames.push_back("");
QueryResult* result = WorldDatabase.Query(
"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 <> ''");
QueryResult* result = WorldDatabase.Query("SELECT DISTINCT(ScriptName) FROM script_binding");
if (!result)
{
BarGoLink bar(1);
bar.step();
sLog.outString();
sLog.outErrorDb(">> Loaded empty set of Script Names!");
sLog.outString();
return;
}
@ -1934,13 +1925,13 @@ void ScriptMgr::LoadScriptNames()
bar.step();
m_scriptNames.push_back((*result)[0].GetString());
++count;
}
while (result->NextRow());
} while (result->NextRow());
delete result;
std::sort(m_scriptNames.begin(), m_scriptNames.end());
sLog.outString(">> Loaded %d unique Script Names", count);
sLog.outString();
sLog.outString(">> Loaded %d Script Names", count);
}
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
// assume "" is the first element
if (!name)
{
return 0;
}
ScriptNameMap::const_iterator itr =
std::lower_bound(m_scriptNames.begin(), m_scriptNames.end(), name);
if (itr == m_scriptNames.end() || *itr != name)
{
return 0;
}
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
{
if (!m_pGetScriptLibraryVersion)
return "";
#ifdef ENABLE_SD3
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)
{
if (!m_pGetCreatureAI)
return NULL;
// Used by Eluna
#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)
{
if (!m_pCreateInstanceData)
return NULL;
return m_pCreateInstanceData(pMap);
#ifdef ENABLE_SD3
return SD3::CreateInstanceData(pMap);
#else
return NULL;
#endif
}
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)
{
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)
{
#ifdef ENABLE_ELUNA
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
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)
{
// Used by Eluna
#ifdef ENABLE_ELUNA
if (code)
return m_pOnGOGossipSelectWithCode != NULL && m_pOnGOGossipSelectWithCode(pPlayer, pGameObject, sender, action, code);
{
if (sEluna->OnGossipSelectCode(pPlayer, pGameObject, sender, action, code))
return true;
}
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)
{
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)
{
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)
{
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)
{
if (!m_pGetNPCDialogStatus)
return DIALOG_STATUS_UNDEFINED;
// Used by Eluna
#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)
{
if (!m_pGetGODialogStatus)
return DIALOG_STATUS_UNDEFINED;
// Used by Eluna
#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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
UnloadScriptLibrary();
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)
#ifdef ENABLE_SD3
if (std::strcmp(libName, MANGOS_SCRIPT_NAME) == 0)
{
m_pOnFreeScriptLibrary = NULL; // prevent call before init
UnloadScriptLibrary();
return SCRIPT_LOAD_ERR_OUTDATED;
SD3::FreeScriptLibrary();
SD3::InitScriptLibrary();
return SCRIPT_LOAD_OK;
}
m_pOnInitScriptLibrary();
return SCRIPT_LOAD_OK;
#endif
return SCRIPT_LOAD_ERR_NOT_FOUND;
}
void ScriptMgr::UnloadScriptLibrary()
{
if (!m_hScriptLib)
return;
if (m_pOnFreeScriptLibrary)
m_pOnFreeScriptLibrary();
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;
#ifdef ENABLE_SD3
SD3::FreeScriptLibrary();
#else
return;
#endif
}
void ScriptMgr::CollectPossibleEventIds(std::set<uint32>& eventIds)

View file

@ -47,6 +47,24 @@ class SpellCastTargets;
class Unit;
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
{
SCRIPT_COMMAND_TALK = 0, // resSource = WorldObject, resTarget = Unit/none
@ -477,24 +495,50 @@ class ScriptMgr
void LoadDbScriptStrings();
void LoadScriptNames();
void LoadAreaTriggerScripts();
void LoadEventIdScripts();
void LoadScriptBinding();
uint32 GetAreaTriggerScriptId(uint32 triggerId) 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 GetScriptIdsCount() const { return m_scriptNames.size(); }
uint32 GetScriptIdsCount() const
{
return m_scriptNames.size();
}
ScriptLoadResult LoadScriptLibrary(const char* libName);
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 DecreaseScheduledScriptCount() { return (uint32)--m_scheduledScripts; }
uint32 DecreaseScheduledScriptCount(size_t count) { return (uint32)(m_scheduledScripts -= count); }
bool IsScriptScheduled() const { return m_scheduledScripts > 0; }
uint32 IncreaseScheduledScriptsCount()
{
return (uint32)++m_scheduledScripts;
}
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);
CreatureAI* GetCreatureAI(Creature* pCreature);
@ -508,13 +552,14 @@ class ScriptMgr
bool OnQuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest);
bool OnQuestAccept(Player* pPlayer, GameObject* pGameObject, 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, GameObject* pGameObject, Quest const* pQuest);
bool OnQuestRewarded(Player* pPlayer, Creature* pCreature, Quest const* pQuest, uint32 reward);
bool OnQuestRewarded(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest, uint32 reward);
uint32 GetDialogStatus(Player* pPlayer, Creature* pCreature);
uint32 GetDialogStatus(Player* pPlayer, GameObject* pGameObject);
bool OnGameObjectUse(Player* pPlayer, GameObject* pGameObject);
bool OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets);
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 OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Creature* 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 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 UNORDERED_MAP<uint32, uint32> AreaTriggerScriptMap;
typedef UNORDERED_MAP<uint32, uint32> EventIdScriptMap;
typedef UNORDERED_MAP<int32, uint32> EntryToScriptIdMap;
AreaTriggerScriptMap m_AreaTriggerScripts;
EventIdScriptMap m_EventIdScripts;
EntryToScriptIdMap m_scriptBind[SCRIPTED_MAX_TYPE];
ScriptNameMap m_scriptNames;
MANGOS_LIBRARY_HANDLE m_hScriptLib;
// atomic op counter for active scripts amount
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

View file

@ -29,52 +29,56 @@
#include "Weather.h"
#include "WorldPacket.h"
#include "Player.h"
#include "Map.h"
#include "World.h"
#include "Log.h"
#include "ObjectMgr.h"
// #include "ObjectMgr.h" // chucky delete ?
#include "Util.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /* ENABLE_ELUNA */
/// 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_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)));
}
/// Launch a weather update
bool Weather::Update(time_t diff)
bool Weather::Update(uint32 diff, Map const* _map)
{
m_timer.Update(diff);
///- If the timer has passed, ReGenerate the weather
if (m_timer.Passed())
if (ReGenerate())
{
m_timer.Reset();
// update only if Regenerate has changed the weather
if (ReGenerate())
{
///- Weather will be removed if not updated (no players in zone anymore)
if (!UpdateWeather())
return false;
}
///- Weather will be removed if not updated (no players in zone anymore)
if (!SendWeatherForPlayersInZone(_map))
return false;
}
return true;
}
/// Calculate the new weather
/// Calculate the new weather, returns true if and only if the weather changed
bool Weather::ReGenerate()
{
if (m_isPermanentWeather)
return false;
// remember old values
WeatherType old_type = m_type;
float old_grade = m_grade;
if (!m_weatherChances)
{
m_type = WEATHER_TYPE_FINE;
m_grade = 0.0f;
return false;
// No chanced calculation for this zone
return old_type != m_type || old_grade != m_grade;
}
/// Weather statistics:
@ -85,11 +89,9 @@ bool Weather::ReGenerate()
uint32 u = urand(0, 99);
if (u < 30)
{
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
// 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
uint32 chance1 = m_weatherChances->data[season].rainChance;
uint32 chance1 = m_weatherChances->data[season].rainChance;
uint32 chance2 = chance1 + m_weatherChances->data[season].snowChance;
uint32 chance3 = chance2 + m_weatherChances->data[season].stormChance;
uint32 rnd = urand(0, 99);
if (rnd <= chance1)
{
m_type = WEATHER_TYPE_RAIN;
}
else if (rnd <= chance2)
{
m_type = WEATHER_TYPE_SNOW;
}
else if (rnd <= chance3)
{
m_type = WEATHER_TYPE_STORM;
}
else
{
m_type = WEATHER_TYPE_FINE;
}
/// New weather statistics (if not fine):
///- 85% light
@ -182,20 +192,28 @@ bool Weather::ReGenerate()
// Severe change, but how severe?
rnd = urand(0, 99);
if (rnd < 50)
{
m_grade = rand_norm_f() * 0.3333f + 0.3334f;
}
else
{
m_grade = rand_norm_f() * 0.3333f + 0.6667f;
}
}
NormalizeGrade();
// return true only in case weather changes
return m_type != old_type || m_grade != old_grade;
}
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);
player->GetSession()->SendPacket(&data);
}
@ -206,10 +224,9 @@ bool Weather::SendWeatherForPlayersInZone(Map const* _map)
WeatherState state = GetWeatherState();
// To be sent packet
WorldPacket data(SMSG_WEATHER, 4 + 4 + 1);
data << uint32(state);
data << float(m_grade);
data << uint8(0); // 1 = instant change, 0 = smooth change
data << uint32(state) << (float)m_grade << uint8(0);
///- Send the weather packet to all players in this zone
if (!_map->SendToPlayersInZone(&data, m_zone))
@ -224,15 +241,7 @@ bool Weather::SendWeatherForPlayersInZone(Map const* _map)
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()
{
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);
return true;
}
} */
// Set the weather
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);
}
/// 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
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);
}
// ---------------------------------------------------------
// 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:
Weather(uint32 zone, WeatherZoneChances const* weatherChances);
~Weather() { };
~Weather() {};
bool ReGenerate();
bool UpdateWeather();
/// Send Weather to one player
void SendWeatherUpdateToPlayer(Player* player);
bool SendWeatherForPlayersInZone(Map const* _map);
static void SendFineWeatherUpdateToPlayer(Player* player);
/// Set the weather
void SetWeather(WeatherType type, float grade, Map const* _map, bool isPermanent);
void SetWeather(WeatherType type, float grade);
/// For which zone is this weather?
uint32 GetZone() { return m_zone; };
bool Update(time_t diff);
/// Update the weather in this zone, when the timer is expired the weather will be rolled again
bool Update(uint32 diff, Map const* _map);
/// Check if a type is valid
static bool IsValidWeatherType(uint32 type)
{
switch (type)
@ -85,14 +82,17 @@ class Weather
return false;
}
}
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
void NormalizeGrade();
// Helper to log recent state
void LogWeatherState(WeatherState state) const;
WeatherState GetWeatherState() const;
uint32 m_zone;
WeatherType m_type;
float m_grade;
@ -108,17 +108,59 @@ class Weather
/// Weathers for one map
class WeatherSystem
{
public:
WeatherSystem(Map const* _map);
~WeatherSystem();
public:
WeatherSystem(Map const* _map);
~WeatherSystem();
Weather* FindOrCreateWeather(uint32 zoneId);
void UpdateWeathers(uint32 diff);
Weather* FindOrCreateWeather(uint32 zoneId);
void UpdateWeathers(uint32 diff);
private:
Map const* const m_map;
private:
Map const* const m_map;
typedef UNORDERED_MAP<uint32 /*zoneId*/, Weather*> WeatherMap;
WeatherMap m_weathers;
typedef UNORDERED_MAP<uint32 /*zoneId*/, Weather*> WeatherMap;
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

View file

@ -76,6 +76,9 @@
#include "CreatureLinkingMgr.h"
#include "Calendar.h"
#include "PhaseMgr.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /*ENABLE_ELUNA*/
INSTANTIATE_SINGLETON_1(World);
@ -428,6 +431,9 @@ void World::RemoveWeather(uint32 id)
}
/// Add a Weather object to the list
/*
* chucky - delete this?
* this is not in Two
Weather* World::AddWeather(uint32 zone_id)
{
WeatherZoneChances const* weatherChances = sObjectMgr.GetWeatherChances(zone_id);
@ -442,6 +448,7 @@ Weather* World::AddWeather(uint32 zone_id)
w->UpdateWeather();
return w;
}
*/
/// Initialize config values
void World::LoadConfigSettings(bool reload)
@ -958,16 +965,16 @@ void World::SetInitialWorldSettings()
///- Check the existence of the map files for all races start areas.
if (!MapManager::ExistMapAndVMap(0, -6240.32f, 331.033f) || // Dwarf/ Gnome
!MapManager::ExistMapAndVMap(0, -8949.95f, -132.493f) || // Human
!MapManager::ExistMapAndVMap(1, -618.518f, -4251.67f) || // Orc
!MapManager::ExistMapAndVMap(0, 1676.35f, 1677.45f) || // Scourge
!MapManager::ExistMapAndVMap(1, 10311.3f, 832.463f) || // NightElf
!MapManager::ExistMapAndVMap(1, -2917.58f, -257.98f) || // Tauren
(m_configUint32Values[CONFIG_UINT32_EXPANSION] >= EXPANSION_TBC &&
(!MapManager::ExistMapAndVMap(530, 10349.6f, -6357.29f) || // BloodElf
!MapManager::ExistMapAndVMap(530, -3961.64f, -13931.2f))) || // Draenei
(m_configUint32Values[CONFIG_UINT32_EXPANSION] >= EXPANSION_WOTLK &&
!MapManager::ExistMapAndVMap(609, 2355.84f, -5664.77f))) // Death Knight
!MapManager::ExistMapAndVMap(0, -8949.95f, -132.493f) || // Human
!MapManager::ExistMapAndVMap(1, -618.518f, -4251.67f) || // Orc
!MapManager::ExistMapAndVMap(0, 1676.35f, 1677.45f) || // Scourge
!MapManager::ExistMapAndVMap(1, 10311.3f, 832.463f) || // NightElf
!MapManager::ExistMapAndVMap(1, -2917.58f, -257.98f) || // Tauren
(m_configUint32Values[CONFIG_UINT32_EXPANSION] >= EXPANSION_TBC &&
(!MapManager::ExistMapAndVMap(530, 10349.6f, -6357.29f) || // BloodElf
!MapManager::ExistMapAndVMap(530, -3961.64f, -13931.2f))) || // Draenei
(m_configUint32Values[CONFIG_UINT32_EXPANSION] >= EXPANSION_WOTLK &&
!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());
Log::WaitBeforeContinueIfNeed();
@ -997,16 +1004,15 @@ void World::SetInitialWorldSettings()
///- Load the DBC files
sLog.outString("Initialize data stores...");
LoadDBCStores(m_dataPath);
LoadDB2Stores(m_dataPath);
DetectDBCLang();
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...");
sScriptMgr.LoadScriptNames();
sLog.outString("Loading WorldTemplate...");
sObjectMgr.LoadWorldTemplate();
sLog.outString("Loading InstanceTemplate...");
sObjectMgr.LoadInstanceTemplate();
@ -1030,6 +1036,12 @@ void World::SetInitialWorldSettings()
sObjectMgr.SetHighestGuids(); // must be after PackInstances() and PackGroupIds()
sLog.outString();
#ifdef ENABLE_ELUNA
///- Initialize Lua Engine
sLog.outString("Initialize Eluna Lua Engine...");
Eluna::Initialize();
#endif /* ENABLE_ELUNA */
sLog.outString("Loading Page Texts...");
sObjectMgr.LoadPageTexts();
@ -1084,6 +1096,9 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading Equipment templates...");
sObjectMgr.LoadEquipmentTemplates();
sLog.outString("Loading Creature Stats...");
sObjectMgr.LoadCreatureClassLvlStats();
sLog.outString("Loading Creature templates...");
sObjectMgr.LoadCreatureTemplates();
@ -1142,7 +1157,7 @@ void World::SetInitialWorldSettings()
sPoolMgr.LoadFromDB();
sLog.outString("Loading Weather Data...");
sObjectMgr.LoadWeatherZoneChances();
sWeatherMgr.LoadWeatherZoneChances();
sLog.outString("Loading Quests...");
sObjectMgr.LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables
@ -1166,12 +1181,6 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading Conditions...");
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();
sMapPersistentStateMgr.InitWorldMaps();
@ -1196,11 +1205,10 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading Tavern Area Triggers...");
sObjectMgr.LoadTavernAreaTriggers();
sLog.outString("Loading AreaTrigger script names...");
sScriptMgr.LoadAreaTriggerScripts();
sLog.outString("Loading event id script names...");
sScriptMgr.LoadEventIdScripts();
#ifdef ENABLE_SD3
sLog.outString("Loading all script bindings...");
sScriptMgr.LoadScriptBinding();
#endif /* ENABLE_SD3 */
sLog.outString("Loading Graveyard-zone links...");
sObjectMgr.LoadGraveyardZones();
@ -1339,8 +1347,14 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading GM tickets...");
sTicketMgr.LoadGMTickets();
sLog.outString("Loading hotfix data...");
sObjectMgr.LoadHotfixData();
sLog.outString("Loading Dungeon Finder Requirements...");
sObjectMgr.LoadDungeonFinderRequirements();
sLog.outString("Loading Dungeon Finder Rewards...");
sObjectMgr.LoadDungeonFinderRewards();
sLog.outString("Loading Dungeon Finder Items...");
sObjectMgr.LoadDungeonFinderItems();
///- Handle outdated emails (delete/return)
sLog.outString("Returning old mails...");
@ -1372,21 +1386,25 @@ void World::SetInitialWorldSettings()
sEventAIMgr.LoadCreatureEventAI_Scripts();
sLog.outString("Initializing Scripts...");
#ifdef ENABLE_SD3
switch (sScriptMgr.LoadScriptLibrary(MANGOS_SCRIPT_NAME))
{
case SCRIPT_LOAD_OK:
sLog.outString("Scripting library loaded.");
break;
case SCRIPT_LOAD_ERR_NOT_FOUND:
sLog.outError("Scripting library not found or not accessible.");
break;
case SCRIPT_LOAD_ERR_WRONG_API:
sLog.outError("Scripting library has wrong list functions (outdated?).");
break;
case SCRIPT_LOAD_ERR_OUTDATED:
sLog.outError("Scripting library build for old mangosd revision. You need rebuild it.");
break;
case SCRIPT_LOAD_OK:
sLog.outString("Scripting library loaded.");
break;
case SCRIPT_LOAD_ERR_NOT_FOUND:
sLog.outError("Scripting library not found or not accessible.");
break;
case SCRIPT_LOAD_ERR_WRONG_API:
sLog.outError("Scripting library has wrong list functions (outdated?).");
break;
case SCRIPT_LOAD_ERR_OUTDATED:
sLog.outError("Scripting library build for old mangosd revision. You need rebuild it.");
break;
}
#else /* ENABLE_SD3 */
sLog.outError("SD3 was not included in compilation, not using it.");
#endif /* ENABLE_SD3 */
///- 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
char isoDate[128];
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)",
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_UPTIME].SetInterval(getConfig(CONFIG_UINT32_UPTIME_UPDATE)*MINUTE * IN_MILLISECONDS);
// Update "uptime" table based on configuration entry in minutes.
@ -1414,6 +1431,9 @@ void World::SetInitialWorldSettings()
// for AhBot
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
// mailtimer is increased when updating auctions
// one second is 1000 -(tested on win system)
@ -1433,6 +1453,7 @@ void World::SetInitialWorldSettings()
///- Initialize Battlegrounds
sLog.outString("Starting BattleGround System");
sBattleGroundMgr.CreateInitialBattleGrounds();
sBattleGroundMgr.InitAutomaticArenaPointDistribution();
///- Initialize Outdoor PvP
sLog.outString("Starting Outdoor PvP System");
@ -1442,13 +1463,19 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading Transports...");
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...");
LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
sLog.outString("Calculate next currency reset time...");
InitCurrencyResetTime();
sLog.outString("Calculate next daily quest reset time...");
sLog.outString("Calculate next daily quest and dungeon reset time...");
InitDailyQuestResetTime();
sLog.outString("Calculate next weekly quest reset time...");
@ -1457,6 +1484,9 @@ void World::SetInitialWorldSettings()
sLog.outString("Calculate next monthly quest reset time...");
SetMonthlyQuestResetTime();
sLog.outString("Calculate random battleground reset time...");
InitRandomBGResetTime();
sLog.outString("Starting Game Event system...");
uint32 nextGameEvent = sGameEventMgr.Initialize();
m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent); // depend on next event
@ -1467,6 +1497,13 @@ void World::SetInitialWorldSettings()
sLog.outString("Initialize AuctionHouseBot...");
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");
uint32 uStartInterval = WorldTimer::getMSTimeDiff(uStartTime, WorldTimer::getMSTime());
@ -1526,9 +1563,13 @@ void World::Update(uint32 diff)
for (int i = 0; i < WUPDATE_COUNT; ++i)
{
if (m_timers[i].GetCurrent() >= 0)
{
m_timers[i].Update(diff);
}
else
{
m_timers[i].SetCurrent(0);
}
}
///- Update the game time and check for shutdown time
@ -1537,9 +1578,12 @@ void World::Update(uint32 diff)
///-Update mass mailer tasks if any
sMassMailMgr.Update();
/// Handle daily quests reset time
/// Handle daily quests and dungeon reset time
if (m_gameTime > m_NextDailyQuestReset)
{
ResetDailyQuests();
sLFGMgr.ResetDailyRecords();
}
/// Handle weekly quests reset time
if (m_gameTime > m_NextWeeklyQuestReset)
@ -1549,9 +1593,9 @@ void World::Update(uint32 diff)
if (m_gameTime > m_NextMonthlyQuestReset)
ResetMonthlyQuests();
/// Handle monthly quests reset time
if (m_gameTime > m_NextCurrencyReset)
ResetCurrencyWeekCounts();
/// Handle random battlegrounds reset time
if (m_gameTime > m_NextRandomBGReset)
ResetRandomBG();
/// <ul><li> Handle auctions when the timer has passed
if (m_timers[WUPDATE_AUCTIONS].Passed())
@ -1577,28 +1621,16 @@ void World::Update(uint32 diff)
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
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
if (m_timers[WUPDATE_UPTIME].Passed())
{
@ -1615,6 +1647,11 @@ void World::Update(uint32 diff)
sBattleGroundMgr.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
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
ProcessCliCommands();
///- Used by Eluna
#ifdef ENABLE_ELUNA
sEluna->OnWorldUpdate(diff);
#endif /* ENABLE_ELUNA */
// cleanup unused GridMap objects as well as VMaps
sTerrainMgr.Update(diff);
}
@ -2241,6 +2283,18 @@ void World::ResetDailyQuests()
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()
{
DETAIL_LOG("Weekly quests reset for all characters.");

View file

@ -78,13 +78,14 @@ enum ShutdownExitCode
enum WorldTimers
{
WUPDATE_AUCTIONS = 0,
WUPDATE_WEATHERS = 1,
WUPDATE_UPTIME = 2,
WUPDATE_CORPSES = 3,
WUPDATE_EVENTS = 4,
WUPDATE_DELETECHARS = 5,
WUPDATE_AHBOT = 6,
WUPDATE_COUNT = 7
WUPDATE_UPTIME = 1,
WUPDATE_CORPSES = 2,
WUPDATE_EVENTS = 3,
WUPDATE_DELETECHARS = 4,
WUPDATE_AHBOT = 5,
WUPDATE_LFGMGR = 6,
WUPDATE_WEATHERS = 7,
WUPDATE_COUNT = 8
};
/// Configuration elements
@ -126,6 +127,11 @@ enum eConfigUInt32Values
CONFIG_UINT32_MAX_PLAYER_LEVEL,
CONFIG_UINT32_START_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_CONQUEST_POINTS,
CONFIG_UINT32_CURRENCY_CONQUEST_POINTS_DEFAULT_WEEK_CAP,
@ -190,6 +196,7 @@ enum eConfigUInt32Values
CONFIG_UINT32_BATTLEGROUND_QUEUE_ANNOUNCER_JOIN,
CONFIG_UINT32_ARENA_MAX_RATING_DIFFERENCE,
CONFIG_UINT32_ARENA_RATING_DISCARD_TIMER,
CONFIG_UINT32_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS,
CONFIG_UINT32_ARENA_SEASON_ID,
CONFIG_UINT32_ARENA_SEASON_PREVIOUS_ID,
CONFIG_UINT32_CLIENTCACHE_VERSION,
@ -347,6 +354,7 @@ enum eConfigBoolValues
CONFIG_BOOL_SKILL_FAIL_POSSIBLE_FISHINGPOOL,
CONFIG_BOOL_BATTLEGROUND_CAST_DESERTER,
CONFIG_BOOL_BATTLEGROUND_QUEUE_ANNOUNCER_START,
CONFIG_BOOL_ARENA_AUTO_DISTRIBUTE_POINTS,
CONFIG_BOOL_ARENA_QUEUE_ANNOUNCER_JOIN,
CONFIG_BOOL_ARENA_QUEUE_ANNOUNCER_EXIT,
CONFIG_BOOL_OUTDOORPVP_SI_ENABLED,
@ -636,6 +644,7 @@ class World
void SetMonthlyQuestResetTime(bool initialize = true);
void ResetCurrencyWeekCounts();
void ResetDailyQuests();
void ResetRandomBG();
void ResetWeeklyQuests();
void ResetMonthlyQuests();
@ -716,6 +725,9 @@ class World
time_t m_NextWeeklyQuestReset;
time_t m_NextMonthlyQuestReset;
// next daily quests reset time
time_t m_NextRandomBGReset;
// Player Queue
Queue m_QueuedSessions;

View file

@ -2104,7 +2104,7 @@ namespace LuaPlayer
if (!quest || player->GetQuestStatus(entry) != QUEST_STATUS_COMPLETE)
return 0;
player->RewardQuest(quest, 0, player);
player->RewardQuest(quest, 0, player, false);
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",
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)
{
@ -163,11 +163,11 @@ void DoOrSimulateScriptTextForMap(int32 iTextEntry, uint32 uiCreatureEntry, Map*
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
{
pMap->MonsterYellToMap(pInfo, iTextEntry, pData->Language, pTarget);
pMap->MonsterYellToMap(pInfo, iTextEntry, pData->LanguageId, pTarget);
}
}