Implement expansion class check and unique class limit.

This commit is contained in:
VladimirMangos 2008-11-09 03:46:47 +03:00
parent 73e595ef87
commit d2be8dbe8f
3 changed files with 49 additions and 23 deletions

View file

@ -228,17 +228,16 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
if (raceEntry->addon > Expansion()) if (raceEntry->addon > Expansion())
{ {
data << (uint8)CHAR_CREATE_EXPANSION; data << (uint8)CHAR_CREATE_EXPANSION;
sLog.outError("Not Expansion 1 account:[%d] but tried to Create character with expansion 1 race (%u)",GetAccountId(),race_); sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u race (%u)",Expansion(),GetAccountId(),raceEntry->addon,race_);
SendPacket( &data ); SendPacket( &data );
return; return;
} }
// prevent character creating Expansion class without Expansion account // prevent character creating Expansion class without Expansion account
// TODO: use possible addon field in ChrClassesEntry in next dbc version if (classEntry->addon > Expansion())
if (Expansion() < 2 && class_ == CLASS_DEATH_KNIGHT)
{ {
data << (uint8)CHAR_CREATE_EXPANSION; data << (uint8)CHAR_CREATE_EXPANSION_CLASS;
sLog.outError("Not Expansion 2 account:[%d] but tried to Create character with expansion 2 class (%u)",GetAccountId(),class_); sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u class (%u)",Expansion(),GetAccountId(),classEntry->addon,class_);
SendPacket( &data ); SendPacket( &data );
return; return;
} }
@ -309,25 +308,37 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS); uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS);
bool have_same_race = false; bool have_same_race = false;
if(!AllowTwoSideAccounts || skipCinematics == 1) if(!AllowTwoSideAccounts || skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT)
{ {
QueryResult *result2 = CharacterDatabase.PQuery("SELECT DISTINCT race FROM characters WHERE account = '%u' %s", GetAccountId(),skipCinematics == 1 ? "" : "LIMIT 1"); QueryResult *result2 = CharacterDatabase.PQuery("SELECT race,class FROM characters WHERE account = '%u' %s",
GetAccountId(), (skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) ? "" : "LIMIT 1");
if(result2) if(result2)
{ {
uint32 team_= Player::TeamForRace(race_); uint32 team_= Player::TeamForRace(race_);
Field* field = result2->Fetch(); Field* field = result2->Fetch();
uint8 race = field[0].GetUInt32(); uint8 acc_race = field[0].GetUInt32();
if(class_ == CLASS_DEATH_KNIGHT)
{
uint8 acc_class = field[1].GetUInt32();
if(acc_class == CLASS_DEATH_KNIGHT)
{
data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT;
SendPacket( &data );
return;
}
}
// need to check team only for first character // need to check team only for first character
// TODO: what to if account already has characters of both races? // TODO: what to if account already has characters of both races?
if (!AllowTwoSideAccounts) if (!AllowTwoSideAccounts)
{ {
uint32 team=0; uint32 acc_team=0;
if(race > 0) if(acc_race > 0)
team = Player::TeamForRace(race); acc_team = Player::TeamForRace(acc_race);
if(team != team_) if(acc_team != team_)
{ {
data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION; data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION;
SendPacket( &data ); SendPacket( &data );
@ -336,15 +347,29 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
} }
} }
if (skipCinematics == 1) // search same race for cinematic or same class if need
// TODO: check if cinematic already shown? (already logged in?; cinematic field)
while ((skipCinematics == 1 && !have_same_race) || class_ == CLASS_DEATH_KNIGHT)
{ {
// TODO: check if cinematic already shown? (already logged in?; cinematic field) if(!result2->NextRow())
while (race_ != race && result2->NextRow()) break;
field = result2->Fetch();
acc_race = field[0].GetUInt32();
if(!have_same_race)
have_same_race = race_ == acc_race;
if(class_ == CLASS_DEATH_KNIGHT)
{ {
field = result2->Fetch(); uint8 acc_class = field[1].GetUInt32();
race = field[0].GetUInt32(); if(acc_class == CLASS_DEATH_KNIGHT)
{
data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT;
SendPacket( &data );
return;
}
} }
have_same_race = race_ == race;
} }
delete result2; delete result2;
} }

View file

@ -543,9 +543,9 @@ struct ChatChannelsEntry
struct ChrClassesEntry struct ChrClassesEntry
{ {
uint32 ClassID; // 0 uint32 ClassID; // 0
// 1-2, unused // 1, unused
uint32 powerType; // 3 uint32 powerType; // 2
// 4, unused // 3-4, unused
//char* name[16]; // 5-20 unused //char* name[16]; // 5-20 unused
// 21 string flag, unused // 21 string flag, unused
//char* string1[16]; // 21-36 unused //char* string1[16]; // 21-36 unused
@ -556,6 +556,7 @@ struct ChrClassesEntry
uint32 spellfamily; // 56 uint32 spellfamily; // 56
// 57, unused // 57, unused
uint32 CinematicSequence; // 58 id from CinematicSequences.dbc uint32 CinematicSequence; // 58 id from CinematicSequences.dbc
uint32 addon; // 59 (0 - original race, 1 - tbc addon, ...)
}; };
struct ChrRacesEntry struct ChrRacesEntry
@ -961,7 +962,7 @@ struct ScalingStatValuesEntry
struct SkillLineEntry struct SkillLineEntry
{ {
uint32 id; // 0 m_ID uint32 id; // 0 m_ID
int32 categoryId; // 1 m_categoryID (index from SkillLineCategory.dbc) uint32 categoryId; // 1 m_categoryID (index from SkillLineCategory.dbc)
//uint32 skillCostID; // 2 m_skillCostsID not used //uint32 skillCostID; // 2 m_skillCostsID not used
char* name[16]; // 3-18 m_displayName_lang char* name[16]; // 3-18 m_displayName_lang
// 19 string flags, not used // 19 string flags, not used

View file

@ -26,7 +26,7 @@ const char BattlemasterListEntryfmt[]="niiiiiiiiiiiixxxssssssssssssssssxx";
const char CharTitlesEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; const char CharTitlesEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx"; const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx";
// ChatChannelsEntryfmt, index not used (more compact store) // ChatChannelsEntryfmt, index not used (more compact store)
const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixix"; const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
const char ChrRacesEntryfmt[]="nxixiixxixxxxissssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; const char ChrRacesEntryfmt[]="nxixiixxixxxxissssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
const char CreatureDisplayInfofmt[]="nxxxfxxxxxxxxxxx"; const char CreatureDisplayInfofmt[]="nxxxfxxxxxxxxxxx";
const char CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx"; const char CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx";