Largely simplified proj_InFlightIndirect.
Improved readability while functionality should be roughly the same.
Now this is very similar to the Direct function, except for differences noted.

Additionaly:
Comply to Per's codingstyle: Less spaces for more readability!
---
 src/projectile.c |  341 ++++++++++++++++++++++++------------------------------
 1 files changed, 149 insertions(+), 192 deletions(-)

diff --git a/src/projectile.c b/src/projectile.c
index fe4eb41..34f4c75 100644
--- a/src/projectile.c
+++ b/src/projectile.c
@@ -902,253 +902,210 @@ static void proj_InFlightDirectFunc(PROJECTILE *psProj)
 
 /***************************************************************************/
 
-static void proj_InFlightIndirectFunc( PROJECTILE *psObj )
+static void proj_InFlightIndirectFunc(PROJECTILE *psProj)
 {
-       WEAPON_STATS    *psStats;
-       SDWORD                  iTime, iRad, iDist, dx, dy, dz, iX, iY;
-       Vector3i pos;
-       float                   fVVert;
-       BOOL                    bOver = false;
-       BASE_OBJECT             *psNewTarget;
-       UDWORD                  i;
-       SDWORD                  xdiff,ydiff,extendRad;
-       UDWORD                  zdiff;
-       BOOL                    bPenetrate;
-       WEAPON                  asWeap;
-
-       CHECK_PROJECTILE(psObj);
-
-       psStats = psObj->psWStats;
-       bPenetrate = psStats->penetrate;
-       ASSERT( psStats != NULL,
-               "proj_InFlightIndirectFunc: Invalid weapon stats pointer" );
+       /* 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)
+       */
 
-       iTime = gameTime - psObj->born;
+       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;
 
-       dx = (SDWORD)psObj->tarX-(SDWORD)psObj->startX;
-       dy = (SDWORD)psObj->tarY-(SDWORD)psObj->startY;
+       CHECK_PROJECTILE(psProj);
 
-       // ffs
-       iRad = (SDWORD)sqrtf( dx*dx + dy*dy );
+       timeSoFar = gameTime - psProj->born;
 
-       iDist = iTime * psObj->vXY / GAME_TICKS_PER_SEC;
+       psStats = psProj->psWStats;
+       ASSERT(psStats != NULL, "proj_InFlightIndirectFunc: Invalid weapon 
stats pointer");
 
-       iX = psObj->startX + (iDist * dx / iRad);
-       iY = psObj->startY + (iDist * dy / iRad);
+       /* Calculate extended lifespan where appropriate */
+       distanceExtensionFactor = 1.2f;
 
-       /* impact if about to go off map else update coordinates */
-       if ( !worldOnMap( iX, iY ) )
-       {
-               psObj->state = PROJ_IMPACT;
-               debug( LOG_NEVER, "**** projectile off map - removed ****\n" );
-               return;
-       }
-       else
+       /* Do movement */
        {
-               psObj->pos.x = (UWORD)iX;
-               psObj->pos.y = (UWORD)iY;
-       }
+               unsigned int targetDistance, currentDistance;
 
-       dz = (psObj->vZ - (iTime*ACC_GRAVITY/GAME_TICKS_PER_SEC/2)) *
-                               iTime / GAME_TICKS_PER_SEC;
-       psObj->pos.z = (UWORD)(psObj->srcHeight + dz);
+               /* 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".
 
-       fVVert = psObj->vZ - (iTime * ACC_GRAVITY / GAME_TICKS_PER_SEC);
-       psObj->pitch = (SWORD)( RAD_TO_DEG(atan2(fVVert, psObj->vXY)) );
+               targetDistance = sqrtf(move.x*move.x + move.y*move.y);
+               currentDistance = timeSoFar * psProj->vXY / GAME_TICKS_PER_SEC; 
// FIXME ARTILLERY
 
-       //Watermelon:extended life span for artillery projectile
-       extendRad = (SDWORD)(iRad * 1.2f);
+               // Prevent div by zero:
+               if (targetDistance == 0)
+                       targetDistance = 1;
+
+               distanceRatio = (float)currentDistance / targetDistance;
+               distancePercent = PERCENT(currentDistance, targetDistance);
 
-       if( gfxVisible(psObj) )
-       {
-               switch(psStats->weaponSubClass)
                {
-                       case WSC_MGUN:
-                       case WSC_CANNON:
-                       case WSC_MORTARS:
-                       case WSC_ENERGY:
-                       case WSC_GAUSS:
-                       case WSC_HOWITZERS:
-                       case WSC_AAGUN:
-                       case WSC_LAS_SAT:
-                       case WSC_BOMB:
-                       case WSC_COUNTER:
-                       case NUM_WEAPON_SUBCLASS:
-                       case INVALID_SUBCLASS:
-                               break;
-                       case WSC_FLAME:
-                               effectGiveAuxVar(PERCENT(iDist,iRad));
-                               pos.x = psObj->pos.x;
-                               pos.y = psObj->pos.z-8;
-                               pos.z = psObj->pos.y;
-                               
addEffect(&pos,EFFECT_EXPLOSION,EXPLOSION_TYPE_FLAMETHROWER,false,NULL,0);
-                               break;
-                       case WSC_COMMAND:
-                       case WSC_ELECTRONIC:
-                       case WSC_EMP:
-                               effectGiveAuxVar((PERCENT(iDist,iRad)/2));
-                               pos.x = psObj->pos.x;
-                               pos.y = psObj->pos.z-8;
-                               pos.z = psObj->pos.y;
-                               
addEffect(&pos,EFFECT_EXPLOSION,EXPLOSION_TYPE_LASER,false,NULL,0);
-                               break;
-                       case WSC_ROCKET:
-                       case WSC_MISSILE:
-                       case WSC_SLOWROCKET:
-                       case WSC_SLOWMISSILE:
-                               pos.x = psObj->pos.x;
-                               pos.y = psObj->pos.z+8;
-                               pos.z = psObj->pos.y;
-                               
addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0);
-                               break;
+                       /* 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(%i) off map - 
removed ****\n", psProj->id);
+                               return;
+                       }
+
+                       /* Update position */
+                       psProj->pos = nextPos;
                }
        }
 
-       //Watermelon:test test
-       for (i = 0;i < numProjNaybors;i++)
+       /* Update pitch */
+       {
+               float fVVert = psProj->vZ - (timeSoFar * ACC_GRAVITY / 
GAME_TICKS_PER_SEC);
+               psProj->pitch = rad2degf(atan2f(fVVert, psProj->vXY));
+       }
+
+       /* Check nearby objects for possible collisions */
+       for (i = 0; i < numProjNaybors; i++)
        {
                BASE_OBJECT *psTempObj = asProjNaybors[i].psObj;
 
                CHECK_OBJECT(psTempObj);
 
-               //Watermelon;dont collide with any other projectiles
-               if ( psTempObj->type == OBJ_PROJECTILE )
+               if (psTempObj == psProj->psDamaged)
                {
+                       // Dont damage one target twice
                        continue;
                }
 
-               //Watermelon:ignore oil resource and pickup
-               if ( psTempObj->type == OBJ_FEATURE &&
-                       ((FEATURE *)psTempObj)->psStats->damageable == 0 )
+               if (psTempObj->died)
                {
+                       // Do not damage dead objects further
                        continue;
                }
 
-               if (psTempObj->died)
+               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->player != psObj->player &&
-                       (psTempObj->type == OBJ_DROID ||
-                       psTempObj->type == OBJ_STRUCTURE ||
-                       psTempObj->type == OBJ_PROJECTILE ||
-                       psTempObj->type == OBJ_FEATURE) &&
-                       !aiCheckAlliances(psTempObj->player,psObj->player))
+               if (psTempObj->type == OBJ_FEATURE &&
+                       !((FEATURE*)psTempObj)->psStats->damageable)
                {
-                       if ( psTempObj->type == OBJ_STRUCTURE || 
psTempObj->type == OBJ_FEATURE )
-                       {
-                               xdiff = (SDWORD)psObj->pos.x - 
(SDWORD)psTempObj->pos.x;
-                               ydiff = (SDWORD)psObj->pos.y - 
(SDWORD)psTempObj->pos.y;
-                               zdiff = abs((UDWORD)psObj->pos.z - 
(UDWORD)psTempObj->pos.z);
+                       // Ignore oil resources, artifacts and other pickups
+                       continue;
+               }
 
-                               if ( zdiff < establishTargetHeight(psTempObj) &&
-                                       (xdiff*xdiff + ydiff*ydiff) < ( 
(SDWORD)establishTargetRadius(psTempObj) * 
(SDWORD)establishTargetRadius(psTempObj) ) )
-                               {
-                                       psNewTarget = psTempObj;
-                                       setProjectileDestination(psObj, 
psNewTarget);
-                                       psObj->state = PROJ_IMPACT;
-                                       return;
-                               }
-                       }
-                       else
-                       {
-                               xdiff = (SDWORD)psObj->pos.x - 
(SDWORD)psTempObj->pos.x;
-                               ydiff = (SDWORD)psObj->pos.y - 
(SDWORD)psTempObj->pos.y;
-                               zdiff = abs((UDWORD)psObj->pos.z - 
(UDWORD)psTempObj->pos.z);
+               if (psTempObj->player == psProj->player ||
+                       aiCheckAlliances(psTempObj->player, psProj->player))
+               {
+                       // No friendly fire
+                       continue;
+               }
 
-                               if ( zdiff < establishTargetHeight(psTempObj) &&
-                                       (UDWORD)(xdiff*xdiff + ydiff*ydiff) < ( 
(SDWORD)establishTargetRadius(psTempObj) * 
(SDWORD)establishTargetRadius(psTempObj) ) )
-                               {
-                                       psNewTarget = psTempObj;
-                                       setProjectileDestination(psObj, 
psNewTarget);
+               /* Actual collision test */
+               {
+                       // 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};
 
-                                       if (bPenetrate)
-                                       {
-                                               // 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 target = {
-                                                       psObj->startX + 
extendRad * dx / iRad,
-                                                       psObj->startY + 
extendRad * dy / iRad,
-                                                       psObj->pos.z
-                                               };
-                                               target.x = clip(target.x, 0, 
world_coord(mapWidth - 1));
-                                               target.y = clip(target.y, 0, 
world_coord(mapHeight - 1));
-
-                                               asWeap.nStat = psObj->psWStats 
- asWeaponStats;
-
-                                               //Watermelon:just assume we 
damaged the chosen target
-                                               setProjectileDamaged(psObj, 
psNewTarget);
-
-                                               proj_SendProjectile( &asWeap, 
(BASE_OBJECT*)psObj, psObj->player, target, NULL, true, -1 );
-                                       }
+                       Vector3i diff = Vector3i_Sub(posProj, posTemp);
 
-                                       psObj->state = PROJ_IMPACT;
+                       unsigned int targetHeight = 
establishTargetHeight(psTempObj);
+                       unsigned int targetRadius = 
establishTargetRadius(psTempObj);
 
-                                       return;
-                               }
-                       }
-               }
-       }
+                       /* Height is always positive */
+                       diff.z = abs(diff.z);
 
-       /* See if effect has finished */
-       if ( iDist > (extendRad - (SDWORD)psObj->targetRadius) )
-       {
-               psObj->state = PROJ_IMPACT;
+                       /* We hit! */
+                       if (diff.z < targetHeight &&
+                               (diff.x*diff.x + diff.y*diff.y) < targetRadius 
* targetRadius)
+                       {
+                               setProjectileDestination(psProj, psTempObj);
 
-               pos.x = psObj->pos.x;
-               pos.z = psObj->pos.y;
-               pos.y = map_Height(pos.x,pos.z) + 8;
+                               /* 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
+                                       };
 
-               /* It's damage time */
-               //Watermelon:'real' check
-               if ( psObj->psDest )
-               {
-                       psObj->pos.z = (UWORD)(pos.y + 8); // bring up the 
impact explosion
+                                       newDest.x = clip(newDest.x, 0, 
world_coord(mapWidth - 1));
+                                       newDest.y = clip(newDest.y, 0, 
world_coord(mapHeight - 1));
 
-                       xdiff = (SDWORD)psObj->pos.x - 
(SDWORD)psObj->psDest->pos.x;
-                       ydiff = (SDWORD)psObj->pos.y - 
(SDWORD)psObj->psDest->pos.y;
-                       zdiff = abs((UDWORD)psObj->pos.z - 
(UDWORD)psObj->psDest->pos.z);
+                                       // Assume we damaged the chosen target
+                                       setProjectileDamaged(psProj, psTempObj);
 
-                       if ( zdiff < establishTargetHeight(psObj->psDest) &&
-                               (xdiff*xdiff + ydiff*ydiff) < (SDWORD)( 
establishTargetRadius(psObj->psDest) * establishTargetRadius(psObj->psDest) ) )
-                       {
-                               psObj->state = PROJ_IMPACT;
-                       }
-                       else
-                       {
-                               setProjectileDestination(psObj, NULL);
+                                       proj_SendProjectile(&asWeap, 
(BASE_OBJECT*)psProj, psProj->player, newDest, NULL, true, -1);
+                               }
+
+                               psProj->state = PROJ_IMPACT;
+
+                               return;
                        }
                }
-               bOver = true;
        }
 
-       /* check not trying to travel through terrain - if so count as a miss */
-       if ( mapObjIsAboveGround( (BASE_OBJECT *) psObj ) == false )
+       if (distanceRatio > distanceExtensionFactor || /* We've traveled our 
maximum range */
+               !mapObjIsAboveGround((BASE_OBJECT*)psProj)) /* trying to travel 
through terrain */
        {
-               psObj->state = PROJ_IMPACT;
-               /* miss registered if NULL target */
-               setProjectileDestination(psObj, NULL);
-               bOver = true;
+               /* Miss due to range or height */
+               psProj->state = PROJ_IMPACT;
+               setProjectileDestination(psProj, NULL); /* miss registered if 
NULL target */
+               return;
        }
 
-       /* Add smoke particle at projectile location (in world coords) */
-       /* Add a trail graphic */
-       /* If it's indirect and not a flamethrower - add a smoke trail! */
-       if ( psStats->weaponSubClass != WSC_FLAME &&
-               psStats->weaponSubClass != WSC_ENERGY &&
-               psStats->weaponSubClass != WSC_COMMAND &&
-               psStats->weaponSubClass != WSC_ELECTRONIC &&
-               psStats->weaponSubClass != WSC_EMP &&
-               !bOver )
+       /* Paint effects if visible */
+       if (gfxVisible(psProj))
        {
-               if(gfxVisible(psObj))
+               switch (psStats->weaponSubClass)
                {
-                       pos.x = psObj->pos.x;
-                       pos.y = psObj->pos.z+4;
-                       pos.z = psObj->pos.y;
-                       
addEffect(&pos,EFFECT_SMOKE,SMOKE_TYPE_TRAIL,false,NULL,0);
+                       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;
                }
        }
 }
-- 
1.5.5.1


_______________________________________________
Warzone-dev mailing list
[email protected]
https://mail.gna.org/listinfo/warzone-dev

Reply via email to