aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Handlers/CharacterHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Handlers/CharacterHandler.cpp')
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp96
1 files changed, 78 insertions, 18 deletions
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index d02d01f512b..98adc84d6fe 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -515,6 +515,15 @@ bool WorldSession::MeetsChrCustomizationReq(ChrCustomizationReqEntry const* req,
if (req->ItemModifiedAppearanceID && !GetCollectionMgr()->HasItemAppearance(req->ItemModifiedAppearanceID).first)
return false;
+ if (req->QuestID)
+ {
+ if (!_player)
+ return false;
+
+ if (!_player->IsQuestRewarded(req->QuestID))
+ return false;
+ }
+
if (checkRequiredDependentChoices)
{
if (std::unordered_map<uint32, std::vector<uint32>> const* requiredChoices = sDB2Manager.GetRequiredCustomizationChoices(req->ID))
@@ -667,20 +676,32 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact
//}
// prevent character creating Expansion class without Expansion account
- ClassAvailability const* classExpansionRequirement = sObjectMgr->GetClassExpansionRequirement(charCreate.CreateInfo->Race, charCreate.CreateInfo->Class);
- if (!classExpansionRequirement)
+ if (ClassAvailability const* raceClassExpansionRequirement = sObjectMgr->GetClassExpansionRequirement(charCreate.CreateInfo->Race, charCreate.CreateInfo->Class))
{
- TC_LOG_ERROR("entities.player.cheat", "Expansion %u account:[%d] tried to Create character for race/class combination that is missing requirements in db (%u/%u)",
- GetAccountExpansion(), GetAccountId(), uint32(charCreate.CreateInfo->Race), uint32(charCreate.CreateInfo->Class));
- SendCharCreate(CHAR_CREATE_EXPANSION_CLASS);
- return;
+ if (raceClassExpansionRequirement->ActiveExpansionLevel > GetExpansion() || raceClassExpansionRequirement->AccountExpansionLevel > GetAccountExpansion())
+ {
+ TC_LOG_ERROR("entities.player.cheat", "Account:[%d] tried to create character with race/class %u/%u without required expansion (had %u/%u, required %u/%u)",
+ GetAccountId(), uint32(charCreate.CreateInfo->Race), uint32(charCreate.CreateInfo->Class), GetExpansion(), GetAccountExpansion(),
+ raceClassExpansionRequirement->ActiveExpansionLevel, raceClassExpansionRequirement->AccountExpansionLevel);
+ SendCharCreate(CHAR_CREATE_EXPANSION_CLASS);
+ return;
+ }
}
-
- if (classExpansionRequirement->ActiveExpansionLevel > GetExpansion() || classExpansionRequirement->AccountExpansionLevel > GetAccountExpansion())
+ else if (ClassAvailability const* classExpansionRequirement = sObjectMgr->GetClassExpansionRequirementFallback(charCreate.CreateInfo->Class))
+ {
+ if (classExpansionRequirement->MinActiveExpansionLevel > GetExpansion() || classExpansionRequirement->AccountExpansionLevel > GetAccountExpansion())
+ {
+ TC_LOG_ERROR("entities.player.cheat", "Account:[%d] tried to create character with race/class %u/%u without required expansion (had %u/%u, required %u/%u)",
+ GetAccountId(), uint32(charCreate.CreateInfo->Race), uint32(charCreate.CreateInfo->Class), GetExpansion(), GetAccountExpansion(),
+ classExpansionRequirement->ActiveExpansionLevel, classExpansionRequirement->AccountExpansionLevel);
+ SendCharCreate(CHAR_CREATE_EXPANSION_CLASS);
+ return;
+ }
+ }
+ else
{
- TC_LOG_ERROR("entities.player.cheat", "Account:[%d] tried to create character with race/class %u/%u without required expansion (had %u/%u, required %u/%u)",
- GetAccountId(), uint32(charCreate.CreateInfo->Race), uint32(charCreate.CreateInfo->Class), GetExpansion(), GetAccountExpansion(),
- classExpansionRequirement->ActiveExpansionLevel, classExpansionRequirement->AccountExpansionLevel);
+ TC_LOG_ERROR("entities.player.cheat", "Expansion %u account:[%d] tried to Create character for race/class combination that is missing requirements in db (%u/%u)",
+ GetAccountExpansion(), GetAccountId(), uint32(charCreate.CreateInfo->Race), uint32(charCreate.CreateInfo->Class));
SendCharCreate(CHAR_CREATE_EXPANSION_CLASS);
return;
}
@@ -792,9 +813,14 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact
bool haveSameRace = false;
uint32 demonHunterReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_DEMON_HUNTER);
bool hasDemonHunterReqLevel = (demonHunterReqLevel == 0);
+ uint32 evokerReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_EVOKER);
+ bool hasEvokerReqLevel = (evokerReqLevel == 0);
bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || HasPermission(rbac::RBAC_PERM_TWO_SIDE_CHARACTER_CREATION);
uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
- bool checkDemonHunterReqs = createInfo->Class == CLASS_DEMON_HUNTER && !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_DEMON_HUNTER);
+ bool checkClassLevelReqs = (createInfo->Class == CLASS_DEMON_HUNTER || createInfo->Class == CLASS_EVOKER)
+ && !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_DEMON_HUNTER);
+ int32 evokerLimit = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_EVOKERS_PER_REALM);
+ bool hasEvokerLimit = evokerLimit != 0;
if (result)
{
@@ -802,8 +828,9 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact
Field* field = result->Fetch();
uint8 accRace = field[1].GetUInt8();
+ uint8 accClass = field[2].GetUInt8();
- if (checkDemonHunterReqs)
+ if (checkClassLevelReqs)
{
if (!hasDemonHunterReqLevel)
{
@@ -811,8 +838,17 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact
if (accLevel >= demonHunterReqLevel)
hasDemonHunterReqLevel = true;
}
+ if (!hasEvokerReqLevel)
+ {
+ uint8 accLevel = field[0].GetUInt8();
+ if (accLevel >= evokerReqLevel)
+ hasEvokerReqLevel = true;
+ }
}
+ if (accClass == CLASS_EVOKER)
+ --evokerLimit;
+
// need to check team only for first character
/// @todo what to if account already has characters of both races?
if (!allowTwoSideAccounts)
@@ -830,18 +866,19 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact
// search same race for cinematic or same class if need
/// @todo check if cinematic already shown? (already logged in?; cinematic field)
- while ((skipCinematics == 1 && !haveSameRace) || createInfo->Class == CLASS_DEMON_HUNTER)
+ while ((skipCinematics == 1 && !haveSameRace) || createInfo->Class == CLASS_DEMON_HUNTER || createInfo->Class == CLASS_EVOKER)
{
if (!result->NextRow())
break;
field = result->Fetch();
accRace = field[1].GetUInt8();
+ accClass = field[2].GetUInt8();
if (!haveSameRace)
haveSameRace = createInfo->Race == accRace;
- if (checkDemonHunterReqs)
+ if (checkClassLevelReqs)
{
if (!hasDemonHunterReqLevel)
{
@@ -849,13 +886,36 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact
if (accLevel >= demonHunterReqLevel)
hasDemonHunterReqLevel = true;
}
+ if (!hasEvokerReqLevel)
+ {
+ uint8 accLevel = field[0].GetUInt8();
+ if (accLevel >= evokerReqLevel)
+ hasEvokerReqLevel = true;
+ }
}
+
+ if (accClass == CLASS_EVOKER)
+ --evokerLimit;
+ }
+ }
+
+ if (checkClassLevelReqs)
+ {
+ if (!hasDemonHunterReqLevel)
+ {
+ SendCharCreate(CHAR_CREATE_NEW_PLAYER);
+ return;
+ }
+ if (!hasEvokerReqLevel)
+ {
+ SendCharCreate(CHAR_CREATE_DRACTHYR_LEVEL_REQUIREMENT);
+ return;
}
}
- if (checkDemonHunterReqs && !hasDemonHunterReqLevel)
+ if (createInfo->Class == CLASS_EVOKER && hasEvokerLimit && evokerLimit < 1)
{
- SendCharCreate(CHAR_CREATE_NEW_PLAYER);
+ SendCharCreate(CHAR_CREATE_DRACTHYR_DUPLICATE);
return;
}
@@ -922,7 +982,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CREATE_INFO);
stmt->setUInt32(0, GetAccountId());
- stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEMON_HUNTER) ? 1200 : 1); // 200 (max chars per realm) + 1000 (max deleted chars per realm)
+ stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEMON_HUNTER || createInfo->Class == CLASS_EVOKER) ? 1200 : 1); // 200 (max chars per realm) + 1000 (max deleted chars per realm)
queryCallback.WithPreparedCallback(std::move(finalizeCharacterCreation)).SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
}));
}