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:58:41 +01:00
parent aa2455b586
commit 683cea9e83
11 changed files with 75 additions and 26 deletions
@@ -1251,7 +1251,7 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 vehId, uint3
if (!vehId) if (!vehId)
vehId = cinfo->VehicleId; vehId = cinfo->VehicleId;
if (vehId && !CreateVehicleKit(vehId)) if (vehId && !CreateVehicleKit(vehId, Entry))
vehId = 0; vehId = 0;
Object::_Create(guidlow, Entry, vehId ? HIGHGUID_VEHICLE : HIGHGUID_UNIT); Object::_Create(guidlow, Entry, vehId ? HIGHGUID_VEHICLE : HIGHGUID_UNIT);
+19 -8
View File
@@ -11694,7 +11694,7 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
if (VehicleId) if (VehicleId)
{ {
if (CreateVehicleKit(VehicleId)) if (CreateVehicleKit(VehicleId, creatureEntry))
{ {
GetVehicleKit()->Reset(); GetVehicleKit()->Reset();
@@ -11708,7 +11708,7 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
plr->GetSession()->SendPacket(&data); plr->GetSession()->SendPacket(&data);
// mounts can also have accessories // 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); VehicleEntry const *vehInfo = sVehicleStore.LookupEntry(id);
if (!vehInfo) if (!vehInfo)
return false; return false;
m_vehicleKit = new Vehicle(this, vehInfo); m_vehicleKit = new Vehicle(this, vehInfo, creatureEntry);
m_updateFlag |= UPDATEFLAG_VEHICLE; m_updateFlag |= UPDATEFLAG_VEHICLE;
m_unitTypeMask |= UNIT_MASK_VEHICLE; m_unitTypeMask |= UNIT_MASK_VEHICLE;
return true; return true;
@@ -16459,7 +16459,7 @@ bool Unit::CheckPlayerCondition(Player* pPlayer)
bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
{ {
bool success = false; 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); SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(spellClickEntry);
for (SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) 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; uint8 i = 0;
bool valid = false; bool valid = false;
while (i < MAX_SPELL_EFFECTS && !valid) while (i < MAX_SPELL_EFFECTS && !valid)
if (spellEntry->EffectApplyAuraName[i] == SPELL_AURA_CONTROL_VEHICLE) if (spellEntry->EffectApplyAuraName[i++] == SPELL_AURA_CONTROL_VEHICLE)
valid = true; valid = true;
if (!valid) if (!valid)
@@ -16486,10 +16486,21 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
return false; 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 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; success = true;
} }
+1 -1
View File
@@ -2039,7 +2039,7 @@ class Unit : public WorldObject
Unit *GetMisdirectionTarget() { return m_misdirectionTargetGUID ? GetUnit(*this, m_misdirectionTargetGUID) : NULL; } Unit *GetMisdirectionTarget() { return m_misdirectionTargetGUID ? GetUnit(*this, m_misdirectionTargetGUID) : NULL; }
bool IsAIEnabled, NeedChangeAI; bool IsAIEnabled, NeedChangeAI;
bool CreateVehicleKit(uint32 id); bool CreateVehicleKit(uint32 id, uint32 creatureEntry);
void RemoveVehicleKit(); void RemoveVehicleKit();
Vehicle *GetVehicleKit()const { return m_vehicleKit; } Vehicle *GetVehicleKit()const { return m_vehicleKit; }
Vehicle *GetVehicle() const { return m_vehicle; } Vehicle *GetVehicle() const { return m_vehicle; }
+18 -4
View File
@@ -27,7 +27,8 @@
#include "CreatureAI.h" #include "CreatureAI.h"
#include "ZoneScript.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) for (uint32 i = 0; i < MAX_VEHICLE_SEATS; ++i)
{ {
@@ -119,9 +120,11 @@ void Vehicle::Install()
sScriptMgr->OnInstall(this); 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) if (!mVehicleList)
return; return;
@@ -167,7 +170,7 @@ void Vehicle::Reset()
} }
else else
{ {
InstallAllAccessories(me->GetEntry()); InstallAllAccessories();
if (m_usableSeatNum) if (m_usableSeatNum)
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
} }
@@ -528,3 +531,14 @@ SeatMap::iterator Vehicle::GetSeatIteratorForPassenger(Unit* passenger)
return m_Seats.end(); 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;
}
+4 -2
View File
@@ -113,14 +113,14 @@ class Vehicle
friend class WorldSession; friend class WorldSession;
public: public:
explicit Vehicle(Unit *unit, VehicleEntry const *vehInfo); explicit Vehicle(Unit *unit, VehicleEntry const *vehInfo, uint32 creatureEntry);
virtual ~Vehicle(); virtual ~Vehicle();
void Install(); void Install();
void Uninstall(); void Uninstall();
void Reset(); void Reset();
void Die(); void Die();
void InstallAllAccessories(uint32 entry); void InstallAllAccessories();
Unit *GetBase() const { return me; } Unit *GetBase() const { return me; }
VehicleEntry const *GetVehicleInfo() const { return m_vehicleInfo; } VehicleEntry const *GetVehicleInfo() const { return m_vehicleInfo; }
@@ -128,6 +128,7 @@ class Vehicle
bool HasEmptySeat(int8 seatId) const; bool HasEmptySeat(int8 seatId) const;
Unit *GetPassenger(int8 seatId) const; Unit *GetPassenger(int8 seatId) const;
int8 GetNextEmptySeat(int8 seatId, bool next) const; int8 GetNextEmptySeat(int8 seatId, bool next) const;
uint8 GetAvailableSeatCount() const;
bool AddPassenger(Unit *passenger, int8 seatId = -1); bool AddPassenger(Unit *passenger, int8 seatId = -1);
void EjectPassenger(Unit* passenger, Unit* controller); void EjectPassenger(Unit* passenger, Unit* controller);
@@ -152,6 +153,7 @@ class Vehicle
VehicleEntry const *m_vehicleInfo; VehicleEntry const *m_vehicleInfo;
uint32 m_usableSeatNum; // Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags uint32 m_usableSeatNum; // Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags
uint32 m_bonusHP; 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); void InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 type, uint32 summonTime);
}; };
-6
View File
@@ -790,12 +790,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureInfo const* cInfo)
if (cInfo->rangeattacktime == 0) if (cInfo->rangeattacktime == 0)
const_cast<CreatureInfo*>(cInfo)->rangeattacktime = BASE_ATTACK_TIME; 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) 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); sLog->outErrorDb("Creature (Entry: %u) has wrong trainer type %u.", cInfo->Entry, cInfo->trainer_type);
@@ -6594,7 +6594,7 @@ void AuraEffect::HandleAuraSetVehicle(AuraApplication const * aurApp, uint8 mode
if (apply) if (apply)
{ {
if (!target->CreateVehicleKit(vehicleId)) if (!target->CreateVehicleKit(vehicleId, 0))
return; return;
} }
else if (target->GetVehicleKit()) else if (target->GetVehicleKit())
+28
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_1 = GetLastSpellInChain(spellInfo_1->Id);
uint32 spellId_2 = GetLastSpellInChain(spellInfo_2->Id); uint32 spellId_2 = GetLastSpellInChain(spellInfo_2->Id);
@@ -162,7 +162,7 @@ class boss_ick : public CreatureScript
void EnterCombat(Unit * /*who*/) void EnterCombat(Unit * /*who*/)
{ {
_vehicle->InstallAllAccessories(me->GetEntry()); _vehicle->InstallAllAccessories();
if (Creature* krick = GetKrick()) if (Creature* krick = GetKrick())
DoScriptText(SAY_KRICK_AGGRO, krick); DoScriptText(SAY_KRICK_AGGRO, krick);
@@ -301,7 +301,7 @@ class boss_rimefang : public CreatureScript
void JustReachedHome() void JustReachedHome()
{ {
_vehicle->InstallAllAccessories(me->GetEntry()); _vehicle->InstallAllAccessories();
} }
void DoAction(const int32 actionId) void DoAction(const int32 actionId)
@@ -366,7 +366,7 @@ public:
void SpellHit(Unit* /*caster*/, const SpellEntry* pSpell) void SpellHit(Unit* /*caster*/, const SpellEntry* pSpell)
{ {
if (pSpell->Id == SPELL_START_THE_ENGINE) if (pSpell->Id == SPELL_START_THE_ENGINE)
vehicle->InstallAllAccessories(me->GetEntry()); vehicle->InstallAllAccessories();
if (pSpell->Id == SPELL_ELECTROSHOCK) if (pSpell->Id == SPELL_ELECTROSHOCK)
me->InterruptSpell(CURRENT_CHANNELED_SPELL); me->InterruptSpell(CURRENT_CHANNELED_SPELL);