After these changes, the 2 functions look like attached, with the also 
attached differences.
static void proj_InFlightDirectFunc( PROJECTILE *psProj )
{
	/* we want a delay between Las-Sats firing and actually hitting in multiPlayer
	magic number but that's how long the audio countdown message lasts! */
	const unsigned int LAS_SAT_DELAY = 8;
	int timeSoFar;
	int distancePercent; /* How far we are 0..100 */
	float distanceRatio; /* How far we are, 1.0==at target */
	float distanceExtensionFactor; /* Extended lifespan */
	Vector3i move;
	unsigned int i;
	// Projectile is missile:
	bool bMissile = false;
	WEAPON_STATS *psStats;

	CHECK_PROJECTILE(psProj);

	timeSoFar = gameTime - psProj->born;

	psStats = psProj->psWStats;
	ASSERT( psStats != NULL,
		"proj_InFlightDirectFunc: Invalid weapon stats pointer" );

	/* we want a delay between Las-Sats firing and actually hitting in multiPlayer
	magic number but that's how long the audio countdown message lasts! */
    if ( bMultiPlayer && psStats->weaponSubClass == WSC_LAS_SAT &&
		timeSoFar < LAS_SAT_DELAY * GAME_TICKS_PER_SEC )
	{
		return;
    }

	/* Calculate extended lifespan where appropriate */
	switch (psStats->weaponSubClass)
	{
		case WSC_MGUN:
		case WSC_COMMAND:
			distanceExtensionFactor = 1.2f;
			break;
		case WSC_CANNON:
		case WSC_BOMB:
		case WSC_ELECTRONIC:
		case WSC_EMP:
		case WSC_FLAME:
		case WSC_ENERGY:
		case WSC_GAUSS:
			distanceExtensionFactor = 1.5f;
			break;
		case WSC_AAGUN: // No extended distance
			distanceExtensionFactor = 1.0f;
			break;
		case WSC_ROCKET:
		case WSC_MISSILE:
		case WSC_SLOWROCKET:
		case WSC_SLOWMISSILE:
			bMissile = true; // Take the same extended targetDistance as artillery
		case WSC_COUNTER:
		case WSC_MORTARS:
		case WSC_HOWITZERS:
		case WSC_LAS_SAT:
			distanceExtensionFactor = 1.5f;
			break;
		default:
			// NUM_WEAPON_SUBCLASS and INVALID_SUBCLASS
			break;
	}

	/* Do movement */
	{
		unsigned int targetDistance, currentDistance;

		/* Calculate movement vector: */
		if ( psStats->movementModel == MM_HOMINGDIRECT && psProj->psDest )
		{
			/* If it's homing and it has a target (not a miss)... */
			move.x = psProj->psDest->pos.x - psProj->startX;
			move.y = psProj->psDest->pos.y - psProj->startY;
			move.z = psProj->psDest->pos.z - psProj->srcHeight;
		}
		else
		{
			move.x = psProj->tarX - psProj->startX;
			move.y = psProj->tarY - psProj->startY;
			move.z = psProj->altChange;
		}

		targetDistance = sqrtf( move.x*move.x + move.y*move.y );
		currentDistance = timeSoFar * psStats->flightSpeed / GAME_TICKS_PER_SEC;

		// Prevent div by zero:
		if ( targetDistance == 0 )
			targetDistance = 1;

		distanceRatio = (float)currentDistance / targetDistance;
		distancePercent = PERCENT(currentDistance, targetDistance);

		{
			/* Calculate next position */
			Vector3uw nextPos = {
				psProj->startX + (distanceRatio * move.x),
				psProj->startY + (distanceRatio * move.y),
				psProj->srcHeight + (distanceRatio * move.z)
			};

			/* impact if about to go off map else update coordinates */
			if ( !worldOnMap( nextPos.x, nextPos.y ) )
			{
				psProj->state = PROJ_IMPACT;
				setProjectileDestination(psProj, NULL);
				debug( LOG_NEVER, "**** projectile off map - removed ****\n" );
				return;
			}

			/* Update position */
			psProj->pos = nextPos;
		}
	}

	for (i = 0; i < numProjNaybors; i++)
	{
		BASE_OBJECT *psTempObj = asProjNaybors[i].psObj;

		CHECK_OBJECT(psTempObj);

		if ( psTempObj == psProj->psDamaged )
		{
			// Dont damage one target twice
			continue;
		}

		if ( psTempObj->died )
		{
			// Do not damage dead objects further
			continue;
		}

		if ( psTempObj->type == OBJ_PROJECTILE &&
			!( bMissile || ((PROJECTILE *)psTempObj)->psWStats->weaponSubClass == WSC_COUNTER ) )
		{
			// A projectile should not collide with another projectile unless it's a counter-missile weapon
			continue;
		}

		if ( psTempObj->type == OBJ_FEATURE &&
			!((FEATURE *)psTempObj)->psStats->damageable )
		{
			// Ignore oil resources, artifacts and other pickups
			continue;
		}

		if ( psTempObj->player == psProj->player ||
			aiCheckAlliances(psTempObj->player, psProj->player) )
		{
			// No friendly fire
			continue;
		}

		if ( psStats->surfaceToAir == SHOOT_IN_AIR &&
			( psTempObj->type == OBJ_STRUCTURE ||
				psTempObj->type == OBJ_FEATURE ||
				( psTempObj->type == OBJ_DROID && !vtolDroid((DROID *)psTempObj) )
			) )
		{
			// AA weapons should not hit buildings and non-vtol droids
			continue;
		}

		{
			// FIXME HACK Needed since we got those ugly Vector3uw floating around in BASE_OBJECT...
			Vector3i
				posProj = { psProj->pos.x, psProj->pos.y, psProj->pos.z },
				posTemp = { psTempObj->pos.x, psTempObj->pos.y, psTempObj->pos.z };

			Vector3i diff = Vector3i_Sub(posProj, posTemp);

			unsigned int targetHeight = establishTargetHeight(psTempObj);
			unsigned int targetRadius = establishTargetRadius(psTempObj);

			/* Height is always positive */
			diff.z = abs(diff.z);

			/* We hit! */
			if ( diff.z < targetHeight &&
				(diff.x*diff.x + diff.y*diff.y) < targetRadius * targetRadius )
			{
				setProjectileDestination(psProj, psTempObj);

				/* Buildings cannot be penetrated and we need a penetrating weapon */
				if ( psTempObj->type == OBJ_DROID && psStats->penetrate )
				{
					WEAPON asWeap = { psStats - asWeaponStats, 0, 0, 0, 0 };
					// Determine position to fire a missile at
					// (must be at least 0 because we don't use signed integers
					//  this shouldn't be larger than the height and width of the map either)
					Vector3i newDest = {
						psProj->startX + move.x * distanceExtensionFactor,
						psProj->startY + move.y * distanceExtensionFactor,
						psProj->srcHeight + move.z * distanceExtensionFactor
					};

					newDest.x = clip(newDest.x, 0, world_coord(mapWidth - 1));
					newDest.y = clip(newDest.y, 0, world_coord(mapHeight - 1));

					//Watermelon:just assume we damaged the chosen target
					setProjectileDamaged(psProj, psTempObj);

					proj_SendProjectile( &asWeap, (BASE_OBJECT*)psProj, psProj->player, newDest, NULL, true, -1 );
				}

				psProj->state = PROJ_IMPACT;

				return;
			}
		}
	}

	if ( distanceRatio > distanceExtensionFactor || /* We've traveled our maximum range */
		!mapObjIsAboveGround( (BASE_OBJECT *) psProj ) ) /* trying to travel through terrain */
	{
		/* Miss due to range or height */
		psProj->state = PROJ_IMPACT;
		setProjectileDestination(psProj, NULL); /* miss registered if NULL target */
		return;
	}

	/* Paint effects if visible */
	if ( gfxVisible(psProj) )
	{
		switch (psStats->weaponSubClass)
		{
			case WSC_FLAME:
			{
				Vector3i pos = { psProj->pos.x, psProj->pos.z-8, psProj->pos.y };
				effectGiveAuxVar(distancePercent);
				addEffect(&pos,EFFECT_EXPLOSION,EXPLOSION_TYPE_FLAMETHROWER,false,NULL,0);
			} break;
			case WSC_COMMAND:
			case WSC_ELECTRONIC:
			case WSC_EMP:
			{
				Vector3i pos = { psProj->pos.x, psProj->pos.z-8, psProj->pos.y };
				effectGiveAuxVar(distancePercent/2);
				addEffect(&pos,EFFECT_EXPLOSION,EXPLOSION_TYPE_LASER,false,NULL,0);
			} break;
			case WSC_ROCKET:
			case WSC_MISSILE:
			case WSC_SLOWROCKET:
			case WSC_SLOWMISSILE:
			{
				Vector3i pos = { psProj->pos.x, psProj->pos.z+8, psProj->pos.y };
				addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0);
			} break;
			default:
				/* add smoke trail to indirect weapons firing directly */
				if ( !proj_Direct(psStats) )
				{
					Vector3i pos = { psProj->pos.x, psProj->pos.z+4, psProj->pos.y };
					addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0);
				}
				/* Otherwise no effect */
				break;
		}
	}
}
static void proj_InFlightIndirectFunc( PROJECTILE *psProj )
{
	/* NOTE Main differences to direct projectiles:
		- Movement vector / pitch update
		- No extended radius
		- Some optimisations by leaving out tests which are never true (homing, AA, counter-missile, lassat)
	*/

	int timeSoFar;
	int distancePercent; /* How far we are 0..100 */
	float distanceRatio; /* How far we are, 1.0==at target */
	float distanceExtensionFactor; /* Extended lifespan */
	Vector3i move;
	unsigned int i;
	WEAPON_STATS *psStats;

	CHECK_PROJECTILE(psProj);

	timeSoFar = gameTime - psProj->born;

	psStats = psProj->psWStats;
	ASSERT( psStats != NULL,
		"proj_InFlightIndirectFunc: Invalid weapon stats pointer" );

	/* Calculate extended lifespan where appropriate */
	distanceExtensionFactor = 1.2f;

	/* Do movement */
	{
		unsigned int targetDistance, currentDistance;

		/* Calculate movement vector: */
		move.x = psProj->tarX - psProj->startX;
		move.y = psProj->tarY - psProj->startY;
		move.z = (psProj->vZ - (timeSoFar * ACC_GRAVITY / (GAME_TICKS_PER_SEC * 2))) * timeSoFar / GAME_TICKS_PER_SEC; // '2' because we reach our highest point in the mid of flight, when "vZ is 0".

		targetDistance = sqrtf( move.x*move.x + move.y*move.y );
		currentDistance = timeSoFar * psProj->vXY / GAME_TICKS_PER_SEC; // FIXME ARTILLERY

		// Prevent div by zero:
		if ( targetDistance == 0 )
			targetDistance = 1;

		distanceRatio = (float)currentDistance / targetDistance;
		distancePercent = PERCENT(currentDistance, targetDistance);

		{
			/* Calculate next position */
			Vector3uw nextPos = {
				psProj->startX + (distanceRatio * move.x),
				psProj->startY + (distanceRatio * move.y),
				psProj->srcHeight + move.z
			};

			/* impact if about to go off map else update coordinates */
			if ( !worldOnMap( nextPos.x, nextPos.y ) )
			{
				psProj->state = PROJ_IMPACT;
				setProjectileDestination(psProj, NULL);
				debug( LOG_NEVER, "**** projectile off map - removed ****\n" );
				return;
			}

			/* Update position */
			psProj->pos = nextPos;
		}
	}

	/* Update pitch */
	{
		float fVVert = psProj->vZ - (timeSoFar * ACC_GRAVITY / GAME_TICKS_PER_SEC);
		psProj->pitch = rad2degf(atan2f(fVVert, psProj->vXY));
	}

	for (i = 0; i < numProjNaybors; i++)
	{
		BASE_OBJECT *psTempObj = asProjNaybors[i].psObj;

		CHECK_OBJECT(psTempObj);

		if ( psTempObj == psProj->psDamaged )
		{
			// Dont damage one target twice
			continue;
		}

		if ( psTempObj->died )
		{
			// Do not damage dead objects further
			continue;
		}

		if ( psTempObj->type == OBJ_PROJECTILE )
		{
			// A projectile should not collide with another projectile unless it's a counter-missile weapon
			// FIXME Indirectly firing weapons are never counter-missiles?
			continue;
		}

		if ( psTempObj->type == OBJ_FEATURE &&
			!((FEATURE *)psTempObj)->psStats->damageable )
		{
			// Ignore oil resources, artifacts and other pickups
			continue;
		}

		if ( psTempObj->player == psProj->player ||
			aiCheckAlliances(psTempObj->player, psProj->player) )
		{
			// No friendly fire
			continue;
		}

		{
			// FIXME HACK Needed since we got those ugly Vector3uw floating around in BASE_OBJECT...
			Vector3i
				posProj = { psProj->pos.x, psProj->pos.y, psProj->pos.z },
				posTemp = { psTempObj->pos.x, psTempObj->pos.y, psTempObj->pos.z };

			Vector3i diff = Vector3i_Sub(posProj, posTemp);

			unsigned int targetHeight = establishTargetHeight(psTempObj);
			unsigned int targetRadius = establishTargetRadius(psTempObj);

			/* Height is always positive */
			diff.z = abs(diff.z);

			/* We hit! */
			if ( diff.z < targetHeight &&
				(diff.x*diff.x + diff.y*diff.y) < targetRadius * targetRadius )
			{
				setProjectileDestination(psProj, psTempObj);

				/* Buildings cannot be penetrated and we need a penetrating weapon */
				if ( psTempObj->type == OBJ_DROID && psStats->penetrate )
				{
					WEAPON asWeap = { psStats - asWeaponStats, 0, 0, 0, 0 };
					// Determine position to fire a missile at
					// (must be at least 0 because we don't use signed integers
					//  this shouldn't be larger than the height and width of the map either)
					Vector3i newDest = {
						psProj->startX + move.x * distanceExtensionFactor,
						psProj->startY + move.y * distanceExtensionFactor,
						psProj->srcHeight + move.z * distanceExtensionFactor
					};

					newDest.x = clip(newDest.x, 0, world_coord(mapWidth - 1));
					newDest.y = clip(newDest.y, 0, world_coord(mapHeight - 1));

					//Watermelon:just assume we damaged the chosen target
					setProjectileDamaged(psProj, psTempObj);

					proj_SendProjectile( &asWeap, (BASE_OBJECT*)psProj, psProj->player, newDest, NULL, true, -1 );
				}

				psProj->state = PROJ_IMPACT;

				return;
			}
		}
	}

	if ( distanceRatio > distanceExtensionFactor || /* We've traveled our maximum range */
		!mapObjIsAboveGround( (BASE_OBJECT *) psProj ) ) /* trying to travel through terrain */
	{
		/* Miss due to range or height */
		psProj->state = PROJ_IMPACT;
		setProjectileDestination(psProj, NULL); /* miss registered if NULL target */
		return;
	}

	/* Paint effects if visible */
	if ( gfxVisible(psProj) )
	{
		switch (psStats->weaponSubClass)
		{
			case WSC_FLAME:
			{
				Vector3i pos = { psProj->pos.x, psProj->pos.z-8, psProj->pos.y };
				effectGiveAuxVar(distancePercent);
				addEffect(&pos,EFFECT_EXPLOSION,EXPLOSION_TYPE_FLAMETHROWER,false,NULL,0);
			} break;
			case WSC_COMMAND:
			case WSC_ELECTRONIC:
			case WSC_EMP:
			{
				Vector3i pos = { psProj->pos.x, psProj->pos.z-8, psProj->pos.y };
				effectGiveAuxVar(distancePercent/2);
				addEffect(&pos,EFFECT_EXPLOSION,EXPLOSION_TYPE_LASER,false,NULL,0);
			} break;
			case WSC_ROCKET:
			case WSC_MISSILE:
			case WSC_SLOWROCKET:
			case WSC_SLOWMISSILE:
			{
				Vector3i pos = { psProj->pos.x, psProj->pos.z+8, psProj->pos.y };
				addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0);
			} break;
			default:
			{
				Vector3i pos = { psProj->pos.x, psProj->pos.z+4, psProj->pos.y };
				addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0);
			} break;
		}
	}
}
--- proj_direct.c	2008-05-22 23:25:00.000000000 +0200
+++ proj_indirect.c	2008-05-22 23:24:36.000000000 +0200
@@ -1,16 +1,17 @@
-static void proj_InFlightDirectFunc( PROJECTILE *psProj )
+static void proj_InFlightIndirectFunc( PROJECTILE *psProj )
 {
-	/* we want a delay between Las-Sats firing and actually hitting in multiPlayer
-	magic number but that's how long the audio countdown message lasts! */
-	const unsigned int LAS_SAT_DELAY = 8;
+	/* NOTE Main differences to direct projectiles:
+		- Movement vector / pitch update
+		- No extended radius
+		- Some optimisations by leaving out tests which are never true (homing, AA, counter-missile, lassat)
+	*/
+
 	int timeSoFar;
 	int distancePercent; /* How far we are 0..100 */
 	float distanceRatio; /* How far we are, 1.0==at target */
 	float distanceExtensionFactor; /* Extended lifespan */
 	Vector3i move;
 	unsigned int i;
-	// Projectile is missile:
-	bool bMissile = false;
 	WEAPON_STATS *psStats;
 
 	CHECK_PROJECTILE(psProj);
@@ -19,72 +20,22 @@
 
 	psStats = psProj->psWStats;
 	ASSERT( psStats != NULL,
-		"proj_InFlightDirectFunc: Invalid weapon stats pointer" );
-
-	/* we want a delay between Las-Sats firing and actually hitting in multiPlayer
-	magic number but that's how long the audio countdown message lasts! */
-    if ( bMultiPlayer && psStats->weaponSubClass == WSC_LAS_SAT &&
-		timeSoFar < LAS_SAT_DELAY * GAME_TICKS_PER_SEC )
-	{
-		return;
-    }
+		"proj_InFlightIndirectFunc: Invalid weapon stats pointer" );
 
 	/* Calculate extended lifespan where appropriate */
-	switch (psStats->weaponSubClass)
-	{
-		case WSC_MGUN:
-		case WSC_COMMAND:
-			distanceExtensionFactor = 1.2f;
-			break;
-		case WSC_CANNON:
-		case WSC_BOMB:
-		case WSC_ELECTRONIC:
-		case WSC_EMP:
-		case WSC_FLAME:
-		case WSC_ENERGY:
-		case WSC_GAUSS:
-			distanceExtensionFactor = 1.5f;
-			break;
-		case WSC_AAGUN: // No extended distance
-			distanceExtensionFactor = 1.0f;
-			break;
-		case WSC_ROCKET:
-		case WSC_MISSILE:
-		case WSC_SLOWROCKET:
-		case WSC_SLOWMISSILE:
-			bMissile = true; // Take the same extended targetDistance as artillery
-		case WSC_COUNTER:
-		case WSC_MORTARS:
-		case WSC_HOWITZERS:
-		case WSC_LAS_SAT:
-			distanceExtensionFactor = 1.5f;
-			break;
-		default:
-			// NUM_WEAPON_SUBCLASS and INVALID_SUBCLASS
-			break;
-	}
+	distanceExtensionFactor = 1.2f;
 
 	/* Do movement */
 	{
 		unsigned int targetDistance, currentDistance;
 
 		/* Calculate movement vector: */
-		if ( psStats->movementModel == MM_HOMINGDIRECT && psProj->psDest )
-		{
-			/* If it's homing and it has a target (not a miss)... */
-			move.x = psProj->psDest->pos.x - psProj->startX;
-			move.y = psProj->psDest->pos.y - psProj->startY;
-			move.z = psProj->psDest->pos.z - psProj->srcHeight;
-		}
-		else
-		{
-			move.x = psProj->tarX - psProj->startX;
-			move.y = psProj->tarY - psProj->startY;
-			move.z = psProj->altChange;
-		}
+		move.x = psProj->tarX - psProj->startX;
+		move.y = psProj->tarY - psProj->startY;
+		move.z = (psProj->vZ - (timeSoFar * ACC_GRAVITY / (GAME_TICKS_PER_SEC * 2))) * timeSoFar / GAME_TICKS_PER_SEC; // '2' because we reach our highest point in the mid of flight, when "vZ is 0".
 
 		targetDistance = sqrtf( move.x*move.x + move.y*move.y );
-		currentDistance = timeSoFar * psStats->flightSpeed / GAME_TICKS_PER_SEC;
+		currentDistance = timeSoFar * psProj->vXY / GAME_TICKS_PER_SEC; // FIXME ARTILLERY
 
 		// Prevent div by zero:
 		if ( targetDistance == 0 )
@@ -98,7 +49,7 @@
 			Vector3uw nextPos = {
 				psProj->startX + (distanceRatio * move.x),
 				psProj->startY + (distanceRatio * move.y),
-				psProj->srcHeight + (distanceRatio * move.z)
+				psProj->srcHeight + move.z
 			};
 
 			/* impact if about to go off map else update coordinates */
@@ -115,6 +66,12 @@
 		}
 	}
 
+	/* Update pitch */
+	{
+		float fVVert = psProj->vZ - (timeSoFar * ACC_GRAVITY / GAME_TICKS_PER_SEC);
+		psProj->pitch = rad2degf(atan2f(fVVert, psProj->vXY));
+	}
+
 	for (i = 0; i < numProjNaybors; i++)
 	{
 		BASE_OBJECT *psTempObj = asProjNaybors[i].psObj;
@@ -133,10 +90,10 @@
 			continue;
 		}
 
-		if ( psTempObj->type == OBJ_PROJECTILE &&
-			!( bMissile || ((PROJECTILE *)psTempObj)->psWStats->weaponSubClass == WSC_COUNTER ) )
+		if ( psTempObj->type == OBJ_PROJECTILE )
 		{
 			// A projectile should not collide with another projectile unless it's a counter-missile weapon
+			// FIXME Indirectly firing weapons are never counter-missiles?
 			continue;
 		}
 
@@ -154,16 +111,6 @@
 			continue;
 		}
 
-		if ( psStats->surfaceToAir == SHOOT_IN_AIR &&
-			( psTempObj->type == OBJ_STRUCTURE ||
-				psTempObj->type == OBJ_FEATURE ||
-				( psTempObj->type == OBJ_DROID && !vtolDroid((DROID *)psTempObj) )
-			) )
-		{
-			// AA weapons should not hit buildings and non-vtol droids
-			continue;
-		}
-
 		{
 			// FIXME HACK Needed since we got those ugly Vector3uw floating around in BASE_OBJECT...
 			Vector3i
@@ -250,14 +197,10 @@
 				addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0);
 			} break;
 			default:
-				/* add smoke trail to indirect weapons firing directly */
-				if ( !proj_Direct(psStats) )
-				{
-					Vector3i pos = { psProj->pos.x, psProj->pos.z+4, psProj->pos.y };
-					addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0);
-				}
-				/* Otherwise no effect */
-				break;
+			{
+				Vector3i pos = { psProj->pos.x, psProj->pos.z+4, psProj->pos.y };
+				addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0);
+			} break;
 		}
 	}
 }

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
Warzone-dev mailing list
Warzone-dev@gna.org
https://mail.gna.org/listinfo/warzone-dev

Reply via email to