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; }
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); }
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); }
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; }
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; }
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; }
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; }
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; }