diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 60fd3e8d5..0cf7f26d8 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -118,6 +118,35 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) return true; } +void CreatureCreatePos::SelectFinalPoint(Creature* cr) +{ + // if object provided then selected point at specific dist/angle from object forward look + if (m_closeObject) + { + if (m_dist == 0.0f) + { + m_pos.x = m_closeObject->GetPositionX(); + m_pos.y = m_closeObject->GetPositionY(); + m_pos.z = m_closeObject->GetPositionZ(); + } + else + m_closeObject->GetClosePoint(m_pos.x, m_pos.y, m_pos.z, cr->GetObjectBoundingRadius(), m_dist, m_angle); + } +} + +bool CreatureCreatePos::Relocate(Creature* cr) const +{ + cr->Relocate(m_pos.x, m_pos.y, m_pos.z, m_pos.o); + + if (!cr->IsPositionValid()) + { + sLog.outError("%s not created. Suggested coordinates isn't valid (X: %f Y: %f)", cr->GetGuidStr().c_str(), cr->GetPositionX(), cr->GetPositionY()); + return false; + } + + return true; +} + Creature::Creature(CreatureSubtype subtype) : Unit(), i_AI(NULL), lootForPickPocketed(false), lootForBody(false), lootForSkin(false), m_groupLootTimer(0), m_groupLootId(0), @@ -699,45 +728,47 @@ bool Creature::AIM_Initialize() return true; } -bool Creature::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, Team team /*= TEAM_NONE*/, const CreatureData *data /*= NULL*/, GameEventCreatureData const* eventData /*= NULL*/) +bool Creature::Create(uint32 guidlow, CreatureCreatePos& cPos, uint32 Entry, Team team /*= TEAM_NONE*/, const CreatureData *data /*= NULL*/, GameEventCreatureData const* eventData /*= NULL*/) { - MANGOS_ASSERT(map); - SetMap(map); - SetPhaseMask(phaseMask,false); + SetMap(cPos.GetMap()); + SetPhaseMask(cPos.GetPhaseMask(), false); - //oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0; - const bool bResult = CreateFromProto(guidlow, Entry, team, data, eventData); + if (!CreateFromProto(guidlow, Entry, team, data, eventData)) + return false; - if (bResult) + cPos.SelectFinalPoint(this); + + if (!cPos.Relocate(this)) + return false; + + //Notify the map's instance data. + //Only works if you create the object in it, not if it is moves to that map. + //Normally non-players do not teleport to other maps. + if (InstanceData* iData = GetMap()->GetInstanceData()) + iData->OnCreatureCreate(this); + + switch (GetCreatureInfo()->rank) { - //Notify the map's instance data. - //Only works if you create the object in it, not if it is moves to that map. - //Normally non-players do not teleport to other maps. - if (InstanceData* iData = map->GetInstanceData()) - iData->OnCreatureCreate(this); - - switch (GetCreatureInfo()->rank) - { - case CREATURE_ELITE_RARE: - m_corpseDelay = sWorld.getConfig(CONFIG_UINT32_CORPSE_DECAY_RARE); - break; - case CREATURE_ELITE_ELITE: - m_corpseDelay = sWorld.getConfig(CONFIG_UINT32_CORPSE_DECAY_ELITE); - break; - case CREATURE_ELITE_RAREELITE: - m_corpseDelay = sWorld.getConfig(CONFIG_UINT32_CORPSE_DECAY_RAREELITE); - break; - case CREATURE_ELITE_WORLDBOSS: - m_corpseDelay = sWorld.getConfig(CONFIG_UINT32_CORPSE_DECAY_WORLDBOSS); - break; - default: - m_corpseDelay = sWorld.getConfig(CONFIG_UINT32_CORPSE_DECAY_NORMAL); - break; - } - LoadCreatureAddon(); + case CREATURE_ELITE_RARE: + m_corpseDelay = sWorld.getConfig(CONFIG_UINT32_CORPSE_DECAY_RARE); + break; + case CREATURE_ELITE_ELITE: + m_corpseDelay = sWorld.getConfig(CONFIG_UINT32_CORPSE_DECAY_ELITE); + break; + case CREATURE_ELITE_RAREELITE: + m_corpseDelay = sWorld.getConfig(CONFIG_UINT32_CORPSE_DECAY_RAREELITE); + break; + case CREATURE_ELITE_WORLDBOSS: + m_corpseDelay = sWorld.getConfig(CONFIG_UINT32_CORPSE_DECAY_WORLDBOSS); + break; + default: + m_corpseDelay = sWorld.getConfig(CONFIG_UINT32_CORPSE_DECAY_NORMAL); + break; } - return bResult; + LoadCreatureAddon(); + + return true; } bool Creature::IsTrainerOf(Player* pPlayer, bool msg) const @@ -1237,16 +1268,9 @@ bool Creature::LoadFromDB(uint32 guidlow, Map *map) if (map->GetCreature(ObjectGuid(HIGHGUID_UNIT, data->id, guidlow))) return false; - // set coordinates before call Create because some code can be depend from correct coordinates values. - Relocate(data->posX, data->posY, data->posZ, data->orientation); + CreatureCreatePos pos(map, data->posX, data->posY, data->posZ, data->orientation, data->phaseMask); - if (!IsPositionValid()) - { - sLog.outError("Creature (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)", GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); - return false; - } - - if (!Create(guidlow, map, data->phaseMask, data->id, TEAM_NONE, data, eventData)) + if (!Create(guidlow, pos, data->id, TEAM_NONE, data, eventData)) return false; m_respawnradius = data->spawndist; diff --git a/src/game/Creature.h b/src/game/Creature.h index 34e404e42..182cff9e7 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -378,6 +378,32 @@ typedef std::map CreatureSpellCooldowns; #define MAX_VENDOR_ITEMS 150 // Limitation in 3.x.x item count in SMSG_LIST_INVENTORY +struct CreatureCreatePos +{ + public: + // exactly coordinates used + CreatureCreatePos(Map* map, float x, float y, float z, float o, uint32 phaseMask) + : m_map(map), m_phaseMask(phaseMask), m_closeObject(NULL), m_angle(0.0f), m_dist(0.0f) { m_pos.x = x; m_pos.y = y; m_pos.z = z; m_pos.o = o; } + // if dist == 0.0f -> exactly object coordinates used, in other case close point to object (CONTACT_DIST can be used as minimal distances) + CreatureCreatePos(WorldObject* closeObject, float ori, float dist = 0.0f, float angle = 0.0f) + : m_map(closeObject->GetMap()), m_phaseMask(closeObject->GetPhaseMask()), + m_closeObject(closeObject), m_angle(angle), m_dist(dist) { m_pos.o = ori; } + public: + Map* GetMap() const { return m_map; } + uint32 GetPhaseMask() const { return m_phaseMask; } + void SelectFinalPoint(Creature* cr); + bool Relocate(Creature* cr) const; + + // read only after SelectFinalPoint + Position m_pos; + private: + Map* m_map; + uint32 m_phaseMask; + WorldObject* m_closeObject; + float m_angle; + float m_dist; +}; + enum CreatureSubtype { CREATURE_SUBTYPE_GENERIC, // new Creature @@ -399,7 +425,7 @@ class MANGOS_DLL_SPEC Creature : public Unit void AddToWorld(); void RemoveFromWorld(); - bool Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, Team team = TEAM_NONE, const CreatureData *data = NULL, GameEventCreatureData const* eventData = NULL); + bool Create(uint32 guidlow, CreatureCreatePos& cPos, uint32 Entry, Team team = TEAM_NONE, const CreatureData *data = NULL, GameEventCreatureData const* eventData = NULL); bool LoadCreatureAddon(bool reload = false); void SelectLevel(const CreatureInfo *cinfo, float percentHealth = 100.0f, float percentMana = 100.0f); void LoadEquipment(uint32 equip_entry, bool force=false); @@ -639,7 +665,7 @@ class MANGOS_DLL_SPEC Creature : public Unit void SetCombatStartPosition(float x, float y, float z) { CombatStartX = x; CombatStartY = y; CombatStartZ = z; } void GetCombatStartPosition(float &x, float &y, float &z) { x = CombatStartX; y = CombatStartY; z = CombatStartZ; } - void SetSummonPoint(float fX, float fY, float fZ, float fOrient) { m_summonXpoint = fX; m_summonYpoint = fY; m_summonZpoint = fZ; m_summonOrientation = fOrient; } + void SetSummonPoint(CreatureCreatePos const& pos) { m_summonXpoint = pos.m_pos.x; m_summonYpoint = pos.m_pos.y; m_summonZpoint = pos.m_pos.z; m_summonOrientation = pos.m_pos.o; } void GetSummonPoint(float &fX, float &fY, float &fZ, float &fOrient) const { fX = m_summonXpoint; fY = m_summonYpoint; fZ = m_summonZpoint; fOrient = m_summonOrientation; } void SetDeadByDefault (bool death_state) { m_isDeadByDefault = death_state; } diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 747b1753e..abfd04c12 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -1551,24 +1551,12 @@ bool ChatHandler::HandleNpcAddCommand(char* args) return false; Player *chr = m_session->GetPlayer(); - float x = chr->GetPositionX(); - float y = chr->GetPositionY(); - float z = chr->GetPositionZ(); - float o = chr->GetOrientation(); + CreatureCreatePos pos(chr, chr->GetOrientation()); Map *map = chr->GetMap(); Creature* pCreature = new Creature; - pCreature->Relocate(x,y,z,o); - - if (!pCreature->IsPositionValid()) - { - sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY()); - delete pCreature; - return false; - } - - if (!pCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id)) + if (!pCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, id)) { delete pCreature; return false; @@ -3141,16 +3129,9 @@ bool ChatHandler::HandleWpModifyCommand(char* args) wpGuid = 0; Creature* wpCreature = new Creature; - wpCreature->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation()); + CreatureCreatePos pos(chr, chr->GetOrientation()); - if (!wpCreature->IsPositionValid()) - { - sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature->GetGUIDLow(),wpCreature->GetEntry(),wpCreature->GetPositionX(),wpCreature->GetPositionY()); - delete wpCreature; - return false; - } - - if (!wpCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT)) + if (!wpCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, VISUAL_WAYPOINT)) { PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete wpCreature; @@ -3260,16 +3241,9 @@ bool ChatHandler::HandleWpModifyCommand(char* args) // re-create Creature* wpCreature2 = new Creature; - wpCreature2->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation()); + CreatureCreatePos pos(chr, chr->GetOrientation()); - if (!wpCreature2->IsPositionValid()) - { - sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature2->GetGUIDLow(),wpCreature2->GetEntry(),wpCreature2->GetPositionX(),wpCreature2->GetPositionY()); - delete wpCreature2; - return false; - } - - if (!wpCreature2->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT)) + if (!wpCreature2->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, VISUAL_WAYPOINT)) { PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete wpCreature2; @@ -3551,33 +3525,18 @@ bool ChatHandler::HandleWpShowCommand(char* args) do { - Field *fields = result->Fetch(); - uint32 point = fields[0].GetUInt32(); - float x = fields[1].GetFloat(); - float y = fields[2].GetFloat(); - float z = fields[3].GetFloat(); - - uint32 id = VISUAL_WAYPOINT; - Player *chr = m_session->GetPlayer(); Map *map = chr->GetMap(); - float o = chr->GetOrientation(); + + Field *fields = result->Fetch(); + uint32 point = fields[0].GetUInt32(); + CreatureCreatePos pos(map, fields[1].GetFloat(), fields[2].GetFloat(), fields[3].GetFloat(), chr->GetOrientation(), chr->GetPhaseMaskForSpawn()); Creature* wpCreature = new Creature; - wpCreature->Relocate(x, y, z, o); - - if (!wpCreature->IsPositionValid()) + if (!wpCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, VISUAL_WAYPOINT)) { - sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature->GetGUIDLow(),wpCreature->GetEntry(),wpCreature->GetPositionX(),wpCreature->GetPositionY()); - delete wpCreature; - delete result; - return false; - } - - if (!wpCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id)) - { - PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete wpCreature; delete result; return false; @@ -3612,31 +3571,17 @@ bool ChatHandler::HandleWpShowCommand(char* args) return false; } - Field *fields = result->Fetch(); - float x = fields[0].GetFloat(); - float y = fields[1].GetFloat(); - float z = fields[2].GetFloat(); - uint32 id = VISUAL_WAYPOINT; - Player *chr = m_session->GetPlayer(); - float o = chr->GetOrientation(); Map *map = chr->GetMap(); + Field *fields = result->Fetch(); + CreatureCreatePos pos(map, fields[0].GetFloat(), fields[1].GetFloat(), fields[2].GetFloat(), chr->GetOrientation(), chr->GetPhaseMaskForSpawn()); + Creature* pCreature = new Creature; - pCreature->Relocate(x, y, z, o); - - if (!pCreature->IsPositionValid()) + if (!pCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, VISUAL_WAYPOINT)) { - sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY()); - delete pCreature; - delete result; - return false; - } - - if (!pCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT),map, chr->GetPhaseMaskForSpawn(), id)) - { - PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete pCreature; delete result; return false; @@ -3673,31 +3618,18 @@ bool ChatHandler::HandleWpShowCommand(char* args) SetSentErrorMessage(true); return false; } - Field *fields = result->Fetch(); - float x = fields[0].GetFloat(); - float y = fields[1].GetFloat(); - float z = fields[2].GetFloat(); - uint32 id = VISUAL_WAYPOINT; Player *chr = m_session->GetPlayer(); - float o = chr->GetOrientation(); Map *map = chr->GetMap(); + Field *fields = result->Fetch(); + CreatureCreatePos pos(map, fields[0].GetFloat(), fields[1].GetFloat(), fields[2].GetFloat(), chr->GetOrientation(), chr->GetPhaseMaskForSpawn()); + Creature* pCreature = new Creature; - pCreature->Relocate(x, y, z, o); - - if (!pCreature->IsPositionValid()) + if (!pCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, VISUAL_WAYPOINT)) { - sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY()); - delete pCreature; - delete result; - return false; - } - - if (!pCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id)) - { - PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); + PSendSysMessage(LANG_WAYPOINT_NOTCREATED, VISUAL_WAYPOINT); delete pCreature; delete result; return false; diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 84965d5e4..79532988b 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1653,33 +1653,18 @@ Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, floa if (GetTypeId()==TYPEID_PLAYER) team = ((Player*)this)->GetTeam(); - // FIXME: Setup near to finish point because GetObjectBoundingRadius set in Create but some Create calls can be dependent from proper position - // if creature have creature_template_addon.auras with persistent point for example or script call + CreatureCreatePos pos(GetMap(), x, y, x, ang, GetPhaseMask()); + if (x == 0.0f && y == 0.0f && z == 0.0f) - GetClosePoint(x, y, z, 0); + pos = CreatureCreatePos(this, GetOrientation(), CONTACT_DISTANCE, ang); - pCreature->Relocate(x, y, z, ang); - - if (!pCreature->Create(GetMap()->GenerateLocalLowGuid(HIGHGUID_UNIT), GetMap(), GetPhaseMask(), id, team)) + if (!pCreature->Create(GetMap()->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, id, team)) { delete pCreature; return NULL; } - if (x == 0.0f && y == 0.0f && z == 0.0f) - { - GetClosePoint(x, y, z, pCreature->GetObjectBoundingRadius()); - pCreature->Relocate(x, y, z, ang); - } - - pCreature->SetSummonPoint(x, y, z, ang); - - if(!pCreature->IsPositionValid()) - { - sLog.outError("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; - return NULL; - } + pCreature->SetSummonPoint(pos); // Active state set before added to map pCreature->SetActiveObjectState(asActiveObject); diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index d502ccb9f..d2b7b0207 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -149,33 +149,17 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool return false; } - // FIXME: Setup near to finish point because GetObjectBoundingRadius set in Create but some Create calls can be dependent from proper position - // if pet have creature_template_addon.auras with persistent point for example or script call - float px, py, pz; - owner->GetClosePoint(px, py, pz, 0, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - - Relocate(px, py, pz, owner->GetOrientation()); - Map *map = owner->GetMap(); - uint32 guid = map->GenerateLocalLowGuid(HIGHGUID_PET); - if (!Create(guid, map, owner->GetPhaseMask(), petentry, pet_number)) + + CreatureCreatePos pos(owner, owner->GetOrientation(), PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + + uint32 guid = pos.GetMap()->GenerateLocalLowGuid(HIGHGUID_PET); + if (!Create(guid, pos, petentry, pet_number)) { delete result; return false; } - owner->GetClosePoint(px, py, pz, GetObjectBoundingRadius(), PET_FOLLOW_DIST, PET_FOLLOW_ANGLE, this); - - Relocate(px, py, pz, owner->GetOrientation()); - - if (!IsPositionValid()) - { - sLog.outError("Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)", - GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); - delete result; - return false; - } - setPetType(pet_type); setFaction(owner->getFaction()); SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id); @@ -184,7 +168,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool if (cinfo->type == CREATURE_TYPE_CRITTER) { AIM_Initialize(); - map->Add((Creature*)this); + pos.GetMap()->Add((Creature*)this); delete result; return true; } @@ -813,20 +797,13 @@ bool Pet::CreateBaseAtCreature(Creature* creature) return false; } - Relocate(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation()); - - if(!IsPositionValid()) - { - sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)", - GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); - return false; - } + CreatureCreatePos pos(creature, creature->GetOrientation()); uint32 guid = creature->GetMap()->GenerateLocalLowGuid(HIGHGUID_PET); BASIC_LOG("Create pet"); uint32 pet_number = sObjectMgr.GeneratePetNumber(); - if(!Create(guid, creature->GetMap(), creature->GetPhaseMask(), creature->GetEntry(), pet_number)) + if (!Create(guid, pos, creature->GetEntry(), pet_number)) return false; CreatureInfo const *cinfo = GetCreatureInfo(); @@ -1930,16 +1907,21 @@ bool Pet::IsPermanentPetFor(Player* owner) } } -bool Pet::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number) +bool Pet::Create(uint32 guidlow, CreatureCreatePos& cPos, uint32 Entry, uint32 pet_number) { - SetMap(map); - SetPhaseMask(phaseMask,false); + SetMap(cPos.GetMap()); + SetPhaseMask(cPos.GetPhaseMask(), false); Object::_Create(guidlow, pet_number, HIGHGUID_PET); m_originalEntry = Entry; - if(!InitEntry(Entry)) + if (!InitEntry(Entry)) + return false; + + cPos.SelectFinalPoint(this); + + if (!cPos.Relocate(this)) return false; SetSheath(SHEATH_STATE_MELEE); diff --git a/src/game/Pet.h b/src/game/Pet.h index 184626cb0..9b81b0830 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -149,7 +149,7 @@ class Pet : public Creature bool IsPermanentPetFor(Player* owner); // pet have tab in character windows and set UNIT_FIELD_PETNUMBER - bool Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number); + bool Create (uint32 guidlow, CreatureCreatePos& cPos, uint32 Entry, uint32 pet_number); bool CreateBaseAtCreature(Creature* creature); bool LoadPetFromDB( Player* owner,uint32 petentry = 0,uint32 petnumber = 0, bool current = false ); void SavePetToDB(PetSaveMode mode); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 72dbd6e50..0016f96fb 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -4498,14 +4498,10 @@ void Spell::DoSummon(SpellEffectIndex eff_idx) if (m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry)) { // Summon in dest location - float x, y, z; if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) - { - x = m_targets.m_destX; - y = m_targets.m_destY; - z = m_targets.m_destZ; spawnCreature->Relocate(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation()); - } + + // set timer for unsummon if (duration > 0) @@ -4515,45 +4511,21 @@ void Spell::DoSummon(SpellEffectIndex eff_idx) } // Summon in dest location - float x, y, z; - if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) - { - x = m_targets.m_destX; - y = m_targets.m_destY; - z = m_targets.m_destZ; - } - else - // FIXME: Setup near to finish point because GetObjectBoundingRadius set in Create but some Create calls can be dependent from proper position - // if totem have creature_template_addon.auras with persistent point for example or script call - m_caster->GetClosePoint(x, y, z, 0); + CreatureCreatePos pos (m_caster->GetMap(), m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation(), m_caster->GetPhaseMask()); - spawnCreature->Relocate(x, y, z, -m_caster->GetOrientation()); + if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) + pos = CreatureCreatePos(m_caster, -m_caster->GetOrientation()); Map *map = m_caster->GetMap(); uint32 pet_number = sObjectMgr.GeneratePetNumber(); - if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(), - m_spellInfo->EffectMiscValue[eff_idx], pet_number)) + if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), pos, m_spellInfo->EffectMiscValue[eff_idx], pet_number)) { sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[eff_idx]); delete spawnCreature; return; } - if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) - { - m_caster->GetClosePoint(x, y, z, spawnCreature->GetObjectBoundingRadius()); - spawnCreature->Relocate(x, y, z, -m_caster->GetOrientation()); - } - - spawnCreature->SetSummonPoint(x, y, z, -m_caster->GetOrientation()); - - if (!spawnCreature->IsPositionValid()) - { - sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)", - spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); - delete spawnCreature; - return; - } + spawnCreature->SetSummonPoint(pos); // set timer for unsummon if (duration > 0) @@ -4984,55 +4956,34 @@ void Spell::DoSummonGuardian(SpellEffectIndex eff_idx, uint32 forceFaction) { Pet* spawnCreature = new Pet(petType); - float px, py, pz; // If dest location if present + // Summon 1 unit in dest location + CreatureCreatePos pos(m_caster->GetMap(), m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation(), m_caster->GetPhaseMask()); + 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); + if (count > 0) + { + float x, y, z; + m_caster->GetRandomPoint(center_x, center_y, center_z, radius, x, y, z); + pos = CreatureCreatePos(m_caster->GetMap(), x, y, z, m_caster->GetOrientation(), m_caster->GetPhaseMask()); + } } // Summon if dest location not present near caster else - // FIXME: Setup near to finish point because GetObjectBoundingRadius set in Create but some Create calls can be dependent from proper position - // if totem have creature_template_addon.auras with persistent point for example or script call - m_caster->GetClosePoint(px, py, pz, 0); - - spawnCreature->Relocate(px, py, pz, m_caster->GetOrientation()); + pos = CreatureCreatePos(m_caster, m_caster->GetOrientation()); Map *map = m_caster->GetMap(); uint32 pet_number = sObjectMgr.GeneratePetNumber(); - if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(), - m_spellInfo->EffectMiscValue[eff_idx], pet_number)) + if (!spawnCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), pos, m_spellInfo->EffectMiscValue[eff_idx], pet_number)) { sLog.outError("no such creature entry %u", m_spellInfo->EffectMiscValue[eff_idx]); delete spawnCreature; return; } - // Summon if dest location not present near caster - if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) - { - m_caster->GetClosePoint(px, py, pz,spawnCreature->GetObjectBoundingRadius()); - spawnCreature->Relocate(px, py, pz, m_caster->GetOrientation()); - } - - spawnCreature->SetSummonPoint(px, py, pz, m_caster->GetOrientation()); - - if (!spawnCreature->IsPositionValid()) - { - sLog.outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)", - spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); - delete spawnCreature; - return; - } + spawnCreature->SetSummonPoint(pos); if (duration > 0) spawnCreature->SetDuration(duration); @@ -5481,35 +5432,16 @@ void Spell::EffectSummonPet(SpellEffectIndex eff_idx) return; } - // FIXME: Setup near to finish point because GetObjectBoundingRadius set in Create but some Create calls can be dependent from proper position - // if totem have creature_template_addon.auras with persistent point for example or script call - float px, py, pz; - m_caster->GetClosePoint(px, py, pz, 0); - - NewSummon->Relocate(px, py, pz, m_caster->GetOrientation()); - + CreatureCreatePos pos(m_caster, m_caster->GetOrientation()); Map *map = m_caster->GetMap(); uint32 pet_number = sObjectMgr.GeneratePetNumber(); - if(!NewSummon->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(), - petentry, pet_number)) + if (!NewSummon->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), pos, petentry, pet_number)) { delete NewSummon; return; } - m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectBoundingRadius()); - - NewSummon->Relocate(px, py, pz, m_caster->GetOrientation()); - - if(!NewSummon->IsPositionValid()) - { - sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)", - NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY()); - delete NewSummon; - return; - } - uint32 petlevel = m_caster->getLevel(); NewSummon->setPetType(SUMMON_PET); @@ -7656,47 +7588,21 @@ void Spell::DoSummonTotem(SpellEffectIndex eff_idx, uint8 slot_dbc) if (Totem *OldTotem = m_caster->GetTotem(TotemSlot(slot))) OldTotem->UnSummon(); - Team team = TEAM_NONE; - if (m_caster->GetTypeId()==TYPEID_PLAYER) - team = ((Player*)m_caster)->GetTeam(); - - Totem* pTotem = new Totem; - // FIXME: Setup near to finish point because GetObjectBoundingRadius set in Create but some Create calls can be dependent from proper position // if totem have creature_template_addon.auras with persistent point for example or script call float angle = slot < MAX_TOTEM_SLOT ? M_PI_F/MAX_TOTEM_SLOT - (slot*2*M_PI_F/MAX_TOTEM_SLOT) : 0; - float x, y, z; - m_caster->GetClosePoint(x, y, z, 0, 2.0f, angle); + CreatureCreatePos pos(m_caster, m_caster->GetOrientation(), 2.0f, angle); - // totem must be at same Z in case swimming caster and etc. - if (fabs( z - m_caster->GetPositionZ() ) > 5) - z = m_caster->GetPositionZ(); + Totem* pTotem = new Totem; - pTotem->Relocate(x, y, z, m_caster->GetOrientation()); - - if (!pTotem->Create(m_caster->GetMap()->GenerateLocalLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(), - m_spellInfo->EffectMiscValue[eff_idx], team)) + if (!pTotem->Create(m_caster->GetMap()->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, m_spellInfo->EffectMiscValue[eff_idx], m_caster)) { delete pTotem; return; } - // special model selection case for totems - if (m_caster->GetTypeId() == TYPEID_PLAYER) - { - if (uint32 modelid_race = sObjectMgr.GetModelForRace(pTotem->GetNativeDisplayId(), m_caster->getRaceMask())) - pTotem->SetDisplayId(modelid_race); - } - - m_caster->GetClosePoint(x, y, z, pTotem->GetObjectBoundingRadius(), 2.0f, angle); - - // 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()); - pTotem->SetSummonPoint(x, y, z, m_caster->GetOrientation()); + pTotem->SetSummonPoint(pos); if (slot < MAX_TOTEM_SLOT) m_caster->_AddTotem(TotemSlot(slot),pTotem); @@ -8191,50 +8097,22 @@ void Spell::DoSummonCritter(SpellEffectIndex eff_idx, uint32 forceFaction) if (old_critter) m_caster->RemoveMiniPet(); + CreatureCreatePos pos(m_caster->GetMap(), m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, m_caster->GetOrientation(), m_caster->GetPhaseMask()); + if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) + pos = CreatureCreatePos(m_caster, m_caster->GetOrientation()); + // summon new pet Pet* critter = new Pet(MINI_PET); - float x, y, z; - // If dest location if present - if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) - { - x = m_targets.m_destX; - y = m_targets.m_destY; - z = m_targets.m_destZ; - } - else - // FIXME: Setup near to finish point because GetObjectBoundingRadius set in Create but some Create calls can be dependent from proper position - // if pet have creature_template_addon.auras with persistent point for example or script call - m_caster->GetClosePoint(x, y, z, 0); - - critter->Relocate(x, y, z, m_caster->GetOrientation()); - Map *map = m_caster->GetMap(); uint32 pet_number = sObjectMgr.GeneratePetNumber(); - if(!critter->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(), - pet_entry, pet_number)) + if (!critter->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), pos, pet_entry, pet_number)) { sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry); delete critter; return; } - // Summon if dest location not present near caster - if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) - { - m_caster->GetClosePoint(x, y, z, critter->GetObjectBoundingRadius()); - critter->Relocate(x, y, z, m_caster->GetOrientation()); - } - critter->SetSummonPoint(x, y, z, m_caster->GetOrientation()); - - if(!critter->IsPositionValid()) - { - sLog.outError("Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)", - critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY()); - delete critter; - return; - } - //critter->SetName(""); // generated by client critter->SetOwnerGuid(m_caster->GetObjectGuid()); critter->SetCreatorGuid(m_caster->GetObjectGuid()); diff --git a/src/game/Totem.cpp b/src/game/Totem.cpp index d2f7ba71c..2ec288e1a 100644 --- a/src/game/Totem.cpp +++ b/src/game/Totem.cpp @@ -24,6 +24,7 @@ #include "ObjectMgr.h" #include "SpellMgr.h" #include "CreatureAI.h" +#include "InstanceData.h" Totem::Totem() : Creature(CREATURE_SUBTYPE_TOTEM) { @@ -31,6 +32,43 @@ Totem::Totem() : Creature(CREATURE_SUBTYPE_TOTEM) m_type = TOTEM_PASSIVE; } +bool Totem::Create(uint32 guidlow, CreatureCreatePos& cPos, uint32 Entry, Unit* owner) +{ + SetMap(cPos.GetMap()); + SetPhaseMask(cPos.GetPhaseMask(), false); + + Team team = owner->GetTypeId() == TYPEID_PLAYER ? ((Player*)owner)->GetTeam() : TEAM_NONE; + + if (!CreateFromProto(guidlow, Entry, team)) + return false; + + // special model selection case for totems + if (owner->GetTypeId() == TYPEID_PLAYER) + { + if (uint32 modelid_race = sObjectMgr.GetModelForRace(GetNativeDisplayId(), owner->getRaceMask())) + SetDisplayId(modelid_race); + } + + cPos.SelectFinalPoint(this); + + // totem must be at same Z in case swimming caster and etc. + if (fabs(cPos.m_pos.z - owner->GetPositionZ() ) > 5.0f) + cPos.m_pos.z = owner->GetPositionZ(); + + if (!cPos.Relocate(this)) + return false; + + //Notify the map's instance data. + //Only works if you create the object in it, not if it is moves to that map. + //Normally non-players do not teleport to other maps. + if (InstanceData* iData = GetMap()->GetInstanceData()) + iData->OnCreatureCreate(this); + + LoadCreatureAddon(); + + return true; +} + void Totem::Update(uint32 update_diff, uint32 time ) { Unit *owner = GetOwner(); diff --git a/src/game/Totem.h b/src/game/Totem.h index 3dbc81413..c9ccbf419 100644 --- a/src/game/Totem.h +++ b/src/game/Totem.h @@ -33,6 +33,7 @@ class Totem : public Creature public: explicit Totem(); virtual ~Totem(){}; + bool Create(uint32 guidlow, CreatureCreatePos& cPos, uint32 Entry, Unit* owner); void Update(uint32 update_diff, uint32 time ); void Summon(Unit* owner); void UnSummon(); diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp index 2e3c73b5b..bf4957bdb 100644 --- a/src/game/Vehicle.cpp +++ b/src/game/Vehicle.cpp @@ -61,15 +61,21 @@ void Vehicle::Update( uint32 update_diff, uint32 diff) Creature::Update(update_diff, diff); } -bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, Team team) +bool Vehicle::Create(uint32 guidlow, CreatureCreatePos& cPos, uint32 Entry, uint32 vehicleId, Team team) { - SetMap(map); + SetMap(cPos.GetMap()); + SetPhaseMask(cPos.GetPhaseMask(), false); Object::_Create(guidlow, Entry, HIGHGUID_VEHICLE); if(!InitEntry(Entry)) return false; + cPos.SelectFinalPoint(this); + + if (!cPos.Relocate(this)) + return false; + m_defaultMovementType = IDLE_MOTION_TYPE; AIM_Initialize(); diff --git a/src/game/Vehicle.h b/src/game/Vehicle.h index 194525b7c..ca38c99fd 100644 --- a/src/game/Vehicle.h +++ b/src/game/Vehicle.h @@ -34,7 +34,7 @@ class Vehicle : public Creature void AddToWorld(); void RemoveFromWorld(); - bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, Team team); + bool Create(uint32 guidlow, CreatureCreatePos& cPos, uint32 Entry, uint32 vehicleId, Team team); void SetDeathState(DeathState s); // overwrite virtual Creature::SetDeathState and Unit::SetDeathState void Update(uint32 update_diff, uint32 diff); // overwrite virtual Creature::Update and Unit::Update diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp index cfe6cb17f..c6dc0f309 100644 --- a/src/game/debugcmds.cpp +++ b/src/game/debugcmds.cpp @@ -663,30 +663,19 @@ bool ChatHandler::HandleDebugSpawnVehicleCommand(char* args) if (!ve) return false; + Player* chr = m_session->GetPlayer(); + Vehicle *v = new Vehicle; - float px, py, pz; - m_session->GetPlayer()->GetClosePoint(px, py, pz, m_session->GetPlayer()->GetObjectBoundingRadius()); + CreatureCreatePos pos(chr, chr->GetOrientation()); - v->Relocate(px, py, pz, m_session->GetPlayer()->GetOrientation()); - - if (!v->IsPositionValid()) - { - sLog.outError("Vehicle (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)", - v->GetGUIDLow(), v->GetEntry(), v->GetPositionX(), v->GetPositionY()); - delete v; - return false; - } - - Map *map = m_session->GetPlayer()->GetMap(); - - if (!v->Create(map->GenerateLocalLowGuid(HIGHGUID_VEHICLE), map, entry, id, m_session->GetPlayer()->GetTeam())) + if (!v->Create(pos.GetMap()->GenerateLocalLowGuid(HIGHGUID_VEHICLE), pos, entry, id, chr->GetTeam())) { delete v; return false; } - map->Add((Creature*)v); + pos.GetMap()->Add((Creature*)v); return true; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 444a31f23..4f0f2ce81 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "11243" + #define REVISION_NR "11244" #endif // __REVISION_NR_H__