예제 #1
0
int FlareClass::Exec(){
	if (trail){
	   // I-Hawk - Removed, flare's trail isn't managed here anymore but from PS
		//UpdateTrail();
		if (SimLibElapsedTime - timeOfDeath > 10 * SEC_TO_MSEC){
			SetDead (TRUE);
		}
	}
	
	BombClass::Exec();
	
	if(IsExploding())
	{
		SetFlag( SHOW_EXPLOSION );
		SetDead(TRUE);
		return TRUE;
	}
	
	// MLR 2003-11-15 flares were going thru the ground
	{
		float z;
		
		z = OTWDriver.GetGroundLevel(XPos(), YPos());
		if(ZPos() > z)
		{
			int gtype = OTWDriver.GetGroundType(XPos(),YPos());
			
			switch(gtype)
			{
			case COVERAGE_WATER:
			case COVERAGE_RIVER:
			case COVERAGE_SWAMP:
				// flare went into water.
				SetDead(TRUE);
				break;
			default:
				// give em a slight bounce.
				SetDelta((SM_SCALAR)(XDelta() * .25), (SM_SCALAR)(YDelta() * .25), (SM_SCALAR)(-ZDelta() * .25));
				SetPosition(XPos(),YPos(),z);
				break;
			}
		}
	}
	
	SetDelta (XDelta() * 0.99F, YDelta() * 0.99F, ZDelta() * 0.99F);
	return TRUE;
}
예제 #2
0
void EjectedPilotClass::ApplyDamage(FalconDamageMessage *damageMsg)
{
	if(_stage >= PD_CHUTE_OPENING)
	{
	   SimMoverClass::ApplyDamage(damageMsg);

		if(_collapseChute == FALSE)
		{
			// PlayRadioMessage (rcAIRMANDOWNB)
			// _flightId is the VU_ID of the flight the pilot ejected from
			
			Flight flight;
			flight = (Flight) vuDatabase->Find(_flightId);

			if(flight)
			{
				FalconRadioChatterMessage *radioMessage = new FalconRadioChatterMessage( flight->Id(), FalconLocalSession );
				radioMessage->dataBlock.from = flight->Id();
				radioMessage->dataBlock.to = MESSAGE_FOR_TEAM;
				radioMessage->dataBlock.voice_id = flight->GetFlightLeadVoiceID();
				radioMessage->dataBlock.message = rcAIRMANDOWNB;
				//M.N. changed to 32767 -> flexibly use randomized values of max available eval indexes
				radioMessage->dataBlock.edata[0] = 32767;
				
				FalconSendMessage(radioMessage, FALSE);
			}

			F4Assert(_deathMsg == NULL);

			// Create death message. 
			_deathMsg = new FalconDeathMessage (Id(), FalconLocalGame);

			// ahhhhhhhhhhhhhhhhh
#ifdef MLR_NEWSNDCODE			
			SoundPos.Sfx( SFX_SCREAM, 0, 1, 0);
#else
			F4SoundFXSetPos( SFX_SCREAM, TRUE, XPos(), YPos(), ZPos(), 1.0f , 0 , XDelta(),YDelta(),ZDelta());
#endif
      
			_deathMsg->dataBlock.damageType = damageMsg->dataBlock.damageType;
			_deathMsg->dataBlock.dEntityID  = Id();
			_deathMsg->dataBlock.dCampID = 0;
			_deathMsg->dataBlock.dSide   = GetCountry();
			_deathMsg->dataBlock.dPilotID   = pilotSlot;
			_deathMsg->dataBlock.dIndex     = Type();

			_deathMsg->dataBlock.fEntityID  = damageMsg->dataBlock.fEntityID;
			_deathMsg->dataBlock.fCampID    = damageMsg->dataBlock.fCampID;
			_deathMsg->dataBlock.fSide      = damageMsg->dataBlock.fSide;
			_deathMsg->dataBlock.fPilotID   = damageMsg->dataBlock.fPilotID;
			_deathMsg->dataBlock.fIndex     = damageMsg->dataBlock.fIndex;
			_deathMsg->dataBlock.fWeaponID  = damageMsg->dataBlock.fWeaponID;
			_deathMsg->dataBlock.fWeaponUID = damageMsg->dataBlock.fWeaponUID;
		}

		_collapseChute = TRUE;
	}
}
예제 #3
0
void FlareClass::ExtraGraphics()
{
#if 0
	Falcon4EntityClassType* classPtr;

	OTWDriver.RemoveObject(drawPointer, TRUE);
	drawPointer = NULL;
	classPtr = &Falcon4ClassTable[displayIndex];
	OTWDriver.CreateVisualObject (this, classPtr->visType[0], OTWDriver.Scale());

	BombClass::ExtraGraphics();
	OTWDriver.RemoveObject(drawPointer, TRUE);
	drawPointer = NULL;
	classPtr = &Falcon4ClassTable[displayIndex];
	OTWDriver.CreateVisualObject(this, classPtr->visType[0], OTWDriver.Scale());
#else
	BombClass::ExtraGraphics();
	if (drawPointer){
		OTWDriver.RemoveObject(drawPointer, TRUE);
		drawPointer = NULL;
	}
	Falcon4EntityClassType* classPtr = &Falcon4ClassTable[displayIndex];
	OTWDriver.CreateVisualObject(this, classPtr->visType[0], OTWDriver.Scale());
#endif

	Tpoint newPoint = { XPos(), YPos(), ZPos() };
	Tpoint vec = { XDelta(), YDelta(), ZDelta() }; //I-Hawk - Added vector to support new PS flare movement

	//RV - I-Hawk - PS flare effect call, to replace the old Flare effect
    /*
	
	OTWDriver.AddSfxRequest(new SfxClass( SFX_LIGHT_DEBRIS,		// type
								SFX_MOVES,
								&newPoint,							// world pos
								&vec,
								1.0f,							// time to live
								1.0f) );		// scale
								*/
	DrawableParticleSys::PS_AddParticleEx(
		(SFX_FLARE_GFX + 1), &newPoint, &vec
	); 

	// I-Hawk - Removed, Not used anymore  
	/*
	if(!g_bDisableMissleEngGlow) // MLR 2003-11-15 disable that shit-o star effect
	{
		OTWDriver.InsertObject(trailGlow);
		OTWDriver.InsertObject(trailSphere);
	}*/

	// I-Hawk - Removed, old flare graphics stuff

	//OTWDriver.RemoveObject(drawPointer, TRUE);
	//drawPointer = new Drawable2D( DRAW2D_FLARE, 2.0f, &newPoint );
	//OTWDriver.InsertObject(drawPointer);
	timeOfDeath = SimLibElapsedTime;
}
예제 #4
0
/*---------------------------------------------------------------------------*/
void ConvertSegmentToPicoFeat(FPOINT *Start,
                              FPOINT *End,
                              FEATURE_SET FeatureSet) {
/*
 **	Parameters:
 **		Start		starting point of pico-feature
 **		End		ending point of pico-feature
 **		FeatureSet	set to add pico-feature to
 **	Globals:
 **		classify_pico_feature_length	length of a single pico-feature
 **	Operation: This routine converts an entire segment of an outline
 **		into a set of pico features which are added to
 **		FeatureSet.  The length of the segment is rounded to the
 **		nearest whole number of pico-features.  The pico-features
 **		are spaced evenly over the entire segment.
 **	Return: none (results are placed in FeatureSet)
 **	Exceptions: none
 **	History: Tue Apr 30 15:44:34 1991, DSJ, Created.
 */
  FEATURE Feature;
  FLOAT32 Angle;
  FLOAT32 Length;
  int NumFeatures;
  FPOINT Center;
  FPOINT Delta;
  int i;

  Angle = NormalizedAngleFrom (Start, End, 1.0);
  Length = DistanceBetween (*Start, *End);
  NumFeatures = (int) floor (Length / classify_pico_feature_length + 0.5);
  if (NumFeatures < 1)
    NumFeatures = 1;

  /* compute vector for one pico feature */
  Delta.x = XDelta (*Start, *End) / NumFeatures;
  Delta.y = YDelta (*Start, *End) / NumFeatures;

  /* compute position of first pico feature */
  Center.x = Start->x + Delta.x / 2.0;
  Center.y = Start->y + Delta.y / 2.0;

  /* compute each pico feature in segment and add to feature set */
  for (i = 0; i < NumFeatures; i++) {
    Feature = NewFeature (&PicoFeatDesc);
    Feature->Params[PicoFeatDir] = Angle;
    Feature->Params[PicoFeatX] = Center.x;
    Feature->Params[PicoFeatY] = Center.y;
    AddFeature(FeatureSet, Feature);

    Center.x += Delta.x;
    Center.y += Delta.y;
  }
}                                /* ConvertSegmentToPicoFeat */
예제 #5
0
int DebrisClass::Exec (void)
{
	BombClass::Exec();

   if(IsExploding())
   {
      SetFlag( SHOW_EXPLOSION );
      SetDead(TRUE);
      return TRUE;
   }

   SetDelta (XDelta() * 0.99F, YDelta() * 0.99F, ZDelta() * 0.99F);
   return TRUE;
}
예제 #6
0
void EjectedPilotClass::InitChuteOpening()
{
	// Set the new BSP.
	SetModel(MD_PILOT_AND_OPEN_CHUTE);
	
	// Set the orientation to upright
	_rot[I_ROLL] = 0.0;
	_rot[I_PITCH] = 0.0;
	_rot[I_YAW] = _vel.Heading();

	// Set angular velocity to 0.
	_aVel[I_ROLL] = 0.0;
	_aVel[I_PITCH] = 0.0;
	_aVel[I_YAW] = 0.0;

	// play the sound
#ifdef MLR_NEWSNDCODE	
	SoundPos.Sfx( SFX_CHUTE, 0, 1.0f , 0 );
#else
	F4SoundFXSetPos( SFX_CHUTE, TRUE, XPos(), YPos(), ZPos(), 1.0f , 0 , XDelta(),YDelta(),ZDelta());
#endif

	_stageTimer = 0.0f;
}
예제 #7
0
void AircraftClass::DropFlare (void)
{
	vector		pos, posDelta;
	int		type;
	BombClass	*weapon;
	
	if (counterMeasureStation[FLARE_STATION].weaponCount > 0)
	{
		if (this == FalconLocalSession->GetPlayerEntity())
		    g_intellivibeData.FlareDropped++;
		{
			static int chaffsid=0; // just need a fake id so multiple chaffs can play at once.
			chaffsid = (chaffsid + 1) & 0xf;
			SoundPos.Sfx( af->auxaeroData->sndBBFlare, chaffsid);
		}

/*
		pos.x = XPos();
		pos.y = YPos();
		pos.z = ZPos();
		posDelta.x = XDelta() * 0.75F;
		posDelta.y = YDelta() * 0.75F;
		posDelta.z = ZDelta() * 0.75F;
*/
		// MLR 2003-11-16 New positional dispensers
		int NumToLaunch = 1;
		
		if(af->auxaeroData->Flare.Sequence==2)
		{
			NumToLaunch=af->auxaeroData->Flare.Count;
		}

		int i;
		for(i=0;i<NumToLaunch && counterMeasureStation[FLARE_STATION].weaponCount > 0;i++)
		{
			counterMeasureStation[FLARE_STATION].weaponCount--;

			Tpoint work;
			MatrixMult( &((DrawableBSP*)af->platform->drawPointer)->orientation, &af->auxaeroData->Flare.Pos[flareDispenser], &work ); 		
			pos.x=work.x + XPos();
			pos.y=work.y + YPos();
			pos.z=work.z + ZPos();

			MatrixMult( &((DrawableBSP*)af->platform->drawPointer)->orientation, &af->auxaeroData->Flare.Vec[flareDispenser], &work ); 		
			posDelta.x=work.x + XDelta();
			posDelta.y=work.y + YDelta();
			posDelta.z=work.z + ZDelta();


			switch(af->auxaeroData->Flare.Sequence)
			{
			case 0: // alternate dispensers;
			case 2:
				flareDispenser++;

				if(flareDispenser>=af->auxaeroData->Flare.Count)
				  flareDispenser=0;
				break;
			case 1: // use 1 dispenser, then move to the next
			default:
				flareUsed++;
				if(flareUsed>=af->auxaeroData->Flare.Decoys[flareDispenser])
				{
					flareUsed=0;
					flareDispenser++;
					if(flareDispenser>=af->auxaeroData->Flare.Count)
					  flareDispenser=0;
				}
				break;
			}

			//type = GetClassID (DOMAIN_AIR, CLASS_VEHICLE, TYPE_BOMB, STYPE_BOMB_IRON, SPTYPE_MK82, VU_ANY, VU_ANY, VU_ANY) + VU_LAST_ENTITY_TYPE; // JB 010220
			type = GetClassID (DOMAIN_AIR, CLASS_VEHICLE, TYPE_BOMB, STYPE_FLARE1, SPTYPE_CHAFF1 + 1, VU_ANY, VU_ANY, VU_ANY) + VU_LAST_ENTITY_TYPE; // JB 010220
			
			weapon = new FlareClass (type);
			weapon->Init();
			weapon->SetParent(this);
			weapon->Start(&pos, &posDelta, 0.2f);
			vuDatabase->/*Quick*/Insert(weapon);
			weapon->Wake();
		}
		SetFlareExpireTime( SimLibElapsedTime + FlareTime );
		SetNewestFlareID( weapon->Id() );
	}
	//MI for EWS stuff
	if(g_bRealisticAvionics && this == FalconLocalSession->GetPlayerEntity())
	{
		if(counterMeasureStation[FLARE_STATION].weaponCount == 0)
		{
			//F4SoundFXSetDist(af->auxaeroData->sndBBChaffFlareOut, TRUE, 0.0f, 1.0f);
			SoundPos.Sfx(af->auxaeroData->sndBBChaffFlareOut);
			//make sure we don't get here again, no sounds from now on
			counterMeasureStation[FLARE_STATION].weaponCount--;
		}
		else if(OTWDriver.pCockpitManager->mpIcp->FlareBingo == counterMeasureStation[FLARE_STATION].weaponCount)
		{
			if(OTWDriver.pCockpitManager->mpIcp->EWS_BINGO_ON)
				SoundPos.Sfx(af->auxaeroData->sndBBChaffFlareLow);
				//F4SoundFXSetDist( af->auxaeroData->sndBBChaffFlareLow, TRUE, 0.0f, 1.0f );
		}
		//MI moved further down
		/*else if(counterMeasureStation[FLARE_STATION].weaponCount > 0)
			F4SoundFXSetDist(SFX_BB_CHAFLARE, FALSE, 0.0f, 1.0f);*/
	}

	// If this is the player and they want unlimited chaff, let 'em have it
	if (IsSetFlag(MOTION_OWNSHIP) && PlayerOptions.UnlimitedChaff())
		counterMeasureStation[FLARE_STATION].weaponCount++;
}
예제 #8
0
void AircraftClass::DropChaff (void)
{
	vector		pos, posDelta;
	int		type;
	BombClass	*weapon;
	
	if (counterMeasureStation[CHAFF_STATION].weaponCount > 0)
	{

		if (this == FalconLocalSession->GetPlayerEntity())
		    g_intellivibeData.ChaffDropped++;
		/*
		pos.x = XPos();
		pos.y = YPos();
		pos.z = ZPos();
		posDelta.x = XDelta() * 0.75F;
		posDelta.y = YDelta() * 0.75F;
		posDelta.z = ZDelta() * 0.75F;
		*/
		// new positional Dispensers 
		int NumToLaunch = 1;
		
		if(af->auxaeroData->Chaff.Sequence==2)
		{
			NumToLaunch=af->auxaeroData->Chaff.Count;
		}

		int i;
		for(i=0;i<NumToLaunch && counterMeasureStation[CHAFF_STATION].weaponCount > 0;i++)
		{
            counterMeasureStation[CHAFF_STATION].weaponCount--;
			Tpoint work;
			MatrixMult( &((DrawableBSP*)af->platform->drawPointer)->orientation, &af->auxaeroData->Chaff.Pos[chaffDispenser], &work ); 		
			pos.x=work.x + XPos();
			pos.y=work.y + YPos();
			pos.z=work.z + ZPos();

			MatrixMult( &((DrawableBSP*)af->platform->drawPointer)->orientation, &af->auxaeroData->Chaff.Vec[chaffDispenser], &work ); 		
			posDelta.x=work.x + XDelta();
			posDelta.y=work.y + YDelta();
			posDelta.z=work.z + ZDelta();


			switch(af->auxaeroData->Chaff.Sequence)
			{
			case 0: // alternate dispensers;
			case 2:
				chaffDispenser++;

				if(chaffDispenser>=af->auxaeroData->Chaff.Count)
				  chaffDispenser=0;
				break;
			case 1: // use 1 dispenser, then move to the next
			default:
				chaffUsed++;
				if(chaffUsed>=af->auxaeroData->Chaff.Decoys[chaffDispenser])
				{
					chaffUsed=0;
					chaffDispenser++;
					if(chaffDispenser>=af->auxaeroData->Chaff.Count)
					  chaffDispenser=0;
				}
				break;
			}


			// TODO:  Use a different (much higher drag) type for the chaff
			//type = GetClassID (DOMAIN_AIR, CLASS_SFX, TYPE_CHAFF, STYPE_CHAFF, SPTYPE_CHAFF1, VU_ANY, VU_ANY, VU_ANY) + VU_LAST_ENTITY_TYPE; // JB 010220
			type = GetClassID (DOMAIN_AIR, CLASS_VEHICLE, TYPE_BOMB, STYPE_CHAFF, SPTYPE_CHAFF1, VU_ANY, VU_ANY, VU_ANY) + VU_LAST_ENTITY_TYPE; // JB 010220

			weapon = new ChaffClass(type);
			weapon->Init();
			weapon->SetParent(this);
			weapon->Start(&pos, &posDelta, 0.2f);
			vuDatabase->/*Quick*/Insert(weapon);
			weapon->Wake();
		}

		SetChaffExpireTime( SimLibElapsedTime + ChaffTime );
		SetNewestChaffID( weapon->Id() );
	}
	//MI for EWS stuff
	if(g_bRealisticAvionics && this == FalconLocalSession->GetPlayerEntity())
	{
		if(counterMeasureStation[CHAFF_STATION].weaponCount == 0)
		{
			SoundPos.Sfx(af->auxaeroData->sndBBChaffFlareOut);
			//make sure we don't get here again, no sounds from now on
			counterMeasureStation[CHAFF_STATION].weaponCount--;
		}
		else if(OTWDriver.pCockpitManager->mpIcp->ChaffBingo == counterMeasureStation[CHAFF_STATION].weaponCount)
		{
			if(OTWDriver.pCockpitManager->mpIcp->EWS_BINGO_ON)
				SoundPos.Sfx(af->auxaeroData->sndBBChaffFlareLow);
		}
		//MI Moved further down
		/*if(counterMeasureStation[CHAFF_STATION].weaponCount > 0)
			F4SoundFXSetDist(SFX_BB_CHAFLARE, FALSE, 0.0f, 1.0f);*/
	}


	// If this is the player and they want unlimited chaff, let 'em have it
	if (IsSetFlag(MOTION_OWNSHIP) && PlayerOptions.UnlimitedChaff())
		counterMeasureStation[CHAFF_STATION].weaponCount++;
}
예제 #9
0
void EjectedPilotClass::InitLocalData(AircraftClass *ac, int mode, int no){
	DrawableBSP		*acBSP;
	int				labelLen;

	_delayTime = SimLibElapsedTime + no * 2 * CampaignSeconds;
	// Initialize position, rotation, velocity, angular velocity.
	if (ac)
	{
		_pos = EP_VECTOR(ac->XPos(),ac->YPos(),ac->ZPos());

		_rot[I_ROLL] =	ac->Roll();
		_rot[I_PITCH] = ac->Pitch();
		_rot[I_YAW] = ac->Yaw();
		
		_vel = EP_VECTOR(ac->XDelta(),ac->YDelta(),ac->ZDelta());

		_aVel[I_ROLL] = ac->RollDelta();
		_aVel[I_PITCH] = ac->PitchDelta();
		_aVel[I_YAW] = ac->YawDelta();
	}
	else
	{

		_pos = EP_VECTOR(XPos(),YPos(),ZPos());

		_rot[I_ROLL] =	Roll();
		_rot[I_PITCH] = Pitch();
		_rot[I_YAW] = Yaw();
		
		_vel = EP_VECTOR(XDelta(),YDelta(),ZDelta());

		_aVel[I_ROLL] = RollDelta();
		_aVel[I_PITCH] = PitchDelta();
		_aVel[I_YAW] = YawDelta();
	}

	// Play with this value to change the signature of an
	// ejected pilot on the IR.
	SetPowerOutput(0);
	// sfr: not setters on this anymore
	//SetVt(0);
	//SetKias(0);

	// Initialize physical data.
	_pd = NULL;
	_stage = PD_START;

	// Initialize model data to NULL.
	_md = NULL;
	_model = MD_START;

	// Set the ejection mode.
	SetMode(mode);

	// Initialize run time and delta time.
	_runTime = 0.0;
	_deltaTime = 0.0;

	// We just set the type flag to "FalconSimEntity".
	SetTypeFlag(FalconEntity::FalconSimEntity);

	// Is it ourselves - Find out from the aircraft.
	if (ac && no == 0){
		_isPlayer = (SimDriver.GetPlayerEntity() == ac) ? TRUE : FALSE;
	}
	else {
		_isPlayer = FALSE;
	}

	// Is it a player - Find out from the aircraft.
	if (ac){
		_isDigital = ac->IsDigital() ? TRUE : FALSE;
	}
	else{
		_isDigital = TRUE;
	}

	// Set team/country
	if (ac){
      SetCountry (ac->GetCountry());
	}

	_endStageTimeAdjust = 
	(
		IsDigiPilot() ?
		0.0F :
		_pd->humanPilotEndStageTimeAdjust
	);
	
	// It hasn't hit the ground yet.
	_hitGround = FALSE;

	// The chute isn't collapsed yet.
	_collapseChute = FALSE;
	_chuteCollapsedTime = 1000000.0;

	// No death message yet.
	_deathMsg = NULL;

	// Update shared data.
	SetPosition(_pos[I_X], _pos[I_Y], _pos[I_Z]);
	SetDelta(_vel[I_X], _vel[I_Y], _vel[I_Z]);
	SetYPR(_rot[I_YAW], _rot[I_PITCH], _rot[I_ROLL]);
	SetYPRDelta(_aVel[I_YAW], _aVel[I_PITCH], _aVel[I_ROLL]);

	// Update matrices for geometry.
	CalcTransformMatrix((SimMoverClass *)this);

	// Set up our label.
	if (ac)
	{
		acBSP = (DrawableBSP *)ac->drawPointer;
		if(acBSP != NULL)
		{
			strncpy(_label, acBSP->Label(), 32);
			labelLen = strlen(acBSP->Label());
			if (no == 0){
			    strncat(_label, " Pilot", 32 - labelLen);
			}
			else {
			    char crewstr[20];
			    sprintf (crewstr, " Crew%d", no);
			    strncat(_label, crewstr, 32 - labelLen);
			}
			_label[31] = 0;
			_labelColor = acBSP->LabelColor();
		}
		else
		{
			_label[0] = 0;
			_labelColor = 0;
		}
	}
	else
	{
		strcpy(_label, "Pilot");
		labelLen = strlen(_label);
		_labelColor = 0;//acBSP->LabelColor();
	}
	
	_execCalledFromAircraft = FALSE;
	
	// Point to the aircraft that I ejected from.
	if (ac)
	{
		_aircraftId = ac->Id();
		_flightId = ac->GetCampaignObject()->Id();
	}

	// Update exec transfer synching data.
	_lastFrameCount = 0;
	//	_execCount = 0;

   // Act like a bomb, so nobody sees you
   // edg: yuck, we now have an eject pilot motion
   SetFlag(MOTION_BMB_AI);

   SetFlag(MOTION_EJECT_PILOT);

   if (IsLocal()) {
      SimVuDriver *drive = new SimVuDriver(this);
      drive->ExecDR(SimLibElapsedTime);
      SetDriver (drive);
   }
}
예제 #10
0
void HelicopterClass::RunExplosion (void)
{
	int i;
	Tpoint    pos;
	Falcon4EntityClassType *classPtr;
	SimBaseClass	*tmpSimBase;
	Tpoint tp = Origin;
	Trotation tr = IMatrix;

    // F4PlaySound (SFX_DEF[SFX_OWNSHIP_BOOM].handle);
	//F4SoundFXSetPos( SFX_BOOMA1 + PRANDInt5(), TRUE, XPos(), YPos(), ZPos(), 1.0f );
	SoundPos.Sfx( SFX_BOOMA1 + PRANDInt5() ); // MLR 5/16/2004 - 

	// 1st do primary explosion
    pos.x = XPos();
    pos.y = YPos();
    pos.z = ZPos();

	if ( OnGround( ) )
	{
		pos.z = OTWDriver.GetGroundLevel( pos.x, pos.y ) - 4.0f;
		SetDelta( XDelta() * 0.1f, YDelta() * 0.1f, -50.0f );
    	OTWDriver.AddSfxRequest(
  			new SfxClass (SFX_GROUND_EXPLOSION,				// type
			&pos,							// world pos
			1.2f,							// time to live
			100.0f ) );		// scale
	}
	else
	{
    	OTWDriver.AddSfxRequest(
  			new SfxClass (SFX_AIR_HANGING_EXPLOSION,				// type
			&pos,							// world pos
			2.0f,							// time to live
			200.0f + 200 * PRANDFloatPos() ) );		// scale
	}
	classPtr = (Falcon4EntityClassType*)EntityType();

	// Add the parts (appairently hardcoded at 4)
	// Recoded by KCK on 6/23 to remove damage station BS
	for (i=0; i<4; i++)
		{
		tmpSimBase = new SimBaseClass(Type());
		CalcTransformMatrix (tmpSimBase);
		OTWDriver.CreateVisualObject(tmpSimBase, classPtr->visType[i+2], &tp, &tr, OTWDriver.Scale());
		tmpSimBase->SetPosition (pos.x, pos.y, pos.z);

		if (!i)
			{
			tmpSimBase->SetDelta (XDelta(), YDelta(), ZDelta());
			}
		if (!OnGround())
			{
			tmpSimBase->SetDelta (	XDelta() + 50.0f * PRANDFloat(),
									YDelta() + 50.0f * PRANDFloat(),
									ZDelta() + 50.0f * PRANDFloat() );
			}
		else
			{
			tmpSimBase->SetDelta (	XDelta() + 50.0f * PRANDFloat(),
									YDelta() + 50.0f * PRANDFloat(),
									ZDelta() - 50.0f * PRANDFloatPos() );
			}
		tmpSimBase->SetYPR (Yaw(), Pitch(), Roll());

		if (!i)
			{
			// First peice is more steady and is flaming
			tmpSimBase->SetYPRDelta ( 0.0F, 0.0F, 10.0F + PRANDFloat() * 30.0F * DTR);
			OTWDriver.AddSfxRequest(
  			new SfxClass (SFX_FLAMING_PART,				// type
				SFX_MOVES | SFX_USES_GRAVITY | SFX_EXPLODE_WHEN_DONE,
				tmpSimBase,								// sim base *
				3.0f + PRANDFloatPos() * 4.0F,			// time to live
				1.0F ) );								// scale
			}
		else
			{
			// spin piece a random amount
			tmpSimBase->SetYPRDelta (	PRANDFloat() * 30.0F * DTR,
										PRANDFloat() * 30.0F * DTR,
										PRANDFloat() * 30.0F * DTR);
			OTWDriver.AddSfxRequest(
				new SfxClass (SFX_SMOKING_PART,			// type
				SFX_MOVES | SFX_USES_GRAVITY | SFX_BOUNCES | SFX_EXPLODE_WHEN_DONE,
				tmpSimBase,								// sim base *
				4.0f * PRANDFloatPos() + (float)((i+1)*(i+1)),	// time to live
				1.0 ) );								// scale
			}
		}
}
예제 #11
0
/*
** GroundClass Exec() function.
** NOTE: returns TRUE if we've processed this frame.  FALSE if we're to do
** dead reckoning (in VU)
*/
int GroundClass::Exec (void)
{
	//RV - I-Hawk - Added a 0 vector for RV new PS calls
	Tpoint PSvec;
	PSvec.x = 0;
	PSvec.y = 0;
	PSvec.z = 0;

	Tpoint pos;
    Tpoint vec;
	float speedScale;
	float groundZ;
	float	labelLOD;
	float	drawLOD;
	RadarClass *radar = NULL;
	
	SoundPos.UpdatePos((SimBaseClass *)this);

	//Cobra
	pos.x = 0.0f;
	pos.y = 0.0f;
	pos.z = 0.0f;
	
	// MLR 5/23/2004 -
	pos.x = XPos();
	pos.y = YPos();
	pos.z = OTWDriver.GetApproxGroundLevel( pos.x, pos.y );
//	pos.z = -10.0f;//Cobra trying to fix the stupid uninit CTD
	SetPosition(pos.x, pos.y, pos.z);

	// dead? -- we do nothing
	if ( IsDead() ){
		return FALSE;
	}

    // if damaged 
	if ( pctStrength < 0.5f ){
		if (sfxTimer > 1.5f - gai->distLOD * 1.3){
			// reset the timer
			sfxTimer = 0.0f;
			pos.z -= 10.0f;

			// VP_changes this shoud be checked why have GetGroundLevel been subtracted by 10.0F
			// Sometimes the trails seem strange
			vec.x = PRANDFloat() * 20.0f;
			vec.y = PRANDFloat() * 20.0f;
			vec.z = PRANDFloat() * 20.0f;
			
			/*
			OTWDriver.AddSfxRequest(
				new SfxClass(
					SFX_TRAILSMOKE,			// type
					SFX_MOVES | SFX_NO_GROUND_CHECK,						// flags
					&pos,							// world pos
					&vec,							// vector
					3.5f,							// time to live
					4.5f					// scale
				)
			);
					*/
			DrawableParticleSys::PS_AddParticleEx((SFX_TRAILSMOKE + 1),
									&pos,
									&vec);
			
		}
	}
	
	if (IsExploding()){
		// KCK: I've never seen this section of code executed. Maybe it gets hit, but I doubt
		// it.
		if (!IsSetFlag( SHOW_EXPLOSION )){
			// Show the explosion
			Tpoint pos, vec;
			Falcon4EntityClassType *classPtr = (Falcon4EntityClassType *)EntityType();
			//DrawableGroundVehicle *destroyedPtr; // FRB

			//Cobra TJL 11/07/04 CTD point initialize here
			pos.x = 0.0f;
			pos.y = 0.0f;
			pos.z = 0.0f;
			
			// MLR 5/23/2004 - uncommented out the x, y
			pos.x = XPos();
			pos.y = YPos();
			pos.z = OTWDriver.GetApproxGroundLevel( pos.x, pos.y ) - 10.0f;
			
			vec.x = 0.0f;
			vec.y = 0.0f;
			vec.z = 0.0f;
			
			// create a new drawable for destroyed vehicle
			// sometimes.....

           //RV - I-Hawk - Commenting all this if statement... not necessary

			/*
			if ( rand() & 1 ){
				destroyedPtr = new DrawableGroundVehicle(
					classPtr->visType[3],
					&pos,
					Yaw(),
					1.0f 
				);
				
				groundZ = PRANDFloatPos() * 60.0f + 15.0f;
				
				/*
				OTWDriver.AddSfxRequest(
					new SfxClass (
						SFX_BURNING_PART,				// type
						&pos,							// world pos
						&vec,							// 
						(DrawableBSP *)destroyedPtr,
						groundZ,							// time to live
						1.0f 	// scale
					)
				);	
						*/
			/*
				DrawableParticleSys::PS_AddParticleEx((SFX_BURNING_PART + 1),
									&pos,
									&vec);
				
				
				pos.z += 10.0f;
				/*
				OTWDriver.AddSfxRequest(
					new SfxClass(
						SFX_FEATURE_EXPLOSION,				// type
						&pos,							// world pos
						groundZ,							// time to live
						100.0f 		// scale
					) 
				);
						*/
			/*
				DrawableParticleSys::PS_AddParticleEx((SFX_FEATURE_EXPLOSION + 1),
									&pos,
									&PSvec);

			}
			*/
			//RV - I-Hawk - seperating explosion type for ground/sea domains. also
			//adding a check so soldiers will not explode like ground vehicles...

            if (GetDomain() == DOMAIN_LAND && GetType() != TYPE_FOOT)
			{		
				//pos.z -= 20.0f;
				/*
				OTWDriver.AddSfxRequest(
					new SfxClass(
						SFX_VEHICLE_EXPLOSION,				// type
						&pos,							// world pos
						1.5f,							// time to live
						100.0f 		// scale
					)
				);
					*/
				DrawableParticleSys::PS_AddParticleEx((SFX_VEHICLE_EXPLOSION + 1),
										&pos,
										&PSvec);
			}
			else if ( GetDomain() == DOMAIN_SEA )
			{
				DrawableParticleSys::PS_AddParticleEx((SFX_WATER_FIREBALL + 1),
										&pos,
										&PSvec);
			}

			// make sure we don't do it again...
			SetFlag( SHOW_EXPLOSION );
			
			// we can now kill it immediately
			SetDead(TRUE);  
		}
		return FALSE;
	}
	
	// exec any base functionality
	SimVehicleClass::Exec();
	
	// Sept 30, 2002
	// VP_changes: Frequently Z value is not in the correct place. It should follow the terrain.
	if ( drawPointer ){
		drawPointer->GetPosition( &pos );
	}
	else {
		return FALSE;
	}

	//JAM 27Sep03 - Let's try this
	groundZ = pos.z;		// - 0.7f; KCK: WTF is this?

	//VP_changes Sept 25
	groundZ = OTWDriver.GetGroundLevel( pos.x, pos.y );


	// Movement/Targeting for local entities
	if (IsLocal() && SimDriver.MotionOn())
	{
		//I commented this out, because it is done in gai->ProcessTargeting down below DSP 4/30/99
		// Refresh our target pointer (if any)
		//SetTarget( SimCampHandoff( targetPtr, targetList, HANDOFF_RANDOM ) );
		// Look for someone to do radar fire control for us
		FindBattalionFireControl();

		// RV - Biker - Switch on lights for ground/naval vehicles
		int isNight = TimeOfDayGeneral(TheCampaign.CurrentTime) < TOD_DAWNDUSK ? true : false;

		if (drawPointer && ((DrawableBSP *)drawPointer)->GetNumSwitches() >= AIRDEF_LIGHT_SWITCH) 
		{
			if (isShip) 
			{
				isNight = (TimeOfDayGeneral(TheCampaign.CurrentTime) <= TOD_DAWNDUSK || realWeather->weatherCondition == INCLEMENT) ? true : false;

				if (pctStrength > 0.50f) 
				{
					((DrawableBSP *)drawPointer)->SetSwitchMask(0, isNight);
					((DrawableBSP *)drawPointer)->SetSwitchMask(AIRDEF_LIGHT_SWITCH, isNight);
				}
			}
			else if (GetVt() > 1.0f) 
			{
				VuListIterator	vehicleWalker(SimDriver.combinedList);
				FalconEntity* object = (FalconEntity*)vehicleWalker.GetFirst();
				bool hasThreat = false;
				float range = 999.9f * NM_TO_FT;

				// Consider each potential target in our environment
				while (object && !hasThreat) 
				{
					// Skip sleeping sim objects
					if (object->IsSim()) 
					{
						if (!((SimBaseClass*)object)->IsAwake()) 
						{
							object = (FalconEntity*)vehicleWalker.GetNext();
							continue;
						}
					}

					// Fow now we skip missles -- might want to display them eventually...
					if (object->IsMissile() || object->IsBomb()) 
					{
						object = (FalconEntity*)vehicleWalker.GetNext();
						continue;
					}

					if (object->GetTeam() == GetTeam()) 
					{
						object = (FalconEntity*)vehicleWalker.GetNext();
						continue;
					}

					float dx = object->XPos() - XPos();
					float dy = object->YPos() - YPos();
					float dz = object->ZPos() - ZPos();

					range = (float)sqrt(dx*dx + dy*dy + dz*dz);

					if (range < 5.0f * NM_TO_FT)
						hasThreat = true;

					object = (FalconEntity*)vehicleWalker.GetNext();
				}

				// If no enemy nearby and not heavy damaged switch on lights
				if (!hasThreat && pctStrength > 0.75f) {
					((DrawableBSP *)drawPointer)->SetSwitchMask(AIRDEF_LIGHT_SWITCH, isNight);
				}
				else 
				{
					((DrawableBSP *)drawPointer)->SetSwitchMask(AIRDEF_LIGHT_SWITCH, 0);
				}	
			}
			else 
			{
				((DrawableBSP *)drawPointer)->SetSwitchMask(AIRDEF_LIGHT_SWITCH, 0);
			}
		}

		// RV - Biker - Do also switch on lights for tractor vehicles
		if (truckDrawable && truckDrawable->GetNumSwitches() >= AIRDEF_LIGHT_SWITCH) 
		{
			if (GetVt() > 1.0f) 
			{
				VuListIterator	vehicleWalker(SimDriver.combinedList);
				FalconEntity* object = (FalconEntity*)vehicleWalker.GetFirst();
				bool hasThreat = false;
				float range = 999.9f * NM_TO_FT;

				// Consider each potential target in our environment
				while (object && !hasThreat) 
				{
					// Skip sleeping sim objects
					if (object->IsSim()) 
					{
						if (!((SimBaseClass*)object)->IsAwake()) 
						{
							object = (FalconEntity*)vehicleWalker.GetNext();
							continue;
						}
					}

					// Fow now we skip missles -- might want to display them eventually...
					if (object->IsMissile() || object->IsBomb()) 
					{
						object = (FalconEntity*)vehicleWalker.GetNext();
						continue;
					}

					if (object->GetTeam() == GetTeam()) 
					{
						object = (FalconEntity*)vehicleWalker.GetNext();
						continue;
					}

					float dx = object->XPos() - XPos();
					float dy = object->YPos() - YPos();
					float dz = object->ZPos() - ZPos();

					range = (float)sqrt(dx*dx + dy*dy + dz*dz);

					if (range < 5.0f * NM_TO_FT)
						hasThreat = true;

					object = (FalconEntity*)vehicleWalker.GetNext();
				}

				// If no enemy nearby and not heavy damaged switch on lights
				if (!hasThreat && pctStrength > 0.75f) {
					truckDrawable->SetSwitchMask(AIRDEF_LIGHT_SWITCH, isNight);
				}
				else 
				{
					truckDrawable->SetSwitchMask(AIRDEF_LIGHT_SWITCH, 0);
				}
			}
			else 
			{
				truckDrawable->SetSwitchMask(AIRDEF_LIGHT_SWITCH, 0);
			}
		}
		
		// RV - Biker - Shut down ship radar if damaged
		if (isShip && radarDown == false && pctStrength < 0.9f && rand()%50 > (pctStrength - 0.50f)*100) 
		{
			isEmitter = false;
			RadarClass *radar = (RadarClass*)FindSensor(this, SensorClass::Radar);
			if (radar) 
			{
				radarDown = true;
				radar->SetDesiredTarget(NULL);
				radar->SetEmitting(FALSE);
			}

			if (targetPtr) 
			{
				SelectWeapon(true);
			}
		}
		
		// 2001-03-26 ADDED BY S.G. NEED TO KNOW IF THE RADAR CALLED SetSpotted
		// RV - Biker - Rotate radars
		float deltaDOF;
		float curDOF = GetDOFValue(5);
		
		deltaDOF = 180.0f * DTR * SimLibMajorFrameTime;
		curDOF += deltaDOF;
		
		if ( curDOF > 360.0f * DTR )
	  		curDOF -= 360.0f * DTR;

		SetDOF(5, curDOF);
		int spottedSet = FALSE;
		// END OF ADDED SECTION

		// 2002-03-21 ADDED BY S.G. 
		// If localData only has zeros, 
		// there is a good chance they are not valid (should not happen here though)... 
		if (targetPtr) {
			SimObjectLocalData* localData= targetPtr->localData;
			if (
				localData->ataFrom == 0.0f && 
				localData->az == 0.0f  && 
				localData->el == 0.0f && 
				localData->range == 0.0f
			) {
				CalcRelAzElRangeAta(this, targetPtr);
			}
		}
		// END OF ADDED SECTION 2002-03-21

		// check for sending radar emmisions
		// 2002-02-26 MODIFIED BY S.G.
		// Added the nextTargetUpdate check to prevent the radar code to run on every frame!
		if ( isEmitter && nextTargetUpdate < SimLibElapsedTime){
			// 2002-02-26 ADDED BY S.G. Next radar scan is 1 sec for aces, 2 for vets, etc ...
			nextTargetUpdate = SimLibElapsedTime + (5 - gai->skillLevel) * SEC_TO_MSEC; 

			radar = (RadarClass*)FindSensor( this, SensorClass::Radar );
			ShiAssert( radar );
			if (radar){
				radar->Exec( targetList );
			}

			// 2001-03-26 ADDED BY S.G. 
			// IF WE CAN SEE THE RADAR'S TARGET AND WE ARE A AIR DEFENSE THINGY 
			// NOT IN A BKOGEN MORAL STATE, MARK IT AS SPOTTED IF WE'RE BRIGHT ENOUGH
			if (
				radar && 
				radar->CurrentTarget() && 
				gai->skillLevel >= 3 && 
				((UnitClass *)GetCampaignObject())->GetSType() == STYPE_UNIT_AIR_DEFENSE && 
				!((UnitClass *)GetCampaignObject())->Broken()
			){
				CampBaseClass *campBaseObj;
				if (radar->CurrentTarget()->BaseData()->IsSim()){
					campBaseObj = ((SimBaseClass *)radar->CurrentTarget()->BaseData())->GetCampaignObject();
				}
				else{
					campBaseObj = (CampBaseClass *)radar->CurrentTarget()->BaseData();
				}

				// JB 011002 If campBaseObj is NULL the target may be chaff
				if (campBaseObj && !(campBaseObj->GetSpotted(GetTeam())) && campBaseObj->IsFlight()){
					RequestIntercept((FlightClass *)campBaseObj, GetTeam());
				}

				spottedSet = TRUE;
				if (campBaseObj && radar->GetRadarDatFile()){
					campBaseObj->SetSpotted(
						GetTeam(), TheCampaign.CurrentTime, 
						(radar->radarData->flag & RAD_NCTR) != 0 && 
						radar->CurrentTarget()->localData && 
						radar->CurrentTarget()->localData->ataFrom < 45.0f * DTR && 
						radar->CurrentTarget()->localData->range < 
						radar->GetRadarDatFile()->MaxNctrRange / (2.0f * (16.0f - (float)gai->skillLevel) / 16.0f)
					);
				}
				// 2002-03-05 MODIFIED BY S.G. target's aspect and skill used in the equation
			}
		// END OF ADDED SECTION
		}

		// 2001-03-26 ADDED BY S.G. 
		// IF THE BATTALION LEAD HAS LOS 
		// ON IT AND WE ARE A AIR DEFENSE THINGY NOT IN A BKOGEN MORAL STATE, 
		// MARK IT AS SPOTTED IF WE'RE BRIGHT ENOUGH
		// 2002-02-11 MODIFED BY S.G. 
		// Since I only identify visually, need to perform this even if spotted by radar in case I can ID it.
		if (
			/*!spottedSet &&  gai->skillLevel >= 3 && */
			((UnitClass *)GetCampaignObject())->GetSType() == STYPE_UNIT_AIR_DEFENSE && 
			gai == gai->battalionCommand && 
			!((UnitClass *)GetCampaignObject())->Broken() && 
			gai->GetAirTargetPtr() && 
			CheckLOS(gai->GetAirTargetPtr())
		){
			CampBaseClass *campBaseObj;
			if (gai->GetAirTargetPtr()->BaseData()->IsSim())
				campBaseObj = ((SimBaseClass *)gai->GetAirTargetPtr()->BaseData())->GetCampaignObject();
			else
				campBaseObj = (CampBaseClass *)gai->GetAirTargetPtr()->BaseData();

			// JB 011002 If campBaseObj is NULL the target may be chaff

			if (!spottedSet && campBaseObj && !(campBaseObj->GetSpotted(GetTeam())) && campBaseObj->IsFlight())
				RequestIntercept((FlightClass *)campBaseObj, GetTeam());

			if (campBaseObj)
				campBaseObj->SetSpotted(GetTeam(),TheCampaign.CurrentTime, 1);
				// 2002-02-11 MODIFIED BY S.G. Visual detection means identified as well
		}
		// END OF ADDED SECTION

		// KCK: When should we run a target update cycle?
		if (SimLibElapsedTime > lastProcess){
			gai->ProcessTargeting();
			lastProcess = SimLibElapsedTime + processRate;
		}

		// KCK: Check if it's ok to think
		if (SimLibElapsedTime > lastThought ){
			// do movement and (possibly) firing....
			gai->Process ();
			lastThought = SimLibElapsedTime + thoughtRate;
		}

		// RV - Biker - Only allow SAM fire if radar still does work
		SimWeaponClass *theWeapon = Sms->GetCurrentWeapon();

		// FRB - This version seems to give SAMs a little more activity
		if(SimLibElapsedTime > nextSamFireTime  && !allowSamFire){
			allowSamFire = TRUE;
		}

		// Biker's version
		//if(SimLibElapsedTime > nextSamFireTime  && !allowSamFire)
		//{
		//	if (radarDown == false || (theWeapon && theWeapon->IsMissile() && theWeapon->sensorArray[0]->Type() == SensorClass::IRST))
		//		allowSamFire = TRUE;
		//}

		// Move and update delta;
		gai->Move_Towards_Dest();
		
		// edg: always insure that our Z position is valid for the entity.
		// the draw pointer should have this value
		// KCK NOTE: The Z we have is actually LAST FRAME's Z. Probably not a big deal.
		SetPosition(
			XPos() + XDelta() * SimLibMajorFrameTime,
			YPos() + YDelta() * SimLibMajorFrameTime,
			groundZ 
		);
		// do firing
		// this also does weapon keep alive
		if ( Sms ){
			gai->Fire();
		}
	}

	// KCK: I simplified this some. This is now speed squared.
	speedScale = XDelta()*XDelta() + YDelta()*YDelta();
	
	// set our level of detail
	if ( gai == gai->battalionCommand ){
		gai->SetDistLOD();
	}
	else{
		gai->distLOD = gai->battalionCommand->distLOD;
	}
	
	// do some extra LOD stuff: if the unit is not a lead veh amd the
	// distLOD is less than a certain value, remove it from the draw
	// list.
	if (drawPointer && gai->rank != GNDAI_BATTALION_COMMANDER){
		// distLOD cutoff by ranking (KCK: This is explicit for testing, could be a formula/table)
		if (gai->rank & GNDAI_COMPANY_LEADER){
			labelLOD = .5F;
			drawLOD = .25F;
		}
		else if (gai->rank & GNDAI_PLATOON_LEADER){
			labelLOD = .925F;
			drawLOD = .5F;
		}
		else {
			labelLOD = 1.1F;
			drawLOD = .75F;
		}

		// RV - Biker - Why do this maybe helpful knowing which vehicle has problems
		// Determine wether to draw label or not
		if (gai->distLOD < labelLOD){
			if (!IsSetLocalFlag(NOT_LABELED)){
				drawPointer->SetLabel ("", 0xff00ff00);		// Don't label
				SetLocalFlag(NOT_LABELED);
			}
		}
		else if (IsSetLocalFlag(NOT_LABELED)){
			SetLabel(this);
			UnSetLocalFlag(NOT_LABELED);
		}

		//if (IsSetLocalFlag(NOT_LABELED)) {
		//	SetLabel(this);
		//	UnSetLocalFlag(NOT_LABELED);
		//}
	}
	
	if (!targetPtr){
		//rotate turret to be pointing forward again
		float maxAz = TURRET_ROTATE_RATE * SimLibMajorFrameTime;
		float maxEl = TURRET_ELEVATE_RATE * SimLibMajorFrameTime;
		float newEl;
		if (isAirDefense){
			newEl = 60.0F*DTR;
		}
		else {
			newEl = 0.0F;
		}

		float delta = newEl - GetDOFValue(AIRDEF_ELEV);
		if(delta > 180.0F*DTR){
			delta -= 180.0F*DTR;
		}
		else if(delta < -180.0F*DTR){
			delta += 180.0F*DTR;
		}

		// Do elevation adjustments
		if (delta > maxEl){
		    SetDOFInc(AIRDEF_ELEV, maxEl);
		}
		else if (delta < -maxEl){
		    SetDOFInc(AIRDEF_ELEV, -maxEl);
		}
		else {
		    SetDOF(AIRDEF_ELEV, newEl);
		}

		SetDOF(AIRDEF_ELEV, min(85.0F*DTR, max(GetDOFValue(AIRDEF_ELEV), 0.0F)));
		SetDOF(AIRDEF_ELEV2, GetDOFValue(AIRDEF_ELEV));
		
		delta = 0.0F - GetDOFValue(AIRDEF_AZIMUTH);
		
		if(delta > 180.0F*DTR){
		    delta -= 180.0F*DTR;
		}
		else if(delta < -180.0F*DTR){
		    delta += 180.0F*DTR;
		}
		
		// Now do the azmuth adjustments
		if (delta > maxAz){
		    SetDOFInc(AIRDEF_AZIMUTH, maxAz);
		}
		else if (delta < -maxAz){
		    SetDOFInc(AIRDEF_AZIMUTH, -maxAz);
		}
		// RV - Biker - Don't do this
		//else
		//	SetDOF(AIRDEF_AZIMUTH, 0.0F);
	}
	
	// Special shit by ground type
	if ( isFootSquad ){
		if ( speedScale > 0.0f ){
			// Couldn't this be done in the drawable class's update function???
			((DrawableGuys*)drawPointer)->SetSquadMoving( TRUE );
		}
		else {
			// Couldn't this be done in the drawable class's update function???
			((DrawableGuys*)drawPointer)->SetSquadMoving( FALSE );
		}
		
		// If we're less than 80% of the way from "FAR" toward the viewer, just draw one guy
		// otherwise, put 5 guys in a squad.
		if (gai->distLOD < 0.8f) {
			((DrawableGuys*)drawPointer)->SetNumInSquad( 1 );
		} 
		else {
			((DrawableGuys*)drawPointer)->SetNumInSquad( 5 );
		}
	} 
	// We're not a foot squad, so do the vehicle stuff
	else if ( !IsSetLocalFlag( IS_HIDDEN ) && speedScale > 300.0f )
	{
		// speedScale /= ( 900.0f * KPH_TO_FPS * KPH_TO_FPS);		// essentially 1.0F at 30 mph

	    // JPO - for engine noise
	    VehicleClassDataType *vc = GetVehicleClassData(Type() - VU_LAST_ENTITY_TYPE);
	    ShiAssert(FALSE == F4IsBadReadPtr(vc, sizeof *vc));
		// (a) Make sound:
		// everything sounds like a tank right now
		if ( GetCampaignObject()->IsBattalion() ){
		    //if (vc)
			if (vc && vc->EngineSound!=34){ // kludge prevent 34 from playing
				SoundPos.Sfx( vc->EngineSound, 0, 1.0, 0); // MLR 5/16/2004 - 
			}
			else{
				SoundPos.Sfx( SFX_TANK, 0, 1.0, 0); // MLR 5/16/2004 - 
			}
			
			// (b) Make dust
			// dustTimer += SimLibMajorFrameTime;
			// if ( dustTimer > max( 0.2f,  4.5f - speedScale - gai->distLOD * 3.3f ) )
			if ( ((rand() & 7) == 7) &&
				gSfxCount[ SFX_GROUND_DUSTCLOUD ] < gSfxLODCutoff &&
				gTotSfx < gSfxLODTotCutoff 
			){
				// reset the timer
				// dustTimer = 0.0f;
				
				pos.x += PRANDFloat() * 5.0f;
				pos.y += PRANDFloat() * 5.0f;
				pos.z = groundZ;

				// RV - Biker - Move that smoke more behind the vehicle 
				mlTrig		trig;
				mlSinCos (&trig, Yaw());

				pos.x -= 15.0f*trig.cos;
				pos.y -= 15.0f*trig.sin;

				vec.x = PRANDFloat() * 5.0f;
				vec.y = PRANDFloat() * 5.0f;
				vec.z = -20.0f;
				
				//JAM 24Oct03 - No dust trails when it's raining.
				if(realWeather->weatherCondition < INCLEMENT){
					/*
					OTWDriver.AddSfxRequest(
						new SfxClass (SFX_VEHICLE_DUST,				// type //JAM 03Oct03
	//					new SfxClass (SFX_GROUND_DUSTCLOUD,			// type
						SFX_USES_GRAVITY | SFX_NO_DOWN_VECTOR | SFX_MOVES | SFX_NO_GROUND_CHECK,
						&pos,							// world pos
						&vec,
						1.0f,							// time to live
						1.f)); //JAM 03Oct03 8.5f ));		// scale
						*/
					DrawableParticleSys::PS_AddParticleEx((SFX_VEHICLE_DUST + 1),
									&pos,
									&vec);
				}
			}
			
			// (c) Make sure we're using our 'Moving' model (i.e. Trucked artillery, APC, etc)
			if (truckDrawable){
				// Keep truck 20 feet behind us (HACK HACK)
				Tpoint		truckPos;
				mlTrig		trig;
				mlSinCos (&trig, Yaw());
				truckPos.x = XPos()-20.0F*trig.cos;
				truckPos.y = YPos()-20.0F*trig.sin;
				truckPos.z = ZPos();
				truckDrawable->Update(&truckPos, Yaw()+PI);
			}

			if (isTowed || hasCrew){
				SetSwitch(0,0x2);
			}
		}
		else // itsa task force
		{
			if (vc){
				SoundPos.Sfx( vc->EngineSound, 0, 1.0, 0);
			}
			else {
				SoundPos.Sfx( SFX_SHIP, 0, 1.0, 0);
			}
			
			//RV - I-Hawk - Do wakes only at some cases
			if ( (rand() & 7) == 7 )
			{
				//I-Hawk - not using all this anymore
				//
				// reset the timer
				// dustTimer = 0.0f;
				//float ttl;
				//static float trailspd = 5.0f;
				//static float bowfx = 0.92f;
				//static float sternfx = 0.75f;
				//float spdratio = GetVt() / ((UnitClass*)GetCampaignObject())->GetMaxSpeed();

				float radius;
				if ( drawPointer ){
					radius = drawPointer->Radius(); // JPO from 0.15 - now done inline
				}
				else{
					radius = 90.0f;
				}
				
				//I-Hawk - Fixed position for ships wakes, effect "delay" in position is 
				//handled by PS now. No more the "V shape" of water wakes.

				pos.x = XPos() + XDelta() * SimLibMajorFrameTime;
				pos.y = YPos() + YDelta() * SimLibMajorFrameTime;
				pos.z = groundZ;

				//// JPO - think this is sideways on.
				///*
				//vec.x = dmx[1][0] * spdratio * PRANDFloat() * trailspd;
				//vec.y = dmx[1][1] * spdratio * PRANDFloat() * trailspd;
				//vec.z = 0.5f; // from -20 JPO
				//*/

				//I-Hawk - More correct vector for wakes
				vec.x = XDelta();
				vec.y = YDelta();
				vec.z = 0.0f;


				//I-Hawk - Separate wake effect for different ships size
				int theSFX;
			
				if ( radius < 200.0f )
				{
					theSFX = SFX_WATER_WAKE_SMALL;
				}

				else if ( radius >= 200.0f && radius < 400.0f )
				{
					theSFX = SFX_WATER_WAKE_MEDIUM;
				}

				else if ( radius >= 400.0f )
				{
					theSFX = SFX_WATER_WAKE_LARGE;
				}
	
				//I-Hawk - The PS
				DrawableParticleSys::PS_AddParticleEx((theSFX + 1),
									&pos,
									&vec);
			}
		}
	}
	// Otherwise, we're not moving or are hidden. Do some stuff
	else {
		// (b) Make sure we're using our 'Holding' model (i.e. Unlimbered artillery, troops prone, etc)
		if (truckDrawable){
			// Once we stop, our truck doesn't move at all - but sits further away than when moving
			Tpoint truckPos;
			truckPos.x = XPos() + 40.0F;
			truckPos.y = YPos();
			truckPos.z = 0.0F;
			truckDrawable->Update(&truckPos, Yaw());
		}
		if (isTowed || hasCrew){
			SetSwitch(0,0x1);
		}
	}
	
	// ACMI Output
    if (gACMIRec.IsRecording() && (SimLibFrameCount & 0x0f ) == 0){
		ACMIGenPositionRecord genPos;
		genPos.hdr.time = SimLibElapsedTime * MSEC_TO_SEC + OTWDriver.todOffset;
		genPos.data.type = Type();
		genPos.data.uniqueID = ACMIIDTable->Add(Id(),NULL,TeamInfo[GetTeam()]->GetColor());//.num_;
		genPos.data.x = XPos();
		genPos.data.y = YPos();
		genPos.data.z = ZPos();
		genPos.data.roll = Roll();
		genPos.data.pitch = Pitch();
		genPos.data.yaw = Yaw();
		// Remove		genPos.data.teamColor = TeamInfo[GetTeam()]->GetColor();
		gACMIRec.GenPositionRecord( &genPos );
	}

	return IsLocal();
}
예제 #12
0
void HelicopterClass::DoWeapons (void)
{
int fireFlag;
// MissileClass* theMissile;
Tpoint pos, vec;

   // Guns
   fireFlag = fireGun;
   if (Guns)
   {
      Guns->Exec(&fireFlag, gunDmx, &platformAngles, targetPtr, FALSE);

      if (fireFlag)
      {
#ifdef MLR_NEWSNDCODE	     
		  SoundPos.Sfx( SFX_MCGUN );
#else
		 F4SoundFXSetPos( SFX_MCGUN, 0, XPos(), YPos(), ZPos(), 1.0f , 0 , XDelta(),YDelta(),ZDelta());
#endif

		pos.x = XPos();
		pos.y = YPos();
		// RV - Biker - Adjust gun smoke position
		//pos.z = ZPos() - 5.0f;
		pos.z = ZPos() + 1.0f + offsetZ;

		vec.x = PRANDFloat() * 30.0f;
		vec.y = PRANDFloat() * 30.0f;
		vec.z = -PRANDFloatPos() * 30.0f;

		//RV - I-Hawk - changing all LIGHT_CLOUD weapons effects calls
		// to more appropriate GUN_SMOKE effect here
		/*
		OTWDriver.AddSfxRequest(
			new SfxClass ( SFX_GUN_SMOKE,		// type
			SFX_MOVES,
			&pos,					// world pos
			&vec,					// vel vector
			2.3f,					// time to live
			2.0f ) );				// scale
			*/
		DrawableParticleSys::PS_AddParticleEx((SFX_GUN_SMOKE + 1),
												&pos,
												&vec);

         if (!IsFiring())
         {
            // KCK: This has been moved to GunClass::Exec, since that's where we generate
            // new bullets
//            SendFireMessage ((SimWeaponClass*)Guns, FalconWeaponsFire::GUN, TRUE, targetPtr);

			#ifdef _DEBUG
			SimVehicleClass *theObject;
			if ( targetPtr )
			{
				theObject = (SimVehicleClass *)targetPtr->BaseData();
/*				if ( theObject->IsAirplane() )
					MonoPrint( "HELO BRAIN Firing Guns at Air Unit\n" );
				else if ( theObject->IsHelicopter() )
					MonoPrint( "HELO BRAIN Firing Guns at Helo Unit\n" );
				else if ( theObject->IsGroundVehicle() )
					MonoPrint( "HELO BRAIN Firing Guns at Ground Unit\n" );
*/			}
			#endif
         }
         SetFiring(TRUE);
      }
      else
      {
         if (IsFiring())
         {
            SendFireMessage ((SimWeaponClass*)Guns, FalconWeaponsFire::GUN, FALSE, targetPtr);
         }
         SetFiring(FALSE);
      }
   }

   /*
   ** edg: no more FCC stuff here.  All done in hdigi now
   if ( FCC->releaseConsent && Sms->curWeapon )
   {
	   if (FCC->GetMasterMode() == FireControlComputer::Missile ||
		   FCC->GetMasterMode() == FireControlComputer::Dogfight ||
		   FCC->GetMasterMode() == FireControlComputer::MissileOverride)
	   {
			 theMissile = (MissileClass *)Sms->curWeapon;
			 if (Sms->LaunchMissile())
			 {
				SendFireMessage ((SimWeaponClass*)theMissile, FalconWeaponsFire::SRM, TRUE, targetPtr);
	
			   	fireMissile = FALSE;
			   	F4SoundFXSetPos( SFX_MISSILE1, 0, XPos(), YPos(), ZPos(), 1.0f );
			 }
	
	   } 
	   else if (FCC->GetMasterMode() == FireControlComputer::AirGroundMissile)
	   {
			 theMissile = (MissileClass *)Sms->curWeapon;
			 if (Sms->LaunchMissile())
			 {
				SendFireMessage ((SimWeaponClass*)theMissile, FalconWeaponsFire::AGM, TRUE, targetPtr);
	
				fireMissile = FALSE;
				F4SoundFXSetPos( SFX_MISSILE2, 0, XPos(), YPos(), ZPos(), 1.0f );
			 }
	
	   } 
      else if (FCC->GetMasterMode() == FireControlComputer::AirGroundBomb &&
         FCC->GetSubMode() == FireControlComputer::RCKT)
      {
         if (FCC->bombPickle && Sms->curWeapon && !OnGround())
         {
            // Play the sound
            F4SoundFXSetPos( SFX_RCKTLOOP, TRUE, XPos(), YPos(), ZPos(), 1.0f );

			theMissile = (MissileClass *)Sms->curWeapon;

            if (Sms->LaunchRocket())
            {

               // Stop firing
               FCC->bombPickle = FALSE;
               FCC->postDrop = TRUE;

               // Play the sound
               F4SoundFXSetPos( SFX_MISSILE3, TRUE, XPos(), YPos(), ZPos(), 1.0f );

               // Drop a message
               SendFireMessage (theMissile, FalconWeaponsFire::Rocket, TRUE, targetPtr);
            }
         }
      }
   }
   */

   /*
   else if (FCC->GetMasterMode() == FireControlComputer::AirGroundBomb)
   {
      curWeapon = Sms->curWeapon;
      if (FCC->bombPickle)
      {
         SendFireMessage ((SimWeaponClass*)curWeapon, FalconWeaponsFire::BMB, TRUE, targetPtr);
         if (Sms->DropBomb())
         {
            FCC->bombPickle = FALSE;
            FCC->postDrop = TRUE;
         }
      }
   }
   */

   // Handle missiles launched but still on the rail
	Sms->Exec();
}