Core/Pets: Updated pet summoning for latest client version (5 Call Pet spells and stable size 200)

Port From (https://github.com/TrinityCore/TrinityCore/commit/950db60435e7e513633ff5b22ad7f0ed8b1147e4)
This commit is contained in:
hondacrx
2022-03-10 12:02:05 -05:00
parent a77e6865b2
commit c486b2a846
14 changed files with 448 additions and 218 deletions
+69 -53
View File
@@ -96,13 +96,14 @@ namespace Game.Entities
}
}
public static Tuple<PetStable.PetInfo, PetSaveMode> GetLoadPetInfo(PetStable stable, uint petEntry, uint petnumber, bool current)
public static Tuple<PetStable.PetInfo, PetSaveMode> GetLoadPetInfo(PetStable stable, uint petEntry, uint petnumber, PetSaveMode? slot)
{
if (petnumber != 0)
{
// Known petnumber entry
if (stable.CurrentPet != null && stable.CurrentPet.PetNumber == petnumber)
return Tuple.Create(stable.CurrentPet, PetSaveMode.AsCurrent);
for (var activeSlot = 0; activeSlot < stable.ActivePets.Length; ++activeSlot)
if (stable.ActivePets[activeSlot] != null && stable.ActivePets[activeSlot].PetNumber == petnumber)
return Tuple.Create(stable.ActivePets[activeSlot], PetSaveMode.FirstActiveSlot + activeSlot);
for (var stableSlot = 0; stableSlot < stable.StabledPets.Length; ++stableSlot)
if (stable.StabledPets[stableSlot] != null && stable.StabledPets[stableSlot].PetNumber == petnumber)
@@ -112,17 +113,24 @@ namespace Game.Entities
if (pet.PetNumber == petnumber)
return Tuple.Create(pet, PetSaveMode.NotInSlot);
}
else if (current)
else if (slot.HasValue)
{
// Current pet (slot 0)
if (stable.CurrentPet != null)
return Tuple.Create(stable.CurrentPet, PetSaveMode.AsCurrent);
// Current pet
if (slot == PetSaveMode.AsCurrent)
if (stable.GetCurrentActivePetIndex().HasValue && stable.ActivePets[stable.GetCurrentActivePetIndex().Value] != null)
return Tuple.Create(stable.ActivePets[stable.GetCurrentActivePetIndex().Value], (PetSaveMode)stable.GetCurrentActivePetIndex());
if (slot >= PetSaveMode.FirstActiveSlot && slot < PetSaveMode.LastActiveSlot)
if (stable.ActivePets[(int)slot.Value] != null)
return Tuple.Create(stable.ActivePets[(int)slot.Value], slot.Value);
if (slot >= PetSaveMode.FirstStableSlot && slot < PetSaveMode.LastStableSlot)
if (stable.StabledPets[(int)slot.Value] != null)
return Tuple.Create(stable.StabledPets[(int)slot.Value], slot.Value);
}
else if (petEntry != 0)
{
// known petEntry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets)
if (stable.CurrentPet != null && stable.CurrentPet.CreatureId == petEntry)
return Tuple.Create(stable.CurrentPet, PetSaveMode.AsCurrent);
foreach (var pet in stable.UnslottedPets)
if (pet.CreatureId == petEntry)
@@ -131,8 +139,8 @@ namespace Game.Entities
else
{
// Any current or other non-stabled pet (for hunter "call pet")
if (stable.CurrentPet != null)
return Tuple.Create(stable.CurrentPet, PetSaveMode.AsCurrent);
if (stable.ActivePets[0] != null)
return Tuple.Create(stable.ActivePets[0], PetSaveMode.FirstActiveSlot);
if (!stable.UnslottedPets.Empty())
return Tuple.Create(stable.UnslottedPets.First(), PetSaveMode.NotInSlot);
@@ -141,22 +149,22 @@ namespace Game.Entities
return Tuple.Create<PetStable.PetInfo, PetSaveMode>(null, PetSaveMode.AsDeleted);
}
public bool LoadPetFromDB(Player owner, uint petEntry = 0, uint petnumber = 0, bool current = false)
public bool LoadPetFromDB(Player owner, uint petEntry = 0, uint petnumber = 0, bool current = false, PetSaveMode? forcedSlot = null)
{
m_loading = true;
PetStable petStable = owner.GetPetStable();
ulong ownerid = owner.GetGUID().GetCounter();
(PetStable.PetInfo petInfo, PetSaveMode slot) = GetLoadPetInfo(petStable, petEntry, petnumber, current);
if (petInfo == null)
(PetStable.PetInfo petInfo, PetSaveMode slot) = GetLoadPetInfo(petStable, petEntry, petnumber, forcedSlot);
if (petInfo == null || (slot >= PetSaveMode.FirstStableSlot && slot < PetSaveMode.LastStableSlot))
{
m_loading = false;
return false;
}
// Don't try to reload the current pet
if (petStable.CurrentPet != null && owner.GetPet() != null && petStable.CurrentPet.PetNumber == petInfo.PetNumber)
if (petStable.GetCurrentPet() != null && owner.GetPet() != null && petStable.GetCurrentPet().PetNumber == petInfo.PetNumber)
return false;
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(petInfo.CreatedBySpellId, owner.GetMap().GetDifficultyID());
@@ -273,36 +281,28 @@ namespace Game.Entities
}
// set current pet as current
// 0=current
// 1..MAX_PET_STABLES in stable slot
// PET_SAVE_NOT_IN_SLOT(100) = not stable slot (summoning))
// 0-4=current
// PET_SAVE_NOT_IN_SLOT(-1) = not stable slot (summoning))
if (slot == PetSaveMode.NotInSlot)
{
uint petInfoNumber = petInfo.PetNumber;
if (petStable.CurrentPet != null)
if (petStable.CurrentPetIndex != 0)
owner.RemovePet(null, PetSaveMode.NotInSlot);
var unslottedPetInfo = petStable.UnslottedPets.Find(unslottedPet => unslottedPet.PetNumber == petInfoNumber);
Cypher.Assert(petStable.CurrentPet == null);
Cypher.Assert(unslottedPetInfo != null);
var unslottedPetIndex = petStable.UnslottedPets.FindIndex(unslottedPet => unslottedPet.PetNumber == petInfoNumber);
Cypher.Assert(petStable.CurrentPetIndex == 0);
Cypher.Assert(unslottedPetIndex != -1);
petStable.CurrentPet = unslottedPetInfo;
petStable.UnslottedPets.Remove(unslottedPetInfo);
// old petInfo is no longer valid, refresh it
petInfo = petStable.CurrentPet;
petStable.SetCurrentUnslottedPetIndex((uint)unslottedPetIndex);
}
else if (PetSaveMode.FirstStableSlot <= slot && slot <= PetSaveMode.LastStableSlot)
else if (PetSaveMode.FirstActiveSlot <= slot && slot <= PetSaveMode.LastActiveSlot)
{
var index = Array.FindIndex(petStable.StabledPets, pet => pet?.PetNumber == petnumber);
var stabledPet = petStable.StabledPets[index];
Cypher.Assert(index != -1);
var activePetIndex = Array.FindIndex(petStable.ActivePets, pet => pet?.PetNumber == petnumber);
petStable.StabledPets[index] = petStable.CurrentPet;
petStable.CurrentPet = stabledPet;
Cypher.Assert(petStable.CurrentPetIndex == 0);
Cypher.Assert(activePetIndex != -1);
// old petInfo pointer is no longer valid, refresh it
petInfo = petStable.CurrentPet;
petStable.SetCurrentActivePetIndex((uint)activePetIndex);
}
// Send fake summon spell cast - this is needed for correct cooldown application for spells
@@ -437,8 +437,15 @@ namespace Game.Entities
// save auras before possibly removing them
_SaveAuras(trans);
if (mode == PetSaveMode.AsCurrent)
{
var activeSlot = owner.GetPetStable().GetCurrentActivePetIndex();
if (activeSlot.HasValue)
mode = (PetSaveMode)activeSlot;
}
// stable and not in slot saves
if (mode > PetSaveMode.AsCurrent)
if (mode < PetSaveMode.FirstActiveSlot || mode >= PetSaveMode.LastActiveSlot)
RemoveAllAuras();
_SaveSpells(trans);
@@ -446,7 +453,7 @@ namespace Game.Entities
DB.Characters.CommitTransaction(trans);
// current/stable/not_in_slot
if (mode >= PetSaveMode.AsCurrent)
if (mode != PetSaveMode.AsDeleted)
{
ulong ownerLowGUID = GetOwnerGUID().GetCounter();
trans = new SQLTransaction();
@@ -456,21 +463,11 @@ namespace Game.Entities
stmt.AddValue(0, GetCharmInfo().GetPetNumber());
trans.Append(stmt);
// prevent existence another hunter pet in PET_SAVE_AS_CURRENT and PET_SAVE_NOT_IN_SLOT
if (GetPetType() == PetType.Hunter && (mode == PetSaveMode.AsCurrent || mode == PetSaveMode.LastStableSlot))
{
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_PET_BY_SLOT);
stmt.AddValue(0, ownerLowGUID);
stmt.AddValue(1, (short)mode);
stmt.AddValue(2, (short)PetSaveMode.NotInSlot);
trans.Append(stmt);
}
// save pet
string actionBar = GenerateActionBarData();
Cypher.Assert(owner.GetPetStable().CurrentPet != null && owner.GetPetStable().CurrentPet.PetNumber == GetCharmInfo().GetPetNumber());
FillPetInfo(owner.GetPetStable().CurrentPet);
Cypher.Assert(owner.GetPetStable().GetCurrentPet() != null && owner.GetPetStable().GetCurrentPet().PetNumber == GetCharmInfo().GetPetNumber());
FillPetInfo(owner.GetPetStable().GetCurrentPet());
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_PET);
stmt.AddValue(0, GetCharmInfo().GetPetNumber());
@@ -480,7 +477,7 @@ namespace Game.Entities
stmt.AddValue(4, GetLevel());
stmt.AddValue(5, m_unitData.PetExperience);
stmt.AddValue(6, (byte)GetReactState());
stmt.AddValue(7, (byte)mode);
stmt.AddValue(7, (owner.GetPetStable().GetCurrentActivePetIndex().HasValue ? (short)owner.GetPetStable().GetCurrentActivePetIndex().Value : (short)PetSaveMode.NotInSlot));
stmt.AddValue(8, GetName());
stmt.AddValue(9, HasPetFlag(UnitPetFlags.CanBeRenamed) ? 0 : 1);
stmt.AddValue(10, curhealth);
@@ -1676,6 +1673,8 @@ namespace Game.Entities
public class PetStable
{
static uint UnslottedPetIndexMask = 0x80000000;
public class PetInfo
{
public string Name;
@@ -1695,14 +1694,31 @@ namespace Game.Entities
public bool WasRenamed;
}
public PetInfo CurrentPet; // PET_SAVE_AS_CURRENT
public uint? CurrentPetIndex; // index into ActivePets or UnslottedPets if highest bit is set
public PetInfo[] ActivePets = new PetInfo[SharedConst.MaxActivePets]; // PET_SAVE_FIRST_ACTIVE_SLOT - PET_SAVE_LAST_ACTIVE_SLOT
public PetInfo[] StabledPets = new PetInfo[SharedConst.MaxPetStables]; // PET_SAVE_FIRST_STABLE_SLOT - PET_SAVE_LAST_STABLE_SLOT
public List<PetInfo> UnslottedPets = new(); // PET_SAVE_NOT_IN_SLOT
public PetInfo GetUnslottedHunterPet()
public PetInfo GetCurrentPet()
{
return UnslottedPets.Count == 1 && UnslottedPets[0].Type == PetType.Hunter ? UnslottedPets[0] : null;
if (!CurrentPetIndex.HasValue)
return null;
uint? activePetIndex = GetCurrentActivePetIndex();
if (activePetIndex.HasValue)
return ActivePets[activePetIndex.Value] != null ? ActivePets[activePetIndex.Value] : null;
uint? unslottedPetIndex = GetCurrentUnslottedPetIndex();
if (unslottedPetIndex.HasValue)
return unslottedPetIndex < UnslottedPets.Count ? UnslottedPets[(int)unslottedPetIndex.Value] : null;
return null;
}
public uint? GetCurrentActivePetIndex() { return CurrentPetIndex.HasValue && ((CurrentPetIndex & UnslottedPetIndexMask) == 0) ? CurrentPetIndex : null; }
public void SetCurrentActivePetIndex(uint index) { CurrentPetIndex = index; }
uint? GetCurrentUnslottedPetIndex() { return CurrentPetIndex.HasValue && ((CurrentPetIndex & UnslottedPetIndexMask) != 0) ? (CurrentPetIndex & ~UnslottedPetIndexMask) : null; }
public void SetCurrentUnslottedPetIndex(uint index) { CurrentPetIndex = index | UnslottedPetIndexMask; }
}
public enum ActiveStates
+10 -8
View File
@@ -1538,7 +1538,7 @@ namespace Game.Entities
m_bgData.taxiPath[1] = result.Read<uint>(8);
m_bgData.mountSpell = result.Read<uint>(9);
}
void _LoadPetStable(SQLResult result)
void _LoadPetStable(uint summonedPetNumber, SQLResult result)
{
if (result.IsEmpty())
return;
@@ -1568,15 +1568,18 @@ namespace Game.Entities
petInfo.CreatedBySpellId = result.Read<uint>(13);
petInfo.Type = (PetType)result.Read<byte>(14);
petInfo.SpecializationId = result.Read<ushort>(15);
if (slot == PetSaveMode.AsCurrent)
m_petStable.CurrentPet = petInfo;
else if (slot >= PetSaveMode.FirstStableSlot && slot <= PetSaveMode.LastStableSlot)
m_petStable.StabledPets[(int)slot - 1] = petInfo;
if (slot >= PetSaveMode.FirstActiveSlot && slot < PetSaveMode.LastActiveSlot)
m_petStable.ActivePets[(int)slot] = petInfo;
else if (slot >= PetSaveMode.FirstStableSlot && slot < PetSaveMode.LastStableSlot)
m_petStable.StabledPets[slot - PetSaveMode.FirstStableSlot] = petInfo;
else if (slot == PetSaveMode.NotInSlot)
m_petStable.UnslottedPets.Add(petInfo);
} while (result.NextRow());
}
if (Pet.GetLoadPetInfo(m_petStable, 0, summonedPetNumber, null).Item1 != null)
m_temporaryUnsummonedPetNumber = summonedPetNumber;
}
@@ -3080,8 +3083,7 @@ namespace Game.Entities
m_taxi.LoadTaxiMask(taximask); // must be before InitTaxiNodesForLevel
_LoadPetStable(holder.GetResult(PlayerLoginQueryLoad.PetSlots));
m_temporaryUnsummonedPetNumber = summonedPetNumber;
_LoadPetStable(summonedPetNumber, holder.GetResult(PlayerLoginQueryLoad.PetSlots));
// Honor system
// Update Honor kills data
@@ -3590,7 +3592,7 @@ namespace Game.Entities
stmt.AddValue(index++, (ushort)m_ExtraFlags);
PetStable petStable = GetPetStable();
if (petStable != null)
stmt.AddValue(index++, petStable.CurrentPet != null && petStable.CurrentPet.Health > 0 ? petStable.CurrentPet.PetNumber : 0); // summonedPetNumber
stmt.AddValue(index++, petStable.GetCurrentPet() != null && petStable.GetCurrentPet().Health > 0 ? petStable.GetCurrentPet().PetNumber : 0); // summonedPetNumber
else
stmt.AddValue(index++, 0); // summonedPetNumber
stmt.AddValue(index++, (ushort)atLoginFlags);
+39 -67
View File
@@ -4701,12 +4701,19 @@ namespace Game.Entities
return null;
}
public Pet SummonPet(uint entry, float x, float y, float z, float ang, PetType petType, uint duration)
public Pet SummonPet(uint entry, PetSaveMode? slot, float x, float y, float z, float ang, uint duration)
{
return SummonPet(entry, slot, x, y, z, ang, duration, out _);
}
public Pet SummonPet(uint entry, PetSaveMode? slot, float x, float y, float z, float ang, uint duration, out bool isNew)
{
isNew = false;
PetStable petStable = GetOrInitPetStable();
Pet pet = new(this, petType);
if (petType == PetType.Summon && pet.LoadPetFromDB(this, entry, 0, false))
Pet pet = new(this, PetType.Summon);
if (pet.LoadPetFromDB(this, entry, 0, false, slot))
{
if (duration > 0)
pet.SetDuration(duration);
@@ -4718,6 +4725,8 @@ namespace Game.Entities
if (entry == 0)
return null;
// only SUMMON_PET are handled here
pet.Relocate(x, y, z, ang);
if (!pet.IsPositionValid())
{
@@ -4734,7 +4743,7 @@ namespace Game.Entities
return null;
}
if (petType == PetType.Summon && petStable.CurrentPet != null)
if (petStable.GetCurrentPet() != null)
RemovePet(null, PetSaveMode.NotInSlot);
PhasingHandler.InheritPhaseShift(pet, this);
@@ -4747,44 +4756,34 @@ namespace Game.Entities
SetMinion(pet, true);
Cypher.Assert(petStable.CurrentPet == null && (petType != PetType.Hunter || petStable.GetUnslottedHunterPet() == null));
petStable.CurrentPet = new();
pet.FillPetInfo(petStable.CurrentPet);
switch (petType)
{
case PetType.Summon:
// this enables pet details window (Shift+P)
pet.GetCharmInfo().SetPetNumber(petNumber, true);
pet.SetClass(Class.Mage);
pet.SetPetExperience(0);
pet.SetPetNextLevelExperience(1000);
pet.SetFullHealth();
pet.SetFullPower(PowerType.Mana);
pet.SetPetNameTimestamp((uint)GameTime.GetGameTime());
break;
default:
break;
}
// this enables pet details window (Shift+P)
pet.GetCharmInfo().SetPetNumber(petNumber, true);
pet.SetClass(Class.Mage);
pet.SetPetExperience(0);
pet.SetPetNextLevelExperience(1000);
pet.SetFullHealth();
pet.SetFullPower(PowerType.Mana);
pet.SetPetNameTimestamp((uint)GameTime.GetGameTime());
map.AddToMap(pet.ToCreature());
switch (petType)
{
case PetType.Summon:
pet.InitPetCreateSpells();
pet.SavePetToDB(PetSaveMode.AsCurrent);
PetSpellInitialize();
break;
default:
break;
}
Cypher.Assert(petStable.CurrentPetIndex == 0);
petStable.SetCurrentUnslottedPetIndex((uint)petStable.UnslottedPets.Count);
PetStable.PetInfo petInfo = new();
pet.FillPetInfo(petInfo);
petStable.UnslottedPets.Add(petInfo);
pet.InitPetCreateSpells();
pet.SavePetToDB(PetSaveMode.AsCurrent);
PetSpellInitialize();
if (duration > 0)
pet.SetDuration(duration);
//ObjectAccessor.UpdateObjectVisibility(pet);
isNew = true;
return pet;
}
@@ -4829,49 +4828,22 @@ namespace Game.Entities
if (pet == null)
{
if (mode == PetSaveMode.NotInSlot && m_petStable?.CurrentPet != null)
{
// Handle removing pet while it is in "temporarily unsummoned" state, for example on mount
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_CHAR_PET_SLOT_BY_ID);
stmt.AddValue(0, (short)PetSaveMode.NotInSlot);
stmt.AddValue(1, GetGUID().GetCounter());
stmt.AddValue(2, m_petStable.CurrentPet.PetNumber);
DB.Characters.Execute(stmt);
m_petStable.UnslottedPets.Add(m_petStable.CurrentPet);
m_petStable.CurrentPet = null;
}
// Handle removing pet while it is in "temporarily unsummoned" state, for example on mount
if (mode == PetSaveMode.NotInSlot && m_petStable != null && m_petStable.CurrentPetIndex.HasValue)
m_petStable.CurrentPetIndex = null;
return;
}
pet.CombatStop();
if (returnreagent)
{
switch (pet.GetEntry())
{
//warlock pets except imp are removed(?) when logging out
case 1860:
case 1863:
case 417:
case 17252:
mode = PetSaveMode.NotInSlot;
break;
}
}
// only if current pet in slot
pet.SavePetToDB(mode);
Cypher.Assert(m_petStable.CurrentPet != null && m_petStable.CurrentPet.PetNumber == pet.GetCharmInfo().GetPetNumber());
if (mode == PetSaveMode.NotInSlot)
{
m_petStable.UnslottedPets.Add(m_petStable.CurrentPet);
m_petStable.CurrentPet = null;
}
else if (mode == PetSaveMode.AsDeleted)
m_petStable.CurrentPet = null;
PetStable.PetInfo currentPet = m_petStable.GetCurrentPet();
Cypher.Assert(currentPet != null && currentPet.PetNumber == pet.GetCharmInfo().GetPetNumber());
if (mode == PetSaveMode.NotInSlot || mode == PetSaveMode.AsDeleted)
m_petStable.CurrentPetIndex = null;
// else if (stable slots) handled in opcode handlers due to required swaps
// else (current pet) doesnt need to do anything
+8 -3
View File
@@ -761,7 +761,9 @@ namespace Game.Entities
{
Player player = ToPlayer();
PetStable petStable = player.GetOrInitPetStable();
if (petStable.CurrentPet != null || petStable.GetUnslottedHunterPet() != null)
var freeActiveSlot = Array.FindIndex(petStable.ActivePets, petInfo => petInfo == null);
if (freeActiveSlot == -1)
return false;
pet.SetCreatorGUID(GetGUID());
@@ -784,8 +786,11 @@ namespace Game.Entities
pet.InitPetCreateSpells();
pet.SetFullHealth();
petStable.CurrentPet = new();
pet.FillPetInfo(petStable.CurrentPet);
petStable.SetCurrentActivePetIndex((uint)freeActiveSlot);
PetStable.PetInfo petInfo = new();
pet.FillPetInfo(petInfo);
petStable.ActivePets[freeActiveSlot] = petInfo;
return true;
}