当前位置:首页>>魔兽单机>>正文
古老的闪现修复方法--代码参考
2013-07-05 17:13:53 作者:网络 来源: 浏览次数:0
摘要:WOW模拟器古老的闪现修复方法--代码参考
 commit 3692884db1a49fc5fb3d316b890994f52db945c8
Author: 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
 
 


相关报道:

[关闭] [返回顶部]


  返回首页 | 最新资讯 | 资源下载 | 魔兽图片 | 单机文档 | 技术攻略 | 玩家视频
备案号:蜀ICP备2024062380号-1
免责声明:本网站为热爱怀旧WOW的玩家们建立的魔兽世界资料网站,仅供交流和学习使用,非盈利和商用.如有侵权之处,请联系我们,我们会在24小时内确认删除侵权内容,谢谢合作。
Copyright © 2024 - 2024 WOWAII.COM Corporation, All Rights Reserved

机器人国度