Merge branch 'master' into 310

Conflicts:
	src/game/Player.cpp
This commit is contained in:
tomrus88 2009-04-12 14:37:33 +04:00
commit 9b20869a32
83 changed files with 623 additions and 581 deletions

View file

@ -21,7 +21,7 @@
DROP TABLE IF EXISTS `character_db_version`;
CREATE TABLE `character_db_version` (
`required_7546_01_characters_uptime` bit(1) default NULL
`required_7644_01_characters_character_pet` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB';
--

View file

@ -22,7 +22,8 @@
DROP TABLE IF EXISTS `db_version`;
CREATE TABLE `db_version` (
`version` varchar(120) default NULL,
`required_7633_01_mangos_achievement_criteria_data` bit(1) default NULL
`creature_ai_version` varchar(120) default NULL,
`required_7643_02_mangos_mangos_string` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
--
@ -32,7 +33,7 @@ CREATE TABLE `db_version` (
LOCK TABLES `db_version` WRITE;
/*!40000 ALTER TABLE `db_version` DISABLE KEYS */;
INSERT INTO `db_version` VALUES
('Mangos default database.',NULL);
('Mangos default database.','Creature EventAI not provided.',NULL);
/*!40000 ALTER TABLE `db_version` ENABLE KEYS */;
UNLOCK TABLES;
@ -2463,6 +2464,7 @@ INSERT INTO `mangos_string` VALUES
(56,'Current Message of the day: \r\n%s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(57,'Using World DB: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(58,'Using script library: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(59,'Using creature EventAI: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(100,'Global notify: ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(101,'Map: %u (%s) Zone: %u (%s) Area: %u (%s) Phase: %u\nX: %f Y: %f Z: %f Orientation: %f\ngrid[%u,%u]cell[%u,%u] InstanceID: %u\n ZoneX: %f ZoneY: %f\nGroundZ: %f FloorZ: %f Have height data (Map: %u VMap: %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(102,'%s is already being teleported.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),

View file

@ -0,0 +1,7 @@
ALTER TABLE db_version CHANGE COLUMN required_7633_01_mangos_achievement_criteria_data required_7643_01_mangos_db_version bit;
ALTER TABLE db_version
ADD COLUMN creature_ai_version varchar(120) default NULL AFTER version;
UPDATE db_version
SET creature_ai_version = 'Mangos default creature EventAI data.';

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_7643_01_mangos_db_version required_7643_02_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry IN(59);
INSERT INTO mangos_string VALUES
(59,'Using creature EventAI: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

View file

@ -0,0 +1,5 @@
ALTER TABLE character_db_version CHANGE COLUMN required_7546_01_characters_uptime required_7644_01_characters_character_pet bit;
/* only hunter pets must be in stable */
UPDATE `character_pet`
SET slot = 100 WHERE PetType <> 1 AND slot >= 1 AND slot <= 4;

View file

@ -25,57 +25,6 @@ pkgdatadir = $(datadir)/mangos/sql/updates
## Files to be installed
# Install basic SQL files to datadir
pkgdata_DATA = \
2008_10_18_01_characters_characters.sql \
2008_10_18_02_mangos_spell_proc_event.sql \
2008_10_19_01_mangos_spell_affect.sql \
2008_10_19_02_mangos_spell_proc_event.sql \
2008_10_21_01_mangos_mangos_string.sql \
2008_10_21_02_mangos_command.sql \
2008_10_21_03_mangos_command.sql \
2008_10_22_01_mangos_quest_template.sql \
2008_10_22_02_mangos_mangos_string.sql \
2008_10_23_01_mangos_command.sql \
2008_10_23_02_mangos_mangos_string.sql \
2008_10_23_03_mangos_mangos_string.sql \
2008_10_23_04_mangos_command.sql \
2008_10_23_05_mangos_command.sql \
2008_10_26_01_mangos_mangos_string.sql \
2008_10_27_01_mangos_npc_option.sql \
2008_10_27_02_mangos_locales_npc_option.sql \
2008_10_28_01_mangos_mangos_string.sql \
2008_10_28_02_mangos_mangos_string.sql \
2008_10_28_03_mangos_command.sql \
2008_10_28_04_mangos_command.sql \
2008_10_29_01_mangos_mangos_string.sql \
2008_10_29_02_mangos_command.sql \
2008_10_29_03_mangos_db_version.sql \
2008_10_29_04_mangos_mangos_string.sql \
2008_10_29_05_mangos_command.sql \
2008_10_31_01_mangos_creature_template.sql \
2008_10_31_02_mangos_mangos_string.sql \
2008_10_31_03_mangos_command.sql \
2008_11_01_01_mangos_mangos_string.sql \
2008_11_01_02_mangos_command.sql \
2008_11_07_01_characters_character_db_version.sql \
2008_11_07_02_realmd_realmd_db_version.sql \
2008_11_07_03_characters_guild_bank_tab.sql \
2008_11_07_04_realmd_account.sql \
2008_11_09_01_mangos_command.sql \
2008_11_09_02_mangos_command.sql \
2008_11_09_03_mangos_mangos_string.sql \
2008_11_11_01_mangos_db_script_string.sql \
2008_11_11_02_mangos_scripts.sql \
2008_11_12_01_character_character_aura.sql \
2008_11_14_01_mangos_scripts.sql \
2008_11_16_01_mangos_command.sql \
2008_11_18_01_mangos_creature_movement.sql \
2008_11_18_02_mangos_mangos_string.sql \
2008_11_27_01_mangos_playercreateinfo_item.sql \
2008_11_29_01_mangos_spell_proc_event.sql \
2008_11_29_02_mangos_spell_elixir.sql \
2008_12_03_01_character_guild_member.sql \
2008_12_15_01_character_arenas.sql \
2008_12_15_01_mangos_arenas.sql \
2008_12_22_01_mangos_creature_equip_template.sql \
2008_12_22_02_characters_character_pet.sql \
2008_12_22_03_mangos_item_template.sql \
@ -219,62 +168,14 @@ pkgdata_DATA = \
7622_03_mangos_creature_ai_texts.sql \
7627_01_mangos_achievement_criteria_data.sql \
7633_01_mangos_achievement_criteria_data.sql \
7643_01_mangos_db_version.sql \
7643_02_mangos_mangos_string.sql \
7644_01_characters_character_pet.sql \
README
## Additional files to include when running 'make dist'
# SQL update files, to upgrade database schema from older revisions
EXTRA_DIST = \
2008_10_18_01_characters_characters.sql \
2008_10_18_02_mangos_spell_proc_event.sql \
2008_10_19_01_mangos_spell_affect.sql \
2008_10_19_02_mangos_spell_proc_event.sql \
2008_10_21_01_mangos_mangos_string.sql \
2008_10_21_02_mangos_command.sql \
2008_10_21_03_mangos_command.sql \
2008_10_22_01_mangos_quest_template.sql \
2008_10_22_02_mangos_mangos_string.sql \
2008_10_23_01_mangos_command.sql \
2008_10_23_02_mangos_mangos_string.sql \
2008_10_23_03_mangos_mangos_string.sql \
2008_10_23_04_mangos_command.sql \
2008_10_23_05_mangos_command.sql \
2008_10_26_01_mangos_mangos_string.sql \
2008_10_27_01_mangos_npc_option.sql \
2008_10_27_02_mangos_locales_npc_option.sql \
2008_10_28_01_mangos_mangos_string.sql \
2008_10_28_02_mangos_mangos_string.sql \
2008_10_28_03_mangos_command.sql \
2008_10_28_04_mangos_command.sql \
2008_10_29_01_mangos_mangos_string.sql \
2008_10_29_02_mangos_command.sql \
2008_10_29_03_mangos_db_version.sql \
2008_10_29_04_mangos_mangos_string.sql \
2008_10_29_05_mangos_command.sql \
2008_10_31_01_mangos_creature_template.sql \
2008_10_31_02_mangos_mangos_string.sql \
2008_10_31_03_mangos_command.sql \
2008_11_01_01_mangos_mangos_string.sql \
2008_11_01_02_mangos_command.sql \
2008_11_07_01_characters_character_db_version.sql \
2008_11_07_02_realmd_realmd_db_version.sql \
2008_11_07_03_characters_guild_bank_tab.sql \
2008_11_07_04_realmd_account.sql \
2008_11_09_01_mangos_command.sql \
2008_11_09_02_mangos_command.sql \
2008_11_09_03_mangos_mangos_string.sql \
2008_11_11_01_mangos_db_script_string.sql \
2008_11_11_02_mangos_scripts.sql \
2008_11_12_01_character_character_aura.sql \
2008_11_14_01_mangos_scripts.sql \
2008_11_16_01_mangos_command.sql \
2008_11_18_01_mangos_creature_movement.sql \
2008_11_18_02_mangos_mangos_string.sql \
2008_11_27_01_mangos_playercreateinfo_item.sql \
2008_11_29_01_mangos_spell_proc_event.sql \
2008_11_29_02_mangos_spell_elixir.sql \
2008_12_03_01_character_guild_member.sql \
2008_12_15_01_character_arenas.sql \
2008_12_15_01_mangos_arenas.sql \
2008_12_22_01_mangos_creature_equip_template.sql \
2008_12_22_02_characters_character_pet.sql \
2008_12_22_03_mangos_item_template.sql \
@ -418,4 +319,7 @@ EXTRA_DIST = \
7622_03_mangos_creature_ai_texts.sql \
7627_01_mangos_achievement_criteria_data.sql \
7633_01_mangos_achievement_criteria_data.sql \
7643_01_mangos_db_version.sql \
7643_02_mangos_mangos_string.sql \
7644_01_characters_character_pet.sql \
README

View file

@ -642,6 +642,10 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
}
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
{
// speedup for non-login case
if(miscvalue1 && miscvalue1 != achievementCriteria->complete_quests_in_zone.zoneID)
continue;
uint32 counter =0;
for(QuestStatusMap::iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr!=GetPlayer()->getQuestStatusMap().end(); itr++)
{
@ -673,14 +677,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
if(!miscvalue1)
continue;
// skip wrong arena achievements, if not achievIdByArenaSlot then normal totla death counter
// skip wrong arena achievements, if not achievIdByArenaSlot then normal total death counter
bool notfit = false;
for(int i = 0; i < MAX_ARENA_SLOT; ++i)
{
if(achievIdByArenaSlot[i] == achievement->ID)
{
BattleGround* bg = GetPlayer()->GetBattleGround();
if(!bg || ArenaTeam::GetSlotByType(bg->GetArenaType())!=i)
if(!bg || !bg->isArena() || ArenaTeam::GetSlotByType(bg->GetArenaType()) != i)
notfit = true;
break;
@ -1057,6 +1061,13 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if(IsCompletedCriteria(achievementCriteria,achievement))
CompletedCriteria(achievementCriteria,achievement);
// check again the completeness for SUMM and REQ COUNT achievements,
// as they don't depend on the completed criteria but on the sum of the progress of each individual criteria
if (achievement->flags & ACHIEVEMENT_FLAG_SUMM)
{
if (IsCompletedAchievement(achievement))
CompletedAchievement(achievement);
}
if(AchievementEntryList const* achRefList = achievementmgr.GetAchievementByReferencedId(achievement->ID))
{
@ -1202,9 +1213,12 @@ void AchievementMgr::CompletedCriteria(AchievementCriteriaEntry const* criteria,
CompletedAchievement(achievement);
}
// TODO: achievement 705 requires 4 criteria to be fulfilled
bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry)
{
// counter can never complete
if(entry->flags & ACHIEVEMENT_FLAG_COUNTER)
return false;
// for achievement with referenced achievement criterias get from referenced and counter from self
uint32 achievmentForTestId = entry->refAchievement ? entry->refAchievement : entry->ID;
uint32 achievmentForTestCount = entry->count;
@ -1212,10 +1226,32 @@ bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry)
AchievementCriteriaEntryList const* cList = achievementmgr.GetAchievementCriteriaByAchievement(achievmentForTestId);
if(!cList)
return false;
uint32 count = 0;
bool completed_all = true;
// For SUMM achievements, we have to count the progress of each criteria of the achievement.
// Oddly, the target count is NOT countained in the achievement, but in each individual criteria
if (entry->flags & ACHIEVEMENT_FLAG_SUMM)
{
for(AchievementCriteriaEntryList::const_iterator itr = cList->begin(); itr != cList->end(); ++itr)
{
AchievementCriteriaEntry const* criteria = *itr;
CriteriaProgressMap::const_iterator itrProgress = m_criteriaProgress.find(criteria->ID);
if(itrProgress == m_criteriaProgress.end())
continue;
CriteriaProgress const* progress = &itrProgress->second;
count += progress->counter;
// for counters, field4 contains the main count requirement
if (count >= criteria->raw.count)
return true;
}
return false;
}
// Default case - need complete all or
bool completed_all = true;
for(AchievementCriteriaEntryList::const_iterator itr = cList->begin(); itr != cList->end(); ++itr)
{
AchievementCriteriaEntry const* criteria = *itr;

View file

@ -943,15 +943,9 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out
bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing)
// summon old pet if there was one and there isn't a current pet
if (!plr->GetPet() && plr->GetTemporaryUnsummonedPetNumber())
{
Pet* NewPet = new Pet;
if (!NewPet->LoadPetFromDB(plr, 0, (plr)->GetTemporaryUnsummonedPetNumber(), true))
delete NewPet;
(plr)->SetTemporaryUnsummonedPetNumber(0);
}
// unsummon current and summon old pet if there was one and there isn't a current pet
plr->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT);
plr->ResummonPetTemporaryUnSummonedIfAny();
if (isRated() && GetStatus() == STATUS_IN_PROGRESS)
{
@ -1105,19 +1099,7 @@ void BattleGround::AddPlayer(Player *plr)
}
plr->DestroyConjuredItems(true);
Pet* pet = plr->GetPet();
if (pet)
{
if (pet->getPetType() == SUMMON_PET || pet->getPetType() == HUNTER_PET)
{
(plr)->SetTemporaryUnsummonedPetNumber(pet->GetCharmInfo()->GetPetNumber());
(plr)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL));
}
(plr)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT);
}
else
(plr)->SetTemporaryUnsummonedPetNumber(0);
plr->UnsummonPetTemporaryIfAny();
if(GetStatus() == STATUS_WAIT_JOIN) // not started yet
{

View file

@ -161,7 +161,7 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ )
"SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, "
// 9 10 11 12 13
"characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid "
"FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='0' "
"FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='%u' "
"LEFT JOIN guild_member ON characters.guid = guild_member.guid "
"WHERE characters.account = '%u' ORDER BY characters.guid"
:
@ -170,11 +170,11 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ )
"SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, "
// 9 10 11 12 13 14
"characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid, genitive "
"FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='0' "
"FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='%u' "
"LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid "
"LEFT JOIN guild_member ON characters.guid = guild_member.guid "
"WHERE characters.account = '%u' ORDER BY characters.guid",
GetAccountId());
PET_SAVE_AS_CURRENT,GetAccountId());
}
void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
@ -797,8 +797,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
SendDoFlight( MountId, path, startNode );
}
// Load pet if any and player is alive and not in taxi flight
if(pCurrChar->isAlive() && pCurrChar->m_taxi.GetTaxiSource()==0)
// Load pet if any (if player not alive and in taxi flight or another then pet will remember as temporary unsummoned)
pCurrChar->LoadPet();
// Set FFA PvP for non GM in non-rest mode

View file

@ -45,25 +45,25 @@ namespace FactorySelector
std::string ainame=cinfo->AIName;
// select by script name
if( !ainame.empty())
ai_factory = ai_registry.GetRegistryItem( ainame.c_str() );
// select by NPC flags
if(!ai_factory)
{
if( creature->isGuard() )
ai_factory = ai_registry.GetRegistryItem("GuardAI");
else if(creature->isPet() || creature->isCharmed())
// select by NPC flags _first_ - otherwise EventAI might be choosen for pets/totems
// excplicit check for isControlled() and owner type to allow guardian, mini-pets and pets controlled by NPCs to be scripted by EventAI
Unit *owner=NULL;
if(creature->isPet() && ((Pet*)creature)->isControlled() && (owner=creature->GetOwner()) && owner->GetTypeId()==TYPEID_PLAYER || creature->isCharmed())
ai_factory = ai_registry.GetRegistryItem("PetAI");
else if(creature->isTotem())
ai_factory = ai_registry.GetRegistryItem("TotemAI");
}
// select by script name
if( !ai_factory && !ainame.empty())
ai_factory = ai_registry.GetRegistryItem( ainame.c_str() );
if(!ai_factory && creature->isGuard() )
ai_factory = ai_registry.GetRegistryItem("GuardAI");
// select by permit check
if(!ai_factory)
{
int best_val = -1;
int best_val = PERMIT_BASE_NO;
typedef CreatureAIRegistry::RegistryMapType RMT;
RMT const &l = ai_registry.GetRegisteredItems();
for( RMT::const_iterator iter = l.begin(); iter != l.end(); ++iter)

View file

@ -476,7 +476,7 @@ struct AchievementCriteriaEntry
struct
{
uint32 field3; // 3 main requirement
uint32 field4; // 4 main requirement count
uint32 count; // 4 main requirement count
uint32 additionalRequirement1_type; // 5 additional requirement 1 type
uint32 additionalRequirement1_value; // 6 additional requirement 1 value
uint32 additionalRequirement2_type; // 7 additional requirement 2 type

View file

@ -82,7 +82,8 @@ enum MangosStrings
LANG_MOTD_CURRENT = 56,
LANG_USING_WORLD_DB = 57,
LANG_USING_SCRIPT_LIB = 58,
// Room for more level 0 59-99 not used
LANG_USING_EVENT_AI = 59,
// Room for more level 0 60-99 not used
// level 1 chat
LANG_GLOBAL_NOTIFY = 100,

View file

@ -100,6 +100,7 @@ bool ChatHandler::HandleServerInfoCommand(const char* /*args*/)
SendSysMessage(full);
PSendSysMessage(LANG_USING_SCRIPT_LIB,sWorld.GetScriptsVersion());
PSendSysMessage(LANG_USING_WORLD_DB,sWorld.GetDBVersion());
PSendSysMessage(LANG_USING_EVENT_AI,sWorld.GetCreatureEventAIVersion());
PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum);
PSendSysMessage(LANG_UPTIME, str.c_str());

View file

@ -362,7 +362,7 @@ bool ChatHandler::HandleNamegoCommand(const char* args)
if (HasLowerSecurity(chr, 0))
return false;
if(chr->IsBeingTeleported()==true)
if(chr->IsBeingTeleported())
{
PSendSysMessage(LANG_IS_TELEPORTED, nameLink.c_str());
SetSentErrorMessage(true);

View file

@ -1671,6 +1671,37 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const
if (x > 1299.0f && x < 1839.0f && y > 10.0f && y < 440.0f) areaflag = 685;
}
break;
// The Makers' Perch (ground) and Makers' Overlook (ground and cave)
case 1335: // Sholazar Basin
// The Makers' Perch ground (fast box)
if (x > 6100.0f && x < 6250.0f && y > 5650.0f && y < 5800.0f)
{
// nice slow circle
if ((x-6183.0f)*(x-6183.0f)+(y-5717.0f)*(y-5717.0f) < 2500.0f)
areaflag = 2189;
}
// Makers' Overlook (ground and cave)
else if (x > 5634.48f && x < 5774.53f && y < 3475.0f && z > 300.0f)
{
if(y > 3380.26f || y > 3265.0f && z < 360.0f) areaflag = 2187;
}
break;
// The Makers' Perch (underground)
case 2147: // The Stormwright's Shelf (Sholazar Basin)
if (x > 6199.0f && x < 6283.0f && y > 5705.0f && y < 5817.0f && z < 38.0f) areaflag = 2189; break;
// Makers' Overlook (deep cave)
case 267: // Icecrown
if (x > 5684.0f && x < 5798.0f && y > 3035.0f && y < 3367.0f && z < 358.0f) areaflag = 2187; break;
// Wyrmrest Temple (Dragonblight)
case 1814: // Path of the Titans (Dragonblight)
case 1897: // The Dragon Wastes (Dragonblight)
// fast box
if (x > 3400.0f && x < 3700.0f && y > 130.0f && y < 420.0f)
{
// nice slow circle
if ((x-3546.87f)*(x-3546.87f)+(y-272.71f)*(y-272.71f) < 19600.0f) areaflag = 1791;
}
break;
}
return areaflag;

View file

@ -1126,22 +1126,6 @@ void WorldSession::HandleMoveRootAck(WorldPacket&/* recv_data*/)
*/
}
void WorldSession::HandleMoveTeleportAck(WorldPacket&/* recv_data*/)
{
/*
CHECK_PACKET_SIZE(recv_data,8+4);
sLog.outDebug("MSG_MOVE_TELEPORT_ACK");
uint64 guid;
uint32 flags, time;
recv_data >> guid;
recv_data >> flags >> time;
DEBUG_LOG("Guid " I64FMTD,guid);
DEBUG_LOG("Flags %u, time %u",flags, time/IN_MILISECONDS);
*/
}
void WorldSession::HandleSetActionBar(WorldPacket& recv_data)
{
CHECK_PACKET_SIZE(recv_data,1);

View file

@ -39,6 +39,10 @@ void WorldSession::HandleMoveWorldportAckOpcode( WorldPacket & /*recv_data*/ )
void WorldSession::HandleMoveWorldportAckOpcode()
{
// ignore unexpected far teleports
if(!GetPlayer()->IsBeingTeleportedFar())
return;
// get the teleport destination
WorldLocation &loc = GetPlayer()->GetTeleportDest();
@ -57,7 +61,7 @@ void WorldSession::HandleMoveWorldportAckOpcode()
if(GetPlayer()->m_InstanceValid == false && !mInstance)
GetPlayer()->m_InstanceValid = true;
GetPlayer()->SetSemaphoreTeleport(false);
GetPlayer()->SetSemaphoreTeleportFar(false);
// relocate the player to the teleport destination
GetPlayer()->SetMapId(loc.mapid);
@ -77,7 +81,6 @@ void WorldSession::HandleMoveWorldportAckOpcode()
{
sLog.outDebug("WORLD: teleport of player %s (%d) to location %d,%f,%f,%f,%f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.x, loc.y, loc.z, loc.o);
// teleport the player home
GetPlayer()->SetDontMove(false);
if(!GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()))
{
// the player must always be able to teleport home
@ -114,7 +117,6 @@ void WorldSession::HandleMoveWorldportAckOpcode()
if(!_player->InBattleGround())
{
// short preparations to continue flight
GetPlayer()->SetDontMove(false);
FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top());
flight->Initialize(*GetPlayer());
return;
@ -155,16 +157,53 @@ void WorldSession::HandleMoveWorldportAckOpcode()
GetPlayer()->CastSpell(GetPlayer(), 2479, true);
// resummon pet
if(GetPlayer()->m_temporaryUnsummonedPetNumber)
{
Pet* NewPet = new Pet;
if(!NewPet->LoadPetFromDB(GetPlayer(), 0, GetPlayer()->m_temporaryUnsummonedPetNumber, true))
delete NewPet;
GetPlayer()->m_temporaryUnsummonedPetNumber = 0;
GetPlayer()->ResummonPetTemporaryUnSummonedIfAny();
}
GetPlayer()->SetDontMove(false);
void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data)
{
CHECK_PACKET_SIZE(recv_data,8+4);
sLog.outDebug("MSG_MOVE_TELEPORT_ACK");
uint64 guid;
uint32 flags, time;
recv_data >> guid;
recv_data >> flags >> time;
DEBUG_LOG("Guid " I64FMTD,guid);
DEBUG_LOG("Flags %u, time %u",flags, time/IN_MILISECONDS);
Unit *mover = _player->m_mover;
Player *plMover = mover->GetTypeId()==TYPEID_PLAYER ? (Player*)mover : NULL;
if(!plMover || !plMover->IsBeingTeleportedNear())
return;
if(guid != plMover->GetGUID())
return;
plMover->SetSemaphoreTeleportNear(false);
uint32 old_zone = plMover->GetZoneId();
WorldLocation const& dest = plMover->GetTeleportDest();
plMover->SetPosition(dest.x, dest.y, dest.z, dest.o, true);
uint32 newzone, newarea;
plMover->GetZoneAndAreaId(newzone,newarea);
plMover->UpdateZone(newzone,newarea);
// new zone
if(old_zone != newzone)
{
// honorless target
if(plMover->pvpInfo.inHostileArea)
plMover->CastSpell(plMover, 2479, true);
}
// resummon pet
GetPlayer()->ResummonPetTemporaryUnSummonedIfAny();
}
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
@ -172,7 +211,11 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
uint32 opcode = recv_data.GetOpcode();
sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
if(GetPlayer()->GetDontMove())
Unit *mover = _player->m_mover;
Player *plMover = mover->GetTypeId()==TYPEID_PLAYER ? (Player*)mover : NULL;
// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
if(plMover && plMover->IsBeingTeleported())
return;
/* extract packet */
@ -190,9 +233,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
if (!MaNGOS::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o))
return;
Unit *mover = _player->m_mover;
Player *plMover = mover->GetTypeId()==TYPEID_PLAYER ? (Player*)mover : NULL;
/* handle special cases */
if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT)
{
@ -256,7 +296,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
plMover->m_movementInfo = movementInfo;
plMover->SetUnitMovementFlags(movementInfo.flags);
plMover->UpdateFallInformationIfNeed(movementInfo,recv_data.GetOpcode());
if(plMover->isMovingOrTurning())
@ -278,11 +317,15 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
if(plMover->isAlive())
{
plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
// pl can be alive if GM/etc
if(!plMover->isAlive())
{
// change the death state to CORPSE to prevent the death timer from
// starting in the next player update
plMover->KillPlayer();
plMover->BuildPlayerRepop();
}
}
// cancel the death timer here if started
plMover->RepopAtGraveyard();

View file

@ -475,7 +475,6 @@ void WorldSession::SendBindPoint(Creature *npc)
_player->PlayerTalkClass->CloseGossip();
}
//Need fix
void WorldSession::HandleListStabledPetsOpcode( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data,8);
@ -508,7 +507,9 @@ void WorldSession::SendStablePet(uint64 guid )
Pet *pet = _player->GetPet();
size_t wpos = data.wpos();
data << uint8(0); // place holder for slot show number
data << uint8(GetPlayer()->m_stableSlots);
uint8 num = 0; // counter for place holder
@ -520,12 +521,13 @@ void WorldSession::SendStablePet(uint64 guid )
data << uint32(pet->GetEntry());
data << uint32(pet->getLevel());
data << pet->GetName(); // petname
data << uint8(0x01); // flags?, client slot 1 == current pet (0)
data << uint8(1); // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show)
++num;
}
// 0 1 2 3 4 5
QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow());
// 0 1 2 3 4
QueryResult* result = CharacterDatabase.PQuery("SELECT owner, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot",
_player->GetGUIDLow(),PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT);
if(result)
{
@ -533,11 +535,11 @@ void WorldSession::SendStablePet(uint64 guid )
{
Field *fields = result->Fetch();
data << uint32(fields[2].GetUInt32()); // petnumber
data << uint32(fields[3].GetUInt32()); // creature entry
data << uint32(fields[4].GetUInt32()); // level
data << fields[5].GetString(); // name
data << uint8(fields[1].GetUInt32()+1); // slot
data << uint32(fields[1].GetUInt32()); // petnumber
data << uint32(fields[2].GetUInt32()); // creature entry
data << uint32(fields[3].GetUInt32()); // level
data << fields[4].GetString(); // name
data << uint8(2); // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show)
++num;
}while( result->NextRow() );
@ -545,7 +547,7 @@ void WorldSession::SendStablePet(uint64 guid )
delete result;
}
data.put<uint8>(8, num); // set real data to placeholder
data.put<uint8>(wpos, num); // set real data to placeholder
SendPacket(&data);
}
@ -586,7 +588,8 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data )
uint32 free_slot = 1;
QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5 ORDER BY slot ",_player->GetGUIDLow());
QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot ",
_player->GetGUIDLow(),PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT);
if(result)
{
do
@ -595,11 +598,16 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data )
uint32 slot = fields[1].GetUInt32();
if(slot==free_slot) // this slot not free
// slots ordered in query, and if not equal then free
if(slot!=free_slot)
break;
// this slot not free, skip
++free_slot;
}while( result->NextRow() );
}
delete result;
}
if( free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots)
{
@ -638,8 +646,7 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
Pet* pet = _player->GetPet();
if(pet && pet->isAlive())
{
uint8 i = 0x06;
data << uint8(i);
data << uint8(0x06);
SendPacket(&data);
return;
}
@ -650,7 +657,8 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
Pet *newpet = NULL;
QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow(),petnumber);
QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot >='%u' AND slot <= '%u'",
_player->GetGUIDLow(),petnumber,PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT);
if(result)
{
Field *fields = result->Fetch();
@ -694,7 +702,7 @@ void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data )
WorldPacket data(SMSG_STABLE_RESULT, 200);
if(GetPlayer()->m_stableSlots < 4) // max slots amount = 4
if(GetPlayer()->m_stableSlots < MAX_PET_STABLES)
{
StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
if(_player->GetMoney() >= SlotPrice->Price)
@ -746,7 +754,8 @@ void WorldSession::HandleStableSwapPet( WorldPacket & recv_data )
return;
// find swapped pet slot in stable
QueryResult *result = CharacterDatabase.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'",_player->GetGUIDLow(),pet_number);
QueryResult *result = CharacterDatabase.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'",
_player->GetGUIDLow(),pet_number);
if(!result)
return;
@ -756,7 +765,7 @@ void WorldSession::HandleStableSwapPet( WorldPacket & recv_data )
uint32 petentry = fields[1].GetUInt32();
delete result;
// move alive pet to slot or delele dead pet
// move alive pet to slot or delete dead pet
_player->RemovePet(pet,pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED);
// summon unstabled pet

View file

@ -1045,8 +1045,7 @@ bool Object::PrintIndexError(uint32 index, bool set) const
WorldObject::WorldObject()
: m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL),
m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f),
mSemaphoreTeleport(false)
m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f)
{
}

View file

@ -445,8 +445,6 @@ class MANGOS_DLL_SPEC WorldObject : public Object
virtual void SendMessageToSetInRange(WorldPacket *data, float dist, bool self);
void BuildHeartBeatMsg( WorldPacket *data ) const;
void BuildTeleportAckMsg( WorldPacket *data, float x, float y, float z, float ang) const;
bool IsBeingTeleported() { return mSemaphoreTeleport; }
void SetSemaphoreTeleport(bool semphsetting) { mSemaphoreTeleport = semphsetting; }
void MonsterSay(const char* text, uint32 language, uint64 TargetGuid);
void MonsterYell(const char* text, uint32 language, uint64 TargetGuid);
@ -494,7 +492,5 @@ class MANGOS_DLL_SPEC WorldObject : public Object
float m_positionY;
float m_positionZ;
float m_orientation;
bool mSemaphoreTeleport;
};
#endif

View file

@ -5391,6 +5391,61 @@ struct SQLGameObjectLoader : public SQLStorageLoaderBase<SQLGameObjectLoader>
}
};
inline void CheckGOLockId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N)
{
if (sLockStore.LookupEntry(dataN))
return;
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but lock (Id: %u) not found.",
goInfo->id,goInfo->type,N,goInfo->door.lockId,goInfo->door.lockId);
}
inline void CheckGOLinkedTrapId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N)
{
if (GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(dataN))
{
if (trapInfo->type!=GAMEOBJECT_TYPE_TRAP)
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.",
goInfo->id,goInfo->type,N,dataN,dataN,GAMEOBJECT_TYPE_TRAP);
}
/* disable check for while (too many error reports baout not existed in trap templates
else
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but trap GO (Entry %u) not exist in `gameobject_template`.",
goInfo->id,goInfo->type,N,dataN,dataN);
*/
}
inline void CheckGOSpellId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N)
{
if (sSpellStore.LookupEntry(dataN))
return;
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but Spell (Entry %u) not exist.",
goInfo->id,goInfo->type,N,dataN,dataN);
}
inline void CheckAndFixGOChairHeightId(GameObjectInfo const* goInfo,uint32 const& dataN,uint32 N)
{
if (dataN <= (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR) )
return;
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but correct chair height in range 0..%i.",
goInfo->id,goInfo->type,N,dataN,UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR);
// prevent client and server unexpected work
const_cast<uint32&>(dataN) = 0;
}
inline void CheckGONoDamageImmuneId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N)
{
// 0/1 correct values
if (dataN <= 1)
return;
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but expected boolean (0/1) noDamageImmune field value.",
goInfo->id,goInfo->type,N,dataN);
}
void ObjectMgr::LoadGameobjectInfo()
{
SQLGameObjectLoader loader;
@ -5408,68 +5463,45 @@ void ObjectMgr::LoadGameobjectInfo()
case GAMEOBJECT_TYPE_DOOR: //0
{
if (goInfo->door.lockId)
{
if(!sLockStore.LookupEntry(goInfo->door.lockId))
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but lock (Id: %u) not found.",
id,goInfo->type,goInfo->door.lockId,goInfo->door.lockId);
}
CheckGOLockId(goInfo,goInfo->door.lockId,1);
CheckGONoDamageImmuneId(goInfo,goInfo->door.noDamageImmune,3);
break;
}
case GAMEOBJECT_TYPE_BUTTON: //1
{
if (goInfo->button.lockId)
{
if(!sLockStore.LookupEntry(goInfo->button.lockId))
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but lock (Id: %u) not found.",
id,goInfo->type,goInfo->button.lockId,goInfo->button.lockId);
CheckGOLockId(goInfo,goInfo->button.lockId,1);
CheckGONoDamageImmuneId(goInfo,goInfo->button.noDamageImmune,4);
break;
}
case GAMEOBJECT_TYPE_QUESTGIVER: //2
{
if (goInfo->questgiver.lockId)
CheckGOLockId(goInfo,goInfo->questgiver.lockId,0);
CheckGONoDamageImmuneId(goInfo,goInfo->questgiver.noDamageImmune,5);
break;
}
case GAMEOBJECT_TYPE_CHEST: //3
{
if (goInfo->chest.lockId)
{
if(!sLockStore.LookupEntry(goInfo->chest.lockId))
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but lock (Id: %u) not found.",
id,goInfo->type,goInfo->chest.lockId,goInfo->chest.lockId);
}
CheckGOLockId(goInfo,goInfo->chest.lockId,0);
if (goInfo->chest.linkedTrapId) // linked trap
{
if(GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(goInfo->chest.linkedTrapId))
{
if(trapInfo->type!=GAMEOBJECT_TYPE_TRAP)
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data7=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.",
id,goInfo->type,goInfo->chest.linkedTrapId,goInfo->chest.linkedTrapId,GAMEOBJECT_TYPE_TRAP);
}
/* disable check for while
else
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but trap GO (Entry %u) not exist in `gameobject_template`.",
id,goInfo->type,goInfo->chest.linkedTrapId,goInfo->chest.linkedTrapId);
*/
}
CheckGOLinkedTrapId(goInfo,goInfo->chest.linkedTrapId,7);
break;
}
case GAMEOBJECT_TYPE_TRAP: //6
{
/* disable check for while
if (goInfo->trap.lockId)
CheckGOLockId(goInfo,goInfo->trap.lockId,0);
/* disable check for while, too many not existed spells
if (goInfo->trap.spellId) // spell
{
if(!sSpellStore.LookupEntry(goInfo->trap.spellId))
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data3=%u but Spell (Entry %u) not exist.",
id,goInfo->type,goInfo->trap.spellId,goInfo->trap.spellId);
}
CheckGOSpellId(goInfo,goInfo->trap.spellId,3);
*/
break;
}
case GAMEOBJECT_TYPE_CHAIR: //7
if(goInfo->chair.height > (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR) )
{
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but correct chair height in range 0..%i.",
id,goInfo->type,goInfo->chair.height,UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR);
// prevent client and server unexpected work
const_cast<GameObjectInfo*>(goInfo)->chair.height = 0;
}
CheckAndFixGOChairHeightId(goInfo,goInfo->chair.height,1);
break;
case GAMEOBJECT_TYPE_SPELL_FOCUS: //8
{
@ -5481,51 +5513,39 @@ void ObjectMgr::LoadGameobjectInfo()
}
if (goInfo->spellFocus.linkedTrapId) // linked trap
{
if(GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(goInfo->spellFocus.linkedTrapId))
{
if(trapInfo->type!=GAMEOBJECT_TYPE_TRAP)
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.",
id,goInfo->type,goInfo->spellFocus.linkedTrapId,goInfo->spellFocus.linkedTrapId,GAMEOBJECT_TYPE_TRAP);
}
/* disable check for while
else
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but trap GO (Entry %u) not exist in `gameobject_template`.",
id,goInfo->type,goInfo->spellFocus.linkedTrapId,goInfo->spellFocus.linkedTrapId);
*/
}
CheckGOLinkedTrapId(goInfo,goInfo->spellFocus.linkedTrapId,2);
break;
}
case GAMEOBJECT_TYPE_GOOBER: //10
{
if (goInfo->goober.lockId)
CheckGOLockId(goInfo,goInfo->goober.lockId,0);
if (goInfo->goober.pageId) // pageId
{
if (!sPageTextStore.LookupEntry<PageText>(goInfo->goober.pageId))
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data7=%u but PageText (Entry %u) not exist.",
id,goInfo->type,goInfo->goober.pageId,goInfo->goober.pageId);
}
/* disable check for while
/* disable check for while, too many not existed spells
if (goInfo->goober.spellId) // spell
{
if(!sSpellStore.LookupEntry(goInfo->goober.spellId))
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but Spell (Entry %u) not exist.",
id,goInfo->type,goInfo->goober.spellId,goInfo->goober.spellId);
}
CheckGOSpellId(goInfo,goInfo->goober.spellId,10);
*/
CheckGONoDamageImmuneId(goInfo,goInfo->goober.noDamageImmune,11);
if (goInfo->goober.linkedTrapId) // linked trap
{
if(GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(goInfo->goober.linkedTrapId))
{
if(trapInfo->type!=GAMEOBJECT_TYPE_TRAP)
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data12=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.",
id,goInfo->type,goInfo->goober.linkedTrapId,goInfo->goober.linkedTrapId,GAMEOBJECT_TYPE_TRAP);
CheckGOLinkedTrapId(goInfo,goInfo->goober.linkedTrapId,12);
break;
}
/* disable check for while
else
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data12=%u but trap GO (Entry %u) not exist in `gameobject_template`.",
id,goInfo->type,goInfo->goober.linkedTrapId,goInfo->goober.linkedTrapId);
*/
case GAMEOBJECT_TYPE_AREADAMAGE: //12
{
if (goInfo->areadamage.lockId)
CheckGOLockId(goInfo,goInfo->areadamage.lockId,0);
break;
}
case GAMEOBJECT_TYPE_CAMERA: //13
{
if (goInfo->camera.lockId)
CheckGOLockId(goInfo,goInfo->camera.lockId,0);
break;
}
case GAMEOBJECT_TYPE_MO_TRANSPORT: //15
@ -5540,35 +5560,40 @@ void ObjectMgr::LoadGameobjectInfo()
}
case GAMEOBJECT_TYPE_SUMMONING_RITUAL: //18
{
/* disabled
if(goInfo->summoningRitual.spellId)
{
if(!sSpellStore.LookupEntry(goInfo->summoningRitual.spellId))
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but Spell (Entry %u) not exist.",
id,goInfo->type,goInfo->summoningRitual.spellId,goInfo->summoningRitual.spellId);
}
/* disable check for while, too many not existed spells
// always must have spell
CheckGOSpellId(goInfo,goInfo->summoningRitual.spellId,1);
*/
break;
}
case GAMEOBJECT_TYPE_SPELLCASTER: //22
{
if(goInfo->spellcaster.spellId) // spell
{
if(!sSpellStore.LookupEntry(goInfo->spellcaster.spellId))
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data3=%u but Spell (Entry %u) not exist.",
id,goInfo->type,goInfo->spellcaster.spellId,goInfo->spellcaster.spellId);
// always must have spell
CheckGOSpellId(goInfo,goInfo->spellcaster.spellId,0);
break;
}
case GAMEOBJECT_TYPE_FLAGSTAND: //24
{
if (goInfo->flagstand.lockId)
CheckGOLockId(goInfo,goInfo->flagstand.lockId,0);
CheckGONoDamageImmuneId(goInfo,goInfo->flagstand.noDamageImmune,5);
break;
}
case GAMEOBJECT_TYPE_FISHINGHOLE: //25
{
if (goInfo->fishinghole.lockId)
CheckGOLockId(goInfo,goInfo->fishinghole.lockId,4);
break;
}
case GAMEOBJECT_TYPE_FLAGDROP: //26
{
if (goInfo->flagdrop.lockId)
CheckGOLockId(goInfo,goInfo->flagdrop.lockId,0);
CheckGONoDamageImmuneId(goInfo,goInfo->flagdrop.noDamageImmune,3);
break;
}
case GAMEOBJECT_TYPE_BARBER_CHAIR: //32
if(goInfo->barberChair.chairheight > (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR) )
{
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but correct chair height in range 0..%i.",
id,goInfo->type,goInfo->barberChair.chairheight,UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR);
// prevent client and server unexpected work
const_cast<GameObjectInfo*>(goInfo)->barberChair.chairheight = 0;
}
CheckAndFixGOChairHeightId(goInfo,goInfo->barberChair.chairheight,0);
break;
}
}

View file

@ -91,19 +91,27 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
QueryResult *result;
if (petnumber)
// known petnumber entry 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND id = '%u'",ownerid, petnumber);
// known petnumber entry 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType "
"FROM character_pet WHERE owner = '%u' AND id = '%u'",
ownerid, petnumber);
else if (current)
// current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid );
// current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType "
"FROM character_pet WHERE owner = '%u' AND slot = '%u'",
ownerid, PET_SAVE_AS_CURRENT );
else if (petentry)
// known petentry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets)
// 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry );
// 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType "
"FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '%u' OR slot > '%u') ",
ownerid, petentry,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT);
else
// any current or other non-stabled pet (for hunter "call pet")
// 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid);
// 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType "
"FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u') ",
ownerid,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT);
if(!result)
return false;
@ -130,9 +138,17 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
return false;
}
uint32 pet_number = fields[0].GetUInt32();
if (current && owner->IsPetNeedBeTemporaryUnsummoned())
{
owner->SetTemporaryUnsummonedPetNumber(pet_number);
delete result;
return false;
}
Map *map = owner->GetMap();
uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_PET);
uint32 pet_number = fields[0].GetUInt32();
if (!Create(guid, map, owner->GetPhaseMask(), petentry, pet_number))
{
delete result;
@ -213,11 +229,16 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
uint32 savedmana = fields[12].GetUInt32();
// set current pet as current
// 0=current
// 1..MAX_PET_STABLES in stable slot
// PET_SAVE_NOT_IN_SLOT(100) = not stable slot (summoning))
if (fields[8].GetUInt32() != 0)
{
CharacterDatabase.BeginTransaction();
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'", ownerid, m_charmInfo->GetPetNumber());
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'", ownerid, m_charmInfo->GetPetNumber());
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND slot = '%u' AND id <> '%u'",
PET_SAVE_NOT_IN_SLOT, ownerid, PET_SAVE_AS_CURRENT, m_charmInfo->GetPetNumber());
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND id = '%u'",
PET_SAVE_AS_CURRENT, ownerid, m_charmInfo->GetPetNumber());
CharacterDatabase.CommitTransaction();
}
@ -339,14 +360,31 @@ void Pet::SavePetToDB(PetSaveMode mode)
if (!isControlled())
return;
// not save not player pets
if(!IS_PLAYER_GUID(GetOwnerGUID()))
return;
Player* pOwner = (Player*)GetOwner();
if (!pOwner)
return;
// not save pet as current if another pet temporary unsummoned
if (mode == PET_SAVE_AS_CURRENT && pOwner->GetTemporaryUnsummonedPetNumber() &&
pOwner->GetTemporaryUnsummonedPetNumber() != m_charmInfo->GetPetNumber())
{
// pet will lost anyway at restore temporary unsummoned
if(getPetType()==HUNTER_PET)
return;
// for warlock case
mode = PET_SAVE_NOT_IN_SLOT;
}
uint32 curhealth = GetHealth();
uint32 curmana = GetPower(POWER_MANA);
switch(mode)
{
case PET_SAVE_IN_STABLE_SLOT_1:
case PET_SAVE_IN_STABLE_SLOT_2:
case PET_SAVE_NOT_IN_SLOT:
// stable and not in slot saves
if(mode > PET_SAVE_AS_CURRENT)
{
RemoveAllAuras();
@ -354,20 +392,13 @@ void Pet::SavePetToDB(PetSaveMode mode)
if(!(getPetType() == HUNTER_PET && isAlive()))
m_Auras.clear();
}
default:
break;
}
_SaveSpells();
_SaveSpellCooldowns();
_SaveAuras();
switch(mode)
{
case PET_SAVE_AS_CURRENT:
case PET_SAVE_IN_STABLE_SLOT_1:
case PET_SAVE_IN_STABLE_SLOT_2:
case PET_SAVE_NOT_IN_SLOT:
// current/stable/not_in_slot
if(mode >= PET_SAVE_AS_CURRENT)
{
uint32 owner = GUID_LOPART(GetOwnerGUID());
std::string name = m_name;
@ -377,12 +408,14 @@ void Pet::SavePetToDB(PetSaveMode mode)
CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND id = '%u'", owner,m_charmInfo->GetPetNumber() );
// prevent duplicate using slot (except PET_SAVE_NOT_IN_SLOT)
if(mode!=PET_SAVE_NOT_IN_SLOT)
CharacterDatabase.PExecute("UPDATE character_pet SET slot = 3 WHERE owner = '%u' AND slot = '%u'", owner, uint32(mode) );
if(mode <= PET_SAVE_LAST_STABLE_SLOT)
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND slot = '%u'",
PET_SAVE_NOT_IN_SLOT, owner, uint32(mode) );
// prevent existence another hunter pet in PET_SAVE_AS_CURRENT and PET_SAVE_NOT_IN_SLOT
if(getPetType()==HUNTER_PET && (mode==PET_SAVE_AS_CURRENT||mode==PET_SAVE_NOT_IN_SLOT))
CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3')", owner );
if(getPetType()==HUNTER_PET && (mode==PET_SAVE_AS_CURRENT||mode > PET_SAVE_LAST_STABLE_SLOT))
CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u')",
owner,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT);
// save pet
std::ostringstream ss;
ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType) "
@ -423,18 +456,13 @@ void Pet::SavePetToDB(PetSaveMode mode)
<< uint32(getPetType()) << ")";
CharacterDatabase.Execute( ss.str().c_str() );
CharacterDatabase.CommitTransaction();
break;
}
case PET_SAVE_AS_DELETED:
// delete
else
{
RemoveAllAuras();
DeleteFromDB(m_charmInfo->GetPetNumber());
break;
}
default:
sLog.outError("Unknown pet save/remove mode: %d",mode);
}
}

View file

@ -34,13 +34,16 @@ enum PetType
extern char const* petTypeSuffix[MAX_PET_TYPE];
#define MAX_PET_STABLES 4
// stored in character_pet.slot
enum PetSaveMode
{
PET_SAVE_AS_DELETED =-1,
PET_SAVE_AS_CURRENT = 0,
PET_SAVE_IN_STABLE_SLOT_1 = 1,
PET_SAVE_IN_STABLE_SLOT_2 = 2,
PET_SAVE_NOT_IN_SLOT = 3
PET_SAVE_AS_DELETED = -1, // not saved in fact
PET_SAVE_AS_CURRENT = 0, // in current slot (with player)
PET_SAVE_FIRST_STABLE_SLOT = 1,
PET_SAVE_LAST_STABLE_SLOT = MAX_PET_STABLES, // last in DB stable slot index (including), all higher have same meaning as PET_SAVE_NOT_IN_SLOT
PET_SAVE_NOT_IN_SLOT = 100 // for avoid conflict with stable size grow will use 100
};
enum HappinessState

View file

@ -335,7 +335,8 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
m_atLoginFlags = AT_LOGIN_NONE;
m_dontMove = false;
mSemaphoreTeleport_Near = false;
mSemaphoreTeleport_Far = false;
pTrader = 0;
ClearTrade();
@ -1586,8 +1587,6 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
m_movementInfo.t_time = 0;
}
SetSemaphoreTeleport(true);
// The player was ported to another map and looses the duel immediately.
// We have to perform this check before the teleport, otherwise the
// ObjectAccessor won't find the flag.
@ -1603,72 +1602,29 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if ((GetMapId() == mapid) && (!m_transport))
{
// prepare zone change detect
uint32 old_zone = GetZoneId();
// near teleport
if(!GetSession()->PlayerLogout())
{
WorldPacket data;
BuildTeleportAckMsg(&data, x, y, z, orientation);
GetSession()->SendPacket(&data);
SetPosition( x, y, z, orientation, true);
}
else
// this will be used instead of the current location in SaveToDB
m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
SetFallInformation(0, z);
//BuildHeartBeatMsg(&data);
//SendMessageToSet(&data, true);
if (!(options & TELE_TO_NOT_UNSUMMON_PET))
{
//same map, only remove pet if out of range
if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE))
{
if(pet->isControlled() && !pet->isTemporarySummoned() )
m_temporaryUnsummonedPetNumber = pet->GetCharmInfo()->GetPetNumber();
else
m_temporaryUnsummonedPetNumber = 0;
RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
}
//same map, only remove pet if out of range for new position
if(pet && pet->GetDistance(x,y,z) >= OWNER_MAX_DISTANCE)
UnsummonPetTemporaryIfAny();
}
if(!(options & TELE_TO_NOT_LEAVE_COMBAT))
CombatStop();
if (!(options & TELE_TO_NOT_UNSUMMON_PET))
{
// resummon pet
if(pet && m_temporaryUnsummonedPetNumber)
{
Pet* NewPet = new Pet;
if(!NewPet->LoadPetFromDB(this, 0, m_temporaryUnsummonedPetNumber, true))
delete NewPet;
m_temporaryUnsummonedPetNumber = 0;
}
}
uint32 newzone, newarea;
GetZoneAndAreaId(newzone,newarea);
// this will be used instead of the current location in SaveToDB
m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
SetFallInformation(0, z);
// code for finish transfer called in WorldSession::HandleMovementOpcodes()
// at client packet MSG_MOVE_TELEPORT_ACK
SetSemaphoreTeleportNear(true);
// near teleport, triggering send MSG_MOVE_TELEPORT_ACK from client at landing
if(!GetSession()->PlayerLogout())
{
// don't reset teleport semaphore while logging out, otherwise m_teleport_dest won't be used in Player::SaveToDB
SetSemaphoreTeleport(false);
UpdateZone(newzone,newarea);
}
// new zone
if(old_zone != newzone)
{
// honorless target
if(pvpInfo.inHostileArea)
CastSpell(this, 2479, true);
WorldPacket data;
BuildTeleportAckMsg(&data, x, y, z, orientation);
GetSession()->SendPacket(&data);
}
}
else
@ -1680,10 +1636,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
// Check enter rights before map getting to avoid creating instance copy for player
// this check not dependent from map instance copy and same for all instance copies of selected map
if (!MapManager::Instance().CanPlayerEnter(mapid, this))
{
SetSemaphoreTeleport(false);
return false;
}
// If the map is not created, assume it is possible to enter it.
// It will be created in the WorldPortAck.
@ -1708,15 +1661,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
// remove pet on map change
if (pet)
{
//leaving map -> delete pet right away (doing this later will cause problems)
if(pet->isControlled() && !pet->isTemporarySummoned())
m_temporaryUnsummonedPetNumber = pet->GetCharmInfo()->GetPetNumber();
else
m_temporaryUnsummonedPetNumber = 0;
RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
}
UnsummonPetTemporaryIfAny();
// remove all dyn objects
RemoveAllDynObjects();
@ -1776,10 +1721,8 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING);
// move packet sent by client always after far teleport
// SetPosition(final_x, final_y, final_z, final_o, true);
SetDontMove(true);
// code for finish transfer to new map called in WorldSession::HandleMoveWorldportAckOpcode at client packet
SetSemaphoreTeleportFar(true);
}
else
return false;
@ -4599,24 +4542,24 @@ float Player::GetRatingBonusValue(CombatRating cr) const
uint32 Player::GetMeleeCritDamageReduction(uint32 damage) const
{
float melee = GetRatingBonusValue(CR_CRIT_TAKEN_MELEE)*2.0f;
if (melee>25.0f) melee = 25.0f;
float melee = GetRatingBonusValue(CR_CRIT_TAKEN_MELEE)*2.2f;
if (melee>33.0f) melee = 33.0f;
return uint32 (melee * damage /100.0f);
}
uint32 Player::GetRangedCritDamageReduction(uint32 damage) const
{
float ranged = GetRatingBonusValue(CR_CRIT_TAKEN_RANGED)*2.0f;
if (ranged>25.0f) ranged=25.0f;
float ranged = GetRatingBonusValue(CR_CRIT_TAKEN_RANGED)*2.2f;
if (ranged>33.0f) ranged=33.0f;
return uint32 (ranged * damage /100.0f);
}
uint32 Player::GetSpellCritDamageReduction(uint32 damage) const
{
float spell = GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2.0f;
// In wow script resilience limited to 25%
if (spell>25.0f)
spell = 25.0f;
float spell = GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2.2f;
// In wow script resilience limited to 33%
if (spell>33.0f)
spell = 33.0f;
return uint32 (spell * damage / 100.0f);
}
@ -5401,11 +5344,6 @@ void Player::removeActionButton(uint8 button)
sLog.outDetail( "Action Button '%u' Removed from Player '%u'", button, GetGUIDLow() );
}
void Player::SetDontMove(bool dontMove)
{
m_dontMove = dontMove;
}
bool Player::SetPosition(float x, float y, float z, float orientation, bool teleport)
{
// prevent crash when a bad coord is sent by the client
@ -9961,7 +9899,7 @@ Item* Player::StoreItem( ItemPosCountVec const& dest, Item* pItem, bool update )
return NULL;
Item* lastItem = pItem;
uint32 entry = pItem->GetEntry();
for(ItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end(); )
{
uint16 pos = itr->pos;
@ -9977,7 +9915,7 @@ Item* Player::StoreItem( ItemPosCountVec const& dest, Item* pItem, bool update )
lastItem = _StoreItem(pos,pItem,count,true,update);
}
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, entry);
return lastItem;
}
@ -12431,6 +12369,8 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
SendQuestReward( pQuest, XP, questGiver );
if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED;
if (pQuest->GetZoneOrSort() > 0)
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, pQuest->GetZoneOrSort());
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST);
@ -13085,7 +13025,6 @@ void Player::ItemAddedQuestCheck( uint32 entry, uint32 count )
}
}
UpdateForQuestsGO();
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, entry);
}
void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count )
@ -14065,10 +14004,10 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
uint32 extraflags = fields[25].GetUInt32();
m_stableSlots = fields[26].GetUInt32();
if(m_stableSlots > 4)
if(m_stableSlots > MAX_PET_STABLES)
{
sLog.outError("Player can have not more 4 stable slots, but have in DB %u",uint32(m_stableSlots));
m_stableSlots = 4;
sLog.outError("Player can have not more %u stable slots, but have in DB %u",MAX_PET_STABLES,uint32(m_stableSlots));
m_stableSlots = MAX_PET_STABLES;
}
m_atLoginFlags = fields[27].GetUInt32();
@ -18917,7 +18856,7 @@ void Player::UpdateUnderwaterState( Map* m, float x, float y, float z )
}
// Allow travel in dark water on taxi or transport
if (liquid_status.type & MAP_LIQUID_TYPE_DARK_WATER && !isInFlight() && !(GetUnitMovementFlags()&MOVEMENTFLAG_ONTRANSPORT))
if ((liquid_status.type & MAP_LIQUID_TYPE_DARK_WATER) && !isInFlight() && !GetTransport())
m_MirrorTimerFlags |= UNDERWARER_INDARKWATER;
else
m_MirrorTimerFlags &= ~UNDERWARER_INDARKWATER;
@ -19751,6 +19690,40 @@ void Player::UpdateFallInformationIfNeed( MovementInfo const& minfo,uint16 opcod
SetFallInformation(minfo.fallTime, minfo.z);
}
void Player::UnsummonPetTemporaryIfAny()
{
Pet* pet = GetPet();
if(!pet)
return;
if(!m_temporaryUnsummonedPetNumber && pet->isControlled() && !pet->isTemporarySummoned() )
{
m_temporaryUnsummonedPetNumber = pet->GetCharmInfo()->GetPetNumber();
m_oldpetspell = pet->GetUInt32Value(UNIT_CREATED_BY_SPELL);
}
RemovePet(pet, PET_SAVE_AS_CURRENT);
}
void Player::ResummonPetTemporaryUnSummonedIfAny()
{
if(!m_temporaryUnsummonedPetNumber)
return;
// not resummon in not appropriate state
if(IsPetNeedBeTemporaryUnsummoned())
return;
if(GetPetGUID())
return;
Pet* NewPet = new Pet;
if(!NewPet->LoadPetFromDB(this, 0, m_temporaryUnsummonedPetNumber, true))
delete NewPet;
m_temporaryUnsummonedPetNumber = 0;
}
void Player::BuildPlayerTalentsInfoData(WorldPacket *data)
{
*data << uint32(GetFreeTalentPoints()); // unspentTalentPoints

View file

@ -1661,8 +1661,12 @@ class MANGOS_DLL_SPEC Player : public Unit
bool HasSkill(uint32 skill) const;
void learnSkillRewardedSpells(uint32 id, uint32 value);
void SetDontMove(bool dontMove);
bool GetDontMove() const { return m_dontMove; }
WorldLocation& GetTeleportDest() { return m_teleport_dest; }
bool IsBeingTeleported() const { return mSemaphoreTeleport_Near || mSemaphoreTeleport_Far; }
bool IsBeingTeleportedNear() const { return mSemaphoreTeleport_Near; }
bool IsBeingTeleportedFar() const { return mSemaphoreTeleport_Far; }
void SetSemaphoreTeleportNear(bool semphsetting) { mSemaphoreTeleport_Near = semphsetting; }
void SetSemaphoreTeleportFar(bool semphsetting) { mSemaphoreTeleport_Far = semphsetting; }
void CheckExploreSystem(void);
@ -1986,8 +1990,9 @@ class MANGOS_DLL_SPEC Player : public Unit
// Temporarily removed pet cache
uint32 GetTemporaryUnsummonedPetNumber() const { return m_temporaryUnsummonedPetNumber; }
void SetTemporaryUnsummonedPetNumber(uint32 petnumber) { m_temporaryUnsummonedPetNumber = petnumber; }
uint32 GetOldPetSpell() const { return m_oldpetspell; }
void SetOldPetSpell(uint32 petspell) { m_oldpetspell = petspell; }
void UnsummonPetTemporaryIfAny();
void ResummonPetTemporaryUnSummonedIfAny();
bool IsPetNeedBeTemporaryUnsummoned() const { return !IsInWorld() || !isAlive() || IsMounted() /*+in flight*/; }
void SendCinematicStart(uint32 CinematicSequenceId);
void SendMovieStart(uint32 MovieId);
@ -2043,8 +2048,6 @@ class MANGOS_DLL_SPEC Player : public Unit
bool isAllowedToLoot(Creature* creature);
WorldLocation& GetTeleportDest() { return m_teleport_dest; }
DeclinedName const* GetDeclinedNames() const { return m_declinedname; }
uint8 GetRunesState() const { return m_runes->runeState; }
uint8 GetBaseRune(uint8 index) const { return m_runes->runes[index].BaseRune; }
@ -2212,8 +2215,6 @@ class MANGOS_DLL_SPEC Player : public Unit
typedef std::list<Channel*> JoinedChannelsList;
JoinedChannelsList m_channels;
bool m_dontMove;
int m_cinematic;
Player *pTrader;
@ -2276,10 +2277,6 @@ class MANGOS_DLL_SPEC Player : public Unit
uint32 m_groupUpdateMask;
uint64 m_auraUpdateMask;
// Temporarily removed pet cache
uint32 m_temporaryUnsummonedPetNumber;
uint32 m_oldpetspell;
uint64 m_miniPet;
GuardianPetList m_guardianPets;
@ -2290,9 +2287,6 @@ class MANGOS_DLL_SPEC Player : public Unit
float m_summon_y;
float m_summon_z;
// Far Teleport
WorldLocation m_teleport_dest;
DeclinedName *m_declinedname;
Runes *m_runes;
EquipmentSets m_EquipmentSets;
@ -2318,6 +2312,15 @@ class MANGOS_DLL_SPEC Player : public Unit
uint8 m_MirrorTimerFlagsLast;
bool m_isInWater;
// Current teleport data
WorldLocation m_teleport_dest;
bool mSemaphoreTeleport_Near;
bool mSemaphoreTeleport_Far;
// Temporary removed pet cache
uint32 m_temporaryUnsummonedPetNumber;
uint32 m_oldpetspell;
AchievementMgr m_achievementMgr;
ReputationMgr m_reputationMgr;
};

View file

@ -2503,6 +2503,9 @@ void Spell::EffectHealPct( uint32 /*i*/ )
return;
uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
if(Player* modOwner = m_caster->GetSpellModOwner())
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DAMAGE, addhealth, this);
caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
@ -4989,6 +4992,21 @@ void Spell::EffectScriptEffect(uint32 effIndex)
DoCreateItem( effIndex, itemtype );
return;
}
// Everlasting Affliction
case 47422:
{
// Need refresh caster corruption auras on target
Unit::AuraMap& suAuras = unitTarget->GetAuras();
for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
{
SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
if(spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK &&
spellInfo->SpellFamilyFlags & 0x0000000000000002LL &&
(*itr).second->GetCasterGUID()==m_caster->GetGUID())
(*itr).second->RefreshAura();
}
return;
}
}
break;
}

View file

@ -8550,21 +8550,7 @@ void Unit::Mount(uint32 mount)
// unsummon pet
if(GetTypeId() == TYPEID_PLAYER)
{
Pet* pet = GetPet();
if(pet)
{
if(pet->isControlled())
{
((Player*)this)->SetTemporaryUnsummonedPetNumber(pet->GetCharmInfo()->GetPetNumber());
((Player*)this)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL));
}
((Player*)this)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT);
}
else
((Player*)this)->SetTemporaryUnsummonedPetNumber(0);
}
((Player*)this)->UnsummonPetTemporaryIfAny();
}
void Unit::Unmount()
@ -8580,14 +8566,8 @@ void Unit::Unmount()
// only resummon old pet if the player is already added to a map
// this prevents adding a pet to a not created map which would otherwise cause a crash
// (it could probably happen when logging in after a previous crash)
if(GetTypeId() == TYPEID_PLAYER && IsInWorld() && ((Player*)this)->GetTemporaryUnsummonedPetNumber() && isAlive())
{
Pet* NewPet = new Pet;
if(!NewPet->LoadPetFromDB((Player*)this, 0, ((Player*)this)->GetTemporaryUnsummonedPetNumber(), true))
delete NewPet;
((Player*)this)->SetTemporaryUnsummonedPetNumber(0);
}
if(GetTypeId() == TYPEID_PLAYER)
((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
}
void Unit::SetInCombatWith(Unit* enemy)

View file

@ -723,7 +723,7 @@ void World::LoadConfigSettings(bool reload)
{
sLog.outError("StartHonorPoints (%i) must be in range 0..MaxHonorPoints(%u). Set to %u.",
m_configs[CONFIG_START_HONOR_POINTS],m_configs[CONFIG_MAX_HONOR_POINTS],0);
m_configs[CONFIG_MAX_HONOR_POINTS] = 0;
m_configs[CONFIG_START_HONOR_POINTS] = 0;
}
else if(m_configs[CONFIG_START_HONOR_POINTS] > m_configs[CONFIG_MAX_HONOR_POINTS])
{
@ -2831,14 +2831,19 @@ void World::UpdateMaxSessionCounters()
void World::LoadDBVersion()
{
QueryResult* result = WorldDatabase.Query("SELECT version FROM db_version LIMIT 1");
QueryResult* result = WorldDatabase.Query("SELECT version, creature_ai_version FROM db_version LIMIT 1");
if(result)
{
Field* fields = result->Fetch();
m_DBVersion = fields[0].GetString();
m_DBVersion = fields[0].GetCppString();
m_CreatureEventAIVersion = fields[1].GetCppString();
delete result;
}
else
m_DBVersion = "unknown world database";
if(m_DBVersion.empty())
m_DBVersion = "Unknown world database.";
if(m_CreatureEventAIVersion.empty())
m_CreatureEventAIVersion = "Unknown creature EventAI.";
}

View file

@ -503,6 +503,7 @@ class World
//used World DB version
void LoadDBVersion();
char const* GetDBVersion() { return m_DBVersion.c_str(); }
char const* GetCreatureEventAIVersion() { return m_CreatureEventAIVersion.c_str(); }
//used Script version
void SetScriptsVersion(char const* version) { m_ScriptsVersion = version ? version : "unknown scripting library"; }
@ -571,6 +572,7 @@ class World
//used versions
std::string m_DBVersion;
std::string m_CreatureEventAIVersion;
std::string m_ScriptsVersion;
};

View file

@ -237,7 +237,7 @@ bool WorldSession::Update(uint32 /*diff*/)
void WorldSession::LogoutPlayer(bool Save)
{
// finish pending transfers before starting the logout
while(_player && _player->IsBeingTeleported())
while(_player && _player->IsBeingTeleportedFar())
HandleMoveWorldportAckOpcode();
m_playerLogout = true;

View file

@ -447,7 +447,8 @@ bool Master::_StartDB()
sWorld.LoadDBVersion();
sLog.outString("Using %s", sWorld.GetDBVersion());
sLog.outString("Using World DB: %s", sWorld.GetDBVersion());
sLog.outString("Using creature EventAI: %s", sWorld.GetCreatureEventAIVersion());
return true;
}

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "7635"
#define REVISION_NR "7656"
#endif // __REVISION_NR_H__