diff options
| author | Spp <spp@jorge.gr> | 2012-01-31 11:49:53 +0100 |
|---|---|---|
| committer | Spp <spp@jorge.gr> | 2012-01-31 11:49:53 +0100 |
| commit | 37b66384f3d905fb8de506aae48237900a1b6065 (patch) | |
| tree | f6c36187e06f76704d7a661179857916b18b6469 /src/server/game/Entities | |
| parent | fdbb3e52bcbaa236a26bd2bf8293a5deccb34a01 (diff) | |
| parent | d4670a558dd40fc03c9b143dcffa763c834ab966 (diff) | |
Merge branch 'master' into 4.x
Conflicts:
src/server/authserver/Server/AuthSocket.cpp
src/server/game/Entities/Object/Object.cpp
src/server/game/Entities/Player/Player.cpp
src/server/game/Entities/Unit/Unit.cpp
src/server/game/Handlers/AuctionHouseHandler.cpp
src/server/game/Handlers/CharacterHandler.cpp
src/server/game/Handlers/MovementHandler.cpp
src/server/game/Miscellaneous/SharedDefines.h
src/server/game/Spells/Spell.cpp
src/server/game/Spells/SpellEffects.cpp
Diffstat (limited to 'src/server/game/Entities')
| -rwxr-xr-x | src/server/game/Entities/Creature/Creature.cpp | 74 | ||||
| -rwxr-xr-x | src/server/game/Entities/Creature/Creature.h | 4 | ||||
| -rwxr-xr-x | src/server/game/Entities/Creature/CreatureGroups.cpp | 6 | ||||
| -rwxr-xr-x | src/server/game/Entities/GameObject/GameObject.cpp | 14 | ||||
| -rwxr-xr-x | src/server/game/Entities/GameObject/GameObject.h | 5 | ||||
| -rwxr-xr-x | src/server/game/Entities/Object/Object.cpp | 130 | ||||
| -rwxr-xr-x | src/server/game/Entities/Object/Object.h | 3 | ||||
| -rwxr-xr-x | src/server/game/Entities/Player/Player.cpp | 191 | ||||
| -rwxr-xr-x | src/server/game/Entities/Player/Player.h | 11 | ||||
| -rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 289 | ||||
| -rwxr-xr-x | src/server/game/Entities/Unit/Unit.h | 126 |
11 files changed, 433 insertions, 420 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 2c6ba86ea8f..25682999f62 100755 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -48,6 +48,8 @@ #include "Vehicle.h" #include "SpellAuraEffects.h" #include "Group.h" +#include "MoveSplineInit.h" +#include "MoveSpline.h" // apply implementation of the singletons TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const @@ -143,7 +145,7 @@ m_PlayerDamageReq(0), m_lootMoney(0), m_lootRecipient(0), m_lootRecipientGroup(0 m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), -m_creatureInfo(NULL), m_creatureData(NULL), m_formation(NULL) +m_creatureInfo(NULL), m_creatureData(NULL), m_formation(NULL), m_path_id(0) { m_regenTimer = CREATURE_REGEN_INTERVAL; m_valuesCount = UNIT_END; @@ -332,6 +334,7 @@ bool Creature::InitEntry(uint32 Entry, uint32 /*team*/, const CreatureData* data SetSpeed(MOVE_FLIGHT, 1.0f); // using 1.0 rate SetFloatValue(OBJECT_FIELD_SCALE_X, cinfo->scale); + SetLevitate(canFly()); // checked at loading m_defaultMovementType = MovementGeneratorType(cinfo->MovementType); @@ -435,6 +438,17 @@ void Creature::Update(uint32 diff) m_vehicleKit->Reset(); } + if (IsInWater()) + { + if (canSwim()) + AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING); + } + else + { + if (canWalk()) + RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING); + } + switch (m_deathState) { case JUST_ALIVED: @@ -472,9 +486,7 @@ void Creature::Update(uint32 diff) } case CORPSE: { - m_Events.Update(diff); - _UpdateSpells(diff); - + Unit::Update(diff); // deathstate changed on spells update, prevent problems if (m_deathState != CORPSE) break; @@ -565,9 +577,6 @@ void Creature::Update(uint32 diff) m_regenTimer = CREATURE_REGEN_INTERVAL; break; } - case DEAD_FALLING: - GetMotionMaster()->UpdateMotion(diff); - break; default: break; } @@ -715,7 +724,7 @@ void Creature::Motion_Initialize() i_motionMaster.Initialize(); } else if (m_formation->isFormed()) - i_motionMaster.MoveIdle(MOTION_SLOT_IDLE); //wait the order of leader + i_motionMaster.MoveIdle(); //wait the order of leader else i_motionMaster.Initialize(); } @@ -945,7 +954,8 @@ void Creature::AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint3 m_startMove = getMSTime(); m_moveTime = time;*/ - SendMonsterMove(x, y, z, time); + float speed = GetDistance(x, y, z) / ((float)time * 0.001f); + MonsterMoveWithSpeed(x, y, z, speed); } Player* Creature::GetLootRecipient() const @@ -1507,8 +1517,8 @@ void Creature::setDeathState(DeathState s) if (m_formation && m_formation->getLeader() == this) m_formation->FormationReset(true); - if ((canFly() || IsFlying()) && FallGround()) - return; + if ((canFly() || IsFlying())) + i_motionMaster.MoveFall(); Unit::setDeathState(CORPSE); } @@ -1520,7 +1530,7 @@ void Creature::setDeathState(DeathState s) SetLootRecipient(NULL); ResetPlayerDamageReq(); CreatureTemplate const* cinfo = GetCreatureInfo(); - AddUnitMovementFlag(MOVEMENTFLAG_WALKING); + SetWalk(true); if (GetCreatureInfo()->InhabitType & INHABIT_AIR) AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING); if (GetCreatureInfo()->InhabitType & INHABIT_WATER) @@ -1536,24 +1546,6 @@ void Creature::setDeathState(DeathState s) } } -bool Creature::FallGround() -{ - // Let's abort after we called this function one time - if (getDeathState() == DEAD_FALLING) - return false; - - float x, y, z; - GetPosition(x, y, z); - // use larger distance for vmap height search than in most other cases - float ground_Z = GetMap()->GetHeight(x, y, z, true, MAX_FALL_DISTANCE); - if (fabs(ground_Z - z) < 0.1f) - return false; - - GetMotionMaster()->MoveFall(ground_Z, EVENT_FALL_GROUND); - Unit::setDeathState(DEAD_FALLING); - return true; -} - void Creature::Respawn(bool force) { DestroyForNearbyPlayers(); @@ -2417,3 +2409,25 @@ bool Creature::IsDungeonBoss() const CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(GetEntry()); return cinfo && (cinfo->flags_extra & CREATURE_FLAG_EXTRA_DUNGEON_BOSS); } + +void Creature::SetWalk(bool enable) +{ + if (enable) + AddUnitMovementFlag(MOVEMENTFLAG_WALKING); + else + RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); + WorldPacket data(enable ? SMSG_MOVE_SPLINE_SET_WALK_MODE : SMSG_MOVE_SPLINE_SET_RUN_MODE, 9); + data.append(GetPackGUID()); + SendMessageToSet(&data, true); +} + +void Creature::SetLevitate(bool enable) +{ + if (enable) + AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + else + RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + WorldPacket data(enable ? SMSG_MOVE_SPLINE_DISABLE_GRAVITY : SMSG_MOVE_SPLINE_ENABLE_GRAVITY, 9); + data.append(GetPackGUID()); + SendMessageToSet(&data, true); +} diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 017085fec04..908f2b7e312 100755 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -522,6 +522,9 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature void AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type); CreatureAI* AI() const { return (CreatureAI*)i_AI; } + void SetWalk(bool enable); + void SetLevitate(bool enable); + uint32 GetShieldBlockValue() const //dunno mob block value { return (getLevel()/2 + uint32(GetStat(STAT_STRENGTH)/20)); @@ -575,7 +578,6 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature const char* GetNameForLocaleIdx(LocaleConstant locale_idx) const; void setDeathState(DeathState s); // override virtual Unit::setDeathState - bool FallGround(); bool LoadFromDB(uint32 guid, Map* map) { return LoadCreatureFromDB(guid, map, false); } bool LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap = true); diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index 3a63c32fc1e..f440fd497fc 100755 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -203,7 +203,7 @@ void CreatureGroup::FormationReset(bool dismiss) if (dismiss) itr->first->GetMotionMaster()->Initialize(); else - itr->first->GetMotionMaster()->MoveIdle(MOTION_SLOT_IDLE); + itr->first->GetMotionMaster()->MoveIdle(); sLog->outDebug(LOG_FILTER_UNITS, "Set %s movement for member GUID: %u", dismiss ? "default" : "idle", itr->first->GetGUIDLow()); } } @@ -212,10 +212,12 @@ void CreatureGroup::FormationReset(bool dismiss) void CreatureGroup::LeaderMoveTo(float x, float y, float z) { + //! To do: This should probably get its own movement generator or use WaypointMovementGenerator. + //! If the leader's path is known, member's path can be plotted as well using formation offsets. if (!m_leader) return; - float pathangle = atan2(m_leader->GetPositionY() - y, m_leader->GetPositionX() - x); + float pathangle = atan2(m_leader->GetPositionY() - y, m_leader->GetPositionX() - x); for (CreatureGroupMemberType::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 10220c7bc89..64cc1bb325c 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -974,7 +974,7 @@ void GameObject::ResetDoorOrButton() m_cooldownTime = 0; } -void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = false */) +void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = false */, Unit* user /*=NULL*/) { if (m_lootState != GO_READY) return; @@ -983,7 +983,7 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = f time_to_restore = GetGOInfo()->GetAutoCloseTime(); SwitchDoorOrButton(true, alternative); - SetLootState(GO_ACTIVATED); + SetLootState(GO_ACTIVATED, user); m_cooldownTime = time(NULL) + time_to_restore; } @@ -1053,7 +1053,7 @@ void GameObject::Use(Unit* user) case GAMEOBJECT_TYPE_DOOR: //0 case GAMEOBJECT_TYPE_BUTTON: //1 //doors/buttons never really despawn, only reset to default state/flags - UseDoorOrButton(); + UseDoorOrButton(0, false, user); // activate script GetMap()->ScriptsStart(sGameObjectScripts, GetDBTableGUIDLow(), spellCaster, this); @@ -1206,7 +1206,7 @@ void GameObject::Use(Unit* user) TriggeringLinkedGameObject(trapEntry, user); SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); - SetLootState(GO_ACTIVATED); + SetLootState(GO_ACTIVATED, user); // this appear to be ok, however others exist in addition to this that should have custom (ex: 190510, 188692, 187389) if (info->goober.customAnim) @@ -1864,3 +1864,9 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player* } } } + +void GameObject::SetLootState(LootState s, Unit* unit) +{ + m_lootState = s; + AI()->OnStateChanged(s, unit); +} diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 4daf73370f1..2329ed10e49 100755 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -714,7 +714,8 @@ class GameObject : public WorldObject, public GridObject<GameObject> void Use(Unit* user); LootState getLootState() const { return m_lootState; } - void SetLootState(LootState s) { m_lootState = s; } + // Note: unit is only used when s = GO_ACTIVATED + void SetLootState(LootState s, Unit* unit = NULL); uint16 GetLootMode() { return m_LootMode; } bool HasLootMode(uint16 lootMode) { return m_LootMode & lootMode; } @@ -748,7 +749,7 @@ class GameObject : public WorldObject, public GridObject<GameObject> bool hasQuest(uint32 quest_id) const; bool hasInvolvedQuest(uint32 quest_id) const; bool ActivateToQuest(Player* target) const; - void UseDoorOrButton(uint32 time_to_restore = 0, bool alternative = false); + void UseDoorOrButton(uint32 time_to_restore = 0, bool alternative = false, Unit* user = NULL); // 0 = use `gameobject`.`spawntimesecs` void ResetDoorOrButton(); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index d4e48548aa0..d89849f7ccf 100755 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -45,6 +45,7 @@ #include "TemporarySummon.h" #include "Totem.h" #include "OutdoorPvPMgr.h" +#include "MovementPacketBuilder.h" uint32 GuidHigh2TypeId(uint32 guid_hi) { @@ -309,65 +310,9 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags) const *data << self->GetSpeed(MOVE_TURN_RATE); *data << self->GetSpeed(MOVE_PITCH_RATE); - Player const* player = ToPlayer(); - // 0x08000000 - if (player && player->isInFlight()) - { - uint32 flags3 = SPLINEFLAG_GLIDE; - - *data << uint32(flags3); // splines flag - - if (flags3 & 0x00004000) // FinalOrientation - { - *data << (float)0; - } - else if (flags3 & 0x00001000) // FinalOrientation - { - *data << (float)0; - *data << (float)0; - *data << (float)0; - } - else if (flags3 & 0x00002000) // FinalTarget - { - *data << uint64(0); - } - - FlightPathMovementGenerator *fmg = (FlightPathMovementGenerator*)(player->GetMotionMaster()->top()); - TaxiPathNodeList const& path = fmg->GetPath(); - - float x, y, z; - player->GetPosition(x, y, z); - - uint32 inflighttime = uint32(path.GetPassedLength(fmg->GetCurrentNode(), x, y, z) * 32); - uint32 traveltime = uint32(path.GetTotalLength() * 32); - - *data << uint32(inflighttime); // passed move time? - *data << uint32(traveltime); // full move time? - *data << uint32(0); // ticks count? - - *data << float(0); // added in 3.1 - *data << float(0); // added in 3.1 - *data << float(0); // added in 3.1 - - *data << uint32(0); // added in 3.1 - - uint32 poscount = uint32(path.size()); - *data << uint32(poscount); // points count - - for (uint32 i = 0; i < poscount; ++i) - { - *data << float(path[i].x); - *data << float(path[i].y); - *data << float(path[i].z); - } - - *data << uint8(0); // added in 3.0.8 - - *data << float(path[poscount-1].x); - *data << float(path[poscount-1].y); - *data << float(path[poscount-1].z); - } + if (self->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_SPLINE_ENABLED)) + Movement::PacketBuilder::WriteCreate(*self->movespline, *data); } else { @@ -1549,6 +1494,70 @@ void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const z = new_z+ 0.05f; // just to be sure that we are not a few pixel under the surface } +void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const +{ + switch (GetTypeId()) + { + case TYPEID_UNIT: + { + // non fly unit don't must be in air + // non swim unit must be at ground (mostly speedup, because it don't must be in water and water level check less fast + if (!((Creature const*)this)->canFly()) + { + bool canSwim = ((Creature const*)this)->canSwim(); + float ground_z = z; + float max_z = canSwim + ? GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK)) + : ((ground_z = GetBaseMap()->GetHeight(x, y, z, true))); + if (max_z > INVALID_HEIGHT) + { + if (z > max_z) + z = max_z; + else if (z < ground_z) + z = ground_z; + } + } + else + { + float ground_z = GetBaseMap()->GetHeight(x, y, z, true); + if (z < ground_z) + z = ground_z; + } + break; + } + case TYPEID_PLAYER: + { + // for server controlled moves playr work same as creature (but it can always swim) + if (!((Player const*)this)->canFly()) + { + float ground_z = z; + float max_z = GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK)); + if (max_z > INVALID_HEIGHT) + { + if (z > max_z) + z = max_z; + else if (z < ground_z) + z = ground_z; + } + } + else + { + float ground_z = GetBaseMap()->GetHeight(x, y, z, true); + if (z < ground_z) + z = ground_z; + } + break; + } + default: + { + float ground_z = GetBaseMap()->GetHeight(x, y, z, true); + if(ground_z > INVALID_HEIGHT) + z = ground_z; + break; + } + } +} + bool Position::IsPositionValid() const { return Trinity::IsValidMapCoord(m_positionX, m_positionY, m_positionZ, m_orientation); @@ -1987,7 +1996,8 @@ void Unit::BuildHeartBeatMsg(WorldPacket* data) const void WorldObject::SendMessageToSet(WorldPacket* data, bool self) { - SendMessageToSetInRange(data, GetVisibilityRange(), self); + if (IsInWorld()) + SendMessageToSetInRange(data, GetVisibilityRange(), self); } void WorldObject::SendMessageToSetInRange(WorldPacket* data, float dist, bool /*self*/) @@ -2475,7 +2485,7 @@ void WorldObject::GetNearPoint(WorldObject const* /*searcher*/, float &x, float { GetNearPoint2D(x, y, distance2d+searcher_size, absAngle); z = GetPositionZ(); - UpdateGroundPositionZ(x, y, z); + UpdateAllowedPositionZ(x, y, z); /* // if detection disabled, return first point diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index b421142bef1..666f71ffe68 100755 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -497,7 +497,9 @@ struct MovementInfo } uint32 GetMovementFlags() { return flags; } + void SetMovementFlags(uint32 flag) { flags = flag; } void AddMovementFlag(uint32 flag) { flags |= flag; } + void RemoveMovementFlag(uint32 flag) { flags &= ~flag; } bool HasMovementFlag(uint32 flag) const { return flags & flag; } uint16 GetExtraMovementFlags() { return flags2; } @@ -615,6 +617,7 @@ class WorldObject : public Object, public WorldLocation return (m_valuesCount > UNIT_FIELD_COMBATREACH) ? m_floatValues[UNIT_FIELD_COMBATREACH] : DEFAULT_WORLD_OBJECT_SIZE; } void UpdateGroundPositionZ(float x, float y, float &z) const; + void UpdateAllowedPositionZ(float x, float y, float &z) const; void GetRandomPoint(const Position &srcPos, float distance, float &rand_x, float &rand_y, float &rand_z) const; void GetRandomPoint(const Position &srcPos, float distance, Position &pos) const diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index a211d848f59..8cf1413611b 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -297,15 +297,24 @@ Item* TradeData::GetItem(TradeSlots slot) const return m_items[slot] ? m_player->GetItemByGuid(m_items[slot]) : NULL; } -bool TradeData::HasItem(uint64 item_guid) const +bool TradeData::HasItem(uint64 itemGuid) const { for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i) - if (m_items[i] == item_guid) + if (m_items[i] == itemGuid) return true; return false; } +TradeSlots TradeData::GetTradeSlotForItem(uint64 itemGuid) const +{ + for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i) + if (m_items[i] == itemGuid) + return TradeSlots(i); + + return TRADE_SLOT_INVALID; +} + Item* TradeData::GetSpellCastItem() const { return m_spellCastItem ? m_player->GetItemByGuid(m_spellCastItem) : NULL; @@ -2179,6 +2188,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati // reset movement flags at teleport, because player will continue move with these flags after teleport SetUnitMovementFlags(0); + DisableSpline(); if (m_transport) { @@ -2387,9 +2397,14 @@ bool Player::TeleportToBGEntryPoint() if (m_bgData.joinPos.m_mapId == MAPID_INVALID) return false; + Group* group = GetGroup(); + if (group && group->isLFGGroup() && group->GetMembersCount() == 1) + group->Disband(); + else + ScheduleDelayedOperation(DELAYED_BG_GROUP_RESTORE); + ScheduleDelayedOperation(DELAYED_BG_MOUNT_RESTORE); ScheduleDelayedOperation(DELAYED_BG_TAXI_RESTORE); - ScheduleDelayedOperation(DELAYED_BG_GROUP_RESTORE); return TeleportTo(m_bgData.joinPos); } @@ -5240,43 +5255,10 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) } } -/** - * FallMode = 0 implies that the player is dying, or already dead, and the proper death state will be set. - * = 1 simply causes the player to plummet towards the ground, and not suffer any damage. - * = 2 causes the player to plummet towards the ground, and causes falling damage, regardless - * of any auras that might of prevented fall damage. - */ -bool Player::FallGround(uint8 FallMode) -{ - // Let's abort after we called this function one time - if (getDeathState() == DEAD_FALLING && FallMode == 0) - return false; - - float x, y, z; - GetPosition(x, y, z); - float ground_Z = GetMap()->GetHeight(x, y, z); - float z_diff = 0.0f; - if ((z_diff = fabs(ground_Z - z)) < 0.1f) - return false; - - GetMotionMaster()->MoveFall(ground_Z, EVENT_FALL_GROUND); - - // Below formula for falling damage is from Player::HandleFall - if (FallMode == 2 && z_diff >= 14.57f) - { - uint32 damage = std::min(GetMaxHealth(), (uint32)((0.018f * z_diff - 0.2426f) * GetMaxHealth() * sWorld->getRate(RATE_DAMAGE_FALL))); - if (damage) - EnvironmentalDamage(DAMAGE_FALL, damage); - } - else if (FallMode == 0) - Unit::setDeathState(DEAD_FALLING); - return true; -} - void Player::KillPlayer() { if (IsFlying() && !GetTransport()) - FallGround(); + i_motionMaster.MoveFall(); SetMovement(MOVE_ROOT); @@ -7614,6 +7596,22 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) SendInitWorldStates(newZone, newArea); // only if really enters to new zone, not just area change, works strange... } + // group update + if (GetGroup()) + { + SetGroupUpdateFlag(GROUP_UPDATE_FULL); + Group* grp = GetGroup(); + if (GetSession() && grp->isLFGGroup() && sLFGMgr->IsTeleported(GetGUID())) + { + for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* tempplr = itr->getSource(); + if (tempplr) + GetSession()->SendNameQueryOpcode(tempplr->GetGUID()); + } + } + } + m_zoneUpdateId = newZone; m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL; @@ -7701,10 +7699,6 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) // recent client version not send leave/join channel packets for built-in local channels UpdateLocalChannels(newZone); - // group update - if (GetGroup()) - SetGroupUpdateFlag(GROUP_UPDATE_FULL); - UpdateZoneDependentAuras(newZone); } @@ -8856,7 +8850,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) } } - go->SetLootState(GO_ACTIVATED); + go->SetLootState(GO_ACTIVATED, this); } if (go->getLootState() == GO_ACTIVATED) @@ -11955,6 +11949,93 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto) const return EQUIP_ERR_ITEM_NOT_FOUND; } +InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObject const* lootedObject) const +{ + LfgDungeonSet const& dungeons = sLFGMgr->GetSelectedDungeons(GetGUID()); + if (dungeons.empty()) + return EQUIP_ERR_OK; // not using LFG + + if (!GetGroup() || !GetGroup()->isLFGGroup()) + return EQUIP_ERR_OK; // not in LFG group + + // check if looted object is inside the lfg dungeon + bool lootedObjectInDungeon = false; + Map const* map = lootedObject->GetMap(); + if (uint32 dungeonId = sLFGMgr->GetDungeon(GetGroup()->GetGUID(), true)) + if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId)) + if (dungeon->map == map->GetId() && dungeon->difficulty == map->GetDifficulty()) + lootedObjectInDungeon = true; + + if (!lootedObjectInDungeon) + return EQUIP_ERR_OK; + + if (!proto) + return EQUIP_ERR_ITEM_NOT_FOUND; + // Used by group, function NeedBeforeGreed, to know if a prototype can be used by a player + + const static uint32 item_weapon_skills[MAX_ITEM_SUBCLASS_WEAPON] = + { + SKILL_AXES, SKILL_2H_AXES, SKILL_BOWS, SKILL_GUNS, SKILL_MACES, + SKILL_2H_MACES, SKILL_POLEARMS, SKILL_SWORDS, SKILL_2H_SWORDS, 0, + SKILL_STAVES, 0, 0, SKILL_FIST_WEAPONS, 0, + SKILL_DAGGERS, SKILL_THROWN, SKILL_ASSASSINATION, SKILL_CROSSBOWS, SKILL_WANDS, + SKILL_FISHING + }; //Copy from function Item::GetSkill() + + if ((proto->AllowableClass & getClassMask()) == 0 || (proto->AllowableRace & getRaceMask()) == 0) + return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM; + + if (proto->RequiredSpell != 0 && !HasSpell(proto->RequiredSpell)) + return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; + + if (proto->RequiredSkill != 0) + { + if (!GetSkillValue(proto->RequiredSkill)) + return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; + else if (GetSkillValue(proto->RequiredSkill) < proto->RequiredSkillRank) + return EQUIP_ERR_CANT_EQUIP_SKILL; + } + + uint8 _class = getClass(); + + if (proto->Class == ITEM_CLASS_WEAPON && GetSkillValue(item_weapon_skills[proto->SubClass]) == 0) + return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; + + if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass > ITEM_SUBCLASS_ARMOR_MISCELLANEOUS && proto->SubClass < ITEM_SUBCLASS_ARMOR_BUCKLER && proto->InventoryType != INVTYPE_CLOAK) + { + if (_class == CLASS_WARRIOR || _class == CLASS_PALADIN || _class == CLASS_DEATH_KNIGHT) + { + if (getLevel() < 40) + { + if (proto->SubClass != ITEM_SUBCLASS_ARMOR_MAIL) + return EQUIP_ERR_CANT_DO_RIGHT_NOW; + } + else if (proto->SubClass != ITEM_SUBCLASS_ARMOR_PLATE) + return EQUIP_ERR_CANT_DO_RIGHT_NOW; + } + else if (_class == CLASS_HUNTER || _class == CLASS_SHAMAN) + { + if (getLevel() < 40) + { + if (proto->SubClass != ITEM_SUBCLASS_ARMOR_LEATHER) + return EQUIP_ERR_CANT_DO_RIGHT_NOW; + } + else if (proto->SubClass != ITEM_SUBCLASS_ARMOR_MAIL) + return EQUIP_ERR_CANT_DO_RIGHT_NOW; + } + + if (_class == CLASS_ROGUE || _class == CLASS_DRUID) + if (proto->SubClass != ITEM_SUBCLASS_ARMOR_LEATHER) + return EQUIP_ERR_CANT_DO_RIGHT_NOW; + + if (_class == CLASS_MAGE || _class == CLASS_PRIEST || _class == CLASS_WARLOCK) + if (proto->SubClass != ITEM_SUBCLASS_ARMOR_CLOTH) + return EQUIP_ERR_CANT_DO_RIGHT_NOW; + } + + return EQUIP_ERR_OK; +} + Item* Player::StoreNewItem(ItemPosCountVec const& dest, uint32 item, bool update, int32 randomPropertyId) { AllowedLooterSet allowedLooters; @@ -12797,6 +12878,14 @@ void Player::SplitItem(uint16 src, uint16 dst, uint32 count) return; } + //! If trading + if (TradeData* tradeData = GetTradeData()) + { + //! If current item is in trade window (only possible with packet spoofing - silent return) + if (tradeData->GetTradeSlotForItem(pSrcItem->GetGUID()) != TRADE_SLOT_INVALID) + return; + } + sLog->outDebug(LOG_FILTER_PLAYER_ITEMS, "STORAGE: SplitItem bag = %u, slot = %u, item = %u, count = %u", dstbag, dstslot, pSrcItem->GetEntry(), count); Item* pNewItem = pSrcItem->CloneItem(count, this); if (!pNewItem) @@ -12825,7 +12914,7 @@ void Player::SplitItem(uint16 src, uint16 dst, uint32 count) pSrcItem->SetState(ITEM_CHANGED, this); StoreItem(dest, pNewItem, true); } - else if (IsBankPos (dst)) + else if (IsBankPos(dst)) { // change item amount before check (for unique max count check) pSrcItem->SetCount(pSrcItem->GetCount() - count); @@ -12845,7 +12934,7 @@ void Player::SplitItem(uint16 src, uint16 dst, uint32 count) pSrcItem->SetState(ITEM_CHANGED, this); BankItem(dest, pNewItem, true); } - else if (IsEquipmentPos (dst)) + else if (IsEquipmentPos(dst)) { // change item amount before check (for unique max count check), provide space for splitted items pSrcItem->SetCount(pSrcItem->GetCount() - count); @@ -14055,6 +14144,10 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool PrepareQuestMenu(source->GetGUID()); } + if (source->GetTypeId() == TYPEID_GAMEOBJECT) + if (source->ToGameObject()->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + PrepareQuestMenu(source->GetGUID()); + for (GossipMenuItemsMap::const_iterator itr = menuItemBounds.first; itr != menuItemBounds.second; ++itr) { bool canTalk = true; @@ -14140,11 +14233,6 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool switch (itr->second.OptionType) { - case GOSSIP_OPTION_QUESTGIVER: - if (go->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) - PrepareQuestMenu(source->GetGUID()); - canTalk = false; - break; case GOSSIP_OPTION_GOSSIP: if (go->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER && go->GetGoType() != GAMEOBJECT_TYPE_GOOBER) canTalk = false; @@ -16751,6 +16839,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) _LoadInstanceTimeRestrictions(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADINSTANCELOCKTIMES)); _LoadBGData(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADBGDATA)); + GetSession()->SetPlayer(this); MapEntry const* mapEntry = sMapStore.LookupEntry(mapId); if (!mapEntry || !IsPositionValid()) { @@ -21577,8 +21666,6 @@ void Player::SendInitialVisiblePackets(Unit* target) SendAurasForTarget(target); if (target->isAlive()) { - if (target->GetMotionMaster()->GetCurrentMovementGeneratorType() != IDLE_MOTION_TYPE) - target->SendMonsterMoveWithSpeedToCurrentDestination(this); if (target->HasUnitState(UNIT_STAT_MELEE_ATTACKING) && target->getVictim()) target->SendMeleeAttackStart(target->getVictim()); } @@ -21836,7 +21923,9 @@ void Player::SendInitialPacketsBeforeAddToMap() // SMSG_PET_GUIDS // SMSG_UPDATE_WORLD_STATE // SMSG_POWER_UPDATE + SendCurrencies(); + SetMover(this); } void Player::SendInitialPacketsAfterAddToMap() diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 21027402e84..f462f5af48f 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -290,13 +290,14 @@ struct PvPInfo struct DuelInfo { - DuelInfo() : initiator(NULL), opponent(NULL), startTimer(0), startTime(0), outOfBound(0) {} + DuelInfo() : initiator(NULL), opponent(NULL), startTimer(0), startTime(0), outOfBound(0), isMounted(false) {} Player* initiator; Player* opponent; time_t startTimer; time_t startTime; time_t outOfBound; + bool isMounted; }; struct Areas @@ -702,7 +703,8 @@ enum TradeSlots { TRADE_SLOT_COUNT = 7, TRADE_SLOT_TRADED_COUNT = 6, - TRADE_SLOT_NONTRADED = 6 + TRADE_SLOT_NONTRADED = 6, + TRADE_SLOT_INVALID = -1, }; enum TransferAbortReason @@ -1013,7 +1015,8 @@ class TradeData TradeData* GetTraderData() const; Item* GetItem(TradeSlots slot) const; - bool HasItem(uint64 item_guid) const; + bool HasItem(uint64 itemGuid) const; + TradeSlots GetTradeSlotForItem(uint64 itemGuid) const; void SetItem(TradeSlots slot, Item* item); uint32 GetSpell() const { return m_spell; } @@ -1333,6 +1336,7 @@ class Player : public Unit, public GridObject<Player> bool HasItemTotemCategory(uint32 TotemCategory) const; InventoryResult CanUseItem(ItemTemplate const* pItem) const; InventoryResult CanUseAmmo(uint32 item) const; + InventoryResult CanRollForItemInLFG(ItemTemplate const* item, WorldObject const* lootedObject) const; Item* StoreNewItem(ItemPosCountVec const& pos, uint32 item, bool update, int32 randomPropertyId = 0); Item* StoreNewItem(ItemPosCountVec const& pos, uint32 item, bool update, int32 randomPropertyId, AllowedLooterSet &allowedLooters); Item* StoreItem(ItemPosCountVec const& pos, Item* pItem, bool update); @@ -2046,7 +2050,6 @@ class Player : public Unit, public GridObject<Player> Corpse* GetCorpse() const; void SpawnCorpseBones(); void CreateCorpse(); - bool FallGround(uint8 FallMode = 0); void KillPlayer(); uint32 GetResurrectionSpellId(); void ResurrectPlayer(float restore_percent, bool applySickness = false); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 430b6adb6ec..103e42a9da9 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -45,16 +45,16 @@ #include "InstanceSaveMgr.h" #include "GridNotifiersImpl.h" #include "CellImpl.h" -#include "Path.h" #include "CreatureGroups.h" #include "PetAI.h" #include "PassiveAI.h" -#include "Traveller.h" #include "TemporarySummon.h" #include "Vehicle.h" #include "Transport.h" #include "InstanceScript.h" #include "SpellInfo.h" +#include "MoveSplineInit.h" +#include "MoveSpline.h" #include <math.h> @@ -62,9 +62,9 @@ float baseMoveSpeed[MAX_MOVE_TYPE] = { 2.5f, // MOVE_WALK 7.0f, // MOVE_RUN - 2.5f, // MOVE_RUN_BACK + 4.5f, // MOVE_RUN_BACK 4.722222f, // MOVE_SWIM - 4.5f, // MOVE_SWIM_BACK + 2.5f, // MOVE_SWIM_BACK 3.141594f, // MOVE_TURN_RATE 7.0f, // MOVE_FLIGHT 4.5f, // MOVE_FLIGHT_BACK @@ -73,9 +73,9 @@ float baseMoveSpeed[MAX_MOVE_TYPE] = float playerBaseMoveSpeed[MAX_MOVE_TYPE] = { 2.5f, // MOVE_WALK 7.0f, // MOVE_RUN - 2.5f, // MOVE_RUN_BACK + 4.5f, // MOVE_RUN_BACK 4.722222f, // MOVE_SWIM - 4.5f, // MOVE_SWIM_BACK + 2.5f, // MOVE_SWIM_BACK 3.141594f, // MOVE_TURN_RATE 7.0f, // MOVE_FLIGHT 4.5f, // MOVE_FLIGHT_BACK @@ -148,7 +148,7 @@ Unit::Unit(bool isWorldObject): WorldObject(isWorldObject), m_movedPlayer(NULL), m_lastSanctuaryTime(0), IsAIEnabled(false), NeedChangeAI(false), m_ControlledByPlayer(false), i_AI(NULL), i_disabledAI(NULL), m_procDeep(0), m_removedAurasCount(0), i_motionMaster(this), m_ThreatManager(this), m_vehicle(NULL), -m_vehicleKit(NULL), m_unitTypeMask(UNIT_MASK_NONE), m_HostileRefManager(this) +m_vehicleKit(NULL), m_unitTypeMask(UNIT_MASK_NONE), m_HostileRefManager(this), movespline(new Movement::MoveSpline()) { #ifdef _MSC_VER #pragma warning(default:4355) @@ -280,6 +280,7 @@ Unit::~Unit() delete m_charmInfo; delete m_vehicleKit; + delete movespline; ASSERT(!m_duringRemoveFromWorld); ASSERT(!m_attacking); @@ -346,6 +347,7 @@ void Unit::Update(uint32 p_time) ModifyAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, HealthAbovePct(75)); } + UpdateSplineMovement(p_time); i_motionMaster.UpdateMotion(p_time); } @@ -357,151 +359,46 @@ bool Unit::haveOffhandWeapon() const return m_canDualWield; } -void Unit::SendMonsterMoveWithSpeedToCurrentDestination(Player* player) +void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed) { - float x, y, z; - if (GetMotionMaster()->GetDestination(x, y, z)) - SendMonsterMoveWithSpeed(x, y, z, 0, player); -} - -void Unit::SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime, Player* player) -{ - if (!transitTime) - { - if (GetTypeId() == TYPEID_PLAYER) - { - Traveller<Player> traveller(*(Player*)this); - transitTime = traveller.GetTotalTrevelTimeTo(x, y, z); - } - else - { - Traveller<Creature> traveller(*ToCreature()); - transitTime = traveller.GetTotalTrevelTimeTo(x, y, z); - } - } - //float orientation = (float)atan2((double)dy, (double)dx); - SendMonsterMove(x, y, z, transitTime, player); -} - -void Unit::SetFacing(float ori, WorldObject* obj) -{ - SetOrientation(obj ? GetAngle(obj) : ori); - - WorldPacket data(SMSG_MONSTER_MOVE, (1+12+4+1+(obj ? 8 : 4)+4+4+4+12+GetPackGUID().size())); - data.append(GetPackGUID()); - data << uint8(0); // unk - data << GetPositionX() << GetPositionY() << GetPositionZ(); - data << getMSTime(); - if (obj) - { - data << uint8(SPLINETYPE_FACING_TARGET); - data << uint64(obj->GetGUID()); - } - else - { - data << uint8(SPLINETYPE_FACING_ANGLE); - data << ori; - } - data << uint32(SPLINEFLAG_NONE); - data << uint32(0); // move time 0 - data << uint32(1); // one point - data << GetPositionX() << GetPositionY() << GetPositionZ(); - SendMessageToSet(&data, true); -} - -void Unit::SendMonsterStop(bool on_death) -{ - WorldPacket data(SMSG_MONSTER_MOVE, (17 + GetPackGUID().size())); - data.append(GetPackGUID()); - data << uint8(0); // new in 3.1 - data << GetPositionX() << GetPositionY() << GetPositionZ(); - data << getMSTime(); - - if (on_death == true) - { - data << uint8(0); - data << uint32((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING) ? SPLINEFLAG_FLYING : SPLINEFLAG_WALKING); - data << uint32(0); // Time in between points - data << uint32(1); // 1 single waypoint - data << GetPositionX() << GetPositionY() << GetPositionZ(); - } - else - data << uint8(1); - - SendMessageToSet(&data, true); - - ClearUnitState(UNIT_STAT_MOVE); + Movement::MoveSplineInit init(*this); + init.MoveTo(x,y,z); + init.SetVelocity(speed); + init.Launch(); } -void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player) +void Unit::UpdateSplineMovement(uint32 t_diff) { - WorldPacket data(SMSG_MONSTER_MOVE, 1+12+4+1+4+4+4+12+GetPackGUID().size()); - data.append(GetPackGUID()); - - data << uint8(0); // new in 3.1 - data << GetPositionX() << GetPositionY() << GetPositionZ(); - data << getMSTime(); - - data << uint8(0); - data << uint32((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING) ? SPLINEFLAG_FLYING : SPLINEFLAG_WALKING); - data << Time; // Time in between points - data << uint32(1); // 1 single waypoint - data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B - - if (player) - player->GetSession()->SendPacket(&data); - else - SendMessageToSet(&data, true); - - AddUnitState(UNIT_STAT_MOVE); -} + enum{ + POSITION_UPDATE_DELAY = 400, + }; -void Unit::SendMonsterMove(MonsterMoveData const& moveData, Player* player) -{ - WorldPacket data(SMSG_MONSTER_MOVE, GetPackGUID().size() + 1 + 12 + 4 + 1 + 4 + 8 + 4 + 4 + 12); - data.append(GetPackGUID()); + if (movespline->Finalized()) + return; - data << uint8(0); // new in 3.1 - data << GetPositionX() << GetPositionY() << GetPositionZ(); - data << getMSTime(); + movespline->updateState(t_diff); + bool arrived = movespline->Finalized(); - data << uint8(0); - data << moveData.SplineFlag; + if (arrived) + DisableSpline(); - if (moveData.SplineFlag & SPLINEFLAG_ANIMATIONTIER) + m_movesplineTimer.Update(t_diff); + if (m_movesplineTimer.Passed() || arrived) { - data << uint8(moveData.AnimationState); - data << uint32(0); - } + m_movesplineTimer.Reset(POSITION_UPDATE_DELAY); + Movement::Location loc = movespline->ComputePosition(); - data << moveData.Time; - - if (moveData.SplineFlag & SPLINEFLAG_TRAJECTORY) - { - data << moveData.SpeedZ; - data << uint32(0); // walk time after jump + if (GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->UpdatePosition(loc.x,loc.y,loc.z,loc.orientation); + else + GetMap()->CreatureRelocation((Creature*)this,loc.x,loc.y,loc.z,loc.orientation); } - - data << uint32(1); // waypoint count - data << moveData.DestLocation.GetPositionX(); - data << moveData.DestLocation.GetPositionY(); - data << moveData.DestLocation.GetPositionZ(); - - if (player) - player->GetSession()->SendPacket(&data); - else - SendMessageToSet(&data, true); } -void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 MoveFlags, uint32 time, float speedZ, Player* player) +void Unit::DisableSpline() { - MonsterMoveData data; - data.DestLocation.Relocate(NewPosX, NewPosY, NewPosZ); - data.SplineFlag = MoveFlags; - data.Time = time; - data.SpeedZ = speedZ; - - SendMonsterMove(data, player); + m_movementInfo.RemoveMovementFlag(MovementFlags(MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD)); + movespline->_Interrupt(); } void Unit::SendMonsterMoveExitVehicle(Position const* newPos) @@ -731,6 +628,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam // duel ends when player has 1 or less hp bool duel_hasEnded = false; + bool duel_wasMounted = false; if (victim->GetTypeId() == TYPEID_PLAYER && victim->ToPlayer()->duel && damage >= (health-1)) { // prevent kill only if killed in duel and killed by opponent or opponent controlled creature @@ -739,6 +637,20 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam duel_hasEnded = true; } + else if (victim->IsVehicle() && damage >= (health-1) && victim->GetCharmer() && victim->GetCharmer()->GetTypeId() == TYPEID_PLAYER) + { + Player* victimRider = victim->GetCharmer()->ToPlayer(); + + if (victimRider && victimRider->duel && victimRider->duel->isMounted) + { + // prevent kill only if killed in duel and killed by opponent or opponent controlled creature + if (victimRider->duel->opponent == this || victimRider->duel->opponent->GetGUID() == GetCharmerGUID()) + damage = health - 1; + + duel_wasMounted = true; + duel_hasEnded = true; + } + } if (GetTypeId() == TYPEID_PLAYER && this != victim) { @@ -848,8 +760,18 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam // last damage from duel opponent if (duel_hasEnded) { - ASSERT(victim->GetTypeId() == TYPEID_PLAYER); - Player* he = victim->ToPlayer(); + Player* he; + + if (duel_wasMounted) + { + ASSERT(victim->GetCharmer()->GetTypeId() == TYPEID_PLAYER); + he = victim->GetCharmer()->ToPlayer(); + } + else + { + ASSERT(victim->GetTypeId() == TYPEID_PLAYER); + he = victim->ToPlayer(); + } ASSERT(he->duel); @@ -2226,12 +2148,12 @@ void Unit::SendMeleeAttackStart(Unit* victim) void Unit::SendMeleeAttackStop(Unit* victim) { - WorldPacket data(SMSG_ATTACKSTOP, (8+8+4)); // we guess size + WorldPacket data(SMSG_ATTACKSTOP, (8+8+4)); data.append(GetPackGUID()); data.append(victim ? victim->GetPackGUID() : 0); // can be 0x00... data << uint32(0); // can be 0x1 SendMessageToSet(&data, true); - sLog->outStaticDebug("WORLD: Sent SMSG_ATTACKSTART"); + sLog->outStaticDebug("WORLD: Sent SMSG_ATTACKSTOP"); if (victim) sLog->outDetail("%s %u stopped attacking %s %u", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUIDLow(), (victim->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), victim->GetGUIDLow()); @@ -3115,17 +3037,6 @@ bool Unit::isInBackInMap(Unit const* target, float distance, float arc) const return IsWithinDistInMap(target, distance) && !HasInArc(2 * M_PI - arc, target); } -void Unit::SetFacingToObject(WorldObject* pObject) -{ - // update orientation at server - SetOrientation(GetAngle(pObject)); - - // and client - WorldPacket data; - BuildHeartBeatMsg(&data); - SendMessageToSet(&data, false); -} - bool Unit::isInAccessiblePlaceFor(Creature const* c) const { if (IsInWater()) @@ -7191,6 +7102,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere return false; basepoints0 = CalculatePctN(int32(damage), triggerAmount); triggered_spell_id = 58879; + // Cast on spirit wolf + CastCustomSpell(this, triggered_spell_id, &basepoints0, NULL, NULL, true, NULL, triggeredByAura); break; } // Shaman T8 Elemental 4P Bonus @@ -8947,18 +8860,17 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg // Maelstrom Weapon case 53817: { - // Item - Shaman T10 Enhancement 4P Bonus - if (AuraEffect const* aurEff = GetAuraEffect(70832, 0)) - if (Aura const* maelstrom = GetAura(53817)) - if ((maelstrom->GetStackAmount() == maelstrom->GetSpellInfo()->StackAmount) && roll_chance_i(aurEff->GetAmount())) - CastSpell(this, 70831, true, castItem, triggeredByAura); - // has rank dependant proc chance, ignore too often cases // PPM = 2.5 * (rank of talent), uint32 rank = auraSpellInfo->GetRank(); // 5 rank -> 100% 4 rank -> 80% and etc from full rate if (!roll_chance_i(20*rank)) return false; + // Item - Shaman T10 Enhancement 4P Bonus + if (AuraEffect const* aurEff = GetAuraEffect(70832, 0)) + if (Aura const* maelstrom = GetAura(53817)) + if ((maelstrom->GetStackAmount() == maelstrom->GetSpellInfo()->StackAmount - 1) && roll_chance_i(aurEff->GetAmount())) + CastSpell(this, 70831, true, castItem, triggeredByAura); break; } // Astral Shift @@ -13150,7 +13062,7 @@ void Unit::setDeathState(DeathState s) ClearDiminishings(); GetMotionMaster()->Clear(false); GetMotionMaster()->MoveIdle(); - SendMonsterStop(true); + StopMoving(); // without this when removing IncreaseMaxHealth aura player may stuck with 1 hp // do not why since in IncreaseMaxHealth currenthealth is checked SetHealth(0); @@ -13969,7 +13881,7 @@ void Unit::SetHealth(uint32 val) { if (getDeathState() == JUST_DIED) val = 0; - else if (GetTypeId() == TYPEID_PLAYER && (getDeathState() == DEAD || getDeathState() == DEAD_FALLING)) + else if (GetTypeId() == TYPEID_PLAYER && getDeathState() == DEAD) val = 1; else { @@ -15145,22 +15057,20 @@ void Unit::StopMoving() { ClearUnitState(UNIT_STAT_MOVING); - // send explicit stop packet - // rely on vmaps here because for example stormwind is in air - //float z = sMapMgr->GetBaseMap(GetMapId())->GetHeight(GetPositionX(), GetPositionY(), GetPositionZ(), true); - //if (fabs(GetPositionZ() - z) < 2.0f) - // Relocate(GetPositionX(), GetPositionY(), z); - //Relocate(GetPositionX(), GetPositionY(), GetPositionZ()); + // not need send any packets if not in world + if (!IsInWorld()) + return; - if (!(GetUnitMovementFlags() & MOVEMENTFLAG_ONTRANSPORT)) - SendMonsterStop(); + Movement::MoveSplineInit init(*this); + init.SetFacing(GetOrientation()); + init.Launch(); } void Unit::SendMovementFlagUpdate() { WorldPacket data; BuildHeartBeatMsg(&data); - SendMessageToSet(&data, false); + SendMessageToSet(&data, true); } bool Unit::IsSitState() const @@ -16426,6 +16336,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au case CHARM_TYPE_VEHICLE: SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); charmer->ToPlayer()->SetClientControl(this, 1); + charmer->ToPlayer()->SetMover(this); charmer->ToPlayer()->SetViewpoint(this, true); charmer->ToPlayer()->VehicleSpellInitialize(); break; @@ -16434,6 +16345,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); charmer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); charmer->ToPlayer()->SetClientControl(this, 1); + charmer->ToPlayer()->SetMover(this); charmer->ToPlayer()->SetViewpoint(this, true); charmer->ToPlayer()->PossessSpellInitialize(); break; @@ -16724,7 +16636,7 @@ void Unit::GetRaidMember(std::list<Unit*> &nearMembers, float radius) if (owner->isAlive() && (owner == this || IsWithinDistInMap(owner, radius))) nearMembers.push_back(owner); if (Guardian* pet = owner->GetGuardianPet()) - if (pet->isAlive() && (pet == this && IsWithinDistInMap(pet, radius))) + if (pet->isAlive() && (pet == this || IsWithinDistInMap(pet, radius))) nearMembers.push_back(pet); } } @@ -16761,7 +16673,7 @@ void Unit::GetPartyMemberInDist(std::list<Unit*> &TagUnitMap, float radius) if (owner->isAlive() && (owner == this || IsWithinDistInMap(owner, radius))) TagUnitMap.push_back(owner); if (Guardian* pet = owner->GetGuardianPet()) - if (pet->isAlive() && (pet == this && IsWithinDistInMap(pet, radius))) + if (pet->isAlive() && (pet == this || IsWithinDistInMap(pet, radius))) TagUnitMap.push_back(pet); } } @@ -17568,6 +17480,10 @@ void Unit::_ExitVehicle(Position const* exitPosition) m_vehicle->RemovePassenger(this); + // If player is on mouted duel and exits the mount should immediatly lose the duel + if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->duel && ToPlayer()->duel->isMounted) + ToPlayer()->DuelComplete(DUEL_FLED); + // This should be done before dismiss, because there may be some aura removal Vehicle* vehicle = m_vehicle; m_vehicle = NULL; @@ -17599,7 +17515,7 @@ void Unit::_ExitVehicle(Position const* exitPosition) WorldPacket data2; BuildHeartBeatMsg(&data2); - SendMessageToSet(&data2, false); + SendMessageToSet(&data2, true); if (vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION)) if (((Minion*)vehicle->GetBase())->GetOwner() == this) @@ -17729,13 +17645,13 @@ void Unit::SetFlying(bool apply) void Unit::NearTeleportTo(float x, float y, float z, float orientation, bool casting /*= false*/) { + DisableSpline(); if (GetTypeId() == TYPEID_PLAYER) ToPlayer()->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 { - // FIXME: this interrupts spell visual - DestroyForNearbyPlayers(); UpdatePosition(x, y, z, orientation, true); + SendMovementFlagUpdate(); } } @@ -18017,3 +17933,26 @@ bool CharmInfo::IsReturning() { return m_isReturning; } + +void Unit::SetInFront(Unit const* target) +{ + if (!HasUnitState(UNIT_STAT_CANNOT_TURN)) + SetOrientation(GetAngle(target)); +} + +void Unit::SetFacingTo(float ori) +{ + Movement::MoveSplineInit init(*this); + init.SetFacing(ori); + init.Launch(); +} + +void Unit::SetFacingToObject(WorldObject* pObject) +{ + // never face when already moving + if (!IsStopped()) + return; + + // TODO: figure out under what conditions creature will move towards object instead of facing it where it currently is. + SetFacingTo(GetAngle(pObject)); +} diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 21dcb4bf3fe..c50cba080c7 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -465,7 +465,6 @@ enum DeathState CORPSE = 2, DEAD = 3, JUST_ALIVED = 4, - DEAD_FALLING= 5 }; enum UnitState @@ -493,13 +492,22 @@ enum UnitState UNIT_STAT_MOVE = 0x00100000, UNIT_STAT_ROTATING = 0x00200000, UNIT_STAT_EVADE = 0x00400000, + UNIT_STAT_ROAMING_MOVE = 0x00800000, + UNIT_STAT_CONFUSED_MOVE = 0x01000000, + UNIT_STAT_FLEEING_MOVE = 0x02000000, + UNIT_STAT_CHASE_MOVE = 0x04000000, + UNIT_STAT_FOLLOW_MOVE = 0x08000000, UNIT_STAT_UNATTACKABLE = (UNIT_STAT_IN_FLIGHT | UNIT_STAT_ONVEHICLE), - UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE), + //UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE), + // for real move using movegen check and stop (except unstoppable flight) + UNIT_STAT_MOVING = UNIT_STAT_ROAMING_MOVE | UNIT_STAT_CONFUSED_MOVE | UNIT_STAT_FLEEING_MOVE| UNIT_STAT_CHASE_MOVE | UNIT_STAT_FOLLOW_MOVE , UNIT_STAT_CONTROLLED = (UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING), UNIT_STAT_LOST_CONTROL = (UNIT_STAT_CONTROLLED | UNIT_STAT_JUMPING | UNIT_STAT_CHARGING), UNIT_STAT_SIGHTLESS = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_EVADE), UNIT_STAT_CANNOT_AUTOATTACK = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_CASTING), UNIT_STAT_CANNOT_TURN = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_ROTATING), + // stay by different reasons + UNIT_STAT_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED | UNIT_STAT_DISTRACTED, UNIT_STAT_ALL_STATE = 0xffffffff //(UNIT_STAT_STOPPED | UNIT_STAT_MOVING | UNIT_STAT_IN_COMBAT | UNIT_STAT_IN_FLIGHT) }; @@ -719,59 +727,18 @@ enum MovementFlags2 MOVEMENTFLAG2_UNK15 = 0x00004000, MOVEMENTFLAG2_UNK16 = 0x00008000, }; + enum SplineFlags { - SPLINEFLAG_NONE = 0x00000000, - SPLINEFLAG_FORWARD = 0x00000001, - SPLINEFLAG_BACKWARD = 0x00000002, - SPLINEFLAG_STRAFE_LEFT = 0x00000004, - SPLINEFLAG_STRAFE_RIGHT = 0x00000008, - SPLINEFLAG_LEFT = 0x00000010, - SPLINEFLAG_RIGHT = 0x00000020, - SPLINEFLAG_PITCH_UP = 0x00000040, - SPLINEFLAG_PITCH_DOWN = 0x00000080, - SPLINEFLAG_DONE = 0x00000100, - SPLINEFLAG_FALLING = 0x00000200, - SPLINEFLAG_NO_SPLINE = 0x00000400, - SPLINEFLAG_TRAJECTORY = 0x00000800, - SPLINEFLAG_WALKING = 0x00001000, - SPLINEFLAG_FLYING = 0x00002000, - SPLINEFLAG_KNOCKBACK = 0x00004000, - SPLINEFLAG_FINAL_POINT = 0x00008000, - SPLINEFLAG_FINAL_TARGET = 0x00010000, - SPLINEFLAG_FINAL_FACING = 0x00020000, - SPLINEFLAG_CATMULL_ROM = 0x00040000, - SPLINEFLAG_UNKNOWN20 = 0x00080000, - SPLINEFLAG_UNKNOWN21 = 0x00100000, - SPLINEFLAG_ANIMATIONTIER = 0x00200000, - SPLINEFLAG_UNKNOWN23 = 0x00400000, - SPLINEFLAG_TRANSPORT = 0x00800000, - SPLINEFLAG_EXIT_VEHICLE = 0x01000000, - SPLINEFLAG_UNKNOWN26 = 0x02000000, - SPLINEFLAG_UNKNOWN27 = 0x04000000, - SPLINEFLAG_UNKNOWN28 = 0x08000000, - SPLINEFLAG_UNKNOWN29 = 0x10000000, - SPLINEFLAG_ANIMATION = 0x20000000, - SPLINEFLAG_UNKNOWN31 = 0x40000000, - SPLINEFLAG_UNKNOWN32 = 0x80000000, - - SPLINEFLAG_GLIDE = SPLINEFLAG_WALKING | SPLINEFLAG_FLYING, -}; - -enum SplineMode -{ - SPLINEMODE_LINEAR = 0, - SPLINEMODE_CATMULL_ROM = 1, - SPLINEMODE_BEZIER3 = 2 + SPLINEFLAG_WALKMODE = 0x00001000, + SPLINEFLAG_FLYING = 0x00002000, + SPLINEFLAG_TRANSPORT = 0x00800000, + SPLINEFLAG_EXIT_VEHICLE = 0x01000000, }; enum SplineType { - SPLINETYPE_NORMAL = 0, - SPLINETYPE_STOP = 1, - SPLINETYPE_FACING_SPOT = 2, - SPLINETYPE_FACING_TARGET = 3, - SPLINETYPE_FACING_ANGLE = 4 + SPLINETYPE_FACING_ANGLE = 4, }; enum UnitTypeMask @@ -789,6 +756,10 @@ enum UnitTypeMask UNIT_MASK_ACCESSORY = 0x00000200, }; +namespace Movement{ + class MoveSpline; +} + enum DiminishingLevels { DIMINISHING_LEVEL_1 = 0, @@ -1631,20 +1602,18 @@ class Unit : public WorldObject void JumpTo(float speedXY, float speedZ, bool forward = true); void JumpTo(WorldObject* obj, float speedZ); - void SetFacing(float ori, WorldObject* obj = NULL); - void SendMonsterStop(bool on_death = false); - void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player = NULL); - void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 MoveFlags, uint32 time, float speedZ, Player* player = NULL); - void SendMonsterMove(MonsterMoveData const& moveData, Player* receiver = NULL); + void MonsterMoveWithSpeed(float x, float y, float z, float speed); + //void SetFacing(float ori, WorldObject* obj = NULL); void SendMonsterMoveExitVehicle(Position const* newPos); //void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL); void SendMonsterMoveTransport(Unit* vehicleOwner); - void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime = 0, Player* player = NULL); - void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL); void SendMovementFlagUpdate(); + bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_LEVITATING);} + bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);} - template<typename PathElem, typename PathNode> - void SendMonsterMoveByPath(Path<PathElem, PathNode> const& path, uint32 start, uint32 end); + void SetInFront(Unit const* target); + void SetFacingTo(float ori); + void SetFacingToObject(WorldObject* pObject); void SendChangeCurrentVictimOpcode(HostileReference* pHostileReference); void SendClearThreatListOpcode(); @@ -1954,13 +1923,7 @@ class Unit : public WorldObject void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; } bool isInFrontInMap(Unit const* target, float distance, float arc = M_PI) const; - void SetInFront(Unit const* target) - { - if (!HasUnitState(UNIT_STAT_CANNOT_TURN)) - SetOrientation(GetAngle(target)); - } bool isInBackInMap(Unit const* target, float distance, float arc = M_PI) const; - void SetFacingToObject(WorldObject* pObject); // Visibility system bool IsVisible() const { return (m_serverSideVisibility.GetValue(SERVERSIDE_VISIBILITY_GM) > SEC_PLAYER) ? false : true; } @@ -2235,6 +2198,9 @@ class Unit : public WorldObject SetUInt64Value(UNIT_FIELD_TARGET, 0); } + // Movement info + Movement::MoveSpline * movespline; + protected: explicit Unit (bool isWorldObject); @@ -2306,6 +2272,8 @@ class Unit : public WorldObject bool IsAlwaysVisibleFor(WorldObject const* seer) const; bool IsAlwaysDetectableFor(WorldObject const* seer) const; + + void DisableSpline(); private: bool IsTriggeredAtSpellProcEvent(Unit* pVictim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const* & spellProcEvent); bool HandleDummyAuraProc(Unit* pVictim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); @@ -2319,6 +2287,8 @@ class Unit : public WorldObject bool HandleAuraRaidProcFromChargeWithValue(AuraEffect* triggeredByAura); bool HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura); + void UpdateSplineMovement(uint32 t_diff); + // player or player's pet float GetCombatRatingReduction(CombatRating cr) const; uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const; @@ -2333,6 +2303,7 @@ class Unit : public WorldObject uint32 m_state; // Even derived shouldn't modify uint32 m_CombatTimer; uint32 m_lastManaUse; // msecs + TimeTrackerSmall m_movesplineTimer; Diminishing m_Diminishing; // Manage all Units that are threatened by us @@ -2385,31 +2356,4 @@ namespace Trinity const bool m_ascending; }; } - -template<typename Elem, typename Node> -inline void Unit::SendMonsterMoveByPath(Path<Elem, Node> const& path, uint32 start, uint32 end) -{ - uint32 traveltime = uint32(path.GetTotalLength(start, end) * 32); - uint32 pathSize = end - start; - WorldPacket data(SMSG_MONSTER_MOVE, (GetPackGUID().size()+1+4+4+4+4+1+4+4+4+pathSize*4*3)); - data.append(GetPackGUID()); - data << uint8(0); - data << GetPositionX(); - data << GetPositionY(); - data << GetPositionZ(); - data << uint32(getMSTime()); - data << uint8(0); - data << uint32(((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING) || isInFlight()) ? (SPLINEFLAG_FLYING|SPLINEFLAG_WALKING) : SPLINEFLAG_WALKING); - data << uint32(traveltime); - data << uint32(pathSize); - - for (uint32 i = start; i < end; ++i) - { - data << float(path[i].x); - data << float(path[i].y); - data << float(path[i].z); - } - - SendMessageToSet(&data, true); -} #endif |
