mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 13:37:05 +00:00
[10431] Correcting issues with flying creatures falling to ground at death.
Simplified the way FallGround works and death states are set in a more logical way when a mob is in fact DEAD_FALLING. Visual will in some cases not be correct. Notes in code for details. Thanks to Lynx fixing Map::GetHeight It now return mapHeight as last resort, making FallGround work as expected. This fix reveal one (known) bug, and therefore a temp hack is added in TargetedMovegen, to be sure Z is not the ground Z for a creature that are able to fly. Other creatures will follow by the ground level Z (in other words, they will no longer follow in the air).
This commit is contained in:
parent
7df3f06d87
commit
32e3e252fb
6 changed files with 57 additions and 28 deletions
|
|
@ -561,15 +561,13 @@ void Creature::Update(uint32 diff)
|
|||
}
|
||||
case DEAD_FALLING:
|
||||
{
|
||||
if (!FallGround())
|
||||
setDeathState(JUST_DIED);
|
||||
setDeathState(CORPSE);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Creature::StartGroupLoot( Group* group, uint32 timer )
|
||||
{
|
||||
m_groupLootId = group->GetId();
|
||||
|
|
@ -1379,13 +1377,8 @@ void Creature::setDeathState(DeathState s)
|
|||
// always save boss respawn time at death to prevent crash cheating
|
||||
if (sWorld.getConfig(CONFIG_BOOL_SAVE_RESPAWN_TIME_IMMEDIATLY) || isWorldBoss())
|
||||
SaveRespawnTime();
|
||||
|
||||
if (canFly() && FallGround())
|
||||
return;
|
||||
|
||||
if (!IsStopped())
|
||||
StopMoving();
|
||||
}
|
||||
|
||||
Unit::setDeathState(s);
|
||||
|
||||
if (s == JUST_DIED)
|
||||
|
|
@ -1393,17 +1386,19 @@ void Creature::setDeathState(DeathState s)
|
|||
SetTargetGUID(0); // remove target selection in any cases (can be set at aura remove in Unit::setDeathState)
|
||||
SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
||||
|
||||
if (canFly() && FallGround())
|
||||
return;
|
||||
|
||||
if (HasSearchedAssistance())
|
||||
{
|
||||
SetNoSearchAssistance(false);
|
||||
UpdateSpeed(MOVE_RUN, false);
|
||||
}
|
||||
|
||||
// return, since we promote to DEAD_FALLING. DEAD_FALLING is promoted to CORPSE at next update.
|
||||
if (canFly() && FallGround())
|
||||
return;
|
||||
|
||||
Unit::setDeathState(CORPSE);
|
||||
}
|
||||
|
||||
if (s == JUST_ALIVED)
|
||||
{
|
||||
SetHealth(GetMaxHealth());
|
||||
|
|
@ -1423,20 +1418,44 @@ void Creature::setDeathState(DeathState s)
|
|||
|
||||
bool Creature::FallGround()
|
||||
{
|
||||
// Let's abort after we called this function one time
|
||||
if (getDeathState() == DEAD_FALLING)
|
||||
// Only if state is JUST_DIED. DEAD_FALLING is set below and promoted to CORPSE later
|
||||
if (getDeathState() != JUST_DIED)
|
||||
return false;
|
||||
|
||||
// use larger distance for vmap height search than in most other cases
|
||||
float tz = GetMap()->GetHeight(GetPositionX(), GetPositionY(), GetPositionZ(), true, MAX_FALL_DISTANCE);
|
||||
|
||||
if (tz < INVALID_HEIGHT)
|
||||
{
|
||||
DEBUG_LOG("FallGround: creature %u at map %u (x: %f, y: %f, z: %f), not able to retrive a proper GetHeight (z: %f).",
|
||||
GetEntry(), GetMap()->GetId(), GetPositionX(), GetPositionX(), GetPositionZ(), tz);
|
||||
}
|
||||
|
||||
// Abort too if the ground is very near
|
||||
if (fabs(GetPositionZ() - tz) < 0.1f)
|
||||
return false;
|
||||
|
||||
Unit::setDeathState(DEAD_FALLING);
|
||||
GetMotionMaster()->MovePoint(0, GetPositionX(), GetPositionY(), tz);
|
||||
Relocate(GetPositionX(), GetPositionY(), tz);
|
||||
|
||||
float dz = tz - GetPositionZ();
|
||||
float distance = sqrt(dz*dz);
|
||||
|
||||
// flight speed * 2 explicit, not verified though but result looks proper
|
||||
double speed = GetSpeed(MOVE_FLIGHT) * 2;
|
||||
|
||||
speed *= 0.001; // to milliseconds
|
||||
|
||||
uint32 travelTime = uint32(distance/speed);
|
||||
|
||||
DEBUG_LOG("FallGround: traveltime: %u, distance: %f, speed: %f, from %f to %f", travelTime, distance, speed, GetPositionZ(), tz);
|
||||
|
||||
// For creatures that are moving towards target and dies, the visual effect is not nice.
|
||||
// It is possibly caused by a xyz mismatch in DestinationHolder's GetLocationNow and the location
|
||||
// of the mob in client. For mob that are already reached target or dies while not moving
|
||||
// the visual appear to be fairly close to the expected.
|
||||
|
||||
GetMap()->CreatureRelocation(this, GetPositionX(), GetPositionY(), tz, GetOrientation());
|
||||
SendMonsterMove(GetPositionX(), GetPositionY(), tz, SPLINETYPE_NORMAL, SPLINEFLAG_FALLING, travelTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1063,15 +1063,8 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps, float maxSearchD
|
|||
else
|
||||
return vmapHeight; // we have only vmapHeight (if have)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!pUseVmaps)
|
||||
return mapHeight; // explicitly use map data (if have)
|
||||
else if(mapHeight > INVALID_HEIGHT && (z < mapHeight + 2 || z == MAX_HEIGHT))
|
||||
return mapHeight; // explicitly use map data if original z < mapHeight but map found (z+2 > mapHeight)
|
||||
else
|
||||
return VMAP_INVALID_HEIGHT_VALUE; // we not have any height
|
||||
}
|
||||
|
||||
return mapHeight;
|
||||
}
|
||||
|
||||
inline bool IsOutdoorWMO(uint32 mogpFlags, int32 adtId, int32 rootId, int32 groupId,
|
||||
|
|
|
|||
|
|
@ -74,6 +74,12 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner)
|
|||
if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
|
||||
return;
|
||||
*/
|
||||
|
||||
// Just a temp hack, GetContactPoint/GetClosePoint in above code use UpdateGroundPositionZ (in GetNearPoint)
|
||||
// and then has the wrong z to use when creature try follow unit in the air.
|
||||
if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly())
|
||||
z = i_target->GetPositionZ();
|
||||
|
||||
Traveller<T> traveller(owner);
|
||||
i_destinationHolder.SetDestination(traveller, x, y, z);
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ inline float Traveller<Creature>::GetMoveDestinationTo(float x, float y, float z
|
|||
float dx = x - GetPositionX();
|
||||
float dy = y - GetPositionY();
|
||||
|
||||
if(i_traveller.hasUnitState(UNIT_STAT_TAXI_FLIGHT))
|
||||
if (i_traveller.canFly())
|
||||
{
|
||||
float dz = z - GetPositionZ();
|
||||
return sqrt((dx*dx) + (dy*dy) + (dz*dz));
|
||||
|
|
|
|||
|
|
@ -8217,7 +8217,18 @@ void Unit::setDeathState(DeathState s)
|
|||
|
||||
// after removing a Fearaura (in RemoveAllAurasOnDeath)
|
||||
// Unit::SetFeared is called and makes that creatures attack player again
|
||||
StopMoving();
|
||||
if (GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
clearUnitState(UNIT_STAT_MOVING);
|
||||
|
||||
GetMap()->CreatureRelocation((Creature*)this, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
|
||||
SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(), SPLINETYPE_NORMAL, SPLINEFLAG_WALKMODE, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsStopped())
|
||||
StopMoving();
|
||||
}
|
||||
|
||||
ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false);
|
||||
ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "10430"
|
||||
#define REVISION_NR "10431"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue