commit 3692884db1a49fc5fb3d316b890994f52db945c8Author: unknown <Ololo@.(none)>
Date: Tue Jun 2 02:00:00 2009 +0300
blink
diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp
index 1638c9c..2fcd7b0 100644
--- a/src/game/MovementHandler.cpp
+++ b/src/game/MovementHandler.cpp
@@ -295,8 +295,9 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
if(plMover) // nothing is charmed, or player charmed
{
- plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
plMover->m_movementInfo = movementInfo;
+ plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
+
plMover->UpdateFallInformationIfNeed(movementInfo, recv_data.GetOpcode());
if(plMover->isMovingOrTurning())
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index eabe7db..b11d1b0 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -5613,6 +5613,13 @@ bool Player::SetPosition(float x, float y, float z, float orientation, bool tele
y = GetPositionY();
z = GetPositionZ();
+ if(teleport || !(m_movementInfo.flags & (MOVEMENTFLAG_FALLING | MOVEMENTFLAG_JUMPING)))
+ {
+ m_safeposition.x = x;
+ m_safeposition.y = y;
+ m_safeposition.z = z;
+ }
+
// group update
if(GetGroup() && (old_x != x || old_y != y))
SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION);
diff --git a/src/game/Player.h b/src/game/Player.h
index b1711b2..3a91d81 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -783,6 +783,16 @@ struct MovementInfo
void SetMovementFlags(MovementFlags f) { flags = f; }
};
+ //here stored last safe player's position
+struct SafePosition
+{
+ float x, y, z;
+ SafePosition()
+ {
+ x = y = z = 0.0f;
+ }
+};
+
// flags that use in movement check for example at spell casting
MovementFlags const movementFlagsMask = MovementFlags(
MOVEMENTFLAG_FORWARD |MOVEMENTFLAG_BACKWARD |MOVEMENTFLAG_STRAFE_LEFT|MOVEMENTFLAG_STRAFE_RIGHT|
@@ -2008,7 +2018,9 @@ class MANGOS_DLL_SPEC Player : public Unit
/*** VARIOUS SYSTEMS ***/
/*********************************************************/
MovementInfo m_movementInfo;
+ SafePosition m_safeposition;
bool HasMovementFlag(MovementFlags f) const; // for script access to m_movementInfo.HasMovementFlag
+
void UpdateFallInformationIfNeed(MovementInfo const& minfo,uint16 opcode);
Unit *m_mover;
void SetFallInformation(uint32 time, float z)
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 44fe64a..70bf83e 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -4307,19 +4307,6 @@ SpellCastResult Spell::CheckCast(bool strict)
case SPELL_EFFECT_LEAP:
case SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER:
{
- float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
- float fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation());
- float fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation());
- // teleport a bit above terrain level to avoid falling below it
- float fz = m_caster->GetBaseMap()->GetHeight(fx,fy,m_caster->GetPositionZ(),true);
- if(fz <= INVALID_HEIGHT) // note: this also will prevent use effect in instances without vmaps height enabled
- return SPELL_FAILED_TRY_AGAIN;
-
- float caster_pos_z = m_caster->GetPositionZ();
- // Control the caster to not climb or drop when +-fz > 8
- if(!(fz <= caster_pos_z + 8 && fz >= caster_pos_z - 8))
- return SPELL_FAILED_TRY_AGAIN;
-
// not allow use this effect at battleground until battleground start
if(m_caster->GetTypeId() == TYPEID_PLAYER)
if(BattleGround const *bg = ((Player*)m_caster)->GetBattleGround())
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index 5d39fab..99cd5b4 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -5780,26 +5780,110 @@ void Spell::EffectMomentMove(uint32 i)
if(unitTarget->isInFlight())
return;
- if( m_spellInfo->rangeIndex == 1) //self range
+ if(m_spellInfo->rangeIndex == 1) //self range
{
- float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
+ const float lenght2d = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
- // before caster
- float fx, fy, fz;
- unitTarget->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
- float ox, oy, oz;
- unitTarget->GetPosition(ox, oy, oz);
+ const float losH = 1.2f; // LoS height
+ const float dl_2d = 0.7f;
+ int n_itrs = int(lenght2d/dl_2d);
+ if(n_itrs == 0)
+ return;
+
+ float cx,cy,cz;
+ unitTarget->GetPosition(cx,cy,cz);
+ const float angle = unitTarget->GetOrientation();
+ const uint32 mapId = unitTarget->GetMapId();
+
+ const float dx = dl_2d*cos(angle);
+ const float dy = dl_2d*sin(angle);
+
+ std::vector<float> mapData;
+ mapData.resize(n_itrs);
+ float x_i = cx, y_i = cy, z_i = cz;
+
+ bool isFallorFly = false;
+ if (unitTarget->GetTypeId() == TYPEID_PLAYER && ((Player*)unitTarget)->HasMovementFlag(MovementFlags(MOVEMENTFLAG_FALLING |
+ MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2 | MOVEMENTFLAG_WATERWALKING)))
+ isFallorFly = true;
+
+ Map const* map = unitTarget->GetBaseMap();
+ bool above_map = cz+losH >= map->GetHeight(cx,cy,MAX_HEIGHT,false) ? true : false;
+
+ for(int itr = 0; itr < n_itrs; ++itr)
+ {
+ x_i += dx;
+ y_i += dy;
+ float mapHeight = map->GetHeight(x_i,y_i,MAX_HEIGHT,false);
+ if ((above_map && z_i+losH < mapHeight) || (!above_map && z_i+losH > mapHeight))
+ {
+ x_i -= dx;
+ y_i -= dy;
+ break;
+ }
+ if(!isFallorFly)
+ mapData[itr] = mapHeight;
+ }
+
+ float v_x, v_y, v_z;
+ VMAP::IVMapManager *vmgr = VMAP::VMapFactory::createOrGetVMapManager();
+ if(vmgr->getObjectHitPos(mapId, cx,cy,cz+losH, x_i,y_i,z_i+losH, v_x,v_y,v_z,0))
+ {
+ float objSize = unitTarget->GetObjectSize()/dl_2d;
+ v_x -= dx*objSize, v_y -= dy*objSize;
+ if(!isFallorFly)
+ n_itrs = int( sqrtf((v_x-cx)*(v_x-cx)+(v_y-cy)*(v_y-cy))/dl_2d );
+ }
- float fx2, fy2, fz2; // getObjectHitPos overwrite last args in any result case
- if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget->GetMapId(), ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
+ if(isFallorFly)
{
- fx = fx2;
- fy = fy2;
- fz = fz2;
- unitTarget->UpdateGroundPositionZ(fx, fy, fz);
+ float mapH = map->GetHeight(v_x,v_y,v_z,false);
+ float vmapH = vmgr->getHeight(unitTarget->GetMapId(),v_x,v_y,v_z);
+ float ground = vmapH > mapH ? vmapH : mapH;
+
+ if( ((Player*)unitTarget)->HasMovementFlag(MovementFlags(MOVEMENTFLAG_FALLING)) )
+ {
+ Player *pl = (Player*)unitTarget;
+ SafePosition lpos = pl->m_safeposition;
+ uint32 fallTime = pl->m_movementInfo.fallTime;
+ if(lpos.z - ground > 14.0f)
+ {
+ if(fallTime < 2500) //when near the last safe pos
+ v_x = lpos.x,v_y = lpos.y,v_z = lpos.z;
+ else
+ v_z = cz; //normal falling
+ }else
+ if(fallTime > 2500)
+ v_z = ground;
+ }else
+ v_z = cz > ground ? cz : ground;
+ }
+ else
+ {
+ int i = 0;
+ x_i = cx, y_i = cy, v_z = cz;
+ for(std::vector<float>::const_iterator j = mapData.begin(); i < n_itrs && j != mapData.end(); ++j)
+ {
+ x_i += dx;
+ y_i += dy;
+ float ray = v_z > *j ? v_z + 2.0f - *j : 10.0f;
+ float height = vmgr->getHeight(mapId,x_i,y_i,v_z+2.0f,ray > 10.0f ? 10.0f:ray);
+
+ if( !(height > INVALID_HEIGHT && (height > *j || fabs(*j-cz+losH) > fabs(height-cz+losH))) )
+ height = *j;
+
+ if(fabs(v_z - height)/dl_2d > 2.7475f) // >tan(70)
+ {
+ float objSize = unitTarget->GetObjectSize()/dl_2d;
+ v_x = x_i-dx*objSize, v_y = y_i-dy*objSize;
+ break;
+ }
+ v_z = height;
+ ++i;
+ }
}
- unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(), unitTarget == m_caster);
+ unitTarget->NearTeleportTo(v_x, v_y, v_z, angle,unitTarget==m_caster);
}
}
diff --git a/src/shared/vmap/IVMapManager.h b/src/shared/vmap/IVMapManager.h
index d4b776d..a4e11b5 100644
--- a/src/shared/vmap/IVMapManager.h
+++ b/src/shared/vmap/IVMapManager.h
@@ -61,6 +61,7 @@ namespace VMAP
virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) = 0;
virtual float getHeight(unsigned int pMapId, float x, float y, float z) = 0;
+ virtual float getHeight(unsigned int pMapId, float x, float y, float z, float RayLenght) = 0;
/**
test if we hit an object. return true if we hit one. rx,ry,rz will hold the hit position or the dest position, if no intersection was found
return a position, that is pReduceDist closer to the origin
diff --git a/src/shared/vmap/VMapManager.cpp b/src/shared/vmap/VMapManager.cpp
index ec5d870..14e27d8 100644
--- a/src/shared/vmap/VMapManager.cpp
+++ b/src/shared/vmap/VMapManager.cpp
@@ -469,6 +469,27 @@ namespace VMAP
return(height);
}
+ float VMapManager::getHeight(unsigned int pMapId, float x, float y, float z, float RayLenght)
+ {
+ float height = VMAP_INVALID_HEIGHT_VALUE; //no height
+ if(isHeightCalcEnabled() && iInstanceMapTrees.containsKey(pMapId))
+ {
+ Vector3 pPos = convertPositionToInternalRep(x,y,z);
+ MapTree* mapTree = iInstanceMapTrees.get(pMapId);
+ height = mapTree->getHeight(pPos,RayLenght);
+ if(!(height < inf()))
+ {
+ height = VMAP_INVALID_HEIGHT_VALUE; //no height
+ }
+#ifdef _VMAP_LOG_DEBUG
+ Command c = Command();
+ c.fillTestHeightCmd(pMapId,Vector3(x,y,z),height);
+ iCommandLogger.appendCmd(c);
+#endif
+ }
+ return(height);
+ }
+
//=========================================================
/**
used for debugging
@@ -645,6 +666,19 @@ namespace VMAP
return(height);
}
+ float MapTree::getHeight(const Vector3& pPos, float RayLenght)
+ {
+ float height = inf();
+ Vector3 dir = Vector3(0,-1,0);
+ Ray ray = Ray::fromOriginAndDirection(pPos, dir); // direction with length of 1
+ float dist = getIntersectionTime(ray, RayLenght, false);
+ if(dist < inf())
+ {
+ height = (pPos + dir * dist).y;
+ }
+ return(height);
+ }
+
//=========================================================
bool MapTree::PrepareTree()
diff --git a/src/shared/vmap/VMapManager.h b/src/shared/vmap/VMapManager.h
index 3d9057f..22e25ef 100644
--- a/src/shared/vmap/VMapManager.h
+++ b/src/shared/vmap/VMapManager.h
@@ -104,6 +104,7 @@ namespace VMAP
bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2);
bool getObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist);
float getHeight(const G3D::Vector3& pPos);
+ float getHeight(const G3D::Vector3& pPos, float RayLenght);
bool PrepareTree();
bool loadMap(const std::string& pDirFileName, unsigned int pMapTileIdent);
@@ -164,6 +165,7 @@ namespace VMAP
*/
bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist);
float getHeight(unsigned int pMapId, float x, float y, float z);
+ float getHeight(unsigned int pMapId, float x, float y, float z, float RayLenght);
bool processCommand(char *pCommand); // for debug and extensions
|