Advertisement
Guest User

vehicles mangos [11765]

a guest
Aug 2nd, 2011
409
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 141.02 KB | None | 0 0
  1. diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
  2. index d4a8808..69d17bd 100644
  3. --- a/src/game/Creature.cpp
  4. +++ b/src/game/Creature.cpp
  5. @@ -194,6 +194,9 @@ void Creature::AddToWorld()
  6.          GetMap()->GetObjectsStore().insert<Creature>(GetObjectGuid(), (Creature*)this);
  7.  
  8.      Unit::AddToWorld();
  9. +
  10. +    if (GetVehicleKit())
  11. +        GetVehicleKit()->Reset();
  12.  }
  13.  
  14.  void Creature::RemoveFromWorld()
  15. @@ -296,6 +299,7 @@ bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=NULL*/, GameE
  16.      SetDisplayId(display_id);
  17.  
  18.      SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
  19. +    SetByteValue(UNIT_FIELD_BYTES_0, 3, uint8(cinfo->powerType));
  20.  
  21.      // Load creature equipment
  22.      if (eventData && eventData->equipment_id)
  23. @@ -629,36 +633,82 @@ void Creature::RegenerateAll(uint32 update_diff)
  24.      if (!isInCombat() || IsPolymorphed())
  25.          RegenerateHealth();
  26.  
  27. -    RegenerateMana();
  28. +    Regenerate(getPowerType());
  29.  
  30.      m_regenTimer = REGEN_TIME_FULL;
  31.  }
  32.  
  33. -void Creature::RegenerateMana()
  34. +void Creature::Regenerate(Powers power)
  35.  {
  36. -    uint32 curValue = GetPower(POWER_MANA);
  37. -    uint32 maxValue = GetMaxPower(POWER_MANA);
  38. +    uint32 curValue = GetPower(power);
  39. +    uint32 maxValue = GetMaxPower(power);
  40.  
  41.      if (curValue >= maxValue)
  42.          return;
  43.  
  44. -    uint32 addvalue = 0;
  45. +    float addvalue = 0.0f;
  46.  
  47. -    // Combat and any controlled creature
  48. -    if (isInCombat() || GetCharmerOrOwnerGuid())
  49. +    switch(power)
  50.      {
  51. -        if(!IsUnderLastManaUseEffect())
  52. +        case POWER_MANA:
  53.          {
  54. -            float ManaIncreaseRate = sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_MANA);
  55. -            float Spirit = GetStat(STAT_SPIRIT);
  56. +            // Combat and any controlled creature
  57. +            if (isInCombat() || GetCharmerOrOwnerGuid())
  58. +            {
  59. +                if(!IsUnderLastManaUseEffect())
  60. +                {
  61. +                    float ManaIncreaseRate = sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_MANA);
  62. +                    float Spirit = GetStat(STAT_SPIRIT);
  63.  
  64. -            addvalue = uint32((Spirit / 5.0f + 17.0f) * ManaIncreaseRate);
  65. +                    addvalue = int32((Spirit / 5.0f + 17.0f) * ManaIncreaseRate);
  66. +                }
  67. +            }
  68. +            else
  69. +                addvalue = maxValue / 3;
  70. +            break;
  71.          }
  72. +        case POWER_ENERGY:
  73. +            if (IsVehicle())
  74. +            {
  75. +                if (VehicleEntry const* vehicleInfo = sVehicleStore.LookupEntry(GetCreatureInfo()->vehicleId))
  76. +                {
  77. +
  78. +                    switch (vehicleInfo->m_powerType)
  79. +                    {
  80. +                        case ENERGY_TYPE_PYRITE:
  81. +                        case ENERGY_TYPE_BLOOD:
  82. +                        case ENERGY_TYPE_OOZE:
  83. +                        break;
  84. +
  85. +                        case ENERGY_TYPE_STEAM:
  86. +                        default:
  87. +                            addvalue = 10 * sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_ENERGY);
  88. +                        break;
  89. +                    }
  90. +                }
  91. +            }
  92. +            else
  93. +                addvalue = 20 * sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_ENERGY);
  94. +            break;
  95. +        case POWER_FOCUS:
  96. +            addvalue = 24 * sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_FOCUS);
  97. +            break;
  98. +        default:
  99. +            return;
  100.      }
  101. -    else
  102. -        addvalue = maxValue / 3;
  103. +    // Apply modifiers (if any)
  104. +
  105. +    AuraList const& ModPowerRegenAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
  106. +    for(AuraList::const_iterator i = ModPowerRegenAuras.begin(); i != ModPowerRegenAuras.end(); ++i)
  107. +        if ((*i)->GetModifier()->m_miscvalue == power)
  108. +            addvalue += (*i)->GetModifier()->m_amount;
  109. +
  110. +    AuraList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT);
  111. +    for(AuraList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i)
  112. +        if ((*i)->GetModifier()->m_miscvalue == power)
  113. +            addvalue *= ((*i)->GetModifier()->m_amount + 100) / 100.0f;
  114.  
  115. -    ModifyPower(POWER_MANA, addvalue);
  116. +    ModifyPower(power, int32(addvalue));
  117.  }
  118.  
  119.  void Creature::RegenerateHealth()
  120. @@ -1155,19 +1205,32 @@ void Creature::SelectLevel(const CreatureInfo *cinfo, float percentHealth, float
  121.      else
  122.          SetHealthPercent(percentHealth);
  123.  
  124. -    // mana
  125. -    uint32 minmana = std::min(cinfo->maxmana, cinfo->minmana);
  126. -    uint32 maxmana = std::max(cinfo->maxmana, cinfo->minmana);
  127. -    uint32 mana = minmana + uint32(rellevel * (maxmana - minmana));
  128. +    SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, float(health));
  129.  
  130. -    SetCreateMana(mana);
  131. -    SetMaxPower(POWER_MANA, mana);                          //MAX Mana
  132. -    SetPower(POWER_MANA, mana);
  133. +    Powers powerType = Powers(cinfo->powerType);
  134. +    uint32 maxPower = 0;
  135.  
  136. -    // TODO: set UNIT_FIELD_POWER*, for some creature class case (energy, etc)
  137. +    switch(powerType)
  138. +    {
  139. +        case POWER_MANA:
  140. +        {
  141. +            uint32 minmana = std::min(cinfo->maxmana, cinfo->minmana);
  142. +            uint32 maxmana = std::max(cinfo->maxmana, cinfo->minmana);
  143. +            maxPower = minmana + uint32(rellevel * (maxmana - minmana));
  144.  
  145. -    SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, float(health));
  146. -    SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, float(mana));
  147. +            SetCreateMana(maxPower);
  148. +            break;
  149. +        }
  150. +        case POWER_ENERGY:
  151. +        {
  152. +            maxPower = uint32(GetCreatePowers(powerType) * cinfo->power_mod);
  153. +            break;
  154. +        }
  155. +    }
  156. +
  157. +    SetMaxPower(powerType, maxPower);
  158. +    SetPower(powerType, maxPower);
  159. +    SetModifierValue(UnitMods(UNIT_MOD_POWER_START + powerType), BASE_VALUE, float(maxPower));
  160.  
  161.      // damage
  162.      float damagemod = _GetDamageMod(rank);
  163. @@ -1247,6 +1310,10 @@ bool Creature::CreateFromProto(uint32 guidlow, CreatureInfo const* cinfo, Team t
  164.      if (!UpdateEntry(cinfo->Entry, team, data, eventData, false))
  165.          return false;
  166.  
  167. +    // Checked at startup
  168. +    if (GetCreatureInfo()->vehicleId)
  169. +        SetVehicleId(GetCreatureInfo()->vehicleId);
  170. +
  171.      return true;
  172.  }
  173.  
  174. diff --git a/src/game/Creature.h b/src/game/Creature.h
  175. index ca554fc..1206a07 100644
  176. --- a/src/game/Creature.h
  177. +++ b/src/game/Creature.h
  178. @@ -54,6 +54,7 @@ enum CreatureFlagsExtra
  179.      CREATURE_FLAG_EXTRA_NOT_TAUNTABLE   = 0x00000100,       // creature is immune to taunt auras and effect attack me
  180.      CREATURE_FLAG_EXTRA_AGGRO_ZONE      = 0x00000200,       // creature sets itself in combat with zone on aggro
  181.      CREATURE_FLAG_EXTRA_GUARD           = 0x00000400,       // creature is a guard
  182. +    CREATURE_FLAG_EXTRA_KEEP_AI         = 0x00001000,       // creature keeps ScriptedAI even after being charmed / controlled (instead of getting PetAI)
  183.  };
  184.  
  185.  // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform
  186. @@ -81,6 +82,7 @@ struct CreatureInfo
  187.      uint32  maxlevel;
  188.      uint32  minhealth;
  189.      uint32  maxhealth;
  190. +    uint32  powerType;
  191.      uint32  minmana;
  192.      uint32  maxmana;
  193.      uint32  armor;
  194. @@ -128,7 +130,7 @@ struct CreatureInfo
  195.      uint32  MovementType;
  196.      uint32  InhabitType;
  197.      float   unk16;
  198. -    float   unk17;
  199. +    float   power_mod;
  200.      bool    RacialLeader;
  201.      uint32  questItems[6];
  202.      uint32  movementId;
  203. @@ -713,7 +715,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
  204.          float m_respawnradius;
  205.  
  206.          CreatureSubtype m_subtype;                          // set in Creatures subclasses for fast it detect without dynamic_cast use
  207. -        void RegenerateMana();
  208. +        void Regenerate(Powers power);
  209.          void RegenerateHealth();
  210.          MovementGeneratorType m_defaultMovementType;
  211.          Cell m_currentCell;                                 // store current cell where creature listed
  212. diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h
  213. index 2a49d50..78ec0b0 100644
  214. --- a/src/game/CreatureAI.h
  215. +++ b/src/game/CreatureAI.h
  216. @@ -139,6 +139,9 @@ class MANGOS_DLL_SPEC CreatureAI
  217.          // Called at text emote receive from player
  218.          virtual void ReceiveEmote(Player* /*pPlayer*/, uint32 /*text_emote*/) {}
  219.  
  220. +        // Called at vehicle enter
  221. +        virtual void PassengerBoarded(Unit * /*who*/, int8 /*seatId*/, bool /*apply*/) {}
  222. +
  223.          ///== Triggered Actions Requested ==================
  224.  
  225.          // Called when creature attack expected (if creature can and no have current victim)
  226. diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp
  227. index f75a4ac..01dc180 100644
  228. --- a/src/game/CreatureEventAI.cpp
  229. +++ b/src/game/CreatureEventAI.cpp
  230. @@ -916,6 +916,7 @@ void CreatureEventAI::JustReachedHome()
  231.  
  232.  void CreatureEventAI::EnterEvadeMode()
  233.  {
  234. +    m_creature->ExitVehicle();
  235.      m_creature->RemoveAllAuras();
  236.      m_creature->DeleteThreatList();
  237.      m_creature->CombatStop(true);
  238. diff --git a/src/game/DBCEnums.h b/src/game/DBCEnums.h
  239. index 3afa1a3..2d7d0c2 100644
  240. --- a/src/game/DBCEnums.h
  241. +++ b/src/game/DBCEnums.h
  242. @@ -361,7 +361,8 @@ enum SummonPropGroup
  243.      SUMMON_PROP_GROUP_FRIENDLY       = 1,
  244.      SUMMON_PROP_GROUP_PETS           = 2,
  245.      SUMMON_PROP_GROUP_CONTROLLABLE   = 3,
  246. -    SUMMON_PROP_GROUP_VEHICLE        = 4
  247. +    SUMMON_PROP_GROUP_VEHICLE        = 4,
  248. +    SUMMON_PROP_GROUP_UNCONTROLLABLE_VEHICLE = 5
  249.  };
  250.  
  251.  // SummonProperties.dbc, col 3
  252. @@ -467,15 +468,20 @@ enum VehicleFlags
  253.      VEHICLE_FLAG_ALLOW_PITCHING     = 0x00000010,           // Sets MOVEFLAG2_ALLOW_PITCHING
  254.      VEHICLE_FLAG_FULLSPEEDPITCHING  = 0x00000020,           // Sets MOVEFLAG2_FULLSPEEDPITCHING
  255.      VEHICLE_FLAG_CUSTOM_PITCH       = 0x00000040,           // If set use pitchMin and pitchMax from DBC, otherwise pitchMin = -pi/2, pitchMax = pi/2
  256. +    VEHICLE_FLAG_ACCESSORY          = 0x00000200,           // Vehicle is accessory? Need additional check!
  257.      VEHICLE_FLAG_ADJUST_AIM_ANGLE   = 0x00000400,           // Lua_IsVehicleAimAngleAdjustable
  258.      VEHICLE_FLAG_ADJUST_AIM_POWER   = 0x00000800,           // Lua_IsVehicleAimPowerAdjustable
  259. +    VEHICLE_FLAG_DISABLE_SWITCH     = 0x00400000,           // Can't change seats, VEHICLE_ID = 335 chopper
  260. +    VEHICLE_FLAG_NOT_DISMISS        = 0x10000000,           // Vehicle not dismissed after eject passenger?
  261.  };
  262.  
  263.  enum VehicleSeatFlags
  264.  {
  265.      SEAT_FLAG_HIDE_PASSENGER        = 0x00000200,           // Passenger is hidden
  266.      SEAT_FLAG_CAN_CONTROL           = 0x00000800,           // Lua_UnitInVehicleControlSeat
  267. +    SEAT_FLAG_UNCONTROLLED          = 0x00002000,           // Seat uncontrolled for passenger?
  268.      SEAT_FLAG_CAN_ATTACK            = 0x00004000,           // Can attack, cast spells and use items from vehicle?
  269. +    SEAT_FLAG_UNATTACKABLE          = 0x00008000,           // Passenger is not attackable?
  270.      SEAT_FLAG_USABLE                = 0x02000000,           // Lua_CanExitVehicle
  271.      SEAT_FLAG_CAN_SWITCH            = 0x04000000,           // Lua_CanSwitchVehicleSeats
  272.      SEAT_FLAG_CAN_CAST              = 0x20000000,           // Lua_UnitHasVehicleUI
  273. diff --git a/src/game/DBCStores.cpp b/src/game/DBCStores.cpp
  274. index c17f1fd..e73428f 100644
  275. --- a/src/game/DBCStores.cpp
  276. +++ b/src/game/DBCStores.cpp
  277. @@ -424,6 +424,19 @@ void LoadDBCStores(const std::string& dataPath)
  278.  
  279.      LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionTemplateStore,     dbcPath,"FactionTemplate.dbc");
  280.      LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGameObjectDisplayInfoStore,dbcPath,"GameObjectDisplayInfo.dbc");
  281. +    for (uint32 i = 0; i < sGameObjectDisplayInfoStore.GetNumRows(); ++i)
  282. +    {
  283. +        if (GameObjectDisplayInfoEntry *info = const_cast<GameObjectDisplayInfoEntry*>(sGameObjectDisplayInfoStore.LookupEntry(i)))
  284. +        {
  285. +            if (info->maxX < info->minX)
  286. +                std::swap(info->maxX, info->minX);
  287. +            if (info->maxY < info->minY)
  288. +                std::swap(info->maxY, info->minY);
  289. +            if (info->maxZ < info->minZ)
  290. +                std::swap(info->maxZ, info->minZ);
  291. +        }
  292. +    }
  293. +
  294.      LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGemPropertiesStore,       dbcPath,"GemProperties.dbc");
  295.      LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphPropertiesStore,     dbcPath,"GlyphProperties.dbc");
  296.      LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphSlotStore,           dbcPath,"GlyphSlot.dbc");
  297. diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h
  298. index 92bf8b1..0903b9f 100644
  299. --- a/src/game/DBCStructure.h
  300. +++ b/src/game/DBCStructure.h
  301. @@ -916,12 +916,12 @@ struct GameObjectDisplayInfoEntry
  302.      uint32      Displayid;                                  // 0        m_ID
  303.      // char* filename;                                      // 1        m_modelName
  304.                                                              // 2-11     m_Sound
  305. -    float  unknown12;                                       // 12       m_geoBoxMinX (use first value as interact dist, mostly in hacks way)
  306. -                                                            // 13       m_geoBoxMinY
  307. -                                                            // 14       m_geoBoxMinZ
  308. -                                                            // 15       m_geoBoxMaxX
  309. -                                                            // 16       m_geoBoxMaxY
  310. -                                                            // 17       m_geoBoxMaxZ
  311. +    float       minX;                                       // 12       m_geoBoxMinX (use first value as interact dist, mostly in hacks way)
  312. +    float       minY;                                       // 13       m_geoBoxMinY
  313. +    float       minZ;                                       // 14       m_geoBoxMinZ
  314. +    float       maxX;                                       // 15       m_geoBoxMaxX
  315. +    float       maxY;                                       // 16       m_geoBoxMaxY
  316. +    float       maxZ;                                       // 17       m_geoBoxMaxZ
  317.                                                              // 18       m_objectEffectPackageID
  318.  };
  319.  
  320. @@ -1936,7 +1936,7 @@ struct VehicleEntry
  321.      uint32  m_uiLocomotionType;                             // 34
  322.      float   m_msslTrgtImpactTexRadius;                      // 35
  323.      uint32  m_uiSeatIndicatorType;                          // 36       m_vehicleUIIndicatorID
  324. -                                                            // 37       m_powerDisplayID
  325. +    uint32  m_powerType;                                    // 37       m_powerDisplayID
  326.                                                              // 38 new in 3.1
  327.                                                              // 39 new in 3.1
  328.  };
  329. @@ -2001,6 +2001,8 @@ struct VehicleSeatEntry
  330.                                                              // 55       m_cameraEnteringZoom"
  331.                                                              // 56       m_cameraSeatZoomMin
  332.                                                              // 57       m_cameraSeatZoomMax
  333. +
  334. +    bool IsUsable() const { return m_flags & SEAT_FLAG_USABLE; }
  335.  };
  336.  
  337.  struct WMOAreaTableEntry
  338. diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h
  339. index faa32ab..f35f5a9 100644
  340. --- a/src/game/DBCfmt.h
  341. +++ b/src/game/DBCfmt.h
  342. @@ -47,7 +47,7 @@ const char EmotesEntryfmt[]="nxxiiix";
  343.  const char EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx";
  344.  const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiiffixssssssssssssssssxxxxxxxxxxxxxxxxxx";
  345.  const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii";
  346. -const char GameObjectDisplayInfofmt[]="nxxxxxxxxxxxfxxxxxx";
  347. +const char GameObjectDisplayInfofmt[]="nxxxxxxxxxxxffffffx";
  348.  const char GemPropertiesEntryfmt[]="nixxi";
  349.  const char GlyphPropertiesfmt[]="niii";
  350.  const char GlyphSlotfmt[]="nii";
  351. @@ -110,7 +110,7 @@ const char TaxiPathEntryfmt[]="niii";
  352.  const char TaxiPathNodeEntryfmt[]="diiifffiiii";
  353.  const char TeamContributionPointsfmt[]="df";
  354.  const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii";
  355. -const char VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifixxx";
  356. +const char VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifiixx";
  357.  const char VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxx";
  358.  const char WMOAreaTableEntryfmt[]="niiixxxxxiixxxxxxxxxxxxxxxxx";
  359.  const char WorldMapAreaEntryfmt[]="xinxffffixx";
  360. diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp
  361. index 8479ef9..cc65165 100644
  362. --- a/src/game/GameObject.cpp
  363. +++ b/src/game/GameObject.cpp
  364. @@ -59,6 +59,7 @@ GameObject::GameObject() : WorldObject(),
  365.      m_cooldownTime = 0;
  366.  
  367.      m_rotation = 0;
  368. +    m_health = 0;
  369.  }
  370.  
  371.  GameObject::~GameObject()
  372. @@ -149,6 +150,13 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMa
  373.      SetGoArtKit(0);                                         // unknown what this is
  374.      SetGoAnimProgress(animprogress);
  375.  
  376. +    if (goinfo->type == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
  377. +    {
  378. +        m_health = GetMaxHealth();
  379. +        // destructible GO's show their "HP" as their animprogress
  380. +        SetGoAnimProgress(255);
  381. +    }
  382. +
  383.      //Notify the map's instance data.
  384.      //Only works if you create the object in it, not if it is moves to that map.
  385.      //Normally non-players do not teleport to other maps.
  386. @@ -195,7 +203,7 @@ void GameObject::Update(uint32 update_diff, uint32 /*p_time*/)
  387.  
  388.                              SendForcedObjectUpdate();
  389.  
  390. -                            SendGameObjectCustomAnim(GetObjectGuid());
  391. +                            SendGameObjectCustomAnim(GetObjectGuid(), 0);
  392.                          }
  393.  
  394.                          m_lootState = GO_READY;             // can be successfully open with some chance
  395. @@ -1142,7 +1150,7 @@ void GameObject::Use(Unit* user)
  396.  
  397.              // this appear to be ok, however others exist in addition to this that should have custom (ex: 190510, 188692, 187389)
  398.              if (time_to_restore && info->goober.customAnim)
  399. -                SendGameObjectCustomAnim(GetObjectGuid());
  400. +                SendGameObjectCustomAnim(GetObjectGuid(), info->goober.customAnim);
  401.              else
  402.                  SetGoState(GO_STATE_ACTIVE);
  403.  
  404. @@ -1435,6 +1443,8 @@ void GameObject::Use(Unit* user)
  405.                  BattleGround *bg = player->GetBattleGround();
  406.                  if (!bg)
  407.                      return;
  408. +                if (player->GetVehicle())
  409. +                    return;
  410.                  // BG flag click
  411.                  // AB:
  412.                  // 15001
  413. @@ -1471,6 +1481,8 @@ void GameObject::Use(Unit* user)
  414.                  BattleGround *bg = player->GetBattleGround();
  415.                  if (!bg)
  416.                      return;
  417. +                if (player->GetVehicle())
  418. +                    return;
  419.                  // BG flag dropped
  420.                  // WS:
  421.                  // 179785 - Silverwing Flag
  422. @@ -1620,6 +1632,87 @@ void GameObject::Use(Unit* user)
  423.      spell->prepare(&targets);
  424.  }
  425.  
  426. +bool GameObject::IsInRange(float x, float y, float z, float radius) const
  427. +{
  428. +    GameObjectDisplayInfoEntry const *info = sGameObjectDisplayInfoStore.LookupEntry(GetUInt32Value(GAMEOBJECT_DISPLAYID));
  429. +    if (!info)
  430. +        return IsWithinDist3d(x, y, z, radius);
  431. +
  432. +    float dx = x - GetPositionX();
  433. +    float dy = y - GetPositionY();
  434. +    float dz = z - GetPositionZ();
  435. +    float dist = sqrt(dx*dx + dy*dy);
  436. +
  437. +    if (dist <= CONTACT_DISTANCE)   // prevent division by 0
  438. +        return true;
  439. +
  440. +    float sinA = sin(GetOrientation());
  441. +    float cosA = cos(GetOrientation());
  442. +    float sinB = dx / dist;
  443. +    float cosB = dy / dist;
  444. +
  445. +    dx = dist * (cosA * cosB + sinA * sinB);
  446. +    dy = dist * (cosA * sinB - sinA * cosB);
  447. +
  448. +    return dx < info->maxX + radius && dx > info->minX - radius
  449. +        && dy < info->maxY + radius && dy > info->minY - radius
  450. +        && dz < info->maxZ + radius && dz > info->minZ - radius;
  451. +}
  452. +
  453. +void GameObject::DamageTaken(Unit* pDoneBy, uint32 damage)
  454. +{
  455. +    if (GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING || !m_health)
  456. +        return;
  457. +
  458. +    DEBUG_FILTER_LOG(LOG_FILTER_DAMAGE, "GO damage taken: %u to health %u", damage, m_health);
  459. +
  460. +    if (m_health > damage)
  461. +        m_health -= damage;
  462. +    else
  463. +        m_health = 0;
  464. +
  465. +    if (HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED)) // from damaged to destroyed
  466. +    {
  467. +        if (!m_health)
  468. +        {
  469. +            RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED);
  470. +            SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED);
  471. +            SetUInt32Value(GAMEOBJECT_DISPLAYID, m_goInfo->destructibleBuilding.destroyedDisplayId);
  472. +        }
  473. +    }
  474. +    else                                            // from intact to damaged
  475. +    {
  476. +        if (m_health <= m_goInfo->destructibleBuilding.damagedNumHits)
  477. +        {
  478. +            SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED);
  479. +            SetUInt32Value(GAMEOBJECT_DISPLAYID, m_goInfo->destructibleBuilding.damagedDisplayId);
  480. +            // if we have a "dead" display we can "kill" the building after its damaged
  481. +            if (m_goInfo->destructibleBuilding.destroyedDisplayId)
  482. +            {
  483. +                m_health = m_goInfo->destructibleBuilding.damagedNumHits;
  484. +                if (!m_health)
  485. +                    m_health = 1;
  486. +            }
  487. +            // otherwise we just handle it as "destroyed"
  488. +            else
  489. +                m_health = 0;
  490. +         }
  491. +    }
  492. +    SetGoAnimProgress(m_health * 255 / GetMaxHealth());
  493. +}
  494. +
  495. +void GameObject::Rebuild(Unit* pWho)
  496. +{
  497. +    if (GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
  498. +        return;
  499. +
  500. +    RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_DESTROYED);
  501. +    SetUInt32Value(GAMEOBJECT_DISPLAYID, m_goInfo->displayId);
  502. +    m_health = GetMaxHealth();
  503. +
  504. +    SetGoAnimProgress(255);
  505. +}
  506. +
  507.  // overwrite WorldObject function for proper name localization
  508.  const char* GameObject::GetNameForLocaleIdx(int32 loc_idx) const
  509.  {
  510. @@ -1799,7 +1892,7 @@ float GameObject::GetObjectBoundingRadius() const
  511.      // 1. This is clearly hack way because GameObjectDisplayInfoEntry have 6 floats related to GO sizes, but better that use DEFAULT_WORLD_OBJECT_SIZE
  512.      // 2. In some cases this must be only interactive size, not GO size, current way can affect creature target point auto-selection in strange ways for big underground/virtual GOs
  513.      if (m_displayInfo)
  514. -        return fabs(m_displayInfo->unknown12) * GetObjectScale();
  515. +        return fabs(m_displayInfo->minX) * GetObjectScale();
  516.  
  517.      return DEFAULT_WORLD_OBJECT_SIZE;
  518.  }
  519. diff --git a/src/game/GameObject.h b/src/game/GameObject.h
  520. index 2cca164..39c85b5 100644
  521. --- a/src/game/GameObject.h
  522. +++ b/src/game/GameObject.h
  523. @@ -360,26 +360,26 @@ struct GameObjectInfo
  524.              uint32 creditProxyCreature;                     //1
  525.              uint32 empty1;                                  //2
  526.              uint32 intactEvent;                             //3
  527. -            uint32 empty2;                                  //4
  528. +            uint32 damagedDisplayId;                        //4
  529.              uint32 damagedNumHits;                          //5
  530. -            uint32 empty3;                                  //6
  531. -            uint32 empty4;                                  //7
  532. -            uint32 empty5;                                  //8
  533. +            uint32 empty2;                                  //6
  534. +            uint32 empty3;                                  //7
  535. +            uint32 empty4;                                  //8
  536.              uint32 damagedEvent;                            //9
  537. -            uint32 empty6;                                  //10
  538. -            uint32 empty7;                                  //11
  539. -            uint32 empty8;                                  //12
  540. -            uint32 empty9;                                  //13
  541. +            uint32 destroyedDisplayId;                      //10
  542. +            uint32 empty5;                                  //11
  543. +            uint32 empty6;                                  //12
  544. +            uint32 empty7;                                  //13
  545.              uint32 destroyedEvent;                          //14
  546. -            uint32 empty10;                                 //15
  547. +            uint32 empty8;                                  //15
  548.              uint32 debuildingTimeSecs;                      //16
  549. -            uint32 empty11;                                 //17
  550. +            uint32 empty9;                                  //17
  551.              uint32 destructibleData;                        //18
  552.              uint32 rebuildingEvent;                         //19
  553. -            uint32 empty12;                                 //20
  554. -            uint32 empty13;                                 //21
  555. +            uint32 empty10;                                 //20
  556. +            uint32 empty11;                                 //21
  557.              uint32 damageEvent;                             //22
  558. -            uint32 empty14;                                 //23
  559. +            uint32 empty12;                                 //23
  560.          } destructibleBuilding;
  561.          //34 GAMEOBJECT_TYPE_GUILDBANK - empty
  562.          //35 GAMEOBJECT_TYPE_TRAPDOOR
  563. @@ -725,6 +725,13 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
  564.  
  565.          GridReference<GameObject> &GetGridRef() { return m_gridRef; }
  566.  
  567. +        bool IsInRange(float x, float y, float z, float radius) const;
  568. +        void DamageTaken(Unit *pDoneBy, uint32 uiDamage);
  569. +        void Rebuild(Unit *pWho);
  570. +
  571. +        uint32 GetHealth() const { return m_health; }
  572. +        uint32 GetMaxHealth() const { return m_goInfo->destructibleBuilding.intactNumHits + m_goInfo->destructibleBuilding.damagedNumHits; }
  573. +
  574.      protected:
  575.          uint32      m_spellId;
  576.          time_t      m_respawnTime;                          // (secs) time of next respawn (or despawn if GO have owner()),
  577. @@ -733,7 +740,7 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
  578.          bool        m_spawnedByDefault;
  579.          time_t      m_cooldownTime;                         // used as internal reaction delay time store (not state change reaction).
  580.                                                              // For traps/goober this: spell casting cooldown, for doors/buttons: reset time.
  581. -
  582. +        uint32      m_health;
  583.          typedef std::set<ObjectGuid> GuidsSet;
  584.  
  585.          GuidsSet m_SkillupSet;                              // players that already have skill-up at GO use
  586. diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h
  587. index 11b5cd4..0fba845 100644
  588. --- a/src/game/GridNotifiers.h
  589. +++ b/src/game/GridNotifiers.h
  590. @@ -930,7 +930,7 @@ namespace MaNGOS
  591.                  : i_obj(obj), i_originalCaster(originalCaster), i_range(range)
  592.              {
  593.                  i_targetForUnit = i_originalCaster->isType(TYPEMASK_UNIT);
  594. -                i_targetForPlayer = (i_originalCaster->GetTypeId() == TYPEID_PLAYER);
  595. +                i_targetForPlayer = (i_originalCaster->GetObjectGuid().IsVehicle() ? ((Unit*)i_originalCaster)->GetCharmerOrOwnerOrSelf()->GetTypeId() == TYPEID_PLAYER : i_originalCaster->GetTypeId() == TYPEID_PLAYER);
  596.              }
  597.              WorldObject const& GetFocusObject() const { return *i_obj; }
  598.              bool operator()(Unit* u)
  599. @@ -1154,6 +1154,27 @@ namespace MaNGOS
  600.  
  601.      // Player checks and do
  602.  
  603. +    class GameObjectInRangeCheck
  604. +    {
  605. +        public:
  606. +            GameObjectInRangeCheck(WorldObject const* _obj, float _x, float _y, float _z, float _range):
  607. +              i_obj(_obj), x(_x), y(_y), z(_z), range(_range) {}
  608. +
  609. +            WorldObject const& GetFocusObject() const { return *i_obj; }
  610. +
  611. +            bool operator() (GameObject* go)
  612. +            {
  613. +                return go->IsInRange(x, y, z, range);
  614. +            }
  615. +
  616. +        private:
  617. +            WorldObject const* i_obj;
  618. +            float x, y, z, range;
  619. +
  620. +            // prevent cloning this object
  621. +            GameObjectInRangeCheck(GameObjectInRangeCheck const&);
  622. +    };
  623. +
  624.      class AnyPlayerInObjectRangeCheck
  625.      {
  626.          public:
  627. diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp
  628. index 62dd59a..1bf5a49 100644
  629. --- a/src/game/GroupHandler.cpp
  630. +++ b/src/game/GroupHandler.cpp
  631. @@ -807,6 +807,9 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
  632.          else
  633.              *data << uint64(0);
  634.      }
  635. +
  636. +    if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
  637. +        *data << uint32(player->m_movementInfo.GetTransportDBCSeat());
  638.  }
  639.  
  640.  /*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/
  641. diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
  642. index 38429e7..8d88039 100644
  643. --- a/src/game/Level3.cpp
  644. +++ b/src/game/Level3.cpp
  645. @@ -4222,6 +4222,9 @@ bool ChatHandler::HandleNpcInfoCommand(char* /*args*/)
  646.      else
  647.          PSendSysMessage(LANG_NPCINFO_CHAR, target->GetGuidStr().c_str(), faction, npcflags, Entry, displayid, nativeid);
  648.  
  649. +    if (cInfo->vehicleId)
  650. +        PSendSysMessage("VehicleId: %u", cInfo->vehicleId);
  651. +
  652.      PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel());
  653.      PSendSysMessage(LANG_NPCINFO_HEALTH,target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth());
  654.      PSendSysMessage(LANG_NPCINFO_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS), target->GetUInt32Value(UNIT_DYNAMIC_FLAGS), target->getFaction());
  655. diff --git a/src/game/Map.cpp b/src/game/Map.cpp
  656. index 6a267fe..55ea6e4 100644
  657. --- a/src/game/Map.cpp
  658. +++ b/src/game/Map.cpp
  659. @@ -3128,6 +3128,7 @@ uint32 Map::GenerateLocalLowGuid(HighGuid guidhigh)
  660.      switch(guidhigh)
  661.      {
  662.          case HIGHGUID_UNIT:
  663. +        case HIGHGUID_VEHICLE:
  664.              return m_CreatureGuids.Generate();
  665.          case HIGHGUID_GAMEOBJECT:
  666.              return m_GameObjectGuids.Generate();
  667. @@ -3135,8 +3136,6 @@ uint32 Map::GenerateLocalLowGuid(HighGuid guidhigh)
  668.              return m_DynObjectGuids.Generate();
  669.          case HIGHGUID_PET:
  670.              return m_PetGuids.Generate();
  671. -        case HIGHGUID_VEHICLE:
  672. -            return m_VehicleGuids.Generate();
  673.          default:
  674.              MANGOS_ASSERT(0);
  675.      }
  676. diff --git a/src/game/Map.h b/src/game/Map.h
  677. index 31e8731..834ecfd 100644
  678. --- a/src/game/Map.h
  679. +++ b/src/game/Map.h
  680. @@ -338,7 +338,6 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>
  681.          ObjectGuidGenerator<HIGHGUID_GAMEOBJECT> m_GameObjectGuids;
  682.          ObjectGuidGenerator<HIGHGUID_DYNAMICOBJECT> m_DynObjectGuids;
  683.          ObjectGuidGenerator<HIGHGUID_PET> m_PetGuids;
  684. -        ObjectGuidGenerator<HIGHGUID_VEHICLE> m_VehicleGuids;
  685.  
  686.          // Type specific code for add/remove to/from grid
  687.          template<class T>
  688. diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp
  689. index 8310000..0249f21 100644
  690. --- a/src/game/MotionMaster.cpp
  691. +++ b/src/game/MotionMaster.cpp
  692. @@ -68,6 +68,8 @@ void MotionMaster::UpdateMotion(uint32 diff)
  693.      if (m_owner->hasUnitState(UNIT_STAT_CAN_NOT_MOVE))
  694.          return;
  695.  
  696. +  if ( !empty() )
  697. +  {
  698.      MANGOS_ASSERT( !empty() );
  699.      m_cleanFlag |= MMCF_UPDATE;
  700.  
  701. @@ -100,6 +102,7 @@ void MotionMaster::UpdateMotion(uint32 diff)
  702.              m_cleanFlag &= ~MMCF_RESET;
  703.          }
  704.      }
  705. +  } else return;
  706.  }
  707.  
  708.  void MotionMaster::DirectClean(bool reset, bool all)
  709. diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp
  710. index 4bfe28e..c202052 100644
  711. --- a/src/game/MovementHandler.cpp
  712. +++ b/src/game/MovementHandler.cpp
  713. @@ -44,6 +44,9 @@ void WorldSession::HandleMoveWorldportAckOpcode()
  714.      if(!GetPlayer()->IsBeingTeleportedFar())
  715.          return;
  716.  
  717. +    if (_player->GetVehicleKit())
  718. +        _player->GetVehicleKit()->RemoveAllPassengers();
  719. +
  720.      // get start teleport coordinates (will used later in fail case)
  721.      WorldLocation old_loc;
  722.      GetPlayer()->GetPosition(old_loc);
  723. @@ -403,7 +406,7 @@ void WorldSession::HandleMoveNotActiveMoverOpcode(WorldPacket &recv_data)
  724.      _player->m_movementInfo = mi;
  725.  }
  726.  
  727. -void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
  728. +/*void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
  729.  {
  730.      DEBUG_LOG("WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE");
  731.      recv_data.hexlike();
  732. @@ -419,7 +422,7 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
  733.          return;
  734.  
  735.      _player->m_movementInfo = mi;
  736. -}
  737. +}*/
  738.  
  739.  void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvdata*/)
  740.  {
  741. @@ -542,7 +545,7 @@ void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo)
  742.      {
  743.          if (movementInfo.HasMovementFlag(MOVEFLAG_ONTRANSPORT))
  744.          {
  745. -            if (!plMover->m_transport)
  746. +            if (!plMover->GetTransport())
  747.              {
  748.                  // elevators also cause the client to send MOVEFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
  749.                  for (MapManager::TransportSet::const_iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter)
  750. @@ -551,15 +554,19 @@ void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo)
  751.                      {
  752.                          plMover->m_transport = (*iter);
  753.                          (*iter)->AddPassenger(plMover);
  754. +
  755. +                        if (plMover->GetVehicleKit())
  756. +                            plMover->GetVehicleKit()->RemoveAllPassengers();
  757. +
  758.                          break;
  759.                      }
  760.                  }
  761.              }
  762.          }
  763. -        else if (plMover->m_transport)               // if we were on a transport, leave
  764. +        else if (plMover->GetTransport())               // if we were on a transport, leave
  765.          {
  766. -            plMover->m_transport->RemovePassenger(plMover);
  767. -            plMover->m_transport = NULL;
  768. +            plMover->GetTransport()->RemovePassenger(plMover);
  769. +            plMover->SetTransport(NULL);
  770.              movementInfo.ClearTransportData();
  771.          }
  772.  
  773. @@ -606,6 +613,9 @@ void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo)
  774.      else                                                    // creature charmed
  775.      {
  776.          if (mover->IsInWorld())
  777. -            mover->GetMap()->CreatureRelocation((Creature*)mover, movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o);
  778. +        {
  779. +            mover->m_movementInfo = movementInfo;
  780. +            mover->SetPosition(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o);
  781. +        }
  782.      }
  783.  }
  784. diff --git a/src/game/Object.cpp b/src/game/Object.cpp
  785. index b33aa2c..031ee15 100644
  786. --- a/src/game/Object.cpp
  787. +++ b/src/game/Object.cpp
  788. @@ -264,6 +264,11 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 updateFlags) const
  789.                  player->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ONTRANSPORT);
  790.          }
  791.  
  792. +        if (unit->GetTransport() || unit->GetVehicle())
  793. +            unit->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT);
  794. +        else
  795. +            unit->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ONTRANSPORT);
  796. +
  797.          // Update movement info time
  798.          unit->m_movementInfo.UpdateTime(WorldTimer::getMSTime());
  799.          // Write movement info
  800. @@ -1507,11 +1512,11 @@ void WorldObject::SendObjectDeSpawnAnim(ObjectGuid guid)
  801.      SendMessageToSet(&data, true);
  802.  }
  803.  
  804. -void WorldObject::SendGameObjectCustomAnim(ObjectGuid guid)
  805. +void WorldObject::SendGameObjectCustomAnim(ObjectGuid guid, uint32 animprogress)
  806.  {
  807.      WorldPacket data(SMSG_GAMEOBJECT_CUSTOM_ANIM, 8+4);
  808.      data << ObjectGuid(guid);
  809. -    data << uint32(0);                                      // not known what this is
  810. +    data << uint32(animprogress);
  811.      SendMessageToSet(&data, true);
  812.  }
  813.  
  814. diff --git a/src/game/Object.h b/src/game/Object.h
  815. index 000ebf8..4faac43 100644
  816. --- a/src/game/Object.h
  817. +++ b/src/game/Object.h
  818. @@ -547,7 +547,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object
  819.          void PlayDirectSound(uint32 sound_id, Player* target = NULL);
  820.  
  821.          void SendObjectDeSpawnAnim(ObjectGuid guid);
  822. -        void SendGameObjectCustomAnim(ObjectGuid guid);
  823. +        void SendGameObjectCustomAnim(ObjectGuid guid, uint32 animprogress);
  824.  
  825.          virtual bool IsHostileTo(Unit const* unit) const =0;
  826.          virtual bool IsFriendlyTo(Unit const* unit) const =0;
  827. diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
  828. index 5814559..8812f93 100644
  829. --- a/src/game/ObjectMgr.cpp
  830. +++ b/src/game/ObjectMgr.cpp
  831. @@ -616,6 +616,12 @@ void ObjectMgr::LoadCreatureTemplates()
  832.          if (!displayScaleEntry)
  833.              sLog.outErrorDb("Creature (Entry: %u) has nonexistent modelid in modelid_1/modelid_2/modelid_3/modelid_4", cInfo->Entry);
  834.  
  835. +        if (cInfo->powerType >= MAX_POWERS)
  836. +        {
  837. +            sLog.outErrorDb("Creature (Entry: %u) has invalid power type (%u)", cInfo->Entry, cInfo->powerType);
  838. +            const_cast<CreatureInfo*>(cInfo)->powerType = POWER_MANA;
  839. +        }
  840. +
  841.          // use below code for 0-checks for unit_class
  842.          if (!cInfo->unit_class)
  843.              ERROR_DB_STRICT_LOG("Creature (Entry: %u) not has proper unit_class(%u) for creature_template", cInfo->Entry, cInfo->unit_class);
  844. @@ -1398,6 +1404,60 @@ void ObjectMgr::RemoveCreatureFromGrid(uint32 guid, CreatureData const* data)
  845.      }
  846.  }
  847.  
  848. +void ObjectMgr::LoadVehicleAccessories()
  849. +{
  850. +    m_VehicleAccessoryMap.clear();                           // needed for reload case
  851. +
  852. +    uint32 count = 0;
  853. +
  854. +    QueryResult* result = WorldDatabase.Query("SELECT `entry`,`accessory_entry`,`seat_id`,`minion` FROM `vehicle_accessory`");
  855. +
  856. +    if (!result)
  857. +    {
  858. +        BarGoLink bar(1);
  859. +
  860. +        bar.step();
  861. +
  862. +        sLog.outString();
  863. +        sLog.outErrorDb(">> Loaded 0 vehicle accessories. DB table `vehicle_accessory` is empty.");
  864. +        return;
  865. +    }
  866. +
  867. +    BarGoLink bar((int)result->GetRowCount());
  868. +
  869. +    do
  870. +    {
  871. +        Field *fields = result->Fetch();
  872. +        bar.step();
  873. +
  874. +        uint32 uiEntry       = fields[0].GetUInt32();
  875. +        uint32 uiAccessory   = fields[1].GetUInt32();
  876. +        int8   uiSeat        = int8(fields[2].GetInt16());
  877. +        bool   bMinion       = fields[3].GetBool();
  878. +
  879. +        if (!sCreatureStorage.LookupEntry<CreatureInfo>(uiEntry))
  880. +        {
  881. +            sLog.outErrorDb("Table `vehicle_accessory`: creature template entry %u does not exist.", uiEntry);
  882. +            continue;
  883. +        }
  884. +
  885. +        if (!sCreatureStorage.LookupEntry<CreatureInfo>(uiAccessory))
  886. +        {
  887. +            sLog.outErrorDb("Table `vehicle_accessory`: Accessory %u does not exist.", uiAccessory);
  888. +            continue;
  889. +        }
  890. +
  891. +        m_VehicleAccessoryMap[uiEntry].push_back(VehicleAccessory(uiAccessory, uiSeat, bMinion));
  892. +
  893. +        ++count;
  894. +    } while (result->NextRow());
  895. +
  896. +    delete result;
  897. +
  898. +    sLog.outString();
  899. +    sLog.outString(">> Loaded %u Vehicle Accessories", count);
  900. +}
  901. +
  902.  void ObjectMgr::LoadGameobjects()
  903.  {
  904.      uint32 count = 0;
  905. diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
  906. index a338167..bd2c71e 100644
  907. --- a/src/game/ObjectMgr.h
  908. +++ b/src/game/ObjectMgr.h
  909. @@ -37,6 +37,7 @@
  910.  #include "ObjectGuid.h"
  911.  #include "Policies/Singleton.h"
  912.  #include "SQLStorages.h"
  913. +#include "Vehicle.h"
  914.  
  915.  #include <string>
  916.  #include <map>
  917. @@ -616,6 +617,14 @@ class ObjectMgr
  918.              return NULL;
  919.          }
  920.  
  921. +        VehicleAccessoryList const* GetVehicleAccessoryList(uint32 uiEntry) const
  922. +        {
  923. +            VehicleAccessoryMap::const_iterator itr = m_VehicleAccessoryMap.find(uiEntry);
  924. +            if (itr != m_VehicleAccessoryMap.end())
  925. +                return &itr->second;
  926. +            return NULL;
  927. +        }
  928. +
  929.          void LoadArenaTeams();
  930.          void LoadGroups();
  931.          void LoadQuests();
  932. @@ -695,6 +704,8 @@ class ObjectMgr
  933.          void LoadTrainerTemplates();
  934.          void LoadTrainers() { LoadTrainers("npc_trainer", false); }
  935.  
  936. +        void LoadVehicleAccessories();
  937. +
  938.          std::string GeneratePetName(uint32 entry);
  939.          uint32 GetBaseXP(uint32 level) const;
  940.          uint32 GetXPForLevel(uint32 level) const;
  941. @@ -1115,6 +1126,8 @@ class ObjectMgr
  942.          ItemConvertMap        m_ItemExpireConvert;
  943.          ItemRequiredTargetMap m_ItemRequiredTarget;
  944.  
  945. +        VehicleAccessoryMap m_VehicleAccessoryMap;
  946. +
  947.          typedef             std::vector<LocaleConstant> LocalForIndex;
  948.          LocalForIndex        m_LocalForIndex;
  949.  
  950. diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp
  951. index 9e42af9..ce9fd26 100644
  952. --- a/src/game/Opcodes.cpp
  953. +++ b/src/game/Opcodes.cpp
  954. @@ -1168,10 +1168,10 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
  955.      /*0x473*/ { "CMSG_CHAR_CUSTOMIZE",                          STATUS_AUTHED,   PROCESS_THREADUNSAFE, &WorldSession::HandleCharCustomizeOpcode       },
  956.      /*0x474*/ { "SMSG_CHAR_CUSTOMIZE",                          STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },
  957.      /*0x475*/ { "SMSG_PET_RENAMEABLE",                          STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },
  958. -    /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT",                    STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_NULL                     },
  959. -    /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT",               STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_NULL                     },
  960. -    /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT",               STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_NULL                     },
  961. -    /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT",             STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_NULL                     },
  962. +    /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT",                    STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestVehicleExit        },
  963. +    /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT",               STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestVehiclePrevSeat    },
  964. +    /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT",               STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestVehicleNextSeat    },
  965. +    /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT",             STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestVehicleSwitchSeat  },
  966.      /*0x47A*/ { "CMSG_PET_LEARN_TALENT",                        STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetLearnTalent            },
  967.      /*0x47B*/ { "CMSG_PET_UNLEARN_TALENTS",                     STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_NULL                     },
  968.      /*0x47C*/ { "SMSG_SET_PHASE_SHIFT",                         STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },
  969. @@ -1205,7 +1205,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
  970.      /*0x498*/ { "SMSG_SERVER_FIRST_ACHIEVEMENT",                STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },
  971.      /*0x499*/ { "SMSG_PET_LEARNED_SPELL",                       STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },
  972.      /*0x49A*/ { "SMSG_PET_REMOVED_SPELL",                       STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },
  973. -    /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE",      STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_NULL                     },
  974. +    /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE",      STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle},
  975.      /*0x49C*/ { "CMSG_HEARTH_AND_RESURRECT",                    STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHearthandResurrect        },
  976.      /*0x49D*/ { "SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA",    STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },
  977.      /*0x49E*/ { "SMSG_CRITERIA_DELETED",                        STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },
  978. @@ -1218,8 +1218,8 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
  979.      /*0x4A5*/ { "CMSG_QUERY_VEHICLE_STATUS",                    STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_NULL                     },
  980.      /*0x4A6*/ { "SMSG_BATTLEGROUND_INFO_THROTTLED",             STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },
  981.      /*0x4A7*/ { "SMSG_SET_VEHICLE_REC_ID",                      STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },
  982. -    /*0x4A8*/ { "CMSG_RIDE_VEHICLE_INTERACT",                   STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_NULL                     },
  983. -    /*0x4A9*/ { "CMSG_CONTROLLER_EJECT_PASSENGER",              STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_NULL                     },
  984. +    /*0x4A8*/ { "CMSG_RIDE_VEHICLE_INTERACT",                   STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEnterPlayerVehicle        },
  985. +    /*0x4A9*/ { "CMSG_CONTROLLER_EJECT_PASSENGER",              STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEjectPasenger             },
  986.      /*0x4AA*/ { "SMSG_PET_GUIDS",                               STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },
  987.      /*0x4AB*/ { "SMSG_CLIENTCACHE_VERSION",                     STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_ServerSide               },
  988.      /*0x4AC*/ { "CMSG_CHANGE_GDF_ARENA_RATING",                 STATUS_NEVER,    PROCESS_INPLACE,      &WorldSession::Handle_NULL                     },
  989. diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
  990. index fbfa951..f618c19 100644
  991. --- a/src/game/Pet.cpp
  992. +++ b/src/game/Pet.cpp
  993. @@ -275,12 +275,12 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
  994.      if (getPetType() == SUMMON_PET && !current)             //all (?) summon pets come with full health when called, but not when they are current
  995.      {
  996.          SetHealth(GetMaxHealth());
  997. -        SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
  998. +        SetPower(getPowerType(), GetMaxPower(getPowerType()));
  999.      }
  1000.      else
  1001.      {
  1002.          SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth);
  1003. -        SetPower(POWER_MANA, savedmana > GetMaxPower(POWER_MANA) ? GetMaxPower(POWER_MANA) : savedmana);
  1004. +        SetPower(getPowerType(), savedmana > GetMaxPower(getPowerType()) ? GetMaxPower(getPowerType()) : savedmana);
  1005.      }
  1006.  
  1007.      AIM_Initialize();
  1008. @@ -583,7 +583,7 @@ void Pet::RegenerateAll( uint32 update_diff )
  1009.          if (!isInCombat() || IsPolymorphed())
  1010.              RegenerateHealth();
  1011.  
  1012. -        RegenerateMana();
  1013. +        Regenerate(getPowerType());
  1014.  
  1015.          m_regenTimer = 4000;
  1016.      }
  1017. @@ -1094,7 +1094,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
  1018.      UpdateAllStats();
  1019.  
  1020.      SetHealth(GetMaxHealth());
  1021. -    SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
  1022. +    SetPower(getPowerType(), GetMaxPower(getPowerType()));
  1023.  
  1024.      return true;
  1025.  }
  1026. diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp
  1027. index ddceb57..363b3d0 100644
  1028. --- a/src/game/PetAI.cpp
  1029. +++ b/src/game/PetAI.cpp
  1030. @@ -192,7 +192,7 @@ void PetAI::UpdateAI(const uint32 diff)
  1031.      }
  1032.  
  1033.      // Autocast (casted only in combat or persistent spells in any state)
  1034. -    if (!m_creature->IsNonMeleeSpellCasted(false))
  1035. +    if (!m_creature->IsNonMeleeSpellCasted(false) && !m_creature->GetObjectGuid().IsVehicle())
  1036.      {
  1037.          typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
  1038.          TargetSpellList targetSpellStore;
  1039. diff --git a/src/game/Player.cpp b/src/game/Player.cpp
  1040. index 1e2c24c..1570704 100644
  1041. --- a/src/game/Player.cpp
  1042. +++ b/src/game/Player.cpp
  1043. @@ -376,8 +376,6 @@ UpdateMask Player::updateVisualBits;
  1044.  
  1045.  Player::Player (WorldSession *session): Unit(), m_mover(this), m_camera(this), m_achievementMgr(this), m_reputationMgr(this)
  1046.  {
  1047. -    m_transport = 0;
  1048. -
  1049.      m_speakTime = 0;
  1050.      m_speakCount = 0;
  1051.  
  1052. @@ -1724,10 +1722,15 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
  1053.      if (!(options & TELE_TO_NOT_LEAVE_TRANSPORT) && m_transport)
  1054.      {
  1055.          m_transport->RemovePassenger(this);
  1056. -        m_transport = NULL;
  1057. +        SetTransport(NULL);
  1058.          m_movementInfo.ClearTransportData();
  1059.      }
  1060.  
  1061. +    if (GetVehicleKit())
  1062. +        GetVehicleKit()->RemoveAllPassengers();
  1063. +
  1064. +    ExitVehicle();
  1065. +
  1066.      // The player was ported to another map and looses the duel immediately.
  1067.      // We have to perform this check before the teleport, otherwise the
  1068.      // ObjectAccessor won't find the flag.
  1069. @@ -2208,7 +2211,7 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask)
  1070.          return NULL;
  1071.  
  1072.      // not in interactive state
  1073. -    if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL))
  1074. +    if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL)  && !hasUnitState(UNIT_STAT_ON_VEHICLE))
  1075.          return NULL;
  1076.  
  1077.      // exist (we need look pets also for some interaction (quest/etc)
  1078. @@ -2262,7 +2265,7 @@ GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameo
  1079.          return NULL;
  1080.  
  1081.      // not in interactive state
  1082. -    if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL))
  1083. +    if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL) && !hasUnitState(UNIT_STAT_ON_VEHICLE))
  1084.          return NULL;
  1085.  
  1086.      if (GameObject *go = GetMap()->GetGameObject(guid))
  1087. @@ -2487,6 +2490,9 @@ void Player::GiveXP(uint32 xp, Unit* victim)
  1088.      if(!isAlive())
  1089.          return;
  1090.  
  1091. +    if(hasUnitState(UNIT_STAT_ON_VEHICLE))
  1092. +        return;
  1093. +
  1094.      uint32 level = getLevel();
  1095.  
  1096.      // XP to money conversion processed in Player::RewardQuest
  1097. @@ -3970,6 +3976,7 @@ void Player::InitVisibleBits()
  1098.      updateVisualBits.SetBit(PLAYER_BYTES_3);
  1099.      updateVisualBits.SetBit(PLAYER_DUEL_TEAM);
  1100.      updateVisualBits.SetBit(PLAYER_GUILD_TIMESTAMP);
  1101. +    updateVisualBits.SetBit(UNIT_NPC_FLAGS);
  1102.  
  1103.      // PLAYER_QUEST_LOG_x also visible bit on official (but only on party/raid)...
  1104.      for(uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_25_2; i += MAX_QUEST_OFFSET)
  1105. @@ -6072,49 +6079,18 @@ ActionButton const* Player::GetActionButton(uint8 button)
  1106.  
  1107.  bool Player::SetPosition(float x, float y, float z, float orientation, bool teleport)
  1108.  {
  1109. -    // prevent crash when a bad coord is sent by the client
  1110. -    if(!MaNGOS::IsValidMapCoord(x,y,z,orientation))
  1111. -    {
  1112. -        DEBUG_LOG("Player::SetPosition(%f, %f, %f, %f, %d) .. bad coordinates for player %d!",x,y,z,orientation,teleport,GetGUIDLow());
  1113. +    if (!Unit::SetPosition(x, y, z, orientation, teleport))
  1114.          return false;
  1115. -    }
  1116. -
  1117. -    Map *m = GetMap();
  1118. -
  1119. -    const float old_x = GetPositionX();
  1120. -    const float old_y = GetPositionY();
  1121. -    const float old_z = GetPositionZ();
  1122. -    const float old_r = GetOrientation();
  1123.  
  1124. -    if( teleport || old_x != x || old_y != y || old_z != z || old_r != orientation )
  1125. -    {
  1126. -        if (teleport || old_x != x || old_y != y || old_z != z)
  1127. -            RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING);
  1128. -        else
  1129. -            RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING);
  1130. -
  1131. -        RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
  1132. -
  1133. -        // move and update visible state if need
  1134. -        m->PlayerRelocation(this, x, y, z, orientation);
  1135. -
  1136. -        // reread after Map::Relocation
  1137. -        m = GetMap();
  1138. -        x = GetPositionX();
  1139. -        y = GetPositionY();
  1140. -        z = GetPositionZ();
  1141. -
  1142. -        // group update
  1143. -        if (GetGroup() && (old_x != x || old_y != y))
  1144. -            SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION);
  1145. +    // group update
  1146. +    if (GetGroup())
  1147. +        SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION);
  1148.  
  1149. -        if (GetTrader() && !IsWithinDistInMap(GetTrader(), INTERACTION_DISTANCE))
  1150. -            GetSession()->SendCancelTrade();   // will close both side trade windows
  1151. -    }
  1152. +    if (GetTrader() && !IsWithinDistInMap(GetTrader(), INTERACTION_DISTANCE))
  1153. +        GetSession()->SendCancelTrade();   // will close both side trade windows
  1154.  
  1155.      // code block for underwater state update
  1156. -    UpdateUnderwaterState(m, x, y, z);
  1157. -
  1158. +    UpdateUnderwaterState(GetMap(), x, y, z);
  1159.      CheckAreaExploreAndOutdoor();
  1160.  
  1161.      return true;
  1162. @@ -15639,19 +15615,21 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder *holder )
  1163.      {
  1164.          for (MapManager::TransportSet::const_iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter)
  1165.          {
  1166. -            if( (*iter)->GetGUIDLow() == transGUID)
  1167. +            Transport* transport = *iter;
  1168. +
  1169. +            if (transport->GetGUIDLow() == transGUID)
  1170.              {
  1171. -                MapEntry const* transMapEntry = sMapStore.LookupEntry((*iter)->GetMapId());
  1172. +                MapEntry const* transMapEntry = sMapStore.LookupEntry(transport->GetMapId());
  1173.                  // client without expansion support
  1174.                  if(GetSession()->Expansion() < transMapEntry->Expansion())
  1175.                  {
  1176. -                    DEBUG_LOG("Player %s using client without required expansion tried login at transport at non accessible map %u", GetName(), (*iter)->GetMapId());
  1177. +                    DEBUG_LOG("Player %s using client without required expansion tried login at transport at non accessible map %u", GetName(), transport->GetMapId());
  1178.                      break;
  1179.                  }
  1180.  
  1181. -                m_transport = *iter;
  1182. -                m_transport->AddPassenger(this);
  1183. -                SetLocationMapId(m_transport->GetMapId());
  1184. +                SetTransport(transport);
  1185. +                transport->AddPassenger(this);
  1186. +                SetLocationMapId(transport->GetMapId());
  1187.                  break;
  1188.              }
  1189.          }
  1190. @@ -18516,6 +18494,59 @@ void Player::PossessSpellInitialize()
  1191.      GetSession()->SendPacket(&data);
  1192.  }
  1193.  
  1194. +void Player::VehicleSpellInitialize()
  1195. +{
  1196. +    Creature* charm = (Creature*)GetCharm();
  1197. +
  1198. +    if (!charm)
  1199. +        return;
  1200. +
  1201. +    CharmInfo *charmInfo = charm->GetCharmInfo();
  1202. +
  1203. +    if (!charmInfo)
  1204. +    {
  1205. +        sLog.outError("Player::VehicleSpellInitialize(): vehicle (GUID: %u) has no charminfo!", charm->GetGUIDLow());
  1206. +        return;
  1207. +    }
  1208. +
  1209. +    size_t cooldownsCount = charm->m_CreatureSpellCooldowns.size() + charm->m_CreatureCategoryCooldowns.size();
  1210. +
  1211. +    WorldPacket data(SMSG_PET_SPELLS, 8+2+4+4+4*MAX_UNIT_ACTION_BAR_INDEX+1+1+cooldownsCount*(4+2+4+4));
  1212. +    data << charm->GetObjectGuid();
  1213. +    data << uint16(0);
  1214. +    data << uint32(0);
  1215. +    data << uint32(0x08000101);                             // react state
  1216. +
  1217. +    charmInfo->BuildActionBar(&data);
  1218. +
  1219. +    data << uint8(0);                                       // additional spells count
  1220. +    data << uint8(cooldownsCount);
  1221. +
  1222. +    time_t curTime = time(NULL);
  1223. +
  1224. +    for (CreatureSpellCooldowns::const_iterator itr = charm->m_CreatureSpellCooldowns.begin(); itr != charm->m_CreatureSpellCooldowns.end(); ++itr)
  1225. +    {
  1226. +        time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILLISECONDS : 0;
  1227. +
  1228. +        data << uint32(itr->first);                         // spellid
  1229. +        data << uint16(0);                                  // spell category?
  1230. +        data << uint32(cooldown);                           // cooldown
  1231. +        data << uint32(0);                                  // category cooldown
  1232. +    }
  1233. +
  1234. +    for (CreatureSpellCooldowns::const_iterator itr = charm->m_CreatureCategoryCooldowns.begin(); itr != charm->m_CreatureCategoryCooldowns.end(); ++itr)
  1235. +    {
  1236. +        time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILLISECONDS : 0;
  1237. +
  1238. +        data << uint32(itr->first);                         // spellid
  1239. +        data << uint16(0);                                  // spell category?
  1240. +        data << uint32(0);                                  // cooldown
  1241. +        data << uint32(cooldown);                           // category cooldown
  1242. +    }
  1243. +
  1244. +    GetSession()->SendPacket(&data);
  1245. +}
  1246. +
  1247.  void Player::CharmSpellInitialize()
  1248.  {
  1249.      Unit* charm = GetCharm();
  1250. @@ -18785,7 +18816,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
  1251.      if (npc)
  1252.      {
  1253.          // not let cheating with start flight mounted
  1254. -        if (IsMounted())
  1255. +        if (IsMounted() || GetVehicle())
  1256.          {
  1257.              WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
  1258.              data << uint32(ERR_TAXIPLAYERALREADYMOUNTED);
  1259. @@ -18814,6 +18845,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
  1260.      else
  1261.      {
  1262.          RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
  1263. +        ExitVehicle();
  1264.  
  1265.          if (IsInDisallowedMountForm())
  1266.              RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
  1267. @@ -20201,6 +20233,14 @@ void Player::SendInitialPacketsAfterAddToMap()
  1268.          SendMessageToSet(&data2,true);
  1269.      }
  1270.  
  1271. +    if(GetVehicle())
  1272. +    {
  1273. +        WorldPacket data3(SMSG_FORCE_MOVE_ROOT, 10);
  1274. +        data3 << GetPackGUID();
  1275. +        data3 << uint32((m_movementInfo.GetVehicleSeatFlags() & SEAT_FLAG_CAN_CAST) ? 2 : 0);
  1276. +        SendMessageToSet(&data3,true);
  1277. +    }
  1278. +
  1279.      SendAurasForTarget(this);
  1280.      SendEnchantmentDurations();                             // must be after add to map
  1281.      SendItemDurations();                                    // must be after add to map
  1282. diff --git a/src/game/Player.h b/src/game/Player.h
  1283. index 0b5a80b..8fbd6f5 100644
  1284. --- a/src/game/Player.h
  1285. +++ b/src/game/Player.h
  1286. @@ -48,7 +48,6 @@ class Channel;
  1287.  class DynamicObject;
  1288.  class Creature;
  1289.  class PlayerMenu;
  1290. -class Transport;
  1291.  class UpdateMask;
  1292.  class SpellCastTargets;
  1293.  class PlayerSocial;
  1294. @@ -1552,6 +1551,7 @@ class MANGOS_DLL_SPEC Player : public Unit
  1295.          void SendPetGUIDs();
  1296.          void CharmSpellInitialize();
  1297.          void PossessSpellInitialize();
  1298. +        void VehicleSpellInitialize();
  1299.          void RemovePetActionBar();
  1300.  
  1301.          bool HasSpell(uint32 spell) const;
  1302. @@ -2172,17 +2172,6 @@ class MANGOS_DLL_SPEC Player : public Unit
  1303.  
  1304.          ObjectGuid const& GetFarSightGuid() const { return GetGuidValue(PLAYER_FARSIGHT); }
  1305.  
  1306. -        // Transports
  1307. -        Transport * GetTransport() const { return m_transport; }
  1308. -        void SetTransport(Transport * t) { m_transport = t; }
  1309. -
  1310. -        float GetTransOffsetX() const { return m_movementInfo.GetTransportPos()->x; }
  1311. -        float GetTransOffsetY() const { return m_movementInfo.GetTransportPos()->y; }
  1312. -        float GetTransOffsetZ() const { return m_movementInfo.GetTransportPos()->z; }
  1313. -        float GetTransOffsetO() const { return m_movementInfo.GetTransportPos()->o; }
  1314. -        uint32 GetTransTime() const { return m_movementInfo.GetTransportTime(); }
  1315. -        int8 GetTransSeat() const { return m_movementInfo.GetTransportSeat(); }
  1316. -
  1317.          uint32 GetSaveTimer() const { return m_nextSave; }
  1318.          void   SetSaveTimer(uint32 timer) { m_nextSave = timer; }
  1319.  
  1320. @@ -2519,9 +2508,6 @@ class MANGOS_DLL_SPEC Player : public Unit
  1321.          RestType rest_type;
  1322.          ////////////////////Rest System/////////////////////
  1323.  
  1324. -        // Transports
  1325. -        Transport * m_transport;
  1326. -
  1327.          uint32 m_resetTalentsCost;
  1328.          time_t m_resetTalentsTime;
  1329.          uint32 m_usedTalentCount;
  1330. diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp
  1331. index ed7dab0..3355d63 100644
  1332. --- a/src/game/QueryHandler.cpp
  1333. +++ b/src/game/QueryHandler.cpp
  1334. @@ -179,7 +179,7 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data )
  1335.              data << uint32(ci->ModelId[i]);
  1336.  
  1337.          data << float(ci->unk16);                           // health modifier
  1338. -        data << float(ci->unk17);                           // power modifier
  1339. +        data << float(ci->power_mod);                       // power modifier
  1340.          data << uint8(ci->RacialLeader);
  1341.          for(uint32 i = 0; i < 6; ++i)
  1342.              data << uint32(ci->questItems[i]);              // itemId[6], quest drop
  1343. diff --git a/src/game/ReactorAI.cpp b/src/game/ReactorAI.cpp
  1344. index 0a32c86..70b6393 100644
  1345. --- a/src/game/ReactorAI.cpp
  1346. +++ b/src/game/ReactorAI.cpp
  1347. @@ -109,6 +109,7 @@ ReactorAI::EnterEvadeMode()
  1348.          DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature stopped attacking, victim %s [guid=%u]", victim->isAlive() ? "out run him" : "is dead", m_creature->GetGUIDLow());
  1349.      }
  1350.  
  1351. +    m_creature->ExitVehicle();
  1352.      m_creature->RemoveAllAuras();
  1353.      m_creature->DeleteThreatList();
  1354.      i_victimGuid.Clear();
  1355. diff --git a/src/game/SQLStorages.cpp b/src/game/SQLStorages.cpp
  1356. index 716f10c..1e0434d 100644
  1357. --- a/src/game/SQLStorages.cpp
  1358. +++ b/src/game/SQLStorages.cpp
  1359. @@ -21,8 +21,8 @@
  1360.  #include "Database/SQLStorageImpl.h"
  1361.  #include "Database/DatabaseEnv.h"
  1362.  
  1363. -const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiiiiis";
  1364. -const char CreatureInfodstfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiiiiii";
  1365. +const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiiiiis";
  1366. +const char CreatureInfodstfmt[]="iiiiiiiiiisssiiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiiiiii";
  1367.  const char CreatureDataAddonInfofmt[]="iiibbiis";
  1368.  const char CreatureModelfmt[]="iffbii";
  1369.  const char CreatureInfoAddonInfofmt[]="iiibbiis";
  1370. diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
  1371. index 349a25f..38aea15 100644
  1372. --- a/src/game/SharedDefines.h
  1373. +++ b/src/game/SharedDefines.h
  1374. @@ -155,6 +155,17 @@ enum Powers
  1375.  
  1376.  #define MAX_POWERS                        7
  1377.  
  1378. +enum EnergyType
  1379. +{
  1380. +    ENERGY_TYPE_UNK0      = 0,                          // Possible mana or flat energy.
  1381. +    ENERGY_TYPE_UNK1      = 1,                          // 2 vehicles in 3.3.5a
  1382. +    ENERGY_TYPE_PYRITE    = 41,                         // 2 vehicles in 3.3.5a
  1383. +    ENERGY_TYPE_STEAM     = 61,                         // 9 vehicles in 3.3.5a
  1384. +    ENERGY_TYPE_OOZE      = 121,                        // 1 vehicle  in 3.3.5a
  1385. +    ENERGY_TYPE_BLOOD     = 141,                        // 1 vehicle  in 3.3.5a
  1386. +    ENERGY_TYPE_UNK142    = 142,                        // 1 vehicle  in 3.3.5a
  1387. +};
  1388. +
  1389.  enum SpellSchools
  1390.  {
  1391.      SPELL_SCHOOL_NORMAL                 = 0,
  1392. @@ -1226,6 +1237,7 @@ enum Targets
  1393.      TARGET_DYNAMIC_OBJECT_BEHIND       = 48,
  1394.      TARGET_DYNAMIC_OBJECT_LEFT_SIDE    = 49,
  1395.      TARGET_DYNAMIC_OBJECT_RIGHT_SIDE   = 50,
  1396. +    TARGET_OBJECT_AREA_SRC             = 51,
  1397.      TARGET_AREAEFFECT_GO_AROUND_DEST   = 52,                // gameobject around destination, select by spell_script_target
  1398.      TARGET_CURRENT_ENEMY_COORDINATES   = 53,                // set unit coordinates as dest, only 16 target B imlemented
  1399.      TARGET_LARGE_FRONTAL_CONE          = 54,
  1400. @@ -1255,9 +1267,28 @@ enum Targets
  1401.      TARGET_DIRECTLY_FORWARD            = 89,
  1402.      TARGET_NONCOMBAT_PET               = 90,
  1403.      TARGET_91                          = 91,
  1404. +    TARGET_93                          = 93,
  1405. +    TARGET_OWNED_VEHICLE               = 94,
  1406. +    TARGET_UNIT_DRIVER                 = 95,
  1407. +    TARGET_UNIT_PASSENGER_0            = 96,
  1408. +    TARGET_UNIT_PASSENGER_1            = 97,
  1409. +    TARGET_UNIT_PASSENGER_2            = 98,
  1410. +    TARGET_UNIT_PASSENGER_3            = 99,
  1411. +    TARGET_UNIT_PASSENGER_4            = 100,
  1412. +    TARGET_UNIT_PASSENGER_5            = 101,
  1413. +    TARGET_UNIT_PASSENGER_6            = 102,
  1414. +    TARGET_UNIT_PASSENGER_7            = 103,
  1415.      TARGET_IN_FRONT_OF_CASTER_30       = 104,
  1416. +    TARGET_105                         = 105,
  1417. +    TARGET_106                         = 106,
  1418. +    TARGET_107                         = 107,
  1419. +    TARGET_108                         = 108,
  1420. +    TARGET_109                         = 109,
  1421. +    TARGET_110                         = 110,
  1422.  };
  1423.  
  1424. +#define MAX_SPELL_TARGET               110
  1425. +
  1426.  enum SpellMissInfo
  1427.  {
  1428.      SPELL_MISS_NONE                    = 0,
  1429. @@ -1369,8 +1400,8 @@ enum GameObjectFlags
  1430.      GO_FLAG_TRIGGERED       = 0x00000040,                   //typically, summoned objects. Triggered by spell or other events
  1431.      GO_FLAG_UNK_8           = 0x00000080,
  1432.      GO_FLAG_UNK_9           = 0x00000100,                   //? Seen on type 33, possible meaning "destruct in progress"
  1433. -    GO_FLAG_UNK_10          = 0x00000200,                   //? Seen on type 33
  1434. -    GO_FLAG_UNK_11          = 0x00000400                    //? Seen on type 33, possibly meaning "destructed"
  1435. +    GO_FLAG_DAMAGED         = 0x00000200,                   //Seen on type 33
  1436. +    GO_FLAG_DESTROYED       = 0x00000400                    //Seen on type 33, meaning "destroyed"
  1437.  };
  1438.  
  1439.  enum GameObjectDynamicLowFlags
  1440. diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
  1441. index c67cf76..23866b3 100644
  1442. --- a/src/game/Spell.cpp
  1443. +++ b/src/game/Spell.cpp
  1444. @@ -43,6 +43,7 @@
  1445.  #include "VMapFactory.h"
  1446.  #include "BattleGround.h"
  1447.  #include "Util.h"
  1448. +#include "Vehicle.h"
  1449.  #include "Chat.h"
  1450.  
  1451.  #define SPELL_CHANNEL_UPDATE_INTERVAL (1 * IN_MILLISECONDS)
  1452. @@ -1995,6 +1996,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
  1453.              }
  1454.              break;
  1455.          }
  1456. +        case TARGET_OBJECT_AREA_SRC:
  1457.          case TARGET_AREAEFFECT_GO_AROUND_DEST:
  1458.          {
  1459.              // It may be possible to fill targets for some spell effects
  1460. @@ -2003,20 +2005,49 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
  1461.  
  1462.              // Some spells untested, for affected GO type 33. May need further adjustments for spells related.
  1463.  
  1464. -            SpellScriptTargetBounds bounds = sSpellMgr.GetSpellScriptTargetBounds(m_spellInfo->Id);
  1465. +            float x, y, z;
  1466. +            if (targetMode == TARGET_OBJECT_AREA_SRC)
  1467. +            {
  1468. +                if (m_targets.m_targetMask & TARGET_FLAG_SOURCE_LOCATION)
  1469. +                {
  1470. +                    x = m_targets.m_srcX;
  1471. +                    y = m_targets.m_srcY;
  1472. +                    z = m_targets.m_srcZ;
  1473. +                }
  1474. +                else
  1475. +                    break;
  1476. +            }
  1477. +            else if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
  1478. +            {
  1479. +                x = m_targets.m_destX;
  1480. +                y = m_targets.m_destY;
  1481. +                z = m_targets.m_destZ;
  1482. +            }
  1483. +            else
  1484. +                break;
  1485.  
  1486. +            SpellScriptTargetBounds bounds = sSpellMgr.GetSpellScriptTargetBounds(m_spellInfo->Id);
  1487.              std::list<GameObject*> tempTargetGOList;
  1488.  
  1489. -            for(SpellScriptTarget::const_iterator i_spellST = bounds.first; i_spellST != bounds.second; ++i_spellST)
  1490. +            if (bounds.first !=  bounds.second)
  1491.              {
  1492. -                if (i_spellST->second.type == SPELL_TARGET_TYPE_GAMEOBJECT)
  1493. +                for(SpellScriptTarget::const_iterator i_spellST = bounds.first; i_spellST != bounds.second; ++i_spellST)
  1494.                  {
  1495. -                    // search all GO's with entry, within range of m_destN
  1496. -                    MaNGOS::GameObjectEntryInPosRangeCheck go_check(*m_caster, i_spellST->second.targetEntry, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, radius);
  1497. -                    MaNGOS::GameObjectListSearcher<MaNGOS::GameObjectEntryInPosRangeCheck> checker(tempTargetGOList, go_check);
  1498. -                    Cell::VisitGridObjects(m_caster, checker, radius);
  1499. +                    if (i_spellST->second.type == SPELL_TARGET_TYPE_GAMEOBJECT)
  1500. +                    {
  1501. +                        // search all GO's with entry, within range of m_destN
  1502. +                        MaNGOS::GameObjectEntryInPosRangeCheck go_check(*m_caster, i_spellST->second.targetEntry, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, radius);
  1503. +                        MaNGOS::GameObjectListSearcher<MaNGOS::GameObjectEntryInPosRangeCheck> checker(tempTargetGOList, go_check);
  1504. +                        Cell::VisitGridObjects(m_caster, checker, radius);
  1505. +                    }
  1506.                  }
  1507.              }
  1508. +            else
  1509. +            {
  1510. +                MaNGOS::GameObjectInRangeCheck check(m_caster, x, y, z, radius + 15.0f);
  1511. +                MaNGOS::GameObjectListSearcher<MaNGOS::GameObjectInRangeCheck> searcher(tempTargetGOList, check);
  1512. +                Cell::VisitAllObjects(m_caster, searcher, radius);
  1513. +            }
  1514.  
  1515.              if (!tempTargetGOList.empty())
  1516.              {
  1517. @@ -2101,6 +2132,23 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
  1518.                  if( target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->IsPet() && ((Pet*)target)->getPetType() == MINI_PET)
  1519.                      targetUnitMap.push_back(target);
  1520.              break;
  1521. +        case TARGET_OWNED_VEHICLE:
  1522. +            if (VehicleKit* vehicle = m_caster->GetVehicle())
  1523. +                if (Unit* target = vehicle->GetBase())
  1524. +                    targetUnitMap.push_back(target);
  1525. +            break;
  1526. +        case TARGET_UNIT_PASSENGER_0:
  1527. +        case TARGET_UNIT_PASSENGER_1:
  1528. +        case TARGET_UNIT_PASSENGER_2:
  1529. +        case TARGET_UNIT_PASSENGER_3:
  1530. +        case TARGET_UNIT_PASSENGER_4:
  1531. +        case TARGET_UNIT_PASSENGER_5:
  1532. +        case TARGET_UNIT_PASSENGER_6:
  1533. +        case TARGET_UNIT_PASSENGER_7:
  1534. +            if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->GetObjectGuid().IsVehicle())
  1535. +                if (Unit *unit = m_caster->GetVehicleKit()->GetPassenger(targetMode - TARGET_UNIT_PASSENGER_0))
  1536. +                    targetUnitMap.push_back(unit);
  1537. +            break;
  1538.          case TARGET_CASTER_COORDINATES:
  1539.          {
  1540.              // Check original caster is GO - set its coordinates as dst cast
  1541. @@ -3398,8 +3446,8 @@ void Spell::update(uint32 difftime)
  1542.          return;
  1543.      }
  1544.  
  1545. -    // check if the player caster has moved before the spell finished
  1546. -    if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) &&
  1547. +    // check if the player caster has moved before the spell finished (exclude casting on vehicles)
  1548. +    if (!m_caster->GetVehicle() && (m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) &&
  1549.          (m_castPositionX != m_caster->GetPositionX() || m_castPositionY != m_caster->GetPositionY() || m_castPositionZ != m_caster->GetPositionZ()) &&
  1550.          (m_spellInfo->Effect[EFFECT_INDEX_0] != SPELL_EFFECT_STUCK || !((Player*)m_caster)->m_movementInfo.HasMovementFlag(MOVEFLAG_FALLINGFAR)))
  1551.      {
  1552. @@ -4859,8 +4907,15 @@ SpellCastResult Spell::CheckCast(bool strict)
  1553.      if (locRes != SPELL_CAST_OK)
  1554.          return locRes;
  1555.  
  1556. +    bool castOnVehicleAllowed = false;
  1557. +
  1558. +    if (m_caster->GetVehicle())
  1559. +        if ( VehicleSeatEntry const* seatInfo = m_caster->GetVehicle()->GetSeatInfo(m_caster))
  1560. +            if (seatInfo->m_flags & SEAT_FLAG_CAN_CAST || seatInfo->m_flags & SEAT_FLAG_CAN_ATTACK)
  1561. +                castOnVehicleAllowed = true;
  1562. +
  1563.      // not let players cast spells at mount (and let do it to creatures)
  1564. -    if (m_caster->IsMounted() && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell &&
  1565. +    if ((m_caster->IsMounted() || (m_caster->GetVehicle() && !castOnVehicleAllowed)) && m_caster->GetTypeId() == TYPEID_PLAYER && !m_IsTriggeredSpell &&
  1566.          !IsPassiveSpell(m_spellInfo) && !(m_spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_MOUNTED))
  1567.      {
  1568.          if (m_caster->IsTaxiFlying())
  1569. @@ -5732,26 +5787,45 @@ SpellCastResult Spell::CheckPetCast(Unit* target)
  1570.  
  1571.          if(_target)                                         //for target dead/target not valid
  1572.          {
  1573. -            if (!_target->isTargetableForAttack())
  1574. -                return SPELL_FAILED_BAD_TARGETS;            // guessed error
  1575. -
  1576. -            if(IsPositiveSpell(m_spellInfo->Id))
  1577. +            if(IsPositiveSpell(m_spellInfo->Id) && !IsDispelSpell(m_spellInfo))
  1578.              {
  1579.                  if(m_caster->IsHostileTo(_target))
  1580. +                {
  1581. +                    DEBUG_LOG("Charmed creature attempt to cast positive spell %d, but target (guid %u) is hostile",m_spellInfo->Id, target->GetObjectGuid().GetRawValue());
  1582.                      return SPELL_FAILED_BAD_TARGETS;
  1583. +                }
  1584. +            }
  1585. +            else if (!_target->isTargetableForAttack() || (!_target->isVisibleForOrDetect(m_caster,m_caster,true) && !m_IsTriggeredSpell))
  1586. +            {
  1587. +                DEBUG_LOG("Charmed creature attempt to cast spell %d, but target (guid %u) is not targetable or not detectable",m_spellInfo->Id,target->GetObjectGuid().GetRawValue());
  1588. +                return SPELL_FAILED_BAD_TARGETS;            // guessed error
  1589.              }
  1590.              else
  1591.              {
  1592. -                bool duelvsplayertar = false;
  1593. +                bool dualEffect = false;
  1594.                  for(int j = 0; j < MAX_EFFECT_INDEX; ++j)
  1595.                  {
  1596. -                                                            //TARGET_DUELVSPLAYER is positive AND negative
  1597. -                    duelvsplayertar |= (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DUELVSPLAYER);
  1598. +                                                            // This effects is positive AND negative. Need for vehicles cast.
  1599. +                    dualEffect |= (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DUELVSPLAYER
  1600. +                                   || m_spellInfo->EffectImplicitTargetA[j] == TARGET_IN_FRONT_OF_CASTER_30
  1601. +                                   || m_spellInfo->EffectImplicitTargetA[j] == TARGET_MASTER
  1602. +                                   || m_spellInfo->EffectImplicitTargetA[j] == TARGET_IN_FRONT_OF_CASTER
  1603. +                                   || m_spellInfo->EffectImplicitTargetA[j] == TARGET_EFFECT_SELECT
  1604. +                                   || m_spellInfo->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE
  1605. +                                   || m_spellInfo->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES);
  1606.                  }
  1607. -                if(m_caster->IsFriendlyTo(target) && !duelvsplayertar)
  1608. +                if (m_caster->IsFriendlyTo(_target) && !(!m_caster->GetCharmerOrOwner() || !m_caster->GetCharmerOrOwner()->IsFriendlyTo(_target))
  1609. +                     && !dualEffect && !IsDispelSpell(m_spellInfo) && !m_caster->GetVehicleKit())
  1610.                  {
  1611. +                    DEBUG_LOG("Charmed creature attempt to cast spell %d, but target (guid %u) is not valid",m_spellInfo->Id,_target->GetObjectGuid().GetRawValue());
  1612.                      return SPELL_FAILED_BAD_TARGETS;
  1613.                  }
  1614. +
  1615. +                if (m_caster->GetObjectGuid() == _target->GetObjectGuid() && dualEffect && !IsPositiveSpell(m_spellInfo->Id))
  1616. +                {
  1617. +                    DEBUG_LOG("Charmed creature %u attempt to cast negative spell %d on self",_target->GetObjectGuid().GetRawValue(),m_spellInfo->Id);
  1618. +//                    return SPELL_FAILED_BAD_TARGETS;
  1619. +                }
  1620.              }
  1621.          }
  1622.                                                              //cooldown
  1623. @@ -6769,7 +6843,7 @@ bool Spell::CheckTarget( Unit* target, SpellEffectIndex eff )
  1624.      if (target != m_caster && target->GetCharmerOrOwnerGuid() != m_caster->GetObjectGuid())
  1625.      {
  1626.          // any unattackable target skipped
  1627. -        if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
  1628. +        if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) && target->GetObjectGuid() != m_caster->GetCharmerOrOwnerGuid())
  1629.              return false;
  1630.  
  1631.          // unselectable targets skipped in all cases except TARGET_SCRIPT targeting
  1632. @@ -6785,6 +6859,13 @@ bool Spell::CheckTarget( Unit* target, SpellEffectIndex eff )
  1633.              return false;
  1634.      }
  1635.  
  1636. +    if (target != m_caster && m_caster->GetCharmerOrOwnerGuid() == target->GetObjectGuid())
  1637. +    {
  1638. +        if (m_spellInfo->EffectImplicitTargetA[eff] == TARGET_MASTER ||
  1639. +            m_spellInfo->EffectImplicitTargetB[eff] == TARGET_MASTER)
  1640. +            return true;
  1641. +    }
  1642. +
  1643.      // Check player targets and remove if in GM mode or GM invisibility (for not self casting case)
  1644.      if( target != m_caster && target->GetTypeId() == TYPEID_PLAYER)
  1645.      {
  1646. diff --git a/src/game/Spell.h b/src/game/Spell.h
  1647. index 6fff7e2..d46b907 100644
  1648. --- a/src/game/Spell.h
  1649. +++ b/src/game/Spell.h
  1650. @@ -340,6 +340,9 @@ class Spell
  1651.          void EffectActivateRune(SpellEffectIndex eff_idx);
  1652.  
  1653.          void EffectTeachTaxiNode(SpellEffectIndex eff_idx);
  1654. +        void EffectWMODamage(SpellEffectIndex eff_idx);
  1655. +        void EffectWMORepair(SpellEffectIndex eff_idx);
  1656. +        void EffectWMOChange(SpellEffectIndex eff_idx);
  1657.          void EffectTitanGrip(SpellEffectIndex eff_idx);
  1658.          void EffectEnchantItemPrismatic(SpellEffectIndex eff_idx);
  1659.          void EffectPlayMusic(SpellEffectIndex eff_idx);
  1660. @@ -392,6 +395,7 @@ class Spell
  1661.          void DoSummonGuardian(SpellEffectIndex eff_idx, uint32 forceFaction = 0);
  1662.          void DoSummonTotem(SpellEffectIndex eff_idx, uint8 slot_dbc = 0);
  1663.          void DoSummonCritter(SpellEffectIndex eff_idx, uint32 forceFaction = 0);
  1664. +        void DoSummonVehicle(SpellEffectIndex eff_idx, uint32 forceFaction = 0);
  1665.  
  1666.          void WriteSpellGoTargets(WorldPacket* data);
  1667.          void WriteAmmoToPacket(WorldPacket* data);
  1668. diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
  1669. index 6b39004..bcb5ff6 100644
  1670. --- a/src/game/SpellAuras.cpp
  1671. +++ b/src/game/SpellAuras.cpp
  1672. @@ -346,7 +346,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
  1673.      &Aura::HandleAuraAddMechanicAbilities,                  //293 SPELL_AURA_ADD_MECHANIC_ABILITIES  replaces target's action bars with a predefined spellset
  1674.      &Aura::HandleAuraStopNaturalManaRegen,                  //294 SPELL_AURA_STOP_NATURAL_MANA_REGEN implemented in Player:Regenerate
  1675.      &Aura::HandleUnused,                                    //295 unused (3.2.2a)
  1676. -    &Aura::HandleNULL,                                      //296 2 spells
  1677. +    &Aura::HandleAuraSetVehicle,                            //296 SPELL_AURA_SET_VEHICLE_ID sets vehicle on target
  1678.      &Aura::HandleNULL,                                      //297 1 spell (counter spell school?)
  1679.      &Aura::HandleUnused,                                    //298 unused (3.2.2a)
  1680.      &Aura::HandleUnused,                                    //299 unused (3.2.2a)
  1681. @@ -3115,7 +3115,7 @@ void Aura::HandleAuraMounted(bool apply, bool Real)
  1682.          if (minfo)
  1683.              display_id = minfo->modelid;
  1684.  
  1685. -        target->Mount(display_id, GetId());
  1686. +        target->Mount(display_id, GetId(), ci->vehicleId, GetMiscValue());
  1687.      }
  1688.      else
  1689.      {
  1690. @@ -3949,7 +3949,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
  1691.          {
  1692.              ((Creature*)target)->AIM_Initialize();
  1693.          }
  1694. -        else if(target->GetTypeId() == TYPEID_PLAYER)
  1695. +        else if(target->GetTypeId() == TYPEID_PLAYER && !target->GetVehicle())
  1696.          {
  1697.              ((Player*)target)->SetClientControl(target, 0);
  1698.          }
  1699. @@ -3982,7 +3982,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
  1700.  
  1701.          target->SetCharmerGuid(ObjectGuid());
  1702.  
  1703. -        if(target->GetTypeId() == TYPEID_PLAYER)
  1704. +        if(target->GetTypeId() == TYPEID_PLAYER && !target->GetVehicle())
  1705.          {
  1706.              ((Player*)target)->setFactionForRace(target->getRace());
  1707.              ((Player*)target)->SetClientControl(target, 1);
  1708. @@ -4359,7 +4359,7 @@ void Aura::HandleAuraModStun(bool apply, bool Real)
  1709.          target->clearUnitState(UNIT_STAT_STUNNED);
  1710.          target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
  1711.  
  1712. -        if(!target->hasUnitState(UNIT_STAT_ROOT))         // prevent allow move if have also root effect
  1713. +        if(!target->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_ON_VEHICLE))       // prevent allow move if have also root effect
  1714.          {
  1715.              if(target->getVictim() && target->isAlive())
  1716.                  target->SetTargetGuid(target->getVictim()->GetObjectGuid());
  1717. @@ -4595,10 +4595,13 @@ void Aura::HandleAuraModRoot(bool apply, bool Real)
  1718.  
  1719.          if(target->GetTypeId() == TYPEID_PLAYER)
  1720.          {
  1721. -            WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
  1722. -            data << target->GetPackGUID();
  1723. -            data << (uint32)2;
  1724. -            target->SendMessageToSet(&data, true);
  1725. +            if(!target->hasUnitState(UNIT_STAT_ON_VEHICLE))
  1726. +            {
  1727. +                WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
  1728. +                data << target->GetPackGUID();
  1729. +                data << uint32(2);
  1730. +                target->SendMessageToSet(&data, true);
  1731. +            }
  1732.  
  1733.              //Clear unit movement flags
  1734.              ((Player*)target)->m_movementInfo.SetMovementFlags(MOVEFLAG_NONE);
  1735. @@ -4637,7 +4640,7 @@ void Aura::HandleAuraModRoot(bool apply, bool Real)
  1736.  
  1737.          target->clearUnitState(UNIT_STAT_ROOT);
  1738.  
  1739. -        if(!target->hasUnitState(UNIT_STAT_STUNNED))      // prevent allow move if have also stun effect
  1740. +        if(!target->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ON_VEHICLE))      // prevent allow move if have also stun effect
  1741.          {
  1742.              if(target->getVictim() && target->isAlive())
  1743.                  target->SetTargetGuid(target->getVictim()->GetObjectGuid());
  1744. @@ -8150,14 +8153,15 @@ void Aura::HandleAuraControlVehicle(bool apply, bool Real)
  1745.          if (caster->GetTypeId() == TYPEID_PLAYER)
  1746.              ((Player*)caster)->RemovePet(PET_SAVE_AS_CURRENT);
  1747.  
  1748. -        //caster->EnterVehicle(target);
  1749. +        caster->EnterVehicle(target->GetVehicleKit());
  1750.      }
  1751.      else
  1752.      {
  1753.          // some SPELL_AURA_CONTROL_VEHICLE auras have a dummy effect on the player - remove them
  1754.          caster->RemoveAurasDueToSpell(GetId());
  1755.  
  1756. -        //caster->ExitVehicle();
  1757. +        if (caster->GetVehicleKit() == target->GetVehicleKit())
  1758. +            caster->ExitVehicle();
  1759.  
  1760.          if (caster->GetTypeId() == TYPEID_PLAYER)
  1761.              ((Player*)caster)->ResummonPetTemporaryUnSummonedIfAny();
  1762. @@ -9776,3 +9780,38 @@ void SpellAuraHolder::UnregisterSingleCastHolder()
  1763.          m_isSingleTarget = false;
  1764.      }
  1765.  }
  1766. +
  1767. +void Aura::HandleAuraSetVehicle(bool apply, bool real)
  1768. +{
  1769. +    if (!real)
  1770. +        return;
  1771. +
  1772. +    Unit* target = GetTarget();
  1773. +
  1774. +    if (target->GetTypeId() != TYPEID_PLAYER || !target->IsInWorld())
  1775. +        return;
  1776. +
  1777. +    uint32 vehicleId = GetMiscValue();
  1778. +
  1779. +    if (vehicleId == 0)
  1780. +        return;
  1781. +
  1782. +    if (apply)
  1783. +    {
  1784. +        target->SetVehicleId(vehicleId);
  1785. +    }
  1786. +    else
  1787. +        if (target->GetVehicleKit())
  1788. +            target->RemoveVehicleKit();
  1789. +
  1790. +    WorldPacket data(SMSG_SET_VEHICLE_REC_ID, target->GetPackGUID().size()+4);
  1791. +    data << target->GetPackGUID();
  1792. +    data << uint32(apply ? vehicleId : 0);
  1793. +    target->SendMessageToSet(&data, true);
  1794. +
  1795. +    if (apply)
  1796. +    {
  1797. +        data.Initialize(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
  1798. +        ((Player*)target)->GetSession()->SendPacket(&data);
  1799. +    }
  1800. +}
  1801. diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h
  1802. index e7bc4ca..99b5690 100644
  1803. --- a/src/game/SpellAuras.h
  1804. +++ b/src/game/SpellAuras.h
  1805. @@ -352,6 +352,7 @@ class MANGOS_DLL_SPEC Aura
  1806.          void HandleModSpellHealingPercentFromStat(bool apply, bool Real);
  1807.          void HandleAuraModDispelResist(bool apply, bool Real);
  1808.          void HandleAuraControlVehicle(bool apply, bool Real);
  1809. +        void HandleAuraSetVehicle(bool apply, bool Real);
  1810.          void HandleModSpellDamagePercentFromAttackPower(bool apply, bool Real);
  1811.          void HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real);
  1812.          void HandleAuraModPacifyAndSilence(bool Apply, bool Real);
  1813. diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
  1814. index f4832d9..155087b 100644
  1815. --- a/src/game/SpellEffects.cpp
  1816. +++ b/src/game/SpellEffects.cpp
  1817. @@ -147,9 +147,9 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
  1818.      &Spell::EffectStuck,                                    // 84 SPELL_EFFECT_STUCK
  1819.      &Spell::EffectSummonPlayer,                             // 85 SPELL_EFFECT_SUMMON_PLAYER
  1820.      &Spell::EffectActivateObject,                           // 86 SPELL_EFFECT_ACTIVATE_OBJECT
  1821. -    &Spell::EffectNULL,                                     // 87 SPELL_EFFECT_WMO_DAMAGE (57 spells in 3.3.2)
  1822. -    &Spell::EffectNULL,                                     // 88 SPELL_EFFECT_WMO_REPAIR (2 spells in 3.3.2)
  1823. -    &Spell::EffectNULL,                                     // 89 SPELL_EFFECT_WMO_CHANGE (7 spells in 3.3.2)
  1824. +    &Spell::EffectWMODamage,                                // 87 SPELL_EFFECT_WMO_DAMAGE (57 spells in 3.3.2)
  1825. +    &Spell::EffectWMORepair,                                // 88 SPELL_EFFECT_WMO_REPAIR (2 spells in 3.3.2)
  1826. +    &Spell::EffectWMOChange,                                // 89 SPELL_EFFECT_WMO_CHANGE (7 spells in 3.3.2)
  1827.      &Spell::EffectKillCreditPersonal,                       // 90 SPELL_EFFECT_KILL_CREDIT_PERSONAL     Kill credit but only for single person
  1828.      &Spell::EffectUnused,                                   // 91 SPELL_EFFECT_THREAT_ALL               one spell: zzOLDBrainwash
  1829.      &Spell::EffectEnchantHeldItem,                          // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
  1830. @@ -4605,6 +4605,7 @@ void Spell::EffectSummonType(SpellEffectIndex eff_idx)
  1831.                  case UNITNAME_SUMMON_TITLE_MOUNT:
  1832.                      // TODO
  1833.                      // EffectSummonVehicle(i);
  1834. +                    DoSummonVehicle(eff_idx, summon_prop->FactionId);
  1835.                      break;
  1836.                  default:
  1837.                      sLog.outError("EffectSummonType: Unhandled summon title %u", summon_prop->Title);
  1838. @@ -4631,10 +4632,11 @@ void Spell::EffectSummonType(SpellEffectIndex eff_idx)
  1839.              break;
  1840.          }
  1841.          case SUMMON_PROP_GROUP_VEHICLE:
  1842. +        case SUMMON_PROP_GROUP_UNCONTROLLABLE_VEHICLE:
  1843.          {
  1844.              // TODO
  1845.              // EffectSummonVehicle(i);
  1846. -            sLog.outDebug("EffectSummonType: Unhandled summon group type SUMMON_PROP_GROUP_VEHICLE(%u)", summon_prop->Group);
  1847. +            DoSummonVehicle(eff_idx, summon_prop->FactionId);
  1848.              break;
  1849.          }
  1850.          default:
  1851. @@ -5176,6 +5178,68 @@ void Spell::DoSummonGuardian(SpellEffectIndex eff_idx, uint32 forceFaction)
  1852.      }
  1853.  }
  1854.  
  1855. +void Spell::DoSummonVehicle(SpellEffectIndex eff_idx, uint32 forceFaction)
  1856. +{
  1857. +    if (!m_caster)
  1858. +        return;
  1859. +
  1860. +    if (m_caster->hasUnitState(UNIT_STAT_ON_VEHICLE))
  1861. +    {
  1862. +        if (m_spellInfo->Attributes & SPELL_ATTR_UNK7)
  1863. +            m_caster->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE);
  1864. +        else
  1865. +            return;
  1866. +    }
  1867. +
  1868. +    uint32 vehicle_entry = m_spellInfo->EffectMiscValue[eff_idx];
  1869. +
  1870. +    if (!vehicle_entry)
  1871. +        return;
  1872. +
  1873. +    SpellEntry const* m_mountspell = sSpellStore.LookupEntry(m_spellInfo->EffectBasePoints[eff_idx] != 0 ? m_spellInfo->CalculateSimpleValue(eff_idx) : 46598);
  1874. +
  1875. +    if (!m_mountspell)
  1876. +        m_mountspell = sSpellStore.LookupEntry(46598);
  1877. +    // Used BasePoint mount spell, if not present - hardcoded (by Blzz).
  1878. +
  1879. +    float px, py, pz;
  1880. +    // If dest location present
  1881. +    if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
  1882. +    {
  1883. +        px = m_targets.m_destX;
  1884. +        py = m_targets.m_destY;
  1885. +        pz = m_targets.m_destZ;
  1886. +    }
  1887. +    // Summon if dest location not present near caster
  1888. +    else
  1889. +        m_caster->GetClosePoint(px, py, pz,m_caster->GetObjectBoundingRadius());
  1890. +
  1891. +    TempSummonType summonType = (GetSpellDuration(m_spellInfo) == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
  1892. +
  1893. +    Creature* vehicle = m_caster->SummonCreature(vehicle_entry,px,py,pz,m_caster->GetOrientation(),summonType,GetSpellDuration(m_spellInfo),true);
  1894. +
  1895. +    if (vehicle && !vehicle->GetObjectGuid().IsVehicle())
  1896. +    {
  1897. +        sLog.outError("DoSommonVehicle: Creature (guidlow %d, entry %d) summoned, but this is not vehicle. Correct VehicleId in creature_template.", vehicle->GetGUIDLow(), vehicle->GetEntry());
  1898. +        vehicle->ForcedDespawn();
  1899. +        return;
  1900. +    }
  1901. +
  1902. +    if (vehicle)
  1903. +    {
  1904. +        vehicle->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
  1905. +        vehicle->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
  1906. +        m_caster->CastSpell(vehicle, m_mountspell, true);
  1907. +        DEBUG_LOG("Caster (guidlow %d) summon vehicle (guidlow %d, entry %d) and mounted with spell %d ", m_caster->GetGUIDLow(), vehicle->GetGUIDLow(), vehicle->GetEntry(), m_mountspell->Id);
  1908. +
  1909. +        // Notify Summoner
  1910. +        if (m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->AI())
  1911. +            ((Creature*)m_caster)->AI()->JustSummoned(vehicle);
  1912. +    }
  1913. +    else
  1914. +        sLog.outError("Vehicle (guidlow %d, entry %d) NOT summoned by undefined reason. ", vehicle->GetGUIDLow(), vehicle->GetEntry());
  1915. +}
  1916. +
  1917.  void Spell::EffectTeleUnitsFaceCaster(SpellEffectIndex eff_idx)
  1918.  {
  1919.      if (!unitTarget)
  1920. @@ -9203,3 +9267,85 @@ void Spell::EffectCancelAura(SpellEffectIndex eff_idx)
  1921.  
  1922.      unitTarget->RemoveAurasDueToSpell(spellId);
  1923.  }
  1924. +
  1925. +void Spell::EffectWMODamage(SpellEffectIndex eff_idx)
  1926. +{
  1927. +    if (!gameObjTarget || gameObjTarget->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING || !gameObjTarget->GetHealth())
  1928. +    {
  1929. +        DEBUG_LOG( "Spell::EffectWMODamage called, but no valid targets. Spell ID %u", m_spellInfo->Id );
  1930. +        return;
  1931. +    }
  1932. +
  1933. +    Unit *caster = m_originalCaster;
  1934. +
  1935. +    if (!caster)
  1936. +        return;
  1937. +
  1938. +    DEBUG_LOG( "Spell::EffectWMODamage,  spell ID %u, object %u, damage %u", m_spellInfo->Id,gameObjTarget->GetEntry(),uint32(damage));
  1939. +
  1940. +    gameObjTarget->DamageTaken(caster, uint32(damage));
  1941. +
  1942. +    WorldPacket data(SMSG_DESTRUCTIBLE_BUILDING_DAMAGE, 8+8+8+4+4);
  1943. +    data << gameObjTarget->GetPackGUID();
  1944. +    data << caster->GetPackGUID();
  1945. +
  1946. +    if (Unit *who = caster->GetCharmerOrOwner()) //check for pet / vehicle
  1947. +        data << who->GetPackGUID();
  1948. +    else
  1949. +        data << caster->GetPackGUID();
  1950. +
  1951. +    data << uint32(damage);
  1952. +    data << uint32(m_spellInfo->Id);
  1953. +
  1954. +    gameObjTarget->SendMessageToSet(&data, false);
  1955. +}
  1956. +
  1957. +void Spell::EffectWMORepair(SpellEffectIndex eff_idx)
  1958. +{
  1959. +    if (gameObjTarget && gameObjTarget->GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
  1960. +    {
  1961. +        DEBUG_LOG( "Spell::EffectWMORepair,  spell ID %u, object %u", m_spellInfo->Id,gameObjTarget->GetEntry());
  1962. +        gameObjTarget->Rebuild(m_caster);
  1963. +    }
  1964. +    else
  1965. +        DEBUG_LOG( "Spell::EffectWMORepair called, but no valid targets. Spell ID %u", m_spellInfo->Id);
  1966. +
  1967. +}
  1968. +
  1969. +void Spell::EffectWMOChange(SpellEffectIndex eff_idx)
  1970. +{
  1971. +    if (gameObjTarget && gameObjTarget->GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
  1972. +    {
  1973. +        DEBUG_LOG( "Spell::EffectWMOChange,  spell ID %u, object %u, command %u", m_spellInfo->Id,gameObjTarget->GetEntry(), m_spellInfo->EffectMiscValue[eff_idx]);
  1974. +
  1975. +        Unit* caster = m_originalCaster;
  1976. +
  1977. +        if (!caster)
  1978. +            return;
  1979. +
  1980. +        switch (m_spellInfo->EffectMiscValue[eff_idx])
  1981. +        {
  1982. +            case 0: // intact
  1983. +                if (gameObjTarget->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED))
  1984. +                    gameObjTarget->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED);
  1985. +                if (gameObjTarget->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED))
  1986. +                    gameObjTarget->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED);
  1987. +                break;
  1988. +            case 1: // damaged
  1989. +                gameObjTarget->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED);
  1990. +                break;
  1991. +            case 2: // destroyed
  1992. +                gameObjTarget->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED);
  1993. +                break;
  1994. +            case 3: // rebuild
  1995. +                gameObjTarget->Rebuild(caster);
  1996. +                break;
  1997. +            default:
  1998. +                DEBUG_LOG( "Spell::EffectWMOChange,  spell ID %u with defined change value %u", m_spellInfo->Id,m_spellInfo->EffectMiscValue[eff_idx]);
  1999. +                break;
  2000. +        }
  2001. +    }
  2002. +    else
  2003. +        DEBUG_LOG( "Spell::EffectWMORepair called, but no valid targets. Spell ID %u", m_spellInfo->Id);
  2004. +
  2005. +}
  2006. diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp
  2007. index dbaa32d..bb3a295 100644
  2008. --- a/src/game/SpellHandler.cpp
  2009. +++ b/src/game/SpellHandler.cpp
  2010. @@ -343,8 +343,8 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
  2011.      recvPacket >> unk_flags;                                // flags (if 0x02 - some additional data are received)
  2012.  
  2013.      // ignore for remote control state (for player case)
  2014. -    Unit* mover = _player->GetMover();
  2015. -    if (mover != _player && mover->GetTypeId()==TYPEID_PLAYER)
  2016. +    Unit* _mover = GetPlayer()->GetMover();
  2017. +    if (_mover != GetPlayer() && _mover->GetTypeId()==TYPEID_PLAYER)
  2018.      {
  2019.          recvPacket.rpos(recvPacket.wpos());                 // prevent spam at ignore packet
  2020.          return;
  2021. @@ -362,6 +362,25 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
  2022.          return;
  2023.      }
  2024.  
  2025. +    //  Players on vehicles may cast many simple spells (like knock) from self
  2026. +
  2027. +    Unit* mover = NULL;
  2028. +
  2029. +    if (spellInfo->AttributesEx6 & SPELL_ATTR_EX6_UNK12 && _mover->IsCharmerOrOwnerPlayerOrPlayerItself())
  2030. +        mover = _mover->GetCharmerOrOwnerPlayerOrPlayerItself();
  2031. +    else
  2032. +        mover = _mover;
  2033. +
  2034. +    // casting own spells on some vehicles
  2035. +    if (mover->GetObjectGuid().IsVehicle() && mover->GetCharmerOrOwnerPlayerOrPlayerItself())
  2036. +    {
  2037. +        Player *plr = mover->GetCharmerOrOwnerPlayerOrPlayerItself();
  2038. +        if (mover->GetVehicleKit()->GetSeatInfo(plr) &&
  2039. +           (mover->GetVehicleKit()->GetSeatInfo(plr)->m_flags & SEAT_FLAG_CAN_ATTACK ||
  2040. +            mover->GetVehicleKit()->GetSeatInfo(plr)->m_flags & SEAT_FLAG_CAN_CAST ))
  2041. +            mover = plr;
  2042. +    }
  2043. +
  2044.      if (mover->GetTypeId()==TYPEID_PLAYER)
  2045.      {
  2046.          // not have spell in spellbook or spell passive and not casted by client
  2047. @@ -604,11 +623,11 @@ void WorldSession::HandleSpellClick( WorldPacket & recv_data )
  2048.      ObjectGuid guid;
  2049.      recv_data >> guid;
  2050.  
  2051. -    if (_player->isInCombat())                              // client prevent click and set different icon at combat state
  2052. +    if (_player->isInCombat() && !guid.IsVehicle())         // client prevent click and set different icon at combat state
  2053.          return;
  2054.  
  2055.      Creature *unit = _player->GetMap()->GetAnyTypeCreature(guid);
  2056. -    if (!unit || unit->isInCombat())                        // client prevent click and set different icon at combat state
  2057. +    if (!unit)
  2058.          return;
  2059.  
  2060.      SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(unit->GetEntry());
  2061. diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
  2062. index 1f8630d..2ea8e22 100644
  2063. --- a/src/game/SpellMgr.cpp
  2064. +++ b/src/game/SpellMgr.cpp
  2065. @@ -3216,6 +3216,8 @@ void SpellMgr::LoadSpellScriptTarget()
  2066.                  spellProto->EffectImplicitTargetB[i] == TARGET_AREAEFFECT_INSTANT ||
  2067.                  spellProto->EffectImplicitTargetA[i] == TARGET_AREAEFFECT_CUSTOM ||
  2068.                  spellProto->EffectImplicitTargetB[i] == TARGET_AREAEFFECT_CUSTOM ||
  2069. +                spellProto->EffectImplicitTargetA[i] == TARGET_OBJECT_AREA_SRC ||
  2070. +                spellProto->EffectImplicitTargetB[i] == TARGET_OBJECT_AREA_SRC ||
  2071.                  spellProto->EffectImplicitTargetA[i] == TARGET_AREAEFFECT_GO_AROUND_DEST ||
  2072.                  spellProto->EffectImplicitTargetB[i] == TARGET_AREAEFFECT_GO_AROUND_DEST)
  2073.              {
  2074. @@ -3480,7 +3482,7 @@ bool SpellMgr::LoadPetDefaultSpells_helper(CreatureInfo const* cInfo, PetDefault
  2075.  
  2076.  void SpellMgr::LoadPetDefaultSpells()
  2077.  {
  2078. -    MANGOS_ASSERT(MAX_CREATURE_SPELL_DATA_SLOT==CREATURE_MAX_SPELLS);
  2079. +    MANGOS_ASSERT(MAX_CREATURE_SPELL_DATA_SLOT <= CREATURE_MAX_SPELLS);
  2080.  
  2081.      mPetDefaultSpellsMap.clear();
  2082.  
  2083. diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
  2084. index 6da2665..835cee7 100644
  2085. --- a/src/game/Unit.cpp
  2086. +++ b/src/game/Unit.cpp
  2087. @@ -40,6 +40,7 @@
  2088.  #include "Util.h"
  2089.  #include "Totem.h"
  2090.  #include "Vehicle.h"
  2091. +#include "Transports.h"
  2092.  #include "BattleGround.h"
  2093.  #include "InstanceData.h"
  2094.  #include "MapPersistentStateMgr.h"
  2095. @@ -264,6 +265,11 @@ Unit::Unit() :
  2096.      // remove aurastates allowing special moves
  2097.      for(int i=0; i < MAX_REACTIVE; ++i)
  2098.          m_reactiveTimer[i] = 0;
  2099. +
  2100. +    m_transport = NULL;
  2101. +
  2102. +    m_pVehicle = NULL;
  2103. +    m_pVehicleKit = NULL;
  2104.  }
  2105.  
  2106.  Unit::~Unit()
  2107. @@ -771,6 +777,13 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
  2108.                  cVictim->AllLootRemovedFromCorpse();
  2109.              }
  2110.  
  2111. +            // if vehicle and has passengers - remove his
  2112. +            if (cVictim->GetObjectGuid().IsVehicle())
  2113. +            {
  2114. +                if(cVictim->GetVehicleKit())
  2115. +                    cVictim->GetVehicleKit()->RemoveAllPassengers();
  2116. +            }
  2117. +
  2118.              // Call creature just died function
  2119.              if (cVictim->AI())
  2120.                  cVictim->AI()->JustDied(this);
  2121. @@ -5557,8 +5570,10 @@ bool Unit::Attack(Unit *victim, bool meleeAttack)
  2122.      if(!isAlive() || !victim->IsInWorld() || !victim->isAlive())
  2123.          return false;
  2124.  
  2125. -    // player cannot attack in mount state
  2126. -    if(GetTypeId()==TYPEID_PLAYER && IsMounted())
  2127. +    // player cannot attack while mounted or in vehicle (exclude special vehicles)if
  2128. +    if (GetTypeId()==TYPEID_PLAYER && (IsMounted() ||
  2129. +        (GetVehicle() && (!GetVehicle()->GetSeatInfo(this) ||
  2130. +        !(GetVehicle()->GetSeatInfo(this)->m_flags & (SEAT_FLAG_CAN_CAST | SEAT_FLAG_CAN_ATTACK))))))
  2131.          return false;
  2132.  
  2133.      // nobody can attack GM in GM-mode
  2134. @@ -5888,6 +5903,7 @@ void Unit::Uncharm()
  2135.          charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_CHARM);
  2136.          charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_POSSESS);
  2137.          charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_POSSESS_PET);
  2138. +        charm->SetCharmerGuid(ObjectGuid());
  2139.      }
  2140.  }
  2141.  
  2142. @@ -7627,7 +7643,7 @@ float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM) const
  2143.      return WeaponSpeed * PPM / 600.0f;                      // result is chance in percents (probability = Speed_in_sec * (PPM / 60))
  2144.  }
  2145.  
  2146. -void Unit::Mount(uint32 mount, uint32 spellId)
  2147. +void Unit::Mount(uint32 mount, uint32 spellId, uint32 vehicleId, uint32 creatureEntry)
  2148.  {
  2149.      if (!mount)
  2150.          return;
  2151. @@ -7661,6 +7677,15 @@ void Unit::Mount(uint32 mount, uint32 spellId)
  2152.                      pet->ApplyModeFlags(PET_MODE_DISABLE_ACTIONS,true);
  2153.              }
  2154.          }
  2155. +
  2156. +        if (vehicleId)
  2157. +        {
  2158. +            SetVehicleId(vehicleId);
  2159. +            GetVehicleKit()->Reset();
  2160. +
  2161. +            // mounts can also have accessories
  2162. +            GetVehicleKit()->InstallAllAccessories(creatureEntry);
  2163. +        }
  2164.      }
  2165.  }
  2166.  
  2167. @@ -7692,6 +7717,17 @@ void Unit::Unmount(bool from_aura)
  2168.          else
  2169.              ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
  2170.      }
  2171. +
  2172. +    if (GetTypeId() == TYPEID_PLAYER && GetVehicleKit())
  2173. +    {
  2174. +        // Send other players that we are no longer a vehicle
  2175. +        WorldPacket data(SMSG_SET_VEHICLE_REC_ID, 8+4);
  2176. +        data << GetPackGUID();
  2177. +        data << uint32(0);
  2178. +        ((Player*)this)->SendMessageToSet(&data, true);
  2179. +
  2180. +        RemoveVehicleKit();
  2181. +    }
  2182.  }
  2183.  
  2184.  void Unit::SetInCombatWith(Unit* enemy)
  2185. @@ -8371,6 +8407,7 @@ void Unit::SetDeathState(DeathState s)
  2186.  {
  2187.      if (s != ALIVE && s!= JUST_ALIVED)
  2188.      {
  2189. +        ExitVehicle();
  2190.          CombatStop();
  2191.          DeleteThreatList();
  2192.          ClearComboPointHolders();                           // any combo points pointed to unit lost at it death
  2193. @@ -8394,6 +8431,9 @@ void Unit::SetDeathState(DeathState s)
  2194.          // remove aurastates allowing special moves
  2195.          ClearAllReactives();
  2196.          ClearDiminishings();
  2197. +
  2198. +        if (GetVehicleKit())
  2199. +            GetVehicleKit()->RemoveAllPassengers();
  2200.      }
  2201.      else if(s == JUST_ALIVED)
  2202.      {
  2203. @@ -9343,6 +9383,10 @@ void Unit::CleanupsBeforeDelete()
  2204.  {
  2205.      if(m_uint32Values)                                      // only for fully created object
  2206.      {
  2207. +        if (GetVehicle())
  2208. +            ExitVehicle();
  2209. +        if (GetVehicleKit())
  2210. +            RemoveVehicleKit();
  2211.          InterruptNonMeleeSpells(true);
  2212.          m_Events.KillAllEvents(false);                      // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList
  2213.          CombatStop();
  2214. @@ -9410,6 +9454,25 @@ void CharmInfo::InitPossessCreateSpells()
  2215.      }
  2216.  }
  2217.  
  2218. +void CharmInfo::InitVehicleCreateSpells()
  2219. +{
  2220. +    for (uint32 x = ACTION_BAR_INDEX_START; x < ACTION_BAR_INDEX_END; ++x)
  2221. +        SetActionBar(x, 0, ActiveStates(0x8 + x));
  2222. +
  2223. +    for (uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x)
  2224. +    {
  2225. +        uint32 spellId = ((Creature*)m_unit)->m_spells[x];
  2226. +
  2227. +        if (!spellId)
  2228. +            continue;
  2229. +
  2230. +        if (IsPassiveSpell(spellId))
  2231. +            m_unit->CastSpell(m_unit, spellId, true);
  2232. +        else
  2233. +            PetActionBar[x].SetAction(spellId);
  2234. +    }
  2235. +}
  2236. +
  2237.  void CharmInfo::InitCharmCreateSpells()
  2238.  {
  2239.      if(m_unit->GetTypeId() == TYPEID_PLAYER)                //charmed players don't have spells
  2240. @@ -9940,7 +10003,7 @@ void Unit::SetFeared(bool apply, ObjectGuid casterGuid, uint32 spellID, uint32 t
  2241.          }
  2242.      }
  2243.  
  2244. -    if (GetTypeId() == TYPEID_PLAYER)
  2245. +    if (GetTypeId() == TYPEID_PLAYER && !GetVehicle())
  2246.          ((Player*)this)->SetClientControl(this, !apply);
  2247.  }
  2248.  
  2249. @@ -9970,7 +10033,7 @@ void Unit::SetConfused(bool apply, ObjectGuid casterGuid, uint32 spellID)
  2250.          }
  2251.      }
  2252.  
  2253. -    if(GetTypeId() == TYPEID_PLAYER)
  2254. +    if(GetTypeId() == TYPEID_PLAYER && !GetVehicle())
  2255.          ((Player*)this)->SetClientControl(this, !apply);
  2256.  }
  2257.  
  2258. @@ -10422,12 +10485,97 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
  2259.          RemoveNotOwnSingleTargetAuras(newPhaseMask);        // we can lost access to caster or target
  2260.  
  2261.          // all controlled except not owned charmed units
  2262. -        CallForAllControlledUnits(SetPhaseMaskHelper(newPhaseMask), CONTROLLED_PET|CONTROLLED_GUARDIANS|CONTROLLED_MINIPET|CONTROLLED_TOTEMS);
  2263. +        CallForAllControlledUnits(SetPhaseMaskHelper(newPhaseMask), CONTROLLED_PET|CONTROLLED_GUARDIANS|CONTROLLED_MINIPET|CONTROLLED_TOTEMS|CONTROLLED_CHARM);
  2264.      }
  2265.  
  2266.      WorldObject::SetPhaseMask(newPhaseMask, update);
  2267.  }
  2268.  
  2269. +bool Unit::SetPosition(float x, float y, float z, float orientation, bool teleport)
  2270. +{
  2271. +    // prevent crash when a bad coord is sent by the client
  2272. +    if (!MaNGOS::IsValidMapCoord(x, y, z, orientation))
  2273. +    {
  2274. +        DEBUG_LOG("Unit::SetPosition(%f, %f, %f, %f, %d) .. bad coordinates for unit %d!", x, y, z, orientation, teleport, GetGUIDLow());
  2275. +        return false;
  2276. +    }
  2277. +
  2278. +    bool turn = GetOrientation() != orientation;
  2279. +    bool relocate = (teleport || GetPositionX() != x || GetPositionY() != y || GetPositionZ() != z);
  2280. +
  2281. +    if (turn)
  2282. +        RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING);
  2283. +
  2284. +    if (relocate)
  2285. +    {
  2286. +        RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOVE);
  2287. +
  2288. +        if (GetTypeId() == TYPEID_PLAYER)
  2289. +            GetMap()->PlayerRelocation((Player*)this, x, y, z, orientation);
  2290. +        else
  2291. +            GetMap()->CreatureRelocation((Creature*)this, x, y, z, orientation);
  2292. +    }
  2293. +    else if (turn)
  2294. +        SetOrientation(orientation);
  2295. +
  2296. +    if ((relocate || turn) && GetVehicleKit())
  2297. +        GetVehicleKit()->RelocatePassengers(x, y, z, orientation);
  2298. +
  2299. +    return relocate || turn;
  2300. +}
  2301. +
  2302. +void Unit::MonsterMoveTransport(WorldObject *transport, SplineType type, SplineFlags flags, uint32 moveTime, ...)
  2303. +{
  2304. +    va_list vargs;
  2305. +    va_start(vargs, moveTime);
  2306. +
  2307. +    WorldPacket data(SMSG_MONSTER_MOVE_TRANSPORT, 60);
  2308. +    data << GetPackGUID();
  2309. +    data << transport->GetPackGUID();
  2310. +    data << uint8(m_movementInfo.GetTransportSeat());
  2311. +    data << uint8(0);                                       // new in 3.1
  2312. +    data << float(transport->GetPositionX());
  2313. +    data << float(transport->GetPositionY());
  2314. +    data << float(transport->GetPositionZ());
  2315. +    data << uint32(WorldTimer::getMSTime());
  2316. +
  2317. +    data << uint8(type);                                    // spline type
  2318. +
  2319. +    switch(type)
  2320. +    {
  2321. +        case SPLINETYPE_NORMAL:                             // normal packet
  2322. +            break;
  2323. +        case SPLINETYPE_STOP:                               // stop packet (raw pos?)
  2324. +            va_end(vargs);
  2325. +            SendMessageToSet(&data, true);
  2326. +            return;
  2327. +        case SPLINETYPE_FACINGSPOT:                         // facing spot
  2328. +            data << float(va_arg(vargs,double));
  2329. +            data << float(va_arg(vargs,double));
  2330. +            data << float(va_arg(vargs,double));
  2331. +            break;
  2332. +        case SPLINETYPE_FACINGTARGET:
  2333. +            data << uint64(va_arg(vargs,uint64));
  2334. +            break;
  2335. +        case SPLINETYPE_FACINGANGLE:
  2336. +            data << float(va_arg(vargs,double));            // facing angle
  2337. +            break;
  2338. +    }
  2339. +
  2340. +    va_end(vargs);
  2341. +
  2342. +    data << uint32(flags);
  2343. +
  2344. +    data << uint32(moveTime);                               // Time in between points
  2345. +    data << uint32(1);                                      // 1 single waypoint
  2346. +
  2347. +    data << float(m_movementInfo.GetTransportPos()->x);
  2348. +    data << float(m_movementInfo.GetTransportPos()->y);
  2349. +    data << float(m_movementInfo.GetTransportPos()->z);
  2350. +
  2351. +    SendMessageToSet(&data, true);
  2352. +}
  2353. +
  2354.  void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool casting /*= false*/ )
  2355.  {
  2356.      DisableSpline();
  2357. @@ -10436,13 +10584,14 @@ void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool ca
  2358.          ((Player*)this)->TeleportTo(GetMapId(), x, y, z, orientation, TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (casting ? TELE_TO_SPELL : 0));
  2359.      else
  2360.      {
  2361. +        ExitVehicle();
  2362.          Creature* c = (Creature*)this;
  2363.          // Creature relocation acts like instant movement generator, so current generator expects interrupt/reset calls to react properly
  2364.          if (!c->GetMotionMaster()->empty())
  2365.              if (MovementGenerator *movgen = c->GetMotionMaster()->top())
  2366.                  movgen->Interrupt(*c);
  2367.  
  2368. -        GetMap()->CreatureRelocation((Creature*)this, x, y, z, orientation);
  2369. +        SetPosition(x, y, z, orientation, true);
  2370.  
  2371.          SendHeartBeat();
  2372.  
  2373. @@ -10462,6 +10611,112 @@ void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed)
  2374.      init.Launch();
  2375.  }
  2376.  
  2377. +void Unit::RemoveVehicleKit()
  2378. +{
  2379. +    if (!m_pVehicleKit)
  2380. +        return;
  2381. +
  2382. +    m_pVehicleKit->RemoveAllPassengers();
  2383. +
  2384. +    m_updateFlag &= ~UPDATEFLAG_VEHICLE;
  2385. +    RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
  2386. +    RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE);
  2387. +}
  2388. +
  2389. +void Unit::ChangeSeat(int8 seatId, bool next)
  2390. +{
  2391. +    if (!m_pVehicle)
  2392. +        return;
  2393. +
  2394. +    if (seatId < 0)
  2395. +    {
  2396. +        seatId = m_pVehicle->GetNextEmptySeat(m_movementInfo.GetTransportSeat(), next);
  2397. +        if (seatId < 0)
  2398. +            return;
  2399. +    }
  2400. +    else if (seatId == m_movementInfo.GetTransportSeat() || !m_pVehicle->HasEmptySeat(seatId))
  2401. +        return;
  2402. +
  2403. +    if (m_pVehicle->GetPassenger(seatId) &&
  2404. +       (!m_pVehicle->GetPassenger(seatId)->GetObjectGuid().IsVehicle() || !m_pVehicle->GetSeatInfo(m_pVehicle->GetPassenger(seatId))))
  2405. +        return;
  2406. +
  2407. +    m_pVehicle->RemovePassenger(this);
  2408. +    m_pVehicle->AddPassenger(this, seatId);
  2409. +}
  2410. +
  2411. +void Unit::EnterVehicle(VehicleKit *vehicle, int8 seatId)
  2412. +{
  2413. +    if (!isAlive() || GetVehicleKit() == vehicle)
  2414. +        return;
  2415. +
  2416. +    if (m_pVehicle)
  2417. +    {
  2418. +        if (m_pVehicle == vehicle)
  2419. +        {
  2420. +            if (seatId >= 0)
  2421. +                ChangeSeat(seatId);
  2422. +
  2423. +            return;
  2424. +        }
  2425. +        else
  2426. +            ExitVehicle();
  2427. +    }
  2428. +
  2429. +    InterruptNonMeleeSpells(false);
  2430. +    RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
  2431. +
  2432. +    if (!vehicle->AddPassenger(this, seatId))
  2433. +        return;
  2434. +
  2435. +    m_pVehicle = vehicle;
  2436. +
  2437. +    if (Pet* pet = GetPet())
  2438. +        pet->Unsummon(PET_SAVE_AS_CURRENT,this);
  2439. +
  2440. +    if (GetTypeId() == TYPEID_PLAYER)
  2441. +    {
  2442. +        Player* player = (Player*)this;
  2443. +
  2444. +        if (BattleGround *bg = player->GetBattleGround())
  2445. +            bg->EventPlayerDroppedFlag(player);
  2446. +
  2447. +        WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA);
  2448. +        player->GetSession()->SendPacket(&data);
  2449. +
  2450. +        data.Initialize(SMSG_BREAK_TARGET, 8);
  2451. +        data << vehicle->GetBase()->GetPackGUID();
  2452. +        player->GetSession()->SendPacket(&data);
  2453. +    }
  2454. +
  2455. +    if (Transport* pTransport = GetTransport())
  2456. +    {
  2457. +        if (GetTypeId() == TYPEID_PLAYER)
  2458. +            pTransport->RemovePassenger((Player*)this);
  2459. +
  2460. +        SetTransport(NULL);
  2461. +    }
  2462. +}
  2463. +
  2464. +void Unit::ExitVehicle()
  2465. +{
  2466. +    if(!m_pVehicle)
  2467. +        return;
  2468. +
  2469. +    m_pVehicle->RemovePassenger(this);
  2470. +    m_pVehicle = NULL;
  2471. +
  2472. +    if (GetTypeId() == TYPEID_PLAYER)
  2473. +        ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
  2474. +
  2475. +    float x = GetPositionX();
  2476. +    float y = GetPositionY();
  2477. +    float z = GetPositionZ() + 2.0f;
  2478. +    GetClosePoint(x, y, z, 2.0f);
  2479. +    UpdateAllowedPositionZ(x, y, z);
  2480. +    MonsterMoveWithSpeed(x, y, z + 0.5f, 28.f);
  2481. +}
  2482. +
  2483.  struct SetPvPHelper
  2484.  {
  2485.      explicit SetPvPHelper(bool _state) : state(_state) {}
  2486. @@ -10813,6 +11068,9 @@ void Unit::SetVehicleId(uint32 entry)
  2487.  
  2488.          m_vehicleInfo = new VehicleInfo(ventry);
  2489.          m_updateFlag |= UPDATEFLAG_VEHICLE;
  2490. +
  2491. +        if (!m_pVehicleKit)
  2492. +            m_pVehicleKit = new VehicleKit(this);
  2493.      }
  2494.      else
  2495.      {
  2496. diff --git a/src/game/Unit.h b/src/game/Unit.h
  2497. index 09a5f0b..0d4a8fb 100644
  2498. --- a/src/game/Unit.h
  2499. +++ b/src/game/Unit.h
  2500. @@ -197,7 +197,7 @@ enum UnitRename
  2501.      UNIT_CAN_BE_ABANDONED   = 0x02,
  2502.  };
  2503.  
  2504. -#define CREATURE_MAX_SPELLS     4
  2505. +#define CREATURE_MAX_SPELLS     8
  2506.  
  2507.  enum Swing
  2508.  {
  2509. @@ -270,6 +270,7 @@ class Item;
  2510.  class Pet;
  2511.  class PetAura;
  2512.  class Totem;
  2513. +class Transport;
  2514.  class VehicleInfo;
  2515.  
  2516.  struct SpellImmune
  2517. @@ -408,24 +409,25 @@ enum UnitState
  2518.      UNIT_STAT_FOLLOW_MOVE     = 0x00010000,
  2519.      UNIT_STAT_FLEEING         = 0x00020000,                     // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack
  2520.      UNIT_STAT_FLEEING_MOVE    = 0x00040000,
  2521. +    UNIT_STAT_ON_VEHICLE      = 0x00080000,                     // Unit is on vehicle
  2522.  
  2523.      // masks (only for check)
  2524.  
  2525.      // can't move currently
  2526. -    UNIT_STAT_CAN_NOT_MOVE    = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED,
  2527. +    UNIT_STAT_CAN_NOT_MOVE    = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | UNIT_STAT_ON_VEHICLE,
  2528.  
  2529.      // stay by different reasons
  2530.      UNIT_STAT_NOT_MOVE        = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED |
  2531. -                                UNIT_STAT_DISTRACTED,
  2532. +                                UNIT_STAT_DISTRACTED | UNIT_STAT_ON_VEHICLE,
  2533.  
  2534.      // stay or scripted movement for effect( = in player case you can't move by client command)
  2535.      UNIT_STAT_NO_FREE_MOVE    = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED |
  2536.                                  UNIT_STAT_TAXI_FLIGHT |
  2537. -                                UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING,
  2538. +                                UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_ON_VEHICLE,
  2539.  
  2540.      // not react at move in sight or other
  2541.      UNIT_STAT_CAN_NOT_REACT   = UNIT_STAT_STUNNED | UNIT_STAT_DIED |
  2542. -                                UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING,
  2543. +                                UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_ON_VEHICLE,
  2544.  
  2545.      // AI disabled by some reason
  2546.      UNIT_STAT_LOST_CONTROL    = UNIT_STAT_FLEEING | UNIT_STAT_CONTROLLED,
  2547. @@ -588,6 +590,7 @@ enum NPCFlags
  2548.      UNIT_NPC_FLAG_STABLEMASTER          = 0x00400000,       // 100%
  2549.      UNIT_NPC_FLAG_GUILD_BANKER          = 0x00800000,       // cause client to send 997 opcode
  2550.      UNIT_NPC_FLAG_SPELLCLICK            = 0x01000000,       // cause client to send 1015 opcode (spell click), dynamic, set at loading and don't must be set in DB
  2551. +    UNIT_NPC_FLAG_PLAYER_VEHICLE        = 0x02000000,       // players with mounts that have vehicle data should have it set
  2552.  };
  2553.  
  2554.  // used in most movement packets (send and received)
  2555. @@ -717,7 +720,7 @@ class MovementInfo
  2556.  {
  2557.      public:
  2558.          MovementInfo() : moveFlags(MOVEFLAG_NONE), moveFlags2(MOVEFLAG2_NONE), time(0),
  2559. -            t_time(0), t_seat(-1), t_time2(0), s_pitch(0.0f), fallTime(0), u_unk1(0.0f) {}
  2560. +            t_time(0), t_seat(-1), t_seatInfo(NULL), t_time2(0), s_pitch(0.0f), fallTime(0), u_unk1(0.0f) {}
  2561.  
  2562.          // Read/Write methods
  2563.          void Read(ByteBuffer &data);
  2564. @@ -730,10 +733,11 @@ class MovementInfo
  2565.          MovementFlags GetMovementFlags() const { return MovementFlags(moveFlags); }
  2566.          void SetMovementFlags(MovementFlags f) { moveFlags = f; }
  2567.          MovementFlags2 GetMovementFlags2() const { return MovementFlags2(moveFlags2); }
  2568. +        void AddMovementFlag2(MovementFlags2 f) { moveFlags2 |= f; }
  2569.  
  2570.          // Position manipulations
  2571.          Position const *GetPos() const { return &pos; }
  2572. -        void SetTransportData(ObjectGuid guid, float x, float y, float z, float o, uint32 time, int8 seat)
  2573. +        void SetTransportData(ObjectGuid guid, float x, float y, float z, float o, uint32 time, int8 seat, VehicleSeatEntry const* seatInfo = NULL)
  2574.          {
  2575.              t_guid = guid;
  2576.              t_pos.x = x;
  2577. @@ -742,6 +746,7 @@ class MovementInfo
  2578.              t_pos.o = o;
  2579.              t_time = time;
  2580.              t_seat = seat;
  2581. +            t_seatInfo = seatInfo;
  2582.          }
  2583.          void ClearTransportData()
  2584.          {
  2585. @@ -752,10 +757,13 @@ class MovementInfo
  2586.              t_pos.o = 0.0f;
  2587.              t_time = 0;
  2588.              t_seat = -1;
  2589. +            t_seatInfo = NULL;
  2590.          }
  2591.          ObjectGuid const& GetTransportGuid() const { return t_guid; }
  2592.          Position const *GetTransportPos() const { return &t_pos; }
  2593.          int8 GetTransportSeat() const { return t_seat; }
  2594. +        uint32 GetTransportDBCSeat() const { return t_seatInfo ? t_seatInfo->m_ID : 0; }
  2595. +        uint32 GetVehicleSeatFlags() const { return t_seatInfo ? t_seatInfo->m_flags : 0; }
  2596.          uint32 GetTransportTime() const { return t_time; }
  2597.          uint32 GetFallTime() const { return fallTime; }
  2598.          void ChangeOrientation(float o) { pos.o = o; }
  2599. @@ -780,6 +788,7 @@ class MovementInfo
  2600.          Position t_pos;
  2601.          uint32   t_time;
  2602.          int8     t_seat;
  2603. +        VehicleSeatEntry const* t_seatInfo;
  2604.          uint32   t_time2;
  2605.          // swimming and flying
  2606.          float    s_pitch;
  2607. @@ -1049,6 +1058,7 @@ struct CharmInfo
  2608.          bool HasReactState(ReactStates state) { return (m_reactState == state); }
  2609.  
  2610.          void InitPossessCreateSpells();
  2611. +        void InitVehicleCreateSpells();
  2612.          void InitCharmCreateSpells();
  2613.          void InitPetActionBar();
  2614.          void InitEmptyActionBar();
  2615. @@ -1123,6 +1133,7 @@ typedef std::set<ObjectGuid> GuardianPetList;
  2616.  #define REGEN_TIME_PRECISE  500                             // Used in Spell::CheckPower for precise regeneration in spell cast time
  2617.  
  2618.  struct SpellProcEventEntry;                                 // used only privately
  2619. +class  VehicleKit;
  2620.  
  2621.  class MANGOS_DLL_SPEC Unit : public WorldObject
  2622.  {
  2623. @@ -1306,7 +1317,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
  2624.  
  2625.          bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); }
  2626.          uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); }
  2627. -        void Mount(uint32 mount, uint32 spellId = 0);
  2628. +        void Mount(uint32 mount, uint32 spellId = 0, uint32 vehicleId = 0, uint32 creatureEntry = 0);
  2629.          void Unmount(bool from_aura = false);
  2630.  
  2631.          VehicleInfo* GetVehicleInfo() { return m_vehicleInfo; }
  2632. @@ -1462,6 +1473,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
  2633.          void SendPeriodicAuraLog(SpellPeriodicAuraLogInfo *pInfo);
  2634.          void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo);
  2635.  
  2636. +        virtual bool SetPosition(float x, float y, float z, float orientation, bool teleport = false);
  2637. +        void MonsterMoveTransport(WorldObject *transport, SplineType type, SplineFlags flags, uint32 moveTime, ...);
  2638.          void NearTeleportTo(float x, float y, float z, float orientation, bool casting = false);
  2639.          void MonsterMoveWithSpeed(float x, float y, float z, float speed);
  2640.          // recommend use MonsterMove/MonsterMoveWithSpeed for most case that correctly work with movegens
  2641. @@ -1957,6 +1970,25 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
  2642.          void _SetAINotifyScheduled(bool on) { m_AINotifyScheduled = on;}       // only for call from RelocationNotifyEvent code
  2643.          void OnRelocated();
  2644.  
  2645. +        // Transports
  2646. +        Transport* GetTransport() const { return m_transport; }
  2647. +        void SetTransport(Transport* pTransport) { m_transport = pTransport; }
  2648. +
  2649. +        float GetTransOffsetX() const { return m_movementInfo.GetTransportPos()->x; }
  2650. +        float GetTransOffsetY() const { return m_movementInfo.GetTransportPos()->y; }
  2651. +        float GetTransOffsetZ() const { return m_movementInfo.GetTransportPos()->z; }
  2652. +        float GetTransOffsetO() const { return m_movementInfo.GetTransportPos()->o; }
  2653. +        uint32 GetTransTime() const { return m_movementInfo.GetTransportTime(); }
  2654. +        int8 GetTransSeat() const { return m_movementInfo.GetTransportSeat(); }
  2655. +
  2656. +        // Vehicle system
  2657. +        void EnterVehicle(VehicleKit *vehicle, int8 seatId = -1);
  2658. +        void ExitVehicle();
  2659. +        void ChangeSeat(int8 seatId, bool next = true);
  2660. +        VehicleKit* GetVehicle() const { return m_pVehicle; }
  2661. +        VehicleKit* GetVehicleKit() const { return m_pVehicleKit; }
  2662. +        void RemoveVehicleKit();
  2663. +
  2664.      protected:
  2665.          explicit Unit ();
  2666.  
  2667. @@ -2006,6 +2038,11 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
  2668.          uint32 m_regenTimer;
  2669.          uint32 m_lastManaUseTimer;
  2670.  
  2671. +        // Transports
  2672. +        Transport* m_transport;
  2673. +
  2674. +        VehicleKit* m_pVehicle;
  2675. +        VehicleKit* m_pVehicleKit;
  2676.          VehicleInfo* m_vehicleInfo;
  2677.          void DisableSpline();
  2678.      private:
  2679. diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp
  2680. index 5002d79..b64c062 100644
  2681. --- a/src/game/Vehicle.cpp
  2682. +++ b/src/game/Vehicle.cpp
  2683. @@ -21,9 +21,377 @@
  2684.  #include "ObjectMgr.h"
  2685.  #include "Vehicle.h"
  2686.  #include "Unit.h"
  2687. +#include "CreatureAI.h"
  2688.  #include "Util.h"
  2689. +#include "WorldPacket.h"
  2690.  
  2691.  VehicleInfo::VehicleInfo(VehicleEntry const* entry) :
  2692.      m_vehicleEntry(entry)
  2693.  {
  2694.  }
  2695. +
  2696. +VehicleKit::VehicleKit(Unit* base) : m_pBase(base), m_uiNumFreeSeats(0)
  2697. +{
  2698. +    for (uint32 i = 0; i < MAX_VEHICLE_SEAT; ++i)
  2699. +    {
  2700. +        uint32 seatId = GetBase()->GetVehicleInfo()->GetEntry()->m_seatID[i];
  2701. +
  2702. +        if (!seatId)
  2703. +            continue;
  2704. +
  2705. +        if(base)
  2706. +        {
  2707. +            if(GetBase()->GetVehicleInfo()->GetEntry()->m_flags & VEHICLE_FLAG_NO_STRAFE)
  2708. +                GetBase()->m_movementInfo.AddMovementFlag2(MOVEFLAG2_NO_STRAFE);
  2709. +
  2710. +            if(GetBase()->GetVehicleInfo()->GetEntry()->m_flags & VEHICLE_FLAG_NO_JUMPING)
  2711. +                GetBase()->m_movementInfo.AddMovementFlag2(MOVEFLAG2_NO_JUMPING);
  2712. +        }
  2713. +
  2714. +        if (VehicleSeatEntry const *seatInfo = sVehicleSeatStore.LookupEntry(seatId))
  2715. +        {
  2716. +            m_Seats.insert(std::make_pair(i, VehicleSeat(seatInfo)));
  2717. +
  2718. +            if (seatInfo->IsUsable())
  2719. +                ++m_uiNumFreeSeats;
  2720. +        }
  2721. +    }
  2722. +}
  2723. +
  2724. +VehicleKit::~VehicleKit()
  2725. +{
  2726. +}
  2727. +
  2728. +void VehicleKit::RemoveAllPassengers()
  2729. +{
  2730. +    for (SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
  2731. +    {
  2732. +        if (Unit *passenger = itr->second.passenger)
  2733. +        {
  2734. +            passenger->ExitVehicle();
  2735. +            // remove creatures of player mounts
  2736. +            if (passenger->GetTypeId() == TYPEID_UNIT)
  2737. +                passenger->AddObjectToRemoveList();
  2738. +        }
  2739. +    }
  2740. +}
  2741. +
  2742. +bool VehicleKit::HasEmptySeat(int8 seatId) const
  2743. +{
  2744. +    SeatMap::const_iterator seat = m_Seats.find(seatId);
  2745. +
  2746. +    if (seat == m_Seats.end())
  2747. +        return false;
  2748. +
  2749. +    return !seat->second.passenger;
  2750. +}
  2751. +
  2752. +Unit *VehicleKit::GetPassenger(int8 seatId) const
  2753. +{
  2754. +    SeatMap::const_iterator seat = m_Seats.find(seatId);
  2755. +
  2756. +    if (seat == m_Seats.end())
  2757. +        return NULL;
  2758. +
  2759. +    return seat->second.passenger;
  2760. +}
  2761. +
  2762. +int8 VehicleKit::GetNextEmptySeat(int8 seatId, bool next) const
  2763. +{
  2764. +    SeatMap::const_iterator seat = m_Seats.find(seatId);
  2765. +
  2766. +    if (seat == m_Seats.end())
  2767. +        return -1;
  2768. +
  2769. +    while (seat->second.passenger || !seat->second.seatInfo->IsUsable())
  2770. +    {
  2771. +        if (next)
  2772. +        {
  2773. +            ++seat;
  2774. +            if (seat == m_Seats.end())
  2775. +                seat = m_Seats.begin();
  2776. +        }
  2777. +        else
  2778. +        {
  2779. +            if (seat == m_Seats.begin())
  2780. +                seat = m_Seats.end();
  2781. +            --seat;
  2782. +        }
  2783. +
  2784. +        if (seat->first == seatId)
  2785. +            return -1; // no available seat
  2786. +    }
  2787. +
  2788. +    return seat->first;
  2789. +}
  2790. +
  2791. +bool VehicleKit::AddPassenger(Unit *passenger, int8 seatId)
  2792. +{
  2793. +    SeatMap::iterator seat;
  2794. +
  2795. +    if (seatId < 0) // no specific seat requirement
  2796. +    {
  2797. +        for (seat = m_Seats.begin(); seat != m_Seats.end(); ++seat)
  2798. +            if (!seat->second.passenger && (seat->second.seatInfo->IsUsable() || (seat->second.seatInfo->m_flags & SEAT_FLAG_UNCONTROLLED)))
  2799. +                break;
  2800. +
  2801. +        if (seat == m_Seats.end()) // no available seat
  2802. +            return false;
  2803. +    }
  2804. +    else
  2805. +    {
  2806. +        seat = m_Seats.find(seatId);
  2807. +
  2808. +        if (seat == m_Seats.end())
  2809. +            return false;
  2810. +
  2811. +        if (seat->second.passenger)
  2812. +            return false;
  2813. +    }
  2814. +
  2815. +    seat->second.passenger = passenger;
  2816. +    passenger->addUnitState(UNIT_STAT_ON_VEHICLE);
  2817. +
  2818. +    m_pBase->SetPhaseMask(passenger->GetPhaseMask(), true);
  2819. +
  2820. +    VehicleSeatEntry const *seatInfo = seat->second.seatInfo;
  2821. +
  2822. +    passenger->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT);
  2823. +    passenger->m_movementInfo.SetTransportData(m_pBase->GetObjectGuid(),
  2824. +
  2825. +    seatInfo->m_attachmentOffsetX, seatInfo->m_attachmentOffsetY, seatInfo->m_attachmentOffsetZ,
  2826. +    seatInfo->m_passengerYaw, WorldTimer::getMSTime(), seat->first, seatInfo);
  2827. +
  2828. +    if (passenger->GetTypeId() == TYPEID_PLAYER)
  2829. +    {
  2830. +        ((Player*)passenger)->UnsummonPetTemporaryIfAny();
  2831. +        ((Player*)passenger)->GetCamera().SetView(m_pBase);
  2832. +
  2833. +        WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8+4);
  2834. +        data << passenger->GetPackGUID();
  2835. +        data << uint32((passenger->m_movementInfo.GetVehicleSeatFlags() & SEAT_FLAG_CAN_CAST) ? 2 : 0);
  2836. +        passenger->SendMessageToSet(&data, true);
  2837. +    }
  2838. +
  2839. +    if (seat->second.seatInfo->m_flags & SEAT_FLAG_UNATTACKABLE || seat->second.seatInfo->m_flags & SEAT_FLAG_CAN_CONTROL)
  2840. +    {
  2841. +        passenger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  2842. +        passenger->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
  2843. +    }
  2844. +
  2845. +    if (seatInfo->m_flags & SEAT_FLAG_CAN_CONTROL)
  2846. +    {
  2847. +//        m_pBase->StopMoving();
  2848. +        m_pBase->GetMotionMaster()->Clear();
  2849. +        m_pBase->CombatStop(true);
  2850. +        m_pBase->DeleteThreatList();
  2851. +        m_pBase->getHostileRefManager().deleteReferences();
  2852. +        m_pBase->SetCharmerGuid(passenger->GetObjectGuid());
  2853. +        m_pBase->addUnitState(UNIT_STAT_CONTROLLED);
  2854. +
  2855. +        passenger->SetCharm(m_pBase);
  2856. +
  2857. +        if(m_pBase->HasAuraType(SPELL_AURA_FLY) || m_pBase->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED))
  2858. +        {
  2859. +            WorldPacket data;
  2860. +            data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
  2861. +            data << m_pBase->GetPackGUID();
  2862. +            data << (uint32)(0);
  2863. +            m_pBase->SendMessageToSet(&data,false);
  2864. +        }
  2865. +
  2866. +        if (passenger->GetTypeId() == TYPEID_PLAYER)
  2867. +        {
  2868. +            m_pBase->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
  2869. +            m_pBase->setFaction(passenger->getFaction());
  2870. +
  2871. +            if (CharmInfo* charmInfo = m_pBase->InitCharmInfo(m_pBase))
  2872. +            {
  2873. +                charmInfo->InitVehicleCreateSpells();
  2874. +                charmInfo->SetReactState(REACT_PASSIVE);
  2875. +            }
  2876. +
  2877. +            Player* player = (Player*)passenger;
  2878. +            player->SetMover(m_pBase);
  2879. +            player->SetClientControl(m_pBase, 1);
  2880. +            player->VehicleSpellInitialize();
  2881. +        }
  2882. +
  2883. +        if(!(((Creature*)m_pBase)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_KEEP_AI))
  2884. +            ((Creature*)m_pBase)->AIM_Initialize();
  2885. +
  2886. +        if(m_pBase->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE))
  2887. +        {
  2888. +            WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 8+4);
  2889. +            data2 << m_pBase->GetPackGUID();
  2890. +            data2 << (uint32)(2);
  2891. +            m_pBase->SendMessageToSet(&data2,false);
  2892. +        }
  2893. +    }
  2894. +
  2895. +    passenger->MonsterMoveTransport(m_pBase, SPLINETYPE_FACINGANGLE, SPLINEFLAG_UNKNOWN5, 0, 0.0f);
  2896. +
  2897. +    RelocatePassengers(m_pBase->GetPositionX(), m_pBase->GetPositionY(), m_pBase->GetPositionZ()+0.5f, m_pBase->GetOrientation());
  2898. +
  2899. +    UpdateFreeSeatCount();
  2900. +
  2901. +    if (m_pBase->GetTypeId() == TYPEID_UNIT)
  2902. +    {
  2903. +        if (((Creature*)m_pBase)->AI())
  2904. +            ((Creature*)m_pBase)->AI()->PassengerBoarded(passenger, seat->first, true);
  2905. +    }
  2906. +
  2907. +    return true;
  2908. +}
  2909. +
  2910. +void VehicleKit::RemovePassenger(Unit *passenger)
  2911. +{
  2912. +    SeatMap::iterator seat;
  2913. +
  2914. +    for (seat = m_Seats.begin(); seat != m_Seats.end(); ++seat)
  2915. +        if (seat->second.passenger == passenger)
  2916. +            break;
  2917. +
  2918. +    if (seat == m_Seats.end())
  2919. +        return;
  2920. +
  2921. +    seat->second.passenger = NULL;
  2922. +    passenger->clearUnitState(UNIT_STAT_ON_VEHICLE);
  2923. +
  2924. +    float px, py, pz, po;
  2925. +    m_pBase->GetClosePoint(px, py, pz, m_pBase->GetObjectBoundingRadius(), 2.0f, M_PI_F);
  2926. +    po = m_pBase->GetOrientation();
  2927. +
  2928. +    passenger->m_movementInfo.ClearTransportData();
  2929. +    passenger->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ONTRANSPORT);
  2930. +
  2931. +    if (seat->second.seatInfo->m_flags & SEAT_FLAG_UNATTACKABLE || seat->second.seatInfo->m_flags & SEAT_FLAG_CAN_CONTROL)
  2932. +    {
  2933. +        passenger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
  2934. +    }
  2935. +
  2936. +    if (seat->second.seatInfo->m_flags & SEAT_FLAG_CAN_CONTROL)
  2937. +    {
  2938. +        passenger->SetCharm(NULL);
  2939. +        passenger->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE);
  2940. +
  2941. +        m_pBase->SetCharmerGuid(ObjectGuid());
  2942. +        m_pBase->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
  2943. +        m_pBase->clearUnitState(UNIT_STAT_CONTROLLED);
  2944. +        m_pBase->setFaction(((Creature*)m_pBase)->GetCreatureInfo()->faction_A);
  2945. +
  2946. +        if (passenger->GetTypeId() == TYPEID_PLAYER)
  2947. +        {
  2948. +            Player* player = (Player*)passenger;
  2949. +            player->SetMover(NULL);
  2950. +            player->SetClientControl(m_pBase, 0);
  2951. +            player->RemovePetActionBar();
  2952. +        }
  2953. +
  2954. +        if(!(((Creature*)m_pBase)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_KEEP_AI))
  2955. +            ((Creature*)m_pBase)->AIM_Initialize();
  2956. +    }
  2957. +
  2958. +    if (passenger->GetTypeId() == TYPEID_PLAYER)
  2959. +    {
  2960. +        ((Player*)passenger)->GetCamera().ResetView();
  2961. +
  2962. +        WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
  2963. +        data << passenger->GetPackGUID();
  2964. +        data << uint32(2);
  2965. +        passenger->SendMessageToSet(&data, true);
  2966. +
  2967. +        ((Player*)passenger)->ResummonPetTemporaryUnSummonedIfAny();
  2968. +    }
  2969. +
  2970. +    passenger->UpdateAllowedPositionZ(px, py, pz);
  2971. +    passenger->SetPosition(px, py, pz + 0.5f, po);
  2972. +    UpdateFreeSeatCount();
  2973. +
  2974. +    if (m_pBase->GetTypeId() == TYPEID_UNIT)
  2975. +    {
  2976. +        if (((Creature*)m_pBase)->AI())
  2977. +            ((Creature*)m_pBase)->AI()->PassengerBoarded(passenger, seat->first, false);
  2978. +    }
  2979. +}
  2980. +
  2981. +void VehicleKit::Reset()
  2982. +{
  2983. +    InstallAllAccessories(m_pBase->GetEntry());
  2984. +    UpdateFreeSeatCount();
  2985. +}
  2986. +
  2987. +void VehicleKit::InstallAllAccessories(uint32 entry)
  2988. +{
  2989. +    VehicleAccessoryList const* mVehicleList = sObjectMgr.GetVehicleAccessoryList(entry);
  2990. +    if (!mVehicleList)
  2991. +        return;
  2992. +
  2993. +    for (VehicleAccessoryList::const_iterator itr = mVehicleList->begin(); itr != mVehicleList->end(); ++itr)
  2994. +        InstallAccessory(itr->uiAccessory, itr->uiSeat, itr->bMinion);
  2995. +}
  2996. +
  2997. +void VehicleKit::InstallAccessory( uint32 entry, int8 seatId, bool minion)
  2998. +{
  2999. +    if (Unit *passenger = GetPassenger(seatId))
  3000. +    {
  3001. +        // already installed
  3002. +        if (passenger->GetEntry() == entry)
  3003. +            return;
  3004. +
  3005. +        passenger->ExitVehicle();
  3006. +    }
  3007. +
  3008. +    if (Creature *accessory = m_pBase->SummonCreature(entry, m_pBase->GetPositionX(), m_pBase->GetPositionY(), m_pBase->GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000))
  3009. +    {
  3010. +        accessory->SetCreatorGuid(ObjectGuid());
  3011. +        accessory->EnterVehicle(this, seatId);
  3012. +        accessory->SendHeartBeat();
  3013. +    }
  3014. +}
  3015. +
  3016. +void VehicleKit::UpdateFreeSeatCount()
  3017. +{
  3018. +    m_uiNumFreeSeats = 0;
  3019. +
  3020. +    for (SeatMap::const_iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
  3021. +    {
  3022. +        if (!itr->second.passenger && itr->second.seatInfo->IsUsable())
  3023. +            ++m_uiNumFreeSeats;
  3024. +    }
  3025. +
  3026. +    uint32 flag = m_pBase->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK;
  3027. +
  3028. +    if (m_uiNumFreeSeats)
  3029. +        m_pBase->SetFlag(UNIT_NPC_FLAGS, flag);
  3030. +    else
  3031. +        m_pBase->RemoveFlag(UNIT_NPC_FLAGS, flag);
  3032. +}
  3033. +
  3034. +void VehicleKit::RelocatePassengers(float x, float y, float z, float ang)
  3035. +{
  3036. +    for (SeatMap::const_iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
  3037. +    {
  3038. +        if (Unit *passenger = itr->second.passenger)
  3039. +        {
  3040. +            float px = x + passenger->m_movementInfo.GetTransportPos()->x;
  3041. +            float py = y + passenger->m_movementInfo.GetTransportPos()->y;
  3042. +            float pz = z + passenger->m_movementInfo.GetTransportPos()->z;
  3043. +            float po = ang + passenger->m_movementInfo.GetTransportPos()->o;
  3044. +
  3045. +            passenger->UpdateAllowedPositionZ(px, py, pz);
  3046. +            passenger->SetPosition(px, py, pz, po);
  3047. +        }
  3048. +    }
  3049. +}
  3050. +
  3051. +VehicleSeatEntry const* VehicleKit::GetSeatInfo(Unit* passenger)
  3052. +{
  3053. +    for (SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
  3054. +    {
  3055. +        if (Unit *_passenger = itr->second.passenger)
  3056. +            if (_passenger = passenger)
  3057. +                return itr->second.seatInfo;
  3058. +    }
  3059. +    return NULL;
  3060. +}
  3061. diff --git a/src/game/Vehicle.h b/src/game/Vehicle.h
  3062. index 73ec3d6..1b71475 100644
  3063. --- a/src/game/Vehicle.h
  3064. +++ b/src/game/Vehicle.h
  3065. @@ -36,4 +36,54 @@ class VehicleInfo
  3066.          VehicleEntry const* GetEntry() const { return m_vehicleEntry; }
  3067.  };
  3068.  
  3069. +struct VehicleSeat
  3070. +{
  3071. +    VehicleSeat(VehicleSeatEntry const *pSeatInfo = NULL) : seatInfo(pSeatInfo), passenger(NULL) {}
  3072. +
  3073. +    VehicleSeatEntry const *seatInfo;
  3074. +    Unit* passenger;
  3075. +};
  3076. +
  3077. +typedef std::map<int8, VehicleSeat> SeatMap;
  3078. +
  3079. +struct VehicleAccessory
  3080. +{
  3081. +    explicit VehicleAccessory(uint32 _uiAccessory, int8 _uiSeat, bool _bMinion) : uiAccessory(_uiAccessory), uiSeat(_uiSeat), bMinion(_bMinion) {}
  3082. +    uint32 uiAccessory;
  3083. +    int8 uiSeat;
  3084. +    uint32 bMinion;
  3085. +};
  3086. +
  3087. +typedef std::vector<VehicleAccessory> VehicleAccessoryList;
  3088. +typedef std::map<uint32, VehicleAccessoryList> VehicleAccessoryMap;
  3089. +
  3090. +class MANGOS_DLL_SPEC VehicleKit
  3091. +{
  3092. +    public:
  3093. +        explicit VehicleKit(Unit* base);
  3094. +        ~VehicleKit();
  3095. +
  3096. +        void Reset();
  3097. +        void InstallAllAccessories(uint32 entry);
  3098. +
  3099. +        bool HasEmptySeat(int8 seatId) const;
  3100. +        Unit *GetPassenger(int8 seatId) const;
  3101. +        int8 GetNextEmptySeat(int8 seatId, bool next) const;
  3102. +        bool AddPassenger(Unit *passenger, int8 seatId = -1);
  3103. +        void RemovePassenger(Unit *passenger);
  3104. +        void RelocatePassengers(float x, float y, float z, float ang);
  3105. +        void RemoveAllPassengers();
  3106. +        VehicleSeatEntry const* GetSeatInfo(Unit* passenger);
  3107. +
  3108. +        Unit* GetBase() { return m_pBase; }
  3109. +
  3110. +    private:
  3111. +        void UpdateFreeSeatCount();
  3112. +        void InstallAccessory(uint32 entry, int8 seatId, bool minion = true);
  3113. +
  3114. +        SeatMap m_Seats;
  3115. +        uint32 m_uiNumFreeSeats;
  3116. +        Unit* m_pBase;
  3117. +};
  3118. +
  3119.  #endif
  3120. diff --git a/src/game/VehicleHandler.cpp b/src/game/VehicleHandler.cpp
  3121. new file mode 100644
  3122. index 0000000..d55f677
  3123. --- /dev/null
  3124. +++ b/src/game/VehicleHandler.cpp
  3125. @@ -0,0 +1,202 @@
  3126. +/*
  3127. + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/>
  3128. + *
  3129. + * This program is free software; you can redistribute it and/or modify
  3130. + * it under the terms of the GNU General Public License as published by
  3131. + * the Free Software Foundation; either version 2 of the License, or
  3132. + * (at your option) any later version.
  3133. + *
  3134. + * This program is distributed in the hope that it will be useful,
  3135. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3136. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  3137. + * GNU General Public License for more details.
  3138. + *
  3139. + * You should have received a copy of the GNU General Public License
  3140. + * along with this program; if not, write to the Free Software
  3141. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  3142. + */
  3143. +
  3144. +#include "Common.h"
  3145. +#include "WorldPacket.h"
  3146. +#include "WorldSession.h"
  3147. +#include "Opcodes.h"
  3148. +#include "Log.h"
  3149. +#include "Player.h"
  3150. +#include "Vehicle.h"
  3151. +#include "ObjectMgr.h"
  3152. +
  3153. +void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
  3154. +{
  3155. +    DEBUG_LOG("WORLD: Received CMSG_DISMISS_CONTROLLED_VEHICLE");
  3156. +    recv_data.hexlike();
  3157. +
  3158. +    ObjectGuid guid;
  3159. +    MovementInfo mi;
  3160. +
  3161. +    recv_data >> guid.ReadAsPacked();
  3162. +    recv_data >> mi;
  3163. +
  3164. +    if(!GetPlayer()->GetVehicle())
  3165. +        return;
  3166. +
  3167. +    bool dismiss = true;
  3168. +
  3169. +    Creature* vehicle = GetPlayer()->GetMap()->GetAnyTypeCreature(guid);
  3170. +
  3171. +    if (!vehicle || !vehicle->GetVehicleInfo())
  3172. +        return;
  3173. +
  3174. +    if (vehicle->GetVehicleInfo()->GetEntry()->m_flags & (VEHICLE_FLAG_NOT_DISMISS | VEHICLE_FLAG_ACCESSORY))
  3175. +        dismiss = false;
  3176. +
  3177. +    GetPlayer()->m_movementInfo = mi;
  3178. +    GetPlayer()->ExitVehicle();
  3179. +
  3180. +    if (dismiss)
  3181. +        vehicle->ForcedDespawn();
  3182. +}
  3183. +
  3184. +void WorldSession::HandleRequestVehicleExit(WorldPacket &recv_data)
  3185. +{
  3186. +    DEBUG_LOG("WORLD: Received CMSG_REQUEST_VEHICLE_EXIT");
  3187. +
  3188. +    GetPlayer()->ExitVehicle();
  3189. +}
  3190. +
  3191. +void WorldSession::HandleRequestVehiclePrevSeat(WorldPacket &recv_data)
  3192. +{
  3193. +    DEBUG_LOG("WORLD: Received CMSG_REQUEST_VEHICLE_PREV_SEAT");
  3194. +
  3195. +    GetPlayer()->ChangeSeat(-1, false);
  3196. +}
  3197. +
  3198. +void WorldSession::HandleRequestVehicleNextSeat(WorldPacket &recv_data)
  3199. +{
  3200. +    DEBUG_LOG("WORLD: Received CMSG_REQUEST_VEHICLE_NEXT_SEAT");
  3201. +
  3202. +    GetPlayer()->ChangeSeat(-1, true);
  3203. +}
  3204. +
  3205. +void WorldSession::HandleRequestVehicleSwitchSeat(WorldPacket &recv_data)
  3206. +{
  3207. +    DEBUG_LOG("WORLD: Received CMSG_REQUEST_VEHICLE_SWITCH_SEAT");
  3208. +    recv_data.hexlike();
  3209. +
  3210. +    ObjectGuid guid;
  3211. +    recv_data >> guid.ReadAsPacked();
  3212. +
  3213. +    int8 seatId;
  3214. +    recv_data >> seatId;
  3215. +
  3216. +    VehicleKit* pVehicle = GetPlayer()->GetVehicle();
  3217. +
  3218. +    if (!pVehicle)
  3219. +        return;
  3220. +
  3221. +    if (pVehicle->GetBase()->GetVehicleInfo()->GetEntry()->m_flags & VEHICLE_FLAG_DISABLE_SWITCH)
  3222. +        GetPlayer()->ExitVehicle();
  3223. +
  3224. +    if (pVehicle->GetBase()->GetObjectGuid() == guid)
  3225. +        GetPlayer()->ChangeSeat(seatId);
  3226. +
  3227. +    else if (Unit *Vehicle2 = GetPlayer()->GetMap()->GetUnit(guid))
  3228. +    {
  3229. +        if (VehicleKit *pVehicle2 = Vehicle2->GetVehicleKit())
  3230. +            if (pVehicle2->HasEmptySeat(seatId))
  3231. +            {
  3232. +                    GetPlayer()->ExitVehicle();
  3233. +                    GetPlayer()->EnterVehicle(pVehicle2, seatId);
  3234. +            }
  3235. +    }
  3236. +}
  3237. +
  3238. +void WorldSession::HandleEnterPlayerVehicle(WorldPacket &recv_data)
  3239. +{
  3240. +    DEBUG_LOG("WORLD: Received CMSG_RIDE_VEHICLE_INTERACT");
  3241. +    recv_data.hexlike();
  3242. +
  3243. +    ObjectGuid guid;
  3244. +    recv_data >> guid;
  3245. +
  3246. +    Player* player = sObjectMgr.GetPlayer(guid);
  3247. +
  3248. +    if (!player)
  3249. +        return;
  3250. +
  3251. +    if (!GetPlayer()->IsInSameRaidWith(player))
  3252. +        return;
  3253. +
  3254. +    if (!GetPlayer()->IsWithinDistInMap(player, INTERACTION_DISTANCE))
  3255. +        return;
  3256. +
  3257. +    if (player->GetTransport())
  3258. +        return;
  3259. +
  3260. +    if (VehicleKit* pVehicle = player->GetVehicleKit())
  3261. +        GetPlayer()->EnterVehicle(pVehicle);
  3262. +}
  3263. +
  3264. +void WorldSession::HandleEjectPasenger(WorldPacket &recv_data)
  3265. +{
  3266. +    DEBUG_LOG("WORLD: Received CMSG_CONTROLLER_EJECT_PASSENGER");
  3267. +    recv_data.hexlike();
  3268. +
  3269. +    ObjectGuid guid;
  3270. +    recv_data >> guid;
  3271. +
  3272. +    Unit* passenger = ObjectAccessor::GetUnit(*GetPlayer(), guid);
  3273. +
  3274. +    if (!passenger)
  3275. +        return;
  3276. +
  3277. +    if (!passenger->GetVehicle() || passenger->GetVehicle() != GetPlayer()->GetVehicleKit())
  3278. +        return;
  3279. +
  3280. +    passenger->ExitVehicle();
  3281. +
  3282. +    // eject and remove creatures of player mounts
  3283. +    if (passenger->GetTypeId() == TYPEID_UNIT)
  3284. +        passenger->AddObjectToRemoveList();
  3285. +}
  3286. +
  3287. +void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data)
  3288. +{
  3289. +    sLog.outDebug("WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE");
  3290. +    recv_data.hexlike();
  3291. +
  3292. +    ObjectGuid guid, guid2;
  3293. +    recv_data >> guid.ReadAsPacked();
  3294. +
  3295. +    MovementInfo mi;
  3296. +    recv_data >> mi;
  3297. +    GetPlayer()->m_movementInfo = mi;
  3298. +
  3299. +    recv_data >> guid2.ReadAsPacked(); //guid of vehicle or of vehicle in target seat
  3300. +
  3301. +    int8 seatId;
  3302. +    recv_data >> seatId;
  3303. +
  3304. +    VehicleKit* pVehicle = GetPlayer()->GetVehicle();
  3305. +
  3306. +    if (!pVehicle)
  3307. +        return;
  3308. +
  3309. +    if (pVehicle->GetBase()->GetVehicleInfo()->GetEntry()->m_flags & VEHICLE_FLAG_DISABLE_SWITCH)
  3310. +        GetPlayer()->ExitVehicle();
  3311. +
  3312. +    if(guid.GetRawValue() == guid2.GetRawValue())
  3313. +        GetPlayer()->ChangeSeat(seatId, false);
  3314. +
  3315. +    else if (guid2.IsVehicle())
  3316. +    {
  3317. +        if (Creature* vehicle = GetPlayer()->GetMap()->GetAnyTypeCreature(guid2))
  3318. +        {
  3319. +            if (VehicleKit* pVehicle2 = vehicle->GetVehicleKit())
  3320. +                if(pVehicle2->HasEmptySeat(seatId))
  3321. +                {
  3322. +                    GetPlayer()->ExitVehicle();
  3323. +                    GetPlayer()->EnterVehicle(pVehicle2, seatId);
  3324. +                }
  3325. +        }
  3326. +    }
  3327. +}
  3328. diff --git a/src/game/World.cpp b/src/game/World.cpp
  3329. index 2f96f53..093ca2f 100644
  3330. --- a/src/game/World.cpp
  3331. +++ b/src/game/World.cpp
  3332. @@ -63,6 +63,7 @@
  3333.  #include "Util.h"
  3334.  #include "AuctionHouseBot/AuctionHouseBot.h"
  3335.  #include "CharacterDatabaseCleaner.h"
  3336. +#include "Vehicle.h"
  3337.  
  3338.  INSTANTIATE_SINGLETON_1( World );
  3339.  
  3340. @@ -1061,6 +1062,9 @@ void World::SetInitialWorldSettings()
  3341.      sLog.outString( ">>> Creature Addon Data loaded" );
  3342.      sLog.outString();
  3343.  
  3344. +    sLog.outString("Loading Vehicle Accessories...");
  3345. +    sObjectMgr.LoadVehicleAccessories();
  3346. +
  3347.      sLog.outString( "Loading Gameobject Data..." );
  3348.      sObjectMgr.LoadGameobjects();
  3349.  
  3350. diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h
  3351. index 7bfa7d5..202e3ef 100644
  3352. --- a/src/game/WorldSession.h
  3353. +++ b/src/game/WorldSession.h
  3354. @@ -511,9 +511,17 @@ class MANGOS_DLL_SPEC WorldSession
  3355.          void HandleMovementOpcodes(WorldPacket& recvPacket);
  3356.          void HandleSetActiveMoverOpcode(WorldPacket &recv_data);
  3357.          void HandleMoveNotActiveMoverOpcode(WorldPacket &recv_data);
  3358. -        void HandleDismissControlledVehicle(WorldPacket &recv_data);
  3359.          void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data);
  3360.  
  3361. +        void HandleDismissControlledVehicle(WorldPacket &recv_data);
  3362. +        void HandleRequestVehicleExit(WorldPacket &recv_data);
  3363. +        void HandleRequestVehiclePrevSeat(WorldPacket &recv_data);
  3364. +        void HandleRequestVehicleNextSeat(WorldPacket &recv_data);
  3365. +        void HandleRequestVehicleSwitchSeat(WorldPacket &recv_data);
  3366. +        void HandleEnterPlayerVehicle(WorldPacket &recv_data);
  3367. +        void HandleEjectPasenger(WorldPacket &recv_data);
  3368. +        void HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data);
  3369. +
  3370.          void HandleRequestRaidInfoOpcode( WorldPacket & recv_data );
  3371.  
  3372.          void HandleGroupInviteOpcode(WorldPacket& recvPacket);
  3373. diff --git a/win/VC100/game.vcxproj b/win/VC100/game.vcxproj
  3374. index be7d6ba..75b7f84 100644
  3375. --- a/win/VC100/game.vcxproj
  3376. +++ b/win/VC100/game.vcxproj
  3377. @@ -505,6 +505,7 @@
  3378.      <ClCompile Include="..\..\src\game\Unit.cpp" />
  3379.      <ClCompile Include="..\..\src\game\UpdateData.cpp" />
  3380.      <ClCompile Include="..\..\src\game\Vehicle.cpp" />
  3381. +    <ClCompile Include="..\..\src\game\VehicleHandler.cpp" />
  3382.      <ClCompile Include="..\..\src\game\VoiceChatHandler.cpp" />
  3383.      <ClCompile Include="..\..\src\game\WaypointManager.cpp" />
  3384.      <ClCompile Include="..\..\src\game\WaypointMovementGenerator.cpp" />
  3385. diff --git a/win/VC100/game.vcxproj.filters b/win/VC100/game.vcxproj.filters
  3386. index 69d61d8..e6a6031 100644
  3387. --- a/win/VC100/game.vcxproj.filters
  3388. +++ b/win/VC100/game.vcxproj.filters
  3389. @@ -246,6 +246,9 @@
  3390.      <ClCompile Include="..\..\src\game\UpdateData.cpp">
  3391.        <Filter>World/Handlers</Filter>
  3392.      </ClCompile>
  3393. +    <ClCompile Include="..\..\src\game\VehicleHandler.cpp" >
  3394. +      <Filter>World/Handlers</Filter>
  3395. +    </ClCompile>
  3396.      <ClCompile Include="..\..\src\game\VoiceChatHandler.cpp">
  3397.        <Filter>World/Handlers</Filter>
  3398.      </ClCompile>
  3399. diff --git a/win/VC90/game.vcproj b/win/VC90/game.vcproj
  3400. index fa647e2..eece821 100644
  3401. --- a/win/VC90/game.vcproj
  3402. +++ b/win/VC90/game.vcproj
  3403. @@ -1007,6 +1007,10 @@
  3404.                 >
  3405.             </File>
  3406.             <File
  3407. +               RelativePath="..\..\src\game\VehicleHandler.cpp"
  3408. +               >
  3409. +           </File>
  3410. +           <File
  3411.                 RelativePath="..\..\src\game\VoiceChatHandler.cpp"
  3412.                 >
  3413.             </File>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement