From 331cc86c98469ae1ee4b28dad03008a1bdd5b0e3 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Sun, 9 Jun 2013 17:04:44 +0100
Subject: [PATCH] [Fix] Potential issues with reallocs. Added more comments
 too.

---
 src/pilot.c | 92 +++++++++++++++++++++++++++++++++++++++--------------
 src/pilot.h |  1 +
 2 files changed, 69 insertions(+), 24 deletions(-)

diff --git a/src/pilot.c b/src/pilot.c
index b4dc430..e41f4df 100644
--- a/src/pilot.c
+++ b/src/pilot.c
@@ -313,12 +313,14 @@ void pilot_dead(Pilot* p) {
 void pilot_setSecondary(Pilot* p, const char* secondary) {
   int i;
 
+  // No need for ammo if there is no secondary.
   if(secondary == NULL) {
     p->secondary = NULL;
     p->ammo = NULL;
     return;
   }
 
+  // Find the secondary and set ammo appropriately.
   for(i = 0; i < p->noutfits; i++) {
     if(strcmp(secondary, p->outfits[i].outfit->name)==0) {
       p->secondary = &p->outfits[i];;
@@ -337,22 +339,37 @@ void pilot_setAmmo(Pilot* p) {
   int i;
   char* name;
 
+  // Only launchers use ammo.
   if((p->secondary == NULL) || !outfit_isLauncher(p->secondary->outfit)) {
     p->ammo = NULL;
     return;
   }
 
+  // Find the ammo and set it.
   name = p->secondary->outfit->u.lau.ammo;
 
   for(i = 0; i < p->noutfits; i++)
     if(strcmp(p->outfits[i].outfit->name, name)==0) {
-      p->ammo = p->outfits + i;
+      p->ammo = &p->outfits[i];
       return;
     }
 
+  // None found, so we assume if doesn't need ammo.
   p->ammo = NULL;
 }
 
+// Set the pilots afterburner.
+void pilot_setAfterburner(Pilot* p) {
+  int i;
+
+  for(i = 0; i < p->noutfits; i++)
+    if(outfit_isAfterburner(p->outfits[i].outfit)) {
+      p->afterburner = &p->outfits[i];
+      return;
+    }
+  p->afterburner = NULL;
+}
+
 // Render the pilot.
 void pilot_render(Pilot* p) {
   gl_blitSprite(p->ship->gfx_space,
@@ -365,22 +382,25 @@ static void pilot_update(Pilot* pilot, const double dt) {
   unsigned int t, l;
   double a, px, py, vx, vy;
 
+  // She's dead D:
   if(pilot_isFlag(pilot, PILOT_DEAD)) {
     t = SDL_GetTicks();
 
-    if(t > pilot->ptimer) {
-      if(pilot->id == PLAYER_ID)
+    if(t > pilot->ptimer) { // Completely destroyed with final explosion.
+      if(pilot->id == PLAYER_ID) // Player handled differently.
         player_destroyed();
       pilot_setFlag(pilot, PILOT_DELETE); // It'll get deleted next frame.
       return;
     }
 
+    // Final explosion.
     if(!pilot_isFlag(pilot, PILOT_EXPLODED) && (t > pilot->ptimer - 200)) {
       spfx_add(spfx_get("ExpL"),
                VX(pilot->solid->pos), VY(pilot->solid->pos),
                VX(pilot->solid->vel), VY(pilot->solid->vel), SPFX_LAYER_BACK);
       pilot_setFlag(pilot, PILOT_EXPLODED);
     }
+    // Reset random explosion time.
     else if(t > pilot->timer[1]) {
       pilot->timer[1] = t +
           (unsigned int)(100*(double)(pilot->ptimer - pilot->timer[1]) /
@@ -401,7 +421,7 @@ static void pilot_update(Pilot* pilot, const double dt) {
     }
   }
   else if(pilot->armour <= 0.) // PWNED!
-    pilot_dead(pilot);
+    pilot_dead(pilot); // Start death stuff.
 
   // Pupose fallthrough to get the movement similar to disabled.
   if(pilot != player && pilot->armour < PILOT_DISABLED_ARMOUR * pilot->armour_max) {
@@ -410,7 +430,7 @@ static void pilot_update(Pilot* pilot, const double dt) {
     // Come to a halt slowly.
     vect_pset(&pilot->solid->vel,
               VMOD(pilot->solid->vel) * (1. - dt*0.10), VANGLE(pilot->solid->vel));
-    vectnull(&pilot->solid->force);
+    vectnull(&pilot->solid->force); // No more accel.
     pilot->solid->dir_vel = 0.; // Stop it from turning.
 
     // Update the solid.
@@ -421,13 +441,16 @@ static void pilot_update(Pilot* pilot, const double dt) {
   }
   // We are still alive.
   else if(pilot->armour < pilot->armour_max) {
+    // Regen armour.
     pilot->armour += pilot->armour_regen*dt;
     pilot->energy += pilot->energy_regen*dt;
   } else {
+    // And shields.
     pilot->shield += pilot->shield_regen*dt;
     pilot->energy += pilot->energy_regen*dt;
   }
 
+  // Check limits.
   if(pilot->armour > pilot->armour_max) pilot->armour = pilot->armour_max;
   if(pilot->shield > pilot->shield_max) pilot->shield = pilot->shield_max;
   if(pilot->energy > pilot->energy_max) pilot->energy = pilot->energy_max;
@@ -438,14 +461,16 @@ static void pilot_update(Pilot* pilot, const double dt) {
                       pilot->ship->gfx_space, pilot->solid->dir);
 
   if(!pilot_isFlag(pilot, PILOT_HYPERSPACE)) { // Limit the speed.
+
+    // Pilot is afterburning.
     if(pilot_isFlag(pilot, PILOT_AFTERBURNER) && // Must have enough energy.
        (player->energy > pilot->afterburner->outfit->u.afb.energy * dt)) {
-      limit_speed(&pilot->solid->vel,
+      limit_speed(&pilot->solid->vel, // Limit is higher.
                   pilot->speed * pilot->afterburner->outfit->u.afb.speed_perc +
                   pilot->afterburner->outfit->u.afb.speed_abs, dt);
     spfx_shake(SHAKE_DECAY/2. * dt); // Shake goes down at half speed.
     pilot->energy -= pilot->afterburner->outfit->u.afb.energy * dt; // Energy loss.
-    } else
+    } else // Normal limit.
       limit_speed(&pilot->solid->vel, pilot->speed, dt);
   }
 }
@@ -454,8 +479,10 @@ static void pilot_update(Pilot* pilot, const double dt) {
 static void pilot_hyperspace(Pilot* p) {
   double diff;
 
+  // Pilot is actually in hyperspace.
   if(pilot_isFlag(p, PILOT_HYPERSPACE)) {
-    // Pilot is actually in hyperspace.
+
+    // Has the jump happened?
     if(SDL_GetTicks() > p->ptimer) {
       if(p == player) {
         player_brokeHyperspace();
@@ -463,8 +490,10 @@ static void pilot_hyperspace(Pilot* p) {
         pilot_setFlag(p, PILOT_DELETE); // Set flag to delete pilot.
       return;
     }
-    vect_pset(&p->solid->force, p->thrust * 3., p->solid->dir);
+    // Keep accelerating - hyperspace uses much bigger accel.
+    vect_pset(&p->solid->force, p->thrust * 5., p->solid->dir);
   }
+  // Engines getting ready for the jump.
   else if(pilot_isFlag(p, PILOT_HYP_BEGIN)) {
     if(SDL_GetTicks() > p->ptimer) {
       // Engines are ready.
@@ -474,12 +503,14 @@ static void pilot_hyperspace(Pilot* p) {
   } else {
     // Pilot is getting ready for hyperspace.
 
+    // Brake.
     if(VMOD(p->solid->vel) > MIN_VEL_ERR) {
       diff = pilot_face(p, VANGLE(p->solid->vel) + M_PI);
 
-      if(ABS(diff) < MAX_DIR_ERR) // Brake.
+      if(ABS(diff) < MAX_DIR_ERR)
         vect_pset(&p->solid->force, p->thrust, p->solid->dir);
     } else {
+      // Face target.
       vectnull(&p->solid->force); // Stop accelerating.
 
       // Player should actually face the system she's headed to.
@@ -498,10 +529,11 @@ static void pilot_hyperspace(Pilot* p) {
 
 int pilot_addOutfit(Pilot* pilot, Outfit* outfit, int quantity) {
   int i, q;
-  char* s;
+  char* osec;
 
   q = quantity;
 
+  // Does outfit already exist?
   for(i = 0; i < pilot->noutfits; i++)
     if(strcmp(outfit->name, pilot->outfits[i].outfit->name)==0) {
       pilot->outfits[i].quantity += quantity;
@@ -510,20 +542,27 @@ int pilot_addOutfit(Pilot* pilot, Outfit* outfit, int quantity) {
         q -= pilot->outfits[i].quantity - outfit->max;
         pilot->outfits[i].quantity = outfit->max;
       }
+      // Recalculate the stats.
       pilot_calcStats(pilot);
       return q;
     }
 
-  s = (pilot->secondary) ? pilot->secondary->outfit->name : NULL;
+  // Hacks in case it reallocs.
+  osec = (pilot->secondary) ? pilot->secondary->outfit->name : NULL;
+  // No need for ammo since it's already handled in setSecondary,
+  // since pilot has only one afterburner it's handled at the end.
+
+  // Grow the outfits.
   pilot->outfits = realloc(pilot->outfits, (pilot->noutfits+1)*sizeof(PilotOutfit));
   pilot->outfits[pilot->noutfits].outfit   = outfit;
   pilot->outfits[pilot->noutfits].quantity  = quantity;
+
   // Can't be over max.
   if(pilot->outfits[pilot->noutfits].quantity > outfit->max) {
     q -= pilot->outfits[pilot->noutfits].quantity - outfit->max;
     pilot->outfits[i].quantity = outfit->max;
   }
-  pilot->outfits[pilot->noutfits].timer   = 0;
+  pilot->outfits[pilot->noutfits].timer = 0; // Reset time.
   (pilot->noutfits)++;
 
   if(outfit_isTurret(outfit))
@@ -531,7 +570,8 @@ int pilot_addOutfit(Pilot* pilot, Outfit* outfit, int quantity) {
     pilot_setFlag(pilot, PILOT_HASTURRET);
 
   // Hack due to realloc possibility.
-  pilot_setSecondary(pilot, s);
+  pilot_setSecondary(pilot, osec);
+  pilot_setAfterburner(pilot);
 
   pilot_calcStats(pilot);
   return q;
@@ -540,7 +580,7 @@ int pilot_addOutfit(Pilot* pilot, Outfit* outfit, int quantity) {
 // Remove an outfit from the pilot.
 int pilot_rmOutfit(Pilot* pilot, Outfit* outfit, int quantity) {
   int i, q, c;
-  char* s;
+  char* osec;
 
   c = (outfit_isMod(outfit)) ? outfit->u.mod.cargo : 0;
   q = quantity;
@@ -551,11 +591,9 @@ int pilot_rmOutfit(Pilot* pilot, Outfit* outfit, int quantity) {
       if(pilot->outfits[i].quantity <= 0) {
         // We didn't actually remove the full amount.
         q += pilot->outfits[i].quantity;
+
         // Hack in case it reallocs - Can happen even when shrinking.
-        s = (pilot->secondary) ? pilot->secondary->outfit->name : NULL;
-        // Clear it if it's the afterburner.
-        if(&pilot->outfits[i] == pilot->afterburner)
-          pilot->afterburner = NULL;
+        osec = (pilot->secondary) ? pilot->secondary->outfit->name : NULL;
 
         // Remove the outfit.
         memmove(pilot->outfits+i, pilot->outfits+i+1,
@@ -564,7 +602,9 @@ int pilot_rmOutfit(Pilot* pilot, Outfit* outfit, int quantity) {
         pilot->outfits = realloc(pilot->outfits,
                                  sizeof(PilotOutfit)*(pilot->noutfits));
 
-        pilot_setSecondary(pilot, s);
+        // Set secondary and afterburner.
+        pilot_setSecondary(pilot, osec);
+        pilot_setAfterburner(pilot);
       }
       pilot_calcStats(pilot); // Recalculate stats.
       pilot->cargo_free -= c;
@@ -647,10 +687,9 @@ void pilot_calcStats(Pilot* pilot) {
       // Misc.
       pilot->cargo_free += o->u.mod.cargo * q;
     }
-    else if(outfit_isAfterburner(pilot->outfits[i].outfit)) {
+    else if(outfit_isAfterburner(pilot->outfits[i].outfit)) // Set afterburner.
       // Set the afterburner.
       pilot->afterburner = &pilot->outfits[i];
-    }
   }
 
   // Give the pilot her health proportion back.
@@ -669,6 +708,7 @@ int pilot_cargoFree(Pilot* p) {
 int pilot_addCargo(Pilot* pilot, Commodity* cargo, int quantity) {
   int i, q;
 
+  // Check if pilot has it first.
   q = quantity;
   for(i = 0; i < pilot->ncommodities; i++)
     if(!pilot->commodities[i].id && (pilot->commodities[i].commodity == cargo)) {
@@ -734,15 +774,17 @@ unsigned int pilot_addMissionCargo(Pilot* pilot, Commodity* cargo, int quantity)
   return pilot->commodities[pilot->ncommodities-1].id;
 }
 
+// Remove special misssion cargo based on id.
 int pilot_rmMissionCargo(Pilot* pilot, unsigned int cargo_id) {
   int i;
 
+  // Check if pilot has it.
   for(i = 0; i < pilot->ncommodities; i++)
     if(pilot->commodities[i].id == cargo_id)
       break;
 
   if(i >= pilot->ncommodities)
-    return 1;
+    return 1; // Pilot doesn't have it.
 
   // Remove cargo.
   pilot->cargo_free += pilot->commodities[i].quantity;
@@ -762,8 +804,10 @@ int pilot_rmMissionCargo(Pilot* pilot, unsigned int cargo_id) {
 int pilot_rmCargo(Pilot* pilot, Commodity* cargo, int quantity) {
   int i, q;
 
+  // Check if pilot has it.
   q = quantity;
   for(i = 0; i < pilot->ncommodities; i++)
+    // Doesn't remove mission cargo.
     if(!pilot->commodities[i].id && (pilot->commodities[i].commodity == cargo)) {
       if(quantity >= pilot->commodities[i].quantity) {
         q = pilot->commodities[i].quantity;
@@ -782,7 +826,7 @@ int pilot_rmCargo(Pilot* pilot, Commodity* cargo, int quantity) {
       return q;
     }
 
-  return 0;
+  return 0; // Pilot didn't have it.
 }
 
 // Add a hook to the pilot.
diff --git a/src/pilot.h b/src/pilot.h
index 6c3b2f0..c5f2337 100644
--- a/src/pilot.h
+++ b/src/pilot.h
@@ -147,6 +147,7 @@ void pilot_hit(Pilot* p, const Solid* w, const unsigned int shooter,
     const DamageType dtype, const double damage);
 void pilot_setSecondary(Pilot* p, const char* secondary);
 void pilot_setAmmo(Pilot* p);
+void pilot_setAfterburner(Pilot* p);
 double pilot_face(Pilot* p, const float dir);
 // Outfits.
 int pilot_freeSpace(Pilot* p); // Pilot space.