[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

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