Beispiel #1
0
	virtual CFixedVector3D GetPreviousPosition() 
	{ 
		if (!m_InWorld) 
		{ 
			LOGERROR(L"CCmpPosition::GetPreviousPosition called on entity when IsInWorld is false"); 
			return CFixedVector3D(); 
		} 

		entity_pos_t baseY; 
		if (m_RelativeToGround) 
		{ 
			CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY); 
			if (cmpTerrain) 
				baseY = cmpTerrain->GetGroundLevel(m_PrevX, m_PrevZ); 

			if (m_Floating) 
			{ 
				CmpPtr<ICmpWaterManager> cmpWaterMan(GetSimContext(), SYSTEM_ENTITY); 
				if (cmpWaterMan) 
					baseY = std::max(baseY, cmpWaterMan->GetWaterLevel(m_PrevX, m_PrevZ)); 
			} 
		} 

		return CFixedVector3D(m_PrevX, baseY + m_YOffset, m_PrevZ); 
	} 
Beispiel #2
0
	virtual CFixedVector3D GetPreviousPosition()
	{
		if (!m_InWorld)
		{
			LOGERROR("CCmpPosition::GetPreviousPosition called on entity when IsInWorld is false");
			return CFixedVector3D();
		}

		return CFixedVector3D(m_PrevX, GetHeightFixed(), m_PrevZ);
	}
Beispiel #3
0
	virtual void Init(const CParamNode& paramNode)
	{
		std::wstring anchor = paramNode.GetChild("Anchor").ToString();
		if (anchor == L"pitch")
			m_AnchorType = PITCH;
		else if (anchor == L"pitch-roll")
			m_AnchorType = PITCH_ROLL;
		else if (anchor == L"roll")
			m_AnchorType = ROLL;
		else
			m_AnchorType = UPRIGHT;

		m_InWorld = false;

		m_LastYDifference = entity_pos_t::Zero();
		m_Y = paramNode.GetChild("Altitude").ToFixed();
		m_RelativeToGround = true;
		m_Floating = paramNode.GetChild("Floating").ToBool();

		m_RotYSpeed = paramNode.GetChild("TurnRate").ToFixed().ToFloat();

		m_RotX = m_RotY = m_RotZ = entity_angle_t::FromInt(0);
		m_InterpolatedRotX = m_InterpolatedRotY = m_InterpolatedRotZ = 0.f;
		m_LastInterpolatedRotX = m_LastInterpolatedRotZ = 0.f;
		m_Territory = INVALID_PLAYER;

		m_TurretParent = INVALID_ENTITY;
		m_TurretPosition = CFixedVector3D();

		m_ActorFloating = false;

		m_EnabledMessageInterpolate = false;
	}
Beispiel #4
0
	virtual CFixedVector3D GetRotation()
	{
		entity_angle_t y = m_RotY;
		if (m_TurretParent != INVALID_ENTITY)
		{
			CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_TurretParent);
			if (cmpPosition)
				y += cmpPosition->GetRotation().Y;
		}
		return CFixedVector3D(m_RotX, y, m_RotZ);
	}
Beispiel #5
0
	virtual CFixedVector3D GetRotation()
	{
		return CFixedVector3D(m_RotX, m_RotY, m_RotZ);
	}
	virtual void LaunchProjectileAtEntity(entity_id_t source, entity_id_t target, fixed speed, fixed gravity)
	{
		LaunchProjectile(source, CFixedVector3D(), target, speed, gravity);
	}
Beispiel #7
0
	virtual CFixedVector3D PickSpawnPoint(entity_id_t spawned)
	{
		// Try to find a free space around the building's footprint.
		// (Note that we use the footprint, not the obstruction shape - this might be a bit dodgy
		// because the footprint might be inside the obstruction, but it hopefully gives us a nicer
		// shape.)

		const CFixedVector3D error(fixed::FromInt(-1), fixed::FromInt(-1), fixed::FromInt(-1));

		CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
		if (!cmpPosition || !cmpPosition->IsInWorld())
			return error;

		CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
		if (!cmpObstructionManager)
			return error;

		entity_pos_t spawnedRadius;
		ICmpObstructionManager::tag_t spawnedTag;

		CmpPtr<ICmpObstruction> cmpSpawnedObstruction(GetSimContext(), spawned);
		if (cmpSpawnedObstruction)
		{
			spawnedRadius = cmpSpawnedObstruction->GetUnitRadius();
			spawnedTag = cmpSpawnedObstruction->GetObstruction();
		}
		// else use zero radius

		// Get passability class from UnitMotion
		CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), spawned);
		if (!cmpUnitMotion)
			return error;

		ICmpPathfinder::pass_class_t spawnedPass = cmpUnitMotion->GetPassabilityClass();
		CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
		if (!cmpPathfinder)
			return error;
		
		CFixedVector2D initialPos = cmpPosition->GetPosition2D();
		entity_angle_t initialAngle = cmpPosition->GetRotation().Y;

		// Max spawning distance in tiles
		const i32 maxSpawningDistance = 4;

		if (m_Shape == CIRCLE)
		{
			// Expand outwards from foundation
			for (i32 dist = 0; dist <= maxSpawningDistance; ++dist)
			{
				// The spawn point should be far enough from this footprint to fit the unit, plus a little gap
				entity_pos_t clearance = spawnedRadius + entity_pos_t::FromInt(2 + (int)TERRAIN_TILE_SIZE*dist);
				entity_pos_t radius = m_Size0 + clearance;

				// Try equally-spaced points around the circle in alternating directions, starting from the front
				const i32 numPoints = 31 + 2*dist;
				for (i32 i = 0; i < (numPoints+1)/2; i = (i > 0 ? -i : 1-i)) // [0, +1, -1, +2, -2, ... (np-1)/2, -(np-1)/2]
				{
					entity_angle_t angle = initialAngle + (entity_angle_t::Pi()*2).Multiply(entity_angle_t::FromInt(i)/(int)numPoints);

					fixed s, c;
					sincos_approx(angle, s, c);

					CFixedVector3D pos (initialPos.X + s.Multiply(radius), fixed::Zero(), initialPos.Y + c.Multiply(radius));

					SkipTagObstructionFilter filter(spawnedTag); // ignore collisions with the spawned entity
					if (cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Z, spawnedRadius, spawnedPass) == ICmpObstruction::FOUNDATION_CHECK_SUCCESS)
						return pos; // this position is okay, so return it
				}
			}
		}
		else
		{
			fixed s, c;
			sincos_approx(initialAngle, s, c);

			// Expand outwards from foundation
			for (i32 dist = 0; dist <= maxSpawningDistance; ++dist)
			{
				// The spawn point should be far enough from this footprint to fit the unit, plus a little gap
				entity_pos_t clearance = spawnedRadius + entity_pos_t::FromInt(2 + (int)TERRAIN_TILE_SIZE*dist);

				for (i32 edge = 0; edge < 4; ++edge)
				{
					// Try equally-spaced points along the edge in alternating directions, starting from the middle
					const i32 numPoints = 9 + 2*dist;

					// Compute the direction and length of the current edge
					CFixedVector2D dir;
					fixed sx, sy;
					switch (edge)
					{
					case 0:
						dir = CFixedVector2D(c, -s);
						sx = m_Size0;
						sy = m_Size1;
						break;
					case 1:
						dir = CFixedVector2D(-s, -c);
						sx = m_Size1;
						sy = m_Size0;
						break;
					case 2:
						dir = CFixedVector2D(s, c);
						sx = m_Size1;
						sy = m_Size0;
						break;
					case 3:
						dir = CFixedVector2D(-c, s);
						sx = m_Size0;
						sy = m_Size1;
						break;
					}
					CFixedVector2D center = initialPos - dir.Perpendicular().Multiply(sy/2 + clearance);
					dir = dir.Multiply((sx + clearance*2) / (int)(numPoints-1));

					for (i32 i = 0; i < (numPoints+1)/2; i = (i > 0 ? -i : 1-i)) // [0, +1, -1, +2, -2, ... (np-1)/2, -(np-1)/2]
					{
						CFixedVector2D pos (center + dir*i);

						SkipTagObstructionFilter filter(spawnedTag); // ignore collisions with the spawned entity
						if (cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, spawnedRadius, spawnedPass) == ICmpObstruction::FOUNDATION_CHECK_SUCCESS)
							return CFixedVector3D(pos.X, fixed::Zero(), pos.Y); // this position is okay, so return it
					}
				}
			}
		}

		return error;
	}