Core/Movement:

- Don't abort relocation if movementflag restrictions were violated. There might be lag between client and server and even different parts of the core that made this approach improper.
- MOVEMENTFLAG_ROOT cannot be used in conjunction with MOVEMENTFLAG_MASK_MOVING, but it's a valid flag to receive from client.
- Fix falling to ground when unapplying fly/waterwalk aura. NOTE: This is a client-side initiated fall, in the future this should be initiated and updated by the server. (Working on it)
- Rename MOVEMENTFLAG_FALLING to MOVEMENTFLAG_FALLING_FAR
- Rename MOVEMENTFLAG_JUMPING to MOVEMENTFLAG_FALLING

Closes #5751
This commit is contained in:
Machiavelli
2012-03-17 20:36:12 +01:00
parent 01f3620d45
commit 41cc704bf8
13 changed files with 94 additions and 110 deletions
+1 -1
View File
@@ -1186,7 +1186,7 @@ void MovementInfo::OutDebug()
sLog->outString("pitch: %f", pitch);
sLog->outString("fallTime: %u", fallTime);
if (flags & MOVEMENTFLAG_JUMPING)
if (flags & MOVEMENTFLAG_FALLING)
sLog->outString("j_zspeed: %f j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f", j_zspeed, j_sinAngle, j_cosAngle, j_xyspeed);
if (flags & MOVEMENTFLAG_SPLINE_ELEVATION)
+2 -4
View File
@@ -482,9 +482,6 @@ struct MovementInfo
// spline
float splineElevation;
//! Server side only:
bool Violated;
MovementInfo()
{
pos.Relocate(0, 0, 0, 0);
@@ -497,7 +494,6 @@ struct MovementInfo
t_guid = 0;
t_pos.Relocate(0, 0, 0, 0);
t_seat = -1;
Violated = false;
}
uint32 GetMovementFlags() { return flags; }
@@ -510,6 +506,8 @@ struct MovementInfo
void AddExtraMovementFlag(uint16 flag) { flags2 |= flag; }
bool HasExtraMovementFlag(uint16 flag) const { return flags2 & flag; }
void SetFallTime(uint32 time) { fallTime = time; }
void OutDebug();
};
+1 -1
View File
@@ -17117,7 +17117,7 @@ void Unit::BuildMovementPacket(ByteBuffer *data) const
*data << (uint32)m_movementInfo.fallTime;
// 0x00001000
if (GetUnitMovementFlags() & MOVEMENTFLAG_JUMPING)
if (GetUnitMovementFlags() & MOVEMENTFLAG_FALLING)
{
*data << (float)m_movementInfo.j_zspeed;
*data << (float)m_movementInfo.j_sinAngle;
+3 -3
View File
@@ -678,8 +678,8 @@ enum MovementFlags
MOVEMENTFLAG_ONTRANSPORT = 0x00000200, // Used for flying on some creatures
MOVEMENTFLAG_DISABLE_GRAVITY = 0x00000400, // Former MOVEMENTFLAG_LEVITATING. This is used when walking is not possible.
MOVEMENTFLAG_ROOT = 0x00000800, // Must not be set along with MOVEMENTFLAG_MASK_MOVING
MOVEMENTFLAG_JUMPING = 0x00001000,
MOVEMENTFLAG_FALLING = 0x00002000, // damage dealt on that type of falling
MOVEMENTFLAG_FALLING = 0x00001000, // damage dealt on that type of falling
MOVEMENTFLAG_FALLING_FAR = 0x00002000,
MOVEMENTFLAG_PENDING_STOP = 0x00004000,
MOVEMENTFLAG_PENDING_STRAFE_STOP = 0x00008000,
MOVEMENTFLAG_PENDING_FORWARD = 0x00010000,
@@ -701,7 +701,7 @@ enum MovementFlags
// TODO: Check if PITCH_UP and PITCH_DOWN really belong here..
MOVEMENTFLAG_MASK_MOVING =
MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD | MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT |
MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN | MOVEMENTFLAG_JUMPING | MOVEMENTFLAG_FALLING | MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING |
MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN | MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING | MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING |
MOVEMENTFLAG_SPLINE_ELEVATION,
MOVEMENTFLAG_MASK_TURNING =
+1 -7
View File
@@ -374,7 +374,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket & /*recv_data*/)
if (GetPlayer()->isInCombat())
reason = 1;
else if (GetPlayer()->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_JUMPING | MOVEMENTFLAG_FALLING))
else if (GetPlayer()->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR))
reason = 3; // is jumping or falling
else if (GetPlayer()->duel || GetPlayer()->HasAura(9454)) // is dueling or frozen by GM via freeze command
reason = 2; // FIXME - Need the correct value
@@ -1621,12 +1621,6 @@ void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket & recv_data)
recv_data.read_skip<float>(); // unk2
if (movementInfo.Violated)
{
recv_data.rfinish();
return;
}
_player->m_mover->m_movementInfo.flags = movementInfo.GetMovementFlags();
}
@@ -278,14 +278,6 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data)
return;
}
//! If some anti-cheat checks in WorldSession::ReadMovementInfo failed, do not process
//! the change of movement server-sided.
if (movementInfo.Violated)
{
recv_data.rfinish();
return;
}
/* handle special cases */
if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT)
{
@@ -495,12 +487,6 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data)
MovementInfo mi;
ReadMovementInfo(recv_data, &mi);
if (mi.Violated)
{
recv_data.rfinish();
return;
}
mi.guid = old_mover_guid;
_player->m_movementInfo = mi;
@@ -529,12 +515,6 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket & recv_data)
MovementInfo movementInfo;
ReadMovementInfo(recv_data, &movementInfo);
if (movementInfo.Violated)
{
recv_data.rfinish();
return;
}
_player->m_movementInfo = movementInfo;
WorldPacket data(MSG_MOVE_KNOCK_BACK, 66);
@@ -43,12 +43,6 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
mi.guid = guid;
ReadMovementInfo(recv_data, &mi);
if (mi.Violated)
{
recv_data.rfinish();
return;
}
_player->m_movementInfo = mi;
_player->ExitVehicle();
@@ -89,13 +83,6 @@ void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data)
MovementInfo movementInfo;
ReadMovementInfo(recv_data, &movementInfo);
if (movementInfo.Violated)
{
recv_data.rfinish();
return;
}
vehicle_base->m_movementInfo = movementInfo;
uint64 accessory; // accessory guid
+59 -52
View File
@@ -796,7 +796,7 @@ void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo* mi)
data >> mi->fallTime;
if (mi->HasMovementFlag(MOVEMENTFLAG_JUMPING))
if (mi->HasMovementFlag(MOVEMENTFLAG_FALLING))
{
data >> mi->j_zspeed;
data >> mi->j_sinAngle;
@@ -808,56 +808,63 @@ void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo* mi)
data >> mi->splineElevation;
//! Anti-cheat checks. Please keep them in seperate if() blocks to maintain a clear overview.
#define VIOLATE_AND_RETURN \
//! Might be subject to latency, so just remove improper flags.
#ifdef TRINITY_DEBUG
#define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
{ \
sLog->outDebug(LOG_FILTER_UNITS, "WorldSession::ReadMovementInfo: Violation of MovementFlags found. " \
"MovementFlags: %u, MovementFlags2: %u for player GUID: %u. Player will not be relocated.", \
mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetPlayer()->GetGUIDLow()); \
mi->Violated = true; \
return; \
} \
/*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid,
and when used in conjunction with any of the moving movement flags such as MOVEMENTFLAG_FORWARD
it will freeze clients that receive this player's movement info.
if (check) \
{ \
sLog->outDebug(LOG_FILTER_UNITS, "WorldSession::ReadMovementInfo: Violation of MovementFlags found (%s). " \
"MovementFlags: %u, MovementFlags2: %u for player GUID: %u. Mask %u will be removed.", \
STRINGIZE(check), mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetPlayer()->GetGUIDLow(), maskToRemove); \
mi->RemoveMovementFlag((maskToRemove)); \
} \
}
#else
#define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
if (check) \
mi->RemoveMovementFlag((maskToRemove));
#endif
/*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid
in conjunction with any of the moving movement flags such as MOVEMENTFLAG_FORWARD.
It will freeze clients that receive this player's movement info.
*/
if (mi->HasMovementFlag(MOVEMENTFLAG_ROOT))
VIOLATE_AND_RETURN;
//! Cannot hover and jump at the same time
if (mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && mi->HasMovementFlag(MOVEMENTFLAG_JUMPING))
VIOLATE_AND_RETURN;
//! Cannot ascend and descend at the same time
if (mi->HasMovementFlag(MOVEMENTFLAG_ASCENDING) && mi->HasMovementFlag(MOVEMENTFLAG_DESCENDING))
VIOLATE_AND_RETURN;
//! Cannot move left and right at the same time
if (mi->HasMovementFlag(MOVEMENTFLAG_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_RIGHT))
VIOLATE_AND_RETURN;
//! Cannot strafe left and right at the same time
if (mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_RIGHT))
VIOLATE_AND_RETURN;
//! Cannot pitch up and down at the same time
if (mi->HasMovementFlag(MOVEMENTFLAG_PITCH_UP) && mi->HasMovementFlag(MOVEMENTFLAG_PITCH_DOWN))
VIOLATE_AND_RETURN;
//! Cannot move forwards and backwards at the same time
if (mi->HasMovementFlag(MOVEMENTFLAG_FORWARD) && mi->HasMovementFlag(MOVEMENTFLAG_BACKWARD))
VIOLATE_AND_RETURN;
//! Cannot walk on water without SPELL_AURA_WATER_WALK
if (mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && !GetPlayer()->HasAuraType(SPELL_AURA_WATER_WALK))
VIOLATE_AND_RETURN;
//! Cannot feather fall without SPELL_AURA_FEATHER_FALL
if (mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !GetPlayer()->HasAuraType(SPELL_AURA_FEATHER_FALL))
VIOLATE_AND_RETURN;
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT) && mi->HasMovementFlag(MOVEMENTFLAG_MASK_MOVING),
MOVEMENTFLAG_MASK_MOVING);
//! Cannot hover without SPELL_AURA_HOVER
if (mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !GetPlayer()->HasAuraType(SPELL_AURA_HOVER))
VIOLATE_AND_RETURN;
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !GetPlayer()->HasAuraType(SPELL_AURA_HOVER),
MOVEMENTFLAG_HOVER);
//! Cannot ascend and descend at the same time
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ASCENDING) && mi->HasMovementFlag(MOVEMENTFLAG_DESCENDING),
MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING);
//! Cannot move left and right at the same time
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_RIGHT),
MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT);
//! Cannot strafe left and right at the same time
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_RIGHT),
MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT);
//! Cannot pitch up and down at the same time
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_PITCH_UP) && mi->HasMovementFlag(MOVEMENTFLAG_PITCH_DOWN),
MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN);
//! Cannot move forwards and backwards at the same time
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FORWARD) && mi->HasMovementFlag(MOVEMENTFLAG_BACKWARD),
MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD);
//! Cannot walk on water without SPELL_AURA_WATER_WALK
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && !GetPlayer()->HasAuraType(SPELL_AURA_WATER_WALK),
MOVEMENTFLAG_WATERWALKING);
//! Cannot feather fall without SPELL_AURA_FEATHER_FALL
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !GetPlayer()->HasAuraType(SPELL_AURA_FEATHER_FALL),
MOVEMENTFLAG_FALLING_SLOW);
/*! Cannot fly if no fly auras present. Exception is being a GM.
Note that we check for account level instead of Player::IsGameMaster() because in some
@@ -865,12 +872,12 @@ void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo* mi)
e.g. aerial combat.
*/
if (mi->HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY) && GetSecurity() == SEC_PLAYER &&
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY) && GetSecurity() == SEC_PLAYER &&
!GetPlayer()->m_mover->HasAuraType(SPELL_AURA_FLY) &&
!GetPlayer()->m_mover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED))
VIOLATE_AND_RETURN;
!GetPlayer()->m_mover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED),
MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY);
#undef VIOLATE_AND_RETURN
#undef REMOVE_VIOLATING_FLAGS
}
void WorldSession::WriteMovementInfo(WorldPacket* data, MovementInfo* mi)
@@ -899,7 +906,7 @@ void WorldSession::WriteMovementInfo(WorldPacket* data, MovementInfo* mi)
*data << mi->fallTime;
if (mi->HasMovementFlag(MOVEMENTFLAG_JUMPING))
if (mi->HasMovementFlag(MOVEMENTFLAG_FALLING))
{
*data << mi->j_zspeed;
*data << mi->j_sinAngle;
@@ -2855,13 +2855,21 @@ void AuraEffect::HandleAuraAllowFlight(AuraApplication const* aurApp, uint8 mode
//! Not entirely sure if this should be sent for creatures as well, but I don't think so.
target->SetCanFly(apply);
if (!apply)
{
target->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING);
target->AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
target->m_movementInfo.SetFallTime(0);
}
Player* player = target->ToPlayer();
if (!player)
player = target->m_movedPlayer;
if (player)
player->SendMovementCanFlyChange();
//! We still need to initiate a server-side MoveFall here,
//! which requires MSG_MOVE_FALL_LAND on landing.
}
void AuraEffect::HandleAuraWaterWalk(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -2880,11 +2888,13 @@ void AuraEffect::HandleAuraWaterWalk(AuraApplication const* aurApp, uint8 mode,
if (apply)
target->AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
else
else
{
target->RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING);
target->AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
}
target->SendMovementWaterWalking();
}
void AuraEffect::HandleAuraFeatherFall(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3242,13 +3252,21 @@ void AuraEffect::HandleAuraModIncreaseFlightSpeed(AuraApplication const* aurApp,
{
target->SetCanFly(apply);
if (!apply)
{
target->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING);
target->AddUnitMovementFlag(MOVEMENTFLAG_FALLING);
target->m_movementInfo.SetFallTime(0);
}
Player* player = target->ToPlayer();
if (!player)
player = target->m_movedPlayer;
if (player)
player->SendMovementCanFlyChange();
//! We still need to initiate a server-side MoveFall here,
//! which requires MSG_MOVE_FALL_LAND on landing.
}
//! Someone should clean up these hacks and remove it from this function. It doesn't even belong here.
+2 -2
View File
@@ -3505,7 +3505,7 @@ void Spell::update(uint32 difftime)
// check if the player caster has moved before the spell finished
if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) &&
m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) &&
(m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING)))
(m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)))
{
// don't cancel for melee, autorepeat, triggered and instant spells
if (!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered())
@@ -4756,7 +4756,7 @@ SpellCastResult Spell::CheckCast(bool strict)
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->isMoving())
{
// skip stuck spell to allow use it in falling case and apply spell limitations at movement
if ((!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING) || m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK) &&
if ((!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK) &&
(IsAutoRepeat() || (m_spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) != 0))
return SPELL_FAILED_MOVING;
}