mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 22:37:03 +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:
|
case DEAD_FALLING:
|
||||||
{
|
{
|
||||||
if (!FallGround())
|
setDeathState(CORPSE);
|
||||||
setDeathState(JUST_DIED);
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Creature::StartGroupLoot( Group* group, uint32 timer )
|
void Creature::StartGroupLoot( Group* group, uint32 timer )
|
||||||
{
|
{
|
||||||
m_groupLootId = group->GetId();
|
m_groupLootId = group->GetId();
|
||||||
|
|
@ -1379,13 +1377,8 @@ void Creature::setDeathState(DeathState s)
|
||||||
// always save boss respawn time at death to prevent crash cheating
|
// always save boss respawn time at death to prevent crash cheating
|
||||||
if (sWorld.getConfig(CONFIG_BOOL_SAVE_RESPAWN_TIME_IMMEDIATLY) || isWorldBoss())
|
if (sWorld.getConfig(CONFIG_BOOL_SAVE_RESPAWN_TIME_IMMEDIATLY) || isWorldBoss())
|
||||||
SaveRespawnTime();
|
SaveRespawnTime();
|
||||||
|
|
||||||
if (canFly() && FallGround())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!IsStopped())
|
|
||||||
StopMoving();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Unit::setDeathState(s);
|
Unit::setDeathState(s);
|
||||||
|
|
||||||
if (s == JUST_DIED)
|
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)
|
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);
|
SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
||||||
|
|
||||||
if (canFly() && FallGround())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (HasSearchedAssistance())
|
if (HasSearchedAssistance())
|
||||||
{
|
{
|
||||||
SetNoSearchAssistance(false);
|
SetNoSearchAssistance(false);
|
||||||
UpdateSpeed(MOVE_RUN, 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);
|
Unit::setDeathState(CORPSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s == JUST_ALIVED)
|
if (s == JUST_ALIVED)
|
||||||
{
|
{
|
||||||
SetHealth(GetMaxHealth());
|
SetHealth(GetMaxHealth());
|
||||||
|
|
@ -1423,20 +1418,44 @@ void Creature::setDeathState(DeathState s)
|
||||||
|
|
||||||
bool Creature::FallGround()
|
bool Creature::FallGround()
|
||||||
{
|
{
|
||||||
// Let's abort after we called this function one time
|
// Only if state is JUST_DIED. DEAD_FALLING is set below and promoted to CORPSE later
|
||||||
if (getDeathState() == DEAD_FALLING)
|
if (getDeathState() != JUST_DIED)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// use larger distance for vmap height search than in most other cases
|
// use larger distance for vmap height search than in most other cases
|
||||||
float tz = GetMap()->GetHeight(GetPositionX(), GetPositionY(), GetPositionZ(), true, MAX_FALL_DISTANCE);
|
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
|
// Abort too if the ground is very near
|
||||||
if (fabs(GetPositionZ() - tz) < 0.1f)
|
if (fabs(GetPositionZ() - tz) < 0.1f)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Unit::setDeathState(DEAD_FALLING);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1063,15 +1063,8 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps, float maxSearchD
|
||||||
else
|
else
|
||||||
return vmapHeight; // we have only vmapHeight (if have)
|
return vmapHeight; // we have only vmapHeight (if have)
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return mapHeight;
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsOutdoorWMO(uint32 mogpFlags, int32 adtId, int32 rootId, int32 groupId,
|
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 )
|
if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
|
||||||
return;
|
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);
|
Traveller<T> traveller(owner);
|
||||||
i_destinationHolder.SetDestination(traveller, x, y, z);
|
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 dx = x - GetPositionX();
|
||||||
float dy = y - GetPositionY();
|
float dy = y - GetPositionY();
|
||||||
|
|
||||||
if(i_traveller.hasUnitState(UNIT_STAT_TAXI_FLIGHT))
|
if (i_traveller.canFly())
|
||||||
{
|
{
|
||||||
float dz = z - GetPositionZ();
|
float dz = z - GetPositionZ();
|
||||||
return sqrt((dx*dx) + (dy*dy) + (dz*dz));
|
return sqrt((dx*dx) + (dy*dy) + (dz*dz));
|
||||||
|
|
|
||||||
|
|
@ -8217,7 +8217,18 @@ void Unit::setDeathState(DeathState s)
|
||||||
|
|
||||||
// after removing a Fearaura (in RemoveAllAurasOnDeath)
|
// after removing a Fearaura (in RemoveAllAurasOnDeath)
|
||||||
// Unit::SetFeared is called and makes that creatures attack player again
|
// 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_20_PERCENT, false);
|
||||||
ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false);
|
ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "10430"
|
#define REVISION_NR "10431"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue