Пример #1
0
bool ZActor::CanAttackMelee(ZObject* pTarget, ZSkillDesc *pSkillDesc)
{
	if (pSkillDesc == NULL)
	{
		float dist = Magnitude(pTarget->m_Position - m_Position);
		if (dist < m_pNPCInfo->fAttackRange) 
		{
			if (CanSee(pTarget)) return true;
		}
	}
	else
	{
		rvector Pos = GetPosition();
		rvector Dir = GetDirection();
		Dir.z=0; 
		Normalize(Dir);

		float fDist = Magnitude(Pos - pTarget->GetPosition());
		float fColMinRange = pSkillDesc->fEffectAreaMin * 100.0f;
		float fColMaxRange = pSkillDesc->fEffectArea * 100.0f;
		if ((fDist < fColMaxRange + pTarget->GetCollRadius()) && (fDist >= fColMinRange))
		{
			rvector vTargetDir = pTarget->GetPosition() - GetPosition();
			rvector vBodyDir = GetDirection();
			vBodyDir.z = vTargetDir.z = 0.0f;

			float angle = fabs(GetAngleOfVectors(vTargetDir, vBodyDir));
			if (angle <= pSkillDesc->fEffectAngle) return true;
		}
	}

	return false;
}
Пример #2
0
ZTaskResult ZTask_RotateToDir::OnRun(float fDelta)
{
	rvector dir = m_TargetDir;

	if (!m_bRotated)
	{
		rmatrix mat;
		rvector vBodyDir = m_pParent->GetDirection();
		float fAngle=GetAngleOfVectors(dir, vBodyDir);
		float fRotAngle = m_pParent->GetNPCInfo()->fRotateSpeed * (fDelta / 1.0f);

		if (fAngle > 0.0f) fRotAngle = -fRotAngle;
		if (fabs(fRotAngle) > fabs(fAngle)) 
		{
			fRotAngle = -fAngle;
			m_bRotated = true;
			return ZTR_COMPLETED;
		}
		mat = RGetRotZ(ToDegree(fRotAngle));

		m_pParent->RotateTo(vBodyDir * mat);
	}
	else
	{
		return ZTR_COMPLETED;
	}

	

	return ZTR_RUNNING;
}
Пример #3
0
bool ZActor::CanSee(ZObject* pTarget)
{
	rvector vTargetDir = pTarget->GetPosition() - GetPosition();
	rvector vBodyDir = GetDirection();
	vBodyDir.z = vTargetDir.z = 0.0f;

	float angle = fabs(GetAngleOfVectors(vTargetDir, vBodyDir));
	if (angle <= m_pNPCInfo->fViewAngle) return true;

	return false;
}
Пример #4
0
void ZCamera::Update(float fElapsed)
{
	if (!g_pGame)
	{
		assert(false);
		return;
	}

	if (isnan(m_fAngleX) || isnan(m_fAngleZ))
	{
		DMLog("Camera angle is NaN!\n");
		m_fAngleX = CAMERA_DEFAULT_ANGLEX;
		m_fAngleZ = CAMERA_DEFAULT_ANGLEZ;
	}

	ZCombatInterface*	pCombatInterface = ZGetGameInterface()->GetCombatInterface();
	ZCharacter*			pTargetCharacter = g_pGame->m_pMyCharacter;
	if (TargetCharacterOverride)
	{
		pTargetCharacter = TargetCharacterOverride;
	}

	v3 PlayerPosition{ pTargetCharacter->m_Position };
	v3 PlayerDirection{ pTargetCharacter->CameraDir };
	bool Observing = false;

	auto&& Observer = *pCombatInterface->GetObserver();
	
	if (TargetCharacterOverride)
	{
		Observing = true;
		pTargetCharacter->GetHistory(&PlayerPosition, nullptr,
			g_pGame->GetTime(), &PlayerDirection);
	}
	else if (pCombatInterface->GetObserver()->IsVisible())
	{
		auto&& ObserverTarget = Observer.GetTargetCharacter();
		if (ObserverTarget)
		{
			pTargetCharacter = ObserverTarget;
			Observing = pTargetCharacter != nullptr;
		}

		if (pTargetCharacter)
			pTargetCharacter->GetHistory(&PlayerPosition, nullptr,
				g_pGame->GetTime() - Observer.GetDelay(), &PlayerDirection);
	}

	if (!pTargetCharacter) return;

	m_Target = PlayerPosition + GetTargetOffset(PlayerDirection, pTargetCharacter->GetScale());

	v3 dir;
	if (Observing && GetLookMode() == ZCAMERA_DEFAULT)
	{
		// If we're spectating someone, set the direction to their direction.
		dir = PlayerDirection;

		m_fAngleX = acosf(dir.z);
		v3 HorizontalDir{ dir.x, dir.y, 0.f };
		m_fAngleZ = GetAngleOfVectors(rvector(1, 0, 0), HorizontalDir);
	}
	else
		dir = GetCurrentDir();

	v3 shockoffset{ 0, 0, 0 };
	if (m_bShocked)
	{
		float fA = RANDOMFLOAT * 2 * PI_FLOAT;
		float fB = RANDOMFLOAT * 2 * PI_FLOAT;
		auto velocity = v3(sin(fA)*sin(fB), cos(fA)*sin(fB), cos(fB));

		float fPower = (g_pGame->GetTime() - m_fShockStartTime) / m_fShockDuration;
		if (fPower > 1.f)
		{
			StopShock();
		}
		else
		{
			fPower = 1.f - fPower;

			const float FFMAX_POWER = 300.f;

			float ffPower = fPower * m_fShockPower / FFMAX_POWER;
			ffPower = std::min(ffPower, 1.0f);
			ZGetInput()->SetDeviceForcesXY(ffPower, ffPower);

			fPower = pow(fPower, 1.5f);
			auto ShockVelocity = RANDOMFLOAT * m_fShockPower * velocity;
			shockoffset = fPower * fElapsed * ShockVelocity;
		}
	}

	float fRealDist = m_fDist;
	rvector pos = m_CurrentTarget - dir*m_fDist;

	RBSPPICKINFO bpi;

	if (ZGetGame()->GetWorld()->GetBsp()->Pick(m_Target, -dir, &bpi)
		&& Magnitude(m_Target - bpi.PickPos) < Magnitude(m_Target - pos))
	{
		float fColDist = Magnitude(bpi.PickPos - pos);
		float fTargetDist = Magnitude(m_Target - pos);
		pos = bpi.PickPos + dir;

		fRealDist = Magnitude(m_Target - pos) - 10.f;
	}

	if (pTargetCharacter && pTargetCharacter->GetScale() != 1.0f)
		fRealDist *= pTargetCharacter->GetScale();

	m_CurrentTarget = m_Target;

	bool bCollisionWall = CheckCollisionWall(fRealDist, pos, dir);

	float fAddedZ = 0.0f;
	CalcMaxPayneCameraZ(fRealDist, fAddedZ, m_fAngleX);

	if (bCollisionWall)
	{
		m_fCurrentDist += CAMERA_WALL_TRACKSPEED*(fRealDist - m_fCurrentDist);
	}
	else
	{
		m_fCurrentDist += CAMERA_TRACKSPEED*(fRealDist - m_fCurrentDist);
	}

	if (GetLookMode() == ZCAMERA_DEFAULT || GetLookMode() == ZCAMERA_FREEANGLE) {

		m_Position = m_CurrentTarget - dir*m_fCurrentDist;
		m_Position.z += fAddedZ;

		// Lock the camera height if the player has fallen into the abyss
		if (m_Position.z <= DIE_CRITICAL_LINE)
		{
			rvector campos = pTargetCharacter->GetCenterPos() - pTargetCharacter->GetDirection() * 20.0f;
			m_Position.x = campos.x;
			m_Position.y = campos.y;
			m_Position.z = DIE_CRITICAL_LINE;

			if (GetLookMode() == ZCAMERA_DEFAULT)
			{
				rvector tar = pTargetCharacter->GetCenterPos();
				if (tar.z < (DIE_CRITICAL_LINE - 1000.0f)) tar.z = DIE_CRITICAL_LINE - 1000.0f;
				dir = tar - m_Position;
				Normalize(dir);
			}
		}
	}

	v3 up{ 0, 0, 1 };
	if (m_bShocked)
	{
		rvector CameraPos = m_Position + shockoffset;
		RSetCamera(CameraPos, CameraPos + dir, up);
	}
	else
	{
		RSetCamera(m_Position, m_Position + dir, up);
	}

	if (GetLookMode() == ZCAMERA_FREELOOK)
	{
		if (!_isnan(RCameraDirection.x) && !_isnan(RCameraDirection.y) && !_isnan(RCameraDirection.z))
		{
			ZGetGameInterface()->GetCombatInterface()->GetObserver()->SetFreeLookTarget(RCameraDirection);
		}
	}
}
Пример #5
0
bool ZCamera::CheckCollisionWall(float &fRealDist, rvector& pos, rvector& dir)
{
	RBSPPICKINFO bpi;
	float fNearZ = DEFAULT_NEAR_Z;
	rvector pos2 = pos;							// camera pos
	rvector tarpos = pos2 + (dir * fNearZ);		// near pos

	rvector up2, right2;
	up2 = rvector(0.0f, 0.0f, 1.0f);
	right2 = Normalized(CrossProduct(dir, up2));

	up2 = Normalized(CrossProduct(right2, dir));
	right2 = Normalized(CrossProduct(dir, up2));

	float fov = GetFOV();
	float e = 1 / (tanf(fov / 2));
	float fAspect = (float)RGetScreenWidth() / (float)RGetScreenHeight();
	float fPV = (fAspect * fNearZ / e);
	float fPH = (fNearZ / e);

	bool bCollisionWall = false;

	pos2 = pos;
	rvector tar = tarpos + (up2 * fPV);
	rvector dir2;
	dir2 = tar - pos2;
	Normalize(dir2);
	// NOTE: This was using dir as at??? Figure out why
	auto matView = ViewMatrix(pos2, Normalized(dir - pos2), up2);

	if (ZGetGame()->GetWorld()->GetBsp()->Pick(pos2, dir2, &bpi))
	{
		if (Magnitude(tar - bpi.PickPos) < Magnitude(tar - pos2))
		{
			rvector v1, v2, v3;

			v1 = bpi.PickPos;
			v3 = tar;

			if (ZGetGame()->GetWorld()->GetBsp()->Pick(tarpos, up2, &bpi))
			{
				v2 = bpi.PickPos;

				float fD = Magnitude(tarpos - v2);
				if (fD < fPH)
				{
					rvector vv1 = v1 - v2, vv2 = v2 - v3;
					D3DXVECTOR4 rV4;
					vv1 = Transform(vv1, matView);
					v2 = Transform(vv2, matView);

					float fAng = GetAngleOfVectors(vv1, vv2);
					if (fAng < 0.0f) fAng = -fAng;

					if (fAng < PI_FLOAT)
					{
						bCollisionWall = true;

						float fX = fPV - fD;
						float fY = fX * tanf(fAng);

						float fMyRealDist = fRealDist - fY;
						fRealDist = min(fMyRealDist, fRealDist);
					}
				}
			}
		}
	}

	pos2 = pos;
	tar = tarpos + (right2 * fPH);
	dir2 = Normalized(tar - pos2);

	if (ZGetGame()->GetWorld()->GetBsp()->Pick(pos2, dir2, &bpi))
	{
		if (Magnitude(tar - bpi.PickPos) < Magnitude(tar - pos2))
		{
			rvector v1, v2, v3;

			v1 = bpi.PickPos;
			v3 = tar;

			if (ZGetGame()->GetWorld()->GetBsp()->Pick(tarpos, right2, &bpi))
			{
				v2 = bpi.PickPos;

				float fD = Magnitude(tarpos - v2);
				if (fD < fPH)
				{
					rvector vv1 = v1 - v2, vv2 = v2 - v3;
					float fAng = GetAngleOfVectors(vv1, vv2);
					if (fAng < 0.0f) fAng = -fAng;

					if (fAng < (PI_FLOAT / 2))
					{
						bCollisionWall = true;

						float fX = fPH - fD;
						float fY = fX * tanf(fAng);

						float fMyRealDist = fRealDist - fY;
						fRealDist = min(fMyRealDist, fRealDist);
					}
				}
			}
		}
	}

	pos2 = pos;
	tar = tarpos - (up2 * fPV);
	dir2 = Normalized(tar - pos2);
	matView = ViewMatrix(pos2, Normalized(dir2 - pos2), up2);

	if (ZGetGame()->GetWorld()->GetBsp()->Pick(pos2, dir2, &bpi))
	{
		if (Magnitude(tar - bpi.PickPos) < Magnitude(tar - pos2))
		{
			rvector v1, v2, v3;

			v1 = bpi.PickPos;
			v3 = tar;

			if (ZGetGame()->GetWorld()->GetBsp()->Pick(tarpos, -up2, &bpi))
			{
				v2 = bpi.PickPos;

				float fD = Magnitude(tarpos - v2);
				if (fD < fPH)
				{
					bCollisionWall = true;

					rvector vv1 = v1 - v2, vv2 = v2 - v3;
					vv1 = Transform(vv1, matView);
					vv2 = Transform(vv2, matView);

					float fAng = GetAngleOfVectors(vv1, vv2);
					if (fAng < 0.0f) fAng = -fAng;

					if (fAng < (PI_FLOAT / 2))
					{
						float fX = fPV - fD;
						float fY = fX * tanf(fAng);

						float fMyRealDist = fRealDist - fY;
						fRealDist = min(fMyRealDist, fRealDist);
					}
				}
			}
		}
	}

	pos2 = pos;
	tar = tarpos - (right2 * fPH);
	dir2 = Normalized(tar - pos2);

	if (ZGetGame()->GetWorld()->GetBsp()->Pick(pos2, dir2, &bpi))
	{
		if (Magnitude(tar - bpi.PickPos) < Magnitude(tar - pos2))
		{
			rvector v1, v2, v3;

			v1 = bpi.PickPos;
			v3 = tar;

			if (ZGetGame()->GetWorld()->GetBsp()->Pick(tarpos, -right2, &bpi))
			{
				v2 = bpi.PickPos;

				float fD = Magnitude(tarpos - v2);
				if (fD < fPH)
				{
					bCollisionWall = true;

					rvector vv1 = v1 - v2, vv2 = v2 - v3;
					float fAng = GetAngleOfVectors(vv1, vv2);
					if (fAng < 0.0f) fAng = -fAng;

					if (fAng < (PI_FLOAT / 2))
					{
						float fX = fPH - fD;
						float fY = fX * tanf(fAng);

						float fMyRealDist = fRealDist - fY;
						fRealDist = min(fMyRealDist, fRealDist);
					}
				}
			}
		}
	}

	if (fRealDist < 0) fRealDist = 0.0f;

	return bCollisionWall;
}
Пример #6
0
bool MPathTracer::ProcMove(rvector* pNewPos, rvector* pNewDir, rvector* pNewVelocity, rvector* pDir, rvector& Distance, rvector& RealDistance, bool bSmoothArrival)
{
    //if(Velocity.x==0.0f && Velocity.y==0.0f && Velocity.z==0.0f) return true;	// 같은 위치면 도착

    float fDistance = Distance.GetMagnitude();

    rvector TargetDir2D(m_Dir);
    if(Distance.x!=0.0f || Distance.y!=0.0f || Distance.z!=0.0f) {
        TargetDir2D = Distance;
        TargetDir2D.z = 0;
        TargetDir2D.Normalize();
    }
    if(pDir!=NULL) {
        _ASSERT(pDir->z==0.0f);
        // 방향 설정은 보정된 Distance가 아닌 RealDistance에 의존한다.
        float fRealDistance = RealDistance.GetMagnitude();
        if(fRealDistance<=m_Property.fMaxVelocity*m_fDirectionSettingConstant) {
            float fDirectionWeightConstant = max(min((1-fRealDistance/(m_Property.fMaxVelocity*m_fDirectionSettingConstant)), 1), 0);
            TargetDir2D = Normalize(InterpolatedVector(TargetDir2D, Normalize(*pDir), fDirectionWeightConstant));
        }
    }

    // 회전
    ////////////////////////////////////////////////////////////
    float fDiffAngle = GetAngleOfVectors(TargetDir2D, m_Dir);
    float fRotateAngle = fDiffAngle;

    float fRotatePercent = 1.0f;

    // 회전 가/감속
    if(fDiffAngle>0) {
        m_fAngularVelocity = min(m_Property.fMaxRotationVelocity, m_fAngularVelocity + m_Property.fRotationAcceleration);
        if(fabs(fDiffAngle)<m_Property.fMaxRotationVelocity*m_nAgularDecelerationConstant) {
            m_fAngularVelocity = min(m_fAngularVelocity, fDiffAngle/m_nAgularDecelerationConstant);
        }
    }
    else if(fDiffAngle<0) {
        m_fAngularVelocity = max(-m_Property.fMaxRotationVelocity, m_fAngularVelocity - m_Property.fRotationAcceleration);
        if(fabs(fDiffAngle)<m_Property.fMaxRotationVelocity*m_nAgularDecelerationConstant) {
            m_fAngularVelocity = max(m_fAngularVelocity, fDiffAngle/m_nAgularDecelerationConstant);
        }
    }

    if(fDiffAngle!=0.0f) fRotatePercent = m_fAngularVelocity/fDiffAngle;

    rvector NewDir = Normalize(InterpolatedVector(m_Dir, Normalize(TargetDir2D), fRotatePercent));

    // 결과 값
    //m_fResultRotatePercent = fRotateAngle / m_Property.fMaxRotationVelocity;
    m_fResultRotatePercent = GetAngleOfVectors(NewDir, m_Dir) / m_Property.fMaxRotationVelocity;	// 버그로 인해 실제 계산값을 입력

    bool bArriveAngle = false;
    if(fRotatePercent==1.0f) bArriveAngle = true;

    // 가속 & 이동
    ////////////////////////////////////////////////////////////

    // 현재 가능 가속도 계산
    rvector Acceleration = Clip(Distance-m_Velocity, m_Property.fAcceleration);
    //rvector Acceleration = NewDir*m_Property.fAcceleration;
    float fAcceleration = Acceleration.GetMagnitude();
    if(fAcceleration>=0.0f) {
        if(m_bDirectionSpeed==true) {	// 방향에 따른 가감속
            fAcceleration -= (fAcceleration*max(min((float)fabs(fDiffAngle)/pi, 1), 0)*m_nDirectionalSpeedContant);
            Acceleration = Normalize(Acceleration)*fAcceleration;
        }
    }

    // 현재 가능 속도 계산
    rvector NewVelocity = m_Velocity + Acceleration;
    //float fNewVelocity = NewVelocity.GetMagnitude();
    Clip(&NewVelocity, m_Property.fMaxVelocity);	// Clip

    bool bArrive = false;
    // 거리에 따른 속도 조절
    float fNewVelocity = NewVelocity.GetMagnitude();
    if(bSmoothArrival==true && fDistance<=m_Property.fMaxVelocity*m_nDecelerationConstant) {
        float t = fDistance/(m_Property.fMaxVelocity*m_nDecelerationConstant);
        //_ASSERT(m_nDecelerationCurveConstant>=1.0f);
        fNewVelocity = min(fNewVelocity, m_Property.fMaxVelocity*(float)pow((t), m_nDecelerationCurveConstant));
        NewVelocity = Normalize(NewVelocity)*fNewVelocity;
        if(fNewVelocity<=m_Property.fMaxVelocity*m_fArrivalConstant) bArrive = true;
    }
    else if(fNewVelocity>=fDistance) bArrive = true;

    // New Values
    *pNewVelocity = NewVelocity;
    *pNewDir = NewDir;
    *pNewPos = m_Pos+NewVelocity;

    return bArrive;
}