Merge pull request #15139 from horn/6.x

Core/BattlePets: Basics for Battle Pets
This commit is contained in:
MitchesD
2015-09-09 16:15:32 +02:00
38 changed files with 5504 additions and 46 deletions
+50
View File
@@ -167,6 +167,56 @@ LOCK TABLES `autobroadcast` WRITE;
/*!40000 ALTER TABLE `autobroadcast` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `battle_pets`
--
DROP TABLE IF EXISTS `battle_pets`;
CREATE TABLE `battle_pets` (
`guid` bigint(20) NOT NULL,
`battlenetAccountId` int(10) NOT NULL,
`species` int(10) NOT NULL,
`breed` smallint(5) NOT NULL,
`level` smallint(5) NOT NULL DEFAULT '1',
`exp` smallint(5) NOT NULL DEFAULT '0',
`health` int(10) NOT NULL DEFAULT '1',
`quality` tinyint(3) NOT NULL DEFAULT '0',
`flags` smallint(5) NOT NULL DEFAULT '0',
`name` varchar(12) NOT NULL,
PRIMARY KEY (`guid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `battle_pets`
--
LOCK TABLES `battle_pets` WRITE;
/*!40000 ALTER TABLE `battle_pets` DISABLE KEYS */;
/*!40000 ALTER TABLE `battle_pets` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `battle_pet_slots`
--
DROP TABLE IF EXISTS `battle_pet_slots`;
CREATE TABLE `battle_pet_slots` (
`id` tinyint(3) NOT NULL,
`battlenetAccountId` int(10) NOT NULL,
`battlePetGuid` bigint(20) NOT NULL,
`locked` tinyint(3) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`,`battlenetAccountId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `battle_pet_slots`
--
LOCK TABLES `battle_pet_slots` WRITE;
/*!40000 ALTER TABLE `battle_pet_slots` DISABLE KEYS */;
/*!40000 ALTER TABLE `battle_pet_slots` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `battlenet_account_bans`
--
+4
View File
@@ -2523,6 +2523,10 @@ CREATE TABLE `item_instance` (
`transmogrification` int(10) unsigned NOT NULL DEFAULT '0',
`upgradeId` int(10) unsigned NOT NULL DEFAULT '0',
`enchantIllusion` int(10) unsigned NOT NULL DEFAULT '0',
`battlePetSpeciesId` int(10) unsigned NOT NULL DEFAULT '0',
`battlePetBreedData` int(10) unsigned NOT NULL DEFAULT '0',
`battlePetLevel` smallint(5) unsigned NOT NULL DEFAULT '0',
`battlePetDisplayId` int(10) unsigned NOT NULL DEFAULT '0',
`bonusListIDs` text,
PRIMARY KEY (`guid`),
KEY `idx_owner_guid` (`owner_guid`)
+31
View File
@@ -0,0 +1,31 @@
--
-- Table structure for table `battle_pets`
--
DROP TABLE IF EXISTS `battle_pets`;
CREATE TABLE `battle_pets` (
`guid` bigint(20) NOT NULL,
`battlenetAccountId` int(10) NOT NULL,
`species` int(10) NOT NULL,
`breed` smallint(5) NOT NULL,
`level` smallint(5) NOT NULL DEFAULT '1',
`exp` smallint(5) NOT NULL DEFAULT '0',
`health` int(10) NOT NULL DEFAULT '1',
`quality` tinyint(3) NOT NULL DEFAULT '0',
`flags` smallint(5) NOT NULL DEFAULT '0',
`name` varchar(12) NOT NULL,
PRIMARY KEY (`guid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table `battle_pet_slots`
--
DROP TABLE IF EXISTS `battle_pet_slots`;
CREATE TABLE `battle_pet_slots` (
`id` tinyint(3) NOT NULL,
`battlenetAccountId` int(10) NOT NULL,
`battlePetGuid` bigint(20) NOT NULL,
`locked` tinyint(3) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`,`battlenetAccountId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@@ -0,0 +1,5 @@
ALTER TABLE `item_instance`
ADD `battlePetSpeciesId` int(10) unsigned NOT NULL DEFAULT '0' AFTER `enchantIllusion`,
ADD `battlePetBreedData` int(10) unsigned NOT NULL DEFAULT '0' AFTER `battlePetSpeciesId`,
ADD `battlePetLevel` smallint(5) unsigned NOT NULL DEFAULT '0' AFTER `battlePetBreedData`,
ADD `battlePetDisplayId` int(10) unsigned NOT NULL DEFAULT '0' AFTER `battlePetLevel`;
@@ -0,0 +1,66 @@
DELETE FROM `battle_pet_species` WHERE `ID` IN (1449,1636); -- already in BattlePetSpecies.db2
--
-- Table structure for table `battle_pet_breed_quality`
--
DROP TABLE IF EXISTS `battle_pet_breed_quality`;
CREATE TABLE `battle_pet_breed_quality` (
`ID` int(10) unsigned NOT NULL DEFAULT '0',
`Quality` int(10) unsigned NOT NULL DEFAULT '0',
`Modifier` int(11) NOT NULL DEFAULT '0',
`VerifiedBuild` smallint(6) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Table structure for table `battle_pet_breed_state`
--
DROP TABLE IF EXISTS `battle_pet_breed_state`;
CREATE TABLE `battle_pet_breed_state` (
`ID` int(10) unsigned NOT NULL DEFAULT '0',
`BreedID` int(10) unsigned NOT NULL DEFAULT '0',
`State` int(10) unsigned NOT NULL DEFAULT '0',
`Value` int(11) NOT NULL DEFAULT '0',
`VerifiedBuild` smallint(6) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Table structure for table `battle_pet_species_locale`
--
DROP TABLE IF EXISTS `battle_pet_species_locale`;
CREATE TABLE `battle_pet_species_locale` (
`ID` int(10) unsigned NOT NULL DEFAULT '0',
`locale` varchar(4) NOT NULL,
`SourceText` text,
`Description` text,
`VerifiedBuild` smallint(6) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`,`locale`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Table structure for table `battle_pet_species_state`
--
DROP TABLE IF EXISTS `battle_pet_species_state`;
CREATE TABLE `battle_pet_species_state` (
`ID` int(10) unsigned NOT NULL DEFAULT '0',
`SpeciesID` int(10) unsigned NOT NULL DEFAULT '0',
`State` int(10) unsigned NOT NULL DEFAULT '0',
`Value` int(11) NOT NULL DEFAULT '0',
`VerifiedBuild` smallint(6) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Table structure for table `item_to_battle_pet_species`
--
DROP TABLE IF EXISTS `item_to_battle_pet_species`;
CREATE TABLE `item_to_battle_pet_species` (
`ID` int(10) unsigned NOT NULL DEFAULT '0',
`BattlePetSpeciesID` int(10) unsigned NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
File diff suppressed because it is too large Load Diff
@@ -22,7 +22,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
if (!m_reconnecting)
m_stmts.resize(MAX_CHARACTERDATABASE_STATEMENTS);
#define SelectItemInstanceContent "ii.guid, ii.itemEntry, ii.creatorGuid, ii.giftCreatorGuid, ii.count, ii.duration, ii.charges, ii.flags, ii.enchantments, ii.randomPropertyId, ii.durability, ii.playedTime, ii.text, ii.transmogrification, ii.upgradeId, ii.enchantIllusion, ii.bonusListIDs"
#define SelectItemInstanceContent "ii.guid, ii.itemEntry, ii.creatorGuid, ii.giftCreatorGuid, ii.count, ii.duration, ii.charges, ii.flags, ii.enchantments, ii.randomPropertyId, ii.durability, ii.playedTime, ii.text, ii.transmogrification, ii.upgradeId, ii.enchantIllusion, ii.battlePetSpeciesId, ii.battlePetBreedData, ii.battlePetLevel, ii.battlePetDisplayId, ii.bonusListIDs"
PrepareStatement(CHAR_DEL_QUEST_POOL_SAVE, "DELETE FROM pool_quest_save WHERE pool_id = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_QUEST_POOL_SAVE, "INSERT INTO pool_quest_save (pool_id, quest_id) VALUES (?, ?)", CONNECTION_ASYNC);
@@ -159,8 +159,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_ITEM_BOP_TRADE, "DELETE FROM item_soulbound_trade_data WHERE itemGuid = ? LIMIT 1", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_ITEM_BOP_TRADE, "INSERT INTO item_soulbound_trade_data VALUES (?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_REP_INVENTORY_ITEM, "REPLACE INTO character_inventory (guid, bag, slot, item) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_REP_ITEM_INSTANCE, "REPLACE INTO item_instance (itemEntry, owner_guid, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, transmogrification, upgradeId, enchantIllusion, bonusListIDs, guid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_ITEM_INSTANCE, "UPDATE item_instance SET itemEntry = ?, owner_guid = ?, creatorGuid = ?, giftCreatorGuid = ?, count = ?, duration = ?, charges = ?, flags = ?, enchantments = ?, randomPropertyId = ?, durability = ?, playedTime = ?, text = ?, transmogrification = ?, upgradeId = ?, enchantIllusion = ?, bonusListIDs = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_REP_ITEM_INSTANCE, "REPLACE INTO item_instance (itemEntry, owner_guid, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, transmogrification, upgradeId, enchantIllusion, battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, bonusListIDs, guid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_ITEM_INSTANCE, "UPDATE item_instance SET itemEntry = ?, owner_guid = ?, creatorGuid = ?, giftCreatorGuid = ?, count = ?, duration = ?, charges = ?, flags = ?, enchantments = ?, randomPropertyId = ?, durability = ?, playedTime = ?, text = ?, transmogrification = ?, upgradeId = ?, enchantIllusion = ?, battlePetSpeciesId = ?, battlePetBreedData = ?, battlePetLevel = ?, battlePetDisplayId = ?, bonusListIDs = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_ITEM_INSTANCE_ON_LOAD, "UPDATE item_instance SET duration = ?, flags = ?, durability = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_ITEM_INSTANCE, "DELETE FROM item_instance WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_ITEM_INSTANCE_BY_OWNER, "DELETE FROM item_instance WHERE owner_guid = ?", CONNECTION_ASYNC);
@@ -47,6 +47,20 @@ void HotfixDatabaseConnection::DoPrepareStatements()
" ORDER BY ID DESC", CONNECTION_SYNCH);
PREPARE_LOCALE_STMT(HOTFIX_SEL_BARBER_SHOP_STYLE, "SELECT ID, DisplayName_lang, Description_lang FROM barber_shop_style_locale WHERE locale = ?", CONNECTION_SYNCH);
// BattlePetBreedQuality.db2
PrepareStatement(HOTFIX_SEL_BATTLE_PET_BREED_QUALITY, "SELECT ID, Quality, Modifier FROM battle_pet_breed_quality ORDER BY ID DESC", CONNECTION_SYNCH);
// BattlePetBreedState.db2
PrepareStatement(HOTFIX_SEL_BATTLE_PET_BREED_STATE, "SELECT ID, BreedID, State, Value FROM battle_pet_breed_state ORDER BY ID DESC", CONNECTION_SYNCH);
// BattlePetSpecies.db2
PrepareStatement(HOTFIX_SEL_BATTLE_PET_SPECIES, "SELECT ID, CreatureID, IconFileID, SummonSpellID, PetType, Source, Flags, "
"SourceText, Description FROM battle_pet_species ORDER BY ID DESC", CONNECTION_SYNCH);
PREPARE_LOCALE_STMT(HOTFIX_SEL_BATTLE_PET_SPECIES, "SELECT ID, SourceText, Description FROM battle_pet_species_locale WHERE locale = ?", CONNECTION_SYNCH);
// BattlePetSpeciesState.db2
PrepareStatement(HOTFIX_SEL_BATTLE_PET_SPECIES_STATE, "SELECT ID, SpeciesID, State, Value FROM battle_pet_species_state ORDER BY ID DESC", CONNECTION_SYNCH);
// BroadcastText.db2
PrepareStatement(HOTFIX_SEL_BROADCAST_TEXT, "SELECT ID, Language, MaleText, FemaleText, EmoteID1, EmoteID2, EmoteID3, EmoteDelay1, EmoteDelay2, "
"EmoteDelay3, SoundID, UnkEmoteID, Type FROM broadcast_text ORDER BY ID DESC", CONNECTION_SYNCH);
@@ -277,6 +291,9 @@ void HotfixDatabaseConnection::DoPrepareStatements()
// ItemSpecOverride.db2
PrepareStatement(HOTFIX_SEL_ITEM_SPEC_OVERRIDE, "SELECT ID, ItemID, SpecID FROM item_spec_override ORDER BY ID DESC", CONNECTION_SYNCH);
// ItemToBattlePetSpecies.db2
PrepareStatement(HOTFIX_SEL_ITEM_TO_BATTLE_PET_SPECIES, "SELECT ID, BattlePetSpeciesID FROM item_to_battle_pet_species ORDER BY ID DESC", CONNECTION_SYNCH);
// ItemXBonusTree.db2
PrepareStatement(HOTFIX_SEL_ITEM_X_BONUS_TREE, "SELECT ID, ItemID, BonusTreeID FROM item_x_bonus_tree ORDER BY ID DESC", CONNECTION_SYNCH);
@@ -42,6 +42,15 @@ enum HotfixDatabaseStatements
HOTFIX_SEL_BARBER_SHOP_STYLE,
HOTFIX_SEL_BARBER_SHOP_STYLE_LOCALE,
HOTFIX_SEL_BATTLE_PET_BREED_QUALITY,
HOTFIX_SEL_BATTLE_PET_BREED_STATE,
HOTFIX_SEL_BATTLE_PET_SPECIES,
HOTFIX_SEL_BATTLE_PET_SPECIES_LOCALE,
HOTFIX_SEL_BATTLE_PET_SPECIES_STATE,
HOTFIX_SEL_BROADCAST_TEXT,
HOTFIX_SEL_BROADCAST_TEXT_LOCALE,
@@ -159,6 +168,8 @@ enum HotfixDatabaseStatements
HOTFIX_SEL_ITEM_SPEC_OVERRIDE,
HOTFIX_SEL_ITEM_TO_BATTLE_PET_SPECIES,
HOTFIX_SEL_ITEM_X_BONUS_TREE,
HOTFIX_SEL_KEY_CHAIN,
@@ -144,4 +144,13 @@ void LoginDatabaseConnection::DoPrepareStatements()
// Account wide toys
PrepareStatement(LOGIN_SEL_ACCOUNT_TOYS, "SELECT itemId, isFavourite FROM battlenet_account_toys WHERE accountId = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_REP_ACCOUNT_TOYS, "REPLACE INTO battlenet_account_toys (accountId, itemId, isFavourite) VALUES (?, ?, ?)", CONNECTION_ASYNC);
// Battle Pets
PrepareStatement(LOGIN_SEL_BATTLE_PETS, "SELECT guid, species, breed, level, exp, health, quality, flags, name FROM battle_pets WHERE battlenetAccountId = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_BATTLE_PETS, "INSERT INTO battle_pets (guid, battlenetAccountId, species, breed, level, exp, health, quality, flags, name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_DEL_BATTLE_PETS, "DELETE FROM battle_pets WHERE battlenetAccountId = ? AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BATTLE_PETS, "UPDATE battle_pets SET level = ?, exp = ?, health = ?, quality = ?, flags = ?, name = ? WHERE battlenetAccountId = ? AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_BATTLE_PET_SLOTS, "SELECT id, battlePetGuid, locked FROM battle_pet_slots WHERE battlenetAccountId = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_BATTLE_PET_SLOTS, "INSERT INTO battle_pet_slots (id, battlenetAccountId, battlePetGuid, locked) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_DEL_BATTLE_PET_SLOTS, "DELETE FROM battle_pet_slots WHERE battlenetAccountId = ?", CONNECTION_ASYNC);
}
@@ -133,6 +133,14 @@ enum LoginDatabaseStatements
LOGIN_SEL_ACCOUNT_TOYS,
LOGIN_REP_ACCOUNT_TOYS,
LOGIN_SEL_BATTLE_PETS,
LOGIN_INS_BATTLE_PETS,
LOGIN_DEL_BATTLE_PETS,
LOGIN_UPD_BATTLE_PETS,
LOGIN_SEL_BATTLE_PET_SLOTS,
LOGIN_INS_BATTLE_PET_SLOTS,
LOGIN_DEL_BATTLE_PET_SLOTS,
MAX_LOGINDATABASE_STATEMENTS
};
@@ -1057,6 +1057,7 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type,
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: // This also behaves like ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA
case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
case ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT:
SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE);
break;
// std case: increment at miscValue1
@@ -1164,6 +1165,7 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type,
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET:
SetCriteriaProgress(achievementCriteria, 1, referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
@@ -1280,8 +1282,6 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type,
case ACHIEVEMENT_CRITERIA_TYPE_COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO_COUNT:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO:
case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET:
case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT:
case ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET:
case ACHIEVEMENT_CRITERIA_TYPE_WIN_PET_BATTLE:
case ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET:
@@ -1444,12 +1444,14 @@ bool AchievementMgr<T>::IsCompletedCriteria(AchievementCriteria const* achieveme
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
case ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT:
return progress->counter >= requiredAmount;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET:
return progress->counter >= 1;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
return progress->counter >= (requiredAmount * 75);
@@ -2533,6 +2535,10 @@ bool AchievementMgr<T>::AdditionalRequirementsSatisfied(ModifierTreeNode const*
if (!unit || unit->GetHealthPct() >= reqValue)
return false;
break;
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_SPECIES: // 91
if (miscValue1 != reqValue)
return false;
break;
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_QUALITY: // 145
{
if (!referencePlayer)
+467
View File
@@ -0,0 +1,467 @@
/*
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlePetMgr.h"
#include "Containers.h"
#include "Player.h"
#include "WorldSession.h"
void BattlePetMgr::BattlePet::CalculateStats()
{
float health = 0.0f;
float power = 0.0f;
float speed = 0.0f;
// get base breed stats
auto breedState = _battlePetBreedStates.find(PacketInfo.Breed);
if (breedState == _battlePetBreedStates.end()) // non existing breed id
return;
health = breedState->second[STATE_STAT_STAMINA];
power = breedState->second[STATE_STAT_POWER];
speed = breedState->second[STATE_STAT_SPEED];
// modify stats depending on species - not all pets have this
auto speciesState = _battlePetSpeciesStates.find(PacketInfo.Species);
if (speciesState != _battlePetSpeciesStates.end())
{
health += speciesState->second[STATE_STAT_STAMINA];
power += speciesState->second[STATE_STAT_POWER];
speed += speciesState->second[STATE_STAT_SPEED];
}
// modify stats by quality
for (auto itr : sBattlePetBreedQualityStore)
{
if (itr->Quality == PacketInfo.Quality)
{
health *= itr->Modifier;
power *= itr->Modifier;
speed *= itr->Modifier;
break;
}
// TOOD: add check if pet has existing quality
}
// scale stats depending on level
health *= PacketInfo.Level;
power *= PacketInfo.Level;
speed *= PacketInfo.Level;
// set stats
// round, ceil or floor? verify this
PacketInfo.MaxHealth = uint32((round(health / 20) + 100));
PacketInfo.Power = uint32(round(power / 100));
PacketInfo.Speed = uint32(round(speed / 100));
}
std::unordered_map<uint16 /*BreedID*/, std::unordered_map<BattlePetState /*state*/, int32 /*value*/, std::hash<std::underlying_type<BattlePetState>::type> >> BattlePetMgr::_battlePetBreedStates;
std::unordered_map<uint32 /*SpeciesID*/, std::unordered_map<BattlePetState /*state*/, int32 /*value*/, std::hash<std::underlying_type<BattlePetState>::type> >> BattlePetMgr::_battlePetSpeciesStates;
std::unordered_map<uint32 /*SpeciesID*/, std::unordered_set<uint8 /*breed*/>> BattlePetMgr::_availableBreedsPerSpecies;
std::unordered_map<uint32 /*SpeciesID*/, uint8 /*quality*/> BattlePetMgr::_defaultQualityPerSpecies;
void BattlePetMgr::Initialize()
{
if (QueryResult result = LoginDatabase.Query("SELECT MAX(guid) FROM battle_pets"))
sObjectMgr->GetGenerator<HighGuid::BattlePet>().Set((*result)[0].GetUInt64() + 1);
for (auto itr : sBattlePetBreedStateStore)
_battlePetBreedStates[itr->BreedID][BattlePetState(itr->State)] = itr->Value;
for (auto itr : sBattlePetSpeciesStateStore)
_battlePetSpeciesStates[itr->SpeciesID][BattlePetState(itr->State)] = itr->Value;
LoadAvailablePetBreeds();
LoadDefaultPetQualities();
}
void BattlePetMgr::LoadAvailablePetBreeds()
{
QueryResult result = WorldDatabase.Query("SELECT speciesId, breedId FROM battle_pet_breeds");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 battle pet breeds. DB table `battle_pet_breeds` is empty.");
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
uint32 speciesId = fields[0].GetUInt32();
uint16 breedId = fields[1].GetUInt16();
if (!sBattlePetSpeciesStore.LookupEntry(speciesId))
{
TC_LOG_ERROR("sql.sql", "Non-existing BattlePetSpecies.db2 entry %u was referenced in `battle_pet_breeds` by row (%u, %u).", speciesId, speciesId, breedId);
continue;
}
// TODO: verify breed id (3 - 12 (male) or 3 - 22 (male and female)) if needed
_availableBreedsPerSpecies[speciesId].insert(breedId);
++count;
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u battle pet breeds.", count);
}
void BattlePetMgr::LoadDefaultPetQualities()
{
QueryResult result = WorldDatabase.Query("SELECT speciesId, quality FROM battle_pet_quality");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 battle pet qualities. DB table `battle_pet_quality` is empty.");
return;
}
do
{
Field* fields = result->Fetch();
uint32 speciesId = fields[0].GetUInt32();
uint8 quality = fields[1].GetUInt8();
if (!sBattlePetSpeciesStore.LookupEntry(speciesId))
{
TC_LOG_ERROR("sql.sql", "Non-existing BattlePetSpecies.db2 entry %u was referenced in `battle_pet_quality` by row (%u, %u).", speciesId, speciesId, quality);
continue;
}
// TODO: verify quality (0 - 3 for player pets or 0 - 5 for both player and tamer pets) if needed
_defaultQualityPerSpecies[speciesId] = quality;
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u battle pet qualities.", uint32(_defaultQualityPerSpecies.size()));
}
uint16 BattlePetMgr::RollPetBreed(uint32 species)
{
auto itr = _availableBreedsPerSpecies.find(species);
if (itr == _availableBreedsPerSpecies.end())
return 3; // default B/B
return Trinity::Containers::SelectRandomContainerElement(itr->second);
}
uint8 BattlePetMgr::GetDefaultPetQuality(uint32 species)
{
auto itr = _defaultQualityPerSpecies.find(species);
if (itr == _defaultQualityPerSpecies.end())
return 0; // default poor
return itr->second;
}
BattlePetMgr::BattlePetMgr(WorldSession* owner)
{
_owner = owner;
for (uint8 i = 0; i < MAX_PET_BATTLE_SLOTS; ++i)
{
WorldPackets::BattlePet::BattlePetSlot slot;
slot.Index = i;
_slots.push_back(slot);
}
}
void BattlePetMgr::LoadFromDB(PreparedQueryResult pets, PreparedQueryResult slots)
{
if (pets)
{
do
{
Field* fields = pets->Fetch();
uint32 species = fields[1].GetUInt32();
if (BattlePetSpeciesEntry const* speciesEntry = sBattlePetSpeciesStore.LookupEntry(species))
{
if (GetPetCount(species) >= MAX_BATTLE_PETS_PER_SPECIES)
{
TC_LOG_ERROR("misc", "Battlenet account with id %u has more than 3 battle pets of species %u", _owner->GetBattlenetAccountId(), species);
continue;
}
BattlePet pet;
pet.PacketInfo.Guid = ObjectGuid::Create<HighGuid::BattlePet>(fields[0].GetUInt64());
pet.PacketInfo.Species = species;
pet.PacketInfo.Breed = fields[2].GetUInt16();
pet.PacketInfo.Level = fields[3].GetUInt16();
pet.PacketInfo.Exp = fields[4].GetUInt16();
pet.PacketInfo.Health = fields[5].GetUInt32();
pet.PacketInfo.Quality = fields[6].GetUInt8();
pet.PacketInfo.Flags = fields[7].GetUInt16();
pet.PacketInfo.Name = fields[8].GetString();
pet.PacketInfo.CreatureID = speciesEntry->CreatureID;
pet.SaveInfo = BATTLE_PET_UNCHANGED;
pet.CalculateStats();
_pets[pet.PacketInfo.Guid.GetCounter()] = pet;
}
} while (pets->NextRow());
}
if (slots)
{
uint8 i = 0; // slots->GetRowCount() should equal MAX_BATTLE_PET_SLOTS
do
{
Field* fields = slots->Fetch();
_slots[i].Index = fields[0].GetUInt8();
auto itr = _pets.find(fields[1].GetUInt64());
if (itr != _pets.end())
_slots[i].Pet = itr->second.PacketInfo;
_slots[i].Locked = fields[2].GetBool();
i++;
} while (slots->NextRow());
}
}
void BattlePetMgr::SaveToDB(SQLTransaction& trans)
{
PreparedStatement* stmt = nullptr;
for (auto itr = _pets.begin(); itr != _pets.end();)
{
switch (itr->second.SaveInfo)
{
case BATTLE_PET_NEW:
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BATTLE_PETS);
stmt->setUInt64(0, itr->first);
stmt->setUInt32(1, _owner->GetBattlenetAccountId());
stmt->setUInt32(2, itr->second.PacketInfo.Species);
stmt->setUInt16(3, itr->second.PacketInfo.Breed);
stmt->setUInt16(4, itr->second.PacketInfo.Level);
stmt->setUInt16(5, itr->second.PacketInfo.Exp);
stmt->setUInt32(6, itr->second.PacketInfo.Health);
stmt->setUInt8(7, itr->second.PacketInfo.Quality);
stmt->setUInt16(8, itr->second.PacketInfo.Flags);
stmt->setString(9, itr->second.PacketInfo.Name);
trans->Append(stmt);
itr->second.SaveInfo = BATTLE_PET_UNCHANGED;
++itr;
break;
case BATTLE_PET_CHANGED:
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BATTLE_PETS);
stmt->setUInt16(0, itr->second.PacketInfo.Level);
stmt->setUInt16(1, itr->second.PacketInfo.Exp);
stmt->setUInt32(2, itr->second.PacketInfo.Health);
stmt->setUInt8(3, itr->second.PacketInfo.Quality);
stmt->setUInt16(4, itr->second.PacketInfo.Flags);
stmt->setString(5, itr->second.PacketInfo.Name);
stmt->setUInt32(6, _owner->GetBattlenetAccountId());
stmt->setUInt64(7, itr->first);
trans->Append(stmt);
itr->second.SaveInfo = BATTLE_PET_UNCHANGED;
++itr;
break;
case BATTLE_PET_REMOVED:
stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_BATTLE_PETS);
stmt->setUInt32(0, _owner->GetBattlenetAccountId());
stmt->setUInt64(1, itr->first);
trans->Append(stmt);
itr = _pets.erase(itr);
break;
default:
++itr;
break;
}
}
stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_BATTLE_PET_SLOTS);
stmt->setUInt32(0, _owner->GetBattlenetAccountId());
trans->Append(stmt);
for (WorldPackets::BattlePet::BattlePetSlot const& slot : _slots)
{
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BATTLE_PET_SLOTS);
stmt->setUInt8(0, slot.Index);
stmt->setUInt32(1, _owner->GetBattlenetAccountId());
stmt->setUInt64(2, slot.Pet.Guid.GetCounter());
stmt->setBool(3, slot.Locked);
trans->Append(stmt);
}
}
BattlePetMgr::BattlePet* BattlePetMgr::GetPet(ObjectGuid guid)
{
auto itr = _pets.find(guid.GetCounter());
if (itr != _pets.end())
return &itr->second;
return nullptr;
}
void BattlePetMgr::AddPet(uint32 species, uint32 creatureId, uint16 breed, uint8 quality, uint16 level /*= 1*/)
{
BattlePetSpeciesEntry const* battlePetSpecies = sBattlePetSpeciesStore.LookupEntry(species);
if (!battlePetSpecies) // should never happen
return;
BattlePet pet;
pet.PacketInfo.Guid = ObjectGuid::Create<HighGuid::BattlePet>(sObjectMgr->GetGenerator<HighGuid::BattlePet>().Generate());
pet.PacketInfo.Species = species;
pet.PacketInfo.CreatureID = creatureId;
pet.PacketInfo.Level = level;
pet.PacketInfo.Exp = 0;
pet.PacketInfo.Flags = 0;
pet.PacketInfo.Breed = breed;
pet.PacketInfo.Quality = quality;
pet.PacketInfo.Name = "";
pet.CalculateStats();
pet.PacketInfo.Health = pet.PacketInfo.MaxHealth;
pet.SaveInfo = BATTLE_PET_NEW;
_pets[pet.PacketInfo.Guid.GetCounter()] = pet;
std::vector<BattlePet> updates;
updates.push_back(pet);
SendUpdates(updates, true);
_owner->GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET, species);
}
void BattlePetMgr::RemovePet(ObjectGuid guid)
{
BattlePet* pet = GetPet(guid);
if (!pet)
return;
pet->SaveInfo = BATTLE_PET_REMOVED;
// spell is not unlearned on retail
/*if (GetPetCount(pet->PacketInfo.Species) == 0)
if (BattlePetSpeciesEntry const* speciesEntry = sBattlePetSpeciesStore.LookupEntry(pet->PacketInfo.Species))
_owner->GetPlayer()->RemoveSpell(speciesEntry->SummonSpellID);*/
}
uint8 BattlePetMgr::GetPetCount(uint32 species) const
{
uint8 count = 0;
for (auto& itr : _pets)
if (itr.second.PacketInfo.Species == species && itr.second.SaveInfo != BATTLE_PET_REMOVED)
count++;
return count;
}
void BattlePetMgr::UnlockSlot(uint8 slot)
{
if (!_slots[slot].Locked)
return;
_slots[slot].Locked = false;
WorldPackets::BattlePet::PetBattleSlotUpdates updates;
updates.Slots.push_back(_slots[slot]);
updates.AutoSlotted = false; // what's this?
updates.NewSlot = true; // causes the "new slot unlocked" bubble to appear
_owner->SendPacket(updates.Write());
}
std::vector<BattlePetMgr::BattlePet> BattlePetMgr::GetLearnedPets() const
{
std::vector<BattlePet> pets;
for (auto& pet : _pets)
if (pet.second.SaveInfo != BATTLE_PET_REMOVED)
pets.push_back(pet.second);
return pets;
}
void BattlePetMgr::CageBattlePet(ObjectGuid guid)
{
BattlePet* pet = GetPet(guid);
if (!pet)
return;
ItemPosCountVec dest;
if (_owner->GetPlayer()->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, BATTLE_PET_CAGE_ITEM_ID, 1) != EQUIP_ERR_OK)
return;
Item* item = _owner->GetPlayer()->StoreNewItem(dest, BATTLE_PET_CAGE_ITEM_ID, true);
if (!item)
return;
item->SetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID, pet->PacketInfo.Species);
item->SetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA, pet->PacketInfo.Breed | (pet->PacketInfo.Quality << 24));
item->SetModifier(ITEM_MODIFIER_BATTLE_PET_LEVEL, pet->PacketInfo.Level);
item->SetModifier(ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID, pet->PacketInfo.CreatureID);
// FIXME: "You create: ." - item name missing in chat
_owner->GetPlayer()->SendNewItem(item, 1, true, true);
RemovePet(guid);
WorldPackets::BattlePet::BattlePetDeleted deletePet;
deletePet.PetGuid = guid;
_owner->SendPacket(deletePet.Write());
}
void BattlePetMgr::HealBattlePetsPct(uint8 pct)
{
// TODO: After each Pet Battle, any injured companion will automatically
// regain 50 % of the damage that was taken during combat
std::vector<BattlePet> updates;
for (auto& pet : _pets)
if (pet.second.PacketInfo.Health != pet.second.PacketInfo.MaxHealth)
{
pet.second.PacketInfo.Health += CalculatePct(pet.second.PacketInfo.MaxHealth, pct);
// don't allow Health to be greater than MaxHealth
pet.second.PacketInfo.Health = std::min(pet.second.PacketInfo.Health, pet.second.PacketInfo.MaxHealth);
if (pet.second.SaveInfo != BATTLE_PET_NEW)
pet.second.SaveInfo = BATTLE_PET_CHANGED;
updates.push_back(pet.second);
}
SendUpdates(updates, false);
}
void BattlePetMgr::SummonPet(ObjectGuid guid)
{
BattlePet* pet = GetPet(guid);
if (!pet)
return;
BattlePetSpeciesEntry const* speciesEntry = sBattlePetSpeciesStore.LookupEntry(pet->PacketInfo.Species);
if (!speciesEntry)
return;
// TODO: set proper CreatureID for spell DEFAULT_SUMMON_BATTLE_PET_SPELL (default EffectMiscValueA is 40721 - Murkimus the Gladiator)
_owner->GetPlayer()->CastSpell(_owner->GetPlayer(), speciesEntry->SummonSpellID ? speciesEntry->SummonSpellID : DEFAULT_SUMMON_BATTLE_PET_SPELL);
// TODO: set pet level, quality... update fields
}
void BattlePetMgr::SendUpdates(std::vector<BattlePet> pets, bool petAdded)
{
WorldPackets::BattlePet::BattlePetUpdates updates;
for (auto pet : pets)
updates.Pets.push_back(pet.PacketInfo);
updates.PetAdded = petAdded;
_owner->SendPacket(updates.Write());
}
void BattlePetMgr::SendError(BattlePetError error, uint32 creatureId)
{
WorldPackets::BattlePet::BattlePetError battlePetError;
battlePetError.Result = error;
battlePetError.CreatureID = creatureId;
_owner->SendPacket(battlePetError.Write());
}
+141
View File
@@ -0,0 +1,141 @@
/*
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BattlePetMgr_h__
#define BattlePetMgr_h__
#include "DB2Stores.h"
#include "BattlePetPackets.h"
enum BattlePetMisc
{
MAX_PET_BATTLE_SLOTS = 3,
MAX_BATTLE_PETS_PER_SPECIES = 3,
BATTLE_PET_CAGE_ITEM_ID = 82800,
DEFAULT_SUMMON_BATTLE_PET_SPELL = 118301
};
// TODO: fix values in this enum
enum BattlePetError
{
BATTLEPETRESULT_CANT_HAVE_MORE_PETS_OF_THAT_TYPE = 9,
BATTLEPETRESULT_TOO_HIGH_LEVEL_TO_UNCAGE = 12,
BATTLEPETRESULT_CANT_HAVE_MORE_PETS = 13,
// wrong order
BATTLEPETRESULT_DUPLICATE_CONVERTED_PET,
BATTLEPETRESULT_NEED_TO_UNLOCK,
BATTLEPETRESULT_BAD_PARAM,
BATTLEPETRESULT_LOCKED_PET_ALREADY_EXISTS,
BATTLEPETRESULT_OK,
BATTLEPETRESULT_UNCAPTURABLE,
BATTLEPETRESULT_CANT_INVALID_CHARACTER_GUID
};
// taken from BattlePetState.db2 - it seems to store some initial values for battle pets
// there are only values used in BattlePetSpeciesState.db2 and BattlePetBreedState.db2
// TODO: expand this enum if needed
enum BattlePetState
{
STATE_MAX_HEALTH_BONUS = 2,
STATE_INTERNAL_INITIAL_LEVEL = 17,
STATE_STAT_POWER = 18,
STATE_STAT_STAMINA = 19,
STATE_STAT_SPEED = 20,
STATE_MOD_DAMAGE_DEALT_PERCENT = 23,
STATE_GENDER = 78, // 1 - male, 2 - female
STATE_COSMETIC_WATER_BUBBLED = 85,
STATE_SPECIAL_IS_COCKROACH = 93,
STATE_COSMETIC_FLY_TIER = 128,
STATE_COSMETIC_BIGGLESWORTH = 144,
STATE_PASSIVE_ELITE = 153,
STATE_PASSIVE_BOSS = 162,
STATE_COSMETIC_TREASURE_GOBLIN = 176,
// these are not in BattlePetState.db2 but are used in BattlePetSpeciesState.db2
STATE_START_WITH_BUFF = 183,
STATE_START_WITH_BUFF_2 = 184
};
enum BattlePetSaveInfo
{
BATTLE_PET_UNCHANGED = 0,
BATTLE_PET_CHANGED = 1,
BATTLE_PET_NEW = 2,
BATTLE_PET_REMOVED = 3
};
class BattlePetMgr
{
public:
struct BattlePet
{
void CalculateStats();
WorldPackets::BattlePet::BattlePet PacketInfo;
BattlePetSaveInfo SaveInfo;
};
explicit BattlePetMgr(WorldSession* owner);
static void Initialize();
static uint16 RollPetBreed(uint32 species);
static uint8 GetDefaultPetQuality(uint32 species);
void LoadFromDB(PreparedQueryResult pets, PreparedQueryResult slots);
void SaveToDB(SQLTransaction& trans);
BattlePet* GetPet(ObjectGuid guid);
void AddPet(uint32 species, uint32 creatureId, uint16 breed, uint8 quality, uint16 level = 1);
void RemovePet(ObjectGuid guid);
uint8 GetPetCount(uint32 species) const;
WorldPackets::BattlePet::BattlePetSlot* GetSlot(uint8 slot) { return &_slots[slot]; }
void UnlockSlot(uint8 slot);
WorldSession* GetOwner() const { return _owner; }
uint16 GetTrapLevel() const { return _trapLevel; }
std::vector<BattlePet> GetLearnedPets() const;
std::vector<WorldPackets::BattlePet::BattlePetSlot> GetSlots() const { return _slots; }
void CageBattlePet(ObjectGuid guid);
void HealBattlePetsPct(uint8 pct);
void SummonPet(ObjectGuid guid);
void SendUpdates(std::vector<BattlePet> pets, bool petAdded);
void SendError(BattlePetError error, uint32 creatureId);
private:
WorldSession* _owner;
uint16 _trapLevel = 0;
std::unordered_map<uint64 /*battlePetGuid*/, BattlePet> _pets;
std::vector<WorldPackets::BattlePet::BattlePetSlot> _slots;
static void LoadAvailablePetBreeds();
static void LoadDefaultPetQualities();
// hash no longer required in C++14
static std::unordered_map<uint16 /*BreedID*/, std::unordered_map<BattlePetState /*state*/, int32 /*value*/, std::hash<std::underlying_type<BattlePetState>::type> >> _battlePetBreedStates;
static std::unordered_map<uint32 /*SpeciesID*/, std::unordered_map<BattlePetState /*state*/, int32 /*value*/, std::hash<std::underlying_type<BattlePetState>::type> >> _battlePetSpeciesStates;
static std::unordered_map<uint32 /*SpeciesID*/, std::unordered_set<uint8 /*breed*/>> _availableBreedsPerSpecies;
static std::unordered_map<uint32 /*SpeciesID*/, uint8 /*quality*/> _defaultQualityPerSpecies;
};
#endif // BattlePetMgr_h__
+3
View File
@@ -16,6 +16,7 @@ file(GLOB_RECURSE sources_AuctionHouse AuctionHouse/*.cpp AuctionHouse/*.h)
file(GLOB_RECURSE sources_AuctionHouseBot AuctionHouseBot/*.cpp AuctionHouseBot/*.h)
file(GLOB_RECURSE sources_Battlefield Battlefield/*.cpp Battlefield/*.h)
file(GLOB_RECURSE sources_Battlegrounds Battlegrounds/*.cpp Battlegrounds/*.h)
file(GLOB_RECURSE sources_BattlePets BattlePets/*.cpp BattlePets/*.h)
file(GLOB_RECURSE sources_Calendar Calendar/*.cpp Calendar/*.h)
file(GLOB_RECURSE sources_Chat Chat/*.cpp Chat/*.h)
file(GLOB_RECURSE sources_Combat Combat/*.cpp Combat/*.h)
@@ -68,6 +69,7 @@ set(game_STAT_SRCS
${sources_AuctionHouseBot}
${sources_Battlefield}
${sources_Battlegrounds}
${sources_BattlePets}
${sources_Calendar}
${sources_Chat}
${sources_Combat}
@@ -118,6 +120,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Battlefield/Zones
${CMAKE_CURRENT_SOURCE_DIR}/Battlegrounds
${CMAKE_CURRENT_SOURCE_DIR}/Battlegrounds/Zones
${CMAKE_CURRENT_SOURCE_DIR}/BattlePets
${CMAKE_CURRENT_SOURCE_DIR}/Calendar
${CMAKE_CURRENT_SOURCE_DIR}/Chat
${CMAKE_CURRENT_SOURCE_DIR}/Chat/Channels
+10
View File
@@ -29,6 +29,10 @@ DB2Storage<AreaGroupEntry> sAreaGroupStore("AreaGroup.db2",
DB2Storage<AreaGroupMemberEntry> sAreaGroupMemberStore("AreaGroupMember.db2", AreaGroupMemberFormat, HOTFIX_SEL_AREA_GROUP_MEMBER);
DB2Storage<AuctionHouseEntry> sAuctionHouseStore("AuctionHouse.db2", AuctionHouseFormat, HOTFIX_SEL_AUCTION_HOUSE);
DB2Storage<BarberShopStyleEntry> sBarberShopStyleStore("BarberShopStyle.db2", BarberShopStyleFormat, HOTFIX_SEL_BARBER_SHOP_STYLE);
DB2Storage<BattlePetBreedQualityEntry> sBattlePetBreedQualityStore("BattlePetBreedQuality.db2", BattlePetBreedQualityFormat, HOTFIX_SEL_BATTLE_PET_BREED_QUALITY);
DB2Storage<BattlePetBreedStateEntry> sBattlePetBreedStateStore("BattlePetBreedState.db2", BattlePetBreedStateFormat, HOTFIX_SEL_BATTLE_PET_BREED_STATE);
DB2Storage<BattlePetSpeciesEntry> sBattlePetSpeciesStore("BattlePetSpecies.db2", BattlePetSpeciesFormat, HOTFIX_SEL_BATTLE_PET_SPECIES);
DB2Storage<BattlePetSpeciesStateEntry> sBattlePetSpeciesStateStore("BattlePetSpeciesState.db2", BattlePetSpeciesStateFormat, HOTFIX_SEL_BATTLE_PET_SPECIES_STATE);
DB2Storage<BroadcastTextEntry> sBroadcastTextStore("BroadcastText.db2", BroadcastTextFormat, HOTFIX_SEL_BROADCAST_TEXT);
DB2Storage<CharStartOutfitEntry> sCharStartOutfitStore("CharStartOutfit.db2", CharStartOutfitFormat, HOTFIX_SEL_CHAR_START_OUTFIT);
DB2Storage<ChrClassesXPowerTypesEntry> sChrClassesXPowerTypesStore("ChrClassesXPowerTypes.db2", ChrClassesXPowerTypesFormat, HOTFIX_SEL_CHR_CLASSES_X_POWER_TYPES);
@@ -78,6 +82,7 @@ DB2Storage<ItemRandomSuffixEntry> sItemRandomSuffixStore("ItemRand
DB2Storage<ItemSparseEntry> sItemSparseStore("Item-sparse.db2", ItemSparseFormat, HOTFIX_SEL_ITEM_SPARSE);
DB2Storage<ItemSpecEntry> sItemSpecStore("ItemSpec.db2", ItemSpecFormat, HOTFIX_SEL_ITEM_SPEC);
DB2Storage<ItemSpecOverrideEntry> sItemSpecOverrideStore("ItemSpecOverride.db2", ItemSpecOverrideFormat, HOTFIX_SEL_ITEM_SPEC_OVERRIDE);
DB2Storage<ItemToBattlePetSpeciesEntry> sItemToBattlePetSpeciesStore("ItemToBattlePetSpecies.db2", ItemToBattlePetSpeciesFormat, HOTFIX_SEL_ITEM_TO_BATTLE_PET_SPECIES);
DB2Storage<ItemXBonusTreeEntry> sItemXBonusTreeStore("ItemXBonusTree.db2", ItemXBonusTreeFormat, HOTFIX_SEL_ITEM_X_BONUS_TREE);
DB2Storage<KeyChainEntry> sKeyChainStore("KeyChain.db2", KeyChainFormat, HOTFIX_SEL_KEY_CHAIN);
DB2Storage<MailTemplateEntry> sMailTemplateStore("MailTemplate.db2", MailTemplateFormat, HOTFIX_SEL_MAIL_TEMPLATE);
@@ -196,8 +201,12 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale)
LOAD_DB2(sAchievementStore);
LOAD_DB2(sAreaGroupMemberStore);
LOAD_DB2(sAreaGroupStore);
LOAD_DB2(sBattlePetBreedQualityStore);
LOAD_DB2(sBattlePetBreedStateStore);
LOAD_DB2(sAuctionHouseStore);
LOAD_DB2(sBarberShopStyleStore);
LOAD_DB2(sBattlePetSpeciesStore);
LOAD_DB2(sBattlePetSpeciesStateStore);
LOAD_DB2(sBroadcastTextStore);
LOAD_DB2(sCharStartOutfitStore);
LOAD_DB2(sChrClassesXPowerTypesStore);
@@ -247,6 +256,7 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale)
LOAD_DB2(sItemSpecOverrideStore);
LOAD_DB2(sItemSpecStore);
LOAD_DB2(sItemStore);
LOAD_DB2(sItemToBattlePetSpeciesStore);
LOAD_DB2(sItemXBonusTreeStore);
LOAD_DB2(sKeyChainStore);
LOAD_DB2(sMailTemplateStore);
+5
View File
@@ -27,6 +27,10 @@
extern DB2Storage<AchievementEntry> sAchievementStore;
extern DB2Storage<AuctionHouseEntry> sAuctionHouseStore;
extern DB2Storage<BarberShopStyleEntry> sBarberShopStyleStore;
extern DB2Storage<BattlePetBreedQualityEntry> sBattlePetBreedQualityStore;
extern DB2Storage<BattlePetBreedStateEntry> sBattlePetBreedStateStore;
extern DB2Storage<BattlePetSpeciesEntry> sBattlePetSpeciesStore;
extern DB2Storage<BattlePetSpeciesStateEntry> sBattlePetSpeciesStateStore;
extern DB2Storage<BroadcastTextEntry> sBroadcastTextStore;
extern DB2Storage<CharStartOutfitEntry> sCharStartOutfitStore;
extern DB2Storage<CinematicSequencesEntry> sCinematicSequencesStore;
@@ -70,6 +74,7 @@ extern DB2Storage<ItemRandomSuffixEntry> sItemRandomSuffixStore;
extern DB2Storage<ItemSparseEntry> sItemSparseStore;
extern DB2Storage<ItemSpecEntry> sItemSpecStore;
extern DB2Storage<ItemSpecOverrideEntry> sItemSpecOverrideStore;
extern DB2Storage<ItemToBattlePetSpeciesEntry> sItemToBattlePetSpeciesStore;
extern DB2Storage<MailTemplateEntry> sMailTemplateStore;
extern DB2Storage<ModifierTreeEntry> sModifierTreeStore;
extern DB2Storage<MountCapabilityEntry> sMountCapabilityStore;
+42
View File
@@ -77,6 +77,42 @@ struct BarberShopStyleEntry
uint32 Data; // 7 (real ID to hair/facial hair)
};
struct BattlePetBreedQualityEntry
{
uint32 ID; // 0
uint32 Quality; // 1
float Modifier; // 2
};
struct BattlePetBreedStateEntry
{
uint32 ID; // 0
uint32 BreedID; // 1
uint32 State; // 2
int32 Value; // 3
};
struct BattlePetSpeciesEntry
{
uint32 ID; // 0
uint32 CreatureID; // 1
uint32 IconFileID; // 2
uint32 SummonSpellID; // 3
uint32 PetType; // 4
int32 Source; // 5
uint32 Flags; // 6
LocalizedString* SourceText; // 7
LocalizedString* Description; // 8
};
struct BattlePetSpeciesStateEntry
{
uint32 ID; // 0
uint32 SpeciesID; // 1
uint32 State; // 2
int32 Value; // 3
};
#define MAX_BROADCAST_TEXT_EMOTES 3
struct BroadcastTextEntry
@@ -830,6 +866,12 @@ struct ItemSpecOverrideEntry
uint32 SpecID; // 2
};
struct ItemToBattlePetSpeciesEntry
{
uint32 ID; // 0
uint32 BattlePetSpeciesID; // 1
};
struct ItemXBonusTreeEntry
{
uint32 ID; // 0
+5
View File
@@ -23,6 +23,10 @@ char const AreaGroupFormat[] = "n";
char const AreaGroupMemberFormat[] = "nii";
char const AuctionHouseFormat[] = "niiis";
char const BarberShopStyleFormat[] = "nissfiii";
char const BattlePetBreedQualityFormat[] = "nif";
char const BattlePetBreedStateFormat[] = "niii";
char const BattlePetSpeciesFormat[] = "niiiiiiss";
char const BattlePetSpeciesStateFormat[] = "niii";
char const BroadcastTextFormat[] = "nissiiiiiiiii";
char const CharStartOutfitFormat[] = "nbbbbiiiiiiiiiiiiiiiiiiiiiiiiii";
char const ChrClassesXPowerTypesFormat[] = "iii";
@@ -72,6 +76,7 @@ char const ItemRandomSuffixFormat[] = "nssiiiiiiiiii";
char const ItemSparseFormat[] = "niiiiffiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffffffiiifisssssiiiiiiiiiiiiiiiiiiifiiifiii";
char const ItemSpecFormat[] = "niiiiii";
char const ItemSpecOverrideFormat[] = "nii";
char const ItemToBattlePetSpeciesFormat[] = "ni";
char const ItemXBonusTreeFormat[] = "nii";
char const KeyChainFormat[] = "nbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
char const MailTemplateFormat[] = "ns";
+1
View File
@@ -159,6 +159,7 @@ enum AchievementCriteriaAdditionalCondition
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_RATED_BATTLEGROUND = 63, // NYI
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_PROJECT_RARITY = 65,
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_PROJECT_RACE = 66,
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_SPECIES = 91,
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_QUALITY = 145,
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_LEVEL = 146,
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_RARE_MISSION = 147, // NYI
+13 -3
View File
@@ -351,6 +351,10 @@ void Item::SaveToDB(SQLTransaction& trans)
stmt->setUInt32(++index, GetModifier(ITEM_MODIFIER_TRANSMOG_ITEM_ID) | (GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_MOD) << 24));
stmt->setUInt32(++index, GetModifier(ITEM_MODIFIER_UPGRADE_ID));
stmt->setUInt32(++index, GetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION));
stmt->setUInt32(++index, GetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID));
stmt->setUInt32(++index, GetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA));
stmt->setUInt32(++index, GetModifier(ITEM_MODIFIER_BATTLE_PET_LEVEL));
stmt->setUInt32(++index, GetModifier(ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID));
std::ostringstream bonusListIDs;
for (uint32 bonusListID : GetDynamicValues(ITEM_DYNAMIC_FIELD_BONUSLIST_IDS))
@@ -405,8 +409,10 @@ void Item::SaveToDB(SQLTransaction& trans)
bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fields, uint32 entry)
{
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
//result = CharacterDatabase.PQuery("SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, transmogrification, upgradeId, enchantIllusion, bonusListIDs FROM item_instance WHERE guid = '%u'", guid);
// 0 1 2 3 4 5 6 7 8 9 10 11 12
//result = CharacterDatabase.PQuery("SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text,
// 13 14 15 16 17 18 19 20
// transmogrification, upgradeId, enchantIllusion, battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, bonusListIDs FROM item_instance WHERE guid = '%u'", guid);
// create item before any checks for store correct guid
// and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB
@@ -482,8 +488,12 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie
}
SetModifier(ITEM_MODIFIER_UPGRADE_ID, fields[14].GetUInt32());
SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION, fields[15].GetUInt32());
SetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID, fields[16].GetUInt32());
SetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA, fields[17].GetUInt32());
SetModifier(ITEM_MODIFIER_BATTLE_PET_LEVEL, fields[18].GetUInt16());
SetModifier(ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID, fields[19].GetUInt32());
Tokenizer bonusListIDs(fields[16].GetString(), ' ');
Tokenizer bonusListIDs(fields[20].GetString(), ' ');
for (char const* token : bonusListIDs)
{
uint32 bonusListID = atoul(token);
+17 -12
View File
@@ -27,6 +27,7 @@
#include "Battleground.h"
#include "BattlegroundMgr.h"
#include "BattlegroundScore.h"
#include "BattlePetMgr.h"
#include "CellImpl.h"
#include "ChannelMgr.h"
#include "CharacterDatabaseCleaner.h"
@@ -13699,10 +13700,10 @@ void Player::SendNewItem(Item* item, uint32 quantity, bool pushed, bool created,
packet.Quantity = quantity;
packet.QuantityInInventory = GetItemCount(item->GetEntry());
//packet.DungeonEncounterID;
//packet.BattlePetBreedID;
//packet.BattlePetBreedQuality;
//packet.BattlePetSpeciesID;
//packet.BattlePetLevel;
packet.BattlePetBreedID = item->GetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA) & 0xFFFFFF;
packet.BattlePetBreedQuality = (item->GetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA) >> 24) & 0xFF;
packet.BattlePetSpeciesID = item->GetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID);
packet.BattlePetLevel = item->GetModifier(ITEM_MODIFIER_BATTLE_PET_LEVEL);
packet.ItemGUID = item->GetGUID();
@@ -17650,8 +17651,10 @@ void Player::LoadCorpse()
void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
{
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// SELECT ii.guid, ii.itemEntry, ii.creatorGuid, ii.giftCreatorGuid, ii.count, ii.duration, ii.charges, ii.flags, ii.enchantments, ii.randomPropertyId, ii.durability, ii.playedTime, ii.text, ii.transmogrification, ii.upgradeId, ii.enchantIllusion, ii.bonusListIDs, bag, slot FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid WHERE ci.guid = ? ORDER BY bag, slot
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
// SELECT ii.guid, ii.itemEntry, ii.creatorGuid, ii.giftCreatorGuid, ii.count, ii.duration, ii.charges, ii.flags, ii.enchantments, ii.randomPropertyId, ii.durability, ii.playedTime, ii.text, ii.transmogrification, ii.upgradeId
// 15 16 17 18 19 20 21 22
// ii.enchantIllusion, battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, ii.bonusListIDs, bag, slot FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid WHERE ci.guid = ? ORDER BY bag, slot
//NOTE: the "order by `bag`" is important because it makes sure
//the bagMap is filled before items in the bags are loaded
//NOTE2: the "order by `slot`" is needed because mainhand weapons are (wrongly?)
@@ -17673,8 +17676,8 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
Field* fields = result->Fetch();
if (Item* item = _LoadItem(trans, zoneId, timeDiff, fields))
{
ObjectGuid bagGuid = fields[17].GetUInt64() ? ObjectGuid::Create<HighGuid::Item>(fields[17].GetUInt64()) : ObjectGuid::Empty;
uint8 slot = fields[18].GetUInt8();
ObjectGuid bagGuid = fields[21].GetUInt64() ? ObjectGuid::Create<HighGuid::Item>(fields[21].GetUInt64()) : ObjectGuid::Empty;
uint8 slot = fields[22].GetUInt8();
uint8 err = EQUIP_ERR_OK;
// Item is not in bag
@@ -17995,7 +17998,7 @@ void Player::_LoadMailedItems(Mail* mail)
Item* item = NewItemOrBag(proto);
ObjectGuid ownerGuid = fields[17].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[17].GetUInt64()) : ObjectGuid::Empty;
ObjectGuid ownerGuid = fields[21].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[21].GetUInt64()) : ObjectGuid::Empty;
if (!item->LoadFromDB(itemGuid, ownerGuid, fields, itemEntry))
{
TC_LOG_ERROR("entities.player", "Player::_LoadMailedItems - Item in mail (%u) doesn't exist !!!! - item guid: " UI64FMTD ", deleted from mail", mail->messageID, itemGuid);
@@ -19188,9 +19191,11 @@ void Player::SaveToDB(bool create /*=false*/)
CharacterDatabase.CommitTransaction(trans);
SQLTransaction transLogin = LoginDatabase.BeginTransaction();
GetSession()->SaveAccountToys(transLogin);
LoginDatabase.CommitTransaction(transLogin);
// TODO: Move this out
trans = LoginDatabase.BeginTransaction();
GetSession()->SaveAccountToys(trans);
GetSession()->GetBattlePetMgr()->SaveToDB(trans);
LoginDatabase.CommitTransaction(trans);
// save pet (hunter pet level and experience and all type pets health/mana).
if (Pet* pet = GetPet())
+1 -1
View File
@@ -532,7 +532,7 @@ enum PlayerFlags
PLAYER_FLAGS_UNK21 = 0x00200000,
PLAYER_FLAGS_COMMENTATOR2 = 0x00400000,
PLAYER_ALLOW_ONLY_ABILITY = 0x00800000, // used by bladestorm and killing spree, allowed only spells with SPELL_ATTR0_REQ_AMMO, SPELL_EFFECT_ATTACK, checked only for active player
PLAYER_FLAGS_UNK24 = 0x01000000, // disabled all melee ability on tab include autoattack
PLAYER_FLAGS_PET_BATTLES_UNLOCKED = 0x01000000, // enables pet battles
PLAYER_FLAGS_NO_XP_GAIN = 0x02000000,
PLAYER_FLAGS_UNK26 = 0x04000000,
PLAYER_FLAGS_AUTO_DECLINE_GUILD = 0x08000000, // Automatically declines guild invites
+2 -2
View File
@@ -368,7 +368,7 @@ void Guild::BankTab::LoadFromDB(Field* fields)
bool Guild::BankTab::LoadItemFromDB(Field* fields)
{
uint8 slotId = fields[19].GetUInt8();
uint8 slotId = fields[23].GetUInt8();
ObjectGuid::LowType itemGuid = fields[0].GetUInt64();
uint32 itemEntry = fields[1].GetUInt32();
if (slotId >= GUILD_BANK_MAX_SLOTS)
@@ -2395,7 +2395,7 @@ void Guild::LoadBankTabFromDB(Field* fields)
bool Guild::LoadBankItemFromDB(Field* fields)
{
uint8 tabId = fields[18].GetUInt8();
uint8 tabId = fields[22].GetUInt8();
if (tabId >= _GetPurchasedTabsSize())
{
TC_LOG_ERROR("guild", "Invalid tab for item (GUID: %u, id: #%u) in guild bank, skipped.",
+5 -5
View File
@@ -395,10 +395,10 @@ void GuildMgr::LoadGuilds()
// Delete orphan guild bank items
CharacterDatabase.DirectExecute("DELETE gbi FROM guild_bank_item gbi LEFT JOIN guild g ON gbi.guildId = g.guildId WHERE g.guildId IS NULL");
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, transmogrification, upgradeId, enchantIllusion, bonusListIDs,
// 17 18 19
// guildid, TabId, SlotId FROM guild_bank_item gbi INNER JOIN item_instance ii ON gbi.item_guid = ii.guid
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, transmogrification, upgradeId, enchantIllusion,
// 17 18 19 20 21 22 23
// battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, guildid, TabId, SlotId FROM guild_bank_item gbi INNER JOIN item_instance ii ON gbi.item_guid = ii.guid
PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_BANK_ITEMS));
if (!result)
@@ -411,7 +411,7 @@ void GuildMgr::LoadGuilds()
do
{
Field* fields = result->Fetch();
uint64 guildId = fields[17].GetUInt64();
uint64 guildId = fields[21].GetUInt64();
if (Guild* guild = GetGuildById(guildId))
guild->LoadBankItemFromDB(fields);
@@ -0,0 +1,80 @@
/*
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "WorldSession.h"
#include "BattlePetMgr.h"
#include "BattlePetPackets.h"
#include "Player.h"
void WorldSession::HandleBattlePetRequestJournal(WorldPackets::BattlePet::BattlePetRequestJournal& /*battlePetRequestJournal*/)
{
// TODO: Move this to BattlePetMgr::SendJournal() just to have all packets in one file
WorldPackets::BattlePet::BattlePetJournal battlePetJournal;
battlePetJournal.Trap = GetBattlePetMgr()->GetTrapLevel();
for (auto itr : GetBattlePetMgr()->GetLearnedPets())
battlePetJournal.Pets.push_back(itr.PacketInfo);
battlePetJournal.Slots = GetBattlePetMgr()->GetSlots();
SendPacket(battlePetJournal.Write());
}
void WorldSession::HandleBattlePetSetBattleSlot(WorldPackets::BattlePet::BattlePetSetBattleSlot& battlePetSetBattleSlot)
{
if (BattlePetMgr::BattlePet* pet = GetBattlePetMgr()->GetPet(battlePetSetBattleSlot.PetGuid))
GetBattlePetMgr()->GetSlot(battlePetSetBattleSlot.Slot)->Pet = pet->PacketInfo;
}
void WorldSession::HandleBattlePetModifyName(WorldPackets::BattlePet::BattlePetModifyName& battlePetModifyName)
{
if (BattlePetMgr::BattlePet* pet = GetBattlePetMgr()->GetPet(battlePetModifyName.PetGuid))
{
pet->PacketInfo.Name = battlePetModifyName.Name;
if (pet->SaveInfo != BATTLE_PET_NEW)
pet->SaveInfo = BATTLE_PET_CHANGED;
}
}
void WorldSession::HandleBattlePetDeletePet(WorldPackets::BattlePet::BattlePetDeletePet& battlePetDeletePet)
{
GetBattlePetMgr()->RemovePet(battlePetDeletePet.PetGuid);
}
void WorldSession::HandleBattlePetSetFlags(WorldPackets::BattlePet::BattlePetSetFlags& battlePetSetFlags)
{
if (BattlePetMgr::BattlePet* pet = GetBattlePetMgr()->GetPet(battlePetSetFlags.PetGuid))
{
if (battlePetSetFlags.ControlType == 2) // 2 - apply
pet->PacketInfo.Flags |= battlePetSetFlags.Flags;
else // 3 - remove
pet->PacketInfo.Flags &= ~battlePetSetFlags.Flags;
if (pet->SaveInfo != BATTLE_PET_NEW)
pet->SaveInfo = BATTLE_PET_CHANGED;
}
}
void WorldSession::HandleCageBattlePet(WorldPackets::BattlePet::CageBattlePet& cageBattlePet)
{
GetBattlePetMgr()->CageBattlePet(cageBattlePet.PetGuid);
}
void WorldSession::HandleBattlePetSummon(WorldPackets::BattlePet::BattlePetSummon& battlePetSummon)
{
GetBattlePetMgr()->SummonPet(battlePetSummon.PetGuid);
}
@@ -22,6 +22,7 @@
#include "AuthenticationPackets.h"
#include "Battleground.h"
#include "BattlenetServerManager.h"
#include "BattlePetPackets.h"
#include "CalendarMgr.h"
#include "CharacterPackets.h"
#include "Chat.h"
@@ -985,6 +986,10 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
hotfixInfo.Hotfixes = sDB2Manager.GetHotfixData();
SendPacket(hotfixInfo.Write());
// TODO: Move this to BattlePetMgr::SendJournalLock() just to have all packets in one file
WorldPackets::BattlePet::BattlePetJournalLockAcquired lock;
SendPacket(lock.Write());
pCurrChar->SendInitialPacketsBeforeAddToMap();
//Show cinematic at the first time that player login
+19
View File
@@ -27,6 +27,7 @@
#include "DB2Stores.h"
#include "NPCPackets.h"
#include "ItemPackets.h"
#include "BattlePetMgr.h"
void WorldSession::HandleSplitItemOpcode(WorldPackets::Item::SplitItem& splitItem)
{
@@ -1264,3 +1265,21 @@ bool WorldSession::CanUseBank(ObjectGuid bankerGUID) const
return true;
}
void WorldSession::HandleUseCritterItem(WorldPackets::Item::UseCritterItem& useCritterItem)
{
Item* item = _player->GetItemByGuid(useCritterItem.ItemGuid);
if (!item)
return;
ItemToBattlePetSpeciesEntry const* itemToBattlePetSpecies = sItemToBattlePetSpeciesStore.LookupEntry(item->GetEntry());
if (!itemToBattlePetSpecies)
return;
BattlePetSpeciesEntry const* battlePetSpecies = sBattlePetSpeciesStore.LookupEntry(itemToBattlePetSpecies->BattlePetSpeciesID);
if (!battlePetSpecies)
return;
GetBattlePetMgr()->AddPet(battlePetSpecies->ID, battlePetSpecies->CreatureID, BattlePetMgr::RollPetBreed(battlePetSpecies->ID), BattlePetMgr::GetDefaultPetQuality(battlePetSpecies->ID));
_player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true);
}
@@ -0,0 +1,171 @@
/*
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BattlePetPackets.h"
#include "World.h"
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::BattlePet::BattlePetSlot const& slot)
{
data << (slot.Pet.Guid.IsEmpty() ? ObjectGuid::Create<HighGuid::BattlePet>(0) : slot.Pet.Guid);
data << slot.CollarID;
data << slot.Index;
data.WriteBit(slot.Locked);
data.FlushBits();
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::BattlePet::BattlePet const& pet)
{
data << pet.Guid;
data << pet.Species;
data << pet.CreatureID;
data << pet.CollarID;
data << pet.Breed;
data << pet.Level;
data << pet.Exp;
data << pet.Flags;
data << pet.Power;
data << pet.Health;
data << pet.MaxHealth;
data << pet.Speed;
data << pet.Quality;
data.WriteBits(pet.Name.size(), 7);
data.WriteBit(!pet.Owner.IsEmpty()); // HasOwnerInfo
data.WriteBit(pet.Name.empty()); // NoRename
data.FlushBits();
if (!pet.Owner.IsEmpty())
{
data << pet.Owner;
data << GetVirtualRealmAddress(); // Virtual
data << GetVirtualRealmAddress(); // Native
}
data.WriteString(pet.Name);
return data;
}
WorldPacket const* WorldPackets::BattlePet::BattlePetJournal::Write()
{
_worldPacket << Trap;
_worldPacket << Slots.size();
_worldPacket << Pets.size();
for (auto const& slot : Slots)
_worldPacket << slot;
for (auto const& pet : Pets)
_worldPacket << pet;
_worldPacket.WriteBit(1); // HasJournalLock
_worldPacket.FlushBits();
return &_worldPacket;
}
WorldPacket const* WorldPackets::BattlePet::BattlePetUpdates::Write()
{
_worldPacket << Pets.size();
for (auto const& pet : Pets)
_worldPacket << pet;
_worldPacket.WriteBit(PetAdded);
_worldPacket.FlushBits();
return &_worldPacket;
}
WorldPacket const* WorldPackets::BattlePet::PetBattleSlotUpdates::Write()
{
_worldPacket << Slots.size();
for (auto const& slot : Slots)
_worldPacket << slot;
_worldPacket.WriteBit(NewSlot);
_worldPacket.WriteBit(AutoSlotted);
_worldPacket.FlushBits();
return &_worldPacket;
}
void WorldPackets::BattlePet::BattlePetSetBattleSlot::Read()
{
_worldPacket >> PetGuid;
_worldPacket >> Slot;
}
void WorldPackets::BattlePet::BattlePetModifyName::Read()
{
_worldPacket >> PetGuid;
uint32 nameLength = _worldPacket.ReadBits(7);
bool hasDeclinedNames = _worldPacket.ReadBit();
Name = _worldPacket.ReadString(nameLength);
if (hasDeclinedNames)
{
uint8 declinedNameLengths[MAX_DECLINED_NAME_CASES];
for (uint8 i = 0; i < 5; ++i)
declinedNameLengths[i] = _worldPacket.ReadBits(7);
for (uint8 i = 0; i < 5; ++i)
Declined.name[i] = _worldPacket.ReadString(declinedNameLengths[i]);
}
}
void WorldPackets::BattlePet::BattlePetDeletePet::Read()
{
_worldPacket >> PetGuid;
}
void WorldPackets::BattlePet::BattlePetSetFlags::Read()
{
_worldPacket >> PetGuid;
_worldPacket >> Flags;
ControlType = _worldPacket.ReadBits(2);
}
void WorldPackets::BattlePet::CageBattlePet::Read()
{
_worldPacket >> PetGuid;
}
WorldPacket const* WorldPackets::BattlePet::BattlePetDeleted::Write()
{
_worldPacket << PetGuid;
return &_worldPacket;
}
WorldPacket const* WorldPackets::BattlePet::BattlePetError::Write()
{
_worldPacket.WriteBits(Result, 4);
_worldPacket.FlushBits();
_worldPacket << CreatureID;
return &_worldPacket;
}
void WorldPackets::BattlePet::BattlePetSummon::Read()
{
_worldPacket >> PetGuid;
}
@@ -0,0 +1,194 @@
/*
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BattlePetPackets_h__
#define BattlePetPackets_h__
#include "Packet.h"
#include "ObjectGuid.h"
namespace WorldPackets
{
namespace BattlePet
{
struct BattlePet
{
ObjectGuid Guid;
uint32 Species = 0;
uint32 CreatureID = 0;
uint32 CollarID = 0; // what's this?
uint16 Breed = 0;
uint16 Level = 0;
uint16 Exp = 0;
uint16 Flags = 0;
uint32 Power = 0;
uint32 Health = 0;
uint32 MaxHealth = 0;
uint32 Speed = 0;
uint8 Quality = 0;
ObjectGuid Owner; // for non-account wide pets only? (Guild Page, Guild Herald)
std::string Name;
};
struct BattlePetSlot
{
BattlePet Pet;
uint32 CollarID = 0; // what's this?
uint8 Index = 0;
bool Locked = true;
};
class BattlePetJournal final : public ServerPacket
{
public:
BattlePetJournal() : ServerPacket(SMSG_BATTLE_PET_JOURNAL) { }
WorldPacket const* Write() override;
uint16 Trap = 0;
std::vector<BattlePetSlot> Slots;
std::vector<BattlePet> Pets;
};
class BattlePetJournalLockAcquired final : public ServerPacket
{
public:
BattlePetJournalLockAcquired() : ServerPacket(SMSG_BATTLE_PET_JOURNAL_LOCK_ACQUIRED, 0) { }
WorldPacket const* Write() override { return &_worldPacket; }
};
class BattlePetRequestJournal final : public ClientPacket
{
public:
BattlePetRequestJournal(WorldPacket&& packet) : ClientPacket(CMSG_BATTLE_PET_REQUEST_JOURNAL, std::move(packet)) { }
void Read() override { }
};
class BattlePetUpdates final : public ServerPacket
{
public:
BattlePetUpdates() : ServerPacket(SMSG_BATTLE_PET_UPDATES) { }
WorldPacket const* Write() override;
std::vector<BattlePet> Pets;
bool PetAdded = false;
};
class PetBattleSlotUpdates final : public ServerPacket
{
public:
PetBattleSlotUpdates() : ServerPacket(SMSG_PET_BATTLE_SLOT_UPDATES) { }
WorldPacket const* Write() override;
std::vector<BattlePetSlot> Slots;
bool AutoSlotted = false;
bool NewSlot = false;
};
class BattlePetSetBattleSlot final : public ClientPacket
{
public:
BattlePetSetBattleSlot(WorldPacket&& packet) : ClientPacket(CMSG_BATTLE_PET_SET_BATTLE_SLOT, std::move(packet)) { }
void Read() override;
ObjectGuid PetGuid;
uint8 Slot = 0;
};
class BattlePetModifyName final : public ClientPacket
{
public:
BattlePetModifyName(WorldPacket&& packet) : ClientPacket(CMSG_BATTLE_PET_MODIFY_NAME, std::move(packet)) { }
void Read() override;
ObjectGuid PetGuid;
std::string Name;
DeclinedName Declined;
};
class BattlePetDeletePet final : public ClientPacket
{
public:
BattlePetDeletePet(WorldPacket&& packet) : ClientPacket(CMSG_BATTLE_PET_DELETE_PET, std::move(packet)) { }
void Read() override;
ObjectGuid PetGuid;
};
class BattlePetSetFlags final : public ClientPacket
{
public:
BattlePetSetFlags(WorldPacket&& packet) : ClientPacket(CMSG_BATTLE_PET_SET_FLAGS, std::move(packet)) { }
void Read() override;
ObjectGuid PetGuid;
uint32 Flags = 0;
uint8 ControlType = 0;
};
class CageBattlePet final : public ClientPacket
{
public:
CageBattlePet(WorldPacket&& packet) : ClientPacket(CMSG_CAGE_BATTLE_PET, std::move(packet)) { }
void Read() override;
ObjectGuid PetGuid;
};
class BattlePetDeleted final : public ServerPacket
{
public:
BattlePetDeleted() : ServerPacket(SMSG_BATTLE_PET_DELETED, 16) { }
WorldPacket const* Write() override;
ObjectGuid PetGuid;
};
class BattlePetError final : public ServerPacket
{
public:
BattlePetError() : ServerPacket(SMSG_BATTLE_PET_ERROR, 5) { }
WorldPacket const* Write() override;
uint8 Result = 0;
uint32 CreatureID = 0;
};
class BattlePetSummon final : public ClientPacket
{
public:
BattlePetSummon(WorldPacket&& packet) : ClientPacket(CMSG_BATTLE_PET_SUMMON, std::move(packet)) { }
void Read() override;
ObjectGuid PetGuid;
};
}
}
#endif // BattlePetPackets_h__
@@ -461,3 +461,8 @@ void WorldPackets::Item::TransmogrifyItems::Read()
for (TransmogrifyItem& item : Items)
_worldPacket >> item;
}
void WorldPackets::Item::UseCritterItem::Read()
{
_worldPacket >> ItemGuid;
}
@@ -428,6 +428,16 @@ namespace WorldPackets
Array<TransmogrifyItem, MAX_TRANSMOGRIFY_ITEMS> Items;
};
class UseCritterItem final : public ClientPacket
{
public:
UseCritterItem(WorldPacket&& packet) : ClientPacket(CMSG_USE_CRITTER_ITEM, std::move(packet)) { }
void Read() override;
ObjectGuid ItemGuid;
};
ByteBuffer& operator>>(ByteBuffer& data, InvUpdate& invUpdate);
}
}
+15 -14
View File
@@ -22,6 +22,7 @@
#include "Packets/AuctionHousePackets.h"
#include "Packets/BankPackets.h"
#include "Packets/BattlegroundPackets.h"
#include "Packets/BattlePetPackets.h"
#include "Packets/BlackMarketPackets.h"
#include "Packets/CalendarPackets.h"
#include "Packets/ChannelPackets.h"
@@ -205,14 +206,14 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_BATTLE_PAY_GET_PURCHASE_LIST, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BATTLE_PAY_START_PURCHASE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BATTLE_PAY_START_VAS_PURCHASE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BATTLE_PET_DELETE_PET, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BATTLE_PET_DELETE_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::BattlePet::BattlePetDeletePet, &WorldSession::HandleBattlePetDeletePet);
DEFINE_HANDLER(CMSG_BATTLE_PET_DELETE_PET_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BATTLE_PET_MODIFY_NAME, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BATTLE_PET_REQUEST_JOURNAL, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BATTLE_PET_MODIFY_NAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::BattlePet::BattlePetModifyName, &WorldSession::HandleBattlePetModifyName);
DEFINE_HANDLER(CMSG_BATTLE_PET_REQUEST_JOURNAL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::BattlePet::BattlePetRequestJournal, &WorldSession::HandleBattlePetRequestJournal);
DEFINE_HANDLER(CMSG_BATTLE_PET_REQUEST_JOURNAL_LOCK, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BATTLE_PET_SET_BATTLE_SLOT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BATTLE_PET_SET_FLAGS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BATTLE_PET_SUMMON, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BATTLE_PET_SET_BATTLE_SLOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::BattlePet::BattlePetSetBattleSlot, &WorldSession::HandleBattlePetSetBattleSlot);
DEFINE_HANDLER(CMSG_BATTLE_PET_SET_FLAGS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::BattlePet::BattlePetSetFlags, &WorldSession::HandleBattlePetSetFlags);
DEFINE_HANDLER(CMSG_BATTLE_PET_SUMMON, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::BattlePet::BattlePetSummon, &WorldSession::HandleBattlePetSummon);
DEFINE_HANDLER(CMSG_BATTLE_PET_UPDATE_NOTIFY, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BEGIN_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::BeginTrade, &WorldSession::HandleBeginTradeOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_BF_MGR_ENTRY_INVITE_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleBfEntryInviteResponse );
@@ -231,7 +232,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_BUY_REAGENT_BANK, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BUY_WOW_TOKEN_CONFIRM, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_BUY_WOW_TOKEN_START, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_CAGE_BATTLE_PET, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_CAGE_BATTLE_PET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::BattlePet::CageBattlePet, &WorldSession::HandleCageBattlePet);
DEFINE_HANDLER(CMSG_CALENDAR_ADD_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Calendar::CalendarAddEvent, &WorldSession::HandleCalendarAddEvent);
DEFINE_OPCODE_HANDLER_OLD(CMSG_CALENDAR_COMPLAIN, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarComplain );
DEFINE_HANDLER(CMSG_CALENDAR_COPY_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Calendar::CalendarCopyEvent, &WorldSession::HandleCalendarCopyEvent);
@@ -813,7 +814,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_UPGRADE_GARRISON, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_UPGRADE_ITEM, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_USED_FOLLOW, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_USE_CRITTER_ITEM, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_USE_CRITTER_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::UseCritterItem, &WorldSession::HandleUseCritterItem);
DEFINE_HANDLER(CMSG_USE_EQUIPMENT_SET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::EquipmentSet::UseEquipmentSet, &WorldSession::HandleUseEquipmentSet);
DEFINE_HANDLER(CMSG_USE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::UseItem, &WorldSession::HandleUseItemOpcode);
DEFINE_HANDLER(CMSG_USE_TOY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Toy::UseToy, &WorldSession::HandleUseToy);
@@ -916,16 +917,16 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PAY_START_PURCHASE_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PETS_HEALED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_CAGE_DATE_ERROR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_DELETED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_ERROR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_JOURNAL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_JOURNAL_LOCK_ACQUIRED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_DELETED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_ERROR, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_JOURNAL, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_JOURNAL_LOCK_ACQUIRED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_JOURNAL_LOCK_DENIED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_LICENSE_CHANGED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_RESTORED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_REVOKED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_TRAP_LEVEL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_UPDATES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_UPDATES, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BF_MGR_DROP_TIMER_CANCELLED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BF_MGR_DROP_TIMER_STARTED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BF_MGR_EJECTED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1458,7 +1459,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_BATTLE_REPLACEMENTS_MADE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_BATTLE_REQUEST_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_BATTLE_ROUND_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_BATTLE_SLOT_UPDATES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_BATTLE_SLOT_UPDATES, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_CAST_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_CLEAR_SPELLS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_DISMISS_SOUND, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+16 -1
View File
@@ -48,6 +48,7 @@
#include "ClientConfigPackets.h"
#include "MiscPackets.h"
#include "ChatPackets.h"
#include "BattlePetMgr.h"
#include "PacketUtilities.h"
#include <zlib.h>
@@ -130,7 +131,8 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccoun
_RBACData(NULL),
expireTime(60000), // 1 min after socket loss, session is deleted
forceExit(false),
m_currentBankerGUID()
m_currentBankerGUID(),
_battlePetMgr(Trinity::make_unique<BattlePetMgr>(this))
{
memset(_tutorials, 0, sizeof(_tutorials));
@@ -1191,6 +1193,8 @@ public:
enum
{
GLOBAL_ACCOUNT_TOYS = 0,
BATTLE_PETS,
BATTLE_PET_SLOTS,
MAX_QUERIES
};
@@ -1205,6 +1209,14 @@ public:
stmt->setUInt32(0, battlenetAccountId);
ok = SetPreparedQuery(GLOBAL_ACCOUNT_TOYS, stmt) && ok;
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BATTLE_PETS);
stmt->setUInt32(0, battlenetAccountId);
ok = SetPreparedQuery(BATTLE_PETS, stmt) && ok;
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BATTLE_PET_SLOTS);
stmt->setUInt32(0, battlenetAccountId);
ok = SetPreparedQuery(BATTLE_PET_SLOTS, stmt) && ok;
return ok;
}
};
@@ -1252,6 +1264,9 @@ void WorldSession::InitializeSessionCallback(SQLQueryHolder* realmHolder, SQLQue
SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
SendTutorialsData();
_battlePetMgr->LoadFromDB(holder->GetPreparedResult(AccountInfoQueryHolder::BATTLE_PETS),
holder->GetPreparedResult(AccountInfoQueryHolder::BATTLE_PET_SLOTS));
delete realmHolder;
delete holder;
}
+28
View File
@@ -33,6 +33,7 @@
#include "AccountMgr.h"
#include <unordered_set>
class BattlePetMgr;
class Channel;
class Creature;
class GameObject;
@@ -117,6 +118,17 @@ namespace WorldPackets
class ReportPvPPlayerAFK;
}
namespace BattlePet
{
class BattlePetRequestJournal;
class BattlePetSetBattleSlot;
class BattlePetModifyName;
class BattlePetDeletePet;
class BattlePetSetFlags;
class BattlePetSummon;
class CageBattlePet;
}
namespace BlackMarket
{
class BlackMarketOpen;
@@ -320,6 +332,7 @@ namespace WorldPackets
class WrapItem;
class CancelTempEnchantment;
class TransmogrifyItems;
class UseCritterItem;
}
namespace Loot
@@ -987,6 +1000,9 @@ class WorldSession
uint32 GetRecruiterId() const { return recruiterId; }
bool IsARecruiter() const { return isRecruiter; }
// Battle Pets
BattlePetMgr* GetBattlePetMgr() const { return _battlePetMgr.get(); }
public: // opcodes handlers
void Handle_NULL(WorldPackets::Null& null); // not used
@@ -1306,6 +1322,7 @@ class WorldSession
void HandleSwapItem(WorldPackets::Item::SwapItem& swapItem);
void HandleBuybackItem(WorldPackets::Item::BuyBackItem& packet);
void HandleWrapItem(WorldPackets::Item::WrapItem& packet);
void HandleUseCritterItem(WorldPackets::Item::UseCritterItem& packet);
void HandleAttackSwingOpcode(WorldPackets::Combat::AttackSwing& packet);
void HandleAttackStopOpcode(WorldPackets::Combat::AttackStop& packet);
@@ -1581,6 +1598,15 @@ class WorldSession
void HandleGarrisonRequestBlueprintAndSpecializationData(WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationData& garrisonRequestBlueprintAndSpecializationData);
void HandleGarrisonGetBuildingLandmarks(WorldPackets::Garrison::GarrisonGetBuildingLandmarks& garrisonGetBuildingLandmarks);
// Battle Pets
void HandleBattlePetRequestJournal(WorldPackets::BattlePet::BattlePetRequestJournal& battlePetRequestJournal);
void HandleBattlePetSetBattleSlot(WorldPackets::BattlePet::BattlePetSetBattleSlot& battlePetSetBattleSlot);
void HandleBattlePetModifyName(WorldPackets::BattlePet::BattlePetModifyName& battlePetModifyName);
void HandleBattlePetDeletePet(WorldPackets::BattlePet::BattlePetDeletePet& battlePetDeletePet);
void HandleBattlePetSetFlags(WorldPackets::BattlePet::BattlePetSetFlags& battlePetSetFlags);
void HandleBattlePetSummon(WorldPackets::BattlePet::BattlePetSummon& battlePetSummon);
void HandleCageBattlePet(WorldPackets::BattlePet::CageBattlePet& cageBattlePet);
private:
void InitializeQueryCallbackParameters();
void ProcessQueryCallbacks();
@@ -1694,6 +1720,8 @@ class WorldSession
ObjectGuid m_currentBankerGUID;
ToyBoxContainer _toys;
std::unique_ptr<BattlePetMgr> _battlePetMgr;
WorldSession(WorldSession const& right) = delete;
WorldSession& operator=(WorldSession const& right) = delete;
};
+3
View File
@@ -434,6 +434,9 @@ class Spell
void EffectCreateGarrison(SpellEffIndex effIndex);
void EffectAddGarrisonFollower(SpellEffIndex effIndex);
void EffectActivateGarrisonBuilding(SpellEffIndex effIndex);
void EffectHealBattlePetPct(SpellEffIndex effIndex);
void EffectEnableBattlePets(SpellEffIndex effIndex);
void EffectUncageBattlePet(SpellEffIndex effIndex);
typedef std::set<Aura*> UsedSpellMods;
+102 -3
View File
@@ -56,6 +56,7 @@
#include "Guild.h"
#include "ReputationMgr.h"
#include "AreaTrigger.h"
#include "BattlePetMgr.h"
#include "Garrison.h"
#include "CombatLogPackets.h"
#include "DuelPackets.h"
@@ -256,7 +257,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectNULL, //189 SPELL_EFFECT_LOOT
&Spell::EffectNULL, //190 SPELL_EFFECT_190
&Spell::EffectNULL, //191 SPELL_EFFECT_TELEPORT_TO_DIGSITE
&Spell::EffectNULL, //192 SPELL_EFFECT_UNCAGE_BATTLEPET
&Spell::EffectUncageBattlePet, //192 SPELL_EFFECT_UNCAGE_BATTLEPET
&Spell::EffectNULL, //193 SPELL_EFFECT_START_PET_BATTLE
&Spell::EffectNULL, //194 SPELL_EFFECT_194
&Spell::EffectNULL, //195 SPELL_EFFECT_195
@@ -264,8 +265,8 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectNULL, //197 SPELL_EFFECT_197
&Spell::EffectNULL, //198 SPELL_EFFECT_198
&Spell::EffectNULL, //199 SPELL_EFFECT_199
&Spell::EffectNULL, //200 SPELL_EFFECT_HEAL_BATTLEPET_PCT
&Spell::EffectNULL, //201 SPELL_EFFECT_ENABLE_BATTLE_PETS
&Spell::EffectHealBattlePetPct, //200 SPELL_EFFECT_HEAL_BATTLEPET_PCT
&Spell::EffectEnableBattlePets, //201 SPELL_EFFECT_ENABLE_BATTLE_PETS
&Spell::EffectNULL, //202 SPELL_EFFECT_202
&Spell::EffectNULL, //203 SPELL_EFFECT_203
&Spell::EffectNULL, //204 SPELL_EFFECT_CHANGE_BATTLEPET_QUALITY
@@ -2259,6 +2260,22 @@ void Spell::EffectLearnSpell(SpellEffIndex effIndex)
uint32 spellToLearn = (m_spellInfo->Id == 483 || m_spellInfo->Id == 55884) ? damage : effectInfo->TriggerSpell;
player->LearnSpell(spellToLearn, false);
if (m_spellInfo->Id == 55884)
{
if (BattlePetMgr* battlePetMgr = player->GetSession()->GetBattlePetMgr())
{
for (auto entry : sBattlePetSpeciesStore)
{
if (entry->SummonSpellID == spellToLearn)
{
battlePetMgr->AddPet(entry->ID, entry->CreatureID, BattlePetMgr::RollPetBreed(entry->ID), BattlePetMgr::GetDefaultPetQuality(entry->ID));
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT);
break;
}
}
}
}
TC_LOG_DEBUG("spells", "Spell: %s has learned spell %u from %s", player->GetGUID().ToString().c_str(), spellToLearn, m_caster->GetGUID().ToString().c_str());
}
@@ -5861,3 +5878,85 @@ void Spell::EffectActivateGarrisonBuilding(SpellEffIndex effIndex)
if (Garrison* garrison = unitTarget->ToPlayer()->GetGarrison())
garrison->ActivateBuilding(GetEffect(effIndex)->MiscValue);
}
void Spell::EffectHealBattlePetPct(SpellEffIndex effIndex)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
return;
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
if (BattlePetMgr* battlePetMgr = unitTarget->ToPlayer()->GetSession()->GetBattlePetMgr())
battlePetMgr->HealBattlePetsPct(GetEffect(effIndex)->BasePoints);
}
void Spell::EffectEnableBattlePets(SpellEffIndex /*effIndex*/)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
return;
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
Player* plr = unitTarget->ToPlayer();
plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_PET_BATTLES_UNLOCKED);
plr->GetSession()->GetBattlePetMgr()->UnlockSlot(0);
}
void Spell::EffectUncageBattlePet(SpellEffIndex /*effIndex*/)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
return;
if (!m_CastItem || !m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
return;
Player* plr = m_caster->ToPlayer();
// are we allowed to learn battle pets without it?
/*if (plr->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_PET_BATTLES_UNLOCKED))
return; // send some error*/
uint32 speciesId = m_CastItem->GetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID);
uint16 breed = m_CastItem->GetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA) & 0xFFFFFF;
uint8 quality = (m_CastItem->GetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA) >> 24) & 0xFF;
uint16 level = m_CastItem->GetModifier(ITEM_MODIFIER_BATTLE_PET_LEVEL);
uint32 creatureId = m_CastItem->GetModifier(ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID);
BattlePetSpeciesEntry const* speciesEntry = sBattlePetSpeciesStore.LookupEntry(speciesId);
if (!speciesEntry)
return;
BattlePetMgr* battlePetMgr = plr->GetSession()->GetBattlePetMgr();
if (!battlePetMgr)
return;
uint16 maxLearnedLevel = 0;
for (auto pet : battlePetMgr->GetLearnedPets())
maxLearnedLevel = std::max(pet.PacketInfo.Level, maxLearnedLevel);
// TODO: This means if you put your highest lvl pet into cage, you won't be able to uncage it again which is probably wrong.
// We will need to store maxLearnedLevel somewhere to avoid this behaviour.
if (maxLearnedLevel < level)
{
battlePetMgr->SendError(BATTLEPETRESULT_TOO_HIGH_LEVEL_TO_UNCAGE, creatureId); // or speciesEntry.CreatureID
SendCastResult(SPELL_FAILED_CANT_ADD_BATTLE_PET);
return;
}
if (battlePetMgr->GetPetCount(speciesId) >= MAX_BATTLE_PETS_PER_SPECIES)
{
battlePetMgr->SendError(BATTLEPETRESULT_CANT_HAVE_MORE_PETS_OF_THAT_TYPE, creatureId); // or speciesEntry.CreatureID
SendCastResult(SPELL_FAILED_CANT_ADD_BATTLE_PET);
return;
}
if (!plr->HasSpell(speciesEntry->SummonSpellID))
plr->LearnSpell(speciesEntry->SummonSpellID, false);
battlePetMgr->AddPet(speciesId, creatureId, breed, quality, level);
plr->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true);
m_CastItem = nullptr;
}
+4
View File
@@ -27,6 +27,7 @@
#include "AuctionHouseMgr.h"
#include "BattlefieldMgr.h"
#include "BattlegroundMgr.h"
#include "BattlePetMgr.h"
#include "CalendarMgr.h"
#include "Channel.h"
#include "CharacterDatabaseCleaner.h"
@@ -2026,6 +2027,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading realm names...");
sObjectMgr->LoadRealmNames();
TC_LOG_INFO("server.loading", "Loading battle pets info...");
BattlePetMgr::Initialize();
uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
TC_LOG_INFO("server.worldserver", "World initialized in %u minutes %u seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000));