diff options
author | megamage <none@none> | 2009-03-20 14:01:46 -0600 |
---|---|---|
committer | megamage <none@none> | 2009-03-20 14:01:46 -0600 |
commit | 8f627853dfaab8bfecd24bfd96ad02c6503d517e (patch) | |
tree | ab518e88d6bfd462e50998541cbcc1575134ce66 /src | |
parent | 7cd9a01954f6905dfb0e6a113b5799cc2442a39e (diff) |
*More work on summon system.
--HG--
branch : trunk
Diffstat (limited to 'src')
-rw-r--r-- | src/game/Creature.cpp | 7 | ||||
-rw-r--r-- | src/game/Creature.h | 24 | ||||
-rw-r--r-- | src/game/CreatureAISelector.cpp | 11 | ||||
-rw-r--r-- | src/game/Map.h | 3 | ||||
-rw-r--r-- | src/game/Object.cpp | 89 | ||||
-rw-r--r-- | src/game/Pet.cpp | 43 | ||||
-rw-r--r-- | src/game/Pet.h | 5 | ||||
-rw-r--r-- | src/game/PetHandler.cpp | 4 | ||||
-rw-r--r-- | src/game/Player.cpp | 84 | ||||
-rw-r--r-- | src/game/Player.h | 11 | ||||
-rw-r--r-- | src/game/SharedDefines.h | 18 | ||||
-rw-r--r-- | src/game/Spell.h | 8 | ||||
-rw-r--r-- | src/game/SpellAuras.cpp | 1 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 371 | ||||
-rw-r--r-- | src/game/TemporarySummon.cpp | 162 | ||||
-rw-r--r-- | src/game/TemporarySummon.h | 25 | ||||
-rw-r--r-- | src/game/Totem.cpp | 4 | ||||
-rw-r--r-- | src/game/Totem.h | 2 | ||||
-rw-r--r-- | src/game/Unit.cpp | 38 | ||||
-rw-r--r-- | src/game/Unit.h | 6 | ||||
-rw-r--r-- | src/game/Vehicle.cpp | 2 |
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 ¬ifier); template<class NOTIFIER> void VisitWorld(const float &x, const float &y, float radius, NOTIFIER ¬ifier); template<class NOTIFIER> void VisitGrid(const float &x, const float &y, float radius, NOTIFIER ¬ifier); + + 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); } |