예제 #1
0
void Level::SetTargetPos( Enemies enemies )
{
	for( Enemies::iterator it = enemies.begin(); it != enemies.end(); ++it )
	{
		(*it)->SetTargetPos( GetTargetPos() );
	}
}
예제 #2
0
//------------------------------------------------------------------------
bool CGunTurret::IsTargetShootable(IEntity *pTarget)
{
	// raycast shootability check
	Vec3 pos = m_fireHelper.empty() ? GetWeaponPos() : GetSlotHelperPos(eIGS_ThirdPerson, m_fireHelper.c_str(), true);
	Vec3 tpos = GetTargetPos(pTarget);
	Vec3 dir = tpos - pos;

	bool shootable = RayCheck(pTarget, pos, dir);

	if(!shootable)
	{
		// fallback for actors
		// todo: also use this for shooting pos!
		CActor *pActor = GetActor(pTarget->GetId());

		if(pActor && pActor->GetMovementController())
		{
			SMovementState state;
			pActor->GetMovementController()->GetMovementState(state);
			dir = state.eyePosition - pos;
			shootable = RayCheck(pTarget, pos, dir);
		}
	}

	return shootable;
}
예제 #3
0
//------------------------------------------------------------------------
IEntity *CGunTurret::GetClosestTACShell()
{
	if(g_pGame->GetCVars()->i_auto_turret_target_tacshells == 0)
		return NULL;

	float r = m_turretparams.tac_range;

	if(r == 0.f)
		return NULL;

	Vec3 pos = GetWeaponPos();
	SProjectileQuery pquery;
	pquery.box = AABB(Vec3(pos.x-r,pos.y-r,pos.z-r),Vec3(pos.x+r,pos.y+r,pos.z+r));
	int count = g_pGame->GetWeaponSystem()->QueryProjectiles(pquery);

	ETargetClass closest = eTC_NotATarget;
	float closestDistSq = r*r;
	IEntity *pClosest = 0;

	for(int i=0; i<pquery.nCount; ++i)
	{
		IEntity *pEntity = pquery.pResults[i];

		if(!pEntity || pEntity == GetEntity())
			continue;

		ETargetClass t_class = GetTargetClass(pEntity);

		if(t_class == eTC_NotATarget)
			continue;

		pos = GetTargetPos(pEntity);
		float distSq=(pos-GetWeaponPos()).len2();

		if(closest>=t_class && distSq>closestDistSq)
			continue;

		float yaw, pitch;
		GetTargetAngles(pos,yaw,pitch);

		if(!IsTargetAimable(yaw,pitch))
			continue;

		bool canShoot = IsTargetShootable(pEntity);

		if(!canShoot)
			t_class = eTC_NotATarget;

		if(distSq < closestDistSq || (t_class>=closest))
		{
			closestDistSq = distSq;
			closest = t_class;
			pClosest = pEntity;
		}
	}

	return pClosest;
}
예제 #4
0
	void CalcFiringPosition(SActivationInfo* pActInfo, IWeapon* pWeapon)
	{
		Vec3 realTargetPos = GetTargetPos( pActInfo );
		m_firingPos = realTargetPos;
		
		float acc = GetPortFloat( pActInfo, IN_ACCURACY );
		if (acc<1)
		{
			bool itHits = cry_frand() < acc;
			if (!itHits)
			{
				// what this code does is: 
				// - in the plane perpendicular to the shooting vector, and located at the target, it builds a vector, centered in the target, and rotates it to point in a random direction, but always in the plane
				// - then it moves along that vector, a random distance (error distance)
				// - and that is the final to-fire position
			
				const float MAX_ERROR_LENGTH = 6.f;  // meters
				const float MIN_ERROR_ANGLE = 2.f; // degrees
				const float MAX_ERROR_ANGLE = 5.f; // degrees

				// error angle from weapon to target				
				float errorAngle = MIN_ERROR_ANGLE + (MAX_ERROR_ANGLE-MIN_ERROR_ANGLE) * cry_frand();
				
				// 2d angle, in the plane normal to the vector from weapon to target.
				float dirErrorAngle = cry_frand() * 360;
				
				// could be done with just 1 sqrt instead 2, but is not really worth it here.
				Vec3 vecToTarget = pActInfo->pEntity->GetPos() - realTargetPos;
				Vec3 vecToTargetNorm = vecToTarget.GetNormalizedSafe();
				Vec3 dirError2D = vecToTargetNorm.GetOrthogonal();
				dirError2D = dirError2D.GetRotated( vecToTargetNorm, DEG2RAD(dirErrorAngle) );
				
				float dist = vecToTarget.len();
				float errorLen = std::min( dist * tanf( DEG2RAD(errorAngle) ), MAX_ERROR_LENGTH );
				
				m_firingPos = realTargetPos + ( dirError2D * errorLen );
				
				#ifdef DEBUG_NODEFIREWEAPON
				posTarget = realTargetPos;
				posOrig = pActInfo->pEntity->GetPos();
				posShot = m_firingPos;
				#endif
			}
		}
		if (GetPortBool( pActInfo, IN_ALIGNTOTARGET ))
		{     
			UpdateWeaponTM( pActInfo, m_firingPos );
			m_lastPos = pActInfo->pEntity->GetWorldPos();
			m_lastRotation = pActInfo->pEntity->GetWorldRotation();
		}
		pWeapon->SetDestination( m_firingPos );
	}
예제 #5
0
//------------------------------------------------------------------------
//chr safe to remove?
bool CGunTurret::IsTargetCloaked(IActor *pActor) const
{
	// cloak check
	if(m_turretparams.find_cloaked)
		return false;

	bool cloaked = false;

	// if destinationId assigned, target can always be found
	if(m_destinationId && pActor->GetEntityId() == m_destinationId)
		return false;

	if(cloaked && m_turretparams.light_fov != 0.f)
	{
		// if cloaked, target can only be found with searchlight
		// check if target inside light cone
		const Matrix34 &weaponTM = GetEntity()->GetSlotWorldTM(eIGS_ThirdPerson);
		Vec3 wpos(weaponTM.GetTranslation());
		Vec3 wdir(weaponTM.GetColumn1());
		Vec3 tpos(GetTargetPos(pActor->GetEntity()));

		float epsilon = 0.8f;
		Quat rot = Quat::CreateRotationAA(epsilon*0.5f*DEG2RAD(m_turretparams.light_fov), weaponTM.GetColumn2());
		Vec3 a = wpos + m_turretparams.mg_range*(wdir*rot);
		Vec3 b = wpos + m_turretparams.mg_range*(wdir*rot.GetInverted());
		bool inside = Overlap::PointInTriangle(tpos, wpos, a, b, weaponTM.GetColumn2());

		if(inside)
		{
			rot = Quat::CreateRotationAA(0.5f*DEG2RAD(m_turretparams.light_fov), weaponTM.GetColumn0());
			a = wpos + m_turretparams.mg_range*(wdir*rot);
			b = wpos + m_turretparams.mg_range*(wdir*rot.GetInverted());
			inside = Overlap::PointInTriangle(tpos, wpos, a, b, weaponTM.GetColumn0());
		}

		cloaked = !inside;

		if(g_pGameCVars->i_debug_turrets == eGTD_Search)
		{
			IRenderAuxGeom *pGeom = gEnv->pRenderer->GetIRenderAuxGeom();
			pGeom->SetRenderFlags(e_Def3DPublicRenderflags);
			float color[] = {1,1,1,1};
			Vec3 points[] = {wpos, a, b};
			pGeom->DrawPolyline(points, 3, true, ColorB(0,255,0,255));

			if(inside)
				gEnv->pRenderer->Draw2dLabel(200,200,1.4f,color,false,"target inside cone");
		}
	}

	return cloaked;
}
예제 #6
0
파일: Papyrus.cpp 프로젝트: himika/LockOn
	// プレイヤーを対象に向ける
	static void LookAtRef(TESObjectREFR* akRef, float wait)
	{
		if (akRef == NULL)
			return;
		// akRef->Is3DLoaded()
		if (akRef->GetNiNode() == NULL)
			return;

		NiPoint3 targetPos;
		if (!GetTargetPos(akRef, &targetPos))
			return;

		LookAt(targetPos.x, targetPos.y, targetPos.z, wait);
	}
예제 #7
0
파일: CMob.cpp 프로젝트: CAIOVA7X/W2PP
int  CMob::StandingByProcessor(void)
{
	int rt = FALSE;

	if (RouteType == 5 || Affect[0].Type == 24)
	{
		int Face = MOB.Equip[0].sIndex;

		if (Leader == 0 && (Affect[0].Type == 24 || Face >= 315 && Face <= 345))
		{
				rt |= 0x100;
				return rt;
		}

		if (Leader <= 0 || Leader >= MAX_USER)
		{
			rt |= 1;
			return rt;
		}

		if (Affect[0].Type == 24 || Face >= 315 && Face <= 345)
		{
			int summoner = Summoner;

			if (summoner <= 0 || summoner >= MAX_USER)
			{
				rt |= 1;
				return rt;
			}

			int _leader = 0;
			if (Leader == summoner)
				_leader = 1;

			for (int i = 0; i < MAX_PARTY; ++i)
			{
				if (pMob[Leader].PartyList[i] == summoner)
					_leader = 1;
			}

			if (_leader == 0)
			{
				rt |= 1;
				return rt;
			}

			if (pUser[summoner].Mode != USER_PLAY)
			{
				rt |= 1;
				return rt;
			}

			int Distance = BASE_GetDistance(TargetX, TargetY, pMob[summoner].TargetX, pMob[summoner].TargetY);
			if (Distance >= 13)
			{
				NextX = pMob[summoner].TargetX;
				NextY = pMob[summoner].TargetY;
				rt = rt | 0x02;
				return rt;
			}

			if (Distance <= 4 || Distance >= 13)
				return rt;

			SegmentX = pMob[summoner].TargetX;
			SegmentY = pMob[summoner].TargetY;

			GetTargetPos(summoner);
			rt = rt | 0x01;
			return rt;
		}

		rt = rt |= 1;
		return rt;
	}
	
	else
	{
		if (Leader == 0)
		{
			int enemy = GetEnemyFromView();

			if (enemy && TargetX <= SegmentX + HALFGRIDX && TargetX >= SegmentX - HALFGRIDX && TargetY >= SegmentY - HALFGRIDY && TargetY <= SegmentY + HALFGRIDY)
				return enemy | 0x10000000;
			
		}
		
		if (RouteType == 6 && TargetX == SegmentX && TargetY == SegmentY)
			return 0;

		if (SegmentX == TargetX && SegmentY == TargetY)
		{
			if(SegmentProgress == 4 && RouteType == 3)
			{
				if(WaitSec <= 0)
					return 0x10000;
				else
					WaitSec -= 6;

				return 0;
			}
			if (WaitSec <= 0 || RouteType == 6)
			{
				int Seg = SegmentWait[SegmentProgress];
				if (Seg > 0)
				{
					WaitSec = Seg;
					return 0;
				}
			}
			else
			{
				WaitSec -= 6;
				if (WaitSec > 0)
				{
					if (RouteType && TargetX != SegmentListX[0] || TargetY != SegmentListY[0])
					{
						if (MOB.BaseScore.AttackRun & 0xF)
							return rt | 0x10;

						return 0;
					}
					else
						return 0;
				}
				WaitSec = 0;
			}
			int SetSeg = SetSegment();
			
			if (SetSeg == 1)
				return 0;

			if (SetSeg == 2)
				return rt | 1;

			if (SetSeg == 0x10)
				return rt | 1;
		}

		GetNextPos(0);

		if (NextX != TargetX || NextY != TargetY)
			return rt | 1;

		else
		{
			SetSegment();
			return rt;
		}
	}
	return rt;
}
예제 #8
0
void plCameraModifier1::Update()
{
    // update the brain

    // this freeze thing is a useful debugging tool...  
    if (plVirtualCam1::Instance()->freeze)
        return;
    
    if (GetBrain())
    {
        if (fUpdateBrainTarget && fTarget->GetCoordinateInterface()) // if we need to update the brain and the target is loaded
        {
            fUpdateBrainTarget = false;
            GetBrain()->AddTarget(); // update the brain's target
        }

        bool moveInSub = !(GetBrain()->HasFlag(plCameraBrain1::kIgnoreSubworldMovement));

        if (moveInSub && GetBrain()->GetSubject())
        {
            plKey worldKey = nil;

            // First check if this is a physical.  If so, grab the subworld from that
            if (GetBrain()->GetSubject()->GetSimulationInterface())
            {
                plPhysical* phys = GetBrain()->GetSubject()->GetSimulationInterface()->GetPhysical();
                if (phys)
                    worldKey = phys->GetWorldKey();
            }
            // Also, check if this is an avatar.  They don't have physicals, you
            // have to ask the avatar controller for the subworld key.
            if (!worldKey)
            {
                plKey subject = plKey(GetBrain()->GetSubject()->GetKey());
                plArmatureMod* armMod = plAvatarMgr::FindAvatar(subject);
                if (armMod && armMod->GetController() )
                    worldKey = armMod->GetController()->GetSubworld();
            }

            if (worldKey)
            {
                // this picks up and moves the camera to it's previous subworld coordinate (so the subworld isn't moving out from underneath us)
                hsMatrix44 l2w, w2l;
                plSceneObject* so = plSceneObject::ConvertNoRef(worldKey->ObjectIsLoaded());
                if (so)
                {
                    l2w = so->GetLocalToWorld();
                    w2l = so->GetWorldToLocal();

                    if (fInSubLastUpdate)
                    {
                        if (!(fLastSubPos == fFrom && fLastSubPOA == fAt))
                        {
                            SetTargetPos(l2w * fLastSubPos);
                            SetTargetPOA(l2w * fLastSubPOA);
                        }
                    }
                    else
                    {
                        fInSubLastUpdate = true;
                    }
                    GetBrain()->Update();
                    fLastSubPos = w2l * GetTargetPos();
                    fLastSubPOA = w2l * GetTargetPOA();
                }
                return;
            }
            else
            {
                fInSubLastUpdate = false;
            }
        }
        GetBrain()->Update();
        fLastSubPos = GetTargetPos();
        fLastSubPOA = GetTargetPOA();
    }
}   
예제 #9
0
void Level::GoalReached( boost::shared_ptr<Enemy> e )
{
	FreeTargetPos( e->GetTargetPos() );
	e->SetTargetPos( GetTargetPos() );
}
예제 #10
0
파일: Papyrus.cpp 프로젝트: himika/LockOn
	// 一定距離内に居るアクターをすべて返す
	VMArray<Actor*> FindCloseActor(float distance, UInt32 sortOrder)
	{
		enum Order {
			kSortOrder_distance		= 0,		// 距離が近い順
			kSortOrder_crosshair	= 1,		// クロスヘアに近い順
			kSortOrder_zaxis_clock	= 2,		// Z軸時計回り
			kSortOrder_zaxis_rclock	= 3,		// Z軸逆時計回り
			kSortOrder_invalid      = 4
		};

		double fovThreshold = (double)PlayerCamera::GetSingleton()->worldFOV / 180.0 * M_PI /2;

		VMArray<Actor*> result;
		result.arr = NULL;

		tArray<UInt32>* actorHandles = &(*s_cellInfo)->actorHandles;
		if (actorHandles->count == 0)
			return result;

		std::vector<std::pair<double, Actor*>> vec;
		vec.reserve(actorHandles->count);

		PlayerCharacter* player = *g_thePlayer;
		NiPoint3 camPos;
		GetCameraPos(&camPos);

		UInt32 handle;
		size_t i = 0;
		while (actorHandles->GetNthItem(i++, handle))
		{
			TESObjectREFR* ref = NULL;
			if (handle != *g_invalidRefHandle)
				LookupREFRByHandle(&handle, &ref);

			if (ref && ref->formType == kFormType_Character)
			{
				Actor* actor = (Actor*)ref;
				NiPoint3 pos;
				GetTargetPos(actor, &pos);
				double dx = pos.x - camPos.x;
				double dy = pos.y - camPos.y;
				double dz = pos.z - camPos.z;
				double dd = sqrt(dx*dx + dy*dy + dz*dz);

				if (distance <= 0 || dd <= distance)
				{
					double point;
					NiPoint3 cameraAngle;
					GetCameraAngle(&cameraAngle);
					double angleZ = NormalRelativeAngle(atan2(dx, dy) - cameraAngle.z);
					double angleX = NormalRelativeAngle(atan2(-dz, sqrt(dx*dx + dy*dy)) - cameraAngle.x);
					
					if (abs(angleZ) < fovThreshold)
					{
						switch (sortOrder)
						{
						case kSortOrder_distance:
							point = dd;
							break;
						case kSortOrder_crosshair:
							point = sqrt(angleZ*angleZ + angleX*angleX);
							break;
						case kSortOrder_zaxis_clock:
							point = NormalAbsoluteAngle(atan2(dx, dy) - cameraAngle.z);
							break;
						case kSortOrder_zaxis_rclock:
							point = 2*M_PI - NormalAbsoluteAngle(atan2(dx, dy) - cameraAngle.z);
							break;
						default:
							point = 0;
							break;
						}

						if (point >= 0)
						{
							vec.push_back(std::make_pair(point, actor));
						}
					}
				}
			}
		}

		if (vec.size() == 0)
			return result;

		if (sortOrder < kSortOrder_invalid)
			std::sort(vec.begin(), vec.end());

		// Papyrusに返す配列を確保
		if (result.Allocate(vec.size()))
		{
			for (i = 0; i < vec.size(); i++)
			{
				result.Set(&vec[i].second, i);
			}
		}

		return result;
	}
예제 #11
0
//------------------------------------------------------------------------
IEntity *CGunTurret::GetClosestTarget()
{
	float r = MAX(m_turretparams.mg_range, m_turretparams.rocket_range);
	Vec3 pos = GetWeaponPos();

	IEntity	*pClosest = 0;

	float	closestDistSq=sqr(r);
	ETargetClass closest = eTC_NotATarget;

	SEntityProximityQuery query;
	query.box = AABB(Vec3(pos.x-r,pos.y-r,pos.z-r),Vec3(pos.x+r,pos.y+r,pos.z+r));
	int count=gEnv->pEntitySystem->QueryProximity(query);

	for(int i=0; i<query.nCount; i++)
	{
		IEntity *pEntity = query.pEntities[i];

		if(!pEntity || pEntity == GetEntity())
			continue;

		// check parent (and siblings) the turret might be linked to, to not attack them
		if(IEntity *pParent = GetEntity()->GetParent())
		{
			if(pEntity == pParent)
				continue;

			int nChildren = pParent->GetChildCount();

			for(int j=0; j<nChildren; ++j)
			{
				if(pParent->GetChild(j) == pEntity)
					continue;
			}
		}

		ETargetClass t_class = GetTargetClass(pEntity);

		if(t_class == eTC_NotATarget)
			continue;

		Vec3 tpos = GetTargetPos(pEntity);

		if(!IsInRange(tpos,t_class))
			continue;

		float distSq=(tpos-pos).len2();

		if(closest>=t_class && distSq>closestDistSq)
			continue;

		bool canShoot = IsTargetShootable(pEntity);

		if(!canShoot)
			t_class = eTC_NotATarget;
		else if(distSq < closestDistSq || (t_class>=closest))
		{
			closestDistSq = distSq;
			closest = t_class;
			pClosest = pEntity;
		}
	}

	if(closest==eTC_NotATarget && !m_turretparams.surveillance)
		return 0;

	return pClosest;
}
예제 #12
0
//------------------------------------------------------------------------
Vec3 CGunTurret::PredictTargetPos(IEntity *pTarget, bool sec)//sec - weapon to use
{
	pTarget = ResolveTarget(pTarget);
	Vec3 tpos = GetTargetPos(pTarget);

	if(m_turretparams.search_only || m_turretparams.prediction == 0.f)
		return tpos;

	IPhysicalEntity *pe = pTarget->GetPhysics();
	pe_status_dynamics dyn;

	if(!pe || !pe->GetStatus(&dyn))
		return tpos;

	Vec3 vel = dyn.v;
	Vec3 acc = dyn.a;
	float a = acc.len();

	if(a < 0.01f)
		a = 0.f;
	else
		acc /= a;

	Vec3 vpos = GetWeaponPos();
	Vec3 dist = tpos-vpos;
	float d = dist.len();

	if(d < 0.01f)
		return tpos;

	dist /= d;
	float d_speed = vel*dist;

	float speed = 800.0f;
	const SAmmoParams *ammo = g_pGame->GetWeaponSystem()->GetAmmoParams(GetFireMode(0)->GetAmmoType());

	if(!ammo)
		return tpos;

	if(ammo->physicalizationType == ePT_None)
		return tpos;

	speed = ammo->speed;

	float time_to = d/max(1.f, speed-d_speed);

	// MR: clamped acc prediction to reduce jerkyness when targetting objects that are able
	// to do near-instant velocity changes (like players)
	a = min(a, 25.f);

	Vec3 delta = vel*(time_to) + 0.5f*a*acc*time_to*time_to;
	delta *= m_turretparams.prediction;

	if(g_pGameCVars->i_debug_turrets == eGTD_Prediction)
	{
		IPersistantDebug *pDebug = gEnv->pGame->GetIGameFramework()->GetIPersistantDebug();
		pDebug->Begin("CGunTurret::PredictTargetPos", false);
		pDebug->AddSphere(tpos+delta, 0.2f, ColorF(1,0,0,1), 1.f);
		gEnv->pRenderer->DrawLabel(vpos, 1.4f, "Predict %s: speed %.1f (dspeed %.1f), acc %.1f, time %.1f", pTarget->GetName(), vel.len(), d_speed, a, time_to);
	}

	return tpos+delta;
}