aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/game/Creature.cpp7
-rw-r--r--src/game/Creature.h24
-rw-r--r--src/game/CreatureAISelector.cpp11
-rw-r--r--src/game/Map.h3
-rw-r--r--src/game/Object.cpp89
-rw-r--r--src/game/Pet.cpp43
-rw-r--r--src/game/Pet.h5
-rw-r--r--src/game/PetHandler.cpp4
-rw-r--r--src/game/Player.cpp84
-rw-r--r--src/game/Player.h11
-rw-r--r--src/game/SharedDefines.h18
-rw-r--r--src/game/Spell.h8
-rw-r--r--src/game/SpellAuras.cpp1
-rw-r--r--src/game/SpellEffects.cpp371
-rw-r--r--src/game/TemporarySummon.cpp162
-rw-r--r--src/game/TemporarySummon.h25
-rw-r--r--src/game/Totem.cpp4
-rw-r--r--src/game/Totem.h2
-rw-r--r--src/game/Unit.cpp38
-rw-r--r--src/game/Unit.h6
-rw-r--r--src/game/Vehicle.cpp2
21 files changed, 489 insertions, 429 deletions
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 03f5740fd1c..34ca8bb31e0 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -136,10 +136,10 @@ Unit(),
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0),
m_lootMoney(0), m_lootRecipient(0),
m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
-m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isVehicle(false), m_isTotem(false),
+m_gossipOptionLoaded(false), m_emoteState(0),
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_isSummon(false)
+m_creatureInfo(NULL), m_reactState(REACT_AGGRESSIVE), m_formationID(0), m_summonMask(SUMMON_MASK_NONE)
{
m_regenTimer = 200;
m_valuesCount = UNIT_END;
@@ -597,9 +597,10 @@ bool Creature::AIM_Initialize(CreatureAI* ai)
return false;
}
- if(i_AI) delete i_AI;
+ UnitAI *oldAI = i_AI;
i_motionMaster.Initialize();
i_AI = ai ? ai : FactorySelector::selectAI(this);
+ if(oldAI) delete oldAI;
IsAIEnabled = true;
return true;
}
diff --git a/src/game/Creature.h b/src/game/Creature.h
index 8d4a160aab3..bc59826ce51 100644
--- a/src/game/Creature.h
+++ b/src/game/Creature.h
@@ -136,6 +136,16 @@ enum CreatureFlagsExtra
CREATURE_FLAG_EXTRA_NO_TAUNT = 0x00010000, // cannot be taunted
};
+enum SummonMask
+{
+ SUMMON_MASK_NONE = 0x00000000,
+ SUMMON_MASK_SUMMON = 0x00000001,
+ SUMMON_MASK_GUARDIAN = 0x00000002,
+ SUMMON_MASK_TOTEM = 0x00000004,
+ SUMMON_MASK_PET = 0x00000008,
+ SUMMON_MASK_VEHICLE = 0x00000010,
+};
+
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform
#if defined( __GNUC__ )
#pragma pack(1)
@@ -436,11 +446,12 @@ 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; }
+ uint32 GetSummonMask() const { return m_summonMask; }
+ bool isSummon() const { return m_summonMask & SUMMON_MASK_SUMMON; }
+ bool isPet() const { return m_summonMask & SUMMON_MASK_PET; }
+ bool isVehicle() const { return m_summonMask & SUMMON_MASK_VEHICLE; }
+ bool isTotem() const { return m_summonMask & SUMMON_MASK_TOTEM; }
void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; }
- bool isTotem() const { return m_isTotem; }
bool isRacialLeader() const { return GetCreatureInfo()->RacialLeader; }
bool isCivilian() const { return GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_CIVILIAN; }
bool isTrigger() const { return GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER; }
@@ -669,10 +680,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
+ uint32 m_summonMask;
ReactStates m_reactState; // for AI, not charmInfo
void RegenerateMana();
void RegenerateHealth();
diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp
index 402ea7ae2fb..a9c2f9b5dd1 100644
--- a/src/game/CreatureAISelector.cpp
+++ b/src/game/CreatureAISelector.cpp
@@ -64,10 +64,17 @@ 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->isSummon() && ((TempSummon*)creature)->m_Properties)
+ {
+ if(((TempSummon*)creature)->m_Properties->Category == SUMMON_CATEGORY_GUARDIAN
+ || ((TempSummon*)creature)->m_Properties->Type == SUMMON_TYPE_GUARDIAN
+ || ((TempSummon*)creature)->m_Properties->Type == SUMMON_TYPE_MINION)
+ ai_factory = ai_registry.GetRegistryItem("PetAI");
+ else if(((TempSummon*)creature)->m_Properties->Type == SUMMON_TYPE_MINIPET)
+ ai_factory = ai_registry.GetRegistryItem("CritterAI");
+ }
else if(creature->GetCreatureType() == CREATURE_TYPE_CRITTER)
ai_factory = ai_registry.GetRegistryItem("CritterAI");
}
diff --git a/src/game/Map.h b/src/game/Map.h
index 4b4b8fecb2b..bd3ca891a58 100644
--- a/src/game/Map.h
+++ b/src/game/Map.h
@@ -43,6 +43,7 @@ class InstanceData;
class Group;
class InstanceSave;
class WorldObject;
+class TempSummon;
namespace ZThread
{
@@ -414,6 +415,8 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
template<class NOTIFIER> void VisitAll(const float &x, const float &y, float radius, NOTIFIER &notifier);
template<class NOTIFIER> void VisitWorld(const float &x, const float &y, float radius, NOTIFIER &notifier);
template<class NOTIFIER> void VisitGrid(const float &x, const float &y, float radius, NOTIFIER &notifier);
+
+ TempSummon *SummonCreature(uint32 entry, float x, float y, float z, float angle, SummonPropertiesEntry const *properties = NULL, uint32 duration = 0, Unit *summoner = NULL);
private:
void LoadVMap(int pX, int pY);
void LoadMap(uint32 mapid, uint32 instanceid, int x,int y);
diff --git a/src/game/Object.cpp b/src/game/Object.cpp
index eda29509b8c..770c2d14899 100644
--- a/src/game/Object.cpp
+++ b/src/game/Object.cpp
@@ -44,6 +44,7 @@
#include "GridNotifiersImpl.h"
#include "TemporarySummon.h"
+#include "Totem.h"
uint32 GuidHigh2TypeId(uint32 guid_hi)
{
@@ -1578,34 +1579,88 @@ void WorldObject::AddObjectToRemoveList()
map->AddObjectToRemoveList(this);
}
-TempSummon* WorldObject::SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime)
+TempSummon *Map::SummonCreature(uint32 entry, float x, float y, float z, float angle, SummonPropertiesEntry const *properties, uint32 duration, Unit *summoner)
{
- TempSummon* pCreature = new TempSummon(GetGUID());
+ uint32 mask = SUMMON_MASK_SUMMON;
+ if(properties)
+ {
+ if(properties->Category == SUMMON_CATEGORY_GUARDIAN
+ || properties->Type == SUMMON_TYPE_GUARDIAN
+ || properties->Type == SUMMON_TYPE_MINION)
+ mask = SUMMON_MASK_GUARDIAN;
+ else if(properties->Type == SUMMON_TYPE_TOTEM)
+ mask = SUMMON_MASK_TOTEM;
+ else if(properties->Category == SUMMON_CATEGORY_VEHICLE
+ || properties->Type == SUMMON_TYPE_VEHICLE)
+ mask = SUMMON_MASK_VEHICLE;
+ }
- uint32 team = 0;
- if (GetTypeId()==TYPEID_PLAYER)
- team = ((Player*)this)->GetTeam();
+ TempSummon *summon = NULL;
+ bool ok = true;
+ uint32 phase = PHASEMASK_NORMAL, team = 0;
+ if(summoner)
+ {
+ phase = summoner->GetPhaseMask();
+ if(summoner->GetTypeId() == TYPEID_PLAYER)
+ team = ((Player*)summoner)->GetTeam();
+ }
- if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), GetMap(), GetPhaseMask(), id, team))
+ switch(mask)
{
- delete pCreature;
+ case SUMMON_MASK_SUMMON:
+ summon = new TempSummon(properties, summoner);
+ ok = summon->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), this, phase, entry, team);
+ break;
+ case SUMMON_MASK_GUARDIAN:
+ summon = new Guardian(properties, summoner);
+ team = objmgr.GeneratePetNumber();
+ ok = summon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), this, phase, entry, team);
+ // this enables pet details window (Shift+P)
+ summon->GetCharmInfo()->SetPetNumber(team, false);
+ break;
+ case SUMMON_MASK_TOTEM:
+ summon = new Totem(properties, summoner);
+ ok = summon->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), this, phase, entry, team);
+ break;
+ default:
+ return NULL;
+ }
+ if(!ok)
+ {
+ delete summon;
return NULL;
}
- if (x == 0.0f && y == 0.0f && z == 0.0f)
- GetClosePoint(x, y, z, pCreature->GetObjectSize());
-
- pCreature->Relocate(x, y, z, ang);
-
- if(!pCreature->IsPositionValid())
+ summon->Relocate(x, y, z, angle);
+ if(!summon->IsPositionValid())
{
- sLog.outError("ERROR: Creature (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY());
- delete pCreature;
+ sLog.outError("ERROR: Creature (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",summon->GetGUIDLow(),summon->GetEntry(),summon->GetPositionX(),summon->GetPositionY());
+ delete summon;
return NULL;
}
+ summon->InitSummon(duration);
+
+ Add((Creature*)summon);
+
+ return summon;
+}
+
+TempSummon* WorldObject::SummonCreature(uint32 entry, float x, float y, float z, float ang, TempSummonType spwtype, uint32 duration)
+{
+ if(!IsInWorld())
+ return NULL;
+
+ if (x == 0.0f && y == 0.0f && z == 0.0f)
+ GetClosePoint(x, y, z, GetObjectSize());
+
+ TempSummon *pCreature = GetMap()->SummonCreature(entry, x, y, z, ang, NULL, duration, GetTypeId() == TYPEID_UNIT ? (Unit*)this : NULL);
+ if(!pCreature)
+ return NULL;
+
pCreature->SetHomePosition(x, y, z, ang);
- pCreature->Summon(spwtype, despwtime);
+ pCreature->InitSummon(duration);
+ pCreature->SetTempSummonType(spwtype);
if(GetTypeId()==TYPEID_UNIT && ((Creature*)this)->IsAIEnabled)
((Creature*)this)->AI()->JustSummoned(pCreature);
@@ -1617,7 +1672,6 @@ TempSummon* WorldObject::SummonCreature(uint32 id, float x, float y, float z, fl
pCreature->CastSpell(pCreature, pCreature->m_spells[0], false, 0, 0, GetGUID());
}
- //return the creature therewith the summoner has access to it
return pCreature;
}
@@ -1727,7 +1781,6 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
switch(petType)
{
- case GUARDIAN_PET:
case POSSESSED_PET:
pet->SetUInt32Value(UNIT_FIELD_FLAGS,0);
AddGuardian(pet);
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
index d7721070e63..af3725c626c 100644
--- a/src/game/Pet.cpp
+++ b/src/game/Pet.cpp
@@ -44,19 +44,15 @@ Creature(), m_petType(type), m_removed(false), m_happinessTimer(7500), m_duratio
m_resetTalentsCost(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_auraRaidUpdateMask(0), m_loading(false),
m_declinedname(NULL)
{
- m_isPet = true;
+ m_summonMask |= SUMMON_MASK_PET;
m_name = "Pet";
m_regenTimer = 4000;
// pets always have a charminfo, even if they are not actually charmed
- CharmInfo* charmInfo = InitCharmInfo();
+ InitCharmInfo();
if(type == POSSESSED_PET) // always passive
SetReactState(REACT_PASSIVE);
- else if(type == GUARDIAN_PET) // always aggressive
- SetReactState(REACT_AGGRESSIVE);
-
- //m_isActive = true;
}
Pet::~Pet()
@@ -930,41 +926,6 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
}
break;
}
- case GUARDIAN_PET:
- SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
- SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
-
- switch(GetEntry())
- {
- case 1964: //force of nature
- SetCreateHealth(30 + 30*petlevel);
- SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 2.5f - (petlevel / 2)));
- SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 2.5f + (petlevel / 2)));
- break;
- case 15352: //earth elemental 36213
- SetCreateHealth(100 + 120*petlevel);
- SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
- SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
- break;
- case 15438: //fire elemental
- SetCreateHealth(40*petlevel);
- SetCreateMana(28 + 10*petlevel);
- SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 4 - petlevel));
- SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 4 + petlevel));
- break;
- default:
- SetCreateMana(28 + 10*petlevel);
- SetCreateHealth(28 + 30*petlevel);
-
- // FIXME: this is wrong formula, possible each guardian pet have own damage formula
- //these formula may not be correct; however, it is designed to be close to what it should be
- //this makes dps 0.5 of pets level
- SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
- //damage range is then petlevel / 2
- SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
- break;
- }
- break;
default:
sLog.outError("Pet have incorrect type (%u) for levelup.", getPetType());
break;
diff --git a/src/game/Pet.h b/src/game/Pet.h
index d8053fdfd67..b78a5ccc293 100644
--- a/src/game/Pet.h
+++ b/src/game/Pet.h
@@ -29,9 +29,8 @@ enum PetType
{
SUMMON_PET = 0,
HUNTER_PET = 1,
- GUARDIAN_PET = 2,
- POSSESSED_PET = 3,
- MAX_PET_TYPE = 4
+ POSSESSED_PET = 2,
+ MAX_PET_TYPE = 4,
};
extern char const* petTypeSuffix[MAX_PET_TYPE];
diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp
index 9f9cb3a33a3..cc560412bbb 100644
--- a/src/game/PetHandler.cpp
+++ b/src/game/PetHandler.cpp
@@ -157,7 +157,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
p->setDeathState(CORPSE);
}
else // charmed or possessed
- _player->Uncharm();
+ _player->StopCastingCharm();
break;
default:
sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", flag, spellid);
@@ -493,7 +493,7 @@ void WorldSession::HandlePetAbandon( WorldPacket & recv_data )
_player->RemovePet((Pet*)pet,PET_SAVE_AS_DELETED);
}
else if(pet->GetGUID() == _player->GetCharmGUID())
- _player->Uncharm();
+ _player->StopCastingCharm();
}
}
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index f168728108e..c047e3f8794 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -1424,9 +1424,6 @@ void Player::setDeathState(DeathState s)
//FIXME: is pet dismissed at dying or releasing spirit? if second, add setDeathState(DEAD) to HandleRepopRequestOpcode and define pet unsummon here with (s == DEAD)
RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
- // remove uncontrolled pets
- RemoveGuardians();
-
// save value before aura remove in Unit::setDeathState
ressSpellId = GetUInt32Value(PLAYER_SELF_RES_SPELL);
@@ -1886,7 +1883,6 @@ void Player::RemoveFromWorld()
///- Release charmed creatures, unsummon totems and remove pets/guardians
StopCastingCharm();
StopCastingBindSight();
- RemoveGuardians();
}
for(int i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; i++)
@@ -17051,11 +17047,8 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
// only if current pet in slot
switch(pet->getPetType())
{
- case GUARDIAN_PET:
- m_guardianPets.erase(pet->GetGUID());
- break;
case POSSESSED_PET:
- m_guardianPets.erase(pet->GetGUID());
+ m_Guardians.erase(pet->GetGUID());
pet->RemoveCharmedOrPossessedBy(NULL);
break;
default:
@@ -17098,30 +17091,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
}
}
-void Player::RemoveGuardians()
-{
- while(!m_guardianPets.empty())
- {
- uint64 guid = *m_guardianPets.begin();
- if(Pet* pet = ObjectAccessor::GetPet(guid))
- pet->Remove(PET_SAVE_AS_DELETED);
-
- m_guardianPets.erase(guid);
- }
-}
-
-bool Player::HasGuardianWithEntry(uint32 entry)
-{
- // pet guid middle part is entry (and creature also)
- // and in guardian list must be guardians with same entry _always_
- for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr)
- if(GUID_ENPART(*itr)==entry)
- return true;
-
- return false;
-}
-
-void Player::Uncharm()
+void Player::StopCastingCharm()
{
Unit* charm = GetCharm();
if(!charm)
@@ -17295,13 +17265,14 @@ void Player::PetSpellInitialize()
data << uint32(itr->second); // category cooldown
}
+ data.hexlike();
+
GetSession()->SendPacket(&data);
}
void Player::PossessSpellInitialize()
{
Unit* charm = GetCharm();
-
if(!charm)
return;
@@ -17313,24 +17284,23 @@ void Player::PossessSpellInitialize()
return;
}
- uint8 addlist = 0;
- WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25);// first line + actionbar + spellcount + spells + last adds
+ WorldPacket data(SMSG_PET_SPELLS, 20+40+1+1);
- //16
+ //basic info 20
data << uint64(charm->GetGUID());
- data << uint32(0x00000000);
- data << uint32(0);
- data << uint8(0) << uint8(0) << uint16(0);
+ data << uint32(0); //family
+ data << uint32(0); //0
+ data << uint8(0) << uint8(0) << uint16(0); //reactstate, commandstate, 0
- for(uint32 i = 0; i < 10; i++) //40
- {
+ //action bar 40
+ for(uint32 i = 0; i < 10; i++)
data << uint16(charmInfo->GetActionBarEntry(i)->SpellOrAction) << uint16(charmInfo->GetActionBarEntry(i)->Type);
- }
- data << uint8(addlist); //1
+ //addlist 1
+ data << uint8(0);
- uint8 count = 0;
- data << uint8(count); // cooldowns count
+ //cooldown 1
+ data << uint8(0);
GetSession()->SendPacket(&data);
}
@@ -17377,7 +17347,8 @@ void Player::VehicleSpellInitialize()
void Player::CharmSpellInitialize()
{
Unit* charm = GetCharm();
-
+ if(!charm && GetPetGUID())
+ charm = GetUnit(*this, GetPetGUID());
if(!charm)
return;
@@ -17389,14 +17360,12 @@ void Player::CharmSpellInitialize()
}
uint8 addlist = 0;
-
if(charm->GetTypeId() != TYPEID_PLAYER)
{
CreatureInfo const *cinfo = ((Creature*)charm)->GetCreatureInfo();
-
- if(cinfo && cinfo->type == CREATURE_TYPE_DEMON && getClass() == CLASS_WARLOCK)
+ //if(cinfo && cinfo->type == CREATURE_TYPE_DEMON && getClass() == CLASS_WARLOCK)
{
- for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
+ for(uint32 i = 0; i < 4; ++i)
{
if(charmInfo->GetCharmSpell(i)->spellId)
++addlist;
@@ -17404,10 +17373,11 @@ void Player::CharmSpellInitialize()
}
}
- WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25);// first line + actionbar + spellcount + spells + last adds
+ WorldPacket data(SMSG_PET_SPELLS, 20+40+1+4*addlist+1);// first line + actionbar + spellcount + spells + last adds
+ //basic info 20
data << uint64(charm->GetGUID());
- data << uint32(0x00000000);
+ data << uint32(0);
data << uint32(0);
if(charm->GetTypeId() != TYPEID_PLAYER)
data << uint8(((Creature*)charm)->GetReactState()) << uint8(charmInfo->GetCommandState());
@@ -17415,16 +17385,17 @@ void Player::CharmSpellInitialize()
data << uint8(0) << uint8(0);
data << uint16(0);
- for(uint32 i = 0; i < 10; i++) //40
+ //action bar 40
+ for(uint32 i = 0; i < 10; ++i) //40
{
data << uint16(charmInfo->GetActionBarEntry(i)->SpellOrAction) << uint16(charmInfo->GetActionBarEntry(i)->Type);
}
+ //add list
data << uint8(addlist); //1
-
if(addlist)
{
- for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
+ for(uint32 i = 0; i < 4; ++i)
{
CharmSpellEntry *cspell = charmInfo->GetCharmSpell(i);
if(cspell->spellId)
@@ -17435,9 +17406,12 @@ void Player::CharmSpellInitialize()
}
}
+ //cooldown
uint8 count = 0;
data << uint8(count); // cooldowns count
+ data.hexlike();
+
GetSession()->SendPacket(&data);
}
diff --git a/src/game/Player.h b/src/game/Player.h
index aec16d27b71..5c821134c86 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -298,8 +298,6 @@ typedef std::map<RepListID,FactionState> FactionStateList;
typedef std::map<uint32,ReputationRank> ForcedReactions;
-typedef std::set<uint64> GuardianPetList;
-
struct EnchantDuration
{
EnchantDuration() : item(NULL), slot(MAX_ENCHANTMENT_SLOT), leftduration(0) {};
@@ -1052,11 +1050,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 RemoveGuardians();
- bool HasGuardianWithEntry(uint32 entry);
- void AddGuardian(Pet* pet) { m_guardianPets.insert(pet->GetGUID()); }
- GuardianPetList const& GetGuardians() const { return m_guardianPets; }
- void Uncharm();
uint32 GetPhaseMaskForSpawn() const; // used for proper set phase for DB at GM-mode creature/GO spawn
void Say(const std::string& text, const uint32 language);
@@ -2058,7 +2051,7 @@ class TRINITY_DLL_SPEC Player : public Unit
void SetSeer(WorldObject *target) { m_seer = target; }
void CreateViewpoint(WorldObject *target);
WorldObject* GetViewpoint() const;
- void StopCastingCharm() { Uncharm(); }
+ void StopCastingCharm();
void StopCastingBindSight();
// Transports
@@ -2420,8 +2413,6 @@ class TRINITY_DLL_SPEC Player : public Unit
uint32 m_temporaryUnsummonedPetNumber;
uint32 m_oldpetspell;
- GuardianPetList m_guardianPets;
-
// Player summoning
time_t m_summon_expire;
uint32 m_summon_mapid;
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
index 02bc03bced2..fe4a520090d 100644
--- a/src/game/SharedDefines.h
+++ b/src/game/SharedDefines.h
@@ -2386,18 +2386,24 @@ enum SummonCategory
enum SummonType
{
+ SUMMON_TYPE_NONE = 0,
+ SUMMON_TYPE_WILD1 = 1,
+ SUMMON_TYPE_GUARDIAN = 2,
+ SUMMON_TYPE_MINION = 3,
+ SUMMON_TYPE_TOTEM = 4,
SUMMON_TYPE_MINIPET = 5,
+ SUMMON_TYPE_GUARDIAN2 = 6,
+ SUMMON_TYPE_WILD2 = 7,
+ SUMMON_TYPE_WILD3 = 8,
+ SUMMON_TYPE_WILD4 = 9,
+ SUMMON_TYPE_VEHICLE = 10,
+ SUMMON_TYPE_OBJECT = 11,
SUMMON_TYPE_CRITTER = 41,
- SUMMON_TYPE_GUARDIAN = 61,
- SUMMON_TYPE_TOTEM_SLOT1 = 63,
+ //SUMMON_TYPE_GUARDIAN = 61,
SUMMON_TYPE_WILD = 64,
SUMMON_TYPE_DEMON = 66,
SUMMON_TYPE_SUMMON = 67,
- SUMMON_TYPE_TOTEM_SLOT2 = 81,
- SUMMON_TYPE_TOTEM_SLOT3 = 82,
- SUMMON_TYPE_TOTEM_SLOT4 = 83,
- SUMMON_TYPE_TOTEM = 121,
SUMMON_TYPE_UNKNOWN3 = 181,
SUMMON_TYPE_UNKNOWN4 = 187,
SUMMON_TYPE_UNKNOWN1 = 247,
diff --git a/src/game/Spell.h b/src/game/Spell.h
index 0301f5537eb..7b68bd97429 100644
--- a/src/game/Spell.h
+++ b/src/game/Spell.h
@@ -276,10 +276,7 @@ class Spell
void EffectDualWield(uint32 i);
void EffectPickPocket(uint32 i);
void EffectAddFarsight(uint32 i);
- void EffectSummonPossessed(uint32 i);
- void EffectSummonVehicle(uint32 i);
void EffectSummonWild(uint32 i);
- void EffectSummonGuardian(uint32 i);
void EffectHealMechanical(uint32 i);
void EffectJump(uint32 i);
void EffectTeleUnitsFaceCaster(uint32 i);
@@ -307,7 +304,6 @@ class Spell
void EffectSummonPlayer(uint32 i);
void EffectActivateObject(uint32 i);
void EffectApplyGlyph(uint32 i);
- void EffectSummonTotem(uint32 i);
void EffectEnchantHeldItem(uint32 i);
void EffectSummonObject(uint32 i);
void EffectResurrect(uint32 i);
@@ -600,6 +596,10 @@ class Spell
void SpellDamageHeal(uint32 i);
void GetSummonPosition(float &x, float &y, float &z, float radius = 0.0f, uint32 count = 0);
+ void SummonTotem (uint32 entry, SummonPropertiesEntry const *properties);
+ void SummonGuardian (uint32 entry, SummonPropertiesEntry const *properties);
+ void SummonPossessed(uint32 entry, SummonPropertiesEntry const *properties);
+ void SummonVehicle (uint32 entry, SummonPropertiesEntry const *properties);
SpellCastResult CanOpenLock(uint32 effIndex, uint32 lockid, SkillType& skillid, int32& reqSkillValue, int32& skillValue);
// -------------------------------------------
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index 79a87bed293..9fdedb6f430 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -5440,6 +5440,7 @@ void Aura::CleanupTriggeredSpells()
if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL &&
GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()])
return;
+
m_target->RemoveAurasDueToSpell(tSpellId);
}
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index e363b2cb41e..583087a5106 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -3313,15 +3313,12 @@ void Spell::EffectApplyAreaAura(uint32 i)
void Spell::EffectSummonType(uint32 i)
{
+ uint32 entry = m_spellInfo->EffectMiscValue[i];
+ if(!entry)
+ return;
+
switch(m_spellInfo->EffectMiscValueB[i])
{
- case SUMMON_TYPE_GUARDIAN:
- EffectSummonGuardian(i);
- break;
- case SUMMON_TYPE_FORCE_OF_NATURE:
- case SUMMON_TYPE_FERAL_SPIRIT:
- EffectSummonGuardian(i);
- break;
case SUMMON_TYPE_WILD:
case SUMMON_TYPE_FROZEN_EARTH:
case SUMMON_TYPE_LIGHTWELL:
@@ -3333,39 +3330,45 @@ void Spell::EffectSummonType(uint32 i)
case SUMMON_TYPE_SUMMON:
EffectSummon(i);
break;
- case SUMMON_TYPE_TOTEM_SLOT1:
- case SUMMON_TYPE_TOTEM_SLOT2:
- case SUMMON_TYPE_TOTEM_SLOT3:
- case SUMMON_TYPE_TOTEM_SLOT4:
- case SUMMON_TYPE_TOTEM:
- EffectSummonTotem(i);
- break;
- case SUMMON_TYPE_UNKNOWN1:
- case SUMMON_TYPE_UNKNOWN3:
- case SUMMON_TYPE_UNKNOWN4:
- case SUMMON_TYPE_UNKNOWN5:
- break;
default:
{
- SummonPropertiesEntry const *SummonProperties = sSummonPropertiesStore.LookupEntry(m_spellInfo->EffectMiscValueB[i]);
- if(!SummonProperties)
+ SummonPropertiesEntry const *properties = sSummonPropertiesStore.LookupEntry(m_spellInfo->EffectMiscValueB[i]);
+ if(!properties)
{
sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
return;
}
- switch(SummonProperties->Category)
+ switch(properties->Category)
{
default:
- if(SummonProperties->Type == SUMMON_TYPE_MINIPET)
- EffectSummonCritter(i);
- else
- EffectSummonWild(i);
+ switch(properties->Type)
+ {
+ case SUMMON_TYPE_GUARDIAN:
+ case SUMMON_TYPE_MINION:
+ SummonGuardian(entry, properties);
+ break;
+ case SUMMON_TYPE_VEHICLE:
+ SummonVehicle(entry, properties);
+ break;
+ case SUMMON_TYPE_TOTEM:
+ SummonTotem(entry, properties);
+ break;
+ case SUMMON_TYPE_MINIPET:
+ EffectSummonCritter(i);
+ break;
+ default:
+ EffectSummonWild(i);
+ break;
+ }
+ break;
+ case SUMMON_CATEGORY_GUARDIAN:
+ SummonGuardian(entry, properties);
break;
case SUMMON_CATEGORY_POSSESSED:
- EffectSummonPossessed(i);
+ SummonPossessed(entry, properties);
break;
case SUMMON_CATEGORY_VEHICLE:
- EffectSummonVehicle(i);
+ SummonVehicle(entry, properties);
break;
}
break;
@@ -3701,101 +3704,6 @@ void Spell::EffectSummonWild(uint32 i)
}
}
-void Spell::EffectSummonGuardian(uint32 i)
-{
- uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
- if(!pet_entry)
- return;
-
- // Jewelery statue case (totem like)
- if(m_spellInfo->SpellIconID==2056)
- {
- EffectSummonTotem(i);
- return;
- }
-
- Player *caster = NULL;
- if(m_originalCaster)
- {
- if(m_originalCaster->GetTypeId() == TYPEID_PLAYER)
- caster = (Player*)m_originalCaster;
- else if(((Creature*)m_originalCaster)->isTotem())
- caster = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself();
- }
-
- if(!caster)
- {
- EffectSummonWild(i);
- return;
- }
-
- // set timer for unsummon
- int32 duration = GetSpellDuration(m_spellInfo);
-
- // Search old Guardian only for players (if casted spell not have duration or cooldown)
- // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
- // so this code hack in fact
- if(duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0)
- if(caster->HasGuardianWithEntry(pet_entry))
- return; // find old guardian, ignore summon
-
- // in another case summon new
- uint32 level = caster->getLevel();
-
- // level of pet summoned using engineering item based at engineering skill level
- if(m_CastItem)
- {
- ItemPrototype const *proto = m_CastItem->GetProto();
- if(proto && proto->RequiredSkill == SKILL_ENGINERING)
- {
- uint16 skill202 = caster->GetSkillValue(SKILL_ENGINERING);
- if(skill202)
- {
- level = skill202/5;
- }
- }
- }
-
- // select center of summon position
- float center_x = m_targets.m_destX;
- float center_y = m_targets.m_destY;
- float center_z = m_targets.m_destZ;
-
- float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
-
- int32 amount = damage > 0 ? damage : 1;
-
- for(int32 count = 0; count < amount; ++count)
- {
-
- float px, py, pz;
- // If dest location if present
- if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
- {
- // Summon 1 unit in dest location
- if (count == 0)
- {
- px = m_targets.m_destX;
- py = m_targets.m_destY;
- pz = m_targets.m_destZ;
- }
- // Summon in random point all other units if location present
- else
- m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
- }
- // Summon if dest location not present near caster
- else
- m_caster->GetClosePoint(px,py,pz,m_caster->GetObjectSize());
-
- Pet *spawnCreature = caster->SummonPet(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(), GUARDIAN_PET, duration);
- if(!spawnCreature)
- return;
-
- spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
- spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
- }
-}
-
void Spell::EffectTeleUnitsFaceCaster(uint32 i)
{
if(!unitTarget)
@@ -5525,90 +5433,6 @@ void Spell::EffectApplyGlyph(uint32 i)
}
}
-void Spell::EffectSummonTotem(uint32 i)
-{
- uint8 slot = 0;
- switch(m_spellInfo->EffectMiscValueB[i])
- {
- case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
- case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
- case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
- case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
- // Battle standard case
- case SUMMON_TYPE_TOTEM: slot = 254; break;
- // jewelery statue case, like totem without slot
- case SUMMON_TYPE_GUARDIAN: slot = 255; break;
- default: return;
- }
-
- if(slot < MAX_TOTEM)
- {
- uint64 guid = m_caster->m_TotemSlot[slot];
- if(guid != 0)
- {
- Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid);
- if(OldTotem && OldTotem->isTotem())
- ((Totem*)OldTotem)->UnSummon();
- }
- }
-
- uint32 team = 0;
- if (m_caster->GetTypeId()==TYPEID_PLAYER)
- team = ((Player*)m_caster)->GetTeam();
-
- Totem* pTotem = new Totem;
-
- if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
- m_spellInfo->EffectMiscValue[i], team ))
- {
- delete pTotem;
- return;
- }
-
- float x,y,z;
- GetSummonPosition(x, y, z);
-
- // totem must be at same Z in case swimming caster and etc.
- if( fabs( z - m_caster->GetPositionZ() ) > 5 )
- z = m_caster->GetPositionZ();
-
- pTotem->Relocate(x, y, z, m_caster->GetOrientation());
-
- if(slot < MAX_TOTEM)
- m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
-
- pTotem->SetOwner(m_caster->GetGUID());
- pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
-
- int32 duration=GetSpellDuration(m_spellInfo);
- if(Player* modOwner = m_caster->GetSpellModOwner())
- modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
- pTotem->SetDuration(duration);
-
- if (damage) // if not spell info, DB values used
- {
- pTotem->SetMaxHealth(damage);
- pTotem->SetHealth(damage);
- }
-
- pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
-
- if(m_caster->GetTypeId() == TYPEID_PLAYER)
- pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
-
- pTotem->Summon(m_caster);
-
- if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
- {
- WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
- data << uint8(slot);
- data << uint64(pTotem->GetGUID());
- data << uint32(duration);
- data << uint32(m_spellInfo->Id);
- ((Player*)m_caster)->SendDirectMessage(&data);
- }
-}
-
void Spell::EffectEnchantHeldItem(uint32 i)
{
// this is only item spell effect applied to main-hand weapon of target player (players in area)
@@ -6031,8 +5855,7 @@ void Spell::EffectSummonCritter(uint32 i)
GetSummonPosition(x, y, z);
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);
+ TempSummon *critter = m_caster->GetMap()->SummonCreature(pet_entry, x, y, z, m_caster->GetOrientation(), sSummonPropertiesStore.LookupEntry(m_spellInfo->EffectMiscValueB[i]), duration, m_caster);
if(!critter)
return;
@@ -6052,8 +5875,6 @@ void Spell::EffectSummonCritter(uint32 i)
std::string name = player->GetName();
name.append(petTypeSuffix[3]);
critter->SetName( name );
-
- critter->SetSummonProperties(sSummonPropertiesStore.LookupEntry(m_spellInfo->EffectMiscValueB[i]));
}
void Spell::EffectKnockBack(uint32 i)
@@ -6681,12 +6502,128 @@ void Spell::EffectRedirectThreat(uint32 /*i*/)
m_caster->SetReducedThreatPercent((uint32)damage, unitTarget->GetGUID());
}
-void Spell::EffectSummonPossessed(uint32 i)
+void Spell::SummonTotem(uint32 entry, SummonPropertiesEntry const *properties)
{
- uint32 entry = m_spellInfo->EffectMiscValue[i];
- if(!entry)
+ int8 slot = (int8)properties->Slot - 1;
+
+ if(slot >= 0 && slot < MAX_TOTEM)
+ {
+ uint64 guid = m_caster->m_TotemSlot[slot];
+ if(guid != 0)
+ {
+ Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid);
+ if(OldTotem && OldTotem->isTotem())
+ ((Totem*)OldTotem)->UnSummon();
+ }
+ }
+
+ uint32 team = 0;
+ if (m_caster->GetTypeId()==TYPEID_PLAYER)
+ team = ((Player*)m_caster)->GetTeam();
+
+ Totem* pTotem = new Totem(properties, m_caster);
+
+ if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(),
+ entry, team ))
+ {
+ delete pTotem;
+ return;
+ }
+
+ float x,y,z;
+ GetSummonPosition(x, y, z);
+
+ // totem must be at same Z in case swimming caster and etc.
+ if( fabs( z - m_caster->GetPositionZ() ) > 5 )
+ z = m_caster->GetPositionZ();
+
+ pTotem->Relocate(x, y, z, m_caster->GetOrientation());
+
+ if(slot < MAX_TOTEM)
+ m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
+
+ pTotem->SetOwner(m_caster->GetGUID());
+ pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized
+
+ int32 duration=GetSpellDuration(m_spellInfo);
+ if(Player* modOwner = m_caster->GetSpellModOwner())
+ modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
+ pTotem->SetDuration(duration);
+
+ if (damage) // if not spell info, DB values used
+ {
+ pTotem->SetMaxHealth(damage);
+ pTotem->SetHealth(damage);
+ }
+
+ pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
+
+ if(m_caster->GetTypeId() == TYPEID_PLAYER)
+ pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
+
+ pTotem->Summon(m_caster);
+
+ if(slot >= 0 && slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
+ data << uint8(slot);
+ data << uint64(pTotem->GetGUID());
+ data << uint32(duration);
+ data << uint32(m_spellInfo->Id);
+ ((Player*)m_caster)->SendDirectMessage(&data);
+ }
+}
+
+void Spell::SummonGuardian(uint32 entry, SummonPropertiesEntry const *properties)
+{
+ Unit *caster = m_originalCaster;
+ if(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())
+ caster = caster->GetOwner();
+ if(!caster)
return;
+ // in another case summon new
+ uint32 level = caster->getLevel();
+
+ // level of pet summoned using engineering item based at engineering skill level
+ if(m_CastItem && caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ ItemPrototype const *proto = m_CastItem->GetProto();
+ if(proto && proto->RequiredSkill == SKILL_ENGINERING)
+ {
+ uint16 skill202 = ((Player*)caster)->GetSkillValue(SKILL_ENGINERING);
+ if(skill202)
+ {
+ level = skill202/5;
+ }
+ }
+ }
+
+ //float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
+ float radius = 5.0f;
+ int32 amount = damage > 0 ? damage : 1;
+ int32 duration = GetSpellDuration(m_spellInfo);
+ TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
+ Map *map = caster->GetMap();
+
+ for(int32 count = 0; count < amount; ++count)
+ {
+ float px, py, pz;
+ GetSummonPosition(px, py, pz, radius, count);
+
+ TempSummon *summon = map->SummonCreature(entry, px, py, pz, m_caster->GetOrientation(), properties, duration, caster);
+ if(!summon)
+ return;
+
+ if(summon->GetSummonMask() | SUMMON_MASK_GUARDIAN)
+ ((Guardian*)summon)->InitStatsForLevel(level);
+
+ summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
+ }
+}
+
+void Spell::SummonPossessed(uint32 entry, SummonPropertiesEntry const *properties)
+{
if(m_caster->GetTypeId() != TYPEID_PLAYER)
return;
@@ -6705,12 +6642,8 @@ void Spell::EffectSummonPossessed(uint32 i)
pet->SetCharmedOrPossessedBy(m_caster, true);
}
-void Spell::EffectSummonVehicle(uint32 i)
+void Spell::SummonVehicle(uint32 entry, SummonPropertiesEntry const *properties)
{
- uint32 entry = m_spellInfo->EffectMiscValue[i];
- if(!entry)
- return;
-
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());
diff --git a/src/game/TemporarySummon.cpp b/src/game/TemporarySummon.cpp
index 77fbfa439e5..07ab36c40d8 100644
--- a/src/game/TemporarySummon.cpp
+++ b/src/game/TemporarySummon.cpp
@@ -22,12 +22,13 @@
#include "Log.h"
#include "ObjectAccessor.h"
#include "CreatureAI.h"
+#include "ObjectMgr.h"
-TempSummon::TempSummon( uint64 summoner ) :
-Creature(), m_type(TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN), m_timer(0), m_lifetime(0), m_summoner(summoner)
-, m_properties(NULL)
+TempSummon::TempSummon(SummonPropertiesEntry const *properties, Unit *owner) :
+Creature(), m_type(TEMPSUMMON_MANUAL_DESPAWN), m_timer(0), m_lifetime(0)
+, m_Properties(properties), m_summonerGUID(owner->GetGUID())
{
- m_isSummon = true;
+ m_summonMask |= SUMMON_MASK_SUMMON;
}
void TempSummon::Update( uint32 diff )
@@ -159,66 +160,153 @@ void TempSummon::Update( uint32 diff )
Creature::Update( diff );
}
-void TempSummon::Summon(TempSummonType type, uint32 lifetime)
+void TempSummon::InitSummon(uint32 duration)
{
- m_type = type;
- m_timer = lifetime;
- m_lifetime = lifetime;
+ m_timer = duration;
+ m_lifetime = duration;
- GetMap()->Add((Creature*)this);
+ if(m_type == TEMPSUMMON_MANUAL_DESPAWN)
+ m_type = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
AIM_Initialize();
+
+ if(!m_Properties)
+ return;
+
+ Unit* owner = GetSummoner();
+ if(uint32 slot = m_Properties->Slot)
+ {
+ --slot;
+ 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();
+ }
+ }
}
-void TempSummon::UnSummon()
+void TempSummon::SetTempSummonType(TempSummonType type)
{
- CleanupsBeforeDelete();
- AddObjectToRemoveList();
+ m_type = type;
+}
+void TempSummon::UnSummon()
+{
Unit* owner = GetSummoner();
if(owner)
{
if(owner->GetTypeId() == TYPEID_UNIT && ((Creature*)owner)->IsAIEnabled)
((Creature*)owner)->AI()->SummonedCreatureDespawn(this);
- if(!m_properties)
- return;
-
- if(uint32 slot = m_properties->Slot)
+ if(m_Properties)
{
- --slot;
- owner->m_TotemSlot[slot] = 0;
+ if(uint32 slot = m_Properties->Slot)
+ {
+ --slot;
+ if(owner->m_TotemSlot[slot] = GetGUID())
+ owner->m_TotemSlot[slot] = 0;
+ }
}
}
+
+ CleanupsBeforeDelete();
+ AddObjectToRemoveList();
}
-void TempSummon::SetSummonProperties(SummonPropertiesEntry const *properties)
+void TempSummon::SaveToDB()
{
- if(!properties)
- return;
+}
+
+Guardian::Guardian(SummonPropertiesEntry const *properties, Unit *owner) : TempSummon(properties, owner)
+, m_owner(owner)
+{
+ m_summonMask |= SUMMON_MASK_GUARDIAN;
+ InitCharmInfo();
+}
+
+bool Guardian::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number)
+{
+ SetMapId(map->GetId());
+ SetInstanceId(map->GetInstanceId());
+ SetPhaseMask(phaseMask,false);
+
+ Object::_Create(guidlow, pet_number, HIGHGUID_PET);
+
+ m_DBTableGuid = guidlow;
+ m_originalEntry = Entry;
- m_properties = properties;
+ if(!InitEntry(Entry))
+ return false;
- if(uint32 slot = m_properties->Slot)
+ SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
+
+ return true;
+}
+
+void Guardian::InitSummon(uint32 duration)
+{
+ TempSummon::InitSummon(duration);
+
+ SetReactState(REACT_AGGRESSIVE);
+ SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
+
+ SetOwnerGUID(m_owner->GetGUID());
+ SetCreatorGUID(m_owner->GetGUID());
+ SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_owner->getFaction());
+ m_owner->AddGuardian(this);
+ SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
+
+ if(m_owner->GetTypeId() == TYPEID_PLAYER)
{
- --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();
- }
+ m_owner->SetUInt64Value(UNIT_FIELD_SUMMON, GetGUID());
+ m_charmInfo->InitCharmCreateSpells();
+ //charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
+ ((Player*)m_owner)->CharmSpellInitialize();
}
+}
- AIM_Initialize();
+void Guardian::InitStatsForLevel(uint32 petlevel)
+{
+ SetLevel(petlevel);
+ switch(GetEntry())
+ {
+ case 1964: //force of nature
+ SetCreateHealth(30 + 30*petlevel);
+ SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 2.5f - (petlevel / 2)));
+ SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 2.5f + (petlevel / 2)));
+ break;
+ case 15352: //earth elemental 36213
+ SetCreateHealth(100 + 120*petlevel);
+ SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
+ SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
+ break;
+ case 15438: //fire elemental
+ SetCreateHealth(40*petlevel);
+ SetCreateMana(28 + 10*petlevel);
+ SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 4 - petlevel));
+ SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 4 + petlevel));
+ break;
+ default:
+ SetCreateMana(28 + 10*petlevel);
+ SetCreateHealth(28 + 30*petlevel);
+ // FIXME: this is wrong formula, possible each guardian pet have own damage formula
+ //these formula may not be correct; however, it is designed to be close to what it should be
+ //this makes dps 0.5 of pets level
+ SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
+ //damage range is then petlevel / 2
+ SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
+ break;
+ }
}
-void TempSummon::SaveToDB()
+void Guardian::UnSummon()
{
+ m_owner->m_Guardians.erase(GetGUID());
+ TempSummon::UnSummon();
}
diff --git a/src/game/TemporarySummon.h b/src/game/TemporarySummon.h
index 4b22a9e5d77..bec5e36f546 100644
--- a/src/game/TemporarySummon.h
+++ b/src/game/TemporarySummon.h
@@ -27,21 +27,34 @@
class TempSummon : public Creature
{
public:
- explicit TempSummon(uint64 summoner = 0);
+ explicit TempSummon(SummonPropertiesEntry const *properties, Unit *owner);
virtual ~TempSummon(){};
void Update(uint32 time);
- void Summon(TempSummonType type, uint32 lifetime);
+ virtual void InitSummon(uint32 lifetime);
virtual void UnSummon();
+ void SetTempSummonType(TempSummonType type);
void SaveToDB();
- Unit* GetSummoner() const { return m_summoner ? ObjectAccessor::GetUnit(*this, m_summoner) : NULL; }
+ Unit* GetSummoner() const { return m_summonerGUID ? ObjectAccessor::GetUnit(*this, m_summonerGUID) : NULL; }
- void SetSummonProperties(SummonPropertiesEntry const *properties);
- SummonPropertiesEntry const *m_properties;
+ SummonPropertiesEntry const *m_Properties;
private:
TempSummonType m_type;
uint32 m_timer;
uint32 m_lifetime;
- uint64 m_summoner;
+ uint64 m_summonerGUID;
};
+
+class Guardian : public TempSummon
+{
+ public:
+ Guardian(SummonPropertiesEntry const *properties, Unit *owner);
+ bool Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number);
+ void InitSummon(uint32 duration);
+ void UnSummon();
+ void InitStatsForLevel(uint32 level);
+ protected:
+ Unit *m_owner;
+};
+
#endif
diff --git a/src/game/Totem.cpp b/src/game/Totem.cpp
index 0dc1ac41546..266fe476012 100644
--- a/src/game/Totem.cpp
+++ b/src/game/Totem.cpp
@@ -26,9 +26,9 @@
#include "ObjectMgr.h"
#include "SpellMgr.h"
-Totem::Totem() : TempSummon(0)
+Totem::Totem(SummonPropertiesEntry const *properties, Unit *owner) : TempSummon(properties, owner)
{
- m_isTotem = true;
+ m_summonMask |= SUMMON_MASK_TOTEM;
m_duration = 0;
m_type = TOTEM_PASSIVE;
}
diff --git a/src/game/Totem.h b/src/game/Totem.h
index baf4ac2c571..40e2744bbeb 100644
--- a/src/game/Totem.h
+++ b/src/game/Totem.h
@@ -35,7 +35,7 @@ enum TotemType
class Totem : public TempSummon
{
public:
- explicit Totem();
+ explicit Totem(SummonPropertiesEntry const *properties, Unit *owner);
virtual ~Totem(){};
void Update( uint32 time );
void Summon(Unit* owner);
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index ee596024541..c57528e87a9 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -106,7 +106,7 @@ Unit::Unit()
m_addDmgOnce = 0;
- for(int i = 0; i < MAX_TOTEM; ++i)
+ for(int i = 0; i < MAX_SUMMON_SLOT; ++i)
m_TotemSlot[i] = 0;
m_ObjectSlot[0] = m_ObjectSlot[1] = m_ObjectSlot[2] = m_ObjectSlot[3] = 0;
@@ -8139,13 +8139,9 @@ void Unit::CombatStopWithPets(bool cast)
pet->CombatStop(cast);
if(Unit* charm = GetCharm())
charm->CombatStop(cast);
- if(GetTypeId()==TYPEID_PLAYER)
- {
- GuardianPetList const& guardians = ((Player*)this)->GetGuardians();
- for(GuardianPetList::const_iterator itr = guardians.begin(); itr != guardians.end(); ++itr)
- if(Unit* guardian = Unit::GetUnit(*this,*itr))
- guardian->CombatStop(cast);
- }
+ for(GuardianList::const_iterator itr = m_Guardians.begin(); itr != m_Guardians.end(); ++itr)
+ if(Unit* guardian = Unit::GetUnit(*this,*itr))
+ guardian->CombatStop(cast);
}
bool Unit::isAttackingPlayer() const
@@ -8362,7 +8358,7 @@ void Unit::RemoveCharmAuras()
void Unit::UnsummonAllTotems()
{
- for (int8 i = 0; i < MAX_TOTEM; ++i)
+ for (int8 i = 0; i < MAX_SUMMON_SLOT; ++i)
{
if(!m_TotemSlot[i])
continue;
@@ -10447,8 +10443,9 @@ void Unit::setDeathState(DeathState s)
if (s == JUST_DIED)
{
- RemoveAllAurasOnDeath();
UnsummonAllTotems();
+ RemoveGuardians();
+ RemoveAllAurasOnDeath();
//This is needed to clear visible auras after unit dies
UpdateAuras();
@@ -11404,6 +11401,7 @@ void Unit::RemoveFromWorld()
if(IsInWorld())
{
UnsummonAllTotems();
+ RemoveGuardians();
RemoveCharmAuras();
RemoveBindSightAuras();
RemoveNotOwnSingleTargetAuras();
@@ -11563,7 +11561,7 @@ void CharmInfo::InitCharmCreateSpells()
InitPetActionBar();
- for(uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x)
+ for(uint32 x = 0; x < 4; ++x)
{
uint32 spellId = ((Creature*)m_unit)->m_spells[x];
m_charmspells[x].spellId = spellId;
@@ -13351,6 +13349,7 @@ void Unit::RemoveCharmedOrPossessedBy(Unit *charmer)
if(GetTypeId() == TYPEID_PLAYER || GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet())
{
+ //TODO: this will cause crash when a guardian is charmed
DeleteCharmInfo();
}
@@ -13363,6 +13362,23 @@ void Unit::RemoveCharmedOrPossessedBy(Unit *charmer)
}
}
+void Unit::RemoveGuardians()
+{
+ while(!m_Guardians.empty())
+ {
+ uint64 guid = *m_Guardians.begin();
+ if(Unit* guardian = ObjectAccessor::GetUnit(*this, guid))
+ {
+ if(guardian->GetTypeId() == TYPEID_UNIT)
+ {
+ if(((Creature*)guardian)->isSummon())
+ ((TempSummon*)guardian)->UnSummon();
+ }
+ }
+ m_Guardians.erase(guid);
+ }
+}
+
void Unit::RestoreFaction()
{
if(GetTypeId() == TYPEID_PLAYER)
diff --git a/src/game/Unit.h b/src/game/Unit.h
index a79202f915a..b06f2582f2e 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -838,6 +838,8 @@ struct AuraSlotEntry
struct SpellProcEventEntry; // used only privately
+typedef std::set<uint64> GuardianList;
+
class TRINITY_DLL_SPEC Unit : public WorldObject
{
public:
@@ -1304,6 +1306,10 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
uint32 m_detectInvisibilityMask;
uint32 m_invisibilityMask;
+ GuardianList m_Guardians;
+ void RemoveGuardians();
+ void AddGuardian(Unit* pet) { m_Guardians.insert(pet->GetGUID()); }
+
uint32 m_ShapeShiftFormSpellId;
ShapeshiftForm m_form;
bool IsInFeralForm() const { return m_form == FORM_CAT || m_form == FORM_BEAR || m_form == FORM_DIREBEAR; }
diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp
index cd24472d70e..4dd38e9d41e 100644
--- a/src/game/Vehicle.cpp
+++ b/src/game/Vehicle.cpp
@@ -25,7 +25,7 @@
Vehicle::Vehicle() : Creature(), m_vehicleId(0)
{
- m_isVehicle = true;
+ m_summonMask |= SUMMON_MASK_VEHICLE;
m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_VEHICLE);
}