Exemple #1
0
void KAIBase::OnReturn(void)
{
	int nRetCode = cmsInvalid;
	BOOL bRetCode = FALSE;

	bRetCode = CheckReturn();
	KG_PROCESS_SUCCESS(bRetCode);

	nRetCode = m_pSelf->m_eMoveState;

	if (nRetCode == cmsOnStand)
	{
		int nDir = g_GetDirection(m_pSelf->m_nX, m_pSelf->m_nY, m_nReturnX, m_nReturnY);
		m_pSelf->Turn(nDir, true, true);

		// 跑回ReturnPoint
		//KGLogPrintf(KGLOG_DEBUG, "[AI] Return Run to (%d, %d)\n", m_nReturnX, m_nReturnY);
		m_pSelf->RunTo(m_nReturnX, m_nReturnY);
	}

	return;
Exit1:
	//返回原点了,停一秒
	if (m_pNpcTeam)
		DoWait();
	else
		DoIdle(GAME_FPS);

	return;
}
int KHero::LuaMoveToTarget(Lua_State* L)
{
    BOOL bRetCode = false;
    int  nDestX = 0;
    int  nDestY = 0;
    int  nDestZ = 0;
    int  nDirection = 0;
    BOOL bWalk = false;
    int nTopIndex = 0;

    nTopIndex = Lua_GetTopIndex(L);
    KG_PROCESS_ERROR(nTopIndex == 1);

    bWalk = Lua_ValueToBoolean(L, 1);

    bRetCode = GetAITargetPos(nDestX, nDestY, nDestZ);
    KG_PROCESS_ERROR(bRetCode);

    nDirection  = g_GetDirection(m_nX, m_nY, nDestX, nDestY);
    if (bWalk)
        bRetCode    = WalkTo(nDirection, true);   
    else
        bRetCode    = RunTo(nDirection, true);
Exit0:
    return 0;
}
Exemple #3
0
void KMathFunctionTest::KMathTest_6704()
{
    int nRetCode = false;
    char szTestCaseDscribe[] = "与坐标系(0, 0)的方向 x、y达到上限 ";
    KG_CASE_INFO(szTestCaseDscribe, "");

    nRetCode = g_GetDirection(2147483647, 2147483647) ;

    KG_CASE_INFO(szTestCaseDscribe, "");
    KG_CPPUNIT_ASSERT(nRetCode == 32);
} 
Exemple #4
0
void KMathFunctionTest::KMathTest_6703()
{
    int nRetCode = false;
    char szTestCaseDscribe[] = "与坐标系(0, 0)的方向 计算坐标原点的方向 ";
    KG_CASE_INFO(szTestCaseDscribe, "");

    nRetCode = g_GetDirection(0, 0) ;

    KG_CASE_INFO(szTestCaseDscribe, "");
    KG_CPPUNIT_ASSERT(nRetCode == 0);
} 
Exemple #5
0
void KAIBase::OnAlert(void)
{
	KCharacter* pTarget     = NULL;
	BOOL        bRetCode    = FALSE;

    bRetCode = m_pSelf->m_SelectTarget.GetTarget(&pTarget);
    KG_PROCESS_ERROR(bRetCode && pTarget);

	if (pTarget)
	{
		//目标超出范围
		int nDistance2 = g_GetDistance2(m_pSelf->m_nX, m_pSelf->m_nY, pTarget->m_nX, pTarget->m_nY);

		//按等级修正距离
		int nCheckDistance2 = (int)(m_pAIParam->nAlertRange * m_pAIParam->nAlertRange);

		KG_PROCESS_ERROR(nDistance2 <= nCheckDistance2);

		//朝向目标
		int nDirection  = g_GetDirection(m_pSelf->m_nX, m_pSelf->m_nY, pTarget->m_nX, pTarget->m_nY);
		if (m_pSelf->m_nFaceDirection != nDirection)
		{
			m_pSelf->Turn(nDirection, true, true);
		}
	

		//目标未丢失, 看是否超时
		if (g_pSO3World->m_nGameLoop > m_AlertData.nAlartFrame)
		{
			//超时,进行攻击
			m_pSelf->m_ThreatList.ModifyThreat(pTarget, 0);
			TurnToFight();
			return;
		}
	}
	
	bRetCode = CheckTargetInAttackRange();
	KG_PROCESS_SUCCESS(bRetCode);

	return;
Exit0:
	bRetCode = CheckTargetInAttackRange();
	KG_PROCESS_SUCCESS(bRetCode);
	 
	//什么都没有了,出警戒状态,开始发呆
	ClearTarget();
	DoIdle(1);

	return; 
Exit1:
	return;
}
Exemple #6
0
inline int TestGetDirection(int nX1, int nY1, int nX2, int nY2) 
{
	int nResult = false;    
	int nRetCode = false;
    float fRetCode = 0;
    int nDirection = false;
    int nSinValue = 0;

    nDirection = g_GetDirection(nX1, nY1, nX2, nY2);
    fRetCode = ((float)g_Sin(nDirection)) / 4096;
    nSinValue = fRetCode > 0 ? fRetCode + 0.5 : fRetCode - 0.5; 

    fRetCode = (nY2 - nY1) * (nY2 - nY1) + (nX2 - nX1) * (nX2 - nX1);
    fRetCode = (nY2 - nY1) / sqrt(fRetCode);
    nRetCode = fRetCode > 0 ? fRetCode + 0.5 : fRetCode - 0.5; 

    KG_PROCESS_ERROR(nRetCode == nSinValue);

	nResult = true;
Exit0:
	return nResult;
}
Exemple #7
0
void KAIBase::OnPursuit(void)
{
	int             nRetCode            = false;
	BOOL            bSkipKeepRange      = false;
	KCharacter*     pTarget             = NULL;
	KNpc*			pNpc			    = NULL;		
	KNpcTemplate*	pTemplate		    = NULL;
    int             nSelectSkillIndex   = 0;
    int             nSkillExpectation   = 0;
    DWORD           dwSkillID           = 0;
    DWORD           dwSkillLevel        = 0;
    DWORD           dwSelectSkillID     = 0;
    DWORD           dwSelectSkillLevel  = 0;
    KTarget         Target;

	KGLOG_PROCESS_ERROR(m_pSelf);
	KGLOG_PROCESS_ERROR(IS_NPC(m_pSelf->m_dwID));

	pNpc = (KNpc*)(m_pSelf);
	KGLOG_PROCESS_ERROR(pNpc);

	// 检查仇恨表是否为空
	KThreatNode* pThreatNode = pNpc->m_ThreatList.GetFirstThreat();
	if (!pThreatNode)
	{
		BOOL bReturn = true;

		// 组队情况下还要看队友的仇恨表
		if (m_pNpcTeam)
		{
			pTarget = m_pNpcTeam->GetMemberTarget();
			if (pTarget)
			{
				pNpc->m_ThreatList.ModifyThreat(pTarget, 0);
				bReturn = false;
			}
		}
		
		if (bReturn)
		{
			AI_TRACE("仇恨表空的,不打了回去!");
			DoReturn();
			goto Exit1;
		}

		pThreatNode = pThreatNode = pNpc->m_ThreatList.GetFirstThreat();
		KGLOG_PROCESS_ERROR(pThreatNode);
	}

	//检测是否呼叫
	CheckCallHeal();

	// 检查技能状态
	KG_PROCESS_SUCCESS(m_pSelf->m_OTActionParam.eActionType != otActionIdle);

    ASSERT(IS_NPC(m_pSelf->m_dwID));
	pTemplate = ((KNpc*)m_pSelf)->m_pTemplate;
	KGLOG_PROCESS_ERROR(pTemplate);

	//没有普通攻击就表示怪物不能攻击,直接返回
	KG_PROCESS_SUCCESS((pTemplate->dwSkillIDList[0] == 0) && (pTemplate->dwSkillLevelList[0] == 0));

	// 选择技能和目标
	if (g_pSO3World->m_nGameLoop >= pNpc->m_nSkillCommomCD)
	{
		for (int nSkillIndex = MAX_NPC_AI_SKILL - 1; nSkillIndex >= 0; nSkillIndex--)
		{
			dwSelectSkillID		= pTemplate->dwSkillIDList[nSkillIndex];
			dwSelectSkillLevel	= pTemplate->dwSkillLevelList[nSkillIndex];

            if (dwSelectSkillID == 0 || dwSelectSkillLevel == 0 || g_pSO3World->m_nGameLoop < pNpc->m_nSkillCastFrame[nSkillIndex])
			{
				continue;
			}

			nSkillExpectation = GetSkillExpectation((AI_SKILL_TYPE)pTemplate->nAISkillType[nSkillIndex], (DWORD)nSkillIndex, &Target);
			if (nSkillExpectation == AI_IMMEDIATELY_CAST_EXP)
			{
				dwSkillID           = dwSelectSkillID;
				dwSkillLevel        = dwSelectSkillLevel;
				nSelectSkillIndex   = nSkillIndex;
				break;
			}
			else
			{
				if (pTemplate->nSkillCastInterval[nSkillIndex] > g_pSO3World->m_Settings.m_ConstList.nNpcCommonShortCD)
                {
                    //技能没有释放成功就进入公共短CD
					pNpc->m_nSkillCastFrame[nSkillIndex] = g_pSO3World->m_nGameLoop + g_pSO3World->m_Settings.m_ConstList.nNpcCommonShortCD;
                }
				else
                {
					pNpc->m_nSkillCastFrame[nSkillIndex] = g_pSO3World->m_nGameLoop + pTemplate->nSkillCastInterval[nSkillIndex];
                }
			}
		}
	}

	//获取技能目标
	if (Target.GetTargetType() == ttNpc || Target.GetTargetType() == ttPlayer)
	{
        nRetCode = Target.GetTarget(&pTarget);
        KGLOG_PROCESS_ERROR(nRetCode && pTarget);
	}

	// 朝向
	if (pTarget && pTarget != m_pSelf && m_pSelf->m_eMoveState == cmsOnStand)
	{
		int nDirection  = g_GetDirection(m_pSelf->m_nX, m_pSelf->m_nY, pTarget->m_nX, pTarget->m_nY);
		if (m_pSelf->m_nFaceDirection != nDirection)
		{
			m_pSelf->Turn(nDirection, true, true);
		}
	}

	// 释放技能
	if (dwSkillID != 0 && dwSkillLevel != 0)
	{
        KSKILL_RECIPE_KEY RecipeKey;
        KSkill* pSkill = NULL;

        nRetCode = g_pSO3World->m_SkillManager.GetSkillRecipeKey(&RecipeKey, dwSkillID, dwSkillLevel, m_pSelf);
        if (!nRetCode)
        {
            KGLogPrintf(
                KGLOG_ERR, 
                "Can't find npc skill, npc template id = %lu, skill id = %lu, skill level = %lu. Please check you config file. ", 
                pNpc->m_dwTemplateID, dwSkillID, dwSkillLevel
            );
            goto Exit0;
        }

        pSkill = g_pSO3World->m_SkillManager.GetSkill(RecipeKey);
        KGLOG_PROCESS_ERROR(pSkill);

		nRetCode = pSkill->CanCast(m_pSelf, Target);
		if (nRetCode == srcSuccess)
		{
			if (pSkill->m_nPrepareFrames > 0)
			{
				m_pSelf->Stop();
				bSkipKeepRange = TRUE;
			}

			nRetCode = m_pSelf->CastSkill(dwSkillID, dwSkillLevel, Target);
		}

		if (nRetCode == srcTooFarTarget)
		{
			m_PursuitData.dwKeepDisDivisor++;
			if (m_PursuitData.dwKeepDisDivisor > 5)
            {
				m_PursuitData.dwKeepDisDivisor = 5;
            }
		}
		else
		{
			m_PursuitData.dwKeepDisDivisor = 1;
		}

		if (nRetCode == srcSuccess)
		{
			//技能释放成功进入正常CD,这块还没定,可能要等具体发出去了才进CD
			pNpc->m_nSkillCastFrame[nSelectSkillIndex] = g_pSO3World->m_nGameLoop + pTemplate->nSkillCastInterval[nSelectSkillIndex];
	
			//设置公共CD
			pNpc->m_nSkillCommomCD = g_pSO3World->m_nGameLoop + g_pSO3World->m_Settings.m_ConstList.nNpcSkillCommonCD;

			// 判断目标的移动状态,更新仇恨范围
			if (pTarget && pTarget->m_nVelocityXY == 0)
			{
				m_pSelf->m_ThreatList.UpdateKeepThreatField(); //更新仇恨区域
				//m_pSelf->m_ThreatList.ModifyThreat(pTarget, 0);   //更新仇恨
				bSkipKeepRange = true;
			}
		}
		else
		{
			//技能没有释放成功就进入公共短CD
			if (pTemplate->nSkillCastInterval[nSelectSkillIndex] > g_pSO3World->m_Settings.m_ConstList.nNpcCommonShortCD)
            {
				pNpc->m_nSkillCastFrame[nSelectSkillIndex] = g_pSO3World->m_nGameLoop + g_pSO3World->m_Settings.m_ConstList.nNpcCommonShortCD;
            }
			else
            {
				pNpc->m_nSkillCastFrame[nSelectSkillIndex] = g_pSO3World->m_nGameLoop + pTemplate->nSkillCastInterval[nSelectSkillIndex];
            }
		}
	}

	//获取第一仇恨的目标
	pTarget = pThreatNode->pCharacter;
	KGLOG_PROCESS_ERROR(pTarget);

	// 维持距离
	if (!bSkipKeepRange)
	{	
        KSkill* pSkill = NULL;
        KSKILL_RECIPE_KEY RecipeKey;

        nRetCode = g_pSO3World->m_SkillManager.GetSkillRecipeKey(&RecipeKey, pTemplate->dwSkillIDList[0], pTemplate->dwSkillLevelList[0], m_pSelf);
        KGLOG_PROCESS_ERROR(nRetCode);

        pSkill = g_pSO3World->m_SkillManager.GetSkill(RecipeKey);
		KGLOG_PROCESS_ERROR(pSkill);

        if (pNpc->m_nPathFindAstar)
        {
            KeepAttackRangeAStar(pTarget, pSkill);
        }
        else
        {
            KeepAttackRange(pTarget, pSkill);
        }
	}

Exit1:
Exit0:
	return;
}
Exemple #8
0
BOOL KTrackList::GetTrackPoint(KTRACK_POINT* pPoint, DWORD dwTrackID, int nFrame)
{
    BOOL                    bResult         = false;
    KTRACK_TABLE::iterator  TabIter         = m_TrackTable.find(dwTrackID);
    KTRACK*                 pTrack          = NULL;
    size_t                  uTrackSize      = 0;
    KCRITICAL_POINT*        pLeft           = NULL;
    KCRITICAL_POINT*        pRight          = NULL;
    KCRITICAL_POINT*        pNode           = NULL;
    int                     nDeltaFrame     = 0;
    int                     nDeltaFrameL    = 0;
    int                     nDeltaFrameR    = 0;

    KGLOG_PROCESS_ERROR(TabIter != m_TrackTable.end());
    pTrack = &TabIter->second.Track;

    uTrackSize = pTrack->size();
    KGLOG_PROCESS_ERROR(uTrackSize >= 2);

    pLeft   = &(*pTrack)[0];
    pRight  = pLeft + uTrackSize - 1;

    KGLOG_PROCESS_ERROR(nFrame >= pLeft->nFrame);

    // 二分查找,找到一个节点满足条件: nFrame >= pNode->nFrame, 并且下一个节点的满足 nFrame <= pNode->nFrame

    while (pLeft->nFrame <= nFrame && pRight->nFrame > nFrame && pRight - pLeft > 1)
    {
        pNode = pLeft + (pRight - pLeft) / 2;

        if (pNode->nFrame <= nFrame)
        {
            pLeft = pNode;
            continue;
        }

        pRight = pNode;
    }

    // 如果没找到,或者已经过了终点,则返回false

    if (pRight->nFrame == nFrame)
    {
        pLeft = pRight - 1;

        pPoint->nX          = pRight->nX;
        pPoint->nY          = pRight->nY;
        pPoint->nZ          = pRight->nZ;
        pPoint->nDirection  = g_GetDirection(pLeft->nX, pLeft->nY, pRight->nX, pRight->nY);
        goto Exit1;
    }

    KG_PROCESS_ERROR(pRight->nFrame > nFrame);

    // 插值计算nFrame对应的坐标

    nDeltaFrame     = pRight->nFrame - pLeft->nFrame;
    nDeltaFrameL    = nFrame - pLeft->nFrame;
    nDeltaFrameR    = pRight->nFrame - nFrame;

    pPoint->nX         = (pLeft->nX * nDeltaFrameR + pRight->nX * nDeltaFrameL) / nDeltaFrame;
    pPoint->nY         = (pLeft->nY * nDeltaFrameR + pRight->nY * nDeltaFrameL) / nDeltaFrame;
    pPoint->nZ         = (pLeft->nZ * nDeltaFrameR + pRight->nZ * nDeltaFrameL) / nDeltaFrame;
    pPoint->nDirection = g_GetDirection(pLeft->nX, pLeft->nY, pRight->nX, pRight->nY);

Exit1:
    bResult = true;
Exit0:
    return bResult;
}
Exemple #9
0
inline int TestGetDirection(float fLeft, int nRight) 
{
    int nResult = false;    
    int nRetCode = false;
    int nX = 0;
    int nY = 0;

    while (true)
    {
        if (fLeft >= 256)
        {
            fLeft -= 256;
            continue;
        }

        if (fLeft < 0)
        {
            fLeft += 256;
            continue;
        }
        break;
    }

    nRight %= 256;

    if (fLeft == 0)
    {
        nX = 100;
        nY = 0;
    }
    else if (fLeft == 64)
    {
        nX = 0;
        nY = 100;
    }
    else if (fLeft == 128)
    {
        nX = -100;
        nY = 0;
    }
    else if (fLeft == 192)
    {
        nX = 0;
        nY = -100;
    }
    else if (fLeft < 64)//我知道可以组合起来,但这样可以不增加判断条件
    {
        nX = 100;
        nY = nX * tan(2 * fLeft * SO3WORLD_PI/ 256);
    }
    else if (fLeft < 128)
    {
        nX = -100;
        nY = nX * tan(2 * fLeft * SO3WORLD_PI/ 256);
    }
    else if (fLeft < 192)
    {
        nX = -100;
        nY = nX * tan(2 * fLeft * SO3WORLD_PI/ 256);
    }
    else if (fLeft < 256)
    {
        nX = 100;
        nY = nX * tan(2 * fLeft * SO3WORLD_PI/ 256);
    }
    else
    {
        ASSERT(false);
    }

    nRetCode = g_GetDirection(nX, nY);
    KG_PROCESS_ERROR(nRetCode == nRight);

    nResult = true;
Exit0:
    return nResult;
}