Merge branch 'azerothcore:master' into Playerbot

This commit is contained in:
ZhengPeiRu21
2023-03-21 08:46:26 -06:00
committed by GitHub
55 changed files with 3356 additions and 948 deletions
@@ -2481,6 +2481,12 @@ void AchievementGlobalMgr::LoadAchievementCriteriaList()
if (!criteria)
continue;
if (!GetAchievement(criteria->referredAchievement))
{
LOG_DEBUG("server.loading", "Achievement {} referenced by criteria {} doesn't exist, criteria not loaded.", criteria->referredAchievement, criteria->ID);
continue;
}
_achievementCriteriasByType[criteria->requiredType].push_back(criteria);
_achievementCriteriaListByAchievement[criteria->referredAchievement].push_back(criteria);
+5 -2
View File
@@ -917,10 +917,13 @@ void BfCapturePoint::SendChangePhase()
}
}
bool BfCapturePoint::SetCapturePointData(GameObject* capturePoint)
bool BfCapturePoint::SetCapturePointData(GameObject* capturePoint, TeamId team)
{
ASSERT(capturePoint);
//At first call using TEAM_NEUTRAL as a checker but never using it, after first call we reset the capturepoints to the new winner of the last WG war
if (team == TEAM_NEUTRAL)
team = m_team;
LOG_DEBUG("bg.battlefield", "Creating capture point {}", capturePoint->GetEntry());
m_capturePoint = capturePoint->GetGUID();
@@ -939,7 +942,7 @@ bool BfCapturePoint::SetCapturePointData(GameObject* capturePoint)
m_neutralValuePct = goinfo->capturePoint.neutralPercent;
m_minValue = m_maxValue * goinfo->capturePoint.neutralPercent / 100;
m_capturePointEntry = capturePoint->GetEntry();
if (m_team == TEAM_ALLIANCE)
if (team == TEAM_ALLIANCE)
{
m_value = m_maxValue;
m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE;
+2 -1
View File
@@ -104,7 +104,8 @@ public:
virtual void ChangeTeam(TeamId /*oldTeam*/) {}
virtual void SendChangePhase();
bool SetCapturePointData(GameObject* capturePoint);
//Added team to reset capturepoints on sliders after warTime
bool SetCapturePointData(GameObject* capturePoint, TeamId team);
GameObject* GetCapturePointGo();
GameObject* GetCapturePointGo(WorldObject* obj);
@@ -102,7 +102,7 @@ bool BattlefieldWG::SetupBattlefield()
// When between games, the graveyard is controlled by the defending team
if (WGGraveYard[i].startcontrol == TEAM_NEUTRAL)
graveyard->Initialize(m_DefenderTeam, WGGraveYard[i].gyid);
graveyard->Initialize(WGGraveYard[i].gyid == BATTLEFIELD_WG_GY_WORKSHOP_SE || WGGraveYard[i].gyid == BATTLEFIELD_WG_GY_WORKSHOP_SW ? GetAttackerTeam() : m_DefenderTeam, WGGraveYard[i].gyid);
else
graveyard->Initialize(WGGraveYard[i].startcontrol, WGGraveYard[i].gyid);
@@ -114,7 +114,7 @@ bool BattlefieldWG::SetupBattlefield()
for (uint8 i = 0; i < WG_MAX_WORKSHOP; i++)
{
WGWorkshop* workshop = new WGWorkshop(this, i);
if (i < BATTLEFIELD_WG_WORKSHOP_KEEP_WEST)
if (i == BATTLEFIELD_WG_WORKSHOP_SE || i == BATTLEFIELD_WG_WORKSHOP_SW)
workshop->GiveControlTo(GetAttackerTeam(), true);
else
workshop->GiveControlTo(GetDefenderTeam(), true);
@@ -262,6 +262,11 @@ void BattlefieldWG::OnBattleStart()
if (*itr)
(*itr)->UpdateGraveyardAndWorkshop();
// Set Sliders capture points data to his owners when battle start
for (BfCapturePointVector::const_iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
(*itr)->SetCapturePointData((*itr)->GetCapturePointGo(),
(*itr)->GetCapturePointGo()->GetEntry() == GO_WINTERGRASP_FACTORY_BANNER_SE || (*itr)->GetCapturePointGo()->GetEntry() == GO_WINTERGRASP_FACTORY_BANNER_SW ? GetAttackerTeam() : GetDefenderTeam());
for (uint8 team = 0; team < 2; ++team)
for (GuidUnorderedSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
{
@@ -375,7 +380,7 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer)
// Update all graveyard, control is to defender when no wartime
for (uint8 i = 0; i < BATTLEFIELD_WG_GY_HORDE; i++)
if (BfGraveyard* graveyard = GetGraveyardById(i))
graveyard->GiveControlTo(GetDefenderTeam());
graveyard->GiveControlTo(i == BATTLEFIELD_WG_GY_WORKSHOP_SE || i == BATTLEFIELD_WG_GY_WORKSHOP_SW ? GetAttackerTeam() : GetDefenderTeam());
for (GameObjectSet::const_iterator itr = m_KeepGameObject[GetDefenderTeam()].begin(); itr != m_KeepGameObject[GetDefenderTeam()].end(); ++itr)
(*itr)->SetRespawnTime(RESPAWN_IMMEDIATELY);
@@ -396,7 +401,10 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer)
}
for (Workshop::const_iterator itr = WorkshopsList.begin(); itr != WorkshopsList.end(); ++itr)
{
(*itr)->GiveControlTo((*itr)->workshopId == BATTLEFIELD_WG_WORKSHOP_SE || (*itr)->workshopId == BATTLEFIELD_WG_WORKSHOP_SW ? GetAttackerTeam() : GetDefenderTeam(), true);
(*itr)->Save();
}
for (uint8 team = 0; team < 2; ++team)
{
@@ -689,9 +697,9 @@ void BattlefieldWG::OnGameObjectCreate(GameObject* go)
{
if (workshop->workshopId == workshopId)
{
WintergraspCapturePoint* capturePoint = new WintergraspCapturePoint(this, GetAttackerTeam());
capturePoint->SetCapturePointData(go);
WintergraspCapturePoint* capturePoint = new WintergraspCapturePoint(this, workshop->teamControl);
//Sending neutral team at start to set normal capture points by workshop->teamControl, TEAM_NEUTRAL is ignored at first call
capturePoint->SetCapturePointData(go, TEAM_NEUTRAL);
capturePoint->LinkToWorkshop(workshop);
AddCapturePoint(capturePoint);
break;
@@ -846,7 +854,7 @@ void BattlefieldWG::OnPlayerJoinWar(Player* player)
if (player->GetTeamId() == TEAM_HORDE)
player->TeleportTo(571, 5025.857422f, 3674.628906f, 362.737122f, 4.135169f);
else
player->TeleportTo(571, 5101.284f, 2186.564f, 373.549f, 3.812f);
player->TeleportTo(571, 5101.284f, 2186.564f, 365.549f, 3.812f);
}
if (player->GetTeamId() == GetAttackerTeam())
@@ -1474,6 +1474,17 @@ struct WGWorkshop
// Send warning message to all player to inform a faction attack to a workshop
// alliance / horde attacking a workshop
bf->SendWarning(teamControl ? WorkshopsData[workshopId].attackText : (WorkshopsData[workshopId].attackText + 2));
// Updating worldstate, update icon to neutral
state = BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_INTACT;
bf->SendUpdateWorldState(WorkshopsData[workshopId].worldstate, state);
// Found associate graveyard and update it
if (workshopId < BATTLEFIELD_WG_WORKSHOP_KEEP_WEST)
if (bf->GetGraveyardById(workshopId))
bf->GetGraveyardById(workshopId)->GiveControlTo(team);
teamControl = team;
break;
}
case TEAM_ALLIANCE:
+12 -2
View File
@@ -927,7 +927,7 @@ void ArenaTeam::UpdateArenaPointsHelper(std::map<ObjectGuid, uint32>& playerPoin
}
}
void ArenaTeam::SaveToDB()
void ArenaTeam::SaveToDB(bool forceMemberSave)
{
if (!sScriptMgr->CanSaveToDB(this))
return;
@@ -949,6 +949,10 @@ void ArenaTeam::SaveToDB()
for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
// Save the effort and go
if (itr->WeekGames == 0 && !forceMemberSave)
continue;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ARENA_TEAM_MEMBER);
stmt->SetData(0, itr->PersonalRating);
stmt->SetData(1, itr->WeekGames);
@@ -970,8 +974,12 @@ void ArenaTeam::SaveToDB()
CharacterDatabase.CommitTransaction(trans);
}
void ArenaTeam::FinishWeek()
bool ArenaTeam::FinishWeek()
{
// No need to go further than this
if (Stats.WeekGames == 0)
return false;
// Reset team stats
Stats.WeekGames = 0;
Stats.WeekWins = 0;
@@ -982,6 +990,8 @@ void ArenaTeam::FinishWeek()
itr->WeekGames = 0;
itr->WeekWins = 0;
}
return true;
}
bool ArenaTeam::IsFighting() const
+2 -2
View File
@@ -182,7 +182,7 @@ public:
bool LoadArenaTeamFromDB(QueryResult arenaTeamDataResult);
bool LoadMembersFromDB(QueryResult arenaTeamMembersResult);
void LoadStatsFromDB(uint32 ArenaTeamId);
void SaveToDB();
void SaveToDB(bool forceMemberSave = false);
void BroadcastPacket(WorldPacket* packet);
void BroadcastEvent(ArenaTeamEvents event, ObjectGuid guid, uint8 strCount, std::string const& str1, std::string const& str2, std::string const& str3);
@@ -206,7 +206,7 @@ public:
void UpdateArenaPointsHelper(std::map<ObjectGuid, uint32>& PlayerPoints);
void FinishWeek();
bool FinishWeek(); // returns true if arena team played this week
void FinishGame(int32 mod, const Map* bgMap);
void SetPreviousOpponents(uint32 arenaTeamId) { PreviousOpponents = arenaTeamId; }
@@ -239,8 +239,9 @@ void ArenaTeamMgr::DistributeArenaPoints()
{
if (ArenaTeam* at = titr->second)
{
at->FinishWeek();
at->SaveToDB();
if (at->FinishWeek())
at->SaveToDB(true);
at->NotifyStatsChanged();
}
}
+30 -5
View File
@@ -1863,7 +1863,9 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
return false;
if (!CanDetect(obj, ignoreStealth, !distanceCheck, checkAlert))
{
return false;
}
return true;
}
@@ -1890,7 +1892,9 @@ bool WorldObject::CanDetect(WorldObject const* obj, bool ignoreStealth, bool che
if (!ignoreStealth)
{
if (!seer->CanDetectInvisibilityOf(obj)) // xinef: added ignoreStealth, allow AoE spells to hit invisible targets!
{
return false;
}
if (!seer->CanDetectStealthOf(obj, checkAlert))
{
@@ -1923,11 +1927,32 @@ bool WorldObject::CanDetectInvisibilityOf(WorldObject const* obj) const
// It seems like that only Units are affected by this check (couldn't see arena doors with preparation invisibility)
if (obj->ToUnit())
{
uint32 objMask = m_invisibility.GetFlags() & obj->m_invisibilityDetect.GetFlags();
// xinef: include invisible flags of caster in the mask, 2 invisible objects should be able to detect eachother
objMask |= m_invisibility.GetFlags() & obj->m_invisibility.GetFlags();
if (objMask != m_invisibility.GetFlags())
return false;
// Permanently invisible creatures should be able to engage non-invisible targets.
// ex. Skulking Witch (20882) / Greater Invisibility (16380)
bool isPermInvisibleCreature = false;
if (Creature const* baseObj = ToCreature())
{
auto auraEffects = baseObj->GetAuraEffectsByType(SPELL_AURA_MOD_INVISIBILITY);
for (auto const effect : auraEffects)
{
if (SpellInfo const* spell = effect->GetSpellInfo())
{
if (spell->GetMaxDuration() == -1)
{
isPermInvisibleCreature = true;
}
}
}
}
if (!isPermInvisibleCreature)
{
uint32 objMask = m_invisibility.GetFlags() & obj->m_invisibilityDetect.GetFlags();
// xinef: include invisible flags of caster in the mask, 2 invisible objects should be able to detect eachother
objMask |= m_invisibility.GetFlags() & obj->m_invisibility.GetFlags();
if (objMask != m_invisibility.GetFlags())
return false;
}
}
for (uint32 i = 0; i < TOTAL_INVISIBILITY_TYPES; ++i)
+1 -1
View File
@@ -15144,7 +15144,7 @@ void Player::ActivateSpec(uint8 spec)
for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end();)
{
Aura* aura = *iter;
if (!HasActiveSpell(aura->GetId()) && !HasTalent(aura->GetId(), GetActiveSpec()))
if (!HasActiveSpell(aura->GetId()) && !HasTalent(aura->GetId(), GetActiveSpec()) && !aura->GetCastItemGUID())
{
aura->Remove();
iter = scAuras.begin();
+1 -1
View File
@@ -13490,7 +13490,7 @@ void Unit::Dismount()
if (Player* player = ToPlayer())
{
sScriptMgr->AnticheatSetUnderACKmount(player);
ToPlayer()->SetCanTeleport(true);
if (Pet* pPet = player->GetPet())
{
if (pPet->HasUnitFlag(UNIT_FLAG_STUNNED) && !pPet->HasUnitState(UNIT_STATE_STUNNED))
+18 -3
View File
@@ -18,6 +18,7 @@
#include "ObjectGridLoader.h"
#include "CellImpl.h"
#include "Corpse.h"
#include "GridNotifiers.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "DynamicObject.h"
@@ -97,13 +98,17 @@ void AddObjectHelper(CellCoord& cell, GameObjectMapType& m, uint32& count, Map*
}
template <class T>
void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefMgr<T>& m, uint32& count, Map* map)
void LoadHelper(CellGuidSet const& /*guid_set*/, CellCoord& /*cell*/, GridRefMgr<T>& /*m*/, uint32& /*count*/, Map* /*map*/)
{
}
template <>
void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefMgr<Creature>& m, uint32& count, Map* map)
{
for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid)
{
T* obj = new T;
Creature* obj = new Creature();
ObjectGuid::LowType guid = *i_guid;
if (!obj->LoadFromDB(guid, map))
{
delete obj;
@@ -111,6 +116,16 @@ void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefMgr<T>& m,
}
AddObjectHelper(cell, m, count, map, obj);
if (!obj->IsMoveInLineOfSightDisabled() && obj->GetDefaultMovementType() == IDLE_MOTION_TYPE && !obj->isNeedNotify(NOTIFY_VISIBILITY_CHANGED | NOTIFY_AI_RELOCATION))
{
if (obj->IsAlive() && !obj->HasUnitState(UNIT_STATE_SIGHTLESS) && obj->HasReactState(REACT_AGGRESSIVE) && !obj->IsImmuneToNPC())
{
// call MoveInLineOfSight for nearby grid creatures
Acore::AIRelocationNotifier notifier(*obj);
Cell::VisitGridObjects(obj, notifier, 60.f);
}
}
}
}
+7 -6
View File
@@ -237,6 +237,13 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
return;
}
// handle empty bag before CanBeTraded, since that func already has that check
if (item->IsNotEmptyBag())
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS);
return;
}
if (!item->CanBeTraded(true))
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM);
@@ -261,12 +268,6 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
return;
}
if (item->IsNotEmptyBag())
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS);
return;
}
if (!sScriptMgr->CanSendMail(player, receiverGuid, mailbox, subject, body, money, COD, item))
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_INTERNAL_ERROR);
+5 -1
View File
@@ -355,8 +355,12 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
sessionGuard.lock();
LogOpcodeText(opcode, sessionGuard);
if (_worldSession)
{
_worldSession->ResetTimeOutTime(true);
return ReadDataHandlerResult::Ok;
return ReadDataHandlerResult::Ok;
}
LOG_ERROR("network", "WorldSocket::ReadDataHandler: client {} sent CMSG_KEEP_ALIVE without being authenticated", GetRemoteIpAddress().to_string());
return ReadDataHandlerResult::Error;
case CMSG_TIME_SYNC_RESP:
packetToQueue = new WorldPacket(std::move(packet), GameTime::Now());
break;
+2 -1
View File
@@ -6328,7 +6328,8 @@ SpellCastResult Spell::CheckCast(bool strict)
// chance for fail at lockpicking attempt
// second check prevent fail at rechecks
if (skillId != SKILL_NONE && (!m_selfContainer || ((*m_selfContainer) != this)))
// herbalism and mining cannot fail as of patch 3.1.0
if (skillId != SKILL_NONE && skillId != SKILL_HERBALISM && skillId != SKILL_MINING && (!m_selfContainer || ((*m_selfContainer) != this)))
{
// chance for failure in orange lockpick
if (skillId == SKILL_LOCKPICKING && reqSkillValue > irand(skillValue - 25, skillValue + 37))
@@ -4483,6 +4483,18 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->AttributesEx5 |= SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL;
});
// Buffeting Winds of Susurrus
ApplySpellFix({ 32474 }, [](SpellInfo* spellInfo)
{
spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(556); // 28 seconds
});
// Quest - Healing Salve
ApplySpellFix({ 29314 }, [](SpellInfo* spellInfo)
{
spellInfo->CastTimeEntry = sSpellCastTimesStore.LookupEntry(1); // 0s
});
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
SpellInfo* spellInfo = mSpellInfoMap[i];
+2
View File
@@ -1193,6 +1193,8 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
return spellId == 56618;
else if (team == TEAM_ALLIANCE)
return spellId == 56617;
else
return false;
break;
}
// Hellscream's Warsong