aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormegamage <none@none>2009-04-11 14:47:38 -0500
committermegamage <none@none>2009-04-11 14:47:38 -0500
commit3120221deb93af2125a9baefe745cbbab8426ffe (patch)
tree6ebfc7364a8fc73eb234074d33477fbfe3fe08b6
parentf4d69d1b3b8fe6d26195b14f0ec2133b872c735c (diff)
*Note: this patch may do not have any use for TC.
[7645] Fixed problems wit temporary unsummoned pets and cleanup code. Author: VladimirMangos * Save temporary unsummoned pet to current slot (instead non_in_slot mode) and prevent save as current pet summoned while temporay unsummon (arena) * Prevent overwrite temporary summoned pet data * At player loading set temporary unsummoned pet data instead pet loading if pet expected to be temporary unsummoned in current player state (loading in taxi flight/etc) * Restore proper pet at arena leave and unsummon in arena summoned. --HG-- branch : trunk
-rw-r--r--src/game/BattleGround.cpp26
-rw-r--r--src/game/CharacterHandler.cpp5
-rw-r--r--src/game/MovementHandler.cpp9
-rw-r--r--src/game/NPCHandler.cpp5
-rw-r--r--src/game/Pet.cpp59
-rw-r--r--src/game/Player.cpp67
-rw-r--r--src/game/Player.h5
-rw-r--r--src/game/Unit.cpp21
8 files changed, 103 insertions, 94 deletions
diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp
index b3f74457063..fffedb56ad8 100644
--- a/src/game/BattleGround.cpp
+++ b/src/game/BattleGround.cpp
@@ -951,15 +951,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->GetGuardianPet() && plr->GetTemporaryUnsummonedPetNumber())
- {
- Pet* NewPet = new Pet(plr);
- 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)
{
@@ -1113,19 +1107,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
{
diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp
index 5cd9c8f191c..a2e189603f9 100644
--- a/src/game/CharacterHandler.cpp
+++ b/src/game/CharacterHandler.cpp
@@ -814,9 +814,8 @@ 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)
- pCurrChar->LoadPet();
+ // 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
if(sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_RESTING) )
diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp
index 560fb4d651e..b88a67d782f 100644
--- a/src/game/MovementHandler.cpp
+++ b/src/game/MovementHandler.cpp
@@ -157,14 +157,7 @@ void WorldSession::HandleMoveWorldportAckOpcode()
GetPlayer()->CastSpell(GetPlayer(), 2479, true);
// resummon pet
- if(GetPlayer()->m_temporaryUnsummonedPetNumber)
- {
- Pet* NewPet = new Pet(GetPlayer());
- if(!NewPet->LoadPetFromDB(GetPlayer(), 0, GetPlayer()->m_temporaryUnsummonedPetNumber, true))
- delete NewPet;
-
- GetPlayer()->m_temporaryUnsummonedPetNumber = 0;
- }
+ GetPlayer()->ResummonPetTemporaryUnSummonedIfAny();
GetPlayer()->SetDontMove(false);
}
diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp
index 94a8c03ab24..8d1427c86b8 100644
--- a/src/game/NPCHandler.cpp
+++ b/src/game/NPCHandler.cpp
@@ -611,12 +611,13 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data )
// 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;
}
- delete result;
if( free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots)
{
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
index dba79a47a72..e723298565a 100644
--- a/src/game/Pet.cpp
+++ b/src/game/Pet.cpp
@@ -99,17 +99,17 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
QueryResult *result;
- if(petnumber)
+ 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);
- else if(current)
+ 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 = '%u'",
ownerid, PET_SAVE_AS_CURRENT );
- else if(petentry)
+ 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 "
@@ -129,7 +129,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
// update for case of current pet "slot = 0"
petentry = fields[1].GetUInt32();
- if(!petentry)
+ if (!petentry)
{
delete result;
return false;
@@ -141,16 +141,24 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0;
// check temporary summoned pets like mage water elemental
- if(current && is_temporary_summoned)
+ if (current && is_temporary_summoned)
{
delete result;
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))
+ if (!Create(guid, map, owner->GetPhaseMask(), petentry, pet_number))
{
delete result;
return false;
@@ -159,7 +167,8 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
float px, py, pz;
owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
Relocate(px, py, pz, owner->GetOrientation());
- if(!IsPositionValid())
+
+ if (!IsPositionValid())
{
sLog.outError("Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)",
GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY());
@@ -172,14 +181,14 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id);
CreatureInfo const *cinfo = GetCreatureInfo();
- if(cinfo->type == CREATURE_TYPE_CRITTER)
+ if (cinfo->type == CREATURE_TYPE_CRITTER)
{
map->Add((Creature*)this);
delete result;
return true;
}
- if(getPetType() == HUNTER_PET || (getPetType() == SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK))
+ if (getPetType() == HUNTER_PET || (getPetType() == SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK))
m_charmInfo->SetPetNumber(pet_number, true);
else
m_charmInfo->SetPetNumber(pet_number, false);
@@ -204,7 +213,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
SetUInt32Value(UNIT_NPC_FLAGS, 0);
SetName(fields[9].GetString());
- switch(getPetType())
+ switch (getPetType())
{
case SUMMON_PET:
petlevel=owner->getLevel();
@@ -260,12 +269,12 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
_LoadSpells();
_LoadSpellCooldowns();
- if(!is_temporary_summoned)
+ if (!is_temporary_summoned)
{
// permanent controlled pets store state in DB
Tokens tokens = StrSplit(fields[14].GetString(), " ");
- if(tokens.size() != 20)
+ if (tokens.size() != 20)
{
delete result;
return false;
@@ -345,13 +354,33 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
void Pet::SavePetToDB(PetSaveMode mode)
{
- if(!GetEntry())
+ if (!GetEntry())
return;
// save only fully controlled creature
- if(!isControlled())
+ 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);
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 4bf93b3ea70..01ca893b6e3 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -1683,16 +1683,9 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
//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))
@@ -1701,14 +1694,8 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if (!(options & TELE_TO_NOT_UNSUMMON_PET))
{
// resummon pet
- if(pet && m_temporaryUnsummonedPetNumber)
- {
- Pet* NewPet = new Pet(this);
- if(!NewPet->LoadPetFromDB(this, 0, m_temporaryUnsummonedPetNumber, true))
- delete NewPet;
-
- m_temporaryUnsummonedPetNumber = 0;
- }
+ if (pet)
+ ResummonPetTemporaryUnSummonedIfAny();
}
uint32 newzone, newarea;
@@ -1767,15 +1754,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();
@@ -20485,3 +20464,37 @@ void Player::UpdateFallInformationIfNeed( MovementInfo const& minfo,uint16 opcod
if (m_lastFallTime >= minfo.fallTime || m_lastFallZ <=minfo.z || opcode == MSG_MOVE_FALL_LAND)
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(this);
+ if(!NewPet->LoadPetFromDB(this, 0, m_temporaryUnsummonedPetNumber, true))
+ delete NewPet;
+
+ m_temporaryUnsummonedPetNumber = 0;
+}
diff --git a/src/game/Player.h b/src/game/Player.h
index 4738ce603a0..1c2f7db6505 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -1998,8 +1998,9 @@ class TRINITY_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);
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 88155b4be51..4932887d2d9 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -9537,21 +9537,7 @@ void Unit::Mount(uint32 mount)
// unsummon pet
if(GetTypeId() == TYPEID_PLAYER)
- {
- Pet* pet = ((Player*)this)->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()
@@ -9567,6 +9553,7 @@ 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)
+<<<<<<< HEAD:src/game/Unit.cpp
if(GetTypeId() == TYPEID_PLAYER && IsInWorld() && ((Player*)this)->GetTemporaryUnsummonedPetNumber() && isAlive())
{
Pet* NewPet = new Pet((Player*)this);
@@ -9575,6 +9562,10 @@ void Unit::Unmount()
((Player*)this)->SetTemporaryUnsummonedPetNumber(0);
}
+=======
+ if(GetTypeId() == TYPEID_PLAYER)
+ ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
+>>>>>>> 661760f287d94dbbe8f5224b19ba4181c7d62910:src/game/Unit.cpp
}
void Unit::SetInCombatWith(Unit* enemy)