2010-10-07 15:35:36 +02:00
/*
2012-01-01 00:32:13 +01:00
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
2010-10-07 15:35:36 +02:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
2008-12-24 09:58:26 -06:00
*/
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
#include "Common.h"
#include "Log.h"
#include "ObjectMgr.h"
#include "Vehicle.h"
#include "Unit.h"
#include "Util.h"
2009-04-17 15:08:58 -05:00
#include "WorldPacket.h"
2010-08-06 19:23:43 +02:00
#include "ScriptMgr.h"
2009-06-03 00:24:07 -05:00
#include "CreatureAI.h"
2009-06-05 14:21:25 -05:00
#include "ZoneScript.h"
2011-07-26 23:09:28 +02:00
#include "SpellMgr.h"
#include "SpellInfo.h"
2009-10-17 15:51:44 -07:00
2011-06-27 15:20:26 +02:00
Vehicle :: Vehicle ( Unit * unit , VehicleEntry const * vehInfo , uint32 creatureEntry ) : _me ( unit ), _vehicleInfo ( vehInfo ), _usableSeatNum ( 0 ), _creatureEntry ( creatureEntry )
2008-12-24 09:58:26 -06:00
{
2010-09-28 08:21:51 +03:00
for ( uint32 i = 0 ; i < MAX_VEHICLE_SEATS ; ++ i )
2009-08-23 22:09:43 -05:00
{
2011-06-27 14:36:00 +02:00
if ( uint32 seatId = _vehicleInfo -> m_seatID [ i ])
2011-05-31 15:14:55 +02:00
if ( VehicleSeatEntry const * veSeat = sVehicleSeatStore . LookupEntry ( seatId ))
2009-08-23 22:09:43 -05:00
{
2011-06-27 14:42:28 +02:00
Seats . insert ( std :: make_pair ( i , VehicleSeat ( veSeat )));
2010-12-30 19:10:46 +01:00
if ( veSeat -> CanEnterOrExit ())
2011-06-27 14:36:00 +02:00
++ _usableSeatNum ;
2009-10-17 16:20:24 -07:00
}
2009-08-23 22:09:43 -05:00
}
2010-08-08 19:45:53 +02:00
2011-02-26 03:47:23 +01:00
InitMovementInfoForBase ();
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
Vehicle ::~ Vehicle ()
{
2011-06-27 14:42:28 +02:00
for ( SeatMap :: const_iterator itr = Seats . begin (); itr != Seats . end (); ++ itr )
ASSERT ( ! itr -> second . Passenger );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2009-08-23 22:09:43 -05:00
void Vehicle :: Install ()
2008-12-24 09:58:26 -06:00
{
2011-06-27 14:36:00 +02:00
if ( Creature * creature = _me -> ToCreature ())
2009-03-28 16:04:37 -06:00
{
2011-06-27 14:36:00 +02:00
switch ( _vehicleInfo -> m_powerType )
2009-06-14 09:57:57 -05:00
{
2010-08-06 15:50:12 +06:00
case POWER_STEAM :
2010-10-12 21:59:11 +03:00
case POWER_HEAT :
2010-08-21 20:50:38 +02:00
case POWER_BLOOD :
2010-08-31 21:47:43 +02:00
case POWER_OOZE :
2010-10-12 21:59:11 +03:00
case POWER_WRATH :
2011-06-27 14:36:00 +02:00
_me -> setPowerType ( POWER_ENERGY );
_me -> SetMaxPower ( POWER_ENERGY , 100 );
2010-08-06 15:50:12 +06:00
break ;
case POWER_PYRITE :
2011-06-27 14:36:00 +02:00
_me -> setPowerType ( POWER_ENERGY );
_me -> SetMaxPower ( POWER_ENERGY , 50 );
2010-08-06 15:50:12 +06:00
break ;
default :
for ( uint32 i = 0 ; i < MAX_SPELL_VEHICLE ; ++ i )
{
2011-05-31 15:14:55 +02:00
if ( ! creature -> m_spells [ i ])
2010-08-06 15:50:12 +06:00
continue ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellInfo const * spellInfo = sSpellMgr -> GetSpellInfo ( creature -> m_spells [ i ]);
2010-08-06 15:50:12 +06:00
if ( ! spellInfo )
continue ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( spellInfo -> PowerType == POWER_ENERGY )
2010-08-06 15:50:12 +06:00
{
2011-06-27 14:36:00 +02:00
_me -> setPowerType ( POWER_ENERGY );
_me -> SetMaxPower ( POWER_ENERGY , 100 );
2010-08-06 15:50:12 +06:00
break ;
}
2009-08-29 23:20:16 -05:00
}
2010-08-06 15:50:12 +06:00
break ;
2009-04-22 17:50:26 -05:00
}
2009-03-28 16:04:37 -06:00
}
2009-10-17 15:51:44 -07:00
2010-08-07 15:26:24 +02:00
if ( GetBase () -> GetTypeId () == TYPEID_UNIT )
2010-12-22 21:25:23 +01:00
sScriptMgr -> OnInstall ( this );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2011-04-22 21:59:37 +02:00
void Vehicle :: InstallAllAccessories ( bool evading )
2009-06-17 01:01:39 -05:00
{
2011-04-22 21:59:37 +02:00
if ( GetBase () -> GetTypeId () == TYPEID_PLAYER || ! evading )
RemoveAllPassengers (); // We might have aura's saved in the DB with now invalid casters - remove
2011-02-27 03:53:24 +01:00
2011-04-22 21:59:37 +02:00
VehicleAccessoryList const * accessories = sObjectMgr -> GetVehicleAccessoryList ( this );
if ( ! accessories )
2010-03-25 04:09:26 +02:00
return ;
2011-04-22 21:59:37 +02:00
for ( VehicleAccessoryList :: const_iterator itr = accessories -> begin (); itr != accessories -> end (); ++ itr )
if ( ! evading || itr -> IsMinion ) // only install minions on evade mode
InstallAccessory ( itr -> AccessoryEntry , itr -> SeatId , itr -> IsMinion , itr -> SummonedType , itr -> SummonTime );
2009-06-17 01:01:39 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-23 22:09:43 -05:00
void Vehicle :: Uninstall ()
2008-12-24 09:58:26 -06:00
{
2011-06-27 14:36:00 +02:00
sLog -> outDebug ( LOG_FILTER_VEHICLES , "Vehicle::Uninstall Entry: %u, GuidLow: %u" , _creatureEntry , _me -> GetGUIDLow ());
2009-08-23 22:09:43 -05:00
RemoveAllPassengers ();
2010-08-06 19:23:43 +02:00
2010-08-07 15:26:24 +02:00
if ( GetBase () -> GetTypeId () == TYPEID_UNIT )
2010-12-22 21:25:23 +01:00
sScriptMgr -> OnUninstall ( this );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2011-04-22 21:59:37 +02:00
void Vehicle :: Reset ( bool evading /*= false*/ )
2008-12-24 09:58:26 -06:00
{
2011-06-27 14:36:00 +02:00
sLog -> outDebug ( LOG_FILTER_VEHICLES , "Vehicle::Reset Entry: %u, GuidLow: %u" , _creatureEntry , _me -> GetGUIDLow ());
if ( _me -> GetTypeId () == TYPEID_PLAYER )
2010-01-13 11:16:38 +01:00
{
2011-06-27 14:36:00 +02:00
if ( _usableSeatNum )
_me -> SetFlag ( UNIT_NPC_FLAGS , UNIT_NPC_FLAG_PLAYER_VEHICLE );
2010-03-12 18:19:50 +01:00
}
else
{
2011-05-31 15:14:55 +02:00
ApplyAllImmunities ();
2011-04-22 21:59:37 +02:00
InstallAllAccessories ( evading );
2011-06-27 14:36:00 +02:00
if ( _usableSeatNum )
_me -> SetFlag ( UNIT_NPC_FLAGS , UNIT_NPC_FLAG_SPELLCLICK );
2010-01-13 11:16:38 +01:00
}
2010-08-06 19:23:43 +02:00
2010-08-07 15:26:24 +02:00
if ( GetBase () -> GetTypeId () == TYPEID_UNIT )
2010-12-22 21:25:23 +01:00
sScriptMgr -> OnReset ( this );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2011-05-31 15:14:55 +02:00
void Vehicle :: ApplyAllImmunities ()
{
2011-07-15 21:37:09 +07:00
// This couldn't be done in DB, because some spells have MECHANIC_NONE
2011-05-31 15:14:55 +02:00
2011-07-15 21:37:09 +07:00
// Vehicles should be immune on Knockback ...
2011-06-27 14:36:00 +02:00
_me -> ApplySpellImmune ( 0 , IMMUNITY_EFFECT , SPELL_EFFECT_KNOCK_BACK , true );
_me -> ApplySpellImmune ( 0 , IMMUNITY_EFFECT , SPELL_EFFECT_KNOCK_BACK_DEST , true );
2011-05-31 15:14:55 +02:00
// Mechanical units & vehicles ( which are not Bosses, they have own immunities in DB ) should be also immune on healing ( exceptions in switch below )
2011-06-27 14:36:00 +02:00
if ( _me -> ToCreature () && _me -> ToCreature () -> GetCreatureInfo () -> type == CREATURE_TYPE_MECHANICAL && ! _me -> ToCreature () -> isWorldBoss ())
2011-05-31 15:14:55 +02:00
{
// Heal & dispel ...
2011-06-27 14:36:00 +02:00
_me -> ApplySpellImmune ( 0 , IMMUNITY_EFFECT , SPELL_EFFECT_HEAL , true );
2011-07-15 20:17:55 +07:00
_me -> ApplySpellImmune ( 0 , IMMUNITY_EFFECT , SPELL_EFFECT_HEAL_PCT , true );
_me -> ApplySpellImmune ( 0 , IMMUNITY_EFFECT , SPELL_EFFECT_DISPEL , true );
2011-06-27 14:36:00 +02:00
_me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_PERIODIC_HEAL , true );
2011-05-31 15:14:55 +02:00
// ... Shield & Immunity grant spells ...
2011-06-27 14:36:00 +02:00
_me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_SCHOOL_IMMUNITY , true );
_me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_MOD_UNATTACKABLE , true );
_me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_SCHOOL_ABSORB , true );
_me -> ApplySpellImmune ( 0 , IMMUNITY_MECHANIC , MECHANIC_SHIELD , true );
2011-09-29 12:43:05 +02:00
_me -> ApplySpellImmune ( 0 , IMMUNITY_MECHANIC , MECHANIC_IMMUNE_SHIELD , true );
2011-05-31 15:14:55 +02:00
2011-07-15 20:17:55 +07:00
// ... Resistance, Split damage, Change stats ...
2011-06-27 14:36:00 +02:00
_me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_DAMAGE_SHIELD , true );
_me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_SPLIT_DAMAGE_PCT , true );
_me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_MOD_RESISTANCE , true );
_me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_MOD_STAT , true );
_me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN , true );
2011-05-31 15:14:55 +02:00
}
// Different immunities for vehicles goes below
switch ( GetVehicleInfo () -> m_ID )
{
2011-11-12 04:04:22 +07:00
// code below prevents a bug with movable cannons
case 160 : // Strand of the Ancients
case 244 : // Wintergrasp
case 510 : // Isle of Conquest
2011-06-27 14:36:00 +02:00
_me -> SetControlled ( true , UNIT_STAT_ROOT );
2011-11-12 04:40:44 +07:00
// why we need to apply this? we can simple add immunities to slow mechanic in DB
2011-06-27 14:36:00 +02:00
_me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_MOD_DECREASE_SPEED , true );
2011-05-31 15:14:55 +02:00
break ;
default :
break ;
}
}
2009-04-21 12:55:26 -05:00
void Vehicle :: RemoveAllPassengers ()
{
2011-06-27 14:36:00 +02:00
sLog -> outDebug ( LOG_FILTER_VEHICLES , "Vehicle::RemoveAllPassengers. Entry: %u, GuidLow: %u" , _creatureEntry , _me -> GetGUIDLow ());
2010-12-31 17:23:51 +01:00
2011-03-04 21:16:27 +01:00
// Passengers always cast an aura with SPELL_AURA_CONTROL_VEHICLE on the vehicle
// We just remove the aura and the unapply handler will make the target leave the vehicle.
2011-08-03 08:18:24 +02:00
// We don't need to iterate over Seats
2011-06-27 14:36:00 +02:00
_me -> RemoveAurasByType ( SPELL_AURA_CONTROL_VEHICLE );
2010-11-21 10:07:51 -08:00
2011-03-04 21:16:27 +01:00
// Following the above logic, this assertion should NEVER fail.
// Even in 'hacky' cases, there should at least be VEHICLE_SPELL_RIDE_HARDCODED on us.
2011-04-22 11:07:58 +02:00
// SeatMap::const_iterator itr;
2011-08-03 08:18:24 +02:00
// for (itr = Seats.begin(); itr != Seats.end(); ++itr)
2011-04-22 11:07:58 +02:00
// ASSERT(!itr->second.passenger);
2009-04-21 12:55:26 -05:00
}
2009-10-17 15:51:44 -07:00
2009-04-25 08:58:16 -05:00
bool Vehicle :: HasEmptySeat ( int8 seatId ) const
2009-04-21 13:36:34 -05:00
{
2011-06-27 14:42:28 +02:00
SeatMap :: const_iterator seat = Seats . find ( seatId );
if ( seat == Seats . end ())
2010-11-21 10:07:51 -08:00
return false ;
2011-06-27 14:42:28 +02:00
return ! seat -> second . Passenger ;
2009-04-21 13:36:34 -05:00
}
2009-10-17 15:51:44 -07:00
2011-05-31 15:14:55 +02:00
Unit * Vehicle :: GetPassenger ( int8 seatId ) const
2009-06-14 09:57:57 -05:00
{
2011-06-27 14:42:28 +02:00
SeatMap :: const_iterator seat = Seats . find ( seatId );
if ( seat == Seats . end ())
2010-11-21 10:07:51 -08:00
return NULL ;
2010-12-31 17:23:51 +01:00
2011-06-27 14:42:28 +02:00
return ObjectAccessor :: GetUnit ( * GetBase (), seat -> second . Passenger );
2009-06-14 09:57:57 -05:00
}
2009-10-17 15:51:44 -07:00
2011-02-19 21:58:50 +01:00
int8 Vehicle :: GetNextEmptySeat ( int8 seatId , bool next ) const
2009-04-23 00:12:29 -05:00
{
2011-06-27 14:42:28 +02:00
SeatMap :: const_iterator seat = Seats . find ( seatId );
if ( seat == Seats . end ())
2010-12-27 16:55:17 +01:00
return - 1 ;
2011-06-27 14:42:28 +02:00
while ( seat -> second . Passenger || ( ! seat -> second . SeatInfo -> CanEnterOrExit () && ! seat -> second . SeatInfo -> IsUsableByOverride ()))
2009-04-23 00:12:29 -05:00
{
2010-04-07 19:14:10 +02:00
if ( next )
2009-04-23 00:12:29 -05:00
{
++ seat ;
2011-06-27 14:42:28 +02:00
if ( seat == Seats . end ())
seat = Seats . begin ();
2009-04-23 00:12:29 -05:00
}
else
{
2011-06-27 14:42:28 +02:00
if ( seat == Seats . begin ())
seat = Seats . end ();
2009-04-23 00:12:29 -05:00
-- seat ;
}
2010-11-21 10:07:51 -08:00
2010-04-07 19:14:10 +02:00
if ( seat -> first == seatId )
2009-05-23 20:40:14 -05:00
return - 1 ; // no available seat
2009-04-23 00:12:29 -05:00
}
2010-12-27 16:55:17 +01:00
2009-04-23 00:12:29 -05:00
return seat -> first ;
}
2009-10-17 15:51:44 -07:00
2011-02-22 23:47:28 +01:00
void Vehicle :: InstallAccessory ( uint32 entry , int8 seatId , bool minion , uint8 type , uint32 summonTime )
2009-04-21 13:49:39 -05:00
{
2011-03-07 19:05:18 +01:00
sLog -> outDebug ( LOG_FILTER_VEHICLES , "Vehicle: Installing accessory entry %u on vehicle entry %u (seat:%i)" , entry , GetCreatureEntry (), seatId );
2011-04-22 21:59:37 +02:00
if ( Unit * passenger = GetPassenger ( seatId ))
2009-06-17 01:01:39 -05:00
{
// already installed
2010-04-07 19:14:10 +02:00
if ( passenger -> GetEntry () == entry )
2009-08-22 21:25:35 -05:00
{
2010-07-30 20:04:28 +02:00
ASSERT ( passenger -> GetTypeId () == TYPEID_UNIT );
2011-06-27 14:36:00 +02:00
if ( _me -> GetTypeId () == TYPEID_UNIT )
2011-02-25 01:38:21 +01:00
{
2011-06-27 14:36:00 +02:00
if ( _me -> ToCreature () -> IsInEvadeMode () && passenger -> ToCreature () -> IsAIEnabled )
2011-02-25 01:38:21 +01:00
passenger -> ToCreature () -> AI () -> EnterEvadeMode ();
2011-03-04 21:16:27 +01:00
return ;
2011-02-25 01:38:21 +01:00
}
2009-08-22 21:25:35 -05:00
}
2011-02-25 01:38:21 +01:00
else
passenger -> ExitVehicle (); // this should not happen
2009-06-17 01:01:39 -05:00
}
2009-10-17 15:51:44 -07:00
2011-06-27 14:36:00 +02:00
if ( TempSummon * accessory = _me -> SummonCreature ( entry , * _me , TempSummonType ( type ), summonTime ))
2009-08-28 11:26:20 -05:00
{
2010-04-07 19:14:10 +02:00
if ( minion )
2009-08-28 11:26:20 -05:00
accessory -> AddUnitTypeMask ( UNIT_MASK_ACCESSORY );
2010-11-21 10:07:51 -08:00
2011-06-27 14:36:00 +02:00
if ( ! _me -> HandleSpellClick ( accessory , seatId ))
2011-02-26 23:00:09 +01:00
{
2011-04-22 21:59:37 +02:00
accessory -> UnSummon ();
2011-03-04 21:16:27 +01:00
return ;
}
2011-04-22 21:59:37 +02:00
// this cannot be checked instantly like this
// spellsystem is delaying everything to next update tick
//if (!accessory->IsOnVehicle(me))
//{
// accessory->UnSummon();
// return; // Something went wrong in the spellsystem
//}
2011-02-26 23:00:09 +01:00
2009-08-28 11:26:20 -05:00
// This is not good, we have to send update twice
accessory -> SendMovementFlagUpdate ();
2010-08-06 19:23:43 +02:00
2010-08-07 15:26:24 +02:00
if ( GetBase () -> GetTypeId () == TYPEID_UNIT )
2010-12-22 21:25:23 +01:00
sScriptMgr -> OnInstallAccessory ( this , accessory );
2009-08-28 11:26:20 -05:00
}
2009-04-21 13:49:39 -05:00
}
2009-10-17 15:51:44 -07:00
2011-05-31 15:14:55 +02:00
bool Vehicle :: AddPassenger ( Unit * unit , int8 seatId )
2009-04-17 15:08:58 -05:00
{
2010-04-07 19:14:10 +02:00
if ( unit -> GetVehicle () != this )
2009-04-21 12:55:26 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2009-04-21 12:55:26 -05:00
SeatMap :: iterator seat ;
2010-04-07 19:14:10 +02:00
if ( seatId < 0 ) // no specific seat requirement
2009-04-17 15:08:58 -05:00
{
2011-06-27 14:42:28 +02:00
for ( seat = Seats . begin (); seat != Seats . end (); ++ seat )
if ( ! seat -> second . Passenger && ( seat -> second . SeatInfo -> CanEnterOrExit () || seat -> second . SeatInfo -> IsUsableByOverride ()))
2009-04-21 12:55:26 -05:00
break ;
2009-10-17 15:51:44 -07:00
2011-06-27 14:42:28 +02:00
if ( seat == Seats . end ()) // no available seat
2009-04-21 12:55:26 -05:00
return false ;
2009-04-17 15:08:58 -05:00
}
2009-04-21 12:55:26 -05:00
else
{
2011-06-27 14:42:28 +02:00
seat = Seats . find ( seatId );
if ( seat == Seats . end ())
2009-04-21 12:55:26 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2011-06-27 14:42:28 +02:00
if ( seat -> second . Passenger )
2011-01-11 11:18:00 +01:00
{
2011-06-27 14:42:28 +02:00
if ( Unit * passenger = ObjectAccessor :: GetUnit ( * GetBase (), seat -> second . Passenger ))
2010-12-31 17:23:51 +01:00
passenger -> ExitVehicle ();
else
2011-06-27 14:42:28 +02:00
seat -> second . Passenger = 0 ;
2011-01-11 11:18:00 +01:00
}
2009-10-17 15:51:44 -07:00
2011-06-27 14:42:28 +02:00
ASSERT ( ! seat -> second . Passenger );
2009-04-21 12:55:26 -05:00
}
2009-10-17 15:51:44 -07:00
2011-06-27 14:36:00 +02:00
sLog -> outDebug ( LOG_FILTER_VEHICLES , "Unit %s enter vehicle entry %u id %u dbguid %u seat %d" , unit -> GetName (), _me -> GetEntry (), _vehicleInfo -> m_ID , _me -> GetGUIDLow (), ( int32 ) seat -> first );
2009-10-17 15:51:44 -07:00
2011-06-27 14:42:28 +02:00
seat -> second . Passenger = unit -> GetGUID ();
if ( seat -> second . SeatInfo -> CanEnterOrExit ())
2009-05-23 20:40:14 -05:00
{
2011-06-27 14:36:00 +02:00
ASSERT ( _usableSeatNum );
-- _usableSeatNum ;
if ( ! _usableSeatNum )
2010-01-13 11:16:38 +01:00
{
2011-06-27 14:36:00 +02:00
if ( _me -> GetTypeId () == TYPEID_PLAYER )
_me -> RemoveFlag ( UNIT_NPC_FLAGS , UNIT_NPC_FLAG_PLAYER_VEHICLE );
2010-01-13 11:16:38 +01:00
else
2011-06-27 14:36:00 +02:00
_me -> RemoveFlag ( UNIT_NPC_FLAGS , UNIT_NPC_FLAG_SPELLCLICK );
2010-01-13 11:16:38 +01:00
}
2009-05-23 20:40:14 -05:00
}
2009-10-17 15:51:44 -07:00
2011-12-11 15:28:33 +01:00
if ( seat -> second . SeatInfo -> m_flags && ! ( seat -> second . SeatInfo -> m_flags & VEHICLE_SEAT_FLAG_UNK1 ))
2010-12-17 13:43:24 +01:00
unit -> AddUnitState ( UNIT_STAT_ONVEHICLE );
2009-10-17 15:51:44 -07:00
2011-02-23 02:21:08 +01:00
unit -> AddUnitMovementFlag ( MOVEMENTFLAG_ONTRANSPORT );
2011-06-27 14:42:28 +02:00
VehicleSeatEntry const * veSeat = seat -> second . SeatInfo ;
2010-08-04 14:39:45 +02:00
unit -> m_movementInfo . t_pos . m_positionX = veSeat -> m_attachmentOffsetX ;
unit -> m_movementInfo . t_pos . m_positionY = veSeat -> m_attachmentOffsetY ;
unit -> m_movementInfo . t_pos . m_positionZ = veSeat -> m_attachmentOffsetZ ;
unit -> m_movementInfo . t_pos . m_orientation = 0 ;
2009-06-13 09:18:54 -05:00
unit -> m_movementInfo . t_time = 0 ; // 1 for player
2009-04-17 15:08:58 -05:00
unit -> m_movementInfo . t_seat = seat -> first ;
2009-10-17 15:51:44 -07:00
2011-06-27 14:36:00 +02:00
if ( _me -> GetTypeId () == TYPEID_UNIT
2010-02-02 23:25:46 -03:00
&& unit -> GetTypeId () == TYPEID_PLAYER
2011-06-27 14:42:28 +02:00
&& seat -> first == 0 && seat -> second . SeatInfo -> m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL )
2010-08-24 15:04:34 -07:00
{
2011-06-27 14:36:00 +02:00
if ( ! _me -> SetCharmedBy ( unit , CHARM_TYPE_VEHICLE ))
2010-07-30 20:04:28 +02:00
ASSERT ( false );
2010-08-24 15:04:34 -07:00
}
2011-06-27 14:36:00 +02:00
if ( _me -> IsInWorld ())
2009-08-08 11:57:51 -05:00
{
2011-02-26 03:47:23 +01:00
unit -> SendClearTarget (); // SMSG_BREAK_TARGET
unit -> SetControlled ( true , UNIT_STAT_ROOT ); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures)
// also adds MOVEMENTFLAG_ROOT
2011-06-27 14:36:00 +02:00
unit -> SendMonsterMoveTransport ( _me ); // SMSG_MONSTER_MOVE_TRANSPORT
2010-01-13 11:16:38 +01:00
2011-06-27 14:36:00 +02:00
if ( _me -> GetTypeId () == TYPEID_UNIT )
2009-08-23 22:09:43 -05:00
{
2011-06-27 14:36:00 +02:00
if ( _me -> ToCreature () -> IsAIEnabled )
_me -> ToCreature () -> AI () -> PassengerBoarded ( unit , seat -> first , true );
2010-01-13 11:16:38 +01:00
2010-01-18 21:51:45 +02:00
// update all passenger's positions
2011-06-27 14:36:00 +02:00
RelocatePassengers ( _me -> GetPositionX (), _me -> GetPositionY (), _me -> GetPositionZ (), _me -> GetOrientation ());
2009-08-23 22:09:43 -05:00
}
}
2009-10-17 15:51:44 -07:00
2010-08-07 15:26:24 +02:00
if ( GetBase () -> GetTypeId () == TYPEID_UNIT )
2010-12-22 21:25:23 +01:00
sScriptMgr -> OnAddPassenger ( this , unit , seatId );
2009-10-17 15:51:44 -07:00
2009-04-21 12:55:26 -05:00
return true ;
2009-04-17 15:08:58 -05:00
}
2009-10-17 15:51:44 -07:00
2011-05-31 15:14:55 +02:00
void Vehicle :: RemovePassenger ( Unit * unit )
2009-04-17 15:08:58 -05:00
{
2010-04-07 19:14:10 +02:00
if ( unit -> GetVehicle () != this )
2009-04-21 12:55:26 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-12-31 17:23:51 +01:00
SeatMap :: iterator seat = GetSeatIteratorForPassenger ( unit );
2011-06-27 14:42:28 +02:00
ASSERT ( seat != Seats . end ());
2009-10-17 15:51:44 -07:00
2011-06-27 14:36:00 +02:00
sLog -> outDebug ( LOG_FILTER_VEHICLES , "Unit %s exit vehicle entry %u id %u dbguid %u seat %d" , unit -> GetName (), _me -> GetEntry (), _vehicleInfo -> m_ID , _me -> GetGUIDLow (), ( int32 ) seat -> first );
2009-10-17 15:51:44 -07:00
2011-06-27 14:42:28 +02:00
seat -> second . Passenger = 0 ;
if ( seat -> second . SeatInfo -> CanEnterOrExit ())
2009-08-08 11:57:51 -05:00
{
2011-06-27 14:36:00 +02:00
if ( ! _usableSeatNum )
2010-01-13 11:16:38 +01:00
{
2011-06-27 14:36:00 +02:00
if ( _me -> GetTypeId () == TYPEID_PLAYER )
_me -> SetFlag ( UNIT_NPC_FLAGS , UNIT_NPC_FLAG_PLAYER_VEHICLE );
2010-01-13 11:16:38 +01:00
else
2011-06-27 14:36:00 +02:00
_me -> SetFlag ( UNIT_NPC_FLAGS , UNIT_NPC_FLAG_SPELLCLICK );
2010-01-13 11:16:38 +01:00
}
2011-06-27 14:36:00 +02:00
++ _usableSeatNum ;
2009-08-08 11:57:51 -05:00
}
2009-10-17 15:51:44 -07:00
2010-12-17 13:43:24 +01:00
unit -> ClearUnitState ( UNIT_STAT_ONVEHICLE );
2009-10-17 15:51:44 -07:00
2011-06-27 14:42:28 +02:00
if ( _me -> GetTypeId () == TYPEID_UNIT && unit -> GetTypeId () == TYPEID_PLAYER && seat -> first == 0 && seat -> second . SeatInfo -> m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL )
2011-06-27 14:36:00 +02:00
_me -> RemoveCharmedBy ( unit );
2010-08-24 15:04:34 -07:00
2011-06-27 14:36:00 +02:00
if ( _me -> IsInWorld ())
2011-02-23 02:15:48 +01:00
{
2011-02-23 04:08:11 +01:00
unit -> RemoveUnitMovementFlag ( MOVEMENTFLAG_ONTRANSPORT );
unit -> m_movementInfo . t_pos . Relocate ( 0 , 0 , 0 , 0 );
unit -> m_movementInfo . t_time = 0 ;
unit -> m_movementInfo . t_seat = 0 ;
2011-02-23 02:15:48 +01:00
}
2011-06-27 14:36:00 +02:00
if ( _me -> GetTypeId () == TYPEID_UNIT && _me -> ToCreature () -> IsAIEnabled )
_me -> ToCreature () -> AI () -> PassengerBoarded ( unit , seat -> first , false );
2009-10-17 15:51:44 -07:00
2010-05-03 13:01:20 +02:00
// only for flyable vehicles
if ( unit -> HasUnitMovementFlag ( MOVEMENTFLAG_FLYING ))
2011-06-27 14:36:00 +02:00
_me -> CastSpell ( unit , VEHICLE_SPELL_PARACHUTE , true );
2010-08-06 19:23:43 +02:00
2010-08-07 15:26:24 +02:00
if ( GetBase () -> GetTypeId () == TYPEID_UNIT )
2010-12-22 21:25:23 +01:00
sScriptMgr -> OnRemovePassenger ( this , unit );
2009-04-17 15:08:58 -05:00
}
2009-10-17 15:51:44 -07:00
2010-01-16 11:43:47 +02:00
void Vehicle :: RelocatePassengers ( float x , float y , float z , float ang )
{
2011-06-27 14:36:00 +02:00
Map * map = _me -> GetMap ();
2010-07-30 20:04:28 +02:00
ASSERT ( map != NULL );
2010-01-16 11:43:47 +02:00
// not sure that absolute position calculation is correct, it must depend on vehicle orientation and pitch angle
2011-06-27 14:42:28 +02:00
for ( SeatMap :: const_iterator itr = Seats . begin (); itr != Seats . end (); ++ itr )
if ( Unit * passenger = ObjectAccessor :: GetUnit ( * GetBase (), itr -> second . Passenger ))
2010-01-16 11:43:47 +02:00
{
2010-12-31 01:40:31 +01:00
ASSERT ( passenger -> IsInWorld ());
2010-12-31 17:23:51 +01:00
ASSERT ( passenger -> IsOnVehicle ( GetBase ()));
ASSERT ( GetSeatForPassenger ( passenger ));
2010-12-31 01:40:31 +01:00
2010-08-04 14:39:45 +02:00
float px = x + passenger -> m_movementInfo . t_pos . m_positionX ;
float py = y + passenger -> m_movementInfo . t_pos . m_positionY ;
float pz = z + passenger -> m_movementInfo . t_pos . m_positionZ ;
float po = ang + passenger -> m_movementInfo . t_pos . m_orientation ;
2010-01-18 21:51:45 +02:00
2011-10-10 17:08:01 -04:00
passenger -> UpdatePosition ( px , py , pz , po );
2010-01-16 11:43:47 +02:00
}
}
2008-12-24 09:58:26 -06:00
void Vehicle :: Dismiss ()
{
2011-06-27 14:36:00 +02:00
sLog -> outDebug ( LOG_FILTER_VEHICLES , "Vehicle::Dismiss Entry: %u, GuidLow %u" , _creatureEntry , _me -> GetGUIDLow ());
2009-08-28 11:26:20 -05:00
Uninstall ();
2011-06-27 14:36:00 +02:00
_me -> DestroyForNearbyPlayers ();
_me -> CombatStop ();
_me -> AddObjectToRemoveList ();
2009-03-28 22:44:09 -06:00
}
2010-12-29 05:45:38 +01:00
2011-02-26 03:47:23 +01:00
void Vehicle :: InitMovementInfoForBase ()
2010-12-29 05:45:38 +01:00
{
uint32 vehicleFlags = GetVehicleInfo () -> m_flags ;
if ( vehicleFlags & VEHICLE_FLAG_NO_STRAFE )
2011-06-27 14:36:00 +02:00
_me -> AddExtraUnitMovementFlag ( MOVEMENTFLAG2_NO_STRAFE );
2010-12-29 05:45:38 +01:00
if ( vehicleFlags & VEHICLE_FLAG_NO_JUMPING )
2011-06-27 14:36:00 +02:00
_me -> AddExtraUnitMovementFlag ( MOVEMENTFLAG2_NO_JUMPING );
2010-12-29 05:45:38 +01:00
if ( vehicleFlags & VEHICLE_FLAG_FULLSPEEDTURNING )
2011-06-27 14:36:00 +02:00
_me -> AddExtraUnitMovementFlag ( MOVEMENTFLAG2_FULL_SPEED_TURNING );
2010-12-29 05:45:38 +01:00
if ( vehicleFlags & VEHICLE_FLAG_ALLOW_PITCHING )
2011-06-27 14:36:00 +02:00
_me -> AddExtraUnitMovementFlag ( MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING );
2010-12-29 05:45:38 +01:00
if ( vehicleFlags & VEHICLE_FLAG_FULLSPEEDPITCHING )
2011-06-27 14:36:00 +02:00
_me -> AddExtraUnitMovementFlag ( MOVEMENTFLAG2_FULL_SPEED_PITCHING );
2010-12-30 19:10:46 +01:00
}
VehicleSeatEntry const * Vehicle :: GetSeatForPassenger ( Unit * passenger )
{
SeatMap :: iterator itr ;
2011-06-27 14:42:28 +02:00
for ( itr = Seats . begin (); itr != Seats . end (); ++ itr )
if ( itr -> second . Passenger == passenger -> GetGUID ())
return itr -> second . SeatInfo ;
2010-12-30 19:10:46 +01:00
return NULL ;
2010-12-31 17:23:51 +01:00
}
SeatMap :: iterator Vehicle :: GetSeatIteratorForPassenger ( Unit * passenger )
{
SeatMap :: iterator itr ;
2011-06-27 14:42:28 +02:00
for ( itr = Seats . begin (); itr != Seats . end (); ++ itr )
if ( itr -> second . Passenger == passenger -> GetGUID ())
2010-12-31 17:23:51 +01:00
return itr ;
2011-06-27 14:42:28 +02:00
return Seats . end ();
2011-01-11 11:18:00 +01:00
}
2011-02-27 03:53:24 +01:00
uint8 Vehicle :: GetAvailableSeatCount () const
{
uint8 ret = 0 ;
SeatMap :: const_iterator itr ;
2011-06-27 14:42:28 +02:00
for ( itr = Seats . begin (); itr != Seats . end (); ++ itr )
if ( ! itr -> second . Passenger && ( itr -> second . SeatInfo -> CanEnterOrExit () || itr -> second . SeatInfo -> IsUsableByOverride ()))
2011-02-27 03:53:24 +01:00
++ ret ;
return ret ;
2011-05-31 15:14:55 +02:00
}