Пример #1
0
void MoverGroup::sortMovers(
	int32_t numMoversInGroup, MoverPtr* moverList, Stuff::Vector3D destination)
{
	Mover::sortList->clear();
	for (size_t i = 0; i < numMoversInGroup; i++)
	{
		int32_t index = -1;
		float dist	= (float)3.48E+37;
		if (moverList[i])
		{
			index = i;
			Stuff::Vector3D resultVector;
			resultVector.Subtract(moverList[i]->getPosition(), destination);
			dist = resultVector.GetLength();
		}
		Mover::sortList->setId(i, index);
		Mover::sortList->setValue(i, dist);
	}
	Mover::sortList->sort(false);
	for (i = 0; i < numMoversInGroup; i++)
	{
		int32_t moverIndex = Mover::sortList->getId(i);
		if (moverIndex != -1)
			moverList[moverIndex]->selectionIndex = i;
	}
}
Пример #2
0
//---------------------------------------------------------------------------
long SoundSystem::playDigitalSample (unsigned long sampleId, Stuff::Vector3D pos, bool allowDupes)
{
	if (useSound && allowDupes || (!isPlayingSample(sampleId) && !allowDupes))
	{
		if (sampleId >= numSoundBites)
			return(-1);
			
		long ourChannel = findOpenChannel(1,SUPPORT_CHANNEL);
	
		if (ourChannel != -1)
		{
			float distanceVolume = 1.0f;
			float panVolume = 0.0f;
			if (eye && (pos.z != -9999.0f))
			{
				Stuff::Vector3D distance;
				distance.Subtract(eye->getPosition(),pos);
				float dist = distance.GetApproximateLength();
				if (dist < FALLOFF_DISTANCE)
					distanceVolume = (FALLOFF_DISTANCE - dist) / FALLOFF_DISTANCE;
				else
					return -1;		//Do not play sound.  TOO far away!!

				//Figure out where in stereo field to play.
				OppRotate(distance,eye->getRotation().y);

				panVolume = distance.x / (FALLOFF_DISTANCE * 0.5f);
				if (panVolume > 1.0f)
					panVolume = 1.0f;
				else if (panVolume < -1.0f)
					panVolume = -1.0f;
			}

			float vol = sounds[sampleId].volume * distanceVolume;
			if (vol > 1.0f)
				vol = 1.0f;
			else if (vol <= 0.0f)		//No VOlume.  DON't PLAY!
				return -1;

			gosAudio_SetChannelSlider(ourChannel,gosAudio_Panning, panVolume);
			gosAudio_SetChannelSlider(ourChannel,gosAudio_Volume, (digitalMasterVolume * vol * SFXVolume)) ;
			channelSampleId[ourChannel] = sampleId;
			channelInUse[ourChannel] = TRUE;
				
			if (sounds[sampleId].biteData && sounds[sampleId].resourceHandle)
			{
				gosAudio_AssignResourceToChannel( ourChannel, sounds[sampleId].resourceHandle );
				gosAudio_SetChannelPlayMode(ourChannel, gosAudio_PlayOnce);
			}
			
			return(ourChannel);
		}
	}

	return(-1);
}
Пример #3
0
//---------------------------------------------------------------------------
float world_angle_between (Stuff::Vector3D &v1, Stuff::Vector3D &v2) 
{
	Stuff::Vector3D facingVec(0.0f,1.0f,0.0f);

	Stuff::Vector3D goalVec;
	goalVec.Subtract(v1, v2);

	float angle = angle_from(facingVec, goalVec);

	//--------------------------------
	// Get sign of relative angle.
	float z = (facingVec.x * goalVec.y) - (facingVec.y * goalVec.x);
	if (z > 0.0f)
		angle = -angle;
	
	return(angle);
}
Пример #4
0
//---------------------------------------------------------------------------
void Terrain::geometry (void)
{
	//---------------------------------------------------------------------
	leastZ = 1.0f;leastW = 1.0f;
	mostZ = -1.0f; mostW = -1.0;
	leastWY = 0.0f; mostWY = 0.0f;

	//-----------------------------------
	// Transform entire list of vertices
	VertexPtr currentVertex = vertexList;

	Stuff::Vector3D cameraPos;
	cameraPos.x = -eye->getCameraOrigin().x;
	cameraPos.y = eye->getCameraOrigin().z;
	cameraPos.z = eye->getCameraOrigin().y;

	float vClipConstant = eye->verticalSphereClipConstant;
	float hClipConstant = eye->horizontalSphereClipConstant; 
	
 	long i=0;
	for (i=0;i<numberVertices;i++)
	{
		//----------------------------------------------------------------------------------------
		// Figure out if we are in front of camera or not.  Should be faster then actual project!
		// Should weed out VAST overwhelming majority of vertices!
		bool onScreen = false;
	
		//-----------------------------------------------------------------
		// Find angle between lookVector of Camera and vector from camPos
		// to Target.  If angle is less then halfFOV, object is visible.
		if (eye->usePerspective)
		{
			//-------------------------------------------------------------------
			//NEW METHOD from the WAY BACK Days
			onScreen = true;
			
			Stuff::Vector3D vPosition;
			vPosition.x = currentVertex->vx;
			vPosition.y = currentVertex->vy;
			vPosition.z = currentVertex->pVertex->elevation;
  
			Stuff::Vector3D objectCenter;
			objectCenter.Subtract(vPosition,cameraPos);
			Camera::cameraFrame.trans_to_frame(objectCenter);
			float distanceToEye = objectCenter.GetApproximateLength();

			Stuff::Vector3D clipVector = objectCenter;
			clipVector.z = 0.0f;
			float distanceToClip = clipVector.GetApproximateLength();
			float clip_distance = fabs(1.0f / objectCenter.y);
			
			if (distanceToClip > CLIP_THRESHOLD_DISTANCE)
			{
				//Is vertex on Screen OR close enough to screen that its triangle MAY be visible?
				// WE have removed the atans here by simply taking the tan of the angle we want above.
				float object_angle = fabs(objectCenter.z) * clip_distance;
				float extent_angle = VERTEX_EXTENT_RADIUS / distanceToEye;
				if (object_angle > (vClipConstant + extent_angle))
				{
					//In theory, we would return here.  Object is NOT on screen.
					onScreen = false;
				}
				else
				{
					object_angle = fabs(objectCenter.x) * clip_distance;
					if (object_angle > (hClipConstant + extent_angle))
					{
						//In theory, we would return here.  Object is NOT on screen.
						onScreen = false;
					}
				}
			}
			
			if (onScreen)
			{
				if (distanceToEye > Camera::MaxClipDistance)
				{
					currentVertex->hazeFactor = 1.0f;
				}
				else if (distanceToEye > Camera::MinHazeDistance)
				{
					currentVertex->hazeFactor = (distanceToEye - Camera::MinHazeDistance) * Camera::DistanceFactor;
				}
				else
				{
					currentVertex->hazeFactor = 0.0f;
				}
				
				//---------------------------------------
				// Vertex is at edge of world or beyond.
				Stuff::Vector3D vPos(currentVertex->vx,currentVertex->vy,currentVertex->pVertex->elevation);
				bool isVisible = Terrain::IsGameSelectTerrainPosition(vPos) || drawTerrainGrid;
				if (!isVisible)
				{
					currentVertex->hazeFactor = 1.0f;
					onScreen = true;
				}
			}
			else
			{
				currentVertex->hazeFactor = 1.0f;
			}
		}
		else
		{
			currentVertex->hazeFactor = 0.0f;
			onScreen = true;
		}

		bool inView = false;
		Stuff::Vector4D screenPos(-10000.0f,-10000.0f,-10000.0f,-10000.0f);
		if (onScreen)
		{
			Stuff::Vector3D vertex3D(currentVertex->vx,currentVertex->vy,currentVertex->pVertex->elevation);
			inView = eye->projectZ(vertex3D,screenPos);
		
			currentVertex->px = screenPos.x;
			currentVertex->py = screenPos.y;
			currentVertex->pz = screenPos.z;
			currentVertex->pw = screenPos.w;
			
			//----------------------------------------------------------------------------------
			//We must transform these but should NOT draw any face where all three are fogged. 
//			if (currentVertex->hazeFactor == 1.0f)		
//				onScreen = false;
		}
		else
		{
			currentVertex->px = currentVertex->py = 10000.0f;
			currentVertex->pz = -0.5f;
			currentVertex->pw = 0.5f;
			currentVertex->hazeFactor = 0.0f;
		}	
		
		//------------------------------------------------------------
		// Fix clip.  Vertices can all be off screen and triangle
		// still needs to be drawn!
		if (eye->usePerspective && Environment.Renderer != 3)
		{
			currentVertex->clipInfo = onScreen;
		}
		else
			currentVertex->clipInfo = inView;
		
		if (currentVertex->clipInfo)				//ONLY set TRUE ones.  Otherwise we just reset the FLAG each vertex!
		{
			setObjBlockActive(currentVertex->getBlockNumber(), true);
			setObjVertexActive(currentVertex->vertexNum,true);
			
			if (inView)
			{
				if (screenPos.z < leastZ)
				{
					leastZ = screenPos.z;
				}
				
				if (screenPos.z > mostZ)
				{
					mostZ = screenPos.z;
				}
				
				if (screenPos.w < leastW)
				{
					leastW = screenPos.w;
					leastWY = screenPos.y;
				}
				
				if (screenPos.w > mostW)
				{
					mostW = screenPos.w;
					mostWY = screenPos.y;
				}
			}
		}

		currentVertex++;
	}
	
	//-----------------------------------
	// setup terrain quad textures
	// Also sets up mine data.
	TerrainQuadPtr currentQuad = quadList;
	for (i=0;i<numberQuads;i++)
	{
		currentQuad->setupTextures();
		currentQuad++;
	}

	float ywRange = 0.0f, yzRange = 0.0f;
	if (fabs(mostWY - leastWY) > Stuff::SMALL)
	{
		ywRange = (mostW - leastW) / (mostWY - leastWY);
		yzRange = (mostZ - leastZ) / (mostWY - leastWY);
	}

	eye->setInverseProject(mostZ,leastW,yzRange,ywRange);

	//-----------------------------------
	// update the cloud layer
	if (Terrain::cloudLayer)
		Terrain::cloudLayer->update();
}
Пример #5
0
//---------------------------------------------------------------------------
void Clouds::update (void)
{
	renderClouds = false;
	
	scrollU += frameLength * SCROLL_U_FACTOR;
	scrollV += frameLength * SCROLL_V_FACTOR;

	if (scrollU > 1.0f)
		scrollU -= 1.0f;
		
	if (scrollV > 1.0f)
		scrollV -= 1.0f;
		
	if (scrollU < -1.0f)
		scrollU += 1.0f;
		
	if (scrollV < -1.0f)
		scrollV += 1.0f;
		
	//---------------------------------------------------------------------
	// If projectionAngle is less then some magic number, draw the clouds.
	// Otherwise, do not do anything!
	if (eye->active && eye->usePerspective && (eye->getProjectionAngle() < MAX_CLOUDS_ANGLE))
	{
		//renderClouds = true;
		
		//-------------------------------------------------------
		// Create the cloud grid based on camera CENTER position.
		Stuff::Vector3D centerPosition(eye->getPosition());
		
		//-------------------------------------------------------
		// Create a topLeft vertex
		float tLeftX = centerPosition.x + MAX_CLOUDS_SIZE;
		float tLeftY = centerPosition.y + MAX_CLOUDS_SIZE;
		
		//-------------------------------------------------------
		// Create the grid.
		long cloudInc = float2long(MAX_CLOUDS_SIZE * 2.0f / gridSize);
		float uvInc = MAX_UV_REPEAT / float(gridSize);
		
		for (long y=0;y<gridSize;y++)
		{
			for (long x=0;x<gridSize;x++)
			{
				cloudVertices[x + (y*gridSize)].vx = tLeftX - (cloudInc * x);
				cloudVertices[x + (y*gridSize)].vy = tLeftY - (cloudInc * y);
				
				cloudVertices[x + (y*gridSize)].pu = CLOUD_START_U + (uvInc * x);
				cloudVertices[x + (y*gridSize)].pv = CLOUD_START_V + (uvInc * y);
 			}
		}
		
		//-------------------------------------------------------
		// Transform Grid
		long gridTotal = gridSize * gridSize;
		for (long i=0;i<gridTotal;i++)
		{
			//----------------------------------------------------------------------------------------
			// Figure out if we are in front of camera or not.  Should be faster then actual project!
			// Should weed out VAST overwhelming majority of vertices!
			bool onScreen = true;
		
			//-----------------------------------------------------------------
			// Find angle between lookVector of Camera and vector from camPos
			// to Target.  If angle is less then halfFOV, object is visible.
			
			//-------------------------------------------------------------------
			// Then figure out if FarClipped.  Should weed out a boatload more!
			float hazeFactor = 0.0f;
			Stuff::Point3D Distance;
			Stuff::Point3D vPosition;
			Stuff::Point3D eyePosition(eye->getPosition());
			vPosition.x = cloudVertices[i].vx;;
			vPosition.y = cloudVertices[i].vy;
			vPosition.z = centerPosition.z;
				
			Distance.Subtract(eyePosition,vPosition);
			float eyeDistance = Distance.GetApproximateLength();
			if (eyeDistance > Camera::MaxClipDistance)
			{
				hazeFactor = 1.0f;
				//onScreen = false;
			}
			else if (eyeDistance > Camera::MinHazeDistance)
			{
				hazeFactor = (eyeDistance - Camera::MinHazeDistance) * Camera::DistanceFactor;
			}
			else
			{
				hazeFactor = 0.0f;
			}
					
			//------------------------------------------------------------
			// Calculate the HazeDWORD here
			if (hazeFactor != 0.0f)
			{
				float fogFactor = 1.0 - hazeFactor;
				DWORD distFog = float2long(fogFactor * 255.0f);
				
				cloudVertices[i].fogRGB = (distFog<<24) + (0xffffff);
			}
			else
			{
				cloudVertices[i].fogRGB = 0xffffffff;
			}
			
			if (onScreen)
			{
				Stuff::Vector3D Distance;
				Stuff::Point3D objPosition;
				Stuff::Point3D eyePosition(eye->getCameraOrigin());
				objPosition.x = -cloudVertices[i].vx;
				objPosition.y = CLOUD_ALTITUDE;
				objPosition.z = cloudVertices[i].vy;
			
				Distance.Subtract(objPosition,eyePosition);
				Distance.Normalize(Distance);
					
				float cosine = Distance * eye->getLookVector();
				if (cosine > eye->cosHalfFOV)
					onScreen = true;
				else
					onScreen = false;
			}
			else
			{
				hazeFactor = 1.0f;
			}
			
			Stuff::Vector3D vertex3D(cloudVertices[i].vx,cloudVertices[i].vy,(CLOUD_ALTITUDE+eye->getCameraOrigin().y));
			Stuff::Vector4D screenPos;
			bool inView = eye->projectZ(vertex3D,screenPos);
			
			cloudVertices[i].px = screenPos.x;
			cloudVertices[i].py = screenPos.y;
			cloudVertices[i].pz = screenPos.z;
			cloudVertices[i].pw = screenPos.w;
			
			//------------------------------------------------------------
			// Fix clip.  Vertices can all be off screen and triangle
			// still needs to be drawn!
			cloudVertices[i].clipInfo = onScreen && inView;
			
			//------------------------------------------------------------
			// Still need to scrollUVs here!
			cloudVertices[i].pu += scrollU;
			cloudVertices[i].pv += scrollV;
		}
		
		for (y=0;y<(gridSize-1);y++)
		{
			for (long x=0;x<(gridSize-1);x++)
			{
				CloudVertexPtr cloudVertex0 = &(cloudVertices[x     + (y    *gridSize)]);
				CloudVertexPtr cloudVertex1 = &(cloudVertices[(x+1) + (y    *gridSize)]); 
				CloudVertexPtr cloudVertex2 = &(cloudVertices[(x+1) + ((y+1)*gridSize)]); 
				CloudVertexPtr cloudVertex3 = &(cloudVertices[x     + ((y+1)*gridSize)]); 
				
				bool clipCheck = (cloudVertex0->clipInfo || cloudVertex1->clipInfo || cloudVertex2->clipInfo);
				if (clipCheck && ((cloudVertex0->pz < 1.0f) && (cloudVertex0->pz > 0.0f) &&
									(cloudVertex1->pz < 1.0f) && (cloudVertex1->pz > 0.0f) && 
									(cloudVertex2->pz < 1.0f) && (cloudVertex2->pz > 0.0f)))
				{
					mcTextureManager->addTriangle(mcTextureNodeIndex,MC2_DRAWALPHA);
				}
				
				clipCheck = (cloudVertex0->clipInfo || cloudVertex2->clipInfo || cloudVertex3->clipInfo);
				if (clipCheck && ((cloudVertex0->pz < 1.0f) && (cloudVertex0->pz > 0.0f) &&
									(cloudVertex2->pz < 1.0f) && (cloudVertex2->pz > 0.0f) && 
									(cloudVertex3->pz < 1.0f) && (cloudVertex3->pz > 0.0f)))
				{
					mcTextureManager->addTriangle(mcTextureNodeIndex,MC2_DRAWALPHA);
				}
			}
		}			 
	}
}
Пример #6
0
//---------------------------------------------------------------------------
bool Team::lineOfSight(float startLocal, int32_t mCellRow, int32_t mCellCol, int32_t tCellRow, int32_t tCellCol, int32_t teamId, float extRad, bool checkVisibleBits)
{
#ifdef LAB_ONLY
	int64_t x = GetCycles();
#endif
	//-----------------------------------------------------
	// Once we allow teams to have alliances (for contacts,
	// etc.), simply set all nec. team bits in this mask...
	//TILE HACK...
	int32_t tileRow = tCellRow / 3;
	int32_t tileCol = tCellCol / 3;
	if((teamId < 0) || (teamId >= MAX_TEAMS))	//Not on any team.  It can see everything!
		return true;
	if(checkVisibleBits)
	{
		uint8_t teamMask = 0x01 << teamId;
		uint8_t visbBits[4];
		//----------------------------------------------------------------------------
		// First check is simple.  Is anyone within the magical line of sight radius?
		// If not, return false and move on.
		// If they are, you MUST check LOS between this object and the other one.
		bool losResult = false;
		visbBits[0] = Terrain::VisibleBits->getFlag(tileRow, tileCol);
		if(visbBits[0] & teamMask)
			losResult = true;
		if(!losResult)
		{
			visbBits[1] = Terrain::VisibleBits->getFlag(tileRow + 1, tileCol);
			if(visbBits[1] & teamMask)
				losResult = true;
		}
		if(!losResult)
		{
			visbBits[2] = Terrain::VisibleBits->getFlag(tileRow + 1, tileCol + 1);
			if(visbBits[2] & teamMask)
				losResult = true;
		}
		if(!losResult)
		{
			visbBits[3] = Terrain::VisibleBits->getFlag(tileRow, tileCol + 1);
			if(visbBits[3] & teamMask)
				losResult = true;
		}
		if(!losResult)
		{
#ifdef LAB_ONLY
			x = GetCycles() - x;
			MCTimeLOSCalc += x;
#endif
			return losResult;
		}
	}
	if(useRealLOS)
	{
		//------------------------------------------------------------------------------------------
		// Within magic radius.  Check REAL LOS now.
		// Check is really simple.
		// Find deltaCellRow and deltaCellCol and iterate over them from source to dest.
		// If the magic line ever goes BELOW the terrainElevation PLUS localElevation return false.
		Stuff::Vector3D startPos, endPos;
		startPos.Zero();
		endPos.Zero();
		land->getCellPos(tCellRow, tCellCol, endPos);
		land->getCellPos(mCellRow, mCellCol, startPos);
		startPos.z += startLocal;
		Stuff::Vector3D deltaCellVec;
		deltaCellVec.y = tCellRow - mCellRow;
		deltaCellVec.x = tCellCol - mCellCol;
		deltaCellVec.z = 0.0f;
		float startHeight = startPos.z;
		float length = deltaCellVec.GetApproximateLength();
		if(length > Stuff::SMALL)
		{
			float colLength = deltaCellVec.x / length;
			float rowLength = deltaCellVec.y / length;
			float heightLen = (endPos.z - startPos.z) / length;
			float lastCol = fabs(colLength * 2.0);
			float lastRow = fabs(rowLength * 2.0);
			float startCellRow = mCellRow;
			float startCellCol = mCellCol;
			float endCellRow = tCellRow;
			float endCellCol = tCellCol;
			Stuff::Vector3D currentPos = startPos;
			Stuff::Vector3D dist;
			dist.Subtract(endPos, currentPos);
			float remainingDist = dist.GetApproximateLength();
			bool colDone = false, rowDone = false;
			while(!colDone || !rowDone)
			{
				if(fabs(startCellRow - endCellRow) > lastRow)	//DO NOT INCLUDE LAST CELL!!!!!
				{
					startCellRow += rowLength;
				}
				else
				{
//					startCellRow = (endCellRow - lastRow);
					rowDone = true;
				}
				if(fabs(startCellCol - endCellCol) > lastCol)	//DO NOT INCLUDE LAST CELL!!!!!
				{
					startCellCol += colLength;
				}
				else
				{
//					startCellCol = (endCellCol - lastCol);
					colDone = true;
				}
				startHeight += heightLen;
				int32_t startCellC = startCellCol;
				int32_t startCellR = startCellRow;
				land->getCellPos(startCellR, startCellC, currentPos);
				float localElev = (worldUnitsPerMeter * 4.0f * (float)GameMap->getLocalHeight(startCellR, startCellC));
				currentPos.z += localElev;
				if(startHeight + startLocal < currentPos.z)
				{
#ifdef LAB_ONLY
					x = GetCycles() - x;
					MCTimeLOSCalc += x;
#endif
#ifdef LAB_ONLY
					if(drawTerrainGrid)
					{
						Stuff::Vector3D realStart = startPos;
						Stuff::Vector4D lineStart, lineEnd;
						eye->projectZ(realStart, lineStart);
						eye->projectZ(endPos, lineEnd);
						debugLines[currentLineElement++] = new LineElement(lineStart, lineEnd, SD_RED, nullptr, -1);
					}
#endif
					return false;
				}
				if(extRad > Stuff::SMALL)
				{
					dist.Subtract(endPos, currentPos);
					remainingDist = dist.GetApproximateLength();
					if(remainingDist < extRad)
						break;
				}
			}
		}
#ifdef LAB_ONLY
		if(drawTerrainGrid)
		{
			Stuff::Vector3D realStart = startPos;
			Stuff::Vector4D lineStart, lineEnd;
			eye->projectZ(realStart, lineStart);
			eye->projectZ(endPos, lineEnd);
			debugLines[currentLineElement++] = new LineElement(lineStart, lineEnd, SD_GREEN, nullptr, -1);
		}
#endif
	}
#ifdef LAB_ONLY
	x = GetCycles() - x;
	MCTimeLOSCalc += x;
#endif
	return true;
}
Пример #7
0
//---------------------------------------------------------------------------
bool Team::teamLineOfSight(Stuff::Vector3D tPos, float extRad)
{
	//-----------------------------------------------------------
	// For each member of the team, check LOS to point provided.
	for(size_t i = 0; i < rosterSize; i++)
	{
		MoverPtr obj = (MoverPtr)ObjectManager->getByWatchID(roster[i]);
		if(!obj->isDisabled() && !obj->isDestroyed() && (obj->getStatus() != OBJECT_STATUS_SHUTDOWN))
		{
			Stuff::Vector3D distance;
			distance.Subtract(tPos, obj->getPosition());
			float dist = distance.GetApproximateLength();
			//Figure out altitude above minimum terrain altitude and look up in table.
			float baseElevation = MapData::waterDepth;
			if(MapData::waterDepth < Terrain::userMin)
				baseElevation = Terrain::userMin;
			float altitude = obj->getPosition().z - baseElevation;
			float altitudeIntegerRange = (Terrain::userMax - baseElevation) * 0.00390625f;
			int32_t altLevel = 0;
			if(altitudeIntegerRange > Stuff::SMALL)
				altLevel = altitude / altitudeIntegerRange;
			if(altLevel < 0)
				altLevel = 0;
			if(altLevel > 255)
				altLevel = 255;
			float radius = visualRangeTable[altLevel];
			//Scouting specialty skill.
			if(obj->isMover())
			{
				MoverPtr mover = (MoverPtr)obj;
				if(mover->pilot && mover->pilot->isScout())
					radius += (radius * 0.2f);
				radius *= mover->getLOSFactor();
			}
			if(dist <= (radius * 25.0f * worldUnitsPerMeter))
			{
				if(lineOfSight(obj->getLOSPosition(), tPos, id, extRad, 0.0f, false))
					return true;
			}
		}
	}
	//-------------------------------------------------------------------------
	// Check the lookout towers now.  You can find them in special Buildings!!
	for(size_t spBuilding = 0; spBuilding < ObjectManager->numSpecialBuildings; spBuilding++)
	{
		if(ObjectManager->specialBuildings[spBuilding] &&
				ObjectManager->specialBuildings[spBuilding]->getExists() &&
				ObjectManager->specialBuildings[spBuilding]->isLookoutTower() &&
				(ObjectManager->specialBuildings[spBuilding]->getTeamId() == id))
		{
			GameObjectPtr obj = ObjectManager->specialBuildings[spBuilding];
			if(!obj->isDisabled() && !obj->isDestroyed() && (obj->getStatus() != OBJECT_STATUS_SHUTDOWN))
			{
				Stuff::Vector3D distance;
				distance.Subtract(tPos, obj->getPosition());
				float dist = distance.GetApproximateLength();
				//Figure out altitude above minimum terrain altitude and look up in table.
				float baseElevation = MapData::waterDepth;
				if(MapData::waterDepth < Terrain::userMin)
					baseElevation = Terrain::userMin;
				float altitude = obj->getPosition().z - baseElevation;
				float altitudeIntegerRange = (Terrain::userMax - baseElevation) * 0.00390625f;
				int32_t altLevel = 0;
				if(altitudeIntegerRange > Stuff::SMALL)
					altLevel = altitude / altitudeIntegerRange;
				if(altLevel < 0)
					altLevel = 0;
				if(altLevel > 255)
					altLevel = 255;
				float radius = visualRangeTable[altLevel];
				//Scouting specialty skill.
				if(obj->isMover())
				{
					MoverPtr mover = (MoverPtr)obj;
					if(mover->pilot && mover->pilot->isScout())
						radius += (radius * 0.2f);
					radius *= mover->getLOSFactor();
				}
				if(dist <= (radius * 25.0f * worldUnitsPerMeter))
				{
					if(lineOfSight(obj->getLOSPosition(), tPos, id, 0.0f, obj->getAppearRadius(), false))
						return true;
				}
			}
		}
	}
	return false;
}
Пример #8
0
//---------------------------------------------------------------------------
bool Team::lineOfSight(float startLocal, int32_t mCellRow, int32_t mCellCol, float endLocal, int32_t tCellRow, int32_t tCellCol, int32_t teamId, float extRad, float startExtRad, bool checkVisibleBits)
{
#ifdef LAB_ONLY
	int64_t x = GetCycles();
#endif
	//-----------------------------------------------------
	// Once we allow teams to have alliances (for contacts,
	// etc.), simply set all nec. team bits in this mask...
	//TILE HACK...
	int32_t tileRow = tCellRow / 3;
	int32_t tileCol = tCellCol / 3;
	if((teamId < 0) || (teamId >= MAX_TEAMS))	//Not on any team.  It can see everything!
		return true;
#if 0		//Don't need to check this anymore.  We do a distance check outside of this function.
	if(checkVisibleBits)
	{
		uint8_t teamMask = 0x01 << teamId;
		uint8_t visbBits[4];
		//----------------------------------------------------------------------------
		// First check is simple.  Is anyone within the magical line of sight radius?
		// If not, return false and move on.
		// If they are, you MUST check LOS between this object and the other one.
		bool losResult = false;
		visbBits[0] = Terrain::VisibleBits->getFlag(tileRow, tileCol);
		if(visbBits[0] & teamMask)
			losResult = true;
		if(!losResult)
		{
			visbBits[1] = Terrain::VisibleBits->getFlag(tileRow + 1, tileCol);
			if(visbBits[1] & teamMask)
				losResult = true;
		}
		if(!losResult)
		{
			visbBits[2] = Terrain::VisibleBits->getFlag(tileRow + 1, tileCol + 1);
			if(visbBits[2] & teamMask)
				losResult = true;
		}
		if(!losResult)
		{
			visbBits[3] = Terrain::VisibleBits->getFlag(tileRow, tileCol + 1);
			if(visbBits[3] & teamMask)
				losResult = true;
		}
		if(!losResult)
		{
#ifdef LAB_ONLY
			x = GetCycles() - x;
			MCTimeLOSCalc += x;
#endif
			return losResult;
		}
	}
#endif
	if(useRealLOS)
	{
		//------------------------------------------------------------------------------------------
		// Within magic radius.  Check REAL LOS now.
		// Check is really simple.
		// Find deltaCellRow and deltaCellCol and iterate over them from source to dest.
		// If the magic line ever goes BELOW the terrainElevation PLUS localElevation return false.
		Stuff::Vector3D startPos, endPos;
		startPos.Zero();
		endPos.Zero();
		land->getCellPos(tCellRow, tCellCol, endPos);
		land->getCellPos(mCellRow, mCellCol, startPos);
		startPos.z += startLocal;
		endPos.z += endLocal;
		Stuff::Vector3D deltaCellVec;
		deltaCellVec.y = tCellRow - mCellRow;
		deltaCellVec.x = tCellCol - mCellCol;
		deltaCellVec.z = 0.0f;
		float startHeight = startPos.z;
		float length = deltaCellVec.GetApproximateLength();
		length *= ACCURACY_ADJUST;
		if(length > Stuff::SMALL)
		{
			float colLength = (endPos.x - startPos.x) / length;
			float rowLength = (endPos.y - startPos.y) / length;
			float heightLen = (endPos.z - startPos.z) / (length + ACCURACY_ADJUST);
			Stuff::Vector3D currentPos = startPos;
			currentPos.z = land->getTerrainElevation(currentPos);
			int32_t maxDistIter = (length - 0.5f);
			int32_t maxTrees = 0;
			Stuff::Vector3D dist;
			dist.Subtract(endPos, currentPos);
			float remainingDist = dist.GetApproximateLength();
			bool checkExtent = (extRad > Stuff::SMALL);
			bool checkStart = (startExtRad > Stuff::SMALL);
			extRad += HALF_CELL_DIST;
			for(size_t distIter = 0; distIter < maxDistIter; distIter++)
			{
				bool outsideStartRadius = true;
				if(checkStart)
				{
					Stuff::Vector3D distance;
					distance.Subtract(currentPos, startPos);
					distance.z = 0.0f;
					float dist = distance.GetApproximateLength();
					if(dist <= startExtRad)
						outsideStartRadius = false;
				}
				startHeight += heightLen;
				int32_t curCellRow, curCellCol;
				land->worldToCell(currentPos, curCellRow, curCellCol);
				float localElev = (worldUnitsPerMeter * 4.0f * (float)GameMap->getLocalHeight(curCellRow, curCellCol));
				float thisHeight = currentPos.z + localElev;
				//First, check if we are now inside the extent radius of the thing we are calcing LOS to.
				// If we are and we haven't returned false since we're here, we can see it!!!!
				if(checkExtent)
				{
					dist.Subtract(endPos, currentPos);
					remainingDist = dist.GetApproximateLength();
					if(remainingDist <= extRad)
						break;
				}
				if(outsideStartRadius && (startHeight < thisHeight))
				{
					bool isTree = false;
					if(GameMap->getForest(curCellRow, curCellCol))
					{
						maxTrees++;
						isTree = true;
					}
					if(!isTree || (maxTrees >= MaxTreeLOSCellBlock))
					{
#ifdef LAB_ONLY
						x = GetCycles() - x;
						MCTimeLOSCalc += x;
#endif
#ifdef LAB_ONLY
						if(drawTerrainGrid)
						{
							Stuff::Vector3D realStart = startPos;
							Stuff::Vector4D lineStart, lineEnd;
							eye->projectZ(realStart, lineStart);
							eye->projectZ(endPos, lineEnd);
							debugLines[currentLineElement++] = new LineElement(lineStart, lineEnd, SD_RED, nullptr, -1);
						}
#endif
						return false;
					}
				}
				currentPos.x += colLength;
				currentPos.y += rowLength;
				currentPos.z = land->getTerrainElevation(currentPos);
			}
		}
#ifdef LAB_ONLY
		if(drawTerrainGrid)
		{
			Stuff::Vector3D realStart = startPos;
			Stuff::Vector4D lineStart, lineEnd;
			eye->projectZ(realStart, lineStart);
			eye->projectZ(endPos, lineEnd);
			debugLines[currentLineElement++] = new LineElement(lineStart, lineEnd, SD_GREEN, nullptr, -1);
		}
#endif
	}
#ifdef LAB_ONLY
	x = GetCycles() - x;
	MCTimeLOSCalc += x;
#endif
	return true;
}
Пример #9
0
//---------------------------------------------------------------------------
int32_t Building::updateAnimations(void)
{
	//---------------------------------------------
	// Animate Sensor Towers first.
	/*
	if (sensorSystem != nullptr)
	{
		int32_t animState = appearance->getCurrentGestureId();
		if (sensorSystem->numContacts)
		{
			switch (animState)
			{
				case -1:		//NOT UPDATED YET. SWITCH TO ZERO
					if (!appearance->getInTransition())
					{
						appearance->setGesture(0);
					}
					break;

				case 2:			//Just Animating.  Do NOTHING!
					break;

				case 0:			//Not triggered yet.  Switch to 1
					appearance->setGesture(1);
					break;

				case 1:			//triggered, when fully open switch to 2
					if (!appearance->getInTransition())
					{
						appearance->setGesture(2);
					}
					break;

				case 3:			//Closing.  Wait until closed and then switch to 1.
					if (!appearance->getInTransition())
					{
						appearance->setGesture(1);
					}
					break;
			}
		}
		else	//This will be handled by sensor system going disabled if building destroyed OR parent destroyed!
		{
			switch (animState)
			{
				case -1:		//NOT UPDATED YET. SWITCH TO ZERO
					if (!appearance->getInTransition())
					{
						appearance->setGesture(0);
					}
					break;

				case 2:			//Just Animating.  Wait until one loop done, then trigger closing
					if (!appearance->getInTransition())
					{
						appearance->setGesture(3);
					}
					break;

				case 0:			//Not triggered yet.  DO NOTHING!
					break;

				case 1:			//triggered, when fully open switch to 3 to close it.
					if (!appearance->getInTransition())
					{
						appearance->setGesture(3);
					}
					break;

				case 3:		//Closing to closed.  When Closed, DO NOTHING
					break;
			}
		}
	}
	else*/
	if(((BuildingTypePtr)getObjectType())->resourcePoints)
	{
		if(!MPlayer)
		{
			//We are a resource Points Building.
			//OPEN when we have been CAPTURED!!
			int32_t animState = appearance->getCurrentGestureId();
			if(!teamId)	//We've been Captured
			{
				switch(animState)
				{
					case -1:		//NOT UPDATED YET. SWITCH TO ZERO
						if(!appearance->getInTransition())
						{
							appearance->setGesture(0);
						}
						break;
					case 2:			//Just Animating.  Do NOTHING!
						break;
					case 0:			//Not triggered yet.  Switch to 1
						appearance->setGesture(1);
						break;
					case 1:			//triggered, when fully open switch to 2
						if(!appearance->getInTransition())
						{
							appearance->setGesture(2);
						}
						break;
					case 3:			//Closing.  Wait until closed and then switch to 1.
						if(!appearance->getInTransition())
						{
							appearance->setGesture(1);
						}
						break;
				}
			}
			else
			{
				//Stay Closed
				switch(animState)
				{
					case -1:		//NOT UPDATED YET. SWITCH TO ZERO
						if(!appearance->getInTransition())
						{
							appearance->setGesture(0);
						}
						break;
					case 2:			//Just Animating.  Do NOTHING!
						break;
					case 0:			//Do Nothing
						break;
					case 1:			//triggered, when fully open switch to 3
						if(!appearance->getInTransition())
						{
							appearance->setGesture(3);
						}
						break;
					case 3:			//Closing.  Wait until closed and then switch to 1.
						if(!appearance->getInTransition())
						{
							appearance->setGesture(0);
						}
						break;
				}
			}
		}
	}
	else if(((BuildingTypePtr)getObjectType())->mechBay)
	{
		if(!MPlayer)
		{
			//We are a Mech Repair Bay Building.
			// Open to the correct place based on our RepairBuddyWID
			int32_t animState = appearance->getCurrentGestureId();
			if(!refitBuddyWID)	//We're repairing no one.
			{
				switch(animState)
				{
					case -1:		//NOT UPDATED YET. SWITCH TO ZERO
						if(!appearance->getInTransition())
						{
							appearance->setGesture(0);
						}
						break;
					case 1:			//We were repairing someone.  Switch to doing nothing!
						if(!appearance->getInTransition())
						{
							appearance->setGesture(5);
						}
						break;
					case 2:			//We were repairing someone.  Switch to doing nothing!
						if(!appearance->getInTransition())
						{
							appearance->setGesture(6);
						}
						break;
					case 3:			//We were repairing someone.  Switch to doing nothing!
						if(!appearance->getInTransition())
						{
							appearance->setGesture(7);
						}
						break;
					case 4:			//We were repairing someone.  Switch to doing nothing!
						if(!appearance->getInTransition())
						{
							appearance->setGesture(8);
						}
						break;
					case 5:			//We were repairing someone.  Switch to doing nothing!
					case 6:			//We were repairing someone.  Switch to doing nothing!
					case 7:			//We were repairing someone.  Switch to doing nothing!
					case 8:			//We were repairing someone.  Switch to doing nothing!
						if(!appearance->getInTransition())
						{
							appearance->setGesture(0);
						}
						break;
					case 0:			//Do Nothing.  We aren't repairing anyone
						break;
				}
			}
			else
			{
				//We are repairing someone.
				switch(animState)
				{
					case -1:		//NOT UPDATED YET. SWITCH TO ZERO
						if(!appearance->getInTransition())
						{
							appearance->setGesture(0);
						}
						break;
					case 1:
					case 2:
					case 3:
					case 4:		//DO NOTHING!!  We are in position.
					{
						GameObjectPtr refitMech = ObjectManager->getByWatchID(refitBuddyWID);
						if(refitMech && (refitMech->getStatus() == OBJECT_STATUS_SHUTDOWN))
						{
							if(((BuildingTypePtr)getObjectType())->activityEffectId != 0xffffffff)
								appearance->startActivity(((BuildingTypePtr)getObjectType())->activityEffectId, true);
						}
						else
						{
							appearance->stopActivity();
						}
					}
					break;
					case 0:
						if(!appearance->getInTransition())
						{
							GameObjectPtr refitMech = ObjectManager->getByWatchID(refitBuddyWID);
							if(refitMech)
							{
								Stuff::Vector3D distance;
								distance.Subtract(refitMech->getPosition(), getPosition());
								float dist = distance.GetApproximateLength();
								if(dist <= 128.0f)
								{
									if(refitMech && (refitMech->getTonnage() <= 40.0f))
									{
										appearance->setGesture(1);
									}
									else if(refitMech && (refitMech->getTonnage() <= 60.0f))
									{
										appearance->setGesture(2);
									}
									else if(refitMech && (refitMech->getTonnage() <= 80.0f))
									{
										appearance->setGesture(3);
									}
									else if(refitMech && (refitMech->getTonnage() <= 100.0f))
									{
										appearance->setGesture(4);
									}
								}
							}
						}
						break;
					case 5:			//We were repairing someone.  Switch to doing nothing!
					case 6:			//We were repairing someone.  Switch to doing nothing!
					case 7:			//We were repairing someone.  Switch to doing nothing!
					case 8:			//We were repairing someone.  Switch to doing nothing!
						if(!appearance->getInTransition())
						{
							appearance->setGesture(0);
						}
						break;
				}
			}
		}
		else	//MechBays must ALWAYS be open in Mplayer or it will look dumb!
		{
			appearance->setGesture(4);
		}
	}
	else
	{
		//Just about everything else animates here.
		if(!isDisabled() && !isDestroyed())
		{
			if(!appearance->getInTransition())
			{
				appearance->setGesture(0);
			}
		}
		else	//This will be handled by building destroyed OR parent destroyed!
		{
		}
	}
	return 0;
}