@@ -162,7 +162,7 @@ void AccountInfo::LoadResult(Field* fields)
|
||||
Utf8ToUpperOnlyLatin(Login);
|
||||
}
|
||||
|
||||
AuthSession::AuthSession(tcp::socket&& socket) :
|
||||
AuthSession::AuthSession(IoContextTcpSocket&& socket) :
|
||||
Socket(std::move(socket)), _status(STATUS_CHALLENGE), _build(0), _expversion(0) { }
|
||||
|
||||
void AuthSession::Start()
|
||||
@@ -216,7 +216,7 @@ void AuthSession::CheckIpCallback(PreparedQueryResult result)
|
||||
AsyncRead();
|
||||
}
|
||||
|
||||
void AuthSession::ReadHandler()
|
||||
SocketReadCallbackResult AuthSession::ReadHandler()
|
||||
{
|
||||
MessageBuffer& packet = GetReadBuffer();
|
||||
|
||||
@@ -234,7 +234,7 @@ void AuthSession::ReadHandler()
|
||||
if (_status != itr->second.status)
|
||||
{
|
||||
CloseSocket();
|
||||
return;
|
||||
return SocketReadCallbackResult::Stop;
|
||||
}
|
||||
|
||||
uint16 size = uint16(itr->second.packetSize);
|
||||
@@ -248,7 +248,7 @@ void AuthSession::ReadHandler()
|
||||
if (size > MAX_ACCEPTED_CHALLENGE_SIZE)
|
||||
{
|
||||
CloseSocket();
|
||||
return;
|
||||
return SocketReadCallbackResult::Stop;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,13 +258,13 @@ void AuthSession::ReadHandler()
|
||||
if (!(*this.*itr->second.handler)())
|
||||
{
|
||||
CloseSocket();
|
||||
return;
|
||||
return SocketReadCallbackResult::Stop;
|
||||
}
|
||||
|
||||
packet.ReadCompleted(size);
|
||||
}
|
||||
|
||||
AsyncRead();
|
||||
return SocketReadCallbackResult::KeepReading;
|
||||
}
|
||||
|
||||
void AuthSession::SendPacket(ByteBuffer& packet)
|
||||
|
||||
@@ -60,22 +60,22 @@ struct AccountInfo
|
||||
AccountTypes SecurityLevel = SEC_PLAYER;
|
||||
};
|
||||
|
||||
class AuthSession : public Socket<AuthSession>
|
||||
class AuthSession final : public Socket<AuthSession>
|
||||
{
|
||||
typedef Socket<AuthSession> AuthSocket;
|
||||
|
||||
public:
|
||||
static std::unordered_map<uint8, AuthHandler> InitHandlers();
|
||||
|
||||
AuthSession(tcp::socket&& socket);
|
||||
AuthSession(IoContextTcpSocket&& socket);
|
||||
|
||||
void Start() override;
|
||||
bool Update() override;
|
||||
bool Update() final;
|
||||
|
||||
void SendPacket(ByteBuffer& packet);
|
||||
|
||||
protected:
|
||||
void ReadHandler() override;
|
||||
SocketReadCallbackResult ReadHandler() final;
|
||||
|
||||
private:
|
||||
bool HandleLogonChallenge();
|
||||
|
||||
@@ -54,9 +54,9 @@ protected:
|
||||
return threads;
|
||||
}
|
||||
|
||||
static void OnSocketAccept(tcp::socket&& sock, uint32 threadIndex)
|
||||
static void OnSocketAccept(IoContextTcpSocket&& sock, uint32 threadIndex)
|
||||
{
|
||||
Instance().OnSocketOpen(std::forward<tcp::socket>(sock), threadIndex);
|
||||
Instance().OnSocketOpen(std::move(sock), threadIndex);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -18,18 +18,16 @@
|
||||
#ifndef __RASESSION_H__
|
||||
#define __RASESSION_H__
|
||||
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include "Socket.h"
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <future>
|
||||
|
||||
using boost::asio::ip::tcp;
|
||||
|
||||
const std::size_t bufferSize = 4096;
|
||||
|
||||
class RASession : public std::enable_shared_from_this<RASession>
|
||||
{
|
||||
public:
|
||||
RASession(tcp::socket&& socket) :
|
||||
RASession(IoContextTcpSocket&& socket) :
|
||||
_socket(std::move(socket)), _commandExecuting(nullptr) { }
|
||||
|
||||
void Start();
|
||||
@@ -47,7 +45,7 @@ private:
|
||||
static void CommandPrint(void* callbackArg, std::string_view text);
|
||||
static void CommandFinished(void* callbackArg, bool);
|
||||
|
||||
tcp::socket _socket;
|
||||
IoContextTcpSocket _socket;
|
||||
boost::asio::streambuf _readBuffer;
|
||||
boost::asio::streambuf _writeBuffer;
|
||||
std::promise<void>* _commandExecuting;
|
||||
|
||||
@@ -3296,6 +3296,19 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
target->ToUnit()->SetAnimTier(AnimTier(e.action.animTier.animTier));
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_SET_GOSSIP_MENU:
|
||||
{
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
if (Creature* creature = target->ToCreature())
|
||||
{
|
||||
creature->SetGossipMenuId(e.action.setGossipMenu.gossipMenuId);
|
||||
LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: SMART_ACTION_SET_GOSSIP_MENU: Creature {} set gossip menu to {}",
|
||||
creature->GetGUID().ToString(), e.action.setGossipMenu.gossipMenuId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||
break;
|
||||
|
||||
@@ -885,6 +885,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
||||
case SMART_ACTION_WORLD_SCRIPT: return sizeof(SmartAction::worldStateScript);
|
||||
case SMART_ACTION_DISABLE_REWARD: return sizeof(SmartAction::reward);
|
||||
case SMART_ACTION_SET_ANIM_TIER: return sizeof(SmartAction::animTier);
|
||||
case SMART_ACTION_SET_GOSSIP_MENU: return sizeof(SmartAction::setGossipMenu);
|
||||
case SMART_ACTION_DISMOUNT: return NO_PARAMS;
|
||||
default:
|
||||
LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.",
|
||||
@@ -2040,6 +2041,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_ACTION_MOVEMENT_PAUSE:
|
||||
case SMART_ACTION_MOVEMENT_RESUME:
|
||||
case SMART_ACTION_WORLD_SCRIPT:
|
||||
case SMART_ACTION_SET_GOSSIP_MENU:
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type({}), event_type({}), Entry {} SourceType {} Event {}, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
|
||||
|
||||
@@ -724,8 +724,9 @@ enum SMART_ACTION
|
||||
SMART_ACTION_WORLD_SCRIPT = 237, // eventId, param
|
||||
SMART_ACTION_DISABLE_REWARD = 238, // reputation 0/1, loot 0/1
|
||||
SMART_ACTION_SET_ANIM_TIER = 239, // animtier
|
||||
SMART_ACTION_SET_GOSSIP_MENU = 240, // gossipMenuId
|
||||
|
||||
SMART_ACTION_AC_END = 240, // placeholder
|
||||
SMART_ACTION_AC_END = 241, // placeholder
|
||||
};
|
||||
|
||||
enum class SmartActionSummonCreatureFlags
|
||||
@@ -1510,6 +1511,11 @@ struct SmartAction
|
||||
{
|
||||
uint32 animTier;
|
||||
} animTier;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 gossipMenuId;
|
||||
} setGossipMenu;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ BattlegroundSA::BattlegroundSA()
|
||||
EndRoundTimer = 0s;
|
||||
ShipsStarted = false;
|
||||
Status = BG_SA_NOTSTARTED;
|
||||
_nextShipIsEast = true;
|
||||
|
||||
for (uint8 i = 0; i < 6; i++)
|
||||
GateStatus[i] = BG_SA_GATE_OK;
|
||||
@@ -85,6 +86,7 @@ void BattlegroundSA::Init()
|
||||
_notEvenAScratch[TEAM_HORDE] = true;
|
||||
Status = BG_SA_WARMUP;
|
||||
_relicClicked = false;
|
||||
_nextShipIsEast = true;
|
||||
}
|
||||
|
||||
bool BattlegroundSA::SetupBattleground()
|
||||
@@ -181,6 +183,7 @@ bool BattlegroundSA::ResetObjs()
|
||||
|
||||
TotalTime = 0s;
|
||||
ShipsStarted = false;
|
||||
_nextShipIsEast = true;
|
||||
|
||||
//Graveyards!
|
||||
for (uint8 i = 0; i < BG_SA_MAX_GY; i++)
|
||||
@@ -574,10 +577,12 @@ void BattlegroundSA::TeleportToEntrancePosition(Player* player)
|
||||
if (!ShipsStarted)
|
||||
{
|
||||
player->CastSpell(player, 12438, true);//Without this player falls before boat loads...
|
||||
if (urand(0, 1))
|
||||
if (_nextShipIsEast)
|
||||
player->TeleportTo(MAP_STRAND_OF_THE_ANCIENTS, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
|
||||
else
|
||||
player->TeleportTo(MAP_STRAND_OF_THE_ANCIENTS, 2577.003f, 980.261f, 15.0f, 0.807f, 0);
|
||||
|
||||
_nextShipIsEast = !_nextShipIsEast;
|
||||
}
|
||||
else
|
||||
player->TeleportTo(MAP_STRAND_OF_THE_ANCIENTS, 1600.381f, -106.263f, 8.8745f, 3.78f, 0);
|
||||
|
||||
@@ -620,5 +620,7 @@ private:
|
||||
|
||||
// Achievement: Not Even a Scratch
|
||||
bool _notEvenAScratch[PVP_TEAMS_COUNT];
|
||||
/// Toggle for alternating player spawns between East and West ships (true = first/East ship, false = second/West ship)
|
||||
bool _nextShipIsEast;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -328,7 +328,7 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
|
||||
Unit* cvUnit = currentVictim->getTarget();
|
||||
if (!attacker->CanCreatureAttack(cvUnit)) // pussywizard: if currentVictim is not valid => don't compare the threat with it, just take the highest threat valid target
|
||||
currentVictim = nullptr;
|
||||
else if (cvUnit->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || cvUnit->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE) || cvUnit->HasUnitState(UNIT_STATE_CONFUSED)) // pussywizard: no 10%/30% if currentVictim is immune to damage or has auras breakable by damage
|
||||
else if (!IsPreferredTarget(attacker, cvUnit)) // pussywizard: no 10%/30% if currentVictim is immune to damage or has auras breakable by damage
|
||||
currentVictim = nullptr;
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
|
||||
|
||||
// pussywizard: don't go to threat comparison if this ref is immune to damage or has aura breakable on damage (second choice target)
|
||||
// pussywizard: if this is the last entry on the threat list, then all targets are second choice, set bool to true and loop threat list again, ignoring this section
|
||||
if (!noPriorityTargetFound && (target->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || target->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE) || target->HasUnitState(UNIT_STATE_CONFUSED) || target->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, attacker->GetGUID())))
|
||||
if (!noPriorityTargetFound && !IsPreferredTarget(attacker, target))
|
||||
{
|
||||
if (iter != lastRef)
|
||||
{
|
||||
@@ -394,6 +394,8 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
|
||||
}
|
||||
else // pussywizard: no currentVictim, first passing all checks is chosen (highest threat, list is sorted)
|
||||
{
|
||||
// tie-breaker if multiple targets have the same threat: select closest target
|
||||
currentRef = SelectNextVictimTieBreaker(attacker, iter, noPriorityTargetFound);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -406,6 +408,69 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
|
||||
return currentRef;
|
||||
}
|
||||
|
||||
// Helper for Tie-breakers
|
||||
HostileReference* ThreatContainer::SelectNextVictimTieBreaker(Creature* attacker, ThreatContainer::StorageType::const_iterator currentIter, bool noPriorityTargetFound) const
|
||||
{
|
||||
HostileReference* bestRef = *currentIter;
|
||||
float bestThreat = bestRef->GetThreat();
|
||||
float shortestDistSq = attacker->GetExactDistSq(bestRef->getTarget());
|
||||
|
||||
auto tieIter = std::next(currentIter);
|
||||
|
||||
while (tieIter != iThreatList.end())
|
||||
{
|
||||
HostileReference* nextRef = *tieIter;
|
||||
|
||||
if (!nextRef)
|
||||
{
|
||||
++tieIter;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Threatlist is sorted, so we can stop as soon as we find a lower threat
|
||||
if (bestThreat - nextRef->GetThreat() > 0.01f)
|
||||
break;
|
||||
|
||||
Unit* target = nextRef->getTarget();
|
||||
|
||||
if (!target)
|
||||
{
|
||||
++tieIter;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (attacker->CanCreatureAttack(target) && (noPriorityTargetFound || IsPreferredTarget(attacker, target)))
|
||||
{
|
||||
float distSq = attacker->GetExactDistSq(target);
|
||||
if (distSq < shortestDistSq)
|
||||
{
|
||||
bestRef = nextRef;
|
||||
shortestDistSq = distSq;
|
||||
}
|
||||
}
|
||||
++tieIter;
|
||||
}
|
||||
return bestRef;
|
||||
}
|
||||
|
||||
// Helper for checking if a target is preferred (not immune, not confused, etc)
|
||||
bool ThreatContainer::IsPreferredTarget(Creature* attacker, Unit* target) const
|
||||
{
|
||||
if (target->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()))
|
||||
return false;
|
||||
|
||||
if (target->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE))
|
||||
return false;
|
||||
|
||||
if (target->HasUnitState(UNIT_STATE_CONFUSED))
|
||||
return false;
|
||||
|
||||
if (target->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, attacker->GetGUID()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================
|
||||
//=================== ThreatMgr ==========================
|
||||
//============================================================
|
||||
|
||||
@@ -156,6 +156,10 @@ public:
|
||||
|
||||
HostileReference* SelectNextVictim(Creature* attacker, HostileReference* currentVictim) const;
|
||||
|
||||
HostileReference* SelectNextVictimTieBreaker(Creature* attacker, ThreatContainer::StorageType::const_iterator currentIter, bool noPriorityTargetFound) const;
|
||||
|
||||
bool IsPreferredTarget(Creature* attacker, Unit* target) const;
|
||||
|
||||
void setDirty(bool isDirty) { iDirty = isDirty; }
|
||||
|
||||
[[nodiscard]] bool isDirty() const { return iDirty; }
|
||||
|
||||
@@ -542,13 +542,13 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
|
||||
condMeets = object->GetMap()->GetDifficulty() == ConditionValue1;
|
||||
break;
|
||||
}
|
||||
case CONDITION_RANDOM_DUNGEON:
|
||||
case CONDITION_PLAYER_QUEUED_RANDOM_DUNGEON:
|
||||
{
|
||||
if (Unit* unit = object->ToUnit())
|
||||
{
|
||||
if (Player* player = unit->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||
if (Player* player = unit->ToPlayer())
|
||||
{
|
||||
if (sLFGMgr->selectedRandomLfgDungeon(player->GetGUID()))
|
||||
if (sLFGMgr->IsPlayerQueuedForRandomDungeon(player->GetGUID()))
|
||||
{
|
||||
if (!ConditionValue1)
|
||||
condMeets = true;
|
||||
@@ -803,7 +803,7 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
|
||||
case CONDITION_CHARMED:
|
||||
mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
|
||||
break;
|
||||
case CONDITION_RANDOM_DUNGEON:
|
||||
case CONDITION_PLAYER_QUEUED_RANDOM_DUNGEON:
|
||||
mask |= GRID_MAP_TYPE_MASK_PLAYER;
|
||||
break;
|
||||
case CONDITION_WORLD_SCRIPT:
|
||||
@@ -2486,7 +2486,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case CONDITION_RANDOM_DUNGEON:
|
||||
case CONDITION_PLAYER_QUEUED_RANDOM_DUNGEON:
|
||||
if (cond->ConditionValue1 > 1)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "RandomDungeon condition has useless data in value1 ({}).", cond->ConditionValue1);
|
||||
|
||||
@@ -88,7 +88,7 @@ enum ConditionTypes
|
||||
CONDITION_HAS_AURA_TYPE = 102, // aura_type 0 0 true if has aura type
|
||||
CONDITION_WORLD_SCRIPT = 103, // conditionId state 0 true if WorldState::IsConditionFulfilled returns true
|
||||
CONDITION_AI_DATA = 104, // dataId value 0 true if AI::GetData returns value
|
||||
CONDITION_RANDOM_DUNGEON = 105, // difficulty (0 = any) 0 0 true if player is queued for a random dungeon via RDF (param1 = Difficulty)
|
||||
CONDITION_PLAYER_QUEUED_RANDOM_DUNGEON = 105, // checkDifficulty difficulty 0 true if player is queued for a random dungeon via RDF
|
||||
|
||||
CONDITION_AC_END = 106 // placeholder
|
||||
};
|
||||
|
||||
@@ -139,4 +139,13 @@ namespace lfg
|
||||
return m_KicksLeft;
|
||||
}
|
||||
|
||||
void LfgGroupData::AddRandomQueuedPlayer(ObjectGuid guid)
|
||||
{
|
||||
m_RandomQueuedPlayers.insert(guid);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool LfgGroupData::IsRandomQueuedPlayer(ObjectGuid guid) const
|
||||
{
|
||||
return m_RandomQueuedPlayers.contains(guid);
|
||||
}
|
||||
} // namespace lfg
|
||||
|
||||
@@ -37,6 +37,8 @@ namespace lfg
|
||||
void SetState(LfgState state);
|
||||
void RestoreState();
|
||||
void AddPlayer(ObjectGuid guid);
|
||||
void AddRandomQueuedPlayer(ObjectGuid guid);
|
||||
[[nodiscard]] bool IsRandomQueuedPlayer(ObjectGuid guid) const;
|
||||
uint8 RemovePlayer(ObjectGuid guid);
|
||||
void RemoveAllPlayers();
|
||||
void SetLeader(ObjectGuid guid);
|
||||
@@ -66,6 +68,7 @@ namespace lfg
|
||||
LfgState m_OldState; ///< Old State
|
||||
ObjectGuid m_Leader; ///< Leader GUID
|
||||
LfgGuidSet m_Players; ///< Players in group
|
||||
LfgGuidSet m_RandomQueuedPlayers; ///< Players that queued for random dungeon
|
||||
// Dungeon
|
||||
uint32 m_Dungeon; ///< Dungeon entry
|
||||
bool _isLFGGroup;
|
||||
|
||||
@@ -2583,6 +2583,18 @@ namespace lfg
|
||||
GroupsStore[gguid].AddPlayer(guid);
|
||||
}
|
||||
|
||||
void LFGMgr::AddPlayerQueuedForRandomDungeonToGroup(ObjectGuid gguid, ObjectGuid guid)
|
||||
{
|
||||
const LfgDungeonSet& dungeons = GetSelectedDungeons(guid);
|
||||
if (dungeons.empty())
|
||||
return;
|
||||
|
||||
uint32 dungeonId = *dungeons.begin();
|
||||
LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId);
|
||||
if (dungeon && (dungeon->type == LFG_TYPE_RANDOM))
|
||||
GroupsStore[gguid].AddRandomQueuedPlayer(guid);
|
||||
}
|
||||
|
||||
void LFGMgr::SetLeader(ObjectGuid gguid, ObjectGuid leader)
|
||||
{
|
||||
GroupsStore[gguid].SetLeader(leader);
|
||||
@@ -2839,4 +2851,12 @@ namespace lfg
|
||||
sDisableMgr->IsDisabledFor(DISABLE_TYPE_LFG_MAP, mapId, nullptr);
|
||||
}
|
||||
|
||||
bool LFGMgr::IsPlayerQueuedForRandomDungeon(ObjectGuid guid)
|
||||
{
|
||||
auto gguid = GetGroup(guid);
|
||||
if (!gguid)
|
||||
return false;
|
||||
|
||||
return GroupsStore[gguid].IsRandomQueuedPlayer(guid);
|
||||
}
|
||||
} // namespace lfg
|
||||
|
||||
@@ -506,6 +506,9 @@ namespace lfg
|
||||
uint8 RemovePlayerFromGroup(ObjectGuid gguid, ObjectGuid guid);
|
||||
/// Adds player to group
|
||||
void AddPlayerToGroup(ObjectGuid gguid, ObjectGuid guid);
|
||||
/// Store player that selected random queue to group
|
||||
void AddPlayerQueuedForRandomDungeonToGroup(ObjectGuid gguid, ObjectGuid guid);
|
||||
bool IsPlayerQueuedForRandomDungeon(ObjectGuid guid);
|
||||
/// Xinef: Set Random Players Count
|
||||
void SetRandomPlayersCount(ObjectGuid guid, uint8 count);
|
||||
/// Xinef: Get Random Players Count
|
||||
|
||||
@@ -187,6 +187,7 @@ namespace lfg
|
||||
|
||||
sLFGMgr->SetGroup(guid, gguid);
|
||||
sLFGMgr->AddPlayerToGroup(gguid, guid);
|
||||
sLFGMgr->AddPlayerQueuedForRandomDungeonToGroup(gguid, guid);
|
||||
|
||||
// pussywizard: after all necessary actions handle raid browser
|
||||
if (sLFGMgr->GetState(guid) == LFG_STATE_RAIDBROWSER)
|
||||
|
||||
@@ -265,7 +265,7 @@ Creature::Creature(): Unit(), MovableMapObject(), m_groupLootTimer(0), lootingGr
|
||||
m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_wanderDistance(0.0f), m_boundaryCheckTime(2500),
|
||||
m_transportCheckTimer(1000), lootPickPocketRestoreTime(0), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE),
|
||||
m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_alreadyCallForHelp(false), m_AlreadyCallAssistance(false),
|
||||
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_regenPower(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false),
|
||||
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_regenPower(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), _gossipMenuId(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false),
|
||||
m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f),_sparringPct(0.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_lastLeashExtensionTime(nullptr), m_cannotReachTimer(0),
|
||||
_isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0), _playerDamageReq(0), _damagedByPlayer(false), _isCombatMovementAllowed(true)
|
||||
{
|
||||
|
||||
@@ -204,6 +204,8 @@ public:
|
||||
|
||||
[[nodiscard]] CreatureTemplate const* GetCreatureTemplate() const { return m_creatureInfo; }
|
||||
[[nodiscard]] CreatureData const* GetCreatureData() const { return m_creatureData; }
|
||||
[[nodiscard]] uint32 GetGossipMenuId() const { return _gossipMenuId ? _gossipMenuId : GetCreatureTemplate()->GossipMenuId; }
|
||||
void SetGossipMenuId(uint32 gossipMenuId) { _gossipMenuId = gossipMenuId; }
|
||||
void SetDetectionDistance(float dist){ m_detectionDistance = dist; }
|
||||
[[nodiscard]] CreatureAddon const* GetCreatureAddon() const;
|
||||
|
||||
@@ -478,6 +480,7 @@ protected:
|
||||
|
||||
SpellSchoolMask m_meleeDamageSchoolMask;
|
||||
uint32 m_originalEntry;
|
||||
uint32 _gossipMenuId;
|
||||
|
||||
bool m_moveInLineOfSightDisabled;
|
||||
bool m_moveInLineOfSightStrictlyDisabled;
|
||||
|
||||
@@ -1642,12 +1642,9 @@ void Player::ProcessDelayedOperations()
|
||||
if (m_DelayedOperations & DELAYED_SAVE_PLAYER)
|
||||
SaveToDB(false, false);
|
||||
|
||||
if (m_DelayedOperations & DELAYED_SPELL_CAST_DESERTER)
|
||||
{
|
||||
Aura* aura = GetAura(26013);
|
||||
if (!aura || aura->GetDuration() <= 900000)
|
||||
if ((m_DelayedOperations & DELAYED_SPELL_CAST_DESERTER)
|
||||
&& !GetAura(26013))
|
||||
CastSpell(this, 26013, true);
|
||||
}
|
||||
|
||||
if (m_DelayedOperations & DELAYED_BG_MOUNT_RESTORE)
|
||||
{
|
||||
@@ -14378,7 +14375,7 @@ bool Player::CanSeeVendor(Creature const* creature) const
|
||||
if (!sConditionMgr->IsObjectMeetToConditions(const_cast<Player*>(this), const_cast<Creature*>(creature), conditions))
|
||||
return false;
|
||||
|
||||
uint32 const menuId = creature->GetCreatureTemplate()->GossipMenuId;
|
||||
uint32 const menuId = creature->GetGossipMenuId();
|
||||
if (!AnyVendorOptionAvailable(menuId, creature))
|
||||
return false;
|
||||
|
||||
|
||||
@@ -429,7 +429,7 @@ uint32 Player::GetDefaultGossipMenuForSource(WorldObject* source)
|
||||
switch (source->GetTypeId())
|
||||
{
|
||||
case TYPEID_UNIT:
|
||||
return source->ToCreature()->GetCreatureTemplate()->GossipMenuId;
|
||||
return source->ToCreature()->GetGossipMenuId();
|
||||
case TYPEID_GAMEOBJECT:
|
||||
return source->ToGameObject()->GetGOInfo()->GetGossipMenuId();
|
||||
default:
|
||||
|
||||
@@ -2148,7 +2148,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit const* attacker, Unit const* victim, co
|
||||
|
||||
float Unit::GetEffectiveResistChance(Unit const* owner, SpellSchoolMask schoolMask, Unit const* victim)
|
||||
{
|
||||
float victimResistance = float(victim->GetResistance(schoolMask));
|
||||
float victimResistance = static_cast<float>(victim->GetResistance(schoolMask));
|
||||
if (owner)
|
||||
{
|
||||
// Xinef: pets inherit 100% of masters penetration
|
||||
@@ -2156,28 +2156,28 @@ float Unit::GetEffectiveResistChance(Unit const* owner, SpellSchoolMask schoolMa
|
||||
Player const* player = owner->GetSpellModOwner();
|
||||
if (player && owner->GetEntry() != WORLD_TRIGGER)
|
||||
{
|
||||
victimResistance += float(player->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
|
||||
victimResistance -= float(player->GetSpellPenetrationItemMod());
|
||||
victimResistance += static_cast<float>(player->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
|
||||
victimResistance -= static_cast<float>(player->GetSpellPenetrationItemMod());
|
||||
}
|
||||
else
|
||||
victimResistance += float(owner->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
|
||||
victimResistance += static_cast<float>(owner->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
|
||||
}
|
||||
|
||||
victimResistance = std::max(victimResistance, 0.0f);
|
||||
if (owner)
|
||||
victimResistance += std::max((float(victim->GetLevel()) - float(owner->GetLevel())) * 5.0f, 0.0f);
|
||||
victimResistance += std::max(static_cast<float>(victim->GetLevel() - owner->GetLevel()) * 5.0f, 0.0f);
|
||||
|
||||
static uint32 const BOSS_LEVEL = 83;
|
||||
static float const BOSS_RESISTANCE_CONSTANT = 510.0f;
|
||||
uint32 level = victim->GetLevel();
|
||||
float level = static_cast<float>(victim->GetLevel());
|
||||
float resistanceConstant = 0.0f;
|
||||
|
||||
if (level == BOSS_LEVEL)
|
||||
resistanceConstant = BOSS_RESISTANCE_CONSTANT;
|
||||
if (level > 60.0f)
|
||||
resistanceConstant = 150.0f + (level - 60.0f) * (level - 67.5f);
|
||||
else if (level > 20.0f)
|
||||
resistanceConstant = 50.0f + (level - 20.0f) * 2.5f;
|
||||
else
|
||||
resistanceConstant = level * 5.0f;
|
||||
resistanceConstant = 50.0f;
|
||||
|
||||
return victimResistance / (victimResistance + resistanceConstant);
|
||||
return std::min(victimResistance / (victimResistance + resistanceConstant), 0.75f);
|
||||
}
|
||||
|
||||
void Unit::CalcAbsorbResist(DamageInfo& dmgInfo, bool Splited)
|
||||
|
||||
@@ -602,7 +602,10 @@ void WorldSession::HandleSellItemOpcode(WorldPackets::Item::SellItem& packet)
|
||||
if (pItem)
|
||||
{
|
||||
if (!sScriptMgr->OnPlayerCanSellItem(_player, pItem, creature))
|
||||
{
|
||||
_player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGuid, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// prevent sell not owner item
|
||||
if (_player->GetGUID() != pItem->GetOwnerGUID())
|
||||
|
||||
@@ -179,7 +179,7 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket& recvData)
|
||||
if (!sScriptMgr->OnGossipHello(_player, unit))
|
||||
{
|
||||
// _player->TalkedToCreature(unit->GetEntry(), unit->GetGUID());
|
||||
_player->PrepareGossipMenu(unit, unit->GetCreatureTemplate()->GossipMenuId, true);
|
||||
_player->PrepareGossipMenu(unit, unit->GetGossipMenuId(), true);
|
||||
_player->SendPreparedGossip(unit);
|
||||
}
|
||||
unit->AI()->sGossipHello(_player);
|
||||
|
||||
@@ -101,7 +101,7 @@ void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket& recvData)
|
||||
if (sScriptMgr->OnGossipHello(_player, creature))
|
||||
return;
|
||||
|
||||
_player->PrepareGossipMenu(creature, creature->GetCreatureTemplate()->GossipMenuId, true);
|
||||
_player->PrepareGossipMenu(creature, creature->GetGossipMenuId(), true);
|
||||
_player->SendPreparedGossip(creature);
|
||||
|
||||
creature->AI()->sGossipHello(_player);
|
||||
|
||||
@@ -436,7 +436,7 @@ static Optional<float> GetVelocity(Unit* owner, Unit* target, G3D::Vector3 const
|
||||
(owner->IsPet() || owner->IsGuardian() || owner->GetGUID() == target->GetCritterGUID() || owner->GetCharmerOrOwnerGUID() == target->GetGUID()))
|
||||
{
|
||||
uint32 moveFlags = target->GetUnitMovementFlags();
|
||||
if (target->movespline->isWalking())
|
||||
if (target->IsWalking())
|
||||
{
|
||||
moveFlags |= MOVEMENTFLAG_WALKING;
|
||||
}
|
||||
@@ -635,7 +635,7 @@ bool FollowMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
||||
Movement::MoveSplineInit init(owner);
|
||||
init.MovebyPath(i_path->GetPath());
|
||||
if (_inheritWalkState)
|
||||
init.SetWalk(target->IsWalking() || target->movespline->isWalking());
|
||||
init.SetWalk(target->IsWalking());
|
||||
|
||||
if (_inheritSpeed)
|
||||
if (Optional<float> velocity = GetVelocity(owner, target, i_path->GetActualEndPosition(), owner->IsGuardian()))
|
||||
|
||||
@@ -116,7 +116,6 @@ namespace Movement
|
||||
[[nodiscard]] bool Finalized() const { return splineflags.done; }
|
||||
[[nodiscard]] bool isCyclic() const { return splineflags.cyclic; }
|
||||
[[nodiscard]] bool isFalling() const { return splineflags.falling; }
|
||||
[[nodiscard]] bool isWalking() const { return splineflags.walkmode; }
|
||||
[[nodiscard]] bool isBoarding() const { return splineflags.transportEnter || splineflags.transportExit; }
|
||||
[[nodiscard]] Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3(); }
|
||||
[[nodiscard]] Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx + 1) : Vector3(); }
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Movement
|
||||
Falling = 0x00000200, // Affects elevation computation, can't be combined with Parabolic flag
|
||||
No_Spline = 0x00000400,
|
||||
Parabolic = 0x00000800, // Affects elevation computation, can't be combined with Falling flag
|
||||
Walkmode = 0x00001000,
|
||||
CanSwim = 0x00001000,
|
||||
Flying = 0x00002000, // Smooth movement(Catmullrom interpolation mode), flying animation
|
||||
OrientationFixed = 0x00004000, // Model orientation fixed
|
||||
Final_Point = 0x00008000,
|
||||
@@ -117,7 +117,7 @@ namespace Movement
|
||||
bool falling : 1;
|
||||
bool no_spline : 1;
|
||||
bool parabolic : 1;
|
||||
bool walkmode : 1;
|
||||
bool canSwim : 1;
|
||||
bool flying : 1;
|
||||
bool orientationFixed : 1;
|
||||
bool final_point : 1;
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace Movement
|
||||
// If spline is initialized with SetWalk method it only means we need to select
|
||||
// walk move speed for it but not add walk flag to unit
|
||||
uint32 moveFlagsForSpeed = moveFlags;
|
||||
if (args.flags.walkmode)
|
||||
if (args.walk)
|
||||
moveFlagsForSpeed |= MOVEMENTFLAG_WALKING;
|
||||
else
|
||||
moveFlagsForSpeed &= ~MOVEMENTFLAG_WALKING;
|
||||
@@ -199,7 +199,7 @@ namespace Movement
|
||||
args.splineId = splineIdGen.NewId();
|
||||
args.TransformForTransport = unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID();
|
||||
// mix existing state into new
|
||||
args.flags.walkmode = unit->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
args.walk = unit->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
args.flags.flying = unit->m_movementInfo.HasMovementFlag((MovementFlags)(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY));
|
||||
}
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace Movement
|
||||
};
|
||||
|
||||
inline void MoveSplineInit::SetFly() { args.flags.EnableFlying(); }
|
||||
inline void MoveSplineInit::SetWalk(bool enable) { args.flags.walkmode = enable; }
|
||||
inline void MoveSplineInit::SetWalk(bool enable) { args.walk = enable; }
|
||||
inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom(); }
|
||||
inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true; }
|
||||
inline void MoveSplineInit::SetFall() { args.flags.EnableFalling(); }
|
||||
|
||||
@@ -59,6 +59,7 @@ namespace Movement
|
||||
float initialOrientation{0.f};
|
||||
bool HasVelocity{false};
|
||||
bool TransformForTransport{true};
|
||||
bool walk;
|
||||
|
||||
/** Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. */
|
||||
bool Validate(Unit* unit) const;
|
||||
|
||||
@@ -153,7 +153,7 @@ namespace Movement
|
||||
STR(Falling ), // 0x00000200, // Not Compartible With Trajectory Movement
|
||||
STR(No_Spline ), // 0x00000400,
|
||||
STR(Trajectory ), // 0x00000800, // Not Compartible With Fall Movement
|
||||
STR(Walkmode ), // 0x00001000,
|
||||
STR(CanSwim ), // 0x00001000,
|
||||
STR(Flying ), // 0x00002000, // Smooth Movement(Catmullrom Interpolation Mode), Flying Animation
|
||||
STR(Knockback ), // 0x00004000, // Model Orientation Fixed
|
||||
STR(Final_Point ), // 0x00008000,
|
||||
|
||||
@@ -29,14 +29,14 @@ void ScriptMgr::OnNetworkStop()
|
||||
CALL_ENABLED_HOOKS(ServerScript, SERVERHOOK_ON_NETWORK_STOP, script->OnNetworkStop());
|
||||
}
|
||||
|
||||
void ScriptMgr::OnSocketOpen(std::shared_ptr<WorldSocket> socket)
|
||||
void ScriptMgr::OnSocketOpen(std::shared_ptr<WorldSocket> const& socket)
|
||||
{
|
||||
ASSERT(socket);
|
||||
|
||||
CALL_ENABLED_HOOKS(ServerScript, SERVERHOOK_ON_SOCKET_OPEN, script->OnSocketOpen(socket));
|
||||
}
|
||||
|
||||
void ScriptMgr::OnSocketClose(std::shared_ptr<WorldSocket> socket)
|
||||
void ScriptMgr::OnSocketClose(std::shared_ptr<WorldSocket> const& socket)
|
||||
{
|
||||
ASSERT(socket);
|
||||
|
||||
|
||||
@@ -46,11 +46,11 @@ public:
|
||||
virtual void OnNetworkStop() { }
|
||||
|
||||
// Called when a remote socket establishes a connection to the server. Do not store the socket object.
|
||||
virtual void OnSocketOpen(std::shared_ptr<WorldSocket> /*socket*/) { }
|
||||
virtual void OnSocketOpen(std::shared_ptr<WorldSocket> const& /*socket*/) { }
|
||||
|
||||
// Called when a socket is closed. Do not store the socket object, and do not rely on the connection
|
||||
// being open; it is not.
|
||||
virtual void OnSocketClose(std::shared_ptr<WorldSocket> /*socket*/) { }
|
||||
virtual void OnSocketClose(std::shared_ptr<WorldSocket> const& /*socket*/) { }
|
||||
|
||||
/**
|
||||
* @brief This hook called when a packet is sent to a client. The packet object is a copy of the original packet, so reading and modifying it is safe.
|
||||
|
||||
@@ -174,8 +174,8 @@ public: /* SpellScriptLoader */
|
||||
public: /* ServerScript */
|
||||
void OnNetworkStart();
|
||||
void OnNetworkStop();
|
||||
void OnSocketOpen(std::shared_ptr<WorldSocket> socket);
|
||||
void OnSocketClose(std::shared_ptr<WorldSocket> socket);
|
||||
void OnSocketOpen(std::shared_ptr<WorldSocket> const& socket);
|
||||
void OnSocketClose(std::shared_ptr<WorldSocket> const& socket);
|
||||
bool CanPacketReceive(WorldSession* session, WorldPacket const& packet);
|
||||
void OnPacketReceived(WorldSession* session, WorldPacket const& packet);
|
||||
bool CanPacketSend(WorldSession* session, WorldPacket const& packet);
|
||||
|
||||
@@ -116,7 +116,7 @@ void EncryptableAndCompressiblePacket::CompressIfNeeded()
|
||||
SetOpcode(SMSG_COMPRESSED_UPDATE_OBJECT);
|
||||
}
|
||||
|
||||
WorldSocket::WorldSocket(tcp::socket&& socket)
|
||||
WorldSocket::WorldSocket(IoContextTcpSocket&& socket)
|
||||
: Socket(std::move(socket)), _OverSpeedPings(0), _worldSession(nullptr), _authed(false), _sendBufferSize(4096), _loggingPackets(false)
|
||||
{
|
||||
Acore::Crypto::GetRandomBytes(_authSeed);
|
||||
@@ -238,10 +238,10 @@ void WorldSocket::OnClose()
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSocket::ReadHandler()
|
||||
SocketReadCallbackResult WorldSocket::ReadHandler()
|
||||
{
|
||||
if (!IsOpen())
|
||||
return;
|
||||
return SocketReadCallbackResult::Stop;
|
||||
|
||||
MessageBuffer& packet = GetReadBuffer();
|
||||
while (packet.GetActiveSize() > 0)
|
||||
@@ -264,7 +264,7 @@ void WorldSocket::ReadHandler()
|
||||
if (!ReadHeaderHandler())
|
||||
{
|
||||
CloseSocket();
|
||||
return;
|
||||
return SocketReadCallbackResult::Stop;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,11 +295,11 @@ void WorldSocket::ReadHandler()
|
||||
CloseSocket();
|
||||
}
|
||||
|
||||
return;
|
||||
return SocketReadCallbackResult::Stop;
|
||||
}
|
||||
}
|
||||
|
||||
AsyncRead();
|
||||
return SocketReadCallbackResult::KeepReading;
|
||||
}
|
||||
|
||||
bool WorldSocket::ReadHeaderHandler()
|
||||
@@ -329,7 +329,7 @@ bool WorldSocket::ReadHeaderHandler()
|
||||
return true;
|
||||
}
|
||||
|
||||
struct AuthSession
|
||||
struct ClientAuthSession
|
||||
{
|
||||
uint32 BattlegroupID = 0;
|
||||
uint32 LoginServerType = 0;
|
||||
@@ -528,7 +528,7 @@ void WorldSocket::SendPacket(WorldPacket const& packet)
|
||||
|
||||
void WorldSocket::HandleAuthSession(WorldPacket & recvPacket)
|
||||
{
|
||||
std::shared_ptr<AuthSession> authSession = std::make_shared<AuthSession>();
|
||||
std::shared_ptr<ClientAuthSession> authSession = std::make_shared<ClientAuthSession>();
|
||||
|
||||
// Read the content of the packet
|
||||
recvPacket >> authSession->Build;
|
||||
@@ -552,7 +552,7 @@ void WorldSocket::HandleAuthSession(WorldPacket & recvPacket)
|
||||
_queryProcessor.AddCallback(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSession, PreparedQueryResult result)
|
||||
void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<ClientAuthSession> authSession, PreparedQueryResult result)
|
||||
{
|
||||
// Stop if the account is not found
|
||||
if (!result)
|
||||
|
||||
@@ -65,21 +65,21 @@ struct ClientPktHeader
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct AuthSession;
|
||||
struct ClientAuthSession;
|
||||
|
||||
class AC_GAME_API WorldSocket : public Socket<WorldSocket>
|
||||
class AC_GAME_API WorldSocket final : public Socket<WorldSocket>
|
||||
{
|
||||
typedef Socket<WorldSocket> BaseSocket;
|
||||
|
||||
public:
|
||||
WorldSocket(tcp::socket&& socket);
|
||||
WorldSocket(IoContextTcpSocket&& socket);
|
||||
~WorldSocket();
|
||||
|
||||
WorldSocket(WorldSocket const& right) = delete;
|
||||
WorldSocket& operator=(WorldSocket const& right) = delete;
|
||||
|
||||
void Start() override;
|
||||
bool Update() override;
|
||||
bool Update() final;
|
||||
|
||||
void SendPacket(WorldPacket const& packet);
|
||||
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
|
||||
protected:
|
||||
void OnClose() override;
|
||||
void ReadHandler() override;
|
||||
SocketReadCallbackResult ReadHandler() final;
|
||||
bool ReadHeaderHandler();
|
||||
|
||||
enum class ReadDataHandlerResult
|
||||
@@ -113,7 +113,7 @@ private:
|
||||
void SendPacketAndLogOpcode(WorldPacket const& packet);
|
||||
void HandleSendAuthSession();
|
||||
void HandleAuthSession(WorldPacket& recvPacket);
|
||||
void HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSession, PreparedQueryResult result);
|
||||
void HandleAuthSessionCallback(std::shared_ptr<ClientAuthSession> authSession, PreparedQueryResult result);
|
||||
void LoadSessionPermissionsCallback(PreparedQueryResult result);
|
||||
void SendAuthResponseError(uint8 code);
|
||||
|
||||
|
||||
@@ -25,13 +25,13 @@
|
||||
class WorldSocketThread : public NetworkThread<WorldSocket>
|
||||
{
|
||||
public:
|
||||
void SocketAdded(std::shared_ptr<WorldSocket> sock) override
|
||||
void SocketAdded(std::shared_ptr<WorldSocket> const& sock) override
|
||||
{
|
||||
sock->SetSendBufferSize(sWorldSocketMgr.GetApplicationSendBufferSize());
|
||||
sScriptMgr->OnSocketOpen(sock);
|
||||
}
|
||||
|
||||
void SocketRemoved(std::shared_ptr<WorldSocket> sock) override
|
||||
void SocketRemoved(std::shared_ptr<WorldSocket> const& sock) override
|
||||
{
|
||||
sScriptMgr->OnSocketClose(sock);
|
||||
}
|
||||
@@ -81,7 +81,7 @@ void WorldSocketMgr::StopNetwork()
|
||||
sScriptMgr->OnNetworkStop();
|
||||
}
|
||||
|
||||
void WorldSocketMgr::OnSocketOpen(tcp::socket&& sock, uint32 threadIndex)
|
||||
void WorldSocketMgr::OnSocketOpen(IoContextTcpSocket&& sock, uint32 threadIndex)
|
||||
{
|
||||
// set some options here
|
||||
if (_socketSystemSendBufferSize >= 0)
|
||||
@@ -109,7 +109,7 @@ void WorldSocketMgr::OnSocketOpen(tcp::socket&& sock, uint32 threadIndex)
|
||||
}
|
||||
}
|
||||
|
||||
BaseSocketMgr::OnSocketOpen(std::forward<tcp::socket>(sock), threadIndex);
|
||||
BaseSocketMgr::OnSocketOpen(std::move(sock), threadIndex);
|
||||
}
|
||||
|
||||
NetworkThread<WorldSocket>* WorldSocketMgr::CreateThreads() const
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
/// Stops all network threads, It will wait for all running threads .
|
||||
void StopNetwork() override;
|
||||
|
||||
void OnSocketOpen(tcp::socket&& sock, uint32 threadIndex) override;
|
||||
void OnSocketOpen(IoContextTcpSocket&& sock, uint32 threadIndex) override;
|
||||
|
||||
std::size_t GetApplicationSendBufferSize() const { return _socketApplicationSendBufferSize; }
|
||||
|
||||
@@ -50,9 +50,9 @@ protected:
|
||||
|
||||
NetworkThread<WorldSocket>* CreateThreads() const override;
|
||||
|
||||
static void OnSocketAccept(tcp::socket&& sock, uint32 threadIndex)
|
||||
static void OnSocketAccept(IoContextTcpSocket&& sock, uint32 threadIndex)
|
||||
{
|
||||
Instance().OnSocketOpen(std::forward<tcp::socket>(sock), threadIndex);
|
||||
Instance().OnSocketOpen(std::move(sock), threadIndex);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "Chat.h"
|
||||
#include "CommandScript.h"
|
||||
#include "GroupMgr.h"
|
||||
#include "Language.h"
|
||||
#include "Player.h"
|
||||
#include "SpellAuras.h"
|
||||
@@ -211,6 +212,16 @@ public:
|
||||
CharacterDatabase.Execute(stmt);
|
||||
}
|
||||
|
||||
if (isInstance)
|
||||
{
|
||||
if (ObjectGuid groupId = sCharacterCache->GetCharacterGroupGuidByGuid(guid))
|
||||
if (Group* group = sGroupMgr->GetGroupByGUID(groupId.GetCounter()))
|
||||
if (group->isLFGGroup())
|
||||
Player::RemoveFromGroup(group, guid);
|
||||
}
|
||||
else if (target && target->GetMap()->IsBattleground())
|
||||
target->LeaveBattleground();
|
||||
|
||||
handler->PSendSysMessage("{} of {} Deserter has been added to player {}.", secsToTimeString(duration), isInstance ? "Instance" : "Battleground", handler->playerLink(*playerName));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ struct boss_archimonde : public BossAI
|
||||
scheduler.CancelAll();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
DoCastAOE(SPELL_PROTECTION_OF_ELUNE, true);
|
||||
Talk(SAY_ENRAGE);
|
||||
Talk(SAY_DEATH);
|
||||
_enraged = true;
|
||||
me->GetMotionMaster()->Clear(false);
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
|
||||
@@ -172,7 +172,7 @@ struct boss_hadronox : public BossAI
|
||||
SummonCrusherPack(SUMMON_GROUP_CRUSHER_3);
|
||||
events.ScheduleEvent(EVENT_HADRONOX_MOVE1, 0s);
|
||||
events.ScheduleEvent(EVENT_HADRONOX_MOVE2, 45s);
|
||||
events.ScheduleEvent(EVENT_HADRONOX_MOVE3, 90s);
|
||||
events.ScheduleEvent(EVENT_HADRONOX_MOVE3, 70s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1137,7 +1137,7 @@ public:
|
||||
{
|
||||
me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
|
||||
Talk(SAY_LK_SUMMON_VALKYR);
|
||||
DoCastSelf(IsHeroic() ? SPELL_SUMMON_VALKYR_PERIODIC : SPELL_SUMMON_VALKYR);
|
||||
DoCastSelf(Is25ManRaid() ? SPELL_SUMMON_VALKYR_PERIODIC : SPELL_SUMMON_VALKYR);
|
||||
events.ScheduleEvent(EVENT_SUMMON_VALKYR, 45s, EVENT_GROUP_ABILITIES);
|
||||
|
||||
// schedule a defile (or reschedule it) if next defile event
|
||||
|
||||
@@ -44,10 +44,7 @@ enum Spells
|
||||
|
||||
enum Misc
|
||||
{
|
||||
ACHIEV_TIMED_START_EVENT = 9891,
|
||||
EVENT_SPAWN_CRYPT_GUARDS_1 = 0,
|
||||
EVENT_BERSERK = 1,
|
||||
EVENT_SPAWN_CRYPT_GUARDS_EXTRA = 2,
|
||||
ACHIEV_TIMED_START_EVENT = 9891
|
||||
};
|
||||
|
||||
Position const cryptguardPositions[] = {
|
||||
@@ -121,9 +118,10 @@ struct boss_anubrekhan : public BossAI
|
||||
SummonCryptGuards();
|
||||
if (!Is25ManRaid())
|
||||
{
|
||||
ScheduleUniqueTimedEvent(17500ms, [&] {
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
me->SummonCreature(NPC_CRYPT_GUARD, cryptguardPositions[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
|
||||
}, EVENT_SPAWN_CRYPT_GUARDS_1);
|
||||
}, 17500ms);
|
||||
}
|
||||
|
||||
ScheduleTimedEvent(15s, [&] {
|
||||
|
||||
@@ -255,7 +255,8 @@ class spell_gluth_decimate : public SpellScript
|
||||
Unit::DealDamage(GetCaster(), cTarget, damage);
|
||||
return;
|
||||
}
|
||||
GetCaster()->CastCustomSpell(SPELL_DECIMATE_DAMAGE, SPELLVALUE_BASE_POINT0, damage, unitTarget);
|
||||
|
||||
GetCaster()->CastSpell(unitTarget, SPELL_DECIMATE_DAMAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,8 +266,38 @@ class spell_gluth_decimate : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
// 28375 - Decimate
|
||||
class spell_gluth_decimate_damage : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_gluth_decimate_damage)
|
||||
|
||||
void RecalculateDamage()
|
||||
{
|
||||
Unit* target = GetHitUnit();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
int32 targetHealth = int32(target->GetHealth());
|
||||
int32 fivePctHealth = int32(target->CountPctFromMaxHealth(5));
|
||||
|
||||
// Damage needed to leave the target at exactly 5%
|
||||
int32 damage = targetHealth - fivePctHealth;
|
||||
|
||||
if (damage <= 0)
|
||||
damage = 0;
|
||||
|
||||
SetHitDamage(damage);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnHit += SpellHitFn(spell_gluth_decimate_damage::RecalculateDamage);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_gluth()
|
||||
{
|
||||
new boss_gluth();
|
||||
RegisterSpellScript(spell_gluth_decimate);
|
||||
RegisterSpellScript(spell_gluth_decimate_damage);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "CreatureScript.h"
|
||||
#include "InstanceMapScript.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "nexus.h"
|
||||
#include "Player.h"
|
||||
#include "Group.h"
|
||||
@@ -44,6 +45,8 @@ public:
|
||||
{
|
||||
instance_nexus_InstanceMapScript(Map* map) : InstanceScript(map) {}
|
||||
|
||||
GuidVector _frayerGUIDs;
|
||||
|
||||
void Initialize() override
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
@@ -80,6 +83,23 @@ public:
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_COMMANDER_KOLURG);
|
||||
break;
|
||||
case NPC_CRYSTALLINE_FRAYER:
|
||||
_frayerGUIDs.push_back(creature->GetGUID());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void KillAllFrayers()
|
||||
{
|
||||
for (ObjectGuid const& guid : _frayerGUIDs)
|
||||
{
|
||||
if (Creature* frayer = instance->GetCreature(guid))
|
||||
{
|
||||
frayer->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
frayer->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
|
||||
frayer->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
Unit::Kill(frayer, frayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +161,13 @@ public:
|
||||
if (!InstanceScript::SetBossState(id, state))
|
||||
return false;
|
||||
|
||||
if (state != DONE || id > DATA_ORMOROK_EVENT)
|
||||
if (state != DONE)
|
||||
return true;
|
||||
|
||||
if (id == DATA_ORMOROK_EVENT)
|
||||
KillAllFrayers();
|
||||
|
||||
if (id > DATA_ORMOROK_EVENT)
|
||||
return true;
|
||||
|
||||
BossInfo const* bossInfo = GetBossInfo(id + DATA_TELESTRA_ORB);
|
||||
@@ -156,9 +182,17 @@ enum eFrayer
|
||||
{
|
||||
SPELL_SUMMON_SEED_POD = 52796,
|
||||
SPELL_SEED_POD = 48082,
|
||||
SPELL_AURA_OF_REGENERATION = 52067,
|
||||
SPELL_AURA_OF_REGENERATION = 57056,
|
||||
SPELL_CRYSTAL_BLOOM = 48058,
|
||||
SPELL_ENSNARE = 48053
|
||||
SPELL_ENSNARE = 48053,
|
||||
|
||||
SAY_EMOTE = 0
|
||||
};
|
||||
|
||||
enum FrayerGroups
|
||||
{
|
||||
GROUP_COMBAT = 1,
|
||||
GROUP_SEED_POD = 2
|
||||
};
|
||||
|
||||
struct npc_crystalline_frayer : public ScriptedAI
|
||||
@@ -166,27 +200,44 @@ struct npc_crystalline_frayer : public ScriptedAI
|
||||
npc_crystalline_frayer(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool _allowDeath;
|
||||
uint32 restoreTimer;
|
||||
uint32 abilityTimer1;
|
||||
uint32 abilityTimer2;
|
||||
bool _inSeedPod;
|
||||
TaskScheduler _scheduler;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
restoreTimer = 0;
|
||||
abilityTimer1 = 0;
|
||||
abilityTimer2 = 30000;
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
_allowDeath = false;
|
||||
_inSeedPod = false;
|
||||
_scheduler.CancelAll();
|
||||
|
||||
me->RemoveAllAuras();
|
||||
me->SetObjectScale(1.0f);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
me->SetRegeneratingHealth(true);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->GetMotionMaster()->MoveRandom(10.0f);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit*) override
|
||||
{
|
||||
_allowDeath = me->GetInstanceScript()->GetBossState(DATA_ORMOROK_EVENT) == DONE;
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
_allowDeath = instance->GetBossState(DATA_ORMOROK_EVENT) == DONE;
|
||||
|
||||
_scheduler.Schedule(5s, GROUP_COMBAT, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_ENSNARE);
|
||||
context.Repeat(5s);
|
||||
}).Schedule(0s, GROUP_COMBAT, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_CRYSTAL_BLOOM);
|
||||
context.Repeat(30s);
|
||||
});
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (me->isRegeneratingHealth())
|
||||
if (!_inSeedPod)
|
||||
ScriptedAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
@@ -196,57 +247,67 @@ struct npc_crystalline_frayer : public ScriptedAI
|
||||
{
|
||||
if (!_allowDeath)
|
||||
{
|
||||
me->RemoveAllAuras();
|
||||
me->GetThreatMgr().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
damage = 0;
|
||||
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetRegeneratingHealth(false);
|
||||
me->CastSpell(me, SPELL_SUMMON_SEED_POD, true);
|
||||
me->CastSpell(me, SPELL_SEED_POD, true);
|
||||
me->CastSpell(me, SPELL_AURA_OF_REGENERATION, false);
|
||||
restoreTimer = 1;
|
||||
EnterSeedPod();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnterSeedPod()
|
||||
{
|
||||
_inSeedPod = true;
|
||||
_scheduler.CancelGroup(GROUP_COMBAT);
|
||||
|
||||
me->AttackStop();
|
||||
me->GetThreatMgr().ClearAllThreat();
|
||||
me->CombatStop(true);
|
||||
me->RemoveAllAuras();
|
||||
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
|
||||
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
me->SetRegeneratingHealth(false);
|
||||
me->SetObjectScale(0.6f);
|
||||
|
||||
DoCastSelf(SPELL_SEED_POD, true);
|
||||
DoCastSelf(SPELL_SUMMON_SEED_POD, true);
|
||||
DoCastSelf(SPELL_AURA_OF_REGENERATION, true);
|
||||
|
||||
_scheduler.Schedule(90s, GROUP_SEED_POD, [this](TaskContext /*context*/)
|
||||
{
|
||||
LeaveSeedPod();
|
||||
});
|
||||
}
|
||||
|
||||
void LeaveSeedPod()
|
||||
{
|
||||
_inSeedPod = false;
|
||||
|
||||
Talk(SAY_EMOTE);
|
||||
|
||||
me->RemoveAurasDueToSpell(SPELL_SEED_POD);
|
||||
me->RemoveAurasDueToSpell(SPELL_AURA_OF_REGENERATION);
|
||||
|
||||
me->SetObjectScale(1.0f);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
me->SetRegeneratingHealth(true);
|
||||
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->GetMotionMaster()->MoveRandom(10.0f);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (restoreTimer)
|
||||
{
|
||||
restoreTimer += diff;
|
||||
if (restoreTimer >= 90 * IN_MILLISECONDS)
|
||||
{
|
||||
Talk(0);
|
||||
me->SetRegeneratingHealth(true);
|
||||
restoreTimer = 0;
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (_inSeedPod)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
abilityTimer1 += diff;
|
||||
abilityTimer2 += diff;
|
||||
|
||||
if (abilityTimer1 >= 5000)
|
||||
{
|
||||
me->CastSpell(me->GetVictim(), SPELL_ENSNARE, false);
|
||||
abilityTimer1 = 0;
|
||||
}
|
||||
|
||||
if (abilityTimer2 >= 30000)
|
||||
{
|
||||
me->CastSpell(me->GetVictim(), SPELL_CRYSTAL_BLOOM, false);
|
||||
abilityTimer2 = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ enum Npcs
|
||||
|
||||
NPC_COMMANDER_STOUTBEARD = 26796,
|
||||
NPC_COMMANDER_KOLURG = 26798,
|
||||
NPC_CRYSTALLINE_FRAYER = 26793,
|
||||
|
||||
GO_TELESTRA_SPHERE = 188526,
|
||||
GO_ANOMALUS_SPHERE = 188527,
|
||||
|
||||
@@ -276,6 +276,7 @@ public:
|
||||
orb->RemoveAurasDueToSpell(SPELL_AWAKEN_SUBBOSS);
|
||||
|
||||
me->RemoveAurasDueToSpell(SPELL_FREEZE);
|
||||
me->GetThreatMgr().ResetAllThreat();
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetControlled(false, UNIT_STATE_STUNNED);
|
||||
// SETINCOMBATWITHZONE
|
||||
|
||||
@@ -610,150 +610,6 @@ private:
|
||||
BetrayalState _state;
|
||||
};
|
||||
|
||||
/*####
|
||||
## npc_drakuru_shackles
|
||||
####*/
|
||||
|
||||
enum DrakuruShackles
|
||||
{
|
||||
NPC_RAGECLAW = 29686,
|
||||
QUEST_TROLLS_IS_GONE_CRAZY = 12861,
|
||||
SPELL_LEFT_CHAIN = 59951,
|
||||
SPELL_RIGHT_CHAIN = 59952,
|
||||
SPELL_UNLOCK_SHACKLE = 55083,
|
||||
SPELL_FREE_RAGECLAW = 55223
|
||||
};
|
||||
|
||||
class npc_drakuru_shackles : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_drakuru_shackles() : CreatureScript("npc_drakuru_shackles") { }
|
||||
|
||||
struct npc_drakuru_shacklesAI : public NullCreatureAI
|
||||
{
|
||||
npc_drakuru_shacklesAI(Creature* creature) : NullCreatureAI(creature)
|
||||
{
|
||||
_rageclawGUID.Clear();
|
||||
timer = 0;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
timer += diff;
|
||||
if (timer >= 2000)
|
||||
{
|
||||
timer = 0;
|
||||
if (_rageclawGUID)
|
||||
return;
|
||||
|
||||
if (Creature* cr = me->FindNearestCreature(NPC_RAGECLAW, 10.0f))
|
||||
{
|
||||
_rageclawGUID = cr->GetGUID();
|
||||
LockRageclaw(cr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LockRageclaw(Creature* rageclaw)
|
||||
{
|
||||
// pointer check not needed
|
||||
me->SetFacingToObject(rageclaw);
|
||||
rageclaw->SetFacingToObject(me);
|
||||
|
||||
DoCast(rageclaw, SPELL_LEFT_CHAIN, true);
|
||||
DoCast(rageclaw, SPELL_RIGHT_CHAIN, true);
|
||||
}
|
||||
|
||||
void UnlockRageclaw(Unit* /*who*/, Creature* rageclaw)
|
||||
{
|
||||
// pointer check not needed
|
||||
DoCast(rageclaw, SPELL_FREE_RAGECLAW, true);
|
||||
_rageclawGUID.Clear();
|
||||
me->DespawnOrUnsummon(1ms);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* caster, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_UNLOCK_SHACKLE)
|
||||
{
|
||||
if (caster->ToPlayer()->GetQuestStatus(QUEST_TROLLS_IS_GONE_CRAZY) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
if (Creature* rageclaw = ObjectAccessor::GetCreature(*me, _rageclawGUID))
|
||||
{
|
||||
UnlockRageclaw(caster, rageclaw);
|
||||
caster->ToPlayer()->KilledMonster(rageclaw->GetCreatureTemplate(), _rageclawGUID);
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
else
|
||||
me->setDeathState(DeathState::JustDied);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _rageclawGUID;
|
||||
uint32 timer;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return new npc_drakuru_shacklesAI(creature);
|
||||
}
|
||||
};
|
||||
|
||||
/*####
|
||||
## npc_captured_rageclaw
|
||||
####*/
|
||||
|
||||
enum Rageclaw
|
||||
{
|
||||
SPELL_UNSHACKLED = 55085,
|
||||
SPELL_KNEEL = 39656,
|
||||
SAY_RAGECLAW = 0
|
||||
};
|
||||
|
||||
class npc_captured_rageclaw : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_captured_rageclaw() : CreatureScript("npc_captured_rageclaw") { }
|
||||
|
||||
struct npc_captured_rageclawAI : public NullCreatureAI
|
||||
{
|
||||
npc_captured_rageclawAI(Creature* creature) : NullCreatureAI(creature) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
DoCast(me, SPELL_KNEEL, true); // Little Hack for kneel - Thanks Illy :P
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_FREE_RAGECLAW)
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_LEFT_CHAIN);
|
||||
me->RemoveAurasDueToSpell(SPELL_RIGHT_CHAIN);
|
||||
me->RemoveAurasDueToSpell(SPELL_KNEEL);
|
||||
me->SetFaction(me->GetCreatureTemplate()->faction);
|
||||
DoCast(me, SPELL_UNSHACKLED, true);
|
||||
Talk(SAY_RAGECLAW);
|
||||
me->GetMotionMaster()->MoveRandom(10);
|
||||
me->DespawnOrUnsummon(10s);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return new npc_captured_rageclawAI(creature);
|
||||
}
|
||||
};
|
||||
|
||||
/*####
|
||||
## npc_released_offspring_harkoa
|
||||
####*/
|
||||
@@ -973,8 +829,6 @@ void AddSC_zuldrak()
|
||||
new npc_finklestein();
|
||||
new go_finklestein_cauldron();
|
||||
RegisterCreatureAI(npc_overlord_drakuru_betrayal);
|
||||
new npc_drakuru_shackles();
|
||||
new npc_captured_rageclaw();
|
||||
new npc_released_offspring_harkoa();
|
||||
new npc_crusade_recruit();
|
||||
new go_scourge_enclosure();
|
||||
|
||||
@@ -56,17 +56,20 @@ struct boss_talon_king_ikiss : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
_spoken = false;
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
ScheduleHealthCheckEvent({ 80, 50, 25 }, [&] {
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->AttackStop();
|
||||
DoCastAOE(SPELL_BLINK);
|
||||
DoCastSelf(SPELL_ARCANE_BUBBLE, true);
|
||||
Talk(EMOTE_ARCANE_EXP);
|
||||
scheduler.Schedule(1s, [this](TaskContext /*context*/)
|
||||
{
|
||||
DoCastAOE(SPELL_ARCANE_EXPLOSION);
|
||||
}).Schedule(6500ms, [this](TaskContext /*context*/)
|
||||
}).Schedule(7s, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->GetThreatMgr().ResetAllThreat();
|
||||
});
|
||||
});
|
||||
@@ -160,7 +163,7 @@ class spell_talon_king_ikiss_blink : public SpellScript
|
||||
void HandleDummyHitTarget(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
GetHitUnit()->CastSpell(GetCaster(), SPELL_BLINK_TELEPORT, true);
|
||||
GetCaster()->CastSpell(GetHitUnit(), SPELL_BLINK_TELEPORT, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
||||
@@ -90,7 +90,7 @@ struct boss_pathaleon_the_calculator : public BossAI
|
||||
me->LoadEquipment(EQUIPMENT_FRENZY);
|
||||
});
|
||||
|
||||
scheduler.Schedule(20s, 25s, [this](TaskContext context)
|
||||
scheduler.Schedule(10s, 16s, [this](TaskContext context)
|
||||
{
|
||||
if (!_isEnraged)
|
||||
{
|
||||
@@ -113,7 +113,7 @@ struct boss_pathaleon_the_calculator : public BossAI
|
||||
me->ModifyPower(POWER_MANA, 5000);
|
||||
DoCastSelf(SPELL_ARCANE_TORRENT);
|
||||
context.Repeat(15s);
|
||||
}).Schedule(10s, 15s, [this](TaskContext context)
|
||||
}).Schedule(10s, 16s, [this](TaskContext context)
|
||||
{
|
||||
if (DoCastRandomTarget(SPELL_DOMINATION, 0, 50.0f, true, false, false) == SPELL_CAST_OK)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "IpAddress.h"
|
||||
#include "Log.h"
|
||||
#include "Socket.h"
|
||||
#include "Systemd.h"
|
||||
#include <atomic>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
@@ -32,7 +33,7 @@ constexpr auto ACORE_MAX_LISTEN_CONNECTIONS = boost::asio::socket_base::max_list
|
||||
class AsyncAcceptor
|
||||
{
|
||||
public:
|
||||
typedef void(*AcceptCallback)(tcp::socket&& newSocket, uint32 threadIndex);
|
||||
typedef void(*AcceptCallback)(IoContextTcpSocket&& newSocket, uint32 threadIndex);
|
||||
|
||||
AsyncAcceptor(Acore::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, bool supportSocketActivation = false) :
|
||||
_acceptor(ioContext), _endpoint(Acore::Net::make_address(bindIp), port),
|
||||
@@ -56,7 +57,7 @@ public:
|
||||
template<AcceptCallback acceptCallback>
|
||||
void AsyncAcceptWithCallback()
|
||||
{
|
||||
tcp::socket* socket;
|
||||
IoContextTcpSocket* socket;
|
||||
uint32 threadIndex;
|
||||
std::tie(socket, threadIndex) = _socketFactory();
|
||||
_acceptor.async_accept(*socket, [this, socket, threadIndex](boost::system::error_code error)
|
||||
@@ -129,16 +130,16 @@ public:
|
||||
_acceptor.close(err);
|
||||
}
|
||||
|
||||
void SetSocketFactory(std::function<std::pair<tcp::socket*, uint32>()> func) { _socketFactory = func; }
|
||||
void SetSocketFactory(std::function<std::pair<IoContextTcpSocket*, uint32>()> func) { _socketFactory = std::move(func); }
|
||||
|
||||
private:
|
||||
std::pair<tcp::socket*, uint32> DefaultSocketFactory() { return std::make_pair(&_socket, 0); }
|
||||
std::pair<IoContextTcpSocket*, uint32> DefaultSocketFactory() { return std::make_pair(&_socket, 0); }
|
||||
|
||||
tcp::acceptor _acceptor;
|
||||
tcp::endpoint _endpoint;
|
||||
tcp::socket _socket;
|
||||
boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, IoContextTcpSocket::executor_type> _acceptor;
|
||||
boost::asio::ip::tcp::endpoint _endpoint;
|
||||
IoContextTcpSocket _socket;
|
||||
std::atomic<bool> _closed;
|
||||
std::function<std::pair<tcp::socket*, uint32>()> _socketFactory;
|
||||
std::function<std::pair<IoContextTcpSocket*, uint32>()> _socketFactory;
|
||||
bool _supportSocketActivation;
|
||||
};
|
||||
|
||||
|
||||
@@ -91,13 +91,13 @@ public:
|
||||
SocketAdded(sock);
|
||||
}
|
||||
|
||||
tcp::socket* GetSocketForAccept() { return &_acceptSocket; }
|
||||
IoContextTcpSocket* GetSocketForAccept() { return &_acceptSocket; }
|
||||
|
||||
void EnableProxyProtocol() { _proxyHeaderReadingEnabled = true; }
|
||||
|
||||
protected:
|
||||
virtual void SocketAdded(std::shared_ptr<SocketType> /*sock*/) { }
|
||||
virtual void SocketRemoved(std::shared_ptr<SocketType> /*sock*/) { }
|
||||
virtual void SocketAdded(std::shared_ptr<SocketType> const& /*sock*/) { }
|
||||
virtual void SocketRemoved(std::shared_ptr<SocketType> const& /*sock*/) { }
|
||||
|
||||
void AddNewSockets()
|
||||
{
|
||||
@@ -229,7 +229,7 @@ private:
|
||||
SocketContainer _newSockets;
|
||||
|
||||
Acore::Asio::IoContext _ioContext;
|
||||
tcp::socket _acceptSocket;
|
||||
IoContextTcpSocket _acceptSocket;
|
||||
boost::asio::steady_timer _updateTimer;
|
||||
|
||||
bool _proxyHeaderReadingEnabled;
|
||||
|
||||
@@ -21,9 +21,8 @@
|
||||
#include "Log.h"
|
||||
#include "MessageBuffer.h"
|
||||
#include <atomic>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <type_traits>
|
||||
@@ -35,6 +34,23 @@ using boost::asio::ip::tcp;
|
||||
#define AC_SOCKET_USE_IOCP
|
||||
#endif
|
||||
|
||||
// Specialize boost socket for io_context executor instead of type-erased any_io_executor
|
||||
// This avoids the type-erasure overhead of any_io_executor
|
||||
using IoContextTcpSocket = boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::io_context::executor_type>;
|
||||
|
||||
enum class SocketReadCallbackResult
|
||||
{
|
||||
KeepReading,
|
||||
Stop
|
||||
};
|
||||
|
||||
enum class SocketState : uint8
|
||||
{
|
||||
Open = 0,
|
||||
Closing = 1,
|
||||
Closed = 2
|
||||
};
|
||||
|
||||
enum ProxyHeaderReadingState {
|
||||
PROXY_HEADER_READING_STATE_NOT_STARTED,
|
||||
PROXY_HEADER_READING_STATE_STARTED,
|
||||
@@ -51,8 +67,8 @@ template<class T>
|
||||
class Socket : public std::enable_shared_from_this<T>
|
||||
{
|
||||
public:
|
||||
explicit Socket(tcp::socket&& socket) : _socket(std::move(socket)), _remoteAddress(_socket.remote_endpoint().address()),
|
||||
_remotePort(_socket.remote_endpoint().port()), _readBuffer(), _closed(false), _closing(false), _isWritingAsync(false),
|
||||
explicit Socket(IoContextTcpSocket&& socket) : _socket(std::move(socket)), _remoteAddress(_socket.remote_endpoint().address()),
|
||||
_remotePort(_socket.remote_endpoint().port()), _readBuffer(), _state(SocketState::Open), _isWritingAsync(false),
|
||||
_proxyHeaderReadingState(PROXY_HEADER_READING_STATE_NOT_STARTED)
|
||||
{
|
||||
_readBuffer.Resize(READ_BLOCK_SIZE);
|
||||
@@ -60,7 +76,7 @@ public:
|
||||
|
||||
virtual ~Socket()
|
||||
{
|
||||
_closed = true;
|
||||
_state = SocketState::Closed;
|
||||
boost::system::error_code error;
|
||||
_socket.close(error);
|
||||
}
|
||||
@@ -69,13 +85,14 @@ public:
|
||||
|
||||
virtual bool Update()
|
||||
{
|
||||
if (_closed)
|
||||
SocketState state = _state.load();
|
||||
if (state == SocketState::Closed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef AC_SOCKET_USE_IOCP
|
||||
if (_isWritingAsync || (_writeQueue.empty() && !_closing))
|
||||
if (_isWritingAsync || (_writeQueue.empty() && state != SocketState::Closing))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -150,12 +167,18 @@ public:
|
||||
|
||||
[[nodiscard]] ProxyHeaderReadingState GetProxyHeaderReadingState() const { return _proxyHeaderReadingState; }
|
||||
|
||||
[[nodiscard]] bool IsOpen() const { return !_closed && !_closing; }
|
||||
[[nodiscard]] bool IsOpen() const { return _state.load() == SocketState::Open; }
|
||||
|
||||
void CloseSocket()
|
||||
{
|
||||
if (_closed.exchange(true))
|
||||
return;
|
||||
SocketState expected = SocketState::Open;
|
||||
if (!_state.compare_exchange_strong(expected, SocketState::Closed))
|
||||
{
|
||||
// If it was Closing, try to transition to Closed
|
||||
expected = SocketState::Closing;
|
||||
if (!_state.compare_exchange_strong(expected, SocketState::Closed))
|
||||
return; // Already closed
|
||||
}
|
||||
|
||||
boost::system::error_code shutdownError;
|
||||
_socket.shutdown(boost::asio::socket_base::shutdown_send, shutdownError);
|
||||
@@ -168,13 +191,17 @@ public:
|
||||
}
|
||||
|
||||
/// Marks the socket for closing after write buffer becomes empty
|
||||
void DelayedCloseSocket() { _closing = true; }
|
||||
void DelayedCloseSocket()
|
||||
{
|
||||
SocketState expected = SocketState::Open;
|
||||
_state.compare_exchange_strong(expected, SocketState::Closing);
|
||||
}
|
||||
|
||||
MessageBuffer& GetReadBuffer() { return _readBuffer; }
|
||||
|
||||
protected:
|
||||
virtual void OnClose() { }
|
||||
virtual void ReadHandler() = 0;
|
||||
virtual SocketReadCallbackResult ReadHandler() = 0;
|
||||
|
||||
bool AsyncProcessQueue()
|
||||
{
|
||||
@@ -188,7 +215,7 @@ protected:
|
||||
_socket.async_write_some(boost::asio::buffer(buffer.GetReadPointer(), buffer.GetActiveSize()), std::bind(&Socket<T>::WriteHandler,
|
||||
this->shared_from_this(), std::placeholders::_1, std::placeholders::_2));
|
||||
#else
|
||||
_socket.async_wait(tcp::socket::wait_write, [self = this->shared_from_this()](boost::system::error_code error)
|
||||
_socket.async_wait(boost::asio::socket_base::wait_write, [self = this->shared_from_this()](boost::system::error_code error)
|
||||
{
|
||||
self->WriteHandlerWrapper(error, 0);
|
||||
});
|
||||
@@ -216,7 +243,8 @@ private:
|
||||
}
|
||||
|
||||
_readBuffer.WriteCompleted(transferredBytes);
|
||||
ReadHandler();
|
||||
if (ReadHandler() == SocketReadCallbackResult::KeepReading)
|
||||
AsyncRead();
|
||||
}
|
||||
|
||||
// ProxyReadHeaderHandler reads Proxy Protocol v2 header (v1 is not supported).
|
||||
@@ -344,7 +372,7 @@ private:
|
||||
|
||||
if (!_writeQueue.empty())
|
||||
AsyncProcessQueue();
|
||||
else if (_closing)
|
||||
else if (_state.load() == SocketState::Closing)
|
||||
CloseSocket();
|
||||
}
|
||||
else
|
||||
@@ -380,7 +408,7 @@ private:
|
||||
|
||||
_writeQueue.pop();
|
||||
|
||||
if (_closing && _writeQueue.empty())
|
||||
if (_state.load() == SocketState::Closing && _writeQueue.empty())
|
||||
{
|
||||
CloseSocket();
|
||||
}
|
||||
@@ -391,7 +419,7 @@ private:
|
||||
{
|
||||
_writeQueue.pop();
|
||||
|
||||
if (_closing && _writeQueue.empty())
|
||||
if (_state.load() == SocketState::Closing && _writeQueue.empty())
|
||||
{
|
||||
CloseSocket();
|
||||
}
|
||||
@@ -406,7 +434,7 @@ private:
|
||||
|
||||
_writeQueue.pop();
|
||||
|
||||
if (_closing && _writeQueue.empty())
|
||||
if (_state.load() == SocketState::Closing && _writeQueue.empty())
|
||||
{
|
||||
CloseSocket();
|
||||
}
|
||||
@@ -415,7 +443,7 @@ private:
|
||||
}
|
||||
#endif
|
||||
|
||||
tcp::socket _socket;
|
||||
IoContextTcpSocket _socket;
|
||||
|
||||
boost::asio::ip::address _remoteAddress;
|
||||
uint16 _remotePort;
|
||||
@@ -423,8 +451,7 @@ private:
|
||||
MessageBuffer _readBuffer;
|
||||
std::queue<MessageBuffer> _writeQueue;
|
||||
|
||||
std::atomic<bool> _closed;
|
||||
std::atomic<bool> _closing;
|
||||
std::atomic<SocketState> _state;
|
||||
|
||||
bool _isWritingAsync;
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
_threads[i].Wait();
|
||||
}
|
||||
|
||||
virtual void OnSocketOpen(tcp::socket&& sock, uint32 threadIndex)
|
||||
virtual void OnSocketOpen(IoContextTcpSocket&& sock, uint32 threadIndex)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
return min;
|
||||
}
|
||||
|
||||
std::pair<tcp::socket*, uint32> GetSocketForAccept()
|
||||
std::pair<IoContextTcpSocket*, uint32> GetSocketForAccept()
|
||||
{
|
||||
uint32 threadIndex = SelectThreadWithMinConnections();
|
||||
return { _threads[threadIndex].GetSocketForAccept(), threadIndex };
|
||||
|
||||
Reference in New Issue
Block a user