关灯
开启左侧

古老的闪现修复方法--代码参考

  [复制链接]
admin实名认证 发表于 2016-4-18 22:31:04 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
 
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

标签:修复
 

精彩评论1

倒序浏览
微信 发表于 2016-10-15 17:11:48 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
 
VIP介绍
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 最佳新人

    注册账号后积极发帖的会员
  • 活跃会员

    经常参与各类话题的讨论,发帖内容较有主见
  • 热心会员

    经常帮助其他会员答疑
  • 推广达人

    积极宣传本站,为本站带来更多注册会员
  • 宣传达人

    积极宣传本站,为本站带来更多的用户访问量
  • 灌水之王

    经常在论坛发帖,且发帖量较大
  • 突出贡献

    长期对论坛的繁荣而不断努力,或多次提出建设性意见
  • 优秀版主

    活跃且尽责职守的版主
  • 荣誉管理

    曾经为论坛做出突出贡献目前已离职的版主
  • 论坛元老

    为论坛做出突出贡献的会员

0关注

5粉丝

3421帖子

排行榜
作者专栏

QQ交流群&&微信订阅号

QQ交流群

微信订阅号

吾爱尚玩资源基地永久域名:

Www.523Play.Com

在线管理员QQ:1589479632

邮箱:Email@523play.com

QQ交流群:558936238

Copyright   ©2015-2116  吾爱尚玩资源基地|523play.comPowered by©523Pplay.Com技术支持:吾爱尚玩资源基地