diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index c63a58b07..d2ef20ae8 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -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; } diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 19c8424b3..626974f3f 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -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, diff --git a/src/game/TargetedMovementGenerator.cpp b/src/game/TargetedMovementGenerator.cpp index fb5607ad3..29877ac07 100644 --- a/src/game/TargetedMovementGenerator.cpp +++ b/src/game/TargetedMovementGenerator.cpp @@ -74,6 +74,12 @@ void TargetedMovementGeneratorMedium::_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 traveller(owner); i_destinationHolder.SetDestination(traveller, x, y, z); diff --git a/src/game/Traveller.h b/src/game/Traveller.h index a88e29b20..36f3d538c 100644 --- a/src/game/Traveller.h +++ b/src/game/Traveller.h @@ -92,7 +92,7 @@ inline float Traveller::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)); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index f8461c117..7705d4858 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -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); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index d20704b2e..8490af799 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "10430" + #define REVISION_NR "10431" #endif // __REVISION_NR_H__