*Fix the bug that summon dbc is not read. Now creatures can be summoned.

*Make minipet as tempsummon instead of pet. Make totem as tempsummon.

--HG--
branch : trunk
This commit is contained in:
megamage
2009-03-19 14:41:30 -06:00
parent 74985e8490
commit a2392121f0
21 changed files with 111 additions and 128 deletions
@@ -12,6 +12,7 @@
#include "GridNotifiersImpl.h"
#include "Unit.h"
#include "GameObject.h"
#include "TemporarySummon.h"
#include "sc_creature.h"
#include "sc_gossip.h"
#include "sc_instance.h"
+1 -1
View File
@@ -139,7 +139,7 @@ m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_resp
m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isVehicle(false), m_isTotem(false),
m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_AlreadyCallAssistance(false),
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
m_creatureInfo(NULL), m_reactState(REACT_AGGRESSIVE), m_formationID(0)
m_creatureInfo(NULL), m_reactState(REACT_AGGRESSIVE), m_formationID(0), m_isSummon(false)
{
m_regenTimer = 200;
m_valuesCount = UNIT_END;
+2
View File
@@ -436,6 +436,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
void GetRespawnCoord(float &x, float &y, float &z, float* ori = NULL, float* dist =NULL) const;
uint32 GetEquipmentId() const { return m_equipmentId; }
bool isSummon() const { return m_isSummon; }
bool isPet() const { return m_isPet; }
bool isVehicle() const { return m_isVehicle; }
void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; }
@@ -668,6 +669,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
GossipOptionList m_goptions;
uint8 m_emoteState;
bool m_isSummon;
bool m_isPet; // set only in Pet::Pet
bool m_isVehicle; // set only in Vehicle::Vehicle
bool m_isTotem; // set only in Totem::Totem
+3
View File
@@ -26,6 +26,7 @@
#include "MovementGenerator.h"
#include "ScriptCalls.h"
#include "Pet.h"
#include "TemporarySummon.h"
INSTANTIATE_SINGLETON_1(CreatureAIRegistry);
INSTANTIATE_SINGLETON_1(MovementGeneratorRegistry);
@@ -63,6 +64,8 @@ namespace FactorySelector
ai_factory = ai_registry.GetRegistryItem("PetAI");
else if(creature->isTotem())
ai_factory = ai_registry.GetRegistryItem("TotemAI");
else if(creature->isSummon() && ((TempSummon*)creature)->m_properties && ((TempSummon*)creature)->m_properties->Type == SUMMON_TYPE_MINIPET)
ai_factory = ai_registry.GetRegistryItem("CritterAI");
else if(creature->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
ai_factory = ai_registry.GetRegistryItem("NullCreatureAI");
else if(creature->GetCreatureType() == CREATURE_TYPE_CRITTER)
+5 -4
View File
@@ -1578,9 +1578,9 @@ void WorldObject::AddObjectToRemoveList()
map->AddObjectToRemoveList(this);
}
Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime)
TempSummon* WorldObject::SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime)
{
TemporarySummon* pCreature = new TemporarySummon(GetGUID());
TempSummon* pCreature = new TempSummon(GetGUID());
uint32 team = 0;
if (GetTypeId()==TYPEID_PLAYER)
@@ -1625,12 +1625,13 @@ Vehicle* WorldObject::SummonVehicle(uint32 entry, float x, float y, float z, flo
{
CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry);
if(!ci)
return false;
return NULL;
uint32 id = ci->spells[7]; //temp store id here
if(!id) id = 156;
VehicleEntry const *ve = sVehicleStore.LookupEntry(id);
if(!ve)
return false;
return NULL;
Vehicle *v = new Vehicle;
Map *map = GetMap();
+2 -1
View File
@@ -104,6 +104,7 @@ class Player;
class UpdateMask;
class InstanceData;
class GameObject;
class TempSummon;
class Vehicle;
typedef UNORDERED_MAP<Player*, UpdateData> UpdateDataMapType;
@@ -499,7 +500,7 @@ class TRINITY_DLL_SPEC WorldObject : public Object
Map * GetMap() const;
Map const* GetBaseMap() const;
Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime);
TempSummon* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime);
Vehicle* SummonVehicle(uint32 entry, float x, float y, float z, float ang);
GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime);
Creature* SummonTrigger(float x, float y, float z, float ang, uint32 dur, CreatureAI* (*GetAI)(Creature*) = NULL);
+1 -9
View File
@@ -51,7 +51,7 @@ m_declinedname(NULL)
// pets always have a charminfo, even if they are not actually charmed
CharmInfo* charmInfo = InitCharmInfo();
if(type == MINI_PET || type == POSSESSED_PET) // always passive
if(type == POSSESSED_PET) // always passive
SetReactState(REACT_PASSIVE);
else if(type == GUARDIAN_PET) // always aggressive
SetReactState(REACT_AGGRESSIVE);
@@ -744,11 +744,6 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
return false;
}
if(cinfo->type == CREATURE_TYPE_CRITTER)
{
setPetType(MINI_PET);
return true;
}
SetDisplayId(creature->GetDisplayId());
SetNativeDisplayId(creature->GetNativeDisplayId());
SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
@@ -1725,9 +1720,6 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint3
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
if(getPetType() == MINI_PET) // always non-attackable
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
return true;
}
+2 -3
View File
@@ -30,9 +30,8 @@ enum PetType
SUMMON_PET = 0,
HUNTER_PET = 1,
GUARDIAN_PET = 2,
MINI_PET = 3,
POSSESSED_PET = 4,
MAX_PET_TYPE = 5
POSSESSED_PET = 3,
MAX_PET_TYPE = 4
};
extern char const* petTypeSuffix[MAX_PET_TYPE];
-23
View File
@@ -458,7 +458,6 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this)
m_mover = this;
m_seer = this;
m_miniPet = 0;
m_bgAfkReportedTimer = 0;
m_contestedPvPTimer = 0;
@@ -1426,7 +1425,6 @@ void Player::setDeathState(DeathState s)
RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
// remove uncontrolled pets
RemoveMiniPet();
RemoveGuardians();
// save value before aura remove in Unit::setDeathState
@@ -1888,8 +1886,6 @@ void Player::RemoveFromWorld()
///- Release charmed creatures, unsummon totems and remove pets/guardians
StopCastingCharm();
StopCastingBindSight();
UnsummonAllTotems();
RemoveMiniPet();
RemoveGuardians();
}
@@ -17055,9 +17051,6 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
// only if current pet in slot
switch(pet->getPetType())
{
case MINI_PET:
m_miniPet = 0;
break;
case GUARDIAN_PET:
m_guardianPets.erase(pet->GetGUID());
break;
@@ -17105,22 +17098,6 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
}
}
void Player::RemoveMiniPet()
{
if(Pet* pet = GetMiniPet())
{
pet->Remove(PET_SAVE_AS_DELETED);
m_miniPet = 0;
}
}
Pet* Player::GetMiniPet()
{
if(!m_miniPet)
return NULL;
return ObjectAccessor::GetPet(m_miniPet);
}
void Player::RemoveGuardians()
{
while(!m_guardianPets.empty())
-4
View File
@@ -1052,9 +1052,6 @@ class TRINITY_DLL_SPEC Player : public Unit
Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 despwtime);
void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false);
void RemoveMiniPet();
Pet* GetMiniPet();
void SetMiniPet(Pet* pet) { m_miniPet = pet->GetGUID(); }
void RemoveGuardians();
bool HasGuardianWithEntry(uint32 entry);
void AddGuardian(Pet* pet) { m_guardianPets.insert(pet->GetGUID()); }
@@ -2423,7 +2420,6 @@ class TRINITY_DLL_SPEC Player : public Unit
uint32 m_temporaryUnsummonedPetNumber;
uint32 m_oldpetspell;
uint64 m_miniPet;
GuardianPetList m_guardianPets;
// Player summoning
+11 -5
View File
@@ -2375,13 +2375,19 @@ enum DungeonDifficulties
TOTAL_DIFFICULTIES
};
enum SummonCategory
{
SUMMON_CATEGORY_WILD = 0,
SUMMON_CATEGORY_ALLY = 1,
SUMMON_CATEGORY_GUARDIAN = 2,
SUMMON_CATEGORY_POSSESSED = 3,
SUMMON_CATEGORY_VEHICLE = 4,
};
enum SummonType
{
//SUMMON_TYPE_WILD = 0,
//SUMMON_TYPE_ALLY = 1,
//SUMMON_TYPE_GUARDIAN = 2,
SUMMON_TYPE_POSSESSED = 3,
SUMMON_TYPE_VEHICLE = 4,
SUMMON_TYPE_MINIPET = 5,
SUMMON_TYPE_CRITTER = 41,
SUMMON_TYPE_GUARDIAN = 61,
SUMMON_TYPE_TOTEM_SLOT1 = 63,
+3 -3
View File
@@ -1541,7 +1541,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
switch(cur)
{
case TARGET_UNIT_MINIPET:
if( target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isPet() && ((Pet*)target)->getPetType() == MINI_PET)
if(target->GetGUID() == m_caster->m_TotemSlot[4])
TagUnitMap.push_back(target);
break;
case TARGET_UNIT_TARGET_ALLY:
@@ -4172,9 +4172,9 @@ SpellCastResult Spell::CheckCast(bool strict)
SummonPropertiesEntry const *SummonProperties = sSummonPropertiesStore.LookupEntry(m_spellInfo->EffectMiscValueB[i]);
if(!SummonProperties)
break;
switch(SummonProperties->Group)
switch(SummonProperties->Category)
{
case SUMMON_TYPE_POSSESSED:
case SUMMON_CATEGORY_POSSESSED:
{
if(m_caster->GetPetGUID())
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
+20 -54
View File
@@ -1166,7 +1166,7 @@ void Spell::EffectDummy(uint32 i)
if(!unitTarget)
return;
TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
TempSummon* tempSummon = dynamic_cast<TempSummon*>(unitTarget);
if(!tempSummon)
return;
@@ -3333,11 +3333,6 @@ void Spell::EffectSummonType(uint32 i)
case SUMMON_TYPE_SUMMON:
EffectSummon(i);
break;
case SUMMON_TYPE_CRITTER:
case SUMMON_TYPE_CRITTER2:
case SUMMON_TYPE_CRITTER3:
EffectSummonCritter(i);
break;
case SUMMON_TYPE_TOTEM_SLOT1:
case SUMMON_TYPE_TOTEM_SLOT2:
case SUMMON_TYPE_TOTEM_SLOT3:
@@ -3358,15 +3353,18 @@ void Spell::EffectSummonType(uint32 i)
sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
return;
}
switch(SummonProperties->Group)
switch(SummonProperties->Category)
{
default:
EffectSummonWild(i);
if(SummonProperties->Type == SUMMON_TYPE_MINIPET)
EffectSummonCritter(i);
else
EffectSummonWild(i);
break;
case SUMMON_TYPE_POSSESSED:
case SUMMON_CATEGORY_POSSESSED:
EffectSummonPossessed(i);
break;
case SUMMON_TYPE_VEHICLE:
case SUMMON_CATEGORY_VEHICLE:
EffectSummonVehicle(i);
break;
}
@@ -6036,32 +6034,6 @@ void Spell::EffectSummonCritter(uint32 i)
if(!pet_entry)
return;
Pet* old_critter = player->GetMiniPet();
// for same pet just despawn
if(old_critter && old_critter->GetEntry() == pet_entry)
{
player->RemoveMiniPet();
return;
}
// despawn old pet before summon new
if(old_critter)
player->RemoveMiniPet();
// summon new pet
Pet* critter = new Pet(MINI_PET);
Map *map = m_caster->GetMap();
uint32 pet_number = objmgr.GeneratePetNumber();
if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(),
pet_entry, pet_number))
{
sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
delete critter;
return;
}
float x,y,z;
// If dest location if present
if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
@@ -6072,40 +6044,32 @@ void Spell::EffectSummonCritter(uint32 i)
}
// Summon if dest location not present near caster
else
m_caster->GetClosePoint(x,y,z,critter->GetObjectSize());
m_caster->GetClosePoint(x,y,z,m_caster->GetObjectSize());
critter->Relocate(x,y,z,m_caster->GetOrientation());
if(!critter->IsPositionValid())
{
sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",
critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
delete critter;
int32 duration = GetSpellDuration(m_spellInfo);
TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
TempSummon *critter = m_caster->SummonCreature(pet_entry, x, y, z, m_caster->GetOrientation(), summonType, duration);
if(!critter)
return;
}
critter->SetOwnerGUID(m_caster->GetGUID());
critter->SetCreatorGUID(m_caster->GetGUID());
critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
critter->AIM_Initialize();
critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
//critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
critter->SetMaxHealth(1);
critter->SetHealth(1);
critter->SetLevel(1);
// set timer for unsummon
int32 duration = GetSpellDuration(m_spellInfo);
if(duration > 0)
critter->SetDuration(duration);
critter->SetReactState(REACT_PASSIVE);
critter->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
std::string name = player->GetName();
name.append(petTypeSuffix[critter->getPetType()]);
name.append(petTypeSuffix[3]);
critter->SetName( name );
player->SetMiniPet(critter);
map->Add((Creature*)critter);
critter->SetSummonProperties(sSummonPropertiesStore.LookupEntry(m_spellInfo->EffectMiscValueB[i]));
}
void Spell::EffectKnockBack(uint32 i)
@@ -6787,6 +6751,8 @@ void Spell::EffectSummonVehicle(uint32 i)
float x, y, z;
m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
Vehicle *vehicle = m_caster->SummonVehicle(entry, x, y, z, m_caster->GetOrientation());
if(!vehicle)
return;
vehicle->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
}
+42 -8
View File
@@ -23,12 +23,14 @@
#include "ObjectAccessor.h"
#include "CreatureAI.h"
TemporarySummon::TemporarySummon( uint64 summoner ) :
TempSummon::TempSummon( uint64 summoner ) :
Creature(), m_type(TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN), m_timer(0), m_lifetime(0), m_summoner(summoner)
, m_properties(NULL)
{
m_isSummon = true;
}
void TemporarySummon::Update( uint32 diff )
void TempSummon::Update( uint32 diff )
{
if (m_deathState == DEAD)
{
@@ -157,7 +159,7 @@ void TemporarySummon::Update( uint32 diff )
Creature::Update( diff );
}
void TemporarySummon::Summon(TempSummonType type, uint32 lifetime)
void TempSummon::Summon(TempSummonType type, uint32 lifetime)
{
m_type = type;
m_timer = lifetime;
@@ -168,19 +170,51 @@ void TemporarySummon::Summon(TempSummonType type, uint32 lifetime)
AIM_Initialize();
}
void TemporarySummon::UnSummon()
void TempSummon::UnSummon()
{
CleanupsBeforeDelete();
AddObjectToRemoveList();
Unit* sum = m_summoner ? ObjectAccessor::GetUnit(*this, m_summoner) : NULL;
if (sum && sum->GetTypeId() == TYPEID_UNIT && ((Creature*)sum)->IsAIEnabled)
Unit* owner = GetSummoner();
if(owner)
{
((Creature*)sum)->AI()->SummonedCreatureDespawn(this);
if(owner->GetTypeId() == TYPEID_UNIT && ((Creature*)owner)->IsAIEnabled)
((Creature*)owner)->AI()->SummonedCreatureDespawn(this);
if(uint32 slot = m_properties->Slot)
{
--slot;
owner->m_TotemSlot[slot] = 0;
}
}
}
void TemporarySummon::SaveToDB()
void TempSummon::SetSummonProperties(SummonPropertiesEntry const *properties)
{
if(!properties)
return;
m_properties = properties;
if(uint32 slot = m_properties->Slot)
{
--slot;
Unit* owner = GetSummoner();
if(owner)
{
if(owner->m_TotemSlot[slot] && owner->m_TotemSlot[slot] != GetGUID())
{
Creature *OldTotem = ObjectAccessor::GetCreature(*this, owner->m_TotemSlot[slot]);
if(OldTotem && OldTotem->isSummon())
((TempSummon*)OldTotem)->UnSummon();
}
owner->m_TotemSlot[slot] = GetGUID();
}
}
AIM_Initialize();
}
void TempSummon::SaveToDB()
{
}
+7 -4
View File
@@ -24,16 +24,19 @@
#include "Creature.h"
#include "ObjectAccessor.h"
class TemporarySummon : public Creature
class TempSummon : public Creature
{
public:
explicit TemporarySummon(uint64 summoner = 0);
virtual ~TemporarySummon(){};
explicit TempSummon(uint64 summoner = 0);
virtual ~TempSummon(){};
void Update(uint32 time);
void Summon(TempSummonType type, uint32 lifetime);
void UnSummon();
virtual void UnSummon();
void SaveToDB();
Unit* GetSummoner() const { return m_summoner ? ObjectAccessor::GetUnit(*this, m_summoner) : NULL; }
void SetSummonProperties(SummonPropertiesEntry const *properties);
SummonPropertiesEntry const *m_properties;
private:
TempSummonType m_type;
uint32 m_timer;
+1 -1
View File
@@ -26,7 +26,7 @@
#include "ObjectMgr.h"
#include "SpellMgr.h"
Totem::Totem() : Creature()
Totem::Totem() : TempSummon(0)
{
m_isTotem = true;
m_duration = 0;
+2 -2
View File
@@ -21,7 +21,7 @@
#ifndef TRINITYCORE_TOTEM_H
#define TRINITYCORE_TOTEM_H
#include "Creature.h"
#include "TemporarySummon.h"
enum TotemType
{
@@ -32,7 +32,7 @@ enum TotemType
#define SENTRY_TOTEM_ENTRY 3968
class Totem : public Creature
class Totem : public TempSummon
{
public:
explicit Totem();
+5 -3
View File
@@ -50,6 +50,7 @@
#include "PetAI.h"
#include "NullCreatureAI.h"
#include "Traveller.h"
#include "TemporarySummon.h"
#include <math.h>
@@ -4381,7 +4382,7 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
{
if(AurSpellInfo->Effect[i] == SPELL_EFFECT_SUMMON)
if(SummonPropertiesEntry const *SummonProperties = sSummonPropertiesStore.LookupEntry(AurSpellInfo->EffectMiscValueB[i]))
if(SummonProperties->Group == SUMMON_TYPE_POSSESSED)
if(SummonProperties->Category == SUMMON_CATEGORY_POSSESSED)
{
((Player*)caster)->StopCastingCharm();
break;
@@ -8325,8 +8326,8 @@ void Unit::UnsummonAllTotems()
continue;
Creature *OldTotem = ObjectAccessor::GetCreature(*this, m_TotemSlot[i]);
if (OldTotem && OldTotem->isTotem())
((Totem*)OldTotem)->UnSummon();
if(OldTotem && OldTotem->isSummon())
((TempSummon*)OldTotem)->UnSummon();
}
}
@@ -11355,6 +11356,7 @@ void Unit::RemoveFromWorld()
// cleanup
if(IsInWorld())
{
UnsummonAllTotems();
RemoveCharmAuras();
RemoveBindSightAuras();
RemoveNotOwnSingleTargetAuras();
+1 -1
View File
@@ -822,7 +822,7 @@ enum ReactiveType
};
#define MAX_REACTIVE 3
#define MAX_TOTEM 4
#define MAX_TOTEM 6
struct AuraSlotEntry
{
+1 -1
View File
@@ -337,7 +337,7 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRuneCostStore, dbcPath,"SpellRuneCost.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellShapeshiftStore, dbcPath,"SpellShapeshiftForm.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sStableSlotPricesStore, dbcPath,"StableSlotPrices.dbc");
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSummonPropertiesStore, dbcPath,"SummonProperties.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSummonPropertiesStore, dbcPath,"SummonProperties.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentStore, dbcPath,"Talent.dbc");
// create talent spells set
+1 -1
View File
@@ -1401,7 +1401,7 @@ struct StableSlotPricesEntry
struct SummonPropertiesEntry
{
uint32 Id; // 0
uint32 Group; // 1, 0 - can't be controlled?, 1 - something guardian?, 2 - pet?, 3 - something controllable?, 4 - taxi/mount?
uint32 Category; // 1, 0 - can't be controlled?, 1 - something guardian?, 2 - pet?, 3 - something controllable?, 4 - taxi/mount?
uint32 Unk2; // 2, 14 rows > 0
uint32 Type; // 3, see enum
uint32 Slot; // 4, 0-6