コード例 #1
0
ファイル: GridMap.cpp プロジェクト: Hennesei/mangos
bool TerrainInfo::CheckPathAccurate(float srcX, float srcY, float srcZ, float& dstX, float& dstY, float& dstZ, Unit* mover, bool onlyLOS ) const
{

    float tstX = dstX;
    float tstY = dstY;
    float tstZ = dstZ;
    // check by standart way. may be not need path checking?
    if (!mover && CheckPath(srcX, srcY, srcZ, tstX, tstY, tstZ) && IsNextZcoordOK(tstX, tstY, tstZ, 5.0f))
    {
        DEBUG_LOG("TerrainInfo::CheckPathAccurate vmaps hit! delta is %f %f %f",dstX - tstX,dstY - tstY,dstZ - tstZ);
        dstX = tstX;
        dstY = tstY;
        dstZ = tstZ + 0.1f;
        return true;
    }

    const float distance = sqrt((dstY - srcY)*(dstY - srcY) + (dstX - srcX)*(dstX - srcX));
    const float DELTA    = 0.5f;
    const uint8 numChecks = ceil(fabs(distance/DELTA));
    const float DELTA_X  = (dstX-srcX)/numChecks;
    const float DELTA_Y  = (dstY-srcY)/numChecks;
    const float DELTA_Z  = (dstZ-srcZ)/numChecks;

    float lastGoodX = srcX;
    float lastGoodY = srcY;
    float lastGoodZ = srcZ;

    uint32 errorsCount = 0;
    uint32 goodCount   = 0;
    uint32 vmaperrorsCount   = 0;

    std::set<GameObject*> inLOSGOList;
    bool bGOCheck = false;
    if (mover)
    {
        std::list<GameObject*> tempTargetGOList;
        MaNGOS::GameObjectInRangeCheck check(mover, tstX, tstY, tstZ, distance + 2.0f *mover->GetObjectBoundingRadius());
        MaNGOS::GameObjectListSearcher<MaNGOS::GameObjectInRangeCheck> searcher(tempTargetGOList, check);
        Cell::VisitAllObjects(mover, searcher, 2*mover->GetObjectBoundingRadius());
        if (!tempTargetGOList.empty())
        {
            for(std::list<GameObject*>::iterator iter = tempTargetGOList.begin(); iter != tempTargetGOList.end(); ++iter)
            {
                GameObject* pGo = *iter;

                if (!pGo || !pGo->IsInWorld())
                    continue;

                // Not require check GO's, if his not in path
                // first fast check
                if (pGo->GetPositionX() > std::max(srcX, dstX)
                    || pGo->GetPositionX() < std::min(srcX, dstX)
                    || pGo->GetPositionY() > std::max(srcY, dstY)
                    || pGo->GetPositionY() < std::min(srcY, dstY))
                    continue;

                // don't check very small and very large objects
                if (pGo->GetDeterminativeSize(true) < mover->GetObjectBoundingRadius() * 0.5f ||
                    pGo->GetDeterminativeSize(false) > mover->GetObjectBoundingRadius() * 100.0f)
                    continue;

                // second check by angle
                float angle = mover->GetAngle(pGo) - mover->GetAngle(dstX, dstY);
                if (abs(sin(angle)) * pGo->GetExactDist2d(srcX, srcY) > pGo->GetObjectBoundingRadius() * 0.5f)
                    continue;

                bool bLOSBreak = false;
                switch (pGo->GetGoType())
                {
                        case GAMEOBJECT_TYPE_TRAP:
                        case GAMEOBJECT_TYPE_SPELL_FOCUS:
                        case GAMEOBJECT_TYPE_MO_TRANSPORT:
                        case GAMEOBJECT_TYPE_CAMERA:
                        case GAMEOBJECT_TYPE_FISHINGNODE:
                        case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
                        case GAMEOBJECT_TYPE_SPELLCASTER:
                        case GAMEOBJECT_TYPE_FISHINGHOLE:
                        case GAMEOBJECT_TYPE_CAPTURE_POINT:
                            break;
                        case GAMEOBJECT_TYPE_DOOR:
                            if (pGo->isSpawned() && pGo->GetGoState() == GO_STATE_READY)
                                bLOSBreak = true;
                            break;
                        case GAMEOBJECT_TYPE_TRANSPORT:
                            if (pGo->isSpawned() && pGo->GetGoState() == GO_STATE_ACTIVE)
                                bLOSBreak = true;
                            break;
                        case GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING:
                            if (!pGo->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED))
                                bLOSBreak = true;
                            break;
                        default:
                            if (pGo->isSpawned())
                                bLOSBreak = true;
                            break;
                }
                if (bLOSBreak)
                    inLOSGOList.insert(pGo);
            }
        }
        if (!inLOSGOList.empty())
            bGOCheck = true;
    }

    //Going foward until max distance
    for (uint8 i = 1; i < numChecks; ++i)
    {
        float prevX = srcX + (float(i-1)*DELTA_X);
        float prevY = srcY + (float(i-1)*DELTA_Y);
        float prevZ = GetHeight(prevX, prevY, srcZ + 5.0f);

        tstX = srcX + (float(i)*DELTA_X);
        tstY = srcY + (float(i)*DELTA_Y);
        tstZ = GetHeight(tstX, tstY, srcZ + 5.0f);

        MaNGOS::NormalizeMapCoord(tstX);
        MaNGOS::NormalizeMapCoord(tstY);

        if (tstZ <= INVALID_HEIGHT)
            break;
        tstZ += (0.5f + DELTA_Z);

        if (!CheckPath(prevX, prevY, prevZ, tstX, tstY, tstZ))
        {
            ++vmaperrorsCount;
            ++errorsCount;
            goodCount = 0;
        }
        else if (!IsNextZcoordOK(tstX, tstY, tstZ, 5.0f))
        {
            ++errorsCount;
            goodCount = 0;
        }
        else if (mover && bGOCheck)
        {
            bool bError = false;
            for(std::set<GameObject*>::const_iterator iter = inLOSGOList.begin(); iter != inLOSGOList.end(); ++iter)
            {
                if (!(*iter) || (*iter)->GetDistance2d(tstX, tstY) > (*iter)->GetObjectBoundingRadius())
                    continue;

//                DEBUG_LOG("TerrainInfo::CheckPathAccurate GO %s in LOS found, %f %f %f ",(*iter)->GetObjectGuid().GetString().c_str(),tstX,tstY,tstZ);
                bError = true;
                break;
            }

            if (bError)
            {
                ++errorsCount;
                goodCount = 0;
            }
            else
                ++goodCount;
        }
        else
        {
            ++goodCount;
        }

//        DEBUG_LOG("TerrainInfo::CheckPathAccurate test data %f %f %f good=%u, errors=%u vmap=%u",tstX,tstY,tstZ, goodCount, errorsCount, vmaperrorsCount);

        if (!errorsCount)
        {
            lastGoodX = prevX;
            lastGoodY = prevY;
            lastGoodZ = prevZ;
        }
        else
            if (onlyLOS)
                break;

        if (errorsCount && goodCount > 10)
        {
            --errorsCount;
            goodCount -= 10;
        }
    }

    if (errorsCount)
    {
        dstX = lastGoodX;
        dstY = lastGoodY;
        dstZ = GetHeight(lastGoodX, lastGoodY, lastGoodZ+2.0f) + 0.5f;
    }
    else
    {
        dstX = tstX;
        dstY = tstY;
        dstZ = GetHeight(tstX, tstY, tstZ+2.0f) + 0.5f;
    }

    return (errorsCount == 0);
}
コード例 #2
0
ファイル: GridMap.cpp プロジェクト: Archives/easy-mangos
bool TerrainInfo::CheckPathAccurate(float srcX, float srcY, float srcZ, float& dstX, float& dstY, float& dstZ, Unit* mover ) const
{

    float tstX = dstX;
    float tstY = dstY;
    float tstZ = dstZ;
    // check by standart way. may be not need path checking?
    if (!mover && CheckPath(srcX, srcY, srcZ, tstX, tstY, tstZ) && IsNextZcoordOK(tstX, tstY, tstZ, 5.0f))
    {
        DEBUG_LOG("TerrainInfo::CheckPathAccurate vmaps hit! delta is %f %f %f",dstX - tstX,dstY - tstY,dstZ - tstZ);
        dstX = tstX;
        dstY = tstY;
        dstZ = tstZ + 0.1f;
        return true;
    }

    const float distance = sqrt((dstY - srcY)*(dstY - srcY) + (dstX - srcX)*(dstX - srcX));
    const float DELTA    = 0.5f;
    const uint8 numChecks = ceil(fabs(distance/DELTA));
    const float DELTA_X  = (dstX-srcX)/numChecks;
    const float DELTA_Y  = (dstY-srcY)/numChecks;

    float lastGoodX = srcX;
    float lastGoodY = srcY;
    float lastGoodZ = srcZ;

    uint32 errorsCount = 0;
    uint32 goodCount   = 0;
    uint32 vmaperrorsCount   = 0;

    //Going foward until max distance
    for (uint8 i = 1; i < numChecks; ++i)
    {
        float prevX = srcX + (float(i-1)*DELTA_X);
        float prevY = srcY + (float(i-1)*DELTA_Y);
        float prevZ = GetHeight(prevX, prevY, srcZ+5.0f);

        tstX = srcX + (float(i)*DELTA_X);
        tstY = srcY + (float(i)*DELTA_Y);
        tstZ = GetHeight(tstX, tstY, srcZ+5.0f);

        MaNGOS::NormalizeMapCoord(tstX);
        MaNGOS::NormalizeMapCoord(tstY);

        if (tstZ <= INVALID_HEIGHT)
            break;
        tstZ += 0.5f;

        if (!CheckPath(prevX, prevY, prevZ, tstX, tstY, tstZ))
        {
            ++vmaperrorsCount;
            ++errorsCount;
            goodCount = 0;
        }
        else if (!IsNextZcoordOK(tstX, tstY, tstZ, 5.0f))
        {
            ++errorsCount;
            goodCount = 0;
        }
        else if (mover)
        {
            std::list<GameObject*> tempTargetGOList;
            MaNGOS::GameObjectInRangeCheck check(mover, tstX, tstY, tstZ, 2*mover->GetObjectBoundingRadius());
            MaNGOS::GameObjectListSearcher<MaNGOS::GameObjectInRangeCheck> searcher(tempTargetGOList, check);
            Cell::VisitAllObjects(mover, searcher, 2*mover->GetObjectBoundingRadius());
            if (!tempTargetGOList.empty())
            {
                for(std::list<GameObject*>::iterator iter = tempTargetGOList.begin(); iter != tempTargetGOList.end(); ++iter)
                {
                    if (((*iter)->GetGoType() == GAMEOBJECT_TYPE_DOOR && (*iter)->GetGoState() == GO_STATE_READY)
                        || (*iter)->GetGoType() != GAMEOBJECT_TYPE_DOOR)
                    {
                        ++errorsCount;
                        goodCount = 0;
                    }
                }
            }
            else
                ++goodCount;
        }
        else
        {
            ++goodCount;
        }

        if (!errorsCount)
        {
            lastGoodX = prevX;
            lastGoodY = prevY;
            lastGoodZ = prevZ;
        }
//        DEBUG_LOG("TerrainInfo::CheckPathAccurate test data %f %f %f good=%u, errors=%u vmap=%u",tstX,tstY,tstZ, goodCount, errorsCount, vmaperrorsCount);

        if (errorsCount && goodCount > 10)
        {
            --errorsCount;
            goodCount -= 10;
        }
    }

    if (errorsCount)
    {
        dstX = lastGoodX;
        dstY = lastGoodY;
        dstZ = GetHeight(lastGoodX, lastGoodY, lastGoodZ+2.0f) + 0.5f;
    }
    else
    {
        dstX = tstX;
        dstY = tstY;
        dstZ = GetHeight(tstX, tstY, tstZ+2.0f) + 0.5f;
    }

    return (errorsCount == 0);
}