2010-10-07 15:35:36 +02:00
/*
* Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
* 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"
2009-10-17 15:51:44 -07:00
2010-08-24 15:04:34 -07:00
Vehicle :: Vehicle ( Unit * unit , VehicleEntry const * vehInfo ) : me ( unit ), m_vehicleInfo ( vehInfo ), m_usableSeatNum ( 0 ), m_bonusHP ( 0 )
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
{
2010-04-07 19:14:10 +02:00
if ( uint32 seatId = m_vehicleInfo -> m_seatID [ i ])
if ( VehicleSeatEntry const * veSeat = sVehicleSeatStore . LookupEntry ( seatId ))
2009-08-23 22:09:43 -05:00
{
m_Seats . insert ( std :: make_pair ( i , VehicleSeat ( veSeat )));
2010-12-27 16:55:17 +01:00
if ( veSeat -> IsUsableByPlayer ())
2009-08-23 22:09:43 -05:00
++ m_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
2010-06-28 22:23:57 +02:00
// HACKY WAY, We must found a more generic way to handle this
// Set inmunities since db ones are rewritten with player's ones
2010-06-28 20:56:29 +02:00
switch ( GetVehicleInfo () -> m_ID )
{
case 160 :
me -> SetControlled ( true , UNIT_STAT_ROOT );
me -> ApplySpellImmune ( 0 , IMMUNITY_EFFECT , SPELL_EFFECT_KNOCK_BACK , true );
2010-07-20 04:29:17 +02:00
me -> ApplySpellImmune ( 0 , IMMUNITY_EFFECT , SPELL_EFFECT_KNOCK_BACK_DEST , true );
2010-06-28 22:23:57 +02:00
case 158 :
2010-06-28 20:56:29 +02:00
me -> ApplySpellImmune ( 0 , IMMUNITY_EFFECT , SPELL_EFFECT_HEAL , true );
me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_MOD_FEAR , true );
me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_PERIODIC_HEAL , true );
me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_MOD_STUN , true );
me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_MOD_ROOT , true );
me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_MOD_DECREASE_SPEED , true );
me -> ApplySpellImmune ( 0 , IMMUNITY_STATE , SPELL_AURA_MOD_CONFUSE , true );
me -> ApplySpellImmune ( 0 , IMMUNITY_ID , 49560 , true ); // Death Grip jump effect
break ;
default :
break ;
}
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 ()
{
2009-10-17 16:20:24 -07:00
for ( SeatMap :: const_iterator itr = m_Seats . begin (); itr != m_Seats . end (); ++ itr )
2010-07-30 20:04:28 +02:00
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
{
2010-08-06 15:50:12 +06:00
if ( Creature * pCreature = me -> ToCreature ())
2009-03-28 16:04:37 -06:00
{
2010-08-06 15:50:12 +06:00
switch ( m_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 :
2010-08-06 15:50:12 +06:00
me -> setPowerType ( POWER_ENERGY );
me -> SetMaxPower ( POWER_ENERGY , 100 );
break ;
case POWER_PYRITE :
me -> setPowerType ( POWER_ENERGY );
me -> SetMaxPower ( POWER_ENERGY , 50 );
break ;
default :
for ( uint32 i = 0 ; i < MAX_SPELL_VEHICLE ; ++ i )
{
if ( ! pCreature -> m_spells [ i ])
continue ;
2009-10-17 15:51:44 -07:00
2010-08-06 15:50:12 +06:00
SpellEntry const * spellInfo = sSpellStore . LookupEntry ( pCreature -> m_spells [ i ]);
if ( ! spellInfo )
continue ;
2009-10-17 15:51:44 -07:00
2010-08-06 15:50:12 +06:00
if ( spellInfo -> powerType == POWER_MANA )
break ;
2009-10-17 15:51:44 -07:00
2010-08-06 15:50:12 +06:00
if ( spellInfo -> powerType == POWER_ENERGY )
{
me -> setPowerType ( POWER_ENERGY );
me -> SetMaxPower ( POWER_ENERGY , 100 );
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
2009-08-23 22:09:43 -05:00
Reset ();
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 -> OnInstall ( this );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2010-09-14 16:14:43 +02:00
void Vehicle :: InstallAllAccessories ( uint32 entry )
2009-06-17 01:01:39 -05:00
{
2010-12-22 21:25:23 +01:00
VehicleAccessoryList const * mVehicleList = sObjectMgr -> GetVehicleAccessoryList ( entry );
2010-03-25 04:09:26 +02:00
if ( ! mVehicleList )
return ;
for ( VehicleAccessoryList :: const_iterator itr = mVehicleList -> begin (); itr != mVehicleList -> end (); ++ itr )
InstallAccessory ( itr -> uiAccessory , itr -> uiSeat , itr -> bMinion );
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
{
2010-12-23 23:25:44 +01:00
sLog -> outDebug ( "Vehicle::Uninstall %u" , me -> GetEntry ());
2009-10-17 16:20:24 -07:00
for ( SeatMap :: iterator itr = m_Seats . begin (); itr != m_Seats . end (); ++ itr )
2010-04-07 19:14:10 +02:00
if ( Unit * passenger = itr -> second . passenger )
if ( passenger -> HasUnitTypeMask ( UNIT_MASK_ACCESSORY ))
2010-03-27 16:08:14 +01:00
passenger -> ToTempSummon () -> UnSummon ();
2010-08-06 19:23:43 +02:00
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
2009-08-23 22:09:43 -05:00
void Vehicle :: Die ()
2008-12-24 09:58:26 -06:00
{
2010-12-23 23:25:44 +01:00
sLog -> outDebug ( "Vehicle::Die %u" , me -> GetEntry ());
2009-10-17 16:20:24 -07:00
for ( SeatMap :: iterator itr = m_Seats . begin (); itr != m_Seats . end (); ++ itr )
2010-04-07 19:14:10 +02:00
if ( Unit * passenger = itr -> second . passenger )
if ( passenger -> HasUnitTypeMask ( UNIT_MASK_ACCESSORY ))
2009-08-23 22:09:43 -05:00
passenger -> setDeathState ( JUST_DIED );
2010-08-06 19:23:43 +02:00
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 -> OnDie ( this );
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 :: Reset ()
2008-12-24 09:58:26 -06:00
{
2010-12-23 23:25:44 +01:00
sLog -> outDebug ( "Vehicle::Reset" );
2010-03-12 18:19:50 +01:00
if ( me -> GetTypeId () == TYPEID_PLAYER )
2010-01-13 11:16:38 +01:00
{
2010-03-12 18:19:50 +01:00
if ( m_usableSeatNum )
2010-01-13 11:16:38 +01:00
me -> SetFlag ( UNIT_NPC_FLAGS , UNIT_NPC_FLAG_PLAYER_VEHICLE );
2010-03-12 18:19:50 +01:00
}
else
{
2010-09-14 16:14:43 +02:00
InstallAllAccessories ( me -> GetEntry ());
2010-03-12 18:19:50 +01:00
if ( m_usableSeatNum )
2010-01-13 11:16:38 +01:00
me -> SetFlag ( UNIT_NPC_FLAGS , UNIT_NPC_FLAG_SPELLCLICK );
}
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
2009-04-21 12:55:26 -05:00
void Vehicle :: RemoveAllPassengers ()
{
2010-12-23 23:25:44 +01:00
sLog -> outDebug ( "Vehicle::RemoveAllPassengers" );
2009-10-17 16:20:24 -07:00
for ( SeatMap :: iterator itr = m_Seats . begin (); itr != m_Seats . end (); ++ itr )
2010-04-07 19:14:10 +02:00
if ( Unit * passenger = itr -> second . passenger )
2009-04-21 12:55:26 -05:00
{
2010-04-07 19:14:10 +02:00
if ( passenger -> IsVehicle ())
2009-08-23 22:09:43 -05:00
passenger -> GetVehicleKit () -> RemoveAllPassengers ();
2010-04-07 19:14:10 +02:00
if ( passenger -> GetVehicle () != this )
2010-12-23 23:25:44 +01:00
sLog -> outCrash ( "Vehicle %u has invalid passenger %u." , me -> GetEntry (), passenger -> GetEntry ());
2009-04-21 13:36:34 -05:00
passenger -> ExitVehicle ();
2010-04-07 19:14:10 +02:00
if ( itr -> second . passenger )
2009-06-19 11:19:23 -05:00
{
2010-12-23 23:25:44 +01:00
sLog -> outCrash ( "Vehicle %u cannot remove passenger %u. %u is still on vehicle." , me -> GetEntry (), passenger -> GetEntry (), itr -> second . passenger -> GetEntry ());
2009-06-19 17:04:45 -05:00
itr -> second . passenger = NULL ;
2009-06-19 11:19:23 -05:00
}
2010-11-21 10:07:51 -08:00
2010-08-24 07:19:29 +03:00
// creature passengers mounted on player mounts should be despawned at dismount
2010-08-24 22:47:41 +03:00
if ( GetBase () -> GetTypeId () == TYPEID_PLAYER && passenger -> ToCreature ())
2010-08-24 07:19:29 +03:00
passenger -> ToCreature () -> ForcedDespawn ();
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
{
2009-04-25 08:58:16 -05:00
SeatMap :: const_iterator seat = m_Seats . find ( seatId );
2010-11-21 10:07:51 -08:00
if ( seat == m_Seats . end ())
return false ;
2009-04-22 17:50:26 -05:00
return ! seat -> second . passenger ;
2009-04-21 13:36:34 -05:00
}
2009-10-17 15:51:44 -07:00
2009-06-14 09:57:57 -05:00
Unit * Vehicle :: GetPassenger ( int8 seatId ) const
{
SeatMap :: const_iterator seat = m_Seats . find ( seatId );
2010-11-21 10:07:51 -08:00
if ( seat == m_Seats . end ())
return NULL ;
2009-06-14 09:57:57 -05:00
return seat -> second . passenger ;
}
2009-10-17 15:51:44 -07:00
2010-12-27 16:55:17 +01:00
int8 Vehicle :: GetNextEmptySeat ( int8 seatId , bool next , bool byAura ) const
2009-04-23 00:12:29 -05:00
{
2009-04-25 08:58:16 -05:00
SeatMap :: const_iterator seat = m_Seats . find ( seatId );
2010-12-27 16:55:17 +01:00
if ( seat == m_Seats . end ())
return - 1 ;
while ( seat -> second . passenger || ( ! byAura && ! seat -> second . seatInfo -> IsUsableByPlayer ()) || ( byAura && ! seat -> second . seatInfo -> IsUsableByAura ()))
2009-04-23 00:12:29 -05:00
{
2010-12-27 16:55:17 +01:00
sLog -> outDebug ( "Vehicle::GetNextEmptySeat: m_flags: %u, m_flagsB:%u" , seat -> second . seatInfo -> m_flags , seat -> second . seatInfo -> m_flagsB );
2010-04-07 19:14:10 +02:00
if ( next )
2009-04-23 00:12:29 -05:00
{
++ seat ;
2010-04-07 19:14:10 +02:00
if ( seat == m_Seats . end ())
2009-04-23 00:12:29 -05:00
seat = m_Seats . begin ();
}
else
{
2010-04-07 19:14:10 +02:00
if ( seat == m_Seats . begin ())
2009-04-23 00:12:29 -05:00
seat = m_Seats . end ();
-- 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
2009-08-28 11:26:20 -05:00
void Vehicle :: InstallAccessory ( uint32 entry , int8 seatId , bool minion )
2009-04-21 13:49:39 -05:00
{
2010-04-07 19:14:10 +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 );
2010-04-07 19:14:10 +02:00
if ( me -> GetTypeId () == TYPEID_UNIT && me -> ToCreature () -> IsInEvadeMode () && passenger -> ToCreature () -> IsAIEnabled )
2010-03-07 18:30:53 +01:00
passenger -> ToCreature () -> AI () -> EnterEvadeMode ();
2009-06-17 01:01:39 -05:00
return ;
2009-08-22 21:25:35 -05:00
}
2009-06-17 01:01:39 -05:00
passenger -> ExitVehicle (); // this should not happen
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( Creature * accessory = me -> SummonCreature ( entry , * me , TEMPSUMMON_CORPSE_TIMED_DESPAWN , 30000 ))
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
2009-08-28 11:26:20 -05:00
accessory -> EnterVehicle ( this , seatId );
// 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
2010-12-27 16:55:17 +01:00
bool Vehicle :: AddPassenger ( Unit * unit , int8 seatId , bool byAura )
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
{
2009-10-17 16:20:24 -07:00
for ( seat = m_Seats . begin (); seat != m_Seats . end (); ++ seat )
2010-12-27 22:58:22 +01:00
if ( ! seat -> second . passenger && (( ! ( byAura && seat -> second . seatInfo -> IsUsableByPlayer ()) || ( byAura && seat -> second . seatInfo -> IsUsableByAura ()))))
2009-04-21 12:55:26 -05:00
break ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( seat == m_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
{
2009-04-25 08:58:16 -05:00
seat = m_Seats . find ( seatId );
2010-04-07 19:14:10 +02:00
if ( seat == m_Seats . end ())
2009-04-21 12:55:26 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( seat -> second . passenger )
2009-04-21 12:55:26 -05:00
seat -> second . passenger -> ExitVehicle ();
2009-10-17 15:51:44 -07:00
2010-07-30 20:04:28 +02:00
ASSERT ( ! seat -> second . passenger );
2009-04-21 12:55:26 -05:00
}
2009-10-17 15:51:44 -07:00
2010-12-23 23:25:44 +01:00
sLog -> outDebug ( "Unit %s enter vehicle entry %u id %u dbguid %u seat %d" , unit -> GetName (), me -> GetEntry (), m_vehicleInfo -> m_ID , me -> GetGUIDLow (), ( int32 ) seat -> first );
2009-10-17 15:51:44 -07:00
2009-04-21 12:55:26 -05:00
seat -> second . passenger = unit ;
2010-12-27 16:55:17 +01:00
if ( seat -> second . seatInfo -> IsUsableByPlayer ())
2009-05-23 20:40:14 -05:00
{
2010-07-30 20:04:28 +02:00
ASSERT ( m_usableSeatNum );
2009-05-23 20:40:14 -05:00
-- m_usableSeatNum ;
2010-04-07 19:14:10 +02:00
if ( ! m_usableSeatNum )
2010-01-13 11:16:38 +01:00
{
if ( me -> GetTypeId () == TYPEID_PLAYER )
me -> RemoveFlag ( UNIT_NPC_FLAGS , UNIT_NPC_FLAG_PLAYER_VEHICLE );
else
me -> RemoveFlag ( UNIT_NPC_FLAGS , UNIT_NPC_FLAG_SPELLCLICK );
}
2009-05-23 20:40:14 -05:00
}
2009-10-17 15:51:44 -07:00
2010-09-28 08:21:51 +03:00
if ( seat -> second . seatInfo -> m_flags && ! ( seat -> second . seatInfo -> m_flags & VEHICLE_SEAT_FLAG_UNK11 ))
2010-12-17 13:43:24 +01:00
unit -> AddUnitState ( UNIT_STAT_ONVEHICLE );
2009-10-17 15:51:44 -07:00
2010-12-29 05:45:38 +01:00
unit -> AddUnitMovementFlag ( MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_ROOT );
2009-04-17 15:08:58 -05: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
2010-04-07 19:14:10 +02:00
if ( me -> GetTypeId () == TYPEID_UNIT
2010-02-02 23:25:46 -03:00
&& unit -> GetTypeId () == TYPEID_PLAYER
2010-09-28 08:21:51 +03:00
&& seat -> first == 0 && seat -> second . seatInfo -> m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL )
2010-08-24 15:04:34 -07:00
{
2009-08-23 22:09:43 -05:00
if ( ! me -> SetCharmedBy ( unit , CHARM_TYPE_VEHICLE ))
2010-07-30 20:04:28 +02:00
ASSERT ( false );
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
if ( VehicleScalingInfo const * scalingInfo = sObjectMgr -> GetVehicleScalingInfo ( m_vehicleInfo -> m_ID ))
2010-08-24 15:04:34 -07:00
{
Player * plr = unit -> ToPlayer ();
float averageItemLevel = plr -> GetAverageItemLevel ();
if ( averageItemLevel < scalingInfo -> baseItemLevel )
averageItemLevel = scalingInfo -> baseItemLevel ;
averageItemLevel -= scalingInfo -> baseItemLevel ;
m_bonusHP = uint32 ( me -> GetMaxHealth () * ( averageItemLevel * scalingInfo -> scalingFactor ));
me -> SetMaxHealth ( me -> GetMaxHealth () + m_bonusHP );
me -> SetHealth ( me -> GetHealth () + m_bonusHP );
}
}
2010-04-07 19:14:10 +02:00
if ( me -> IsInWorld ())
2009-08-08 11:57:51 -05:00
{
2010-01-13 11:16:38 +01:00
unit -> SendMonsterMoveTransport ( me );
2010-04-07 19:14:10 +02:00
if ( me -> GetTypeId () == TYPEID_UNIT )
2009-08-23 22:09:43 -05:00
{
2010-04-07 19:14:10 +02:00
if ( me -> ToCreature () -> IsAIEnabled )
2010-03-07 18:30:53 +01:00
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
RelocatePassengers ( me -> GetPositionX (), me -> GetPositionY (), me -> GetPositionZ (), me -> GetOrientation ());
2009-08-23 22:09:43 -05:00
}
}
2010-10-31 14:19:14 +01:00
unit -> DestroyForNearbyPlayers ();
unit -> UpdateObjectVisibility ( false );
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
2009-04-17 15:08:58 -05:00
void Vehicle :: RemovePassenger ( Unit * unit )
{
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
2009-04-17 15:08:58 -05:00
SeatMap :: iterator seat ;
2009-10-17 16:20:24 -07:00
for ( seat = m_Seats . begin (); seat != m_Seats . end (); ++ seat )
2010-04-07 19:14:10 +02:00
if ( seat -> second . passenger == unit )
2009-04-17 15:08:58 -05:00
break ;
2009-10-17 15:51:44 -07:00
2010-07-30 20:04:28 +02:00
ASSERT ( seat != m_Seats . end ());
2009-10-17 15:51:44 -07:00
2010-12-23 23:25:44 +01:00
sLog -> outDebug ( "Unit %s exit vehicle entry %u id %u dbguid %u seat %d" , unit -> GetName (), me -> GetEntry (), m_vehicleInfo -> m_ID , me -> GetGUIDLow (), ( int32 ) seat -> first );
2009-10-17 15:51:44 -07:00
2009-08-08 11:57:51 -05:00
seat -> second . passenger = NULL ;
2010-12-27 16:55:17 +01:00
if ( seat -> second . seatInfo -> IsUsableByPlayer ())
2009-08-08 11:57:51 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_usableSeatNum )
2010-01-13 11:16:38 +01:00
{
if ( me -> GetTypeId () == TYPEID_PLAYER )
me -> SetFlag ( UNIT_NPC_FLAGS , UNIT_NPC_FLAG_PLAYER_VEHICLE );
else
me -> SetFlag ( UNIT_NPC_FLAGS , UNIT_NPC_FLAG_SPELLCLICK );
}
2009-08-08 11:57:51 -05:00
++ m_usableSeatNum ;
}
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
2010-04-07 19:14:10 +02:00
if ( me -> GetTypeId () == TYPEID_UNIT
2010-02-02 23:25:46 -03:00
&& unit -> GetTypeId () == TYPEID_PLAYER
2010-09-28 08:21:51 +03:00
&& seat -> first == 0 && seat -> second . seatInfo -> m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL )
2010-08-24 15:04:34 -07:00
{
2009-08-23 22:09:43 -05:00
me -> RemoveCharmedBy ( unit );
2009-10-17 15:51:44 -07:00
2010-08-24 15:04:34 -07:00
if ( m_bonusHP )
{
me -> SetHealth ( me -> GetHealth () - m_bonusHP );
me -> SetMaxHealth ( me -> GetMaxHealth () - m_bonusHP );
m_bonusHP = 0 ;
}
}
2010-04-07 19:14:10 +02:00
if ( me -> GetTypeId () == TYPEID_UNIT && me -> ToCreature () -> IsAIEnabled )
2010-03-07 18:30:53 +01:00
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 ))
2010-11-21 10:07:51 -08: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-12-30 17:33:51 +01:00
void Vehicle :: EjectPassenger ( Unit * passenger , Unit * controller )
{
SeatMap :: const_iterator m_SeatsItr ;
for ( m_SeatsItr = m_Seats . begin (); m_SeatsItr != m_Seats . end (); ++ m_SeatsItr )
if ( m_SeatsItr -> second . passenger == passenger )
if ( m_SeatsItr -> second . seatInfo -> IsEjectable ())
return passenger -> ExitVehicle ();
else
sLog -> outError ( "Player %u attempted to eject unit GUID " UI64FMTD " from non-ejectable seat." , controller -> GetGUIDLow (), passenger -> GetGUID ());
}
2010-01-16 11:43:47 +02:00
void Vehicle :: RelocatePassengers ( float x , float y , float z , float ang )
{
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
for ( SeatMap :: const_iterator itr = m_Seats . begin (); itr != m_Seats . end (); ++ itr )
if ( Unit * passenger = itr -> second . passenger )
{
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
passenger -> SetPosition ( px , py , pz , po );
2010-01-16 11:43:47 +02:00
}
}
2008-12-24 09:58:26 -06:00
void Vehicle :: Dismiss ()
{
2010-12-23 23:25:44 +01:00
sLog -> outDebug ( "Vehicle::Dismiss %u" , me -> GetEntry ());
2009-08-28 11:26:20 -05:00
Uninstall ();
2009-08-23 22:09:43 -05:00
me -> SendObjectDeSpawnAnim ( me -> GetGUID ());
me -> CombatStop ();
me -> AddObjectToRemoveList ();
2009-03-28 22:44:09 -06:00
}
2010-12-29 05:45:38 +01:00
uint16 Vehicle :: GetExtraMovementFlagsForBase () const
{
uint16 movementMask = MOVEMENTFLAG2_NONE ;
uint32 vehicleFlags = GetVehicleInfo () -> m_flags ;
if ( vehicleFlags & VEHICLE_FLAG_NO_STRAFE )
movementMask |= MOVEMENTFLAG2_NO_STRAFE ;
if ( vehicleFlags & VEHICLE_FLAG_NO_JUMPING )
movementMask |= MOVEMENTFLAG2_NO_JUMPING ;
if ( vehicleFlags & VEHICLE_FLAG_FULLSPEEDTURNING )
movementMask |= MOVEMENTFLAG2_FULL_SPEED_TURNING ;
if ( vehicleFlags & VEHICLE_FLAG_ALLOW_PITCHING )
movementMask |= MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING ;
if ( vehicleFlags & VEHICLE_FLAG_FULLSPEEDPITCHING )
movementMask |= MOVEMENTFLAG2_FULL_SPEED_PITCHING ;
sLog -> outDebug ( "Vehicle::GetExtraMovementFlagsForBase() returned %u" , movementMask );
return movementMask ;
}