fix(Core/Movement): fix multiple creature movement issues (#5097)

This commit is contained in:
Footman
2021-04-09 21:56:19 +03:00
committed by GitHub
parent 91a39f27d9
commit c32cd06a78
22 changed files with 7181 additions and 93 deletions

View File

@@ -1703,8 +1703,8 @@ void Creature::setDeathState(DeathState s, bool despawn)
m_formation->FormationReset(true);
bool needsFalling = !despawn && (IsFlying() || IsHovering()) && !IsUnderWater();
SetHover(false, false);
SetDisableGravity(false, false);
SetHover(false);
SetDisableGravity(false);
if (needsFalling)
GetMotionMaster()->MoveFall(0, true);
@@ -1726,7 +1726,6 @@ void Creature::setDeathState(DeathState s, bool despawn)
// pussywizard:
if (HasUnitMovementFlag(MOVEMENTFLAG_FALLING))
RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING);
UpdateEnvironmentIfNeeded(3);
SetUInt32Value(UNIT_NPC_FLAGS, cinfo->npcflag);
ClearUnitState(uint32(UNIT_STATE_ALL_STATE & ~(UNIT_STATE_IGNORE_PATHFINDING | UNIT_STATE_NO_ENVIRONMENT_UPD)));
@@ -1734,11 +1733,12 @@ void Creature::setDeathState(DeathState s, bool despawn)
Unit::setDeathState(ALIVE, despawn);
// Xinef: Load auras AFTER setting alive state
LoadCreaturesAddon(true);
Motion_Initialize();
LoadCreaturesAddon(true);
if (GetCreatureData() && GetPhaseMask() != GetCreatureData()->phaseMask)
SetPhaseMask(GetCreatureData()->phaseMask, false);
UpdateEnvironmentIfNeeded(3);
}
}
@@ -3013,7 +3013,7 @@ void Creature::SetObjectScale(float scale)
if (IsPet())
combatReach = DEFAULT_COMBAT_REACH;
SetFloatValue(UNIT_FIELD_COMBATREACH, combatReach * GetFloatValue(OBJECT_FIELD_SCALE_X) * scale);
SetFloatValue(UNIT_FIELD_COMBATREACH, combatReach * scale);
}
void Creature::SetDisplayId(uint32 modelId)

View File

@@ -3671,7 +3671,7 @@ void Unit::UpdateEnvironmentIfNeeded(const uint8 option)
float radiusWidth = GetCollisionRadius();
float radiusHeight = GetCollisionHeight() / 2;
float radiusAvg = (radiusWidth + radiusHeight) / 2;
if (option <= 1 && GetExactDistSq(&m_last_environment_position) < radiusAvg*radiusAvg)
if (option <= 1 && GetExactDistSq(&m_last_environment_position) < radiusAvg * radiusAvg)
return;
m_last_environment_position.Relocate(GetPositionX(), GetPositionY(), GetPositionZ());
@@ -3687,7 +3687,8 @@ void Unit::UpdateEnvironmentIfNeeded(const uint8 option)
m_is_updating_environment = false;
return;
}
bool canChangeFlying = option == 3 || GetMotionMaster()->GetCurrentMovementGeneratorType() != WAYPOINT_MOTION_TYPE;
bool canChangeFlying = option == 3 || ((c->GetScriptId() == 0 || GetInstanceId() == 0) && GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE);
bool canFallGround = option == 0 && canChangeFlying && GetInstanceId() == 0 && !IsInCombat() && !GetVehicle() && !GetTransport() && !HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && !c->IsTrigger() && !c->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE) && GetMotionMaster()->GetCurrentMovementGeneratorType() <= RANDOM_MOTION_TYPE && !HasUnitState(UNIT_STATE_EVADE) && !IsControlledByPlayer();
float x = GetPositionX(), y = GetPositionY(), z = GetPositionZ();
bool isInAir = true;
@@ -3747,16 +3748,17 @@ void Unit::UpdateEnvironmentIfNeeded(const uint8 option)
}
}
bool canUpdateEnvironment = !HasUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD);
bool flyingBarelyInWater = false;
// Refresh being in water
if (m_last_isinwater_status)
{
if (!c->CanFly() || enoughWater)
{
if (!HasUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD) && c->CanSwim() && (!HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING) || !HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY)))
if (canUpdateEnvironment && c->CanSwim() && (!HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING) || !HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY)))
{
SetSwim(true);
// SetDisableGravity(true);
changed = true;
}
isInAir = false;
@@ -3770,11 +3772,9 @@ void Unit::UpdateEnvironmentIfNeeded(const uint8 option)
if (!m_last_isinwater_status)
{
if (!HasUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD) && c->CanWalk() && HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING))
if (canUpdateEnvironment && c->CanWalk() && HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING))
{
SetSwim(false);
if (!c->CanFly()) // if can fly, this will be removed below if needed
SetDisableGravity(false);
changed = true;
}
}
@@ -3801,7 +3801,7 @@ void Unit::UpdateEnvironmentIfNeeded(const uint8 option)
}
}
if (!HasUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD) && canChangeFlying)
if (canUpdateEnvironment && canChangeFlying)
{
// xinef: summoned vehicles are treated as always in air, fixes flying on such units
if (IsVehicle() && !c->GetDBTableGUIDLow())
@@ -3822,7 +3822,6 @@ void Unit::UpdateEnvironmentIfNeeded(const uint8 option)
}
else if (c->CanFly() && isInAir && !c->IsFalling())
{
if (!HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY) || !HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY))
{
SetCanFly(true);
@@ -3835,7 +3834,6 @@ void Unit::UpdateEnvironmentIfNeeded(const uint8 option)
SetHover(false);
changed = true;
}
}
else
{
@@ -3869,7 +3867,7 @@ void Unit::UpdateEnvironmentIfNeeded(const uint8 option)
if (changed)
propagateSpeedChange();
if (!HasUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD) && canFallGround && !c->CanFly() && !c->IsFalling() && !m_last_isinwater_status && (c->GetUnitMovementFlags() & (MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_HOVER | MOVEMENTFLAG_SWIMMING)) == 0 && z - ground_z > 5.0f && z - ground_z < 80.0f)
if (canUpdateEnvironment && canFallGround && !c->CanFly() && !c->IsFalling() && !m_last_isinwater_status && (c->GetUnitMovementFlags() & (MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_HOVER | MOVEMENTFLAG_SWIMMING)) == 0 && z - ground_z > 5.0f && z - ground_z < 80.0f)
GetMotionMaster()->MoveFall();
m_is_updating_environment = false;
@@ -20197,7 +20195,7 @@ float Unit::GetCollisionRadius() const
float Unit::GetCollisionHeight() const
{
float scaleMod = GetObjectScale(); // 99% sure about this
float defaultHeight = DEFAULT_WORLD_OBJECT_SIZE * scaleMod;
float defaultHeight = DEFAULT_COLLISION_HEIGHT * scaleMod;
CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.AssertEntry(GetNativeDisplayId());
CreatureModelDataEntry const* modelData = sCreatureModelDataStore.AssertEntry(displayInfo->ModelId);

View File

@@ -48,7 +48,6 @@ bool ChaseMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
// the owner might be unable to move (rooted or casting), or we have lost the target, pause movement
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || HasLostTarget(owner) || (cOwner && cOwner->IsMovementPreventedByCasting()))
{
i_path = nullptr;
owner->StopMoving();
_lastTargetPosition.reset();
if (Creature* cOwner = owner->ToCreature())
@@ -234,7 +233,7 @@ bool FollowMovementGenerator<T>::PositionOkay(T* owner, Unit* target, float rang
if (owner->GetExactDistSq(target) > G3D::square(owner->GetCombatReach() + target->GetCombatReach() + range))
return false;
return !owner->IsPet() || !angle || angle->IsAngleOkay(target->GetRelativeAngle(owner)); // need to check - dont think we need !pet exception here because there are scripts with MoveFollow that require angle
return !angle || angle->IsAngleOkay(target->GetRelativeAngle(owner));
}
template<class T>

View File

@@ -2449,12 +2449,10 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
TempSummonType summonType = (duration <= 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
uint32 currMinionsCount = m_caster->m_Controlled.size();
uint32 totalNumGuardians = numSummons + currMinionsCount;
for (uint32 count = 0; count < numSummons; ++count)
{
Position pos;
if (totalNumGuardians == 1)
if (count == 0)
pos = *destTarget;
else
// randomize position for multiple summons
@@ -5069,7 +5067,7 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
m_caster->GetFirstCollisionPosition(pos, dist, angle);
}
m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ);
m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ + Z_OFFSET_FIND_HEIGHT);
}
}