Core/Vehicles:

- Grab correct npc entry from npc_spellclick_spells in case of player vehicle. Fixes DB errors added in my previous changeset
- Allow aura's with SPELL_AURA_CONTROL_VEHICLE to stack if there are enough free seats, even if spellIds are identical.
- Fix a possible infinite loop. Thanks to manuel for spotting
This commit is contained in:
Machiavelli
2011-02-27 03:53:24 +01:00
parent aa2455b586
commit 683cea9e83
11 changed files with 75 additions and 26 deletions

View File

@@ -1251,7 +1251,7 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 vehId, uint3
if (!vehId)
vehId = cinfo->VehicleId;
if (vehId && !CreateVehicleKit(vehId))
if (vehId && !CreateVehicleKit(vehId, Entry))
vehId = 0;
Object::_Create(guidlow, Entry, vehId ? HIGHGUID_VEHICLE : HIGHGUID_UNIT);

View File

@@ -11694,7 +11694,7 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
if (VehicleId)
{
if (CreateVehicleKit(VehicleId))
if (CreateVehicleKit(VehicleId, creatureEntry))
{
GetVehicleKit()->Reset();
@@ -11708,7 +11708,7 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
plr->GetSession()->SendPacket(&data);
// mounts can also have accessories
GetVehicleKit()->InstallAllAccessories(creatureEntry);
GetVehicleKit()->InstallAllAccessories();
}
}
}
@@ -15683,13 +15683,13 @@ void Unit::RestoreFaction()
}
}
bool Unit::CreateVehicleKit(uint32 id)
bool Unit::CreateVehicleKit(uint32 id, uint32 creatureEntry)
{
VehicleEntry const *vehInfo = sVehicleStore.LookupEntry(id);
if (!vehInfo)
return false;
m_vehicleKit = new Vehicle(this, vehInfo);
m_vehicleKit = new Vehicle(this, vehInfo, creatureEntry);
m_updateFlag |= UPDATEFLAG_VEHICLE;
m_unitTypeMask |= UNIT_MASK_VEHICLE;
return true;
@@ -16459,7 +16459,7 @@ bool Unit::CheckPlayerCondition(Player* pPlayer)
bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
{
bool success = false;
uint32 spellClickEntry = GetTypeId() == TYPEID_UNIT ? GetEntry() : GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID);
uint32 spellClickEntry = GetVehicleKit() ? GetVehicleKit()->m_creatureEntry : GetEntry();
SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(spellClickEntry);
for (SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
{
@@ -16477,7 +16477,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
uint8 i = 0;
bool valid = false;
while (i < MAX_SPELL_EFFECTS && !valid)
if (spellEntry->EffectApplyAuraName[i] == SPELL_AURA_CONTROL_VEHICLE)
if (spellEntry->EffectApplyAuraName[i++] == SPELL_AURA_CONTROL_VEHICLE)
valid = true;
if (!valid)
@@ -16486,10 +16486,21 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
return false;
}
caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId+1, target, true, NULL, NULL, origCasterGUID);
if (IsInMap(caster))
caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId+1, target, true, NULL, NULL, origCasterGUID);
else // This can happen during Player::_LoadAuras
{
int32 bp0 = seatId;
Aura::TryCreate(spellEntry, this, clicker, &bp0, NULL, origCasterGUID);
}
}
else
caster->CastSpell(target, spellEntry, true, NULL, NULL, origCasterGUID);
{
if (IsInMap(caster))
caster->CastSpell(target, spellEntry, true, NULL, NULL, origCasterGUID);
else
Aura::TryCreate(spellEntry, this, clicker, NULL, NULL, origCasterGUID);
}
success = true;
}

View File

@@ -2039,7 +2039,7 @@ class Unit : public WorldObject
Unit *GetMisdirectionTarget() { return m_misdirectionTargetGUID ? GetUnit(*this, m_misdirectionTargetGUID) : NULL; }
bool IsAIEnabled, NeedChangeAI;
bool CreateVehicleKit(uint32 id);
bool CreateVehicleKit(uint32 id, uint32 creatureEntry);
void RemoveVehicleKit();
Vehicle *GetVehicleKit()const { return m_vehicleKit; }
Vehicle *GetVehicle() const { return m_vehicle; }

View File

@@ -27,7 +27,8 @@
#include "CreatureAI.h"
#include "ZoneScript.h"
Vehicle::Vehicle(Unit *unit, VehicleEntry const *vehInfo) : me(unit), m_vehicleInfo(vehInfo), m_usableSeatNum(0), m_bonusHP(0)
Vehicle::Vehicle(Unit *unit, VehicleEntry const *vehInfo, uint32 creatureEntry)
: me(unit), m_vehicleInfo(vehInfo), m_usableSeatNum(0), m_bonusHP(0), m_creatureEntry(creatureEntry)
{
for (uint32 i = 0; i < MAX_VEHICLE_SEATS; ++i)
{
@@ -119,9 +120,11 @@ void Vehicle::Install()
sScriptMgr->OnInstall(this);
}
void Vehicle::InstallAllAccessories(uint32 entry)
void Vehicle::InstallAllAccessories()
{
VehicleAccessoryList const* mVehicleList = sObjectMgr->GetVehicleAccessoryList(entry);
me->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE); // We might have aura's saved in the DB with now invalid casters - remove
VehicleAccessoryList const* mVehicleList = sObjectMgr->GetVehicleAccessoryList(m_creatureEntry);
if (!mVehicleList)
return;
@@ -167,7 +170,7 @@ void Vehicle::Reset()
}
else
{
InstallAllAccessories(me->GetEntry());
InstallAllAccessories();
if (m_usableSeatNum)
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
}
@@ -528,3 +531,14 @@ SeatMap::iterator Vehicle::GetSeatIteratorForPassenger(Unit* passenger)
return m_Seats.end();
}
uint8 Vehicle::GetAvailableSeatCount() const
{
uint8 ret = 0;
SeatMap::const_iterator itr;
for (itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
if (!itr->second.passenger && (itr->second.seatInfo->CanEnterOrExit() || itr->second.seatInfo->IsUsableByOverride()))
++ret;
return ret;
}

View File

@@ -113,14 +113,14 @@ class Vehicle
friend class WorldSession;
public:
explicit Vehicle(Unit *unit, VehicleEntry const *vehInfo);
explicit Vehicle(Unit *unit, VehicleEntry const *vehInfo, uint32 creatureEntry);
virtual ~Vehicle();
void Install();
void Uninstall();
void Reset();
void Die();
void InstallAllAccessories(uint32 entry);
void InstallAllAccessories();
Unit *GetBase() const { return me; }
VehicleEntry const *GetVehicleInfo() const { return m_vehicleInfo; }
@@ -128,6 +128,7 @@ class Vehicle
bool HasEmptySeat(int8 seatId) const;
Unit *GetPassenger(int8 seatId) const;
int8 GetNextEmptySeat(int8 seatId, bool next) const;
uint8 GetAvailableSeatCount() const;
bool AddPassenger(Unit *passenger, int8 seatId = -1);
void EjectPassenger(Unit* passenger, Unit* controller);
@@ -152,6 +153,7 @@ class Vehicle
VehicleEntry const *m_vehicleInfo;
uint32 m_usableSeatNum; // Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags
uint32 m_bonusHP;
uint32 m_creatureEntry; // Can be different than me->GetBase()->GetEntry() in case of players
void InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 type, uint32 summonTime);
};

View File

@@ -790,12 +790,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureInfo const* cInfo)
if (cInfo->rangeattacktime == 0)
const_cast<CreatureInfo*>(cInfo)->rangeattacktime = BASE_ATTACK_TIME;
if (cInfo->npcflag & UNIT_NPC_FLAG_SPELLCLICK)
{
sLog->outErrorDb("Creature (Entry: %u) has dynamic flag UNIT_NPC_FLAG_SPELLCLICK (%u) set, it is expected to be set by code handling `npc_spellclick_spells` content.", cInfo->Entry, UNIT_NPC_FLAG_SPELLCLICK);
const_cast<CreatureInfo*>(cInfo)->npcflag &= ~UNIT_NPC_FLAG_SPELLCLICK;
}
if ((cInfo->npcflag & UNIT_NPC_FLAG_TRAINER) && cInfo->trainer_type >= MAX_TRAINER_TYPE)
sLog->outErrorDb("Creature (Entry: %u) has wrong trainer type %u.", cInfo->Entry, cInfo->trainer_type);

View File

@@ -6594,7 +6594,7 @@ void AuraEffect::HandleAuraSetVehicle(AuraApplication const * aurApp, uint8 mode
if (apply)
{
if (!target->CreateVehicleKit(vehicleId))
if (!target->CreateVehicleKit(vehicleId, 0))
return;
}
else if (target->GetVehicleKit())

View File

@@ -3177,6 +3177,34 @@ bool SpellMgr::CanAurasStack(Aura const *aura1, Aura const *aura2, bool sameCast
}
}
bool isVehicleAura1 = false;
bool isVehicleAura2 = false;
uint8 i = 0;
while (i < MAX_SPELL_EFFECTS && !(isVehicleAura1 && isVehicleAura2))
{
if (spellInfo_1->EffectApplyAuraName[i] == SPELL_AURA_CONTROL_VEHICLE)
isVehicleAura1 = true;
if (spellInfo_2->EffectApplyAuraName[i] == SPELL_AURA_CONTROL_VEHICLE)
isVehicleAura2 = true;
++i;
}
if (isVehicleAura1 && isVehicleAura2)
{
Vehicle* veh = NULL;
if (aura1->GetOwner()->ToUnit())
veh = aura1->GetOwner()->ToUnit()->GetVehicleKit();
if (!veh) // We should probably just let it stack. Vehicle system will prevent undefined behaviour later
return true;
if (!veh->GetAvailableSeatCount())
return false; // No empty seat available
return true; // Empty seat available (skip rest)
}
uint32 spellId_1 = GetLastSpellInChain(spellInfo_1->Id);
uint32 spellId_2 = GetLastSpellInChain(spellInfo_2->Id);

View File

@@ -162,7 +162,7 @@ class boss_ick : public CreatureScript
void EnterCombat(Unit * /*who*/)
{
_vehicle->InstallAllAccessories(me->GetEntry());
_vehicle->InstallAllAccessories();
if (Creature* krick = GetKrick())
DoScriptText(SAY_KRICK_AGGRO, krick);

View File

@@ -301,7 +301,7 @@ class boss_rimefang : public CreatureScript
void JustReachedHome()
{
_vehicle->InstallAllAccessories(me->GetEntry());
_vehicle->InstallAllAccessories();
}
void DoAction(const int32 actionId)

View File

@@ -366,7 +366,7 @@ public:
void SpellHit(Unit* /*caster*/, const SpellEntry* pSpell)
{
if (pSpell->Id == SPELL_START_THE_ENGINE)
vehicle->InstallAllAccessories(me->GetEntry());
vehicle->InstallAllAccessories();
if (pSpell->Id == SPELL_ELECTROSHOCK)
me->InterruptSpell(CURRENT_CHANNELED_SPELL);