mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-16 04:59:41 -04:00
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:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -301,7 +301,7 @@ class boss_rimefang : public CreatureScript
|
||||
|
||||
void JustReachedHome()
|
||||
{
|
||||
_vehicle->InstallAllAccessories(me->GetEntry());
|
||||
_vehicle->InstallAllAccessories();
|
||||
}
|
||||
|
||||
void DoAction(const int32 actionId)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user