diff options
-rwxr-xr-x | src/server/game/Entities/Vehicle/Vehicle.cpp | 22 | ||||
-rw-r--r-- | src/server/game/Entities/Vehicle/Vehicle.h | 6 | ||||
-rw-r--r-- | src/server/game/Handlers/SpellHandler.cpp | 39 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 34 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 51 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.h | 1 |
6 files changed, 104 insertions, 49 deletions
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index f3844d96069..bfffc84671f 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -576,6 +576,26 @@ void Vehicle::Dismiss() } /** + * @fn bool Vehicle::IsVehicleInUse() const + * + * @brief Returns information whether the vehicle is currently used by any unit + * + * @author Shauren + * @date 26-2-2013 + * + * @return true if any passenger is boarded on vehicle, false otherwise. + */ + +bool Vehicle::IsVehicleInUse() const +{ + for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr) + if (itr->second.Passenger) + return true; + + return false; +} + +/** * @fn void Vehicle::InitMovementInfoForBase() * * @brief Sets correct MovementFlags2 based on VehicleFlags from DBC. @@ -613,7 +633,7 @@ void Vehicle::InitMovementInfoForBase() * @return null if passenger not found on vehicle, else the DBC record for the seat. */ -VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit* passenger) +VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit const* passenger) { SeatMap::iterator itr; for (itr = Seats.begin(); itr != Seats.end(); ++itr) diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index 8b67b82cfa3..f9bf3c21ef4 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -63,14 +63,14 @@ class Vehicle : public TransportBase void RelocatePassengers(); void RemoveAllPassengers(); void Dismiss(); - bool IsVehicleInUse() { return Seats.begin() != Seats.end(); } + bool IsVehicleInUse() const; void SetLastShootPos(Position const& pos) { _lastShootPos.Relocate(pos); } - Position GetLastShootPos() { return _lastShootPos; } + Position const& GetLastShootPos() const { return _lastShootPos; } SeatMap Seats; ///< The collection of all seats on the vehicle. Including vacant ones. - VehicleSeatEntry const* GetSeatForPassenger(Unit* passenger); + VehicleSeatEntry const* GetSeatForPassenger(Unit const* passenger); protected: friend class VehicleJoinEvent; diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 45cb8164775..8f63345925d 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -320,7 +320,6 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) } SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) { sLog->outError(LOG_FILTER_NETWORKIO, "WORLD: unknown spell id %u", spellId); @@ -328,31 +327,37 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) return; } - if (mover->GetTypeId() == TYPEID_PLAYER) + if (spellInfo->IsPassive()) { - // not have spell in spellbook or spell passive and not casted by client - if (!mover->ToPlayer()->HasActiveSpell (spellId) || spellInfo->IsPassive()) - { - //cheater? kick? ban? - recvPacket.rfinish(); // prevent spam at ignore packet - return; - } + recvPacket.rfinish(); // prevent spam at ignore packet + return; } - else + + Unit* caster = mover; + if (caster->GetTypeId() == TYPEID_UNIT && !caster->ToCreature()->HasSpell(spellId)) { - // not have spell in spellbook or spell passive and not casted by client - if ((mover->GetTypeId() == TYPEID_UNIT && !mover->ToCreature()->HasSpell(spellId)) || spellInfo->IsPassive()) + // If the vehicle creature does not have the spell but it allows the passenger to cast own spells + // change caster to player and let him cast + if (!_player->IsOnVehicle(caster) || spellInfo->CheckVehicle(_player) != SPELL_CAST_OK) { - //cheater? kick? ban? recvPacket.rfinish(); // prevent spam at ignore packet return; } + + caster = _player; + } + + if (caster->GetTypeId() == TYPEID_PLAYER && !caster->ToPlayer()->HasActiveSpell(spellId)) + { + // not have spell in spellbook + recvPacket.rfinish(); // prevent spam at ignore packet + return; } // Client is resending autoshot cast opcode when other spell is casted during shoot rotation // Skip it to prevent "interrupt" message - if (spellInfo->IsAutoRepeatRangedSpell() && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) - && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo == spellInfo) + if (spellInfo->IsAutoRepeatRangedSpell() && caster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) + && caster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo == spellInfo) { recvPacket.rfinish(); return; @@ -367,7 +372,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) // client provided targets SpellCastTargets targets; - targets.Read(recvPacket, mover); + targets.Read(recvPacket, caster); HandleClientCastFlags(recvPacket, castFlags, targets); // auto-selection buff level base at target level (in spellInfo) @@ -380,7 +385,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) spellInfo = actualSpellInfo; } - Spell* spell = new Spell(mover, spellInfo, TRIGGERED_NONE, 0, false); + Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE, 0, false); spell->m_cast_count = castCount; // set count of casts spell->prepare(&targets); } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 8c9f51a0f0a..342f0cfbddf 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4832,34 +4832,12 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_MOVING; } - - Vehicle* vehicle = m_caster->GetVehicle(); - if (vehicle && !(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE)) + // Check vehicle flags + if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE)) { - uint16 checkMask = 0; - for (uint8 effIndex = EFFECT_0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) - { - SpellEffectInfo const* effInfo = &m_spellInfo->Effects[effIndex]; - if (effInfo->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) - { - SpellShapeshiftEntry const* shapeShiftEntry = sSpellShapeshiftStore.LookupEntry(effInfo->MiscValue); - if (shapeShiftEntry && (shapeShiftEntry->flags1 & 1) == 0) // unk flag - checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED; - break; - } - } - - if (m_spellInfo->HasAura(SPELL_AURA_MOUNTED)) - checkMask |= VEHICLE_SEAT_FLAG_CAN_CAST_MOUNT_SPELL; - - if (!checkMask) - checkMask = VEHICLE_SEAT_FLAG_CAN_ATTACK; - - // All creatures should be able to cast as passengers freely, restriction and attribute are only for players - VehicleSeatEntry const* vehicleSeat = vehicle->GetSeatForPassenger(m_caster); - if (!(m_spellInfo->AttributesEx6 & SPELL_ATTR6_CASTABLE_WHILE_ON_VEHICLE) && !(m_spellInfo->Attributes & SPELL_ATTR0_CASTABLE_WHILE_MOUNTED) - && (vehicleSeat->m_flags & checkMask) != checkMask && m_caster->GetTypeId() == TYPEID_PLAYER) - return SPELL_FAILED_DONT_REPORT; + SpellCastResult vehicleCheck = m_spellInfo->CheckVehicle(m_caster); + if (vehicleCheck != SPELL_CAST_OK) + return vehicleCheck; } // check spell cast conditions from database @@ -7167,7 +7145,7 @@ bool Spell::CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToC if (((*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && !(*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)) || (!(*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && (*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck))) return false; - + std::list<SpellScript::ObjectAreaTargetSelectHandler>::iterator areaTargetSelectHookEnd = (*itr)->OnObjectAreaTargetSelect.end(), areaTargetSelectHookItr = (*itr)->OnObjectAreaTargetSelect.begin(); for (; areaTargetSelectHookItr != areaTargetSelectHookEnd; ++areaTargetSelectHookItr) if (((*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && !(*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)) || diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index d2ab1a315e8..aea7689c051 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -23,6 +23,7 @@ #include "ConditionMgr.h" #include "Player.h" #include "Battleground.h" +#include "Vehicle.h" uint32 GetTargetFlagMask(SpellTargetObjectTypes objType) { @@ -1614,6 +1615,56 @@ SpellCastResult SpellInfo::CheckExplicitTarget(Unit const* caster, WorldObject c return SPELL_CAST_OK; } +SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const +{ + // All creatures should be able to cast as passengers freely, restriction and attribute are only for players + if (caster->GetTypeId() != TYPEID_PLAYER) + return SPELL_CAST_OK; + + Vehicle* vehicle = caster->GetVehicle(); + if (vehicle) + { + uint16 checkMask = 0; + for (uint8 effIndex = EFFECT_0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + { + if (Effects[effIndex].ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) + { + SpellShapeshiftEntry const* shapeShiftEntry = sSpellShapeshiftStore.LookupEntry(Effects[effIndex].MiscValue); + if (shapeShiftEntry && (shapeShiftEntry->flags1 & 1) == 0) // unk flag + checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED; + break; + } + } + + if (HasAura(SPELL_AURA_MOUNTED)) + checkMask |= VEHICLE_SEAT_FLAG_CAN_CAST_MOUNT_SPELL; + + if (!checkMask) + checkMask = VEHICLE_SEAT_FLAG_CAN_ATTACK; + + VehicleSeatEntry const* vehicleSeat = vehicle->GetSeatForPassenger(caster); + if (!(AttributesEx6 & SPELL_ATTR6_CASTABLE_WHILE_ON_VEHICLE) && !(Attributes & SPELL_ATTR0_CASTABLE_WHILE_MOUNTED) + && (vehicleSeat->m_flags & checkMask) != checkMask) + return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; + + // Can only summon uncontrolled minions/guardians when on controlled vehicle + if (vehicleSeat->m_flags & (VEHICLE_SEAT_FLAG_CAN_CONTROL | VEHICLE_SEAT_FLAG_UNK2)) + { + for (uint32 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i) + { + if (Effects[i].Effect != SPELL_EFFECT_SUMMON) + continue; + + SummonPropertiesEntry const* props = sSummonPropertiesStore.LookupEntry(Effects[i].MiscValueB); + if (props && props->Category != SUMMON_CATEGORY_WILD) + return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; + } + } + } + + return SPELL_CAST_OK; +} + bool SpellInfo::CheckTargetCreatureType(Unit const* target) const { // Curse of Doom & Exorcism: not find another way to fix spell target check :/ diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index bbc5b61e282..cc0a0101597 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -420,6 +420,7 @@ public: SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL) const; SpellCastResult CheckTarget(Unit const* caster, WorldObject const* target, bool implicit = true) const; SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = NULL) const; + SpellCastResult CheckVehicle(Unit const* caster) const; bool CheckTargetCreatureType(Unit const* target) const; SpellSchoolMask GetSchoolMask() const; |