Example #1
0
void DoMissileSmoke (CObject *objP)
{
	int				nParts, nSpeed, nLife, nObject, nSmoke;
	float				nScale = 1.75f;
	tThrusterInfo	ti;

nObject = objP->Index ();
if (!(SHOW_SMOKE && gameOpts->render.particles.bMissiles)) {
	if (particleManager.GetObjectSystem (nObject) >= 0)
		KillObjectSmoke (nObject);
	return;
	}
if ((objP->info.xShields < 0) || (objP->info.nFlags & (OF_SHOULD_BE_DEAD | OF_DESTROYED)))
	nParts = 0;
else {
	nSpeed = WI_speed (objP->info.nId, gameStates.app.nDifficultyLevel);
	nLife = gameOpts->render.particles.nLife [3] + 1;
#if 1
	nParts = int (MSL_MAX_PARTS * X2F (nSpeed) / (34.0f * (4 - nLife)));
	if ((objP->info.nId == EARTHSHAKER_MEGA_ID) || (objP->info.nId == ROBOT_SHAKER_MEGA_ID))
		nParts /= 2;

#else
	nParts = (objP->info.nId == EARTHSHAKER_ID) ? 1500 :
				(objP->info.nId == MEGAMSL_ID) ? 1400 :
				(objP->info.nId == SMARTMSL_ID) ? 1300 :
				1200;
#endif
	}
if (nParts) {
	if (0 > (nSmoke = particleManager.GetObjectSystem (nObject))) {
		if (!gameOpts->render.particles.bSyncSizes) {
			nParts = -MAX_PARTICLES (nParts, gameOpts->render.particles.nDens [3]);
			nScale = PARTICLE_SIZE (gameOpts->render.particles.nSize [3], nScale);
			}
		nSmoke = particleManager.Create (&objP->info.position.vPos, NULL, NULL, objP->info.nSegment, 1, nParts, nScale,
													gameOpts->render.particles.bSyncSizes ? -1 : gameOpts->render.particles.nSize [3],
													1, nLife * MSL_PART_LIFE, MSL_PART_SPEED, SMOKE_PARTICLES, nObject, smokeColors + 1, 1, -1);
		if (nSmoke < 0)
			return;
		particleManager.SetObjectSystem (nObject, nSmoke);
		}
	CalcThrusterPos (objP, &ti, 0);
	particleManager.SetPos (nSmoke, ti.vPos, NULL, objP->info.nSegment);
	}
else
	KillObjectSmoke (nObject);
}
Example #2
0
void DoMissileSmoke (tObject *objP)
{
	int				nParts, nSpeed, nLife, i;
	float				nScale = 1.5f;
	tThrusterInfo	ti;

i = OBJ_IDX (objP);
if (!(SHOW_SMOKE && gameOpts->render.smoke.bMissiles)) {
	if (gameData.smoke.objects [i] >= 0)
		KillObjectSmoke (i);
	return;
	}
if ((objP->info.xShields < 0) || (objP->info.nFlags & (OF_SHOULD_BE_DEAD | OF_DESTROYED)))
	nParts = 0;
else {
	nSpeed = WI_speed (objP->info.nId, gameStates.app.nDifficultyLevel);
	nLife = gameOpts->render.smoke.nLife [3] + 1;
#if 1
	nParts = (int) (MSL_MAX_PARTS * X2F (nSpeed) / (40.0f * (4 - nLife)));
	if ((objP->info.nId == EARTHSHAKER_MEGA_ID) || (objP->info.nId == ROBOT_SHAKER_MEGA_ID))
		nParts /= 2;

#else
	nParts = (objP->info.nId == EARTHSHAKER_ID) ? 1500 :
				(objP->info.nId == MEGAMSL_ID) ? 1400 :
				(objP->info.nId == SMARTMSL_ID) ? 1300 :
				1200;
#endif
	}
if (nParts) {
	if (gameData.smoke.objects [i] < 0) {
		if (!gameOpts->render.smoke.bSyncSizes) {
			nParts = -MAX_PARTICLES (nParts, gameOpts->render.smoke.nDens [3]);
			nScale = PARTICLE_SIZE (gameOpts->render.smoke.nSize [3], nScale);
			}
		SetSmokeObject (i, CreateSmoke (&objP->info.position.vPos, NULL, NULL, objP->info.nSegment, 1, nParts, nScale,
												  gameOpts->render.smoke.bSyncSizes ? -1 : gameOpts->render.smoke.nSize [3],
												  1, nLife * MSL_PART_LIFE, MSL_PART_SPEED, SMOKE_PARTICLES, i, smokeColors + 1, 1, -1));
		}
	CalcThrusterPos (objP, &ti, 0);
	SetSmokePos (gameData.smoke.objects [i], ti.vPos, NULL, objP->info.nSegment);
	}
else
	KillObjectSmoke (i);
}
CFixVector *TransformGunPoint (CObject *objP, CFixVector *vGunPoints, int nGun,
										 fix xDelay, ubyte nLaserType, CFixVector *vMuzzle, CFixMatrix *mP)
{
	int						bSpectate = SPECTATOR (objP);
	tObjTransformation*	posP = bSpectate ? &gameStates.app.playerPos : &objP->info.position;
	CFixMatrix				m, *viewP;
	CFixVector				v [2];
#if FULL_COCKPIT_OFFS
	int						bLaserOffs = ((gameStates.render.cockpit.nType == CM_FULL_COCKPIT) &&
												  (objP->Index () == LOCALPLAYER.nObject));
#else
	int						bLaserOffs = 0;
#endif

if (nGun < 0) {	// use center between gunPoints nGun and nGun + 1
	*v = vGunPoints [-nGun] + vGunPoints [-nGun - 1];
//	VmVecScale (VmVecAdd (v, vGunPoints - nGun, vGunPoints - nGun - 1), I2X (1) / 2);
	*v *= (I2X (1) / 2);
}
else {
	v [0] = vGunPoints [nGun];
	if (bLaserOffs)
		v [0] += posP->mOrient.UVec () * LASER_OFFS;
	}
if (!mP)
	mP = &m;
if (bSpectate) {
   viewP = mP;
	*viewP = posP->mOrient.Transpose ();
}
else
   viewP = objP->View ();
v[1] = *viewP * v [0];
memcpy (mP, &posP->mOrient, sizeof (CFixMatrix));
if (nGun < 0)
	v[1] += (*mP).UVec () * (-2 * v->Mag ());
(*vMuzzle) = posP->vPos + v [1];
//	If supposed to fire at a delayed time (xDelay), then move this point backwards.
if (xDelay)
	*vMuzzle += mP->FVec () * (-FixMul (xDelay, WI_speed (nLaserType, gameStates.app.nDifficultyLevel)));
return vMuzzle;
}
Example #4
0
void ReadFlyingControls (CObject *objP)
{
	fix		forwardThrustTime;
	CObject*	gmObjP;
	int		bMulti;

if (gameData.time.xFrame <= 0)
	return;

if (gameStates.app.bPlayerIsDead || gameStates.app.bEnterGame) {
	StopPlayerMovement ();
	FlushInput ();
/*
	VmVecZero(&objP->mType.physInfo.rotThrust);
	VmVecZero(&objP->mType.physInfo.thrust);
	VmVecZero(&objP->mType.physInfo.velocity);
*/
	gameStates.app.bEnterGame--;
	return;
	}

if ((objP->info.nType != OBJ_PLAYER) || (objP->info.nId != gameData.multiplayer.nLocalPlayer))
	return;	//references to CPlayerShip require that this obj be the CPlayerData

tGuidedMissileInfo *gmiP = gameData.objs.guidedMissile + gameData.multiplayer.nLocalPlayer;
gmObjP = gmiP->objP;
if (gmObjP && (gmObjP->info.nSignature == gmiP->nSignature)) {
	CAngleVector	vRotAngs;
	CFixMatrix		mRot, mOrient;
	fix				speed;

	//this is a horrible hack.  guided missile stuff should not be
	//handled in the middle of a routine that is dealing with the CPlayerData
	objP->mType.physInfo.rotThrust.SetZero ();
	vRotAngs [PA] = Controls [0].pitchTime / 2 + gameStates.gameplay.seismic.nMagnitude / 64;
	vRotAngs [BA] = Controls [0].bankTime / 2 + gameStates.gameplay.seismic.nMagnitude / 16;
	vRotAngs [HA] = Controls [0].headingTime / 2 + gameStates.gameplay.seismic.nMagnitude / 64;
	mRot = CFixMatrix::Create (vRotAngs);
	mOrient = gmObjP->info.position.mOrient * mRot;
	gmObjP->info.position.mOrient = mOrient;
	speed = WI_speed (gmObjP->info.nId, gameStates.app.nDifficultyLevel);
	gmObjP->mType.physInfo.velocity = gmObjP->info.position.mOrient.FVec () * speed;
	if(IsMultiGame)
		MultiSendGuidedInfo (gmObjP, 0);
	}
else {
#if DBG
	if (Controls [0].headingTime)
		Controls [0].headingTime = Controls [0].headingTime;
#endif
	objP->mType.physInfo.rotThrust = CFixVector::Create (Controls [0].pitchTime,
	                                                     Controls [0].headingTime, //Controls [0].headingTime ? I2X (1) / 4 : 0; //Controls [0].headingTime;
	                                                     Controls [0].bankTime);
	}
forwardThrustTime = Controls [0].forwardThrustTime;
if ((LOCALPLAYER.flags & PLAYER_FLAGS_AFTERBURNER) && (d_rand () < OBJECTS [gameData.multiplayer.nLocalPlayer].DriveDamage ())) {
	if (Controls [0].afterburnerState) {			//CPlayerData has key down
		fix afterburner_scale;
		int oldCount,newCount;

		//add in value from 0..1
		afterburner_scale = I2X (1) + min (I2X (1) / 2, gameData.physics.xAfterburnerCharge) * 2;
		forwardThrustTime = FixMul (gameData.time.xFrame, afterburner_scale);	//based on full thrust
		oldCount = (gameData.physics.xAfterburnerCharge / (DROP_DELTA_TIME / AFTERBURNER_USE_SECS));
		if (!gameStates.gameplay.bAfterburnerCheat)
			gameData.physics.xAfterburnerCharge -= gameData.time.xFrame / AFTERBURNER_USE_SECS;
		if (gameData.physics.xAfterburnerCharge < 0)
			gameData.physics.xAfterburnerCharge = 0;
		newCount = (gameData.physics.xAfterburnerCharge / (DROP_DELTA_TIME / AFTERBURNER_USE_SECS));
		if (gameStates.app.bNostalgia && (oldCount != newCount))
			gameStates.render.bDropAfterburnerBlob = 1;	//drop blob (after physics called)
		}
	else {
		fix xChargeUp = min (gameData.time.xFrame / 8, I2X (1) - gameData.physics.xAfterburnerCharge);	//recharge over 8 seconds
		if (xChargeUp > 0) {
			fix xCurEnergy = LOCALPLAYER.energy - I2X (10);
			xCurEnergy = max (xCurEnergy, 0) / 10;	//don't drop below 10
			if (xCurEnergy > 0) {	//maybe limit charge up by energy
				xChargeUp = min (xChargeUp, xCurEnergy / 10);
				if (xChargeUp > 0) {
					gameData.physics.xAfterburnerCharge += xChargeUp;
					LOCALPLAYER.energy -= xChargeUp * 100 / 10;	//full charge uses 10% of energy
					}
				}
			}
		}
	}
// Set CObject's thrust vector for forward/backward
objP->mType.physInfo.thrust = objP->info.position.mOrient.FVec () * forwardThrustTime;
// slide left/right
objP->mType.physInfo.thrust += objP->info.position.mOrient.RVec () * Controls [0].sidewaysThrustTime;
// slide up/down
objP->mType.physInfo.thrust += objP->info.position.mOrient.UVec () * Controls [0].verticalThrustTime;
objP->mType.physInfo.thrust *= 2 * objP->DriveDamage ();
if (!gameStates.input.bSkipControls)
	memcpy (&gameData.physics.playerThrust, &objP->mType.physInfo.thrust, sizeof (gameData.physics.playerThrust));
bMulti = IsMultiGame;
if ((objP->mType.physInfo.flags & PF_WIGGLE) && !gameData.objs.speedBoost [objP->Index ()].bBoosted) {
#if 1//!DBG
	WiggleObject (objP);
#endif
	}
	// As of now, objP->mType.physInfo.thrust & objP->mType.physInfo.rotThrust are
	// in units of time... In other words, if thrust==gameData.time.xFrame, that
	// means that the user was holding down the MaxThrust key for the
	// whole frame.  So we just scale them up by the max, and divide by
	// gameData.time.xFrame to make them independant of framerate

	//	Prevent divide overflows on high frame rates.
	//	In a signed divide, you get an overflow if num >= div<<15
fix	ft = gameData.time.xFrame;

//	Note, you must check for ft < I2X (1)/2, else you can get an overflow  on the << 15.
if ((ft < I2X (1)/2) && ((ft << 15) <= gameData.pig.ship.player->maxThrust))
	ft = (gameData.pig.ship.player->maxThrust >> 15) + 1;
objP->mType.physInfo.thrust *= FixDiv (gameData.pig.ship.player->maxThrust, ft);
if ((ft < I2X (1)/2) && ((ft << 15) <= gameData.pig.ship.player->maxRotThrust))
	ft = (gameData.pig.ship.player->maxThrust >> 15) + 1;
objP->mType.physInfo.rotThrust *= FixDiv (gameData.pig.ship.player->maxRotThrust, ft);
}
//-------------------------------------------------------------------------------------------
//sequence this weapon object for this _frame_ (underscores added here to aid MK in his searching!)
void DoWeaponSequence (CObject *objP)
{
	CObject	*gmObjP;
	fix		xWeaponSpeed, xScaleFactor, xDistToTarget;

Assert (objP->info.controlType == CT_WEAPON);
//	Ok, this is a big hack by MK.
//	If you want an CObject to last for exactly one frame, then give it a lifeleft of ONE_FRAME_TIME
if (objP->info.xLifeLeft == ONE_FRAME_TIME) {
	if (IsMultiGame)
		objP->info.xLifeLeft = OMEGA_MULTI_LIFELEFT;
	else
		objP->info.xLifeLeft = 0;
	objP->info.renderType = RT_NONE;
	}
if (objP->info.xLifeLeft < 0) {		// We died of old age
	objP->Die ();
	if (WI_damage_radius (objP->info.nId))
		objP->ExplodeBadassWeapon (objP->info.position.vPos);
	return;
	}
//delete weapons that are not moving
xWeaponSpeed = objP->mType.physInfo.velocity.Mag();
if (!((gameData.app.nFrameCount ^ objP->info.nSignature) & 3) &&
		(objP->info.nType == OBJ_WEAPON) && (objP->info.nId != FLARE_ID) &&
		(gameData.weapons.info [objP->info.nId].speed [gameStates.app.nDifficultyLevel] > 0) &&
		(xWeaponSpeed < I2X (2))) {
	ReleaseObject (objP->Index ());
	return;
	}
if ((objP->info.nType == OBJ_WEAPON) && (objP->info.nId == FUSION_ID)) {		//always set fusion weapon to max vel
	CFixVector::Normalize (objP->mType.physInfo.velocity);
	objP->mType.physInfo.velocity *= (WI_speed (objP->info.nId,gameStates.app.nDifficultyLevel));
	}
//	For homing missiles, turn towards target. (unless it's the guided missile)
if ((gameData.laser.xUpdateTime >= I2X (1) / 40) &&
	 (objP->info.nType == OBJ_WEAPON) &&
    (gameStates.app.cheats.bHomingWeapons || WI_homingFlag (objP->info.nId)) &&
	 !(objP->info.nFlags & PF_HAS_BOUNCED) &&
	 !((objP->info.nId == GUIDEDMSL_ID) &&
	   (objP == (gmObjP = gameData.objs.guidedMissile [OBJECTS [objP->cType.laserInfo.parent.nObject].info.nId].objP)) &&
	   (objP->info.nSignature == gmObjP->info.nSignature))) {
	fix xFrameTime;
	for (xFrameTime = gameData.laser.xUpdateTime; xFrameTime >= I2X (1) / 40; xFrameTime -= I2X (1) / 40) {
		CFixVector	vVecToObject, vNewVel;
		fix			dot = I2X (1);
		fix			speed, xMaxSpeed, xDist;
		int			nObjId = objP->info.nId;
		//	For first 1/2 second of life, missile flies straight.
		//if (objP->cType.laserInfo.xCreationTime + HomingMslStraightTime (nObjId) < gameData.time.xGame) 
			{
			int	nHomingTarget = objP->cType.laserInfo.nHomingTarget;

			//	If it's time to do tracking, then it's time to grow up, stop bouncing and start exploding!.
			if ((nObjId == ROBOT_SMARTMINE_BLOB_ID) ||
				 (nObjId == ROBOT_SMARTMSL_BLOB_ID) ||
				 (nObjId == SMARTMINE_BLOB_ID) ||
				 (nObjId == SMARTMSL_BLOB_ID) ||
				 (nObjId == EARTHSHAKER_MEGA_ID))
				objP->mType.physInfo.flags &= ~PF_BOUNCE;

			//	Make sure the CObject we are tracking is still trackable.
			nHomingTarget = TrackHomingTarget (nHomingTarget, objP, &dot);
			if (nHomingTarget != -1) {
				if (nHomingTarget == LOCALPLAYER.nObject) {
					xDistToTarget = CFixVector::Dist (objP->info.position.vPos, OBJECTS [nHomingTarget].info.position.vPos);
					if ((xDistToTarget < LOCALPLAYER.homingObjectDist) || (LOCALPLAYER.homingObjectDist < 0))
						LOCALPLAYER.homingObjectDist = xDistToTarget;
					}
				vVecToObject = OBJECTS [nHomingTarget].info.position.vPos - objP->info.position.vPos;
				xDist = CFixVector::Normalize (vVecToObject);
				vNewVel = objP->mType.physInfo.velocity;
				speed = CFixVector::Normalize (vNewVel);
				xMaxSpeed = WI_speed (objP->info.nId,gameStates.app.nDifficultyLevel);
				if (speed + I2X (1) < xMaxSpeed) {
					speed += FixMul (xMaxSpeed, I2X (1) / 80);
					if (speed > xMaxSpeed)
						speed = xMaxSpeed;
					}
				if (EGI_FLAG (bEnhancedShakers, 0, 0, 0) && (objP->info.nId == EARTHSHAKER_MEGA_ID)) {
					fix h = (objP->info.xLifeLeft + I2X (1) - 1) / I2X (1);

					if (h > 7)
						vVecToObject *= (I2X (1) / (h - 6));
					}
	#if 0
				vVecToObject *= HomingMslScale ();
	#endif
				vNewVel += vVecToObject;
				//	The boss' smart children track better...
				if (gameData.weapons.info [objP->info.nId].renderType != WEAPON_RENDER_POLYMODEL)
					vNewVel += vVecToObject;
				CFixVector::Normalize (vNewVel);
				CFixVector vOldVel = objP->mType.physInfo.velocity;
				objP->mType.physInfo.velocity = vNewVel;
				objP->mType.physInfo.velocity *= speed;
				CFixVector vTest = objP->info.position.vPos + vNewVel * xDist;
				if (!CanSeePoint (NULL, &objP->info.position.vPos, &vTest, objP->info.nSegment, 3 * objP->info.xSize / 2))
					objP->mType.physInfo.velocity = vOldVel;
				else {	//	Subtract off life proportional to amount turned. For hardest turn, it will lose 2 seconds per second.
					dot = abs (I2X (1) - dot);
					objP->info.xLifeLeft -= FixMul (dot * 32, I2X (1) / 40);
					}

				//	Only polygon OBJECTS have visible orientation, so only they should turn.
				if (gameData.weapons.info [objP->info.nId].renderType == WEAPON_RENDER_POLYMODEL)
					HomingMissileTurnTowardsVelocity (objP, &vNewVel);		//	vNewVel is normalized velocity.
				}
			}
		}
	}
	//	Make sure weapon is not moving faster than allowed speed.
if ((objP->info.nType == OBJ_WEAPON) &&
	 (xWeaponSpeed > WI_speed (objP->info.nId, gameStates.app.nDifficultyLevel))) {
	//	Only slow down if not allowed to move.  Makes sense, huh?  Allows proxbombs to get moved by physics force. --MK, 2/13/96
	if (WI_speed (objP->info.nId, gameStates.app.nDifficultyLevel)) {
		xScaleFactor = FixDiv (WI_speed (objP->info.nId,gameStates.app.nDifficultyLevel), xWeaponSpeed);
		objP->mType.physInfo.velocity *= xScaleFactor;
		}
	}
}