Compare commits
8 Commits
c276e0b530
...
b6a4087afb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6a4087afb | ||
|
|
9f99e89bc3 | ||
|
|
b83071388c | ||
|
|
f234f034a1 | ||
|
|
591b5fc61f | ||
|
|
2ed3a480b7 | ||
|
|
cc5950f068 | ||
|
|
38149673de |
@ -0,0 +1,36 @@
|
||||
--
|
||||
DROP TABLE IF EXISTS `mail_server_template_items`;
|
||||
CREATE TABLE `mail_server_template_items` (
|
||||
`id` INT UNSIGNED AUTO_INCREMENT,
|
||||
`templateID` INT UNSIGNED NOT NULL,
|
||||
`faction` ENUM('Alliance', 'Horde') NOT NULL,
|
||||
`item` INT UNSIGNED NOT NULL,
|
||||
`itemCount` INT UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
CONSTRAINT `fk_mail_template`
|
||||
FOREIGN KEY (`templateID`) REFERENCES `mail_server_template`(`id`)
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB COLLATE='utf8mb4_unicode_ci';
|
||||
|
||||
INSERT INTO `mail_server_template_items` (`templateID`, `faction`, `item`, `itemCount`)
|
||||
SELECT `id`, 'Alliance', `itemA`, `itemCountA` FROM `mail_server_template` WHERE `itemA` > 0;
|
||||
|
||||
INSERT INTO `mail_server_template_items` (`templateID`, `faction`, `item`, `itemCount`)
|
||||
SELECT `id`, 'Horde', `itemH`, `itemCountH` FROM `mail_server_template` WHERE `itemH` > 0;
|
||||
|
||||
ALTER TABLE `mail_server_template`
|
||||
DROP COLUMN `itemA`,
|
||||
DROP COLUMN `itemCountA`,
|
||||
DROP COLUMN `itemH`,
|
||||
DROP COLUMN `itemCountH`;
|
||||
|
||||
-- Make sure we dont have invalid instances in mail_server_character.mailId before we add the foregin key to avoid SQL errors
|
||||
DELETE FROM `mail_server_character` WHERE `mailId` NOT IN (SELECT `id` FROM `mail_server_template`);
|
||||
|
||||
-- Add foreign key for mail_server_character.mailId
|
||||
ALTER TABLE `mail_server_character`
|
||||
DROP PRIMARY KEY,
|
||||
ADD PRIMARY KEY (`guid`, `mailId`),
|
||||
ADD CONSTRAINT `fk_mail_template_character`
|
||||
FOREIGN KEY (`mailId`) REFERENCES `mail_server_template`(`id`)
|
||||
ON DELETE CASCADE;
|
||||
@ -10298,38 +10298,45 @@ uint32 ObjectMgr::GetQuestMoneyReward(uint8 level, uint32 questMoneyDifficulty)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ObjectMgr::SendServerMail(Player* player, uint32 id, uint32 reqLevel, uint32 reqPlayTime, uint32 rewardMoneyA, uint32 rewardMoneyH, uint32 rewardItemA, uint32 rewardItemCountA, uint32 rewardItemH, uint32 rewardItemCountH, std::string subject, std::string body, uint8 active) const
|
||||
void ObjectMgr::SendServerMail(Player* player, uint32 id, uint32 reqLevel, uint32 reqPlayTime, uint32 rewardMoneyA, uint32 rewardMoneyH, std::vector<ServerMailItems> const& items, std::string subject, std::string body, uint8 active) const
|
||||
{
|
||||
if (active)
|
||||
if (!active)
|
||||
return;
|
||||
|
||||
if (player->GetLevel() < reqLevel)
|
||||
return;
|
||||
|
||||
if (player->GetTotalPlayedTime() < reqPlayTime)
|
||||
return;
|
||||
|
||||
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
|
||||
|
||||
MailSender sender(MAIL_NORMAL, player->GetGUID().GetCounter(), MAIL_STATIONERY_GM);
|
||||
MailDraft draft(subject, body);
|
||||
|
||||
draft.AddMoney(player->GetTeamId() == TEAM_ALLIANCE ? rewardMoneyA : rewardMoneyH);
|
||||
// Loop through all items and attach them to the mail
|
||||
for (auto const& mailItem : items)
|
||||
{
|
||||
if (player->GetLevel() < reqLevel)
|
||||
return;
|
||||
if (!mailItem.item || !mailItem.itemCount)
|
||||
continue;
|
||||
|
||||
if (player->GetTotalPlayedTime() < reqPlayTime)
|
||||
return;
|
||||
|
||||
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
|
||||
|
||||
MailSender sender(MAIL_NORMAL, player->GetGUID().GetCounter(), MAIL_STATIONERY_GM);
|
||||
MailDraft draft(subject, body);
|
||||
|
||||
draft.AddMoney(player->GetTeamId() == TEAM_ALLIANCE ? rewardMoneyA : rewardMoneyH);
|
||||
if (Item* mailItem = Item::CreateItem(player->GetTeamId() == TEAM_ALLIANCE ? rewardItemA : rewardItemH, player->GetTeamId() == TEAM_ALLIANCE ? rewardItemCountA : rewardItemCountH))
|
||||
if (Item* newItem = Item::CreateItem(mailItem.item, mailItem.itemCount))
|
||||
{
|
||||
mailItem->SaveToDB(trans);
|
||||
draft.AddItem(mailItem);
|
||||
newItem->SaveToDB(trans);
|
||||
draft.AddItem(newItem);
|
||||
}
|
||||
|
||||
draft.SendMailTo(trans, MailReceiver(player), sender);
|
||||
CharacterDatabase.CommitTransaction(trans);
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_MAIL_SERVER_CHARACTER);
|
||||
stmt->SetData(0, player->GetGUID().GetCounter());
|
||||
stmt->SetData(1, id);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
LOG_DEBUG("entities.player", "ObjectMgr::SendServerMail() Sent mail id {} to {}", id, player->GetGUID().ToString());
|
||||
}
|
||||
|
||||
draft.SendMailTo(trans, MailReceiver(player), sender);
|
||||
CharacterDatabase.CommitTransaction(trans);
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_MAIL_SERVER_CHARACTER);
|
||||
stmt->SetData(0, player->GetGUID().GetCounter());
|
||||
stmt->SetData(1, id);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
LOG_DEBUG("entities.player", "ObjectMgr::SendServerMail() Sent mail id {} to {}", id, player->GetGUID().ToString());
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadMailServerTemplates()
|
||||
@ -10338,8 +10345,8 @@ void ObjectMgr::LoadMailServerTemplates()
|
||||
|
||||
_serverMailStore.clear(); // for reload case
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11
|
||||
QueryResult result = CharacterDatabase.Query("SELECT `id`, `reqLevel`, `reqPlayTime`, `moneyA`, `moneyH`, `itemA`, `itemCountA`, `itemH`,`itemCountH`, `subject`, `body`, `active` FROM `mail_server_template`");
|
||||
// 0 1 2 3 4 5 6 7
|
||||
QueryResult result = CharacterDatabase.Query("SELECT `id`, `reqLevel`, `reqPlayTime`, `moneyA`, `moneyH`, `subject`, `body`, `active` FROM `mail_server_template`");
|
||||
if (!result)
|
||||
{
|
||||
LOG_INFO("sql.sql", ">> Loaded 0 server mail rewards. DB table `mail_server_template` is empty.");
|
||||
@ -10362,13 +10369,9 @@ void ObjectMgr::LoadMailServerTemplates()
|
||||
servMail.reqPlayTime = fields[2].Get<uint32>();
|
||||
servMail.moneyA = fields[3].Get<uint32>();
|
||||
servMail.moneyH = fields[4].Get<uint32>();
|
||||
servMail.itemA = fields[5].Get<uint32>();
|
||||
servMail.itemCountA = fields[6].Get<uint32>();
|
||||
servMail.itemH = fields[7].Get<uint32>();
|
||||
servMail.itemCountH = fields[8].Get<uint32>();
|
||||
servMail.subject = fields[9].Get<std::string>();
|
||||
servMail.body = fields[10].Get<std::string>();
|
||||
servMail.active = fields[11].Get<uint8>();
|
||||
servMail.subject = fields[5].Get<std::string>();
|
||||
servMail.body = fields[6].Get<std::string>();
|
||||
servMail.active = fields[7].Get<uint8>();
|
||||
|
||||
if (servMail.reqLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
@ -10381,32 +10384,79 @@ void ObjectMgr::LoadMailServerTemplates()
|
||||
LOG_ERROR("sql.sql", "Table `mail_server_template` has moneyA {} or moneyH {} larger than MAX_MONEY_AMOUNT {} for id {}, skipped.", servMail.moneyA, servMail.moneyH, MAX_MONEY_AMOUNT, servMail.id);
|
||||
return;
|
||||
}
|
||||
|
||||
ItemTemplate const* itemTemplateA = sObjectMgr->GetItemTemplate(servMail.itemA);
|
||||
if (!itemTemplateA && servMail.itemA)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Table `mail_server_template` has invalid item in itemA {} for id {}, skipped.", servMail.itemA, servMail.id);
|
||||
return;
|
||||
}
|
||||
ItemTemplate const* itemTemplateH = sObjectMgr->GetItemTemplate(servMail.itemH);
|
||||
if (!itemTemplateH && servMail.itemH)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Table `mail_server_template` has invalid item in itemH {} for id {}, skipped.", servMail.itemH, servMail.id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!servMail.itemA && servMail.itemCountA)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Table `mail_server_template` has itemCountA {} with no ItemA, set to 0", servMail.itemCountA);
|
||||
servMail.itemCountA = 0;
|
||||
}
|
||||
if (!servMail.itemH && servMail.itemCountH)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Table `mail_server_template` has itemCountH {} with no ItemH, set to 0", servMail.itemCountH);
|
||||
servMail.itemCountH = 0;
|
||||
}
|
||||
} while (result->NextRow());
|
||||
|
||||
LoadMailServerTemplatesItems();
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded {} Mail Server Template in {} ms", _serverMailStore.size(), GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadMailServerTemplatesItems()
|
||||
{
|
||||
QueryResult result = CharacterDatabase.Query("SELECT `templateID`, `faction`, `item`, `itemCount` FROM `mail_server_template_items`");
|
||||
if (!result)
|
||||
{
|
||||
LOG_INFO("sql.sql", ">> Loaded 0 server mail items. DB table `mail_server_template_items` is empty.");
|
||||
LOG_INFO("server.loading", " ");
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 templateID = fields[0].Get<uint32>();
|
||||
std::string faction = fields[1].Get<std::string>();
|
||||
uint32 item = fields[2].Get<uint32>();
|
||||
uint32 itemCount = fields[3].Get<uint32>();
|
||||
|
||||
if (_serverMailStore.find(templateID) == _serverMailStore.end())
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Table `mail_server_template_items` has an invalid templateID {}, skipped.", templateID);
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(item);
|
||||
if (!itemTemplate)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Table `mail_server_template_items` has an invalid item {} for templateID {}, skipped.", item, templateID);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!itemCount)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Table `mail_server_template_items` has itemCount 0 for item {}, skipped.", item);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 stackable = itemTemplate->Stackable;
|
||||
if (itemCount > stackable)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Table `mail_server_template_items` has itemCount {} exceeding item_template.Stackable {} for item {}, skipped.", itemCount, stackable, item);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 maxCount = itemTemplate->MaxCount;
|
||||
if (maxCount && itemCount > maxCount)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Table `mail_server_template_items` has itemCount {} exceeding item_template.MaxCount {} for item {}, skipped", itemCount, maxCount, item);
|
||||
continue;
|
||||
}
|
||||
|
||||
ServerMailItems mailItem;
|
||||
mailItem.item = item;
|
||||
mailItem.itemCount = itemCount;
|
||||
|
||||
if (faction == "Alliance")
|
||||
_serverMailStore[templateID].itemsA.push_back(mailItem);
|
||||
else if (faction == "Horde")
|
||||
_serverMailStore[templateID].itemsH.push_back(mailItem);
|
||||
else
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Table `mail_server_template_items` has invalid faction value '{}' for id {}, skipped.", faction, templateID);
|
||||
continue;
|
||||
}
|
||||
|
||||
} while (result->NextRow());
|
||||
}
|
||||
|
||||
@ -1056,6 +1056,7 @@ public:
|
||||
void LoadInstanceEncounters();
|
||||
void LoadMailLevelRewards();
|
||||
void LoadMailServerTemplates();
|
||||
void LoadMailServerTemplatesItems();
|
||||
void LoadVehicleTemplateAccessories();
|
||||
void LoadVehicleAccessories();
|
||||
void LoadVehicleSeatAddon();
|
||||
@ -1449,7 +1450,7 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] uint32 GetQuestMoneyReward(uint8 level, uint32 questMoneyDifficulty) const;
|
||||
void SendServerMail(Player* player, uint32 id, uint32 reqLevel, uint32 reqPlayTime, uint32 rewardMoneyA, uint32 rewardMoneyH, uint32 rewardItemA, uint32 rewardItemCountA, uint32 rewardItemH, uint32 rewardItemCountH, std::string subject, std::string body, uint8 active) const;
|
||||
void SendServerMail(Player* player, uint32 id, uint32 reqLevel, uint32 reqPlayTime, uint32 rewardMoneyA, uint32 rewardMoneyH, std::vector<ServerMailItems> const& items, std::string subject, std::string body, uint8 active) const;
|
||||
private:
|
||||
// first free id for selected id type
|
||||
uint32 _auctionId; // pussywizard: accessed by a single thread
|
||||
|
||||
@ -210,6 +210,13 @@ struct Mail
|
||||
[[nodiscard]] bool IsReturnedMail() const { return checked & MAIL_CHECK_MASK_RETURNED; }
|
||||
};
|
||||
|
||||
struct ServerMailItems
|
||||
{
|
||||
ServerMailItems() = default;
|
||||
uint32 item{ 0 };
|
||||
uint32 itemCount{ 0 };
|
||||
};
|
||||
|
||||
struct ServerMail
|
||||
{
|
||||
ServerMail() = default;
|
||||
@ -218,13 +225,13 @@ struct ServerMail
|
||||
uint32 reqPlayTime{ 0 };
|
||||
uint32 moneyA{ 0 };
|
||||
uint32 moneyH{ 0 };
|
||||
uint32 itemA{ 0 };
|
||||
uint32 itemCountA{ 0 };
|
||||
uint32 itemH{ 0 };
|
||||
uint32 itemCountH{ 0 };
|
||||
std::string subject;
|
||||
std::string body;
|
||||
uint8 active{ 0 };
|
||||
|
||||
// Items from mail_server_template_items
|
||||
std::vector<ServerMailItems> itemsA;
|
||||
std::vector<ServerMailItems> itemsH;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -588,16 +588,20 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
if (t_diff)
|
||||
_dynamicTree.update(t_diff);
|
||||
|
||||
/// update worldsessions for existing players
|
||||
// Update world sessions and players
|
||||
for (m_mapRefIter = m_mapRefMgr.begin(); m_mapRefIter != m_mapRefMgr.end(); ++m_mapRefIter)
|
||||
{
|
||||
Player* player = m_mapRefIter->GetSource();
|
||||
if (player && player->IsInWorld())
|
||||
{
|
||||
//player->Update(t_diff);
|
||||
// Update session
|
||||
WorldSession* session = player->GetSession();
|
||||
MapSessionFilter updater(session);
|
||||
session->Update(s_diff, updater);
|
||||
|
||||
// update players at tick
|
||||
if (!t_diff)
|
||||
player->Update(s_diff);
|
||||
}
|
||||
}
|
||||
|
||||
@ -605,17 +609,6 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
|
||||
if (!t_diff)
|
||||
{
|
||||
for (m_mapRefIter = m_mapRefMgr.begin(); m_mapRefIter != m_mapRefMgr.end(); ++m_mapRefIter)
|
||||
{
|
||||
Player* player = m_mapRefIter->GetSource();
|
||||
|
||||
if (!player || !player->IsInWorld())
|
||||
continue;
|
||||
|
||||
// update players at tick
|
||||
player->Update(s_diff);
|
||||
}
|
||||
|
||||
HandleDelayedVisibility();
|
||||
return;
|
||||
}
|
||||
@ -624,36 +617,35 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
resetMarkedCells();
|
||||
resetMarkedCellsLarge();
|
||||
|
||||
// Prepare object updaters
|
||||
Acore::ObjectUpdater updater(t_diff, false);
|
||||
|
||||
// for creature
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer > grid_object_update(updater);
|
||||
// for pets
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer > world_object_update(updater);
|
||||
// For creature
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer> grid_object_update(updater);
|
||||
|
||||
// for large creatures
|
||||
// For pets
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer> world_object_update(updater);
|
||||
|
||||
// For large creatures
|
||||
Acore::ObjectUpdater largeObjectUpdater(t_diff, true);
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer > grid_large_object_update(largeObjectUpdater);
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer > world_large_object_update(largeObjectUpdater);
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer> grid_large_object_update(largeObjectUpdater);
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer> world_large_object_update(largeObjectUpdater);
|
||||
|
||||
// pussywizard: container for far creatures in combat with players
|
||||
std::vector<Creature*> updateList;
|
||||
updateList.reserve(10);
|
||||
|
||||
// non-player active objects, increasing iterator in the loop in case of object removal
|
||||
// Update non-player active objects
|
||||
for (m_activeNonPlayersIter = m_activeNonPlayers.begin(); m_activeNonPlayersIter != m_activeNonPlayers.end();)
|
||||
{
|
||||
WorldObject* obj = *m_activeNonPlayersIter;
|
||||
++m_activeNonPlayersIter;
|
||||
|
||||
if (!obj || !obj->IsInWorld())
|
||||
continue;
|
||||
|
||||
VisitNearbyCellsOf(obj, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
if (obj && obj->IsInWorld())
|
||||
VisitNearbyCellsOf(obj, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
}
|
||||
|
||||
// the player iterator is stored in the map object
|
||||
// to make sure calls to Map::Remove don't invalidate it
|
||||
// Update players and their associated objects
|
||||
for (m_mapRefIter = m_mapRefMgr.begin(); m_mapRefIter != m_mapRefMgr.end(); ++m_mapRefIter)
|
||||
{
|
||||
Player* player = m_mapRefIter->GetSource();
|
||||
@ -661,12 +653,10 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
if (!player || !player->IsInWorld())
|
||||
continue;
|
||||
|
||||
// update players at tick
|
||||
player->Update(s_diff);
|
||||
|
||||
VisitNearbyCellsOfPlayer(player, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
|
||||
// If player is using far sight, visit that object too
|
||||
// If player is using far sight, update viewpoint
|
||||
if (WorldObject* viewPoint = player->GetViewpoint())
|
||||
{
|
||||
if (Creature* viewCreature = viewPoint->ToCreature())
|
||||
@ -684,7 +674,8 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
{
|
||||
updateList.clear();
|
||||
float rangeSq = player->GetGridActivationRange() - 1.0f;
|
||||
rangeSq = rangeSq * rangeSq;
|
||||
rangeSq *= rangeSq;
|
||||
|
||||
HostileReference* ref = player->getHostileRefMgr().getFirst();
|
||||
while (ref)
|
||||
{
|
||||
@ -694,20 +685,20 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
updateList.push_back(cre);
|
||||
ref = ref->next();
|
||||
}
|
||||
for (std::vector<Creature*>::const_iterator itr = updateList.begin(); itr != updateList.end(); ++itr)
|
||||
VisitNearbyCellsOf(*itr, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
|
||||
for (Creature* cre : updateList)
|
||||
VisitNearbyCellsOf(cre, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
}
|
||||
}
|
||||
|
||||
for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();) // pussywizard: transports updated after VisitNearbyCellsOf, grids around are loaded, everything ok
|
||||
// Update transports - pussywizard: transports updated after VisitNearbyCellsOf, grids around are loaded, everything ok
|
||||
for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();)
|
||||
{
|
||||
MotionTransport* transport = *_transportsUpdateIter;
|
||||
++_transportsUpdateIter;
|
||||
|
||||
if (!transport->IsInWorld())
|
||||
continue;
|
||||
|
||||
transport->Update(t_diff);
|
||||
if (transport->IsInWorld())
|
||||
transport->Update(t_diff);
|
||||
}
|
||||
|
||||
SendObjectUpdates();
|
||||
@ -1674,14 +1665,16 @@ bool Map::IsUnderWater(uint32 phaseMask, float x, float y, float z, float collis
|
||||
|
||||
bool Map::HasEnoughWater(WorldObject const* searcher, float x, float y, float z) const
|
||||
{
|
||||
LiquidData const& liquidData = const_cast<Map*>(this)->GetLiquidData(searcher->GetPhaseMask(), x, y, z, searcher->GetCollisionHeight(), MAP_ALL_LIQUIDS);
|
||||
return (liquidData.Status & MAP_LIQUID_STATUS_SWIMMING) != 0 && HasEnoughWater(searcher, liquidData);
|
||||
}
|
||||
LiquidData const& liquidData = const_cast<Map*>(this)->GetLiquidData(
|
||||
searcher->GetPhaseMask(), x, y, z, searcher->GetCollisionHeight(), MAP_ALL_LIQUIDS);
|
||||
|
||||
if ((liquidData.Status & MAP_LIQUID_STATUS_SWIMMING) == 0)
|
||||
return false;
|
||||
|
||||
bool Map::HasEnoughWater(WorldObject const* searcher, LiquidData const& liquidData) const
|
||||
{
|
||||
float minHeightInWater = searcher->GetMinHeightInWater();
|
||||
return liquidData.Level > INVALID_HEIGHT && liquidData.Level > liquidData.DepthLevel && liquidData.Level - liquidData.DepthLevel >= minHeightInWater;
|
||||
return liquidData.Level > INVALID_HEIGHT &&
|
||||
liquidData.Level > liquidData.DepthLevel &&
|
||||
liquidData.Level - liquidData.DepthLevel >= minHeightInWater;
|
||||
}
|
||||
|
||||
char const* Map::GetMapName() const
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellScriptLoader.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "sunwell_plateau.h"
|
||||
|
||||
enum Quotes
|
||||
@ -83,6 +84,10 @@ struct boss_sacrolash : public BossAI
|
||||
_isSisterDead = false;
|
||||
BossAI::Reset();
|
||||
me->SetLootMode(0);
|
||||
|
||||
if (Creature* alythess = instance->GetCreature(DATA_ALYTHESS))
|
||||
if (!alythess->IsAlive())
|
||||
alythess->Respawn(true);
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
@ -104,18 +109,6 @@ struct boss_sacrolash : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
BossAI::EnterEvadeMode(why);
|
||||
if (Creature* alythess = instance->GetCreature(DATA_ALYTHESS))
|
||||
{
|
||||
if (!alythess->IsAlive())
|
||||
alythess->Respawn(true);
|
||||
else if (!alythess->IsInEvadeMode())
|
||||
alythess->AI()->EnterEvadeMode(why);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
@ -191,6 +184,10 @@ struct boss_alythess : public BossAI
|
||||
_isSisterDead = false;
|
||||
BossAI::Reset();
|
||||
me->SetLootMode(0);
|
||||
|
||||
if (Creature* sacrolash = instance->GetCreature(DATA_SACROLASH))
|
||||
if (!sacrolash->IsAlive())
|
||||
sacrolash->Respawn(true);
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
@ -212,18 +209,6 @@ struct boss_alythess : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
BossAI::EnterEvadeMode(why);
|
||||
if (Creature* sacrolash = instance->GetCreature(DATA_SACROLASH))
|
||||
{
|
||||
if (!sacrolash->IsAlive())
|
||||
sacrolash->Respawn(true);
|
||||
else if (!sacrolash->IsInEvadeMode())
|
||||
sacrolash->AI()->EnterEvadeMode(why);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
@ -381,8 +366,15 @@ public:
|
||||
return ValidateSpellInfo({ _touchSpell });
|
||||
}
|
||||
|
||||
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
if (aurEff->GetId() == SPELL_FLAME_SEAR)
|
||||
{
|
||||
uint32 tick = aurEff->GetTickNumber();
|
||||
if (tick % 2 != 0 || tick > 10)
|
||||
return;
|
||||
}
|
||||
|
||||
if (Unit* owner = GetOwner()->ToUnit())
|
||||
owner->CastSpell(owner, _touchSpell, true);
|
||||
}
|
||||
|
||||
@ -37,6 +37,7 @@ public:
|
||||
return;
|
||||
|
||||
uint32 playerGUID = player->GetGUID().GetCounter();
|
||||
bool isAlliance = player->GetTeamId() == TEAM_ALLIANCE;
|
||||
|
||||
for (auto const& [mailId, servMail] : serverMailStore)
|
||||
{
|
||||
@ -45,12 +46,14 @@ public:
|
||||
stmt->SetData(1, mailId);
|
||||
|
||||
// Capture servMail by value
|
||||
auto callback = [session, servMailWrapper = std::reference_wrapper<ServerMail const>(servMail)](PreparedQueryResult result)
|
||||
auto callback = [session, servMailWrapper = std::reference_wrapper<ServerMail const>(servMail), isAlliance](PreparedQueryResult result)
|
||||
{
|
||||
ServerMail const& servMail = servMailWrapper.get(); // Dereference the wrapper to get the original object
|
||||
|
||||
if (!result)
|
||||
{
|
||||
std::vector<ServerMailItems> const& items = isAlliance ? servMail.itemsA : servMail.itemsH;
|
||||
|
||||
sObjectMgr->SendServerMail(
|
||||
session->GetPlayer(),
|
||||
servMail.id,
|
||||
@ -58,10 +61,7 @@ public:
|
||||
servMail.reqPlayTime,
|
||||
servMail.moneyA,
|
||||
servMail.moneyH,
|
||||
servMail.itemA,
|
||||
servMail.itemCountA,
|
||||
servMail.itemH,
|
||||
servMail.itemCountH,
|
||||
items,
|
||||
servMail.subject,
|
||||
servMail.body,
|
||||
servMail.active
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user