[11244] Collect in CreatureCreatePos data for delayed pos setup into Creature::Create.

* CreatureCreatePos work in 3 modes:
    - exactly provided coordinates/orientation/map/phasemask
    - exactly object + orientation as coordinates/map/phasemask
    - delayed position calculation near provided object at specific dist/angle.
* Use in similar way and for Pet/Vehicle Create functions.
  For Totem created new Totem::Create function with some moved in to it totem specific code.
* This let resolve recent problems with creature spawn and preserve fix for cases when
  Creature::Create addon/script code expected known correct possition for creature.
This commit is contained in:
VladimirMangos 2011-03-14 05:42:44 +03:00
parent 44915f6f13
commit 2b65cdb3bb
13 changed files with 223 additions and 362 deletions

View file

@ -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;

View file

@ -378,6 +378,32 @@ typedef std::map<uint32,time_t> 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; }

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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());

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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

View file

@ -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;
}

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "11243"
#define REVISION_NR "11244"
#endif // __REVISION_NR_H__