diff options
| author | Shauren <shauren.trinity@gmail.com> | 2013-02-27 13:17:20 +0100 | 
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2013-02-27 13:17:20 +0100 | 
| commit | 9301e31a4e895d79c518c0002da7cedeaff5df74 (patch) | |
| tree | 80f28381591f1b656ecc72d340457465ef215b26 /src | |
| parent | 480c6cf4dd8965627aa7bc6e903558f2fa5c3ea6 (diff) | |
Core/Spells: Allow free casting of player's own spells on vehicle seats with flag VEHICLE_SEAT_FLAG_CAN_ATTACK
Diffstat (limited to 'src')
| -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;  | 
