Merge commit '6c1e4bc20d68d9fb548eb4896bd8b84a4c3ec4ff' into 4.3.4
Conflicts: README.md sql/updates/world/2015_04_04_00_world.sql sql/updates/world/2015_04_04_01_world.sql sql/updates/world/2015_04_05_06_world_335.sql src/server/game/Battlegrounds/Battleground.cpp src/server/game/DataStores/DBCStores.cpp src/server/game/DataStores/DBCStructure.h src/server/game/DataStores/DBCfmt.h src/server/game/Entities/Object/Object.cpp src/server/game/Entities/Player/Player.cpp src/server/game/Entities/Player/Player.h src/server/game/Entities/Unit/Unit.cpp src/server/game/Handlers/CharacterHandler.cpp src/server/game/Server/WorldSession.cpp src/server/game/Server/WorldSocket.cpp src/server/game/Spells/Spell.cpp src/server/game/Spells/SpellInfo.cpp src/server/game/World/World.cpp src/server/scripts/Commands/cs_account.cpp src/tools/map_extractor/System.cpp src/tools/vmap4_extractor/adtfile.cpp
This commit is contained in:
commit
224c7dc6ae
181 files changed
+707
-1014
No files matched your search
@@ -978,8 +978,6 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
|
||||
{
|
||||
//FIXME: outfitId not used in player creating
|
||||
/// @todo need more checks against packet modifications
|
||||
// should check that skin, face, hair* are valid via DBC per race/class
|
||||
// also do it in Player::BuildEnumData, Player::LoadFromDB
|
||||
|
||||
Object::_Create(guidlow, 0, HIGHGUID_PLAYER);
|
||||
|
||||
@@ -1021,6 +1019,13 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ValidateAppearance(createInfo->Race, createInfo->Class, createInfo->Gender, createInfo->HairStyle, createInfo->HairColor, createInfo->Face, createInfo->FacialHair, createInfo->Skin, true))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player", "Player::Create: Possible hacking-attempt: Account %u tried creating a character named '%s' with invalid appearance attributes - refusing to do so",
|
||||
GetSession()->GetAccountId(), m_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 RaceClassGender = (createInfo->Race) | (createInfo->Class << 8) | (createInfo->Gender << 16);
|
||||
|
||||
SetUInt32Value(UNIT_FIELD_BYTES_0, (RaceClassGender | (powertype << 24)));
|
||||
@@ -1987,6 +1992,24 @@ bool Player::BuildEnumData(PreparedQueryResult result, ByteBuffer* dataBuffer, B
|
||||
uint32 atLoginFlags = fields[15].GetUInt16();
|
||||
Tokenizer equipment(fields[19].GetString(), ' ');
|
||||
uint8 slot = fields[21].GetUInt8();
|
||||
uint32 playerBytes2 = fields[6].GetUInt32();
|
||||
|
||||
uint16 atLoginFlags = fields[15].GetUInt16();
|
||||
|
||||
if (!ValidateAppearance(uint8(plrRace), uint8(plrClass), gender, uint8(playerBytes >> 16), uint8(playerBytes >> 24), uint8(playerBytes >> 8), uint8(playerBytes2), uint8(playerBytes)))
|
||||
{
|
||||
TC_LOG_ERROR("entities.player.loading", "Player %u has wrong Appearance values (Hair/Skin/Color), forcing recustomize", guid);
|
||||
|
||||
if (!(atLoginFlags & AT_LOGIN_CUSTOMIZE))
|
||||
{
|
||||
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG);
|
||||
stmt->setUInt16(0, uint16(AT_LOGIN_CUSTOMIZE));
|
||||
stmt->setUInt32(1, guid);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
atLoginFlags |= AT_LOGIN_CUSTOMIZE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32 charFlags = 0;
|
||||
if (playerFlags & PLAYER_FLAGS_HIDE_HELM)
|
||||
@@ -9968,7 +9991,7 @@ uint32 Player::GetXPRestBonus(uint32 xp)
|
||||
|
||||
SetRestBonus(GetRestBonus() - rested_bonus);
|
||||
|
||||
TC_LOG_DEBUG("entities.player", "Player gain %u xp (+ %u Rested Bonus). Rested points=%f", xp+rested_bonus, rested_bonus, GetRestBonus());
|
||||
TC_LOG_DEBUG("entities.player", "GetXPRestBonus: Player %s (%u) gain %u xp (+%u Rested Bonus). Rested points=%f", GetName().c_str(), GetGUIDLow(), xp+rested_bonus, rested_bonus, GetRestBonus());
|
||||
return rested_bonus;
|
||||
}
|
||||
|
||||
@@ -17374,6 +17397,20 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
|
||||
SetUInt32Value(PLAYER_BYTES_2, fields[10].GetUInt32());
|
||||
SetByteValue(PLAYER_BYTES_3, 0, fields[5].GetUInt8());
|
||||
SetByteValue(PLAYER_BYTES_3, 1, fields[45].GetUInt8());
|
||||
|
||||
if (!ValidateAppearance(
|
||||
fields[3].GetUInt8(), // race
|
||||
fields[4].GetUInt8(), // class
|
||||
gender, GetByteValue(PLAYER_BYTES, 2), // hair type
|
||||
GetByteValue(PLAYER_BYTES, 3), //hair color
|
||||
uint8(fields[9].GetUInt32() >> 8), // face
|
||||
GetByteValue(PLAYER_BYTES_2, 0), // facial hair
|
||||
GetByteValue(PLAYER_BYTES, 0))) // skin color
|
||||
{
|
||||
TC_LOG_ERROR("entities.player", "Player %s has wrong Appearance values (Hair/Skin/Color), can't be loaded.", guid.ToString().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
SetUInt32Value(PLAYER_FLAGS, fields[11].GetUInt32());
|
||||
SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fields[44].GetUInt32());
|
||||
|
||||
@@ -21849,12 +21886,7 @@ void Player::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs)
|
||||
if (itr->second->state == PLAYERSPELL_REMOVED)
|
||||
continue;
|
||||
uint32 unSpellId = itr->first;
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(unSpellId);
|
||||
if (!spellInfo)
|
||||
{
|
||||
ASSERT(spellInfo);
|
||||
continue;
|
||||
}
|
||||
SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(unSpellId);
|
||||
|
||||
// Not send cooldown for this spells
|
||||
if (spellInfo->IsCooldownStartedOnEvent())
|
||||
@@ -22498,9 +22530,9 @@ void Player::SetPvP(bool state)
|
||||
(*itr)->SetPvP(state);
|
||||
}
|
||||
|
||||
void Player::UpdatePvP(bool state, bool override)
|
||||
void Player::UpdatePvP(bool state, bool _override)
|
||||
{
|
||||
if (!state || override)
|
||||
if (!state || _override)
|
||||
{
|
||||
SetPvP(state);
|
||||
pvpInfo.EndTimer = 0;
|
||||
@@ -25655,11 +25687,11 @@ uint32 Player::CalculateTalentsPoints() const
|
||||
return uint32(talentPointsForLevel * sWorld->getRate(RATE_TALENT));
|
||||
}
|
||||
|
||||
bool Player::IsKnowHowFlyIn(uint32 mapid, uint32 zone) const
|
||||
bool Player::canFlyInZone(uint32 mapid, uint32 zone) const
|
||||
{
|
||||
// continent checked in SpellInfo::CheckLocation at cast and area update
|
||||
uint32 v_map = GetVirtualMapForMapAndZone(mapid, zone);
|
||||
return v_map != 571 || HasSpell(54197); // Cold Weather Flying
|
||||
return v_map != 571 || HasSpell(54197); // 54197 = Cold Weather Flying
|
||||
}
|
||||
|
||||
void Player::LearnSpellHighestRank(uint32 spellid)
|
||||
@@ -28066,3 +28098,58 @@ void Player::SendSupercededSpell(uint32 oldSpell, uint32 newSpell)
|
||||
data << uint32(newSpell) << uint32(oldSpell);
|
||||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
bool Player::ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 hairID, uint8 hairColor, uint8 faceID, uint8 facialHair, uint8 skinColor, bool create /*=false*/)
|
||||
{
|
||||
// Check skin color
|
||||
// For Skin type is always 0
|
||||
if (CharSectionsEntry const* entry = GetCharSectionEntry(race, SECTION_TYPE_SKIN, gender, 0, skinColor))
|
||||
{ // Skin Color defined as Face color, too, we check skin & face in one pass
|
||||
if (CharSectionsEntry const* entry2 = GetCharSectionEntry(race, SECTION_TYPE_FACE, gender, faceID, skinColor))
|
||||
{
|
||||
// Check DeathKnight exclusive
|
||||
if (((entry->Flags & SECTION_FLAG_DEATH_KNIGHT) || (entry2->Flags & SECTION_FLAG_DEATH_KNIGHT)) && class_ != CLASS_DEATH_KNIGHT)
|
||||
return false;
|
||||
if (create && !((entry->Flags & SECTION_FLAG_PLAYER) && (entry2->Flags & SECTION_FLAG_PLAYER)))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
// These combinations don't have an entry of Type SECTION_TYPE_FACIAL_HAIR, exclude them from that check
|
||||
bool excludeCheck = (race == RACE_TAUREN) || (race == RACE_DRAENEI) || (gender == GENDER_FEMALE && race != RACE_NIGHTELF && race != RACE_UNDEAD_PLAYER);
|
||||
|
||||
// Check Hair
|
||||
if (CharSectionsEntry const* entry = GetCharSectionEntry(race, SECTION_TYPE_HAIR, gender, hairID, hairColor))
|
||||
{
|
||||
if ((entry->Flags & SECTION_FLAG_DEATH_KNIGHT) && class_ != CLASS_DEATH_KNIGHT)
|
||||
return false;
|
||||
if (create && !(entry->Flags & SECTION_FLAG_PLAYER))
|
||||
return false;
|
||||
|
||||
if (!excludeCheck)
|
||||
{
|
||||
if (CharSectionsEntry const* entry2 = GetCharSectionEntry(race, SECTION_TYPE_FACIAL_HAIR, gender, facialHair, hairColor))
|
||||
{
|
||||
if ((entry2->Flags & SECTION_FLAG_DEATH_KNIGHT) && class_ != CLASS_DEATH_KNIGHT)
|
||||
return false;
|
||||
if (create && !(entry2->Flags & SECTION_FLAG_PLAYER))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// @TODO: Bound checking for facialHair ID (used clientside for markings, tauren beard, etc.)
|
||||
// Not present in DBC
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in new issue
Block a user