Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
- index d4a8808..69d17bd 100644
- --- a/src/game/Creature.cpp
- +++ b/src/game/Creature.cpp
- @@ -194,6 +194,9 @@ void Creature::AddToWorld()
- GetMap()->GetObjectsStore().insert<Creature>(GetObjectGuid(), (Creature*)this);
- Unit::AddToWorld();
- +
- + if (GetVehicleKit())
- + GetVehicleKit()->Reset();
- }
- void Creature::RemoveFromWorld()
- @@ -296,6 +299,7 @@ bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=NULL*/, GameE
- SetDisplayId(display_id);
- SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
- + SetByteValue(UNIT_FIELD_BYTES_0, 3, uint8(cinfo->powerType));
- // Load creature equipment
- if (eventData && eventData->equipment_id)
- @@ -629,36 +633,82 @@ void Creature::RegenerateAll(uint32 update_diff)
- if (!isInCombat() || IsPolymorphed())
- RegenerateHealth();
- - RegenerateMana();
- + Regenerate(getPowerType());
- m_regenTimer = REGEN_TIME_FULL;
- }
- -void Creature::RegenerateMana()
- +void Creature::Regenerate(Powers power)
- {
- - uint32 curValue = GetPower(POWER_MANA);
- - uint32 maxValue = GetMaxPower(POWER_MANA);
- + uint32 curValue = GetPower(power);
- + uint32 maxValue = GetMaxPower(power);
- if (curValue >= maxValue)
- return;
- - uint32 addvalue = 0;
- + float addvalue = 0.0f;
- - // Combat and any controlled creature
- - if (isInCombat() || GetCharmerOrOwnerGuid())
- + switch(power)
- {
- - if(!IsUnderLastManaUseEffect())
- + case POWER_MANA:
- {
- - float ManaIncreaseRate = sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_MANA);
- - float Spirit = GetStat(STAT_SPIRIT);
- + // Combat and any controlled creature
- + if (isInCombat() || GetCharmerOrOwnerGuid())
- + {
- + if(!IsUnderLastManaUseEffect())
- + {
- + float ManaIncreaseRate = sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_MANA);
- + float Spirit = GetStat(STAT_SPIRIT);
- - addvalue = uint32((Spirit / 5.0f + 17.0f) * ManaIncreaseRate);
- + addvalue = int32((Spirit / 5.0f + 17.0f) * ManaIncreaseRate);
- + }
- + }
- + else
- + addvalue = maxValue / 3;
- + break;
- }
- + case POWER_ENERGY:
- + if (IsVehicle())
- + {
- + if (VehicleEntry const* vehicleInfo = sVehicleStore.LookupEntry(GetCreatureInfo()->vehicleId))
- + {
- +
- + switch (vehicleInfo->m_powerType)
- + {
- + case ENERGY_TYPE_PYRITE:
- + case ENERGY_TYPE_BLOOD:
- + case ENERGY_TYPE_OOZE:
- + break;
- +
- + case ENERGY_TYPE_STEAM:
- + default:
- + addvalue = 10 * sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_ENERGY);
- + break;
- + }
- + }
- + }
- + else
- + addvalue = 20 * sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_ENERGY);
- + break;
- + case POWER_FOCUS:
- + addvalue = 24 * sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_FOCUS);
- + break;
- + default:
- + return;
- }
- - else
- - addvalue = maxValue / 3;
- + // Apply modifiers (if any)
- +
- + AuraList const& ModPowerRegenAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
- + for(AuraList::const_iterator i = ModPowerRegenAuras.begin(); i != ModPowerRegenAuras.end(); ++i)
- + if ((*i)->GetModifier()->m_miscvalue == power)
- + addvalue += (*i)->GetModifier()->m_amount;
- +
- + AuraList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT);
- + for(AuraList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i)
- + if ((*i)->GetModifier()->m_miscvalue == power)
- + addvalue *= ((*i)->GetModifier()->m_amount + 100) / 100.0f;
- - ModifyPower(POWER_MANA, addvalue);
- + ModifyPower(power, int32(addvalue));
- }
- void Creature::RegenerateHealth()
- @@ -1155,19 +1205,32 @@ void Creature::SelectLevel(const CreatureInfo *cinfo, float percentHealth, float
- else
- SetHealthPercent(percentHealth);
- - // mana
- - uint32 minmana = std::min(cinfo->maxmana, cinfo->minmana);
- - uint32 maxmana = std::max(cinfo->maxmana, cinfo->minmana);
- - uint32 mana = minmana + uint32(rellevel * (maxmana - minmana));
- + SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, float(health));
- - SetCreateMana(mana);
- - SetMaxPower(POWER_MANA, mana); //MAX Mana
- - SetPower(POWER_MANA, mana);
- + Powers powerType = Powers(cinfo->powerType);
- + uint32 maxPower = 0;
- - // TODO: set UNIT_FIELD_POWER*, for some creature class case (energy, etc)
- + switch(powerType)
- + {
- + case POWER_MANA:
- + {
- + uint32 minmana = std::min(cinfo->maxmana, cinfo->minmana);
- + uint32 maxmana = std::max(cinfo->maxmana, cinfo->minmana);
- + maxPower = minmana + uint32(rellevel * (maxmana - minmana));
- - SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, float(health));
- - SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, float(mana));
- + SetCreateMana(maxPower);
- + break;
- + }
- + case POWER_ENERGY:
- + {
- + maxPower = uint32(GetCreatePowers(powerType) * cinfo->power_mod);
- + break;
- + }
- + }
- +
- + SetMaxPower(powerType, maxPower);
- + SetPower(powerType, maxPower);
- + SetModifierValue(UnitMods(UNIT_MOD_POWER_START + powerType), BASE_VALUE, float(maxPower));
- // damage
- float damagemod = _GetDamageMod(rank);
- @@ -1247,6 +1310,10 @@ bool Creature::CreateFromProto(uint32 guidlow, CreatureInfo const* cinfo, Team t
- if (!UpdateEntry(cinfo->Entry, team, data, eventData, false))
- return false;
- + // Checked at startup
- + if (GetCreatureInfo()->vehicleId)
- + SetVehicleId(GetCreatureInfo()->vehicleId);
- +
- return true;
- }
- diff --git a/src/game/Creature.h b/src/game/Creature.h
- index ca554fc..1206a07 100644
- --- a/src/game/Creature.h
- +++ b/src/game/Creature.h
- @@ -54,6 +54,7 @@ enum CreatureFlagsExtra
- CREATURE_FLAG_EXTRA_NOT_TAUNTABLE = 0x00000100, // creature is immune to taunt auras and effect attack me
- CREATURE_FLAG_EXTRA_AGGRO_ZONE = 0x00000200, // creature sets itself in combat with zone on aggro
- CREATURE_FLAG_EXTRA_GUARD = 0x00000400, // creature is a guard
- + CREATURE_FLAG_EXTRA_KEEP_AI = 0x00001000, // creature keeps ScriptedAI even after being charmed / controlled (instead of getting PetAI)
- };
- // 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
- @@ -81,6 +82,7 @@ struct CreatureInfo
- uint32 maxlevel;
- uint32 minhealth;
- uint32 maxhealth;
- + uint32 powerType;
- uint32 minmana;
- uint32 maxmana;
- uint32 armor;
- @@ -128,7 +130,7 @@ struct CreatureInfo
- uint32 MovementType;
- uint32 InhabitType;
- float unk16;
- - float unk17;
- + float power_mod;
- bool RacialLeader;
- uint32 questItems[6];
- uint32 movementId;
- @@ -713,7 +715,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
- float m_respawnradius;
- CreatureSubtype m_subtype; // set in Creatures subclasses for fast it detect without dynamic_cast use
- - void RegenerateMana();
- + void Regenerate(Powers power);
- void RegenerateHealth();
- MovementGeneratorType m_defaultMovementType;
- Cell m_currentCell; // store current cell where creature listed
- diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h
- index 2a49d50..78ec0b0 100644
- --- a/src/game/CreatureAI.h
- +++ b/src/game/CreatureAI.h
- @@ -139,6 +139,9 @@ class MANGOS_DLL_SPEC CreatureAI
- // Called at text emote receive from player
- virtual void ReceiveEmote(Player* /*pPlayer*/, uint32 /*text_emote*/) {}
- + // Called at vehicle enter
- + virtual void PassengerBoarded(Unit * /*who*/, int8 /*seatId*/, bool /*apply*/) {}
- +
- ///== Triggered Actions Requested ==================
- // Called when creature attack expected (if creature can and no have current victim)
- diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp
- index f75a4ac..01dc180 100644
- --- a/src/game/CreatureEventAI.cpp
- +++ b/src/game/CreatureEventAI.cpp
- @@ -916,6 +916,7 @@ void CreatureEventAI::JustReachedHome()
- void CreatureEventAI::EnterEvadeMode()
- {
- + m_creature->ExitVehicle();
- m_creature->RemoveAllAuras();
- m_creature->DeleteThreatList();
- m_creature->CombatStop(true);
- diff --git a/src/game/DBCEnums.h b/src/game/DBCEnums.h
- index 3afa1a3..2d7d0c2 100644
- --- a/src/game/DBCEnums.h
- +++ b/src/game/DBCEnums.h
- @@ -361,7 +361,8 @@ enum SummonPropGroup
- SUMMON_PROP_GROUP_FRIENDLY = 1,
- SUMMON_PROP_GROUP_PETS = 2,
- SUMMON_PROP_GROUP_CONTROLLABLE = 3,
- - SUMMON_PROP_GROUP_VEHICLE = 4
- + SUMMON_PROP_GROUP_VEHICLE = 4,
- + SUMMON_PROP_GROUP_UNCONTROLLABLE_VEHICLE = 5
- };
- // SummonProperties.dbc, col 3
- @@ -467,15 +468,20 @@ enum VehicleFlags
- VEHICLE_FLAG_ALLOW_PITCHING = 0x00000010, // Sets MOVEFLAG2_ALLOW_PITCHING
- VEHICLE_FLAG_FULLSPEEDPITCHING = 0x00000020, // Sets MOVEFLAG2_FULLSPEEDPITCHING
- VEHICLE_FLAG_CUSTOM_PITCH = 0x00000040, // If set use pitchMin and pitchMax from DBC, otherwise pitchMin = -pi/2, pitchMax = pi/2
- + VEHICLE_FLAG_ACCESSORY = 0x00000200, // Vehicle is accessory? Need additional check!
- VEHICLE_FLAG_ADJUST_AIM_ANGLE = 0x00000400, // Lua_IsVehicleAimAngleAdjustable
- VEHICLE_FLAG_ADJUST_AIM_POWER = 0x00000800, // Lua_IsVehicleAimPowerAdjustable
- + VEHICLE_FLAG_DISABLE_SWITCH = 0x00400000, // Can't change seats, VEHICLE_ID = 335 chopper
- + VEHICLE_FLAG_NOT_DISMISS = 0x10000000, // Vehicle not dismissed after eject passenger?
- };
- enum VehicleSeatFlags
- {
- SEAT_FLAG_HIDE_PASSENGER = 0x00000200, // Passenger is hidden
- SEAT_FLAG_CAN_CONTROL = 0x00000800, // Lua_UnitInVehicleControlSeat
- + SEAT_FLAG_UNCONTROLLED = 0x00002000, // Seat uncontrolled for passenger?
- SEAT_FLAG_CAN_ATTACK = 0x00004000, // Can attack, cast spells and use items from vehicle?
- + SEAT_FLAG_UNATTACKABLE = 0x00008000, // Passenger is not attackable?
- SEAT_FLAG_USABLE = 0x02000000, // Lua_CanExitVehicle
- SEAT_FLAG_CAN_SWITCH = 0x04000000, // Lua_CanSwitchVehicleSeats
- SEAT_FLAG_CAN_CAST = 0x20000000, // Lua_UnitHasVehicleUI
- diff --git a/src/game/DBCStores.cpp b/src/game/DBCStores.cpp
- index c17f1fd..e73428f 100644
- --- a/src/game/DBCStores.cpp
- +++ b/src/game/DBCStores.cpp
- @@ -424,6 +424,19 @@ void LoadDBCStores(const std::string& dataPath)
- LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionTemplateStore, dbcPath,"FactionTemplate.dbc");
- LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGameObjectDisplayInfoStore,dbcPath,"GameObjectDisplayInfo.dbc");
- + for (uint32 i = 0; i < sGameObjectDisplayInfoStore.GetNumRows(); ++i)
- + {
- + if (GameObjectDisplayInfoEntry *info = const_cast<GameObjectDisplayInfoEntry*>(sGameObjectDisplayInfoStore.LookupEntry(i)))
- + {
- + if (info->maxX < info->minX)
- + std::swap(info->maxX, info->minX);
- + if (info->maxY < info->minY)
- + std::swap(info->maxY, info->minY);
- + if (info->maxZ < info->minZ)
- + std::swap(info->maxZ, info->minZ);
- + }
- + }
- +
- LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGemPropertiesStore, dbcPath,"GemProperties.dbc");
- LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphPropertiesStore, dbcPath,"GlyphProperties.dbc");
- LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphSlotStore, dbcPath,"GlyphSlot.dbc");
- diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h
- index 92bf8b1..0903b9f 100644
- --- a/src/game/DBCStructure.h
- +++ b/src/game/DBCStructure.h
- @@ -916,12 +916,12 @@ struct GameObjectDisplayInfoEntry
- uint32 Displayid; // 0 m_ID
- // char* filename; // 1 m_modelName
- // 2-11 m_Sound
- - float unknown12; // 12 m_geoBoxMinX (use first value as interact dist, mostly in hacks way)
- - // 13 m_geoBoxMinY
- - // 14 m_geoBoxMinZ
- - // 15 m_geoBoxMaxX
- - // 16 m_geoBoxMaxY
- - // 17 m_geoBoxMaxZ
- + float minX; // 12 m_geoBoxMinX (use first value as interact dist, mostly in hacks way)
- + float minY; // 13 m_geoBoxMinY
- + float minZ; // 14 m_geoBoxMinZ
- + float maxX; // 15 m_geoBoxMaxX
- + float maxY; // 16 m_geoBoxMaxY
- + float maxZ; // 17 m_geoBoxMaxZ
- // 18 m_objectEffectPackageID
- };
- @@ -1936,7 +1936,7 @@ struct VehicleEntry
- uint32 m_uiLocomotionType; // 34
- float m_msslTrgtImpactTexRadius; // 35
- uint32 m_uiSeatIndicatorType; // 36 m_vehicleUIIndicatorID
- - // 37 m_powerDisplayID
- + uint32 m_powerType; // 37 m_powerDisplayID
- // 38 new in 3.1
- // 39 new in 3.1
- };
- @@ -2001,6 +2001,8 @@ struct VehicleSeatEntry
- // 55 m_cameraEnteringZoom"
- // 56 m_cameraSeatZoomMin
- // 57 m_cameraSeatZoomMax
- +
- + bool IsUsable() const { return m_flags & SEAT_FLAG_USABLE; }
- };
- struct WMOAreaTableEntry
- diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h
- index faa32ab..f35f5a9 100644
- --- a/src/game/DBCfmt.h
- +++ b/src/game/DBCfmt.h
- @@ -47,7 +47,7 @@ const char EmotesEntryfmt[]="nxxiiix";
- const char EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx";
- const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiiffixssssssssssssssssxxxxxxxxxxxxxxxxxx";
- const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii";
- -const char GameObjectDisplayInfofmt[]="nxxxxxxxxxxxfxxxxxx";
- +const char GameObjectDisplayInfofmt[]="nxxxxxxxxxxxffffffx";
- const char GemPropertiesEntryfmt[]="nixxi";
- const char GlyphPropertiesfmt[]="niii";
- const char GlyphSlotfmt[]="nii";
- @@ -110,7 +110,7 @@ const char TaxiPathEntryfmt[]="niii";
- const char TaxiPathNodeEntryfmt[]="diiifffiiii";
- const char TeamContributionPointsfmt[]="df";
- const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii";
- -const char VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifixxx";
- +const char VehicleEntryfmt[]="niffffiiiiiiiifffffffffffffffssssfifiixx";
- const char VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiixxxxxxxxxxxx";
- const char WMOAreaTableEntryfmt[]="niiixxxxxiixxxxxxxxxxxxxxxxx";
- const char WorldMapAreaEntryfmt[]="xinxffffixx";
- diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp
- index 8479ef9..cc65165 100644
- --- a/src/game/GameObject.cpp
- +++ b/src/game/GameObject.cpp
- @@ -59,6 +59,7 @@ GameObject::GameObject() : WorldObject(),
- m_cooldownTime = 0;
- m_rotation = 0;
- + m_health = 0;
- }
- GameObject::~GameObject()
- @@ -149,6 +150,13 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMa
- SetGoArtKit(0); // unknown what this is
- SetGoAnimProgress(animprogress);
- + if (goinfo->type == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
- + {
- + m_health = GetMaxHealth();
- + // destructible GO's show their "HP" as their animprogress
- + SetGoAnimProgress(255);
- + }
- +
- //Notify the map's instance data.
- //Only works if you create the object in it, not if it is moves to that map.
- //Normally non-players do not teleport to other maps.
- @@ -195,7 +203,7 @@ void GameObject::Update(uint32 update_diff, uint32 /*p_time*/)
- SendForcedObjectUpdate();
- - SendGameObjectCustomAnim(GetObjectGuid());
- + SendGameObjectCustomAnim(GetObjectGuid(), 0);
- }
- m_lootState = GO_READY; // can be successfully open with some chance
- @@ -1142,7 +1150,7 @@ void GameObject::Use(Unit* user)
- // this appear to be ok, however others exist in addition to this that should have custom (ex: 190510, 188692, 187389)
- if (time_to_restore && info->goober.customAnim)
- - SendGameObjectCustomAnim(GetObjectGuid());
- + SendGameObjectCustomAnim(GetObjectGuid(), info->goober.customAnim);
- else
- SetGoState(GO_STATE_ACTIVE);
- @@ -1435,6 +1443,8 @@ void GameObject::Use(Unit* user)
- BattleGround *bg = player->GetBattleGround();
- if (!bg)
- return;
- + if (player->GetVehicle())
- + return;
- // BG flag click
- // AB:
- // 15001
- @@ -1471,6 +1481,8 @@ void GameObject::Use(Unit* user)
- BattleGround *bg = player->GetBattleGround();
- if (!bg)
- return;
- + if (player->GetVehicle())
- + return;
- // BG flag dropped
- // WS:
- // 179785 - Silverwing Flag
- @@ -1620,6 +1632,87 @@ void GameObject::Use(Unit* user)
- spell->prepare(&targets);
- }
- +bool GameObject::IsInRange(float x, float y, float z, float radius) const
- +{
- + GameObjectDisplayInfoEntry const *info = sGameObjectDisplayInfoStore.LookupEntry(GetUInt32Value(GAMEOBJECT_DISPLAYID));
- + if (!info)
- + return IsWithinDist3d(x, y, z, radius);
- +
- + float dx = x - GetPositionX();
- + float dy = y - GetPositionY();
- + float dz = z - GetPositionZ();
- + float dist = sqrt(dx*dx + dy*dy);
- +
- + if (dist <= CONTACT_DISTANCE) // prevent division by 0
- + return true;
- +
- + float sinA = sin(GetOrientation());
- + float cosA = cos(GetOrientation());
- + float sinB = dx / dist;
- + float cosB = dy / dist;
- +
- + dx = dist * (cosA * cosB + sinA * sinB);
- + dy = dist * (cosA * sinB - sinA * cosB);
- +
- + return dx < info->maxX + radius && dx > info->minX - radius
- + && dy < info->maxY + radius && dy > info->minY - radius
- + && dz < info->maxZ + radius && dz > info->minZ - radius;
- +}
- +
- +void GameObject::DamageTaken(Unit* pDoneBy, uint32 damage)
- +{
- + if (GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING || !m_health)
- + return;
- +
- + DEBUG_FILTER_LOG(LOG_FILTER_DAMAGE, "GO damage taken: %u to health %u", damage, m_health);
- +
- + if (m_health > damage)
- + m_health -= damage;
- + else
- + m_health = 0;
- +
- + if (HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED)) // from damaged to destroyed
- + {
- + if (!m_health)
- + {
- + RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED);
- + SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED);
- + SetUInt32Value(GAMEOBJECT_DISPLAYID, m_goInfo->destructibleBuilding.destroyedDisplayId);
- + }
- + }
- + else // from intact to damaged
- + {
- + if (m_health <= m_goInfo->destructibleBuilding.damagedNumHits)
- + {
- + SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED);
- + SetUInt32Value(GAMEOBJECT_DISPLAYID, m_goInfo->destructibleBuilding.damagedDisplayId);
- + // if we have a "dead" display we can "kill" the building after its damaged
- + if (m_goInfo->destructibleBuilding.destroyedDisplayId)
- + {
- + m_health = m_goInfo->destructibleBuilding.damagedNumHits;
- + if (!m_health)
- + m_health = 1;
- + }
- + // otherwise we just handle it as "destroyed"
- + else
- + m_health = 0;
- + }
- + }
- + SetGoAnimProgress(m_health * 255 / GetMaxHealth());
- +}
- +
- +void GameObject::Rebuild(Unit* pWho)
- +{
- + if (GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
- + return;
- +
- + RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_DESTROYED);
- + SetUInt32Value(GAMEOBJECT_DISPLAYID, m_goInfo->displayId);
- + m_health = GetMaxHealth();
- +
- + SetGoAnimProgress(255);
- +}
- +
- // overwrite WorldObject function for proper name localization
- const char* GameObject::GetNameForLocaleIdx(int32 loc_idx) const
- {
- @@ -1799,7 +1892,7 @@ float GameObject::GetObjectBoundingRadius() const
- // 1. This is clearly hack way because GameObjectDisplayInfoEntry have 6 floats related to GO sizes, but better that use DEFAULT_WORLD_OBJECT_SIZE
- // 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
- if (m_displayInfo)
- - return fabs(m_displayInfo->unknown12) * GetObjectScale();
- + return fabs(m_displayInfo->minX) * GetObjectScale();
- return DEFAULT_WORLD_OBJECT_SIZE;
- }
- diff --git a/src/game/GameObject.h b/src/game/GameObject.h
- index 2cca164..39c85b5 100644
- --- a/src/game/GameObject.h
- +++ b/src/game/GameObject.h
- @@ -360,26 +360,26 @@ struct GameObjectInfo
- uint32 creditProxyCreature; //1
- uint32 empty1; //2
- uint32 intactEvent; //3
- - uint32 empty2; //4
- + uint32 damagedDisplayId; //4
- uint32 damagedNumHits; //5
- - uint32 empty3; //6
- - uint32 empty4; //7
- - uint32 empty5; //8
- + uint32 empty2; //6
- + uint32 empty3; //7
- + uint32 empty4; //8
- uint32 damagedEvent; //9
- - uint32 empty6; //10
- - uint32 empty7; //11
- - uint32 empty8; //12
- - uint32 empty9; //13
- + uint32 destroyedDisplayId; //10
- + uint32 empty5; //11
- + uint32 empty6; //12
- + uint32 empty7; //13
- uint32 destroyedEvent; //14
- - uint32 empty10; //15
- + uint32 empty8; //15
- uint32 debuildingTimeSecs; //16
- - uint32 empty11; //17
- + uint32 empty9; //17
- uint32 destructibleData; //18
- uint32 rebuildingEvent; //19
- - uint32 empty12; //20
- - uint32 empty13; //21
- + uint32 empty10; //20
- + uint32 empty11; //21
- uint32 damageEvent; //22
- - uint32 empty14; //23
- + uint32 empty12; //23
- } destructibleBuilding;
- //34 GAMEOBJECT_TYPE_GUILDBANK - empty
- //35 GAMEOBJECT_TYPE_TRAPDOOR
- @@ -725,6 +725,13 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
- GridReference<GameObject> &GetGridRef() { return m_gridRef; }
- + bool IsInRange(float x, float y, float z, float radius) const;
- + void DamageTaken(Unit *pDoneBy, uint32 uiDamage);
- + void Rebuild(Unit *pWho);
- +
- + uint32 GetHealth() const { return m_health; }
- + uint32 GetMaxHealth() const { return m_goInfo->destructibleBuilding.intactNumHits + m_goInfo->destructibleBuilding.damagedNumHits; }
- +
- protected:
- uint32 m_spellId;
- time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),
- @@ -733,7 +740,7 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
- bool m_spawnedByDefault;
- time_t m_cooldownTime; // used as internal reaction delay time store (not state change reaction).
- // For traps/goober this: spell casting cooldown, for doors/buttons: reset time.
- -
- + uint32 m_health;
- typedef std::set<ObjectGuid> GuidsSet;
- GuidsSet m_SkillupSet; // players that already have skill-up at GO use
- diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h
- index 11b5cd4..0fba845 100644
- --- a/src/game/GridNotifiers.h
- +++ b/src/game/GridNotifiers.h
- @@ -930,7 +930,7 @@ namespace MaNGOS
- : i_obj(obj), i_originalCaster(originalCaster), i_range(range)
- {
- i_targetForUnit = i_originalCaster->isType(TYPEMASK_UNIT);
- - i_targetForPlayer = (i_originalCaster->GetTypeId() == TYPEID_PLAYER);
- + i_targetForPlayer = (i_originalCaster->GetObjectGuid().IsVehicle() ? ((Unit*)i_originalCaster)->GetCharmerOrOwnerOrSelf()->GetTypeId() == TYPEID_PLAYER : i_originalCaster->GetTypeId() == TYPEID_PLAYER);
- }
- WorldObject const& GetFocusObject() const { return *i_obj; }
- bool operator()(Unit* u)
- @@ -1154,6 +1154,27 @@ namespace MaNGOS
- // Player checks and do
- + class GameObjectInRangeCheck
- + {
- + public:
- + GameObjectInRangeCheck(WorldObject const* _obj, float _x, float _y, float _z, float _range):
- + i_obj(_obj), x(_x), y(_y), z(_z), range(_range) {}
- +
- + WorldObject const& GetFocusObject() const { return *i_obj; }
- +
- + bool operator() (GameObject* go)
- + {
- + return go->IsInRange(x, y, z, range);
- + }
- +
- + private:
- + WorldObject const* i_obj;
- + float x, y, z, range;
- +
- + // prevent cloning this object
- + GameObjectInRangeCheck(GameObjectInRangeCheck const&);
- + };
- +
- class AnyPlayerInObjectRangeCheck
- {
- public:
- diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp
- index 62dd59a..1bf5a49 100644
- --- a/src/game/GroupHandler.cpp
- +++ b/src/game/GroupHandler.cpp
- @@ -807,6 +807,9 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
- else
- *data << uint64(0);
- }
- +
- + if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
- + *data << uint32(player->m_movementInfo.GetTransportDBCSeat());
- }
- /*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/
- diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
- index 38429e7..8d88039 100644
- --- a/src/game/Level3.cpp
- +++ b/src/game/Level3.cpp
- @@ -4222,6 +4222,9 @@ bool ChatHandler::HandleNpcInfoCommand(char* /*args*/)
- else
- PSendSysMessage(LANG_NPCINFO_CHAR, target->GetGuidStr().c_str(), faction, npcflags, Entry, displayid, nativeid);
- + if (cInfo->vehicleId)
- + PSendSysMessage("VehicleId: %u", cInfo->vehicleId);
- +
- PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel());
- PSendSysMessage(LANG_NPCINFO_HEALTH,target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth());
- PSendSysMessage(LANG_NPCINFO_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS), target->GetUInt32Value(UNIT_DYNAMIC_FLAGS), target->getFaction());
- diff --git a/src/game/Map.cpp b/src/game/Map.cpp
- index 6a267fe..55ea6e4 100644
- --- a/src/game/Map.cpp
- +++ b/src/game/Map.cpp
- @@ -3128,6 +3128,7 @@ uint32 Map::GenerateLocalLowGuid(HighGuid guidhigh)
- switch(guidhigh)
- {
- case HIGHGUID_UNIT:
- + case HIGHGUID_VEHICLE:
- return m_CreatureGuids.Generate();
- case HIGHGUID_GAMEOBJECT:
- return m_GameObjectGuids.Generate();
- @@ -3135,8 +3136,6 @@ uint32 Map::GenerateLocalLowGuid(HighGuid guidhigh)
- return m_DynObjectGuids.Generate();
- case HIGHGUID_PET:
- return m_PetGuids.Generate();
- - case HIGHGUID_VEHICLE:
- - return m_VehicleGuids.Generate();
- default:
- MANGOS_ASSERT(0);
- }
- diff --git a/src/game/Map.h b/src/game/Map.h
- index 31e8731..834ecfd 100644
- --- a/src/game/Map.h
- +++ b/src/game/Map.h
- @@ -338,7 +338,6 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>
- ObjectGuidGenerator<HIGHGUID_GAMEOBJECT> m_GameObjectGuids;
- ObjectGuidGenerator<HIGHGUID_DYNAMICOBJECT> m_DynObjectGuids;
- ObjectGuidGenerator<HIGHGUID_PET> m_PetGuids;
- - ObjectGuidGenerator<HIGHGUID_VEHICLE> m_VehicleGuids;
- // Type specific code for add/remove to/from grid
- template<class T>
- diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp
- index 8310000..0249f21 100644
- --- a/src/game/MotionMaster.cpp
- +++ b/src/game/MotionMaster.cpp
- @@ -68,6 +68,8 @@ void MotionMaster::UpdateMotion(uint32 diff)
- if (m_owner->hasUnitState(UNIT_STAT_CAN_NOT_MOVE))
- return;
- + if ( !empty() )
- + {
- MANGOS_ASSERT( !empty() );
- m_cleanFlag |= MMCF_UPDATE;
- @@ -100,6 +102,7 @@ void MotionMaster::UpdateMotion(uint32 diff)
- m_cleanFlag &= ~MMCF_RESET;
- }
- }
- + } else return;
- }
- void MotionMaster::DirectClean(bool reset, bool all)
- diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp
- index 4bfe28e..c202052 100644
- --- a/src/game/MovementHandler.cpp
- +++ b/src/game/MovementHandler.cpp
- @@ -44,6 +44,9 @@ void WorldSession::HandleMoveWorldportAckOpcode()
- if(!GetPlayer()->IsBeingTeleportedFar())
- return;
- + if (_player->GetVehicleKit())
- + _player->GetVehicleKit()->RemoveAllPassengers();
- +
- // get start teleport coordinates (will used later in fail case)
- WorldLocation old_loc;
- GetPlayer()->GetPosition(old_loc);
- @@ -403,7 +406,7 @@ void WorldSession::HandleMoveNotActiveMoverOpcode(WorldPacket &recv_data)
- _player->m_movementInfo = mi;
- }
- -void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
- +/*void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
- {
- DEBUG_LOG("WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE");
- recv_data.hexlike();
- @@ -419,7 +422,7 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
- return;
- _player->m_movementInfo = mi;
- -}
- +}*/
- void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvdata*/)
- {
- @@ -542,7 +545,7 @@ void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo)
- {
- if (movementInfo.HasMovementFlag(MOVEFLAG_ONTRANSPORT))
- {
- - if (!plMover->m_transport)
- + if (!plMover->GetTransport())
- {
- // elevators also cause the client to send MOVEFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
- for (MapManager::TransportSet::const_iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter)
- @@ -551,15 +554,19 @@ void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo)
- {
- plMover->m_transport = (*iter);
- (*iter)->AddPassenger(plMover);
- +
- + if (plMover->GetVehicleKit())
- + plMover->GetVehicleKit()->RemoveAllPassengers();
- +
- break;
- }
- }
- }
- }
- - else if (plMover->m_transport) // if we were on a transport, leave
- + else if (plMover->GetTransport()) // if we were on a transport, leave
- {
- - plMover->m_transport->RemovePassenger(plMover);
- - plMover->m_transport = NULL;
- + plMover->GetTransport()->RemovePassenger(plMover);
- + plMover->SetTransport(NULL);
- movementInfo.ClearTransportData();
- }
- @@ -606,6 +613,9 @@ void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo)
- else // creature charmed
- {
- if (mover->IsInWorld())
- - mover->GetMap()->CreatureRelocation((Creature*)mover, movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o);
- + {
- + mover->m_movementInfo = movementInfo;
- + mover->SetPosition(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o);
- + }
- }
- }
- diff --git a/src/game/Object.cpp b/src/game/Object.cpp
- index b33aa2c..031ee15 100644
- --- a/src/game/Object.cpp
- +++ b/src/game/Object.cpp
- @@ -264,6 +264,11 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 updateFlags) const
- player->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ONTRANSPORT);
- }
- + if (unit->GetTransport() || unit->GetVehicle())
- + unit->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT);
- + else
- + unit->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ONTRANSPORT);
- +
- // Update movement info time
- unit->m_movementInfo.UpdateTime(WorldTimer::getMSTime());
- // Write movement info
- @@ -1507,11 +1512,11 @@ void WorldObject::SendObjectDeSpawnAnim(ObjectGuid guid)
- SendMessageToSet(&data, true);
- }
- -void WorldObject::SendGameObjectCustomAnim(ObjectGuid guid)
- +void WorldObject::SendGameObjectCustomAnim(ObjectGuid guid, uint32 animprogress)
- {
- WorldPacket data(SMSG_GAMEOBJECT_CUSTOM_ANIM, 8+4);
- data << ObjectGuid(guid);
- - data << uint32(0); // not known what this is
- + data << uint32(animprogress);
- SendMessageToSet(&data, true);
- }
- diff --git a/src/game/Object.h b/src/game/Object.h
- index 000ebf8..4faac43 100644
- --- a/src/game/Object.h
- +++ b/src/game/Object.h
- @@ -547,7 +547,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object
- void PlayDirectSound(uint32 sound_id, Player* target = NULL);
- void SendObjectDeSpawnAnim(ObjectGuid guid);
- - void SendGameObjectCustomAnim(ObjectGuid guid);
- + void SendGameObjectCustomAnim(ObjectGuid guid, uint32 animprogress);
- virtual bool IsHostileTo(Unit const* unit) const =0;
- virtual bool IsFriendlyTo(Unit const* unit) const =0;
- diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
- index 5814559..8812f93 100644
- --- a/src/game/ObjectMgr.cpp
- +++ b/src/game/ObjectMgr.cpp
- @@ -616,6 +616,12 @@ void ObjectMgr::LoadCreatureTemplates()
- if (!displayScaleEntry)
- sLog.outErrorDb("Creature (Entry: %u) has nonexistent modelid in modelid_1/modelid_2/modelid_3/modelid_4", cInfo->Entry);
- + if (cInfo->powerType >= MAX_POWERS)
- + {
- + sLog.outErrorDb("Creature (Entry: %u) has invalid power type (%u)", cInfo->Entry, cInfo->powerType);
- + const_cast<CreatureInfo*>(cInfo)->powerType = POWER_MANA;
- + }
- +
- // use below code for 0-checks for unit_class
- if (!cInfo->unit_class)
- ERROR_DB_STRICT_LOG("Creature (Entry: %u) not has proper unit_class(%u) for creature_template", cInfo->Entry, cInfo->unit_class);
- @@ -1398,6 +1404,60 @@ void ObjectMgr::RemoveCreatureFromGrid(uint32 guid, CreatureData const* data)
- }
- }
- +void ObjectMgr::LoadVehicleAccessories()
- +{
- + m_VehicleAccessoryMap.clear(); // needed for reload case
- +
- + uint32 count = 0;
- +
- + QueryResult* result = WorldDatabase.Query("SELECT `entry`,`accessory_entry`,`seat_id`,`minion` FROM `vehicle_accessory`");
- +
- + if (!result)
- + {
- + BarGoLink bar(1);
- +
- + bar.step();
- +
- + sLog.outString();
- + sLog.outErrorDb(">> Loaded 0 vehicle accessories. DB table `vehicle_accessory` is empty.");
- + return;
- + }
- +
- + BarGoLink bar((int)result->GetRowCount());
- +
- + do
- + {
- + Field *fields = result->Fetch();
- + bar.step();
- +
- + uint32 uiEntry = fields[0].GetUInt32();
- + uint32 uiAccessory = fields[1].GetUInt32();
- + int8 uiSeat = int8(fields[2].GetInt16());
- + bool bMinion = fields[3].GetBool();
- +
- + if (!sCreatureStorage.LookupEntry<CreatureInfo>(uiEntry))
- + {
- + sLog.outErrorDb("Table `vehicle_accessory`: creature template entry %u does not exist.", uiEntry);
- + continue;
- + }
- +
- + if (!sCreatureStorage.LookupEntry<CreatureInfo>(uiAccessory))
- + {
- + sLog.outErrorDb("Table `vehicle_accessory`: Accessory %u does not exist.", uiAccessory);
- + continue;
- + }
- +
- + m_VehicleAccessoryMap[uiEntry].push_back(VehicleAccessory(uiAccessory, uiSeat, bMinion));
- +
- + ++count;
- + } while (result->NextRow());
- +
- + delete result;
- +
- + sLog.outString();
- + sLog.outString(">> Loaded %u Vehicle Accessories", count);
- +}
- +
- void ObjectMgr::LoadGameobjects()
- {
- uint32 count = 0;
- diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
- index a338167..bd2c71e 100644
- --- a/src/game/ObjectMgr.h
- +++ b/src/game/ObjectMgr.h
- @@ -37,6 +37,7 @@
- #include "ObjectGuid.h"
- #include "Policies/Singleton.h"
- #include "SQLStorages.h"
- +#include "Vehicle.h"
- #include <string>
- #include <map>
- @@ -616,6 +617,14 @@ class ObjectMgr
- return NULL;
- }
- + VehicleAccessoryList const* GetVehicleAccessoryList(uint32 uiEntry) const
- + {
- + VehicleAccessoryMap::const_iterator itr = m_VehicleAccessoryMap.find(uiEntry);
- + if (itr != m_VehicleAccessoryMap.end())
- + return &itr->second;
- + return NULL;
- + }
- +
- void LoadArenaTeams();
- void LoadGroups();
- void LoadQuests();
- @@ -695,6 +704,8 @@ class ObjectMgr
- void LoadTrainerTemplates();
- void LoadTrainers() { LoadTrainers("npc_trainer", false); }
- + void LoadVehicleAccessories();
- +
- std::string GeneratePetName(uint32 entry);
- uint32 GetBaseXP(uint32 level) const;
- uint32 GetXPForLevel(uint32 level) const;
- @@ -1115,6 +1126,8 @@ class ObjectMgr
- ItemConvertMap m_ItemExpireConvert;
- ItemRequiredTargetMap m_ItemRequiredTarget;
- + VehicleAccessoryMap m_VehicleAccessoryMap;
- +
- typedef std::vector<LocaleConstant> LocalForIndex;
- LocalForIndex m_LocalForIndex;
- diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp
- index 9e42af9..ce9fd26 100644
- --- a/src/game/Opcodes.cpp
- +++ b/src/game/Opcodes.cpp
- @@ -1168,10 +1168,10 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
- /*0x473*/ { "CMSG_CHAR_CUSTOMIZE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharCustomizeOpcode },
- /*0x474*/ { "SMSG_CHAR_CUSTOMIZE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x475*/ { "SMSG_PET_RENAMEABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- - /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- - /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- - /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- - /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- + /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestVehicleExit },
- + /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestVehiclePrevSeat },
- + /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestVehicleNextSeat },
- + /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestVehicleSwitchSeat },
- /*0x47A*/ { "CMSG_PET_LEARN_TALENT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetLearnTalent },
- /*0x47B*/ { "CMSG_PET_UNLEARN_TALENTS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x47C*/ { "SMSG_SET_PHASE_SHIFT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- @@ -1205,7 +1205,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
- /*0x498*/ { "SMSG_SERVER_FIRST_ACHIEVEMENT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x499*/ { "SMSG_PET_LEARNED_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x49A*/ { "SMSG_PET_REMOVED_SPELL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- - /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- + /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle},
- /*0x49C*/ { "CMSG_HEARTH_AND_RESURRECT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHearthandResurrect },
- /*0x49D*/ { "SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x49E*/ { "SMSG_CRITERIA_DELETED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- @@ -1218,8 +1218,8 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
- /*0x4A5*/ { "CMSG_QUERY_VEHICLE_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- /*0x4A6*/ { "SMSG_BATTLEGROUND_INFO_THROTTLED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4A7*/ { "SMSG_SET_VEHICLE_REC_ID", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- - /*0x4A8*/ { "CMSG_RIDE_VEHICLE_INTERACT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- - /*0x4A9*/ { "CMSG_CONTROLLER_EJECT_PASSENGER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- + /*0x4A8*/ { "CMSG_RIDE_VEHICLE_INTERACT", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEnterPlayerVehicle },
- + /*0x4A9*/ { "CMSG_CONTROLLER_EJECT_PASSENGER", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEjectPasenger },
- /*0x4AA*/ { "SMSG_PET_GUIDS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4AB*/ { "SMSG_CLIENTCACHE_VERSION", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4AC*/ { "CMSG_CHANGE_GDF_ARENA_RATING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
- diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
- index fbfa951..f618c19 100644
- --- a/src/game/Pet.cpp
- +++ b/src/game/Pet.cpp
- @@ -275,12 +275,12 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
- if (getPetType() == SUMMON_PET && !current) //all (?) summon pets come with full health when called, but not when they are current
- {
- SetHealth(GetMaxHealth());
- - SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
- + SetPower(getPowerType(), GetMaxPower(getPowerType()));
- }
- else
- {
- SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth);
- - SetPower(POWER_MANA, savedmana > GetMaxPower(POWER_MANA) ? GetMaxPower(POWER_MANA) : savedmana);
- + SetPower(getPowerType(), savedmana > GetMaxPower(getPowerType()) ? GetMaxPower(getPowerType()) : savedmana);
- }
- AIM_Initialize();
- @@ -583,7 +583,7 @@ void Pet::RegenerateAll( uint32 update_diff )
- if (!isInCombat() || IsPolymorphed())
- RegenerateHealth();
- - RegenerateMana();
- + Regenerate(getPowerType());
- m_regenTimer = 4000;
- }
- @@ -1094,7 +1094,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
- UpdateAllStats();
- SetHealth(GetMaxHealth());
- - SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
- + SetPower(getPowerType(), GetMaxPower(getPowerType()));
- return true;
- }
- diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp
- index ddceb57..363b3d0 100644
- --- a/src/game/PetAI.cpp
- +++ b/src/game/PetAI.cpp
- @@ -192,7 +192,7 @@ void PetAI::UpdateAI(const uint32 diff)
- }
- // Autocast (casted only in combat or persistent spells in any state)
- - if (!m_creature->IsNonMeleeSpellCasted(false))
- + if (!m_creature->IsNonMeleeSpellCasted(false) && !m_creature->GetObjectGuid().IsVehicle())
- {
- typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
- TargetSpellList targetSpellStore;
- diff --git a/src/game/Player.cpp b/src/game/Player.cpp
- index 1e2c24c..1570704 100644
- --- a/src/game/Player.cpp
- +++ b/src/game/Player.cpp
- @@ -376,8 +376,6 @@ UpdateMask Player::updateVisualBits;
- Player::Player (WorldSession *session): Unit(), m_mover(this), m_camera(this), m_achievementMgr(this), m_reputationMgr(this)
- {
- - m_transport = 0;
- -
- m_speakTime = 0;
- m_speakCount = 0;
- @@ -1724,10 +1722,15 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
- if (!(options & TELE_TO_NOT_LEAVE_TRANSPORT) && m_transport)
- {
- m_transport->RemovePassenger(this);
- - m_transport = NULL;
- + SetTransport(NULL);
- m_movementInfo.ClearTransportData();
- }
- + if (GetVehicleKit())
- + GetVehicleKit()->RemoveAllPassengers();
- +
- + ExitVehicle();
- +
- // The player was ported to another map and looses the duel immediately.
- // We have to perform this check before the teleport, otherwise the
- // ObjectAccessor won't find the flag.
- @@ -2208,7 +2211,7 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask)
- return NULL;
- // not in interactive state
- - if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL))
- + if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL) && !hasUnitState(UNIT_STAT_ON_VEHICLE))
- return NULL;
- // exist (we need look pets also for some interaction (quest/etc)
- @@ -2262,7 +2265,7 @@ GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameo
- return NULL;
- // not in interactive state
- - if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL))
- + if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL) && !hasUnitState(UNIT_STAT_ON_VEHICLE))
- return NULL;
- if (GameObject *go = GetMap()->GetGameObject(guid))
- @@ -2487,6 +2490,9 @@ void Player::GiveXP(uint32 xp, Unit* victim)
- if(!isAlive())
- return;
- + if(hasUnitState(UNIT_STAT_ON_VEHICLE))
- + return;
- +
- uint32 level = getLevel();
- // XP to money conversion processed in Player::RewardQuest
- @@ -3970,6 +3976,7 @@ void Player::InitVisibleBits()
- updateVisualBits.SetBit(PLAYER_BYTES_3);
- updateVisualBits.SetBit(PLAYER_DUEL_TEAM);
- updateVisualBits.SetBit(PLAYER_GUILD_TIMESTAMP);
- + updateVisualBits.SetBit(UNIT_NPC_FLAGS);
- // PLAYER_QUEST_LOG_x also visible bit on official (but only on party/raid)...
- for(uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_25_2; i += MAX_QUEST_OFFSET)
- @@ -6072,49 +6079,18 @@ ActionButton const* Player::GetActionButton(uint8 button)
- bool Player::SetPosition(float x, float y, float z, float orientation, bool teleport)
- {
- - // prevent crash when a bad coord is sent by the client
- - if(!MaNGOS::IsValidMapCoord(x,y,z,orientation))
- - {
- - DEBUG_LOG("Player::SetPosition(%f, %f, %f, %f, %d) .. bad coordinates for player %d!",x,y,z,orientation,teleport,GetGUIDLow());
- + if (!Unit::SetPosition(x, y, z, orientation, teleport))
- return false;
- - }
- -
- - Map *m = GetMap();
- -
- - const float old_x = GetPositionX();
- - const float old_y = GetPositionY();
- - const float old_z = GetPositionZ();
- - const float old_r = GetOrientation();
- - if( teleport || old_x != x || old_y != y || old_z != z || old_r != orientation )
- - {
- - if (teleport || old_x != x || old_y != y || old_z != z)
- - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING);
- - else
- - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING);
- -
- - RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
- -
- - // move and update visible state if need
- - m->PlayerRelocation(this, x, y, z, orientation);
- -
- - // reread after Map::Relocation
- - m = GetMap();
- - x = GetPositionX();
- - y = GetPositionY();
- - z = GetPositionZ();
- -
- - // group update
- - if (GetGroup() && (old_x != x || old_y != y))
- - SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION);
- + // group update
- + if (GetGroup())
- + SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION);
- - if (GetTrader() && !IsWithinDistInMap(GetTrader(), INTERACTION_DISTANCE))
- - GetSession()->SendCancelTrade(); // will close both side trade windows
- - }
- + if (GetTrader() && !IsWithinDistInMap(GetTrader(), INTERACTION_DISTANCE))
- + GetSession()->SendCancelTrade(); // will close both side trade windows
- // code block for underwater state update
- - UpdateUnderwaterState(m, x, y, z);
- -
- + UpdateUnderwaterState(GetMap(), x, y, z);
- CheckAreaExploreAndOutdoor();
- return true;
- @@ -15639,19 +15615,21 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder *holder )
- {
- for (MapManager::TransportSet::const_iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter)
- {
- - if( (*iter)->GetGUIDLow() == transGUID)
- + Transport* transport = *iter;
- +
- + if (transport->GetGUIDLow() == transGUID)
- {
- - MapEntry const* transMapEntry = sMapStore.LookupEntry((*iter)->GetMapId());
- + MapEntry const* transMapEntry = sMapStore.LookupEntry(transport->GetMapId());
- // client without expansion support
- if(GetSession()->Expansion() < transMapEntry->Expansion())
- {
- - DEBUG_LOG("Player %s using client without required expansion tried login at transport at non accessible map %u", GetName(), (*iter)->GetMapId());
- + DEBUG_LOG("Player %s using client without required expansion tried login at transport at non accessible map %u", GetName(), transport->GetMapId());
- break;
- }
- - m_transport = *iter;
- - m_transport->AddPassenger(this);
- - SetLocationMapId(m_transport->GetMapId());
- + SetTransport(transport);
- + transport->AddPassenger(this);
- + SetLocationMapId(transport->GetMapId());
- break;
- }
- }
- @@ -18516,6 +18494,59 @@ void Player::PossessSpellInitialize()
- GetSession()->SendPacket(&data);
- }
- +void Player::VehicleSpellInitialize()
- +{
- + Creature* charm = (Creature*)GetCharm();
- +
- + if (!charm)
- + return;
- +
- + CharmInfo *charmInfo = charm->GetCharmInfo();
- +
- + if (!charmInfo)
- + {
- + sLog.outError("Player::VehicleSpellInitialize(): vehicle (GUID: %u) has no charminfo!", charm->GetGUIDLow());
- + return;
- + }
- +
- + size_t cooldownsCount = charm->m_CreatureSpellCooldowns.size() + charm->m_CreatureCategoryCooldowns.size();
- +
- + WorldPacket data(SMSG_PET_SPELLS, 8+2+4+4+4*MAX_UNIT_ACTION_BAR_INDEX+1+1+cooldownsCount*(4+2+4+4));
- + data << charm->GetObjectGuid();
- + data << uint16(0);
- + data << uint32(0);
- + data << uint32(0x08000101); // react state
- +
- + charmInfo->BuildActionBar(&data);
- +
- + data << uint8(0); // additional spells count
- + data << uint8(cooldownsCount);
- +
- + time_t curTime = time(NULL);
- +
- + for (CreatureSpellCooldowns::const_iterator itr = charm->m_CreatureSpellCooldowns.begin(); itr != charm->m_CreatureSpellCooldowns.end(); ++itr)
- + {
- + time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILLISECONDS : 0;
- +
- + data << uint32(itr->first); // spellid
- + data << uint16(0); // spell category?
- + data << uint32(cooldown); // cooldown
- + data << uint32(0); // category cooldown
- + }
- +
- + for (CreatureSpellCooldowns::const_iterator itr = charm->m_CreatureCategoryCooldowns.begin(); itr != charm->m_CreatureCategoryCooldowns.end(); ++itr)
- + {
- + time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILLISECONDS : 0;
- +
- + data << uint32(itr->first); // spellid
- + data << uint16(0); // spell category?
- + data << uint32(0); // cooldown
- + data << uint32(cooldown); // category cooldown
- + }
- +
- + GetSession()->SendPacket(&data);
- +}
- +
- void Player::CharmSpellInitialize()
- {
- Unit* charm = GetCharm();
- @@ -18785,7 +18816,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
- if (npc)
- {
- // not let cheating with start flight mounted
- - if (IsMounted())
- + if (IsMounted() || GetVehicle())
- {
- WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
- data << uint32(ERR_TAXIPLAYERALREADYMOUNTED);
- @@ -18814,6 +18845,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
- else
- {
- RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
- + ExitVehicle();
- if (IsInDisallowedMountForm())
- RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
- @@ -20201,6 +20233,14 @@ void Player::SendInitialPacketsAfterAddToMap()
- SendMessageToSet(&data2,true);
- }
- + if(GetVehicle())
- + {
- + WorldPacket data3(SMSG_FORCE_MOVE_ROOT, 10);
- + data3 << GetPackGUID();
- + data3 << uint32((m_movementInfo.GetVehicleSeatFlags() & SEAT_FLAG_CAN_CAST) ? 2 : 0);
- + SendMessageToSet(&data3,true);
- + }
- +
- SendAurasForTarget(this);
- SendEnchantmentDurations(); // must be after add to map
- SendItemDurations(); // must be after add to map
- diff --git a/src/game/Player.h b/src/game/Player.h
- index 0b5a80b..8fbd6f5 100644
- --- a/src/game/Player.h
- +++ b/src/game/Player.h
- @@ -48,7 +48,6 @@ class Channel;
- class DynamicObject;
- class Creature;
- class PlayerMenu;
- -class Transport;
- class UpdateMask;
- class SpellCastTargets;
- class PlayerSocial;
- @@ -1552,6 +1551,7 @@ class MANGOS_DLL_SPEC Player : public Unit
- void SendPetGUIDs();
- void CharmSpellInitialize();
- void PossessSpellInitialize();
- + void VehicleSpellInitialize();
- void RemovePetActionBar();
- bool HasSpell(uint32 spell) const;
- @@ -2172,17 +2172,6 @@ class MANGOS_DLL_SPEC Player : public Unit
- ObjectGuid const& GetFarSightGuid() const { return GetGuidValue(PLAYER_FARSIGHT); }
- - // Transports
- - Transport * GetTransport() const { return m_transport; }
- - void SetTransport(Transport * t) { m_transport = t; }
- -
- - float GetTransOffsetX() const { return m_movementInfo.GetTransportPos()->x; }
- - float GetTransOffsetY() const { return m_movementInfo.GetTransportPos()->y; }
- - float GetTransOffsetZ() const { return m_movementInfo.GetTransportPos()->z; }
- - float GetTransOffsetO() const { return m_movementInfo.GetTransportPos()->o; }
- - uint32 GetTransTime() const { return m_movementInfo.GetTransportTime(); }
- - int8 GetTransSeat() const { return m_movementInfo.GetTransportSeat(); }
- -
- uint32 GetSaveTimer() const { return m_nextSave; }
- void SetSaveTimer(uint32 timer) { m_nextSave = timer; }
- @@ -2519,9 +2508,6 @@ class MANGOS_DLL_SPEC Player : public Unit
- RestType rest_type;
- ////////////////////Rest System/////////////////////
- - // Transports
- - Transport * m_transport;
- -
- uint32 m_resetTalentsCost;
- time_t m_resetTalentsTime;
- uint32 m_usedTalentCount;
- diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp
- index ed7dab0..3355d63 100644
- --- a/src/game/QueryHandler.cpp
- +++ b/src/game/QueryHandler.cpp
- @@ -179,7 +179,7 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data )
- data << uint32(ci->ModelId[i]);
- data << float(ci->unk16); // health modifier
- - data << float(ci->unk17); // power modifier
- + data << float(ci->power_mod); // power modifier
- data << uint8(ci->RacialLeader);
- for(uint32 i = 0; i < 6; ++i)
- data << uint32(ci->questItems[i]); // itemId[6], quest drop
- diff --git a/src/game/ReactorAI.cpp b/src/game/ReactorAI.cpp
- index 0a32c86..70b6393 100644
- --- a/src/game/ReactorAI.cpp
- +++ b/src/game/ReactorAI.cpp
- @@ -109,6 +109,7 @@ ReactorAI::EnterEvadeMode()
- 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());
- }
- + m_creature->ExitVehicle();
- m_creature->RemoveAllAuras();
- m_creature->DeleteThreatList();
- i_victimGuid.Clear();
- diff --git a/src/game/SQLStorages.cpp b/src/game/SQLStorages.cpp
- index 716f10c..1e0434d 100644
- --- a/src/game/SQLStorages.cpp
- +++ b/src/game/SQLStorages.cpp
- @@ -21,8 +21,8 @@
- #include "Database/SQLStorageImpl.h"
- #include "Database/DatabaseEnv.h"
- -const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiiiiis";
- -const char CreatureInfodstfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiiiiii";
- +const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiiiiis";
- +const char CreatureInfodstfmt[]="iiiiiiiiiisssiiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiiiiii";
- const char CreatureDataAddonInfofmt[]="iiibbiis";
- const char CreatureModelfmt[]="iffbii";
- const char CreatureInfoAddonInfofmt[]="iiibbiis";
- diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
- index 349a25f..38aea15 100644
- --- a/src/game/SharedDefines.h
- +++ b/src/game/SharedDefines.h
- @@ -155,6 +155,17 @@ enum Powers
- #define MAX_POWERS 7
- +enum EnergyType
- +{
- + ENERGY_TYPE_UNK0 = 0, // Possible mana or flat energy.
- + ENERGY_TYPE_UNK1 = 1, // 2 vehicles in 3.3.5a
- + ENERGY_TYPE_PYRITE = 41, // 2 vehicles in 3.3.5a
- + ENERGY_TYPE_STEAM = 61, // 9 vehicles in 3.3.5a
- + ENERGY_TYPE_OOZE = 121, // 1 vehicle in 3.3.5a
- + ENERGY_TYPE_BLOOD = 141, // 1 vehicle in 3.3.5a
- + ENERGY_TYPE_UNK142 = 142, // 1 vehicle in 3.3.5a
- +};
- +
- enum SpellSchools
- {
- SPELL_SCHOOL_NORMAL = 0,
- @@ -1226,6 +1237,7 @@ enum Targets
- TARGET_DYNAMIC_OBJECT_BEHIND = 48,
- TARGET_DYNAMIC_OBJECT_LEFT_SIDE = 49,
- TARGET_DYNAMIC_OBJECT_RIGHT_SIDE = 50,
- + TARGET_OBJECT_AREA_SRC = 51,
- TARGET_AREAEFFECT_GO_AROUND_DEST = 52, // gameobject around destination, select by spell_script_target
- TARGET_CURRENT_ENEMY_COORDINATES = 53, // set unit coordinates as dest, only 16 target B imlemented
- TARGET_LARGE_FRONTAL_CONE = 54,
- @@ -1255,9 +1267,28 @@ enum Targets
- TARGET_DIRECTLY_FORWARD = 89,
- TARGET_NONCOMBAT_PET = 90,
- TARGET_91 = 91,
- + TARGET_93 = 93,
- + TARGET_OWNED_VEHICLE = 94,
- + TARGET_UNIT_DRIVER = 95,
- + TARGET_UNIT_PASSENGER_0 = 96,
- + TARGET_UNIT_PASSENGER_1 = 97,
- + TARGET_UNIT_PASSENGER_2 = 98,
- + TARGET_UNIT_PASSENGER_3 = 99,
- + TARGET_UNIT_PASSENGER_4 = 100,
- + TARGET_UNIT_PASSENGER_5 = 101,
- + TARGET_UNIT_PASSENGER_6 = 102,
- + TARGET_UNIT_PASSENGER_7 = 103,
- TARGET_IN_FRONT_OF_CASTER_30 = 104,
- + TARGET_105 = 105,
- + TARGET_106 = 106,
- + TARGET_107 = 107,
- + TARGET_108 = 108,
- + TARGET_109 = 109,
- + TARGET_110 = 110,
- };
- +#define MAX_SPELL_TARGET 110
- +
- enum SpellMissInfo
- {
- SPELL_MISS_NONE = 0,
- @@ -1369,8 +1400,8 @@ enum GameObjectFlags
- GO_FLAG_TRIGGERED = 0x00000040, //typically, summoned objects. Triggered by spell or other events
- GO_FLAG_UNK_8 = 0x00000080,
- GO_FLAG_UNK_9 = 0x00000100, //? Seen on type 33, possible meaning "destruct in progress"
- - GO_FLAG_UNK_10 = 0x00000200, //? Seen on type 33
- - GO_FLAG_UNK_11 = 0x00000400 //? Seen on type 33, possibly meaning "destructed"
- + GO_FLAG_DAMAGED = 0x00000200, //Seen on type 33
- + GO_FLAG_DESTROYED = 0x00000400 //Seen on type 33, meaning "destroyed"
- };
- enum GameObjectDynamicLowFlags
- diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
- index c67cf76..23866b3 100644
- --- a/src/game/Spell.cpp
- +++ b/src/game/Spell.cpp
- @@ -43,6 +43,7 @@
- #include "VMapFactory.h"
- #include "BattleGround.h"
- #include "Util.h"
- +#include "Vehicle.h"
- #include "Chat.h"
- #define SPELL_CHANNEL_UPDATE_INTERVAL (1 * IN_MILLISECONDS)
- @@ -1995,6 +1996,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
- }
- break;
- }
- + case TARGET_OBJECT_AREA_SRC:
- case TARGET_AREAEFFECT_GO_AROUND_DEST:
- {
- // It may be possible to fill targets for some spell effects
- @@ -2003,20 +2005,49 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
- // Some spells untested, for affected GO type 33. May need further adjustments for spells related.
- - SpellScriptTargetBounds bounds = sSpellMgr.GetSpellScriptTargetBounds(m_spellInfo->Id);
- + float x, y, z;
- + if (targetMode == TARGET_OBJECT_AREA_SRC)
- + {
- + if (m_targets.m_targetMask & TARGET_FLAG_SOURCE_LOCATION)
- + {
- + x = m_targets.m_srcX;
- + y = m_targets.m_srcY;
- + z = m_targets.m_srcZ;
- + }
- + else
- + break;
- + }
- + else if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
- + {
- + x = m_targets.m_destX;
- + y = m_targets.m_destY;
- + z = m_targets.m_destZ;
- + }
- + else
- + break;
- + SpellScriptTargetBounds bounds = sSpellMgr.GetSpellScriptTargetBounds(m_spellInfo->Id);
- std::list<GameObject*> tempTargetGOList;
- - for(SpellScriptTarget::const_iterator i_spellST = bounds.first; i_spellST != bounds.second; ++i_spellST)
- + if (bounds.first != bounds.second)
- {
- - if (i_spellST->second.type == SPELL_TARGET_TYPE_GAMEOBJECT)
- + for(SpellScriptTarget::const_iterator i_spellST = bounds.first; i_spellST != bounds.second; ++i_spellST)
- {
- - // search all GO's with entry, within range of m_destN
- - MaNGOS::GameObjectEntryInPosRangeCheck go_check(*m_caster, i_spellST->second.targetEntry, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, radius);
- - MaNGOS::GameObjectListSearcher<MaNGOS::GameObjectEntryInPosRangeCheck> checker(tempTargetGOList, go_check);
- - Cell::VisitGridObjects(m_caster, checker, radius);
- + if (i_spellST->second.type == SPELL_TARGET_TYPE_GAMEOBJECT)
- + {
- + // search all GO's with entry, within range of m_destN
- + MaNGOS::GameObjectEntryInPosRangeCheck go_check(*m_caster, i_spellST->second.targetEntry, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, radius);
- + MaNGOS::GameObjectListSearcher<MaNGOS::GameObjectEntryInPosRangeCheck> checker(tempTargetGOList, go_check);
- + Cell::VisitGridObjects(m_caster, checker, radius);
- + }
- }
- }
- + else
- + {
- + MaNGOS::GameObjectInRangeCheck check(m_caster, x, y, z, radius + 15.0f);
- + MaNGOS::GameObjectListSearcher<MaNGOS::GameObjectInRangeCheck> searcher(tempTargetGOList, check);
- + Cell::VisitAllObjects(m_caster, searcher, radius);
- + }
- if (!tempTargetGOList.empty())
- {
- @@ -2101,6 +2132,23 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
- if( target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->IsPet() && ((Pet*)target)->getPetType() == MINI_PET)
- targetUnitMap.push_back(target);
- break;
- + case TARGET_OWNED_VEHICLE:
- + if (VehicleKit* vehicle = m_caster->GetVehicle())
- + if (Unit* target = vehicle->GetBase())
- + targetUnitMap.push_back(target);
- + break;
- + case TARGET_UNIT_PASSENGER_0:
- + case TARGET_UNIT_PASSENGER_1:
- + case TARGET_UNIT_PASSENGER_2:
- + case TARGET_UNIT_PASSENGER_3:
- + case TARGET_UNIT_PASSENGER_4:
- + case TARGET_UNIT_PASSENGER_5:
- + case TARGET_UNIT_PASSENGER_6:
- + case TARGET_UNIT_PASSENGER_7:
- + if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->GetObjectGuid().IsVehicle())
- + if (Unit *unit = m_caster->GetVehicleKit()->GetPassenger(targetMode - TARGET_UNIT_PASSENGER_0))
- + targetUnitMap.push_back(unit);
- + break;
- case TARGET_CASTER_COORDINATES:
- {
- // Check original caster is GO - set its coordinates as dst cast
- @@ -3398,8 +3446,8 @@ void Spell::update(uint32 difftime)
- return;
- }
- - // check if the player caster has moved before the spell finished
- - if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) &&
- + // check if the player caster has moved before the spell finished (exclude casting on vehicles)
- + if (!m_caster->GetVehicle() && (m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) &&
- (m_castPositionX != m_caster->GetPositionX() || m_castPositionY != m_caster->GetPositionY() || m_castPositionZ != m_caster->GetPositionZ()) &&
- (m_spellInfo->Effect[EFFECT_INDEX_0] != SPELL_EFFECT_STUCK || !((Player*)m_caster)->m_movementInfo.HasMovementFlag(MOVEFLAG_FALLINGFAR)))
- {
- @@ -4859,8 +4907,15 @@ SpellCastResult Spell::CheckCast(bool strict)
- if (locRes != SPELL_CAST_OK)
- return locRes;
- + bool castOnVehicleAllowed = false;
- +
- + if (m_caster->GetVehicle())
- + if ( VehicleSeatEntry const* seatInfo = m_caster->GetVehicle()->GetSeatInfo(m_caster))
- + if (seatInfo->m_flags & SEAT_FLAG_CAN_CAST || seatInfo->m_flags & SEAT_FLAG_CAN_ATTACK)
- + castOnVehicleAllowed = true;
- +
- // not let players cast spells at mount (and let do it to creatures)
- - if (m_caster->IsMounted() && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell &&
- + if ((m_caster->IsMounted() || (m_caster->GetVehicle() && !castOnVehicleAllowed)) && m_caster->GetTypeId() == TYPEID_PLAYER && !m_IsTriggeredSpell &&
- !IsPassiveSpell(m_spellInfo) && !(m_spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_MOUNTED))
- {
- if (m_caster->IsTaxiFlying())
- @@ -5732,26 +5787,45 @@ SpellCastResult Spell::CheckPetCast(Unit* target)
- if(_target) //for target dead/target not valid
- {
- - if (!_target->isTargetableForAttack())
- - return SPELL_FAILED_BAD_TARGETS; // guessed error
- -
- - if(IsPositiveSpell(m_spellInfo->Id))
- + if(IsPositiveSpell(m_spellInfo->Id) && !IsDispelSpell(m_spellInfo))
- {
- if(m_caster->IsHostileTo(_target))
- + {
- + DEBUG_LOG("Charmed creature attempt to cast positive spell %d, but target (guid %u) is hostile",m_spellInfo->Id, target->GetObjectGuid().GetRawValue());
- return SPELL_FAILED_BAD_TARGETS;
- + }
- + }
- + else if (!_target->isTargetableForAttack() || (!_target->isVisibleForOrDetect(m_caster,m_caster,true) && !m_IsTriggeredSpell))
- + {
- + 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());
- + return SPELL_FAILED_BAD_TARGETS; // guessed error
- }
- else
- {
- - bool duelvsplayertar = false;
- + bool dualEffect = false;
- for(int j = 0; j < MAX_EFFECT_INDEX; ++j)
- {
- - //TARGET_DUELVSPLAYER is positive AND negative
- - duelvsplayertar |= (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DUELVSPLAYER);
- + // This effects is positive AND negative. Need for vehicles cast.
- + dualEffect |= (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DUELVSPLAYER
- + || m_spellInfo->EffectImplicitTargetA[j] == TARGET_IN_FRONT_OF_CASTER_30
- + || m_spellInfo->EffectImplicitTargetA[j] == TARGET_MASTER
- + || m_spellInfo->EffectImplicitTargetA[j] == TARGET_IN_FRONT_OF_CASTER
- + || m_spellInfo->EffectImplicitTargetA[j] == TARGET_EFFECT_SELECT
- + || m_spellInfo->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE
- + || m_spellInfo->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES);
- }
- - if(m_caster->IsFriendlyTo(target) && !duelvsplayertar)
- + if (m_caster->IsFriendlyTo(_target) && !(!m_caster->GetCharmerOrOwner() || !m_caster->GetCharmerOrOwner()->IsFriendlyTo(_target))
- + && !dualEffect && !IsDispelSpell(m_spellInfo) && !m_caster->GetVehicleKit())
- {
- + DEBUG_LOG("Charmed creature attempt to cast spell %d, but target (guid %u) is not valid",m_spellInfo->Id,_target->GetObjectGuid().GetRawValue());
- return SPELL_FAILED_BAD_TARGETS;
- }
- +
- + if (m_caster->GetObjectGuid() == _target->GetObjectGuid() && dualEffect && !IsPositiveSpell(m_spellInfo->Id))
- + {
- + DEBUG_LOG("Charmed creature %u attempt to cast negative spell %d on self",_target->GetObjectGuid().GetRawValue(),m_spellInfo->Id);
- +// return SPELL_FAILED_BAD_TARGETS;
- + }
- }
- }
- //cooldown
- @@ -6769,7 +6843,7 @@ bool Spell::CheckTarget( Unit* target, SpellEffectIndex eff )
- if (target != m_caster && target->GetCharmerOrOwnerGuid() != m_caster->GetObjectGuid())
- {
- // any unattackable target skipped
- - if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- + if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) && target->GetObjectGuid() != m_caster->GetCharmerOrOwnerGuid())
- return false;
- // unselectable targets skipped in all cases except TARGET_SCRIPT targeting
- @@ -6785,6 +6859,13 @@ bool Spell::CheckTarget( Unit* target, SpellEffectIndex eff )
- return false;
- }
- + if (target != m_caster && m_caster->GetCharmerOrOwnerGuid() == target->GetObjectGuid())
- + {
- + if (m_spellInfo->EffectImplicitTargetA[eff] == TARGET_MASTER ||
- + m_spellInfo->EffectImplicitTargetB[eff] == TARGET_MASTER)
- + return true;
- + }
- +
- // Check player targets and remove if in GM mode or GM invisibility (for not self casting case)
- if( target != m_caster && target->GetTypeId() == TYPEID_PLAYER)
- {
- diff --git a/src/game/Spell.h b/src/game/Spell.h
- index 6fff7e2..d46b907 100644
- --- a/src/game/Spell.h
- +++ b/src/game/Spell.h
- @@ -340,6 +340,9 @@ class Spell
- void EffectActivateRune(SpellEffectIndex eff_idx);
- void EffectTeachTaxiNode(SpellEffectIndex eff_idx);
- + void EffectWMODamage(SpellEffectIndex eff_idx);
- + void EffectWMORepair(SpellEffectIndex eff_idx);
- + void EffectWMOChange(SpellEffectIndex eff_idx);
- void EffectTitanGrip(SpellEffectIndex eff_idx);
- void EffectEnchantItemPrismatic(SpellEffectIndex eff_idx);
- void EffectPlayMusic(SpellEffectIndex eff_idx);
- @@ -392,6 +395,7 @@ class Spell
- void DoSummonGuardian(SpellEffectIndex eff_idx, uint32 forceFaction = 0);
- void DoSummonTotem(SpellEffectIndex eff_idx, uint8 slot_dbc = 0);
- void DoSummonCritter(SpellEffectIndex eff_idx, uint32 forceFaction = 0);
- + void DoSummonVehicle(SpellEffectIndex eff_idx, uint32 forceFaction = 0);
- void WriteSpellGoTargets(WorldPacket* data);
- void WriteAmmoToPacket(WorldPacket* data);
- diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
- index 6b39004..bcb5ff6 100644
- --- a/src/game/SpellAuras.cpp
- +++ b/src/game/SpellAuras.cpp
- @@ -346,7 +346,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
- &Aura::HandleAuraAddMechanicAbilities, //293 SPELL_AURA_ADD_MECHANIC_ABILITIES replaces target's action bars with a predefined spellset
- &Aura::HandleAuraStopNaturalManaRegen, //294 SPELL_AURA_STOP_NATURAL_MANA_REGEN implemented in Player:Regenerate
- &Aura::HandleUnused, //295 unused (3.2.2a)
- - &Aura::HandleNULL, //296 2 spells
- + &Aura::HandleAuraSetVehicle, //296 SPELL_AURA_SET_VEHICLE_ID sets vehicle on target
- &Aura::HandleNULL, //297 1 spell (counter spell school?)
- &Aura::HandleUnused, //298 unused (3.2.2a)
- &Aura::HandleUnused, //299 unused (3.2.2a)
- @@ -3115,7 +3115,7 @@ void Aura::HandleAuraMounted(bool apply, bool Real)
- if (minfo)
- display_id = minfo->modelid;
- - target->Mount(display_id, GetId());
- + target->Mount(display_id, GetId(), ci->vehicleId, GetMiscValue());
- }
- else
- {
- @@ -3949,7 +3949,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
- {
- ((Creature*)target)->AIM_Initialize();
- }
- - else if(target->GetTypeId() == TYPEID_PLAYER)
- + else if(target->GetTypeId() == TYPEID_PLAYER && !target->GetVehicle())
- {
- ((Player*)target)->SetClientControl(target, 0);
- }
- @@ -3982,7 +3982,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
- target->SetCharmerGuid(ObjectGuid());
- - if(target->GetTypeId() == TYPEID_PLAYER)
- + if(target->GetTypeId() == TYPEID_PLAYER && !target->GetVehicle())
- {
- ((Player*)target)->setFactionForRace(target->getRace());
- ((Player*)target)->SetClientControl(target, 1);
- @@ -4359,7 +4359,7 @@ void Aura::HandleAuraModStun(bool apply, bool Real)
- target->clearUnitState(UNIT_STAT_STUNNED);
- target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
- - if(!target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
- + if(!target->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_ON_VEHICLE)) // prevent allow move if have also root effect
- {
- if(target->getVictim() && target->isAlive())
- target->SetTargetGuid(target->getVictim()->GetObjectGuid());
- @@ -4595,10 +4595,13 @@ void Aura::HandleAuraModRoot(bool apply, bool Real)
- if(target->GetTypeId() == TYPEID_PLAYER)
- {
- - WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
- - data << target->GetPackGUID();
- - data << (uint32)2;
- - target->SendMessageToSet(&data, true);
- + if(!target->hasUnitState(UNIT_STAT_ON_VEHICLE))
- + {
- + WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
- + data << target->GetPackGUID();
- + data << uint32(2);
- + target->SendMessageToSet(&data, true);
- + }
- //Clear unit movement flags
- ((Player*)target)->m_movementInfo.SetMovementFlags(MOVEFLAG_NONE);
- @@ -4637,7 +4640,7 @@ void Aura::HandleAuraModRoot(bool apply, bool Real)
- target->clearUnitState(UNIT_STAT_ROOT);
- - if(!target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
- + if(!target->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ON_VEHICLE)) // prevent allow move if have also stun effect
- {
- if(target->getVictim() && target->isAlive())
- target->SetTargetGuid(target->getVictim()->GetObjectGuid());
- @@ -8150,14 +8153,15 @@ void Aura::HandleAuraControlVehicle(bool apply, bool Real)
- if (caster->GetTypeId() == TYPEID_PLAYER)
- ((Player*)caster)->RemovePet(PET_SAVE_AS_CURRENT);
- - //caster->EnterVehicle(target);
- + caster->EnterVehicle(target->GetVehicleKit());
- }
- else
- {
- // some SPELL_AURA_CONTROL_VEHICLE auras have a dummy effect on the player - remove them
- caster->RemoveAurasDueToSpell(GetId());
- - //caster->ExitVehicle();
- + if (caster->GetVehicleKit() == target->GetVehicleKit())
- + caster->ExitVehicle();
- if (caster->GetTypeId() == TYPEID_PLAYER)
- ((Player*)caster)->ResummonPetTemporaryUnSummonedIfAny();
- @@ -9776,3 +9780,38 @@ void SpellAuraHolder::UnregisterSingleCastHolder()
- m_isSingleTarget = false;
- }
- }
- +
- +void Aura::HandleAuraSetVehicle(bool apply, bool real)
- +{
- + if (!real)
- + return;
- +
- + Unit* target = GetTarget();
- +
- + if (target->GetTypeId() != TYPEID_PLAYER || !target->IsInWorld())
- + return;
- +
- + uint32 vehicleId = GetMiscValue();
- +
- + if (vehicleId == 0)
- + return;
- +
- + if (apply)
- + {
- + target->SetVehicleId(vehicleId);
- + }
- + else
- + if (target->GetVehicleKit())
- + target->RemoveVehicleKit();
- +
- + WorldPacket data(SMSG_SET_VEHICLE_REC_ID, target->GetPackGUID().size()+4);
- + data << target->GetPackGUID();
- + data << uint32(apply ? vehicleId : 0);
- + target->SendMessageToSet(&data, true);
- +
- + if (apply)
- + {
- + data.Initialize(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
- + ((Player*)target)->GetSession()->SendPacket(&data);
- + }
- +}
- diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h
- index e7bc4ca..99b5690 100644
- --- a/src/game/SpellAuras.h
- +++ b/src/game/SpellAuras.h
- @@ -352,6 +352,7 @@ class MANGOS_DLL_SPEC Aura
- void HandleModSpellHealingPercentFromStat(bool apply, bool Real);
- void HandleAuraModDispelResist(bool apply, bool Real);
- void HandleAuraControlVehicle(bool apply, bool Real);
- + void HandleAuraSetVehicle(bool apply, bool Real);
- void HandleModSpellDamagePercentFromAttackPower(bool apply, bool Real);
- void HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real);
- void HandleAuraModPacifyAndSilence(bool Apply, bool Real);
- diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
- index f4832d9..155087b 100644
- --- a/src/game/SpellEffects.cpp
- +++ b/src/game/SpellEffects.cpp
- @@ -147,9 +147,9 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
- &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
- &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
- &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
- - &Spell::EffectNULL, // 87 SPELL_EFFECT_WMO_DAMAGE (57 spells in 3.3.2)
- - &Spell::EffectNULL, // 88 SPELL_EFFECT_WMO_REPAIR (2 spells in 3.3.2)
- - &Spell::EffectNULL, // 89 SPELL_EFFECT_WMO_CHANGE (7 spells in 3.3.2)
- + &Spell::EffectWMODamage, // 87 SPELL_EFFECT_WMO_DAMAGE (57 spells in 3.3.2)
- + &Spell::EffectWMORepair, // 88 SPELL_EFFECT_WMO_REPAIR (2 spells in 3.3.2)
- + &Spell::EffectWMOChange, // 89 SPELL_EFFECT_WMO_CHANGE (7 spells in 3.3.2)
- &Spell::EffectKillCreditPersonal, // 90 SPELL_EFFECT_KILL_CREDIT_PERSONAL Kill credit but only for single person
- &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
- &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
- @@ -4605,6 +4605,7 @@ void Spell::EffectSummonType(SpellEffectIndex eff_idx)
- case UNITNAME_SUMMON_TITLE_MOUNT:
- // TODO
- // EffectSummonVehicle(i);
- + DoSummonVehicle(eff_idx, summon_prop->FactionId);
- break;
- default:
- sLog.outError("EffectSummonType: Unhandled summon title %u", summon_prop->Title);
- @@ -4631,10 +4632,11 @@ void Spell::EffectSummonType(SpellEffectIndex eff_idx)
- break;
- }
- case SUMMON_PROP_GROUP_VEHICLE:
- + case SUMMON_PROP_GROUP_UNCONTROLLABLE_VEHICLE:
- {
- // TODO
- // EffectSummonVehicle(i);
- - sLog.outDebug("EffectSummonType: Unhandled summon group type SUMMON_PROP_GROUP_VEHICLE(%u)", summon_prop->Group);
- + DoSummonVehicle(eff_idx, summon_prop->FactionId);
- break;
- }
- default:
- @@ -5176,6 +5178,68 @@ void Spell::DoSummonGuardian(SpellEffectIndex eff_idx, uint32 forceFaction)
- }
- }
- +void Spell::DoSummonVehicle(SpellEffectIndex eff_idx, uint32 forceFaction)
- +{
- + if (!m_caster)
- + return;
- +
- + if (m_caster->hasUnitState(UNIT_STAT_ON_VEHICLE))
- + {
- + if (m_spellInfo->Attributes & SPELL_ATTR_UNK7)
- + m_caster->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE);
- + else
- + return;
- + }
- +
- + uint32 vehicle_entry = m_spellInfo->EffectMiscValue[eff_idx];
- +
- + if (!vehicle_entry)
- + return;
- +
- + SpellEntry const* m_mountspell = sSpellStore.LookupEntry(m_spellInfo->EffectBasePoints[eff_idx] != 0 ? m_spellInfo->CalculateSimpleValue(eff_idx) : 46598);
- +
- + if (!m_mountspell)
- + m_mountspell = sSpellStore.LookupEntry(46598);
- + // Used BasePoint mount spell, if not present - hardcoded (by Blzz).
- +
- + float px, py, pz;
- + // If dest location present
- + if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
- + {
- + px = m_targets.m_destX;
- + py = m_targets.m_destY;
- + pz = m_targets.m_destZ;
- + }
- + // Summon if dest location not present near caster
- + else
- + m_caster->GetClosePoint(px, py, pz,m_caster->GetObjectBoundingRadius());
- +
- + TempSummonType summonType = (GetSpellDuration(m_spellInfo) == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
- +
- + Creature* vehicle = m_caster->SummonCreature(vehicle_entry,px,py,pz,m_caster->GetOrientation(),summonType,GetSpellDuration(m_spellInfo),true);
- +
- + if (vehicle && !vehicle->GetObjectGuid().IsVehicle())
- + {
- + sLog.outError("DoSommonVehicle: Creature (guidlow %d, entry %d) summoned, but this is not vehicle. Correct VehicleId in creature_template.", vehicle->GetGUIDLow(), vehicle->GetEntry());
- + vehicle->ForcedDespawn();
- + return;
- + }
- +
- + if (vehicle)
- + {
- + vehicle->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
- + vehicle->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
- + m_caster->CastSpell(vehicle, m_mountspell, true);
- + 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);
- +
- + // Notify Summoner
- + if (m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->AI())
- + ((Creature*)m_caster)->AI()->JustSummoned(vehicle);
- + }
- + else
- + sLog.outError("Vehicle (guidlow %d, entry %d) NOT summoned by undefined reason. ", vehicle->GetGUIDLow(), vehicle->GetEntry());
- +}
- +
- void Spell::EffectTeleUnitsFaceCaster(SpellEffectIndex eff_idx)
- {
- if (!unitTarget)
- @@ -9203,3 +9267,85 @@ void Spell::EffectCancelAura(SpellEffectIndex eff_idx)
- unitTarget->RemoveAurasDueToSpell(spellId);
- }
- +
- +void Spell::EffectWMODamage(SpellEffectIndex eff_idx)
- +{
- + if (!gameObjTarget || gameObjTarget->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING || !gameObjTarget->GetHealth())
- + {
- + DEBUG_LOG( "Spell::EffectWMODamage called, but no valid targets. Spell ID %u", m_spellInfo->Id );
- + return;
- + }
- +
- + Unit *caster = m_originalCaster;
- +
- + if (!caster)
- + return;
- +
- + DEBUG_LOG( "Spell::EffectWMODamage, spell ID %u, object %u, damage %u", m_spellInfo->Id,gameObjTarget->GetEntry(),uint32(damage));
- +
- + gameObjTarget->DamageTaken(caster, uint32(damage));
- +
- + WorldPacket data(SMSG_DESTRUCTIBLE_BUILDING_DAMAGE, 8+8+8+4+4);
- + data << gameObjTarget->GetPackGUID();
- + data << caster->GetPackGUID();
- +
- + if (Unit *who = caster->GetCharmerOrOwner()) //check for pet / vehicle
- + data << who->GetPackGUID();
- + else
- + data << caster->GetPackGUID();
- +
- + data << uint32(damage);
- + data << uint32(m_spellInfo->Id);
- +
- + gameObjTarget->SendMessageToSet(&data, false);
- +}
- +
- +void Spell::EffectWMORepair(SpellEffectIndex eff_idx)
- +{
- + if (gameObjTarget && gameObjTarget->GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
- + {
- + DEBUG_LOG( "Spell::EffectWMORepair, spell ID %u, object %u", m_spellInfo->Id,gameObjTarget->GetEntry());
- + gameObjTarget->Rebuild(m_caster);
- + }
- + else
- + DEBUG_LOG( "Spell::EffectWMORepair called, but no valid targets. Spell ID %u", m_spellInfo->Id);
- +
- +}
- +
- +void Spell::EffectWMOChange(SpellEffectIndex eff_idx)
- +{
- + if (gameObjTarget && gameObjTarget->GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
- + {
- + DEBUG_LOG( "Spell::EffectWMOChange, spell ID %u, object %u, command %u", m_spellInfo->Id,gameObjTarget->GetEntry(), m_spellInfo->EffectMiscValue[eff_idx]);
- +
- + Unit* caster = m_originalCaster;
- +
- + if (!caster)
- + return;
- +
- + switch (m_spellInfo->EffectMiscValue[eff_idx])
- + {
- + case 0: // intact
- + if (gameObjTarget->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED))
- + gameObjTarget->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED);
- + if (gameObjTarget->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED))
- + gameObjTarget->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED);
- + break;
- + case 1: // damaged
- + gameObjTarget->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED);
- + break;
- + case 2: // destroyed
- + gameObjTarget->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED);
- + break;
- + case 3: // rebuild
- + gameObjTarget->Rebuild(caster);
- + break;
- + default:
- + DEBUG_LOG( "Spell::EffectWMOChange, spell ID %u with defined change value %u", m_spellInfo->Id,m_spellInfo->EffectMiscValue[eff_idx]);
- + break;
- + }
- + }
- + else
- + DEBUG_LOG( "Spell::EffectWMORepair called, but no valid targets. Spell ID %u", m_spellInfo->Id);
- +
- +}
- diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp
- index dbaa32d..bb3a295 100644
- --- a/src/game/SpellHandler.cpp
- +++ b/src/game/SpellHandler.cpp
- @@ -343,8 +343,8 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
- recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received)
- // ignore for remote control state (for player case)
- - Unit* mover = _player->GetMover();
- - if (mover != _player && mover->GetTypeId()==TYPEID_PLAYER)
- + Unit* _mover = GetPlayer()->GetMover();
- + if (_mover != GetPlayer() && _mover->GetTypeId()==TYPEID_PLAYER)
- {
- recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
- return;
- @@ -362,6 +362,25 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
- return;
- }
- + // Players on vehicles may cast many simple spells (like knock) from self
- +
- + Unit* mover = NULL;
- +
- + if (spellInfo->AttributesEx6 & SPELL_ATTR_EX6_UNK12 && _mover->IsCharmerOrOwnerPlayerOrPlayerItself())
- + mover = _mover->GetCharmerOrOwnerPlayerOrPlayerItself();
- + else
- + mover = _mover;
- +
- + // casting own spells on some vehicles
- + if (mover->GetObjectGuid().IsVehicle() && mover->GetCharmerOrOwnerPlayerOrPlayerItself())
- + {
- + Player *plr = mover->GetCharmerOrOwnerPlayerOrPlayerItself();
- + if (mover->GetVehicleKit()->GetSeatInfo(plr) &&
- + (mover->GetVehicleKit()->GetSeatInfo(plr)->m_flags & SEAT_FLAG_CAN_ATTACK ||
- + mover->GetVehicleKit()->GetSeatInfo(plr)->m_flags & SEAT_FLAG_CAN_CAST ))
- + mover = plr;
- + }
- +
- if (mover->GetTypeId()==TYPEID_PLAYER)
- {
- // not have spell in spellbook or spell passive and not casted by client
- @@ -604,11 +623,11 @@ void WorldSession::HandleSpellClick( WorldPacket & recv_data )
- ObjectGuid guid;
- recv_data >> guid;
- - if (_player->isInCombat()) // client prevent click and set different icon at combat state
- + if (_player->isInCombat() && !guid.IsVehicle()) // client prevent click and set different icon at combat state
- return;
- Creature *unit = _player->GetMap()->GetAnyTypeCreature(guid);
- - if (!unit || unit->isInCombat()) // client prevent click and set different icon at combat state
- + if (!unit)
- return;
- SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(unit->GetEntry());
- diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
- index 1f8630d..2ea8e22 100644
- --- a/src/game/SpellMgr.cpp
- +++ b/src/game/SpellMgr.cpp
- @@ -3216,6 +3216,8 @@ void SpellMgr::LoadSpellScriptTarget()
- spellProto->EffectImplicitTargetB[i] == TARGET_AREAEFFECT_INSTANT ||
- spellProto->EffectImplicitTargetA[i] == TARGET_AREAEFFECT_CUSTOM ||
- spellProto->EffectImplicitTargetB[i] == TARGET_AREAEFFECT_CUSTOM ||
- + spellProto->EffectImplicitTargetA[i] == TARGET_OBJECT_AREA_SRC ||
- + spellProto->EffectImplicitTargetB[i] == TARGET_OBJECT_AREA_SRC ||
- spellProto->EffectImplicitTargetA[i] == TARGET_AREAEFFECT_GO_AROUND_DEST ||
- spellProto->EffectImplicitTargetB[i] == TARGET_AREAEFFECT_GO_AROUND_DEST)
- {
- @@ -3480,7 +3482,7 @@ bool SpellMgr::LoadPetDefaultSpells_helper(CreatureInfo const* cInfo, PetDefault
- void SpellMgr::LoadPetDefaultSpells()
- {
- - MANGOS_ASSERT(MAX_CREATURE_SPELL_DATA_SLOT==CREATURE_MAX_SPELLS);
- + MANGOS_ASSERT(MAX_CREATURE_SPELL_DATA_SLOT <= CREATURE_MAX_SPELLS);
- mPetDefaultSpellsMap.clear();
- diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
- index 6da2665..835cee7 100644
- --- a/src/game/Unit.cpp
- +++ b/src/game/Unit.cpp
- @@ -40,6 +40,7 @@
- #include "Util.h"
- #include "Totem.h"
- #include "Vehicle.h"
- +#include "Transports.h"
- #include "BattleGround.h"
- #include "InstanceData.h"
- #include "MapPersistentStateMgr.h"
- @@ -264,6 +265,11 @@ Unit::Unit() :
- // remove aurastates allowing special moves
- for(int i=0; i < MAX_REACTIVE; ++i)
- m_reactiveTimer[i] = 0;
- +
- + m_transport = NULL;
- +
- + m_pVehicle = NULL;
- + m_pVehicleKit = NULL;
- }
- Unit::~Unit()
- @@ -771,6 +777,13 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
- cVictim->AllLootRemovedFromCorpse();
- }
- + // if vehicle and has passengers - remove his
- + if (cVictim->GetObjectGuid().IsVehicle())
- + {
- + if(cVictim->GetVehicleKit())
- + cVictim->GetVehicleKit()->RemoveAllPassengers();
- + }
- +
- // Call creature just died function
- if (cVictim->AI())
- cVictim->AI()->JustDied(this);
- @@ -5557,8 +5570,10 @@ bool Unit::Attack(Unit *victim, bool meleeAttack)
- if(!isAlive() || !victim->IsInWorld() || !victim->isAlive())
- return false;
- - // player cannot attack in mount state
- - if(GetTypeId()==TYPEID_PLAYER && IsMounted())
- + // player cannot attack while mounted or in vehicle (exclude special vehicles)if
- + if (GetTypeId()==TYPEID_PLAYER && (IsMounted() ||
- + (GetVehicle() && (!GetVehicle()->GetSeatInfo(this) ||
- + !(GetVehicle()->GetSeatInfo(this)->m_flags & (SEAT_FLAG_CAN_CAST | SEAT_FLAG_CAN_ATTACK))))))
- return false;
- // nobody can attack GM in GM-mode
- @@ -5888,6 +5903,7 @@ void Unit::Uncharm()
- charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_CHARM);
- charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_POSSESS);
- charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_POSSESS_PET);
- + charm->SetCharmerGuid(ObjectGuid());
- }
- }
- @@ -7627,7 +7643,7 @@ float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM) const
- return WeaponSpeed * PPM / 600.0f; // result is chance in percents (probability = Speed_in_sec * (PPM / 60))
- }
- -void Unit::Mount(uint32 mount, uint32 spellId)
- +void Unit::Mount(uint32 mount, uint32 spellId, uint32 vehicleId, uint32 creatureEntry)
- {
- if (!mount)
- return;
- @@ -7661,6 +7677,15 @@ void Unit::Mount(uint32 mount, uint32 spellId)
- pet->ApplyModeFlags(PET_MODE_DISABLE_ACTIONS,true);
- }
- }
- +
- + if (vehicleId)
- + {
- + SetVehicleId(vehicleId);
- + GetVehicleKit()->Reset();
- +
- + // mounts can also have accessories
- + GetVehicleKit()->InstallAllAccessories(creatureEntry);
- + }
- }
- }
- @@ -7692,6 +7717,17 @@ void Unit::Unmount(bool from_aura)
- else
- ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
- }
- +
- + if (GetTypeId() == TYPEID_PLAYER && GetVehicleKit())
- + {
- + // Send other players that we are no longer a vehicle
- + WorldPacket data(SMSG_SET_VEHICLE_REC_ID, 8+4);
- + data << GetPackGUID();
- + data << uint32(0);
- + ((Player*)this)->SendMessageToSet(&data, true);
- +
- + RemoveVehicleKit();
- + }
- }
- void Unit::SetInCombatWith(Unit* enemy)
- @@ -8371,6 +8407,7 @@ void Unit::SetDeathState(DeathState s)
- {
- if (s != ALIVE && s!= JUST_ALIVED)
- {
- + ExitVehicle();
- CombatStop();
- DeleteThreatList();
- ClearComboPointHolders(); // any combo points pointed to unit lost at it death
- @@ -8394,6 +8431,9 @@ void Unit::SetDeathState(DeathState s)
- // remove aurastates allowing special moves
- ClearAllReactives();
- ClearDiminishings();
- +
- + if (GetVehicleKit())
- + GetVehicleKit()->RemoveAllPassengers();
- }
- else if(s == JUST_ALIVED)
- {
- @@ -9343,6 +9383,10 @@ void Unit::CleanupsBeforeDelete()
- {
- if(m_uint32Values) // only for fully created object
- {
- + if (GetVehicle())
- + ExitVehicle();
- + if (GetVehicleKit())
- + RemoveVehicleKit();
- InterruptNonMeleeSpells(true);
- m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList
- CombatStop();
- @@ -9410,6 +9454,25 @@ void CharmInfo::InitPossessCreateSpells()
- }
- }
- +void CharmInfo::InitVehicleCreateSpells()
- +{
- + for (uint32 x = ACTION_BAR_INDEX_START; x < ACTION_BAR_INDEX_END; ++x)
- + SetActionBar(x, 0, ActiveStates(0x8 + x));
- +
- + for (uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x)
- + {
- + uint32 spellId = ((Creature*)m_unit)->m_spells[x];
- +
- + if (!spellId)
- + continue;
- +
- + if (IsPassiveSpell(spellId))
- + m_unit->CastSpell(m_unit, spellId, true);
- + else
- + PetActionBar[x].SetAction(spellId);
- + }
- +}
- +
- void CharmInfo::InitCharmCreateSpells()
- {
- if(m_unit->GetTypeId() == TYPEID_PLAYER) //charmed players don't have spells
- @@ -9940,7 +10003,7 @@ void Unit::SetFeared(bool apply, ObjectGuid casterGuid, uint32 spellID, uint32 t
- }
- }
- - if (GetTypeId() == TYPEID_PLAYER)
- + if (GetTypeId() == TYPEID_PLAYER && !GetVehicle())
- ((Player*)this)->SetClientControl(this, !apply);
- }
- @@ -9970,7 +10033,7 @@ void Unit::SetConfused(bool apply, ObjectGuid casterGuid, uint32 spellID)
- }
- }
- - if(GetTypeId() == TYPEID_PLAYER)
- + if(GetTypeId() == TYPEID_PLAYER && !GetVehicle())
- ((Player*)this)->SetClientControl(this, !apply);
- }
- @@ -10422,12 +10485,97 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
- RemoveNotOwnSingleTargetAuras(newPhaseMask); // we can lost access to caster or target
- // all controlled except not owned charmed units
- - CallForAllControlledUnits(SetPhaseMaskHelper(newPhaseMask), CONTROLLED_PET|CONTROLLED_GUARDIANS|CONTROLLED_MINIPET|CONTROLLED_TOTEMS);
- + CallForAllControlledUnits(SetPhaseMaskHelper(newPhaseMask), CONTROLLED_PET|CONTROLLED_GUARDIANS|CONTROLLED_MINIPET|CONTROLLED_TOTEMS|CONTROLLED_CHARM);
- }
- WorldObject::SetPhaseMask(newPhaseMask, update);
- }
- +bool Unit::SetPosition(float x, float y, float z, float orientation, bool teleport)
- +{
- + // prevent crash when a bad coord is sent by the client
- + if (!MaNGOS::IsValidMapCoord(x, y, z, orientation))
- + {
- + DEBUG_LOG("Unit::SetPosition(%f, %f, %f, %f, %d) .. bad coordinates for unit %d!", x, y, z, orientation, teleport, GetGUIDLow());
- + return false;
- + }
- +
- + bool turn = GetOrientation() != orientation;
- + bool relocate = (teleport || GetPositionX() != x || GetPositionY() != y || GetPositionZ() != z);
- +
- + if (turn)
- + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING);
- +
- + if (relocate)
- + {
- + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOVE);
- +
- + if (GetTypeId() == TYPEID_PLAYER)
- + GetMap()->PlayerRelocation((Player*)this, x, y, z, orientation);
- + else
- + GetMap()->CreatureRelocation((Creature*)this, x, y, z, orientation);
- + }
- + else if (turn)
- + SetOrientation(orientation);
- +
- + if ((relocate || turn) && GetVehicleKit())
- + GetVehicleKit()->RelocatePassengers(x, y, z, orientation);
- +
- + return relocate || turn;
- +}
- +
- +void Unit::MonsterMoveTransport(WorldObject *transport, SplineType type, SplineFlags flags, uint32 moveTime, ...)
- +{
- + va_list vargs;
- + va_start(vargs, moveTime);
- +
- + WorldPacket data(SMSG_MONSTER_MOVE_TRANSPORT, 60);
- + data << GetPackGUID();
- + data << transport->GetPackGUID();
- + data << uint8(m_movementInfo.GetTransportSeat());
- + data << uint8(0); // new in 3.1
- + data << float(transport->GetPositionX());
- + data << float(transport->GetPositionY());
- + data << float(transport->GetPositionZ());
- + data << uint32(WorldTimer::getMSTime());
- +
- + data << uint8(type); // spline type
- +
- + switch(type)
- + {
- + case SPLINETYPE_NORMAL: // normal packet
- + break;
- + case SPLINETYPE_STOP: // stop packet (raw pos?)
- + va_end(vargs);
- + SendMessageToSet(&data, true);
- + return;
- + case SPLINETYPE_FACINGSPOT: // facing spot
- + data << float(va_arg(vargs,double));
- + data << float(va_arg(vargs,double));
- + data << float(va_arg(vargs,double));
- + break;
- + case SPLINETYPE_FACINGTARGET:
- + data << uint64(va_arg(vargs,uint64));
- + break;
- + case SPLINETYPE_FACINGANGLE:
- + data << float(va_arg(vargs,double)); // facing angle
- + break;
- + }
- +
- + va_end(vargs);
- +
- + data << uint32(flags);
- +
- + data << uint32(moveTime); // Time in between points
- + data << uint32(1); // 1 single waypoint
- +
- + data << float(m_movementInfo.GetTransportPos()->x);
- + data << float(m_movementInfo.GetTransportPos()->y);
- + data << float(m_movementInfo.GetTransportPos()->z);
- +
- + SendMessageToSet(&data, true);
- +}
- +
- void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool casting /*= false*/ )
- {
- DisableSpline();
- @@ -10436,13 +10584,14 @@ void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool ca
- ((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));
- else
- {
- + ExitVehicle();
- Creature* c = (Creature*)this;
- // Creature relocation acts like instant movement generator, so current generator expects interrupt/reset calls to react properly
- if (!c->GetMotionMaster()->empty())
- if (MovementGenerator *movgen = c->GetMotionMaster()->top())
- movgen->Interrupt(*c);
- - GetMap()->CreatureRelocation((Creature*)this, x, y, z, orientation);
- + SetPosition(x, y, z, orientation, true);
- SendHeartBeat();
- @@ -10462,6 +10611,112 @@ void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed)
- init.Launch();
- }
- +void Unit::RemoveVehicleKit()
- +{
- + if (!m_pVehicleKit)
- + return;
- +
- + m_pVehicleKit->RemoveAllPassengers();
- +
- + m_updateFlag &= ~UPDATEFLAG_VEHICLE;
- + RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
- + RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE);
- +}
- +
- +void Unit::ChangeSeat(int8 seatId, bool next)
- +{
- + if (!m_pVehicle)
- + return;
- +
- + if (seatId < 0)
- + {
- + seatId = m_pVehicle->GetNextEmptySeat(m_movementInfo.GetTransportSeat(), next);
- + if (seatId < 0)
- + return;
- + }
- + else if (seatId == m_movementInfo.GetTransportSeat() || !m_pVehicle->HasEmptySeat(seatId))
- + return;
- +
- + if (m_pVehicle->GetPassenger(seatId) &&
- + (!m_pVehicle->GetPassenger(seatId)->GetObjectGuid().IsVehicle() || !m_pVehicle->GetSeatInfo(m_pVehicle->GetPassenger(seatId))))
- + return;
- +
- + m_pVehicle->RemovePassenger(this);
- + m_pVehicle->AddPassenger(this, seatId);
- +}
- +
- +void Unit::EnterVehicle(VehicleKit *vehicle, int8 seatId)
- +{
- + if (!isAlive() || GetVehicleKit() == vehicle)
- + return;
- +
- + if (m_pVehicle)
- + {
- + if (m_pVehicle == vehicle)
- + {
- + if (seatId >= 0)
- + ChangeSeat(seatId);
- +
- + return;
- + }
- + else
- + ExitVehicle();
- + }
- +
- + InterruptNonMeleeSpells(false);
- + RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
- +
- + if (!vehicle->AddPassenger(this, seatId))
- + return;
- +
- + m_pVehicle = vehicle;
- +
- + if (Pet* pet = GetPet())
- + pet->Unsummon(PET_SAVE_AS_CURRENT,this);
- +
- + if (GetTypeId() == TYPEID_PLAYER)
- + {
- + Player* player = (Player*)this;
- +
- + if (BattleGround *bg = player->GetBattleGround())
- + bg->EventPlayerDroppedFlag(player);
- +
- + WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA);
- + player->GetSession()->SendPacket(&data);
- +
- + data.Initialize(SMSG_BREAK_TARGET, 8);
- + data << vehicle->GetBase()->GetPackGUID();
- + player->GetSession()->SendPacket(&data);
- + }
- +
- + if (Transport* pTransport = GetTransport())
- + {
- + if (GetTypeId() == TYPEID_PLAYER)
- + pTransport->RemovePassenger((Player*)this);
- +
- + SetTransport(NULL);
- + }
- +}
- +
- +void Unit::ExitVehicle()
- +{
- + if(!m_pVehicle)
- + return;
- +
- + m_pVehicle->RemovePassenger(this);
- + m_pVehicle = NULL;
- +
- + if (GetTypeId() == TYPEID_PLAYER)
- + ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
- +
- + float x = GetPositionX();
- + float y = GetPositionY();
- + float z = GetPositionZ() + 2.0f;
- + GetClosePoint(x, y, z, 2.0f);
- + UpdateAllowedPositionZ(x, y, z);
- + MonsterMoveWithSpeed(x, y, z + 0.5f, 28.f);
- +}
- +
- struct SetPvPHelper
- {
- explicit SetPvPHelper(bool _state) : state(_state) {}
- @@ -10813,6 +11068,9 @@ void Unit::SetVehicleId(uint32 entry)
- m_vehicleInfo = new VehicleInfo(ventry);
- m_updateFlag |= UPDATEFLAG_VEHICLE;
- +
- + if (!m_pVehicleKit)
- + m_pVehicleKit = new VehicleKit(this);
- }
- else
- {
- diff --git a/src/game/Unit.h b/src/game/Unit.h
- index 09a5f0b..0d4a8fb 100644
- --- a/src/game/Unit.h
- +++ b/src/game/Unit.h
- @@ -197,7 +197,7 @@ enum UnitRename
- UNIT_CAN_BE_ABANDONED = 0x02,
- };
- -#define CREATURE_MAX_SPELLS 4
- +#define CREATURE_MAX_SPELLS 8
- enum Swing
- {
- @@ -270,6 +270,7 @@ class Item;
- class Pet;
- class PetAura;
- class Totem;
- +class Transport;
- class VehicleInfo;
- struct SpellImmune
- @@ -408,24 +409,25 @@ enum UnitState
- UNIT_STAT_FOLLOW_MOVE = 0x00010000,
- UNIT_STAT_FLEEING = 0x00020000, // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack
- UNIT_STAT_FLEEING_MOVE = 0x00040000,
- + UNIT_STAT_ON_VEHICLE = 0x00080000, // Unit is on vehicle
- // masks (only for check)
- // can't move currently
- - UNIT_STAT_CAN_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED,
- + UNIT_STAT_CAN_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | UNIT_STAT_ON_VEHICLE,
- // stay by different reasons
- UNIT_STAT_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED |
- - UNIT_STAT_DISTRACTED,
- + UNIT_STAT_DISTRACTED | UNIT_STAT_ON_VEHICLE,
- // stay or scripted movement for effect( = in player case you can't move by client command)
- UNIT_STAT_NO_FREE_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED |
- UNIT_STAT_TAXI_FLIGHT |
- - UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING,
- + UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_ON_VEHICLE,
- // not react at move in sight or other
- UNIT_STAT_CAN_NOT_REACT = UNIT_STAT_STUNNED | UNIT_STAT_DIED |
- - UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING,
- + UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_ON_VEHICLE,
- // AI disabled by some reason
- UNIT_STAT_LOST_CONTROL = UNIT_STAT_FLEEING | UNIT_STAT_CONTROLLED,
- @@ -588,6 +590,7 @@ enum NPCFlags
- UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100%
- UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode
- 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
- + UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000, // players with mounts that have vehicle data should have it set
- };
- // used in most movement packets (send and received)
- @@ -717,7 +720,7 @@ class MovementInfo
- {
- public:
- MovementInfo() : moveFlags(MOVEFLAG_NONE), moveFlags2(MOVEFLAG2_NONE), time(0),
- - t_time(0), t_seat(-1), t_time2(0), s_pitch(0.0f), fallTime(0), u_unk1(0.0f) {}
- + t_time(0), t_seat(-1), t_seatInfo(NULL), t_time2(0), s_pitch(0.0f), fallTime(0), u_unk1(0.0f) {}
- // Read/Write methods
- void Read(ByteBuffer &data);
- @@ -730,10 +733,11 @@ class MovementInfo
- MovementFlags GetMovementFlags() const { return MovementFlags(moveFlags); }
- void SetMovementFlags(MovementFlags f) { moveFlags = f; }
- MovementFlags2 GetMovementFlags2() const { return MovementFlags2(moveFlags2); }
- + void AddMovementFlag2(MovementFlags2 f) { moveFlags2 |= f; }
- // Position manipulations
- Position const *GetPos() const { return &pos; }
- - void SetTransportData(ObjectGuid guid, float x, float y, float z, float o, uint32 time, int8 seat)
- + void SetTransportData(ObjectGuid guid, float x, float y, float z, float o, uint32 time, int8 seat, VehicleSeatEntry const* seatInfo = NULL)
- {
- t_guid = guid;
- t_pos.x = x;
- @@ -742,6 +746,7 @@ class MovementInfo
- t_pos.o = o;
- t_time = time;
- t_seat = seat;
- + t_seatInfo = seatInfo;
- }
- void ClearTransportData()
- {
- @@ -752,10 +757,13 @@ class MovementInfo
- t_pos.o = 0.0f;
- t_time = 0;
- t_seat = -1;
- + t_seatInfo = NULL;
- }
- ObjectGuid const& GetTransportGuid() const { return t_guid; }
- Position const *GetTransportPos() const { return &t_pos; }
- int8 GetTransportSeat() const { return t_seat; }
- + uint32 GetTransportDBCSeat() const { return t_seatInfo ? t_seatInfo->m_ID : 0; }
- + uint32 GetVehicleSeatFlags() const { return t_seatInfo ? t_seatInfo->m_flags : 0; }
- uint32 GetTransportTime() const { return t_time; }
- uint32 GetFallTime() const { return fallTime; }
- void ChangeOrientation(float o) { pos.o = o; }
- @@ -780,6 +788,7 @@ class MovementInfo
- Position t_pos;
- uint32 t_time;
- int8 t_seat;
- + VehicleSeatEntry const* t_seatInfo;
- uint32 t_time2;
- // swimming and flying
- float s_pitch;
- @@ -1049,6 +1058,7 @@ struct CharmInfo
- bool HasReactState(ReactStates state) { return (m_reactState == state); }
- void InitPossessCreateSpells();
- + void InitVehicleCreateSpells();
- void InitCharmCreateSpells();
- void InitPetActionBar();
- void InitEmptyActionBar();
- @@ -1123,6 +1133,7 @@ typedef std::set<ObjectGuid> GuardianPetList;
- #define REGEN_TIME_PRECISE 500 // Used in Spell::CheckPower for precise regeneration in spell cast time
- struct SpellProcEventEntry; // used only privately
- +class VehicleKit;
- class MANGOS_DLL_SPEC Unit : public WorldObject
- {
- @@ -1306,7 +1317,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
- bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); }
- uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); }
- - void Mount(uint32 mount, uint32 spellId = 0);
- + void Mount(uint32 mount, uint32 spellId = 0, uint32 vehicleId = 0, uint32 creatureEntry = 0);
- void Unmount(bool from_aura = false);
- VehicleInfo* GetVehicleInfo() { return m_vehicleInfo; }
- @@ -1462,6 +1473,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
- void SendPeriodicAuraLog(SpellPeriodicAuraLogInfo *pInfo);
- void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo);
- + virtual bool SetPosition(float x, float y, float z, float orientation, bool teleport = false);
- + void MonsterMoveTransport(WorldObject *transport, SplineType type, SplineFlags flags, uint32 moveTime, ...);
- void NearTeleportTo(float x, float y, float z, float orientation, bool casting = false);
- void MonsterMoveWithSpeed(float x, float y, float z, float speed);
- // recommend use MonsterMove/MonsterMoveWithSpeed for most case that correctly work with movegens
- @@ -1957,6 +1970,25 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
- void _SetAINotifyScheduled(bool on) { m_AINotifyScheduled = on;} // only for call from RelocationNotifyEvent code
- void OnRelocated();
- + // Transports
- + Transport* GetTransport() const { return m_transport; }
- + void SetTransport(Transport* pTransport) { m_transport = pTransport; }
- +
- + float GetTransOffsetX() const { return m_movementInfo.GetTransportPos()->x; }
- + float GetTransOffsetY() const { return m_movementInfo.GetTransportPos()->y; }
- + float GetTransOffsetZ() const { return m_movementInfo.GetTransportPos()->z; }
- + float GetTransOffsetO() const { return m_movementInfo.GetTransportPos()->o; }
- + uint32 GetTransTime() const { return m_movementInfo.GetTransportTime(); }
- + int8 GetTransSeat() const { return m_movementInfo.GetTransportSeat(); }
- +
- + // Vehicle system
- + void EnterVehicle(VehicleKit *vehicle, int8 seatId = -1);
- + void ExitVehicle();
- + void ChangeSeat(int8 seatId, bool next = true);
- + VehicleKit* GetVehicle() const { return m_pVehicle; }
- + VehicleKit* GetVehicleKit() const { return m_pVehicleKit; }
- + void RemoveVehicleKit();
- +
- protected:
- explicit Unit ();
- @@ -2006,6 +2038,11 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
- uint32 m_regenTimer;
- uint32 m_lastManaUseTimer;
- + // Transports
- + Transport* m_transport;
- +
- + VehicleKit* m_pVehicle;
- + VehicleKit* m_pVehicleKit;
- VehicleInfo* m_vehicleInfo;
- void DisableSpline();
- private:
- diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp
- index 5002d79..b64c062 100644
- --- a/src/game/Vehicle.cpp
- +++ b/src/game/Vehicle.cpp
- @@ -21,9 +21,377 @@
- #include "ObjectMgr.h"
- #include "Vehicle.h"
- #include "Unit.h"
- +#include "CreatureAI.h"
- #include "Util.h"
- +#include "WorldPacket.h"
- VehicleInfo::VehicleInfo(VehicleEntry const* entry) :
- m_vehicleEntry(entry)
- {
- }
- +
- +VehicleKit::VehicleKit(Unit* base) : m_pBase(base), m_uiNumFreeSeats(0)
- +{
- + for (uint32 i = 0; i < MAX_VEHICLE_SEAT; ++i)
- + {
- + uint32 seatId = GetBase()->GetVehicleInfo()->GetEntry()->m_seatID[i];
- +
- + if (!seatId)
- + continue;
- +
- + if(base)
- + {
- + if(GetBase()->GetVehicleInfo()->GetEntry()->m_flags & VEHICLE_FLAG_NO_STRAFE)
- + GetBase()->m_movementInfo.AddMovementFlag2(MOVEFLAG2_NO_STRAFE);
- +
- + if(GetBase()->GetVehicleInfo()->GetEntry()->m_flags & VEHICLE_FLAG_NO_JUMPING)
- + GetBase()->m_movementInfo.AddMovementFlag2(MOVEFLAG2_NO_JUMPING);
- + }
- +
- + if (VehicleSeatEntry const *seatInfo = sVehicleSeatStore.LookupEntry(seatId))
- + {
- + m_Seats.insert(std::make_pair(i, VehicleSeat(seatInfo)));
- +
- + if (seatInfo->IsUsable())
- + ++m_uiNumFreeSeats;
- + }
- + }
- +}
- +
- +VehicleKit::~VehicleKit()
- +{
- +}
- +
- +void VehicleKit::RemoveAllPassengers()
- +{
- + for (SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
- + {
- + if (Unit *passenger = itr->second.passenger)
- + {
- + passenger->ExitVehicle();
- + // remove creatures of player mounts
- + if (passenger->GetTypeId() == TYPEID_UNIT)
- + passenger->AddObjectToRemoveList();
- + }
- + }
- +}
- +
- +bool VehicleKit::HasEmptySeat(int8 seatId) const
- +{
- + SeatMap::const_iterator seat = m_Seats.find(seatId);
- +
- + if (seat == m_Seats.end())
- + return false;
- +
- + return !seat->second.passenger;
- +}
- +
- +Unit *VehicleKit::GetPassenger(int8 seatId) const
- +{
- + SeatMap::const_iterator seat = m_Seats.find(seatId);
- +
- + if (seat == m_Seats.end())
- + return NULL;
- +
- + return seat->second.passenger;
- +}
- +
- +int8 VehicleKit::GetNextEmptySeat(int8 seatId, bool next) const
- +{
- + SeatMap::const_iterator seat = m_Seats.find(seatId);
- +
- + if (seat == m_Seats.end())
- + return -1;
- +
- + while (seat->second.passenger || !seat->second.seatInfo->IsUsable())
- + {
- + if (next)
- + {
- + ++seat;
- + if (seat == m_Seats.end())
- + seat = m_Seats.begin();
- + }
- + else
- + {
- + if (seat == m_Seats.begin())
- + seat = m_Seats.end();
- + --seat;
- + }
- +
- + if (seat->first == seatId)
- + return -1; // no available seat
- + }
- +
- + return seat->first;
- +}
- +
- +bool VehicleKit::AddPassenger(Unit *passenger, int8 seatId)
- +{
- + SeatMap::iterator seat;
- +
- + if (seatId < 0) // no specific seat requirement
- + {
- + for (seat = m_Seats.begin(); seat != m_Seats.end(); ++seat)
- + if (!seat->second.passenger && (seat->second.seatInfo->IsUsable() || (seat->second.seatInfo->m_flags & SEAT_FLAG_UNCONTROLLED)))
- + break;
- +
- + if (seat == m_Seats.end()) // no available seat
- + return false;
- + }
- + else
- + {
- + seat = m_Seats.find(seatId);
- +
- + if (seat == m_Seats.end())
- + return false;
- +
- + if (seat->second.passenger)
- + return false;
- + }
- +
- + seat->second.passenger = passenger;
- + passenger->addUnitState(UNIT_STAT_ON_VEHICLE);
- +
- + m_pBase->SetPhaseMask(passenger->GetPhaseMask(), true);
- +
- + VehicleSeatEntry const *seatInfo = seat->second.seatInfo;
- +
- + passenger->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT);
- + passenger->m_movementInfo.SetTransportData(m_pBase->GetObjectGuid(),
- +
- + seatInfo->m_attachmentOffsetX, seatInfo->m_attachmentOffsetY, seatInfo->m_attachmentOffsetZ,
- + seatInfo->m_passengerYaw, WorldTimer::getMSTime(), seat->first, seatInfo);
- +
- + if (passenger->GetTypeId() == TYPEID_PLAYER)
- + {
- + ((Player*)passenger)->UnsummonPetTemporaryIfAny();
- + ((Player*)passenger)->GetCamera().SetView(m_pBase);
- +
- + WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8+4);
- + data << passenger->GetPackGUID();
- + data << uint32((passenger->m_movementInfo.GetVehicleSeatFlags() & SEAT_FLAG_CAN_CAST) ? 2 : 0);
- + passenger->SendMessageToSet(&data, true);
- + }
- +
- + if (seat->second.seatInfo->m_flags & SEAT_FLAG_UNATTACKABLE || seat->second.seatInfo->m_flags & SEAT_FLAG_CAN_CONTROL)
- + {
- + passenger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- + passenger->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
- + }
- +
- + if (seatInfo->m_flags & SEAT_FLAG_CAN_CONTROL)
- + {
- +// m_pBase->StopMoving();
- + m_pBase->GetMotionMaster()->Clear();
- + m_pBase->CombatStop(true);
- + m_pBase->DeleteThreatList();
- + m_pBase->getHostileRefManager().deleteReferences();
- + m_pBase->SetCharmerGuid(passenger->GetObjectGuid());
- + m_pBase->addUnitState(UNIT_STAT_CONTROLLED);
- +
- + passenger->SetCharm(m_pBase);
- +
- + if(m_pBase->HasAuraType(SPELL_AURA_FLY) || m_pBase->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED))
- + {
- + WorldPacket data;
- + data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
- + data << m_pBase->GetPackGUID();
- + data << (uint32)(0);
- + m_pBase->SendMessageToSet(&data,false);
- + }
- +
- + if (passenger->GetTypeId() == TYPEID_PLAYER)
- + {
- + m_pBase->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
- + m_pBase->setFaction(passenger->getFaction());
- +
- + if (CharmInfo* charmInfo = m_pBase->InitCharmInfo(m_pBase))
- + {
- + charmInfo->InitVehicleCreateSpells();
- + charmInfo->SetReactState(REACT_PASSIVE);
- + }
- +
- + Player* player = (Player*)passenger;
- + player->SetMover(m_pBase);
- + player->SetClientControl(m_pBase, 1);
- + player->VehicleSpellInitialize();
- + }
- +
- + if(!(((Creature*)m_pBase)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_KEEP_AI))
- + ((Creature*)m_pBase)->AIM_Initialize();
- +
- + if(m_pBase->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE))
- + {
- + WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 8+4);
- + data2 << m_pBase->GetPackGUID();
- + data2 << (uint32)(2);
- + m_pBase->SendMessageToSet(&data2,false);
- + }
- + }
- +
- + passenger->MonsterMoveTransport(m_pBase, SPLINETYPE_FACINGANGLE, SPLINEFLAG_UNKNOWN5, 0, 0.0f);
- +
- + RelocatePassengers(m_pBase->GetPositionX(), m_pBase->GetPositionY(), m_pBase->GetPositionZ()+0.5f, m_pBase->GetOrientation());
- +
- + UpdateFreeSeatCount();
- +
- + if (m_pBase->GetTypeId() == TYPEID_UNIT)
- + {
- + if (((Creature*)m_pBase)->AI())
- + ((Creature*)m_pBase)->AI()->PassengerBoarded(passenger, seat->first, true);
- + }
- +
- + return true;
- +}
- +
- +void VehicleKit::RemovePassenger(Unit *passenger)
- +{
- + SeatMap::iterator seat;
- +
- + for (seat = m_Seats.begin(); seat != m_Seats.end(); ++seat)
- + if (seat->second.passenger == passenger)
- + break;
- +
- + if (seat == m_Seats.end())
- + return;
- +
- + seat->second.passenger = NULL;
- + passenger->clearUnitState(UNIT_STAT_ON_VEHICLE);
- +
- + float px, py, pz, po;
- + m_pBase->GetClosePoint(px, py, pz, m_pBase->GetObjectBoundingRadius(), 2.0f, M_PI_F);
- + po = m_pBase->GetOrientation();
- +
- + passenger->m_movementInfo.ClearTransportData();
- + passenger->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ONTRANSPORT);
- +
- + if (seat->second.seatInfo->m_flags & SEAT_FLAG_UNATTACKABLE || seat->second.seatInfo->m_flags & SEAT_FLAG_CAN_CONTROL)
- + {
- + passenger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- + }
- +
- + if (seat->second.seatInfo->m_flags & SEAT_FLAG_CAN_CONTROL)
- + {
- + passenger->SetCharm(NULL);
- + passenger->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE);
- +
- + m_pBase->SetCharmerGuid(ObjectGuid());
- + m_pBase->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
- + m_pBase->clearUnitState(UNIT_STAT_CONTROLLED);
- + m_pBase->setFaction(((Creature*)m_pBase)->GetCreatureInfo()->faction_A);
- +
- + if (passenger->GetTypeId() == TYPEID_PLAYER)
- + {
- + Player* player = (Player*)passenger;
- + player->SetMover(NULL);
- + player->SetClientControl(m_pBase, 0);
- + player->RemovePetActionBar();
- + }
- +
- + if(!(((Creature*)m_pBase)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_KEEP_AI))
- + ((Creature*)m_pBase)->AIM_Initialize();
- + }
- +
- + if (passenger->GetTypeId() == TYPEID_PLAYER)
- + {
- + ((Player*)passenger)->GetCamera().ResetView();
- +
- + WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
- + data << passenger->GetPackGUID();
- + data << uint32(2);
- + passenger->SendMessageToSet(&data, true);
- +
- + ((Player*)passenger)->ResummonPetTemporaryUnSummonedIfAny();
- + }
- +
- + passenger->UpdateAllowedPositionZ(px, py, pz);
- + passenger->SetPosition(px, py, pz + 0.5f, po);
- + UpdateFreeSeatCount();
- +
- + if (m_pBase->GetTypeId() == TYPEID_UNIT)
- + {
- + if (((Creature*)m_pBase)->AI())
- + ((Creature*)m_pBase)->AI()->PassengerBoarded(passenger, seat->first, false);
- + }
- +}
- +
- +void VehicleKit::Reset()
- +{
- + InstallAllAccessories(m_pBase->GetEntry());
- + UpdateFreeSeatCount();
- +}
- +
- +void VehicleKit::InstallAllAccessories(uint32 entry)
- +{
- + VehicleAccessoryList const* mVehicleList = sObjectMgr.GetVehicleAccessoryList(entry);
- + if (!mVehicleList)
- + return;
- +
- + for (VehicleAccessoryList::const_iterator itr = mVehicleList->begin(); itr != mVehicleList->end(); ++itr)
- + InstallAccessory(itr->uiAccessory, itr->uiSeat, itr->bMinion);
- +}
- +
- +void VehicleKit::InstallAccessory( uint32 entry, int8 seatId, bool minion)
- +{
- + if (Unit *passenger = GetPassenger(seatId))
- + {
- + // already installed
- + if (passenger->GetEntry() == entry)
- + return;
- +
- + passenger->ExitVehicle();
- + }
- +
- + if (Creature *accessory = m_pBase->SummonCreature(entry, m_pBase->GetPositionX(), m_pBase->GetPositionY(), m_pBase->GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000))
- + {
- + accessory->SetCreatorGuid(ObjectGuid());
- + accessory->EnterVehicle(this, seatId);
- + accessory->SendHeartBeat();
- + }
- +}
- +
- +void VehicleKit::UpdateFreeSeatCount()
- +{
- + m_uiNumFreeSeats = 0;
- +
- + for (SeatMap::const_iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
- + {
- + if (!itr->second.passenger && itr->second.seatInfo->IsUsable())
- + ++m_uiNumFreeSeats;
- + }
- +
- + uint32 flag = m_pBase->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK;
- +
- + if (m_uiNumFreeSeats)
- + m_pBase->SetFlag(UNIT_NPC_FLAGS, flag);
- + else
- + m_pBase->RemoveFlag(UNIT_NPC_FLAGS, flag);
- +}
- +
- +void VehicleKit::RelocatePassengers(float x, float y, float z, float ang)
- +{
- + for (SeatMap::const_iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
- + {
- + if (Unit *passenger = itr->second.passenger)
- + {
- + float px = x + passenger->m_movementInfo.GetTransportPos()->x;
- + float py = y + passenger->m_movementInfo.GetTransportPos()->y;
- + float pz = z + passenger->m_movementInfo.GetTransportPos()->z;
- + float po = ang + passenger->m_movementInfo.GetTransportPos()->o;
- +
- + passenger->UpdateAllowedPositionZ(px, py, pz);
- + passenger->SetPosition(px, py, pz, po);
- + }
- + }
- +}
- +
- +VehicleSeatEntry const* VehicleKit::GetSeatInfo(Unit* passenger)
- +{
- + for (SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
- + {
- + if (Unit *_passenger = itr->second.passenger)
- + if (_passenger = passenger)
- + return itr->second.seatInfo;
- + }
- + return NULL;
- +}
- diff --git a/src/game/Vehicle.h b/src/game/Vehicle.h
- index 73ec3d6..1b71475 100644
- --- a/src/game/Vehicle.h
- +++ b/src/game/Vehicle.h
- @@ -36,4 +36,54 @@ class VehicleInfo
- VehicleEntry const* GetEntry() const { return m_vehicleEntry; }
- };
- +struct VehicleSeat
- +{
- + VehicleSeat(VehicleSeatEntry const *pSeatInfo = NULL) : seatInfo(pSeatInfo), passenger(NULL) {}
- +
- + VehicleSeatEntry const *seatInfo;
- + Unit* passenger;
- +};
- +
- +typedef std::map<int8, VehicleSeat> SeatMap;
- +
- +struct VehicleAccessory
- +{
- + explicit VehicleAccessory(uint32 _uiAccessory, int8 _uiSeat, bool _bMinion) : uiAccessory(_uiAccessory), uiSeat(_uiSeat), bMinion(_bMinion) {}
- + uint32 uiAccessory;
- + int8 uiSeat;
- + uint32 bMinion;
- +};
- +
- +typedef std::vector<VehicleAccessory> VehicleAccessoryList;
- +typedef std::map<uint32, VehicleAccessoryList> VehicleAccessoryMap;
- +
- +class MANGOS_DLL_SPEC VehicleKit
- +{
- + public:
- + explicit VehicleKit(Unit* base);
- + ~VehicleKit();
- +
- + void Reset();
- + void InstallAllAccessories(uint32 entry);
- +
- + bool HasEmptySeat(int8 seatId) const;
- + Unit *GetPassenger(int8 seatId) const;
- + int8 GetNextEmptySeat(int8 seatId, bool next) const;
- + bool AddPassenger(Unit *passenger, int8 seatId = -1);
- + void RemovePassenger(Unit *passenger);
- + void RelocatePassengers(float x, float y, float z, float ang);
- + void RemoveAllPassengers();
- + VehicleSeatEntry const* GetSeatInfo(Unit* passenger);
- +
- + Unit* GetBase() { return m_pBase; }
- +
- + private:
- + void UpdateFreeSeatCount();
- + void InstallAccessory(uint32 entry, int8 seatId, bool minion = true);
- +
- + SeatMap m_Seats;
- + uint32 m_uiNumFreeSeats;
- + Unit* m_pBase;
- +};
- +
- #endif
- diff --git a/src/game/VehicleHandler.cpp b/src/game/VehicleHandler.cpp
- new file mode 100644
- index 0000000..d55f677
- --- /dev/null
- +++ b/src/game/VehicleHandler.cpp
- @@ -0,0 +1,202 @@
- +/*
- + * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + */
- +
- +#include "Common.h"
- +#include "WorldPacket.h"
- +#include "WorldSession.h"
- +#include "Opcodes.h"
- +#include "Log.h"
- +#include "Player.h"
- +#include "Vehicle.h"
- +#include "ObjectMgr.h"
- +
- +void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
- +{
- + DEBUG_LOG("WORLD: Received CMSG_DISMISS_CONTROLLED_VEHICLE");
- + recv_data.hexlike();
- +
- + ObjectGuid guid;
- + MovementInfo mi;
- +
- + recv_data >> guid.ReadAsPacked();
- + recv_data >> mi;
- +
- + if(!GetPlayer()->GetVehicle())
- + return;
- +
- + bool dismiss = true;
- +
- + Creature* vehicle = GetPlayer()->GetMap()->GetAnyTypeCreature(guid);
- +
- + if (!vehicle || !vehicle->GetVehicleInfo())
- + return;
- +
- + if (vehicle->GetVehicleInfo()->GetEntry()->m_flags & (VEHICLE_FLAG_NOT_DISMISS | VEHICLE_FLAG_ACCESSORY))
- + dismiss = false;
- +
- + GetPlayer()->m_movementInfo = mi;
- + GetPlayer()->ExitVehicle();
- +
- + if (dismiss)
- + vehicle->ForcedDespawn();
- +}
- +
- +void WorldSession::HandleRequestVehicleExit(WorldPacket &recv_data)
- +{
- + DEBUG_LOG("WORLD: Received CMSG_REQUEST_VEHICLE_EXIT");
- +
- + GetPlayer()->ExitVehicle();
- +}
- +
- +void WorldSession::HandleRequestVehiclePrevSeat(WorldPacket &recv_data)
- +{
- + DEBUG_LOG("WORLD: Received CMSG_REQUEST_VEHICLE_PREV_SEAT");
- +
- + GetPlayer()->ChangeSeat(-1, false);
- +}
- +
- +void WorldSession::HandleRequestVehicleNextSeat(WorldPacket &recv_data)
- +{
- + DEBUG_LOG("WORLD: Received CMSG_REQUEST_VEHICLE_NEXT_SEAT");
- +
- + GetPlayer()->ChangeSeat(-1, true);
- +}
- +
- +void WorldSession::HandleRequestVehicleSwitchSeat(WorldPacket &recv_data)
- +{
- + DEBUG_LOG("WORLD: Received CMSG_REQUEST_VEHICLE_SWITCH_SEAT");
- + recv_data.hexlike();
- +
- + ObjectGuid guid;
- + recv_data >> guid.ReadAsPacked();
- +
- + int8 seatId;
- + recv_data >> seatId;
- +
- + VehicleKit* pVehicle = GetPlayer()->GetVehicle();
- +
- + if (!pVehicle)
- + return;
- +
- + if (pVehicle->GetBase()->GetVehicleInfo()->GetEntry()->m_flags & VEHICLE_FLAG_DISABLE_SWITCH)
- + GetPlayer()->ExitVehicle();
- +
- + if (pVehicle->GetBase()->GetObjectGuid() == guid)
- + GetPlayer()->ChangeSeat(seatId);
- +
- + else if (Unit *Vehicle2 = GetPlayer()->GetMap()->GetUnit(guid))
- + {
- + if (VehicleKit *pVehicle2 = Vehicle2->GetVehicleKit())
- + if (pVehicle2->HasEmptySeat(seatId))
- + {
- + GetPlayer()->ExitVehicle();
- + GetPlayer()->EnterVehicle(pVehicle2, seatId);
- + }
- + }
- +}
- +
- +void WorldSession::HandleEnterPlayerVehicle(WorldPacket &recv_data)
- +{
- + DEBUG_LOG("WORLD: Received CMSG_RIDE_VEHICLE_INTERACT");
- + recv_data.hexlike();
- +
- + ObjectGuid guid;
- + recv_data >> guid;
- +
- + Player* player = sObjectMgr.GetPlayer(guid);
- +
- + if (!player)
- + return;
- +
- + if (!GetPlayer()->IsInSameRaidWith(player))
- + return;
- +
- + if (!GetPlayer()->IsWithinDistInMap(player, INTERACTION_DISTANCE))
- + return;
- +
- + if (player->GetTransport())
- + return;
- +
- + if (VehicleKit* pVehicle = player->GetVehicleKit())
- + GetPlayer()->EnterVehicle(pVehicle);
- +}
- +
- +void WorldSession::HandleEjectPasenger(WorldPacket &recv_data)
- +{
- + DEBUG_LOG("WORLD: Received CMSG_CONTROLLER_EJECT_PASSENGER");
- + recv_data.hexlike();
- +
- + ObjectGuid guid;
- + recv_data >> guid;
- +
- + Unit* passenger = ObjectAccessor::GetUnit(*GetPlayer(), guid);
- +
- + if (!passenger)
- + return;
- +
- + if (!passenger->GetVehicle() || passenger->GetVehicle() != GetPlayer()->GetVehicleKit())
- + return;
- +
- + passenger->ExitVehicle();
- +
- + // eject and remove creatures of player mounts
- + if (passenger->GetTypeId() == TYPEID_UNIT)
- + passenger->AddObjectToRemoveList();
- +}
- +
- +void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data)
- +{
- + sLog.outDebug("WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE");
- + recv_data.hexlike();
- +
- + ObjectGuid guid, guid2;
- + recv_data >> guid.ReadAsPacked();
- +
- + MovementInfo mi;
- + recv_data >> mi;
- + GetPlayer()->m_movementInfo = mi;
- +
- + recv_data >> guid2.ReadAsPacked(); //guid of vehicle or of vehicle in target seat
- +
- + int8 seatId;
- + recv_data >> seatId;
- +
- + VehicleKit* pVehicle = GetPlayer()->GetVehicle();
- +
- + if (!pVehicle)
- + return;
- +
- + if (pVehicle->GetBase()->GetVehicleInfo()->GetEntry()->m_flags & VEHICLE_FLAG_DISABLE_SWITCH)
- + GetPlayer()->ExitVehicle();
- +
- + if(guid.GetRawValue() == guid2.GetRawValue())
- + GetPlayer()->ChangeSeat(seatId, false);
- +
- + else if (guid2.IsVehicle())
- + {
- + if (Creature* vehicle = GetPlayer()->GetMap()->GetAnyTypeCreature(guid2))
- + {
- + if (VehicleKit* pVehicle2 = vehicle->GetVehicleKit())
- + if(pVehicle2->HasEmptySeat(seatId))
- + {
- + GetPlayer()->ExitVehicle();
- + GetPlayer()->EnterVehicle(pVehicle2, seatId);
- + }
- + }
- + }
- +}
- diff --git a/src/game/World.cpp b/src/game/World.cpp
- index 2f96f53..093ca2f 100644
- --- a/src/game/World.cpp
- +++ b/src/game/World.cpp
- @@ -63,6 +63,7 @@
- #include "Util.h"
- #include "AuctionHouseBot/AuctionHouseBot.h"
- #include "CharacterDatabaseCleaner.h"
- +#include "Vehicle.h"
- INSTANTIATE_SINGLETON_1( World );
- @@ -1061,6 +1062,9 @@ void World::SetInitialWorldSettings()
- sLog.outString( ">>> Creature Addon Data loaded" );
- sLog.outString();
- + sLog.outString("Loading Vehicle Accessories...");
- + sObjectMgr.LoadVehicleAccessories();
- +
- sLog.outString( "Loading Gameobject Data..." );
- sObjectMgr.LoadGameobjects();
- diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h
- index 7bfa7d5..202e3ef 100644
- --- a/src/game/WorldSession.h
- +++ b/src/game/WorldSession.h
- @@ -511,9 +511,17 @@ class MANGOS_DLL_SPEC WorldSession
- void HandleMovementOpcodes(WorldPacket& recvPacket);
- void HandleSetActiveMoverOpcode(WorldPacket &recv_data);
- void HandleMoveNotActiveMoverOpcode(WorldPacket &recv_data);
- - void HandleDismissControlledVehicle(WorldPacket &recv_data);
- void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data);
- + void HandleDismissControlledVehicle(WorldPacket &recv_data);
- + void HandleRequestVehicleExit(WorldPacket &recv_data);
- + void HandleRequestVehiclePrevSeat(WorldPacket &recv_data);
- + void HandleRequestVehicleNextSeat(WorldPacket &recv_data);
- + void HandleRequestVehicleSwitchSeat(WorldPacket &recv_data);
- + void HandleEnterPlayerVehicle(WorldPacket &recv_data);
- + void HandleEjectPasenger(WorldPacket &recv_data);
- + void HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data);
- +
- void HandleRequestRaidInfoOpcode( WorldPacket & recv_data );
- void HandleGroupInviteOpcode(WorldPacket& recvPacket);
- diff --git a/win/VC100/game.vcxproj b/win/VC100/game.vcxproj
- index be7d6ba..75b7f84 100644
- --- a/win/VC100/game.vcxproj
- +++ b/win/VC100/game.vcxproj
- @@ -505,6 +505,7 @@
- <ClCompile Include="..\..\src\game\Unit.cpp" />
- <ClCompile Include="..\..\src\game\UpdateData.cpp" />
- <ClCompile Include="..\..\src\game\Vehicle.cpp" />
- + <ClCompile Include="..\..\src\game\VehicleHandler.cpp" />
- <ClCompile Include="..\..\src\game\VoiceChatHandler.cpp" />
- <ClCompile Include="..\..\src\game\WaypointManager.cpp" />
- <ClCompile Include="..\..\src\game\WaypointMovementGenerator.cpp" />
- diff --git a/win/VC100/game.vcxproj.filters b/win/VC100/game.vcxproj.filters
- index 69d61d8..e6a6031 100644
- --- a/win/VC100/game.vcxproj.filters
- +++ b/win/VC100/game.vcxproj.filters
- @@ -246,6 +246,9 @@
- <ClCompile Include="..\..\src\game\UpdateData.cpp">
- <Filter>World/Handlers</Filter>
- </ClCompile>
- + <ClCompile Include="..\..\src\game\VehicleHandler.cpp" >
- + <Filter>World/Handlers</Filter>
- + </ClCompile>
- <ClCompile Include="..\..\src\game\VoiceChatHandler.cpp">
- <Filter>World/Handlers</Filter>
- </ClCompile>
- diff --git a/win/VC90/game.vcproj b/win/VC90/game.vcproj
- index fa647e2..eece821 100644
- --- a/win/VC90/game.vcproj
- +++ b/win/VC90/game.vcproj
- @@ -1007,6 +1007,10 @@
- >
- </File>
- <File
- + RelativePath="..\..\src\game\VehicleHandler.cpp"
- + >
- + </File>
- + <File
- RelativePath="..\..\src\game\VoiceChatHandler.cpp"
- >
- </File>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement