*More work on summon system.

--HG--
branch : trunk
This commit is contained in:
megamage
2009-03-20 14:01:46 -06:00
parent 7cd9a01954
commit 8f627853df
21 changed files with 494 additions and 434 deletions
+4 -3
View File
@@ -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;
}
+16 -8
View File
@@ -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();
+9 -2
View File
@@ -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");
}
+3
View File
@@ -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);
+73 -20
View File
@@ -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 team = 0;
if (GetTypeId()==TYPEID_PLAYER)
team = ((Player*)this)->GetTeam();
if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), GetMap(), GetPhaseMask(), id, team))
uint32 mask = SUMMON_MASK_SUMMON;
if(properties)
{
delete pCreature;
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;
}
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();
}
switch(mask)
{
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;
}
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)",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, pCreature->GetObjectSize());
GetClosePoint(x, y, z, GetObjectSize());
pCreature->Relocate(x, y, z, ang);
if(!pCreature->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;
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);
+2 -41
View File
@@ -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;
+2 -3
View File
@@ -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];
+2 -2
View File
@@ -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();
}
}
+29 -55
View File
@@ -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);
}
+1 -10
View File
@@ -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;
+12 -6
View File
@@ -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,
+4 -4
View File
@@ -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);
// -------------------------------------------
+1
View File
@@ -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);
}
+152 -219
View File
@@ -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());
+128 -40
View File
@@ -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,50 +160,23 @@ 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();
}
void TempSummon::UnSummon()
{
CleanupsBeforeDelete();
AddObjectToRemoveList();
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)
{
--slot;
owner->m_TotemSlot[slot] = 0;
}
}
}
void TempSummon::SetSummonProperties(SummonPropertiesEntry const *properties)
{
if(!properties)
if(!m_Properties)
return;
m_properties = properties;
if(uint32 slot = m_properties->Slot)
Unit* owner = GetSummoner();
if(uint32 slot = m_Properties->Slot)
{
--slot;
Unit* owner = GetSummoner();
if(owner)
{
if(owner->m_TotemSlot[slot] && owner->m_TotemSlot[slot] != GetGUID())
@@ -214,11 +188,125 @@ void TempSummon::SetSummonProperties(SummonPropertiesEntry const *properties)
owner->m_TotemSlot[slot] = GetGUID();
}
}
}
AIM_Initialize();
void TempSummon::SetTempSummonType(TempSummonType type)
{
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)
{
if(uint32 slot = m_Properties->Slot)
{
--slot;
if(owner->m_TotemSlot[slot] = GetGUID())
owner->m_TotemSlot[slot] = 0;
}
}
}
CleanupsBeforeDelete();
AddObjectToRemoveList();
}
void TempSummon::SaveToDB()
{
}
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;
if(!InitEntry(Entry))
return false;
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)
{
m_owner->SetUInt64Value(UNIT_FIELD_SUMMON, GetGUID());
m_charmInfo->InitCharmCreateSpells();
//charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
((Player*)m_owner)->CharmSpellInitialize();
}
}
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 Guardian::UnSummon()
{
m_owner->m_Guardians.erase(GetGUID());
TempSummon::UnSummon();
}
+19 -6
View File
@@ -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
+2 -2
View File
@@ -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;
}
+1 -1
View File
@@ -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);
+27 -11
View File
@@ -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)
+6
View File
@@ -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; }
+1 -1
View File
@@ -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);
}