コード例 #1
0
ファイル: ZBrain.cpp プロジェクト: MagistrAVSH/node3d
bool ZBrain::FindTarget()
{
	MUID uidTarget	= MUID(0,0);
	float fDist		= FLT_MAX;

	for ( ZCharacterManager::iterator itor = ZGetCharacterManager()->begin();  itor != ZGetCharacterManager()->end();  ++itor)
	{
		// 죽은 놈은 관심없다.
		ZCharacter* pCharacter = (*itor).second;
		if ( pCharacter->IsDie())
			continue;

		// 제외 목록에 들어간 캐릭터는 건너뜀
		if ( ZGetGame()->IsExceptedFromNpcTargetting( pCharacter))
			continue;

		// 거리를 구한다.
		float dist = MagnitudeSq( pCharacter->GetPosition() - m_pBody->GetPosition());


		// 더 가까운 놈이면 이놈을 타겟으로 정한다.
		if ( dist < fDist)
		{
			fDist = dist;
			uidTarget = pCharacter->GetUID();
		}
	}

	m_uidTarget = uidTarget;

	if ( uidTarget == MUID(0,0))
		return false;

	return true;
}
コード例 #2
0
ファイル: ZActor.cpp プロジェクト: Asunaya/RefinedGunz
ZOBJECTHITTEST ZActor::HitTest(const rvector& origin, const rvector& to, float fTime, rvector *pOutPos)
{
	rvector footpos,actor_dir;
	if(!GetHistory(&footpos,&actor_dir,fTime)) return ZOH_NONE;

	if (m_pNPCInfo->bColPick)
	{
		rvector dir = to - origin;
		Normalize(dir);

		RPickInfo pickinfo;
		memset(&pickinfo,0,sizeof(RPickInfo));

		if (m_pVMesh->Pick(origin, dir, &pickinfo))
		{
			*pOutPos = pickinfo.vOut;
			if ((pickinfo.parts == eq_parts_head) || (pickinfo.parts == eq_parts_face))
			{
				return ZOH_HEAD;
			}
			else
			{
				return ZOH_BODY;
			}
		}
	}
	else
	{
		rvector headpos = footpos;
		if (m_pVMesh)
		{
			headpos.z += m_Collision.fHeight - 5.0f;
		}

		rvector ap,cp;
		float fDist=GetDistanceBetweenLineSegment(origin,to,footpos,headpos,&ap,&cp);
		float fDistToThis=Magnitude(origin-cp);
		if(fDist < (m_Collision.fRadius-5.0f))
		{
			rvector dir = to - origin;
			Normalize(dir);

			rvector ap2cp = ap - cp;
			float fap2cpsq = MagnitudeSq(ap2cp);
			float fdiff = sqrt(m_Collision.fRadius*m_Collision.fRadius - fap2cpsq);

			if(pOutPos) *pOutPos = ap-dir*fdiff;;

			return ZOH_BODY;
		}
	}

	return ZOH_NONE;
}
コード例 #3
0
ファイル: EluLoader.cpp プロジェクト: Asunaya/RefinedGunz
static rmatrix MakeSaneWorldMatrix(const v3& pos, v3 dir, v3 up)
{
#ifdef _DEBUG
	if (!IS_EQ(MagnitudeSq(dir), 1))
	{
		DMLog("dir %f\n", Magnitude(dir));
		if (IS_EQ(MagnitudeSq(dir), 0))
			dir = { 1, 0, 0 };
		else
			Normalize(dir);
	}
	if (!IS_EQ(MagnitudeSq(up), 1))
	{
		DMLog("up %f\n", Magnitude(up));
		if (IS_EQ(MagnitudeSq(up), 0))
			up = { 1, 0, 0 };
		else
			Normalize(up);
	}
#endif

	auto mat = GetIdentityMatrix();

	auto right = Normalized(CrossProduct(dir, up));
	up = Normalized(CrossProduct(right, dir));
	v3 basis[] = {
		right,
		dir,
		up };
	for (size_t i{}; i < 3; ++i)
		for (size_t j{}; j < 3; ++j)
			mat.m[i][j] = basis[i][j];

	SetTransPos(mat, pos);

	return mat;
}
コード例 #4
0
ファイル: ZBrain.cpp プロジェクト: MagistrAVSH/node3d
bool ZBrain::EscapeFromStuckIn(list<rvector>& wayPointList)
{
	// 길찾기 코드의 허점이 드러나는 맵 지점들이 있다.. 그런 곳에서는 몹이 이동하지를 못한다
	// 그런곳을 탈출하기 위해 땜빵을 한다. true 리턴하면 웨이포인트를 여기서 지정했다는 의미.
	DWORD currTime = timeGetTime();
	// 오랜시간 같은 곳에 멈춰있다면 아예 워프해버린다
	if (currTime - m_dwExPositionTimeForWarp > 2000)
	{
		rvector diff = m_exPositionForWarp - m_pBody->GetPosition();

		ResetStuckInStateForWarp();

		if (MagnitudeSq(diff) < 100)
		{
			OutputDebugString("NPC NEED WARP....\n");
			RNavigationMesh* pNavMesh = ZGetGame()->GetWorld()->GetBsp()->GetNavigationMesh();
			if (pNavMesh) {
				// 근방의 랜덤지점을 정한다

				// 랜덤 방향 얻기
				float angle = (rand() % (314*2)) * 0.01f;
				D3DXMATRIX matRot;
				D3DXMatrixRotationZ(&matRot, angle);

				rvector dir(200, 0, 0);	// 이동할 거리
				dir = dir * matRot;
				rvector newpos = m_pBody->GetPosition() + dir;

				// 가장 가까운 네비게이션노드의 센터로 옮긴다 (네비게이션노드가 크게 잡혀 있는 맵에선 워프가 심하게 눈에 띌수 있음..)
				RNavigationNode* pNavNode = pNavMesh->FindClosestNode(newpos);
				if (pNavNode) {
					m_pBody->SetPosition( pNavNode->CenterVertex());
					OutputDebugString("NPC WARP DONE!\n");
					return false;
				}
			}
		}
	}

	// 짧은시간 같은 곳에 멈춰있다면 앞으로 한발짝 정도 움직여서 탈출시도
	if (currTime - m_dwExPositionTime > 1000)
	{
		rvector diff = m_exPosition - m_pBody->GetPosition();

		ResetStuckInState();

		if (MagnitudeSq(diff) < 100)
		{
			wayPointList.clear();

			// 기본적으로 앞쪽으로 방향을 잡되 좌우로 랜덤하게 방향을 준다
			rvector dir = m_pBody->GetDirection();
			rmatrix matRot;
			D3DXMatrixRotationZ(&matRot, (rand()%314 - 157) * 0.01f);	// 3.14 즉 반바퀴 범위 내에서 방향을 틀게 함
			Normalize(dir);

			dir *= m_pBody->GetCollRadius() * 0.8f;
			wayPointList.push_back(m_pBody->GetPosition() + dir);

			PushWayPointsToTask();

			return true;
		}
	}

	return false;
}
コード例 #5
0
ファイル: ZBrain.cpp プロジェクト: MagistrAVSH/node3d
void ZBrain::ProcessBuildPath( float fDelta)
{
	// Update timer
	if ( !m_PathFindingTimer.Update( fDelta))
		return;
	
	// Check status
	ZTASK_ID nTaskID = m_pBody->m_TaskManager.GetCurrTaskID();
	if ( (nTaskID == ZTID_ATTACK_MELEE) || (nTaskID == ZTID_ATTACK_RANGE) || (nTaskID == ZTID_ROTATE_TO_DIR) || (nTaskID == ZTID_SKILL))
		return;

	// 맵에 끼었다면 벗어난다
	// 워프해서 끼임을 탈출하는 건 서바이벌일때만으로 제한한다 (워프는 눈에 크게 띄고 조악한 해결법이다. 기존 퀘스트에서 없던 몹워프가 일어나 유저 불만이 있음)
	if (ZGetGameTypeManager()->IsSurvivalOnly( ZGetGame()->GetMatch()->GetMatchType()))
	{
		if (EscapeFromStuckIn(m_WayPointList))
			return;
	}

	// Get target
	ZObject* pTarget = GetTarget();
	if ( !pTarget)
	{
		m_pBody->m_TaskManager.Clear();
		m_pBody->Stop();

		return;
	}


	// 원거리 공격이거나 우호적이면 넘 가까이 다가가지 않고 바라만 본다.
	if ( ( m_Behavior.GetOffenseType() == ZOFFENSETYPE_RANGE) || m_Behavior.IsFriendly())
	{
		// 거리를 구한다.
		float dist = MagnitudeSq( pTarget->GetPosition() - m_pBody->GetPosition());

		bool bStop = false;

		// Friendly type
		if ( m_Behavior.IsFriendly())
		{
			if ( dist < m_fDistForcedIn)
				bStop = true;
		}
		// Else type
		else
		{
			// 직선 거리를 본다.
			if ( ( dist > DIST_FORCEDIN) && (dist < m_fDistIn))
			{
				// 직선 거리는 가까운데 높이가 많이 차이가 나는지 본다.
				dist = pTarget->GetPosition().z - m_pBody->GetPosition().z;

				// 높이가 넘 많이 차이 안나면 정지
				if ( (dist > -DIST_HEIGHT) && (dist < DIST_HEIGHT))
					bStop = true;
			}
		}

		// Stop
		if ( bStop)
		{
			// 볼 수 있는 위치여야지 정지가 가능하다. 만약 안보인다면 뛰어가서 근접공격을 하도록 한다
			if ( m_pBody->CanSee( pTarget) && m_pBody->CanAttackRange( pTarget))
			{
				m_pBody->Stop();
				m_pBody->m_TaskManager.Clear();

				return;
			}
		}
	}


	// Make path
	RNavigationMesh* pNavMesh = ZGetGame()->GetWorld()->GetBsp()->GetNavigationMesh();
	if ( pNavMesh == NULL)
		return;

	// Make navigation path
	rvector tarpos = pTarget->GetPosition();
	if ( !pNavMesh->BuildNavigationPath( m_pBody->GetPosition(), tarpos))
		return;

	m_WayPointList.clear();
	for ( list<rvector>::iterator itor = pNavMesh->GetWaypointList().begin();  itor != pNavMesh->GetWaypointList().end();  ++itor)
		m_WayPointList.push_back( (*itor));


	AdjustWayPointWithBound(m_WayPointList, pNavMesh);

	PushWayPointsToTask();
}
コード例 #6
0
ファイル: ZBrain.cpp プロジェクト: MagistrAVSH/node3d
bool ZBrain::GetUseableSkill( int *pnSkill, MUID *puidTarget, rvector *pTargetPosition)
{
	// Get skill module
	ZModule_Skills *pmod = (ZModule_Skills *)m_pBody->GetModule(ZMID_SKILLS);
	if ( !pmod)
		return false;

	// Set value
	if ( puidTarget)
		(*puidTarget) = MUID(0,0);

	if (pTargetPosition)
		(*pTargetPosition) = rvector(0.0f,0.0f,0.0f);


	// Check skills
	for ( int i = 0;  i < pmod->GetSkillCount();  i++)
	{
		ZSkill *pSkill = pmod->GetSkill( i);

		// Check cool time
		if ( !pSkill->IsReady())
			continue;

		// Get skill description
		ZSkillDesc *pDesc = pmod->GetSkill( i)->GetDesc();


		// 스킬의 적용 대상이 아군인 경우...
		if ( pDesc->IsAlliedTarget())
		{
			// 효과가 있는 대상중 가까이 있는 걸 찾는다.
			float fDist = DIST_OUT;
			ZObject *pAlliedTarget = NULL;


			for ( ZObjectManager::iterator itor = ZGetObjectManager()->begin();  itor != ZGetObjectManager()->end();  ++itor)
			{
				ZObject *pObject = itor->second;

				// 죽은 놈은 넘어간다
				if ( pObject->IsDie())
					continue;

				// 적이면 넘어간다
				if ( ZGetGame()->CanAttack(m_pBody,pObject))
					continue;

				// 자기 자신이면 넘어간다
				if ( pObject == m_pBody)
					continue;


				// Get distance
				float dist = MagnitudeSq( pObject->GetPosition() - m_pBody->GetPosition());
				if ( pSkill->IsUsable( pObject) && ( dist < fDist))
				{
					fDist = dist;
					pAlliedTarget = pObject;
				}
			}	

			// 만약 대상이 없으면 자기 자신한테라도 스킬을 건다.
			if ( ( pAlliedTarget == NULL) && ( pSkill->IsUsable( m_pBody)))
				pAlliedTarget = m_pBody;

			if (pAlliedTarget)
			{
				if ( pnSkill)
					*pnSkill = i;
				
				if ( puidTarget)
					*puidTarget = pAlliedTarget->GetUID();

				if ( pTargetPosition)
					*pTargetPosition = pAlliedTarget->GetCenterPos();

				return true;
			}
		}

		// 스킬의 적용 대상이 적군인 경우...
		else
		{
			ZObject* pTarget = GetTarget();
			if ( pTarget == NULL)
				continue;

			// Check useable
			if ( !pSkill->IsUsable( pTarget))
				continue;

			// Get pick info
			ZPICKINFO pickinfo;
			memset( &pickinfo, 0, sizeof( ZPICKINFO));


			// Check picking
			rvector pos, tarpos, dir;
			// 적과 나의 몸통 실린더에서 가슴 정도의 높이 지점끼리 피킹 쏴본다..
			pos = m_pBody->GetPosition() + rvector( 0, 0, m_pBody->GetCollHeight()*0.5f*0.8f);		// 가슴께로 낮춰주려고 *0.8
			tarpos = pTarget->GetPosition() + rvector( 0, 0, pTarget->GetCollHeight()*0.5f*0.8f);
			dir = tarpos - pos;
			Normalize( dir);

			const DWORD dwPickPassFlag = RM_FLAG_ADDITIVE | RM_FLAG_HIDE | RM_FLAG_PASSROCKET | RM_FLAG_PASSBULLET;
			if ( ZGetGame()->Pick( m_pBody, pos, dir, &pickinfo, dwPickPassFlag))
			{
				if ( pickinfo.pObject)
				{
					if ( pnSkill)
						*pnSkill = i;

					if ( puidTarget)
						*puidTarget = pTarget->GetUID();

					if ( pTargetPosition)
						*pTargetPosition = pTarget->GetCenterPos();

					return true;
				}
			}
		}
	}

	return false;
}