Beispiel #1
0
/**
 * @brief Disables a given active outfit.
 *
 * @param p Pilot whose outfit we are disabling.
 * @return Whether the outfit was actually disabled.
 */
int pilot_outfitOff( Pilot *p, PilotOutfitSlot *o )
{
   double c;

   /* Must not be disabled or cooling down. */
   if ((pilot_isDisabled(p)) || (pilot_isFlag(p, PILOT_COOLDOWN)))
      return 0;

   if (outfit_isAfterburner( o->outfit )) /* Afterburners */
      pilot_afterburnOver( p );
   else if (outfit_isBeam( o->outfit )) {
      /* Beams use stimer to represent minimum time until shutdown. */
      o->stimer = -1;
   }
   else {
      c = outfit_cooldown( o->outfit );
      if (o->stimer != INFINITY)
         o->stimer = c - (c * o->stimer / outfit_duration( o->outfit ));
      else
         o->stimer = c;
      o->state  = PILOT_OUTFIT_COOLDOWN;
   }

   return 1;
}
Beispiel #2
0
/**
 * @brief Disables a given active outfit.
 *
 * @param p Pilot whose outfit we are disabling.
 * @return Whether the outfit was actually disabled.
 */
int pilot_outfitOff( Pilot *p, PilotOutfitSlot *o )
{
   /* Must not be disabled or cooling down. */
   if ((pilot_isDisabled(p)) || (pilot_isFlag(p, PILOT_COOLDOWN)))
      return 0;

   if (outfit_isAfterburner( o->outfit )) /* Afterburners */
      pilot_afterburnOver( p );
   else {
      o->stimer = outfit_cooldown( o->outfit );
      o->state  = PILOT_OUTFIT_COOLDOWN;
   }

   return 1;
}
Beispiel #3
0
/**
 * @brief Gets the outfit's broad type.
 *
 *    @param o Outfit to get the type of.
 *    @return The outfit's broad type in human readable form.
 */
const char* outfit_getTypeBroad( const Outfit* o )
{
   if (outfit_isBolt(o)) return "Bolt Weapon";
   else if (outfit_isBeam(o)) return "Beam Weapon";
   else if (outfit_isLauncher(o)) return "Launcher";
   else if (outfit_isAmmo(o)) return "Ammo";
   else if (outfit_isTurret(o)) return "Turret";
   else if (outfit_isMod(o)) return "Modification";
   else if (outfit_isAfterburner(o)) return "Afterburner";
   else if (outfit_isJammer(o)) return "Jammer";
   else if (outfit_isFighterBay(o)) return "Fighter Bay";
   else if (outfit_isFighter(o)) return "Fighter";
   else if (outfit_isMap(o)) return "Map";
   else if (outfit_isLicense(o)) return "License";
   else return "Unknown";
}
Beispiel #4
0
/**
 * @brief Adds an outfit to the pilot, ignoring CPU or other limits.
 *
 * @note Does not call pilot_calcStats().
 *
 *    @param pilot Pilot to add the outfit to.
 *    @param outfit Outfit to add to the pilot.
 *    @param s Slot to add ammo to.
 *    @return 0 on success.
 */
int pilot_addOutfitRaw( Pilot* pilot, Outfit* outfit, PilotOutfitSlot *s )
{
   Outfit *o;

   /* Set the outfit. */
   s->outfit   = outfit;

   /* Set some default parameters. */
   s->timer    = 0.;

   /* Some per-case scenarios. */
   if (outfit_isFighterBay(outfit)) {
      s->u.ammo.outfit   = NULL;
      s->u.ammo.quantity = 0;
      s->u.ammo.deployed = 0;
   }
   if (outfit_isTurret(outfit)) /* used to speed up AI */
      pilot->nturrets++;
   else if (outfit_isBolt(outfit))
      pilot->ncannons++;
   else if (outfit_isJammer(outfit))
      pilot->njammers++;
   else if (outfit_isAfterburner(outfit))
      pilot->nafterburners++;

   if (outfit_isBeam(outfit)) { /* Used to speed up some calculations. */
      s->u.beamid = 0;
      pilot->nbeams++;
   }
   if (outfit_isLauncher(outfit)) {
      s->u.ammo.outfit   = NULL;
      s->u.ammo.quantity = 0;
      s->u.ammo.deployed = 0; /* Just in case. */
   }

   /* Check if active. */
   o = s->outfit;
   s->active = outfit_isActive(o);

   /* Update heat. */
   pilot_heatCalcSlot( s );

   return 0;
}
Beispiel #5
0
/**
 * @brief Handles a weapon set press.
 *
 *    @param p Pilot the weapon set belongs to.
 *    @param id ID of the weapon set.
 *    @param type Is +1 if it's a press or -1 if it's a release.
 */
void pilot_weapSetPress( Pilot* p, int id, int type )
{
   int i, l, on, n;
   PilotWeaponSet *ws;

   ws = pilot_weapSet(p,id);
   /* Case no outfits. */
   if (ws->slots == NULL)
      return;

   /* Handle fire groups. */
   switch (ws->type) {
      case WEAPSET_TYPE_CHANGE:
         /* On press just change active weapon set to whatever is available. */
         if (type > 0) {
            if (id != p->active_set)
               pilot_weapSetUpdateOutfits( p, ws );
            p->active_set = id;
         }
         break;

      case WEAPSET_TYPE_WEAPON:
         /* Activation philosophy here is to turn on while pressed and off
          * when it's not held anymore. */
         if (type > 0)
            ws->active = 1;
         else if (type < 0)
            ws->active = 0;
         break;

      case WEAPSET_TYPE_ACTIVE:
         /* The behaviour here is more complex. What we do is consider a group
          * to be entirely off if not all outfits are either on or cooling down.
          * In the case it's deemed to be off, all outfits that are off get turned
          * on, otherwise all outfits that are on are turrned to cooling down. */
         /* Only care about presses. */
         if (type < 0)
            break;

         /* Must not be disabled or cooling down. */
         if ((pilot_isDisabled(p)) || (pilot_isFlag(p, PILOT_COOLDOWN)))
            return;

         /* Decide what to do. */
         on = 1;
         l  = array_size(ws->slots);
         for (i=0; i<l; i++) {
            if (ws->slots[i].slot->state == PILOT_OUTFIT_OFF) {
               on = 0;
               break;
            }
         }

         /* Turn them off. */
         n = 0;
         if (on) {
            for (i=0; i<l; i++) {
               if (ws->slots[i].slot->state != PILOT_OUTFIT_ON)
                  continue;

               n += pilot_outfitOff( p, ws->slots[i].slot );
            }
         }
         /* Turn them on. */
         else {
            for (i=0; i<l; i++) {
               if (ws->slots[i].slot->state != PILOT_OUTFIT_OFF)
                  continue;
               if (outfit_isAfterburner(ws->slots[i].slot->outfit))
                  pilot_afterburn( p );
               else {
                  ws->slots[i].slot->state  = PILOT_OUTFIT_ON;
                  ws->slots[i].slot->stimer = outfit_duration( ws->slots[i].slot->outfit );
               }
               n++;
            }
         }
         /* Must recalculate stats. */
         if (n > 0)
            pilot_calcStats( p );

         break;
   }
}
Beispiel #6
0
/**
 * @brief Recalculates the pilot's stats based on his outfits.
 *
 *    @param pilot Pilot to recalculate his stats.
 */
void pilot_calcStats( Pilot* pilot )
{
   int i;
   Outfit* o;
   PilotOutfitSlot *slot;
   double ac, sc, ec, fc; /* temporary health coefficients to set */
   ShipStats amount, *s, *default_s;

   /*
    * set up the basic stuff
    */
   /* mass */
   pilot->solid->mass   = pilot->ship->mass;
   pilot->base_mass     = pilot->solid->mass;
   /* cpu */
   pilot->cpu           = 0.;
   /* movement */
   pilot->thrust_base   = pilot->ship->thrust;
   pilot->turn_base     = pilot->ship->turn;
   pilot->speed_base    = pilot->ship->speed;
   /* crew */
   pilot->crew          = pilot->ship->crew;
   /* cargo */
   pilot->cap_cargo     = pilot->ship->cap_cargo;
   /* fuel_consumption. */
   pilot->fuel_consumption = pilot->ship->fuel_consumption;
   /* health */
   ac = (pilot->armour_max > 0.) ? pilot->armour / pilot->armour_max : 0.;
   sc = (pilot->shield_max > 0.) ? pilot->shield / pilot->shield_max : 0.;
   ec = (pilot->energy_max > 0.) ? pilot->energy / pilot->energy_max : 0.;
   fc = (pilot->fuel_max   > 0.) ? pilot->fuel   / pilot->fuel_max   : 0.;
   pilot->armour_max    = pilot->ship->armour;
   pilot->shield_max    = pilot->ship->shield;
   pilot->fuel_max      = pilot->ship->fuel;
   pilot->armour_regen  = pilot->ship->armour_regen;
   pilot->shield_regen  = pilot->ship->shield_regen;
   /* Absorption. */
   pilot->dmg_absorb    = pilot->ship->dmg_absorb;
   /* Energy. */
   pilot->energy_max    = pilot->ship->energy;
   pilot->energy_regen  = pilot->ship->energy_regen;
   pilot->energy_loss   = 0.; /* Initially no net loss. */
   /* Stats. */
   s = &pilot->stats;
   memcpy( s, &pilot->ship->stats_array, sizeof(ShipStats) );
   memset( &amount, 0, sizeof(ShipStats) );

   /*
    * Now add outfit changes
    */
   pilot->mass_outfit   = 0.;
   pilot->jamming       = 0;
   for (i=0; i<pilot->noutfits; i++) {
      slot = pilot->outfits[i];
      o    = slot->outfit;

      /* Outfit must exist. */
      if (o==NULL)
         continue;

      /* Modify CPU. */
      pilot->cpu           += outfit_cpu(o);

      /* Add mass. */
      pilot->mass_outfit   += o->mass;

      /* Keep a separate counter for required (core) outfits. */
      if (sp_required( o->slot.spid ))
         pilot->base_mass += o->mass;

      /* Add ammo mass. */
      if (outfit_ammo(o) != NULL)
         if (slot->u.ammo.outfit != NULL)
            pilot->mass_outfit += slot->u.ammo.quantity * slot->u.ammo.outfit->mass;

      if (outfit_isAfterburner(o)) /* Afterburner */
         pilot->afterburner = pilot->outfits[i]; /* Set afterburner */

      /* Active outfits must be on to affect stuff. */
      if (slot->active && !(slot->state==PILOT_OUTFIT_ON))
         continue;

      if (outfit_isMod(o)) { /* Modification */
         /* Movement. */
         pilot->thrust_base   += o->u.mod.thrust;
         pilot->turn_base     += o->u.mod.turn;
         pilot->speed_base    += o->u.mod.speed;
         /* Health. */
         pilot->dmg_absorb    += o->u.mod.absorb;
         pilot->armour_max    += o->u.mod.armour;
         pilot->armour_regen  += o->u.mod.armour_regen;
         pilot->shield_max    += o->u.mod.shield;
         pilot->shield_regen  += o->u.mod.shield_regen;
         pilot->energy_max    += o->u.mod.energy;
         pilot->energy_regen  += o->u.mod.energy_regen;
         pilot->energy_loss   += o->u.mod.energy_loss;
         /* Fuel. */
         pilot->fuel_max      += o->u.mod.fuel;
         /* Misc. */
         pilot->cap_cargo     += o->u.mod.cargo;
         pilot->mass_outfit   += o->u.mod.mass_rel * pilot->ship->mass;
         pilot->crew          += o->u.mod.crew_rel * pilot->ship->crew;
         /*
          * Stats.
          */
         ss_statsModFromList( s, o->u.mod.stats, &amount );

      }
      else if (outfit_isAfterburner(o)) { /* Afterburner */
         pilot_setFlag( pilot, PILOT_AFTERBURNER ); /* We use old school flags for this still... */
         pilot->energy_loss += pilot->afterburner->outfit->u.afb.energy; /* energy loss */
      }
      else if (outfit_isJammer(o)) { /* Jammer */
         pilot->jamming        = 1;
         pilot->energy_loss   += o->u.jam.energy;
      }
   }

   if (!pilot_isFlag( pilot, PILOT_AFTERBURNER ))
      pilot->solid->speed_max = pilot->speed;

   /* Slot voodoo. */
   s = &pilot->stats;
   default_s = &pilot->ship->stats_array;

   /* Fire rate:
    *  amount = p * exp( -0.15 * (n-1) )
    *  1x 15% -> 15%
    *  2x 15% -> 25.82%
    *  3x 15% -> 33.33%
    *  6x 15% -> 42.51%
    */
   if (amount.fwd_firerate > 0) {
      s->fwd_firerate = default_s->fwd_firerate + (s->fwd_firerate-default_s->fwd_firerate) * exp( -0.15 * (double)(MAX(amount.fwd_firerate-1.,0)) );
   }
   /* Cruiser. */
   if (amount.tur_firerate > 0) {
      s->tur_firerate = default_s->tur_firerate + (s->tur_firerate-default_s->tur_firerate) * exp( -0.15 * (double)(MAX(amount.tur_firerate-1.,0)) );
   }
   /*
    * Electronic warfare setting base parameters.
    */
   s->ew_hide           = default_s->ew_hide + (s->ew_hide-default_s->ew_hide)                      * exp( -0.2 * (double)(MAX(amount.ew_hide-1.,0)) );
   s->ew_detect         = default_s->ew_detect + (s->ew_detect-default_s->ew_detect)                * exp( -0.2 * (double)(MAX(amount.ew_detect-1.,0)) );
   s->ew_jump_detect    = default_s->ew_jump_detect + (s->ew_jump_detect-default_s->ew_jump_detect) * exp( -0.2 * (double)(MAX(amount.ew_jump_detect-1.,0)) );

   /* Square the internal values to speed up comparisons. */
   pilot->ew_base_hide   = pow2( s->ew_hide );
   pilot->ew_detect      = pow2( s->ew_detect );
   pilot->ew_jump_detect = pow2( s->ew_jump_detect );

   /*
    * Relative increases.
    */
   /* Movement. */
   pilot->thrust_base  *= s->thrust_mod;
   pilot->turn_base    *= s->turn_mod;
   pilot->speed_base   *= s->speed_mod;
   /* Health. */
   pilot->armour_max   *= s->armour_mod;
   pilot->armour_regen *= s->armour_regen_mod;
   pilot->shield_max   *= s->shield_mod;
   pilot->shield_regen *= s->shield_regen_mod;
   pilot->energy_max   *= s->energy_mod;
   pilot->energy_regen *= s->energy_regen_mod;
   /* cpu */
   pilot->cpu_max       = (int)floor((float)(pilot->ship->cpu + s->cpu_max)*s->cpu_mod);
   pilot->cpu          += pilot->cpu_max; /* CPU is negative, this just sets it so it's based off of cpu_max. */
   /* Misc. */
   pilot->dmg_absorb    = MAX( 0., pilot->dmg_absorb );
   pilot->crew         *= s->crew_mod;
   pilot->cap_cargo    *= s->cargo_mod;
   s->engine_limit     *= s->engine_limit_rel;

   /*
    * Flat increases.
    */
   pilot->energy_max   += s->energy_flat;
   pilot->energy       += s->energy_flat;
   pilot->energy_regen -= s->energy_usage;

   /* Give the pilot his health proportion back */
   pilot->armour = ac * pilot->armour_max;
   pilot->shield = sc * pilot->shield_max;
   pilot->energy = ec * pilot->energy_max;
   pilot->fuel   = fc * pilot->fuel_max;

   /* Set final energy tau. */
   pilot->energy_tau = pilot->energy_max / pilot->energy_regen;

   /* Cargo has to be reset. */
   pilot_cargoCalc(pilot);

   /* Calculate mass. */
   pilot->solid->mass = s->mass_mod*pilot->ship->mass + pilot->stats.cargo_inertia*pilot->mass_cargo + pilot->mass_outfit;

   /* Calculate the heat. */
   pilot_heatCalc( pilot );

   /* Modulate by mass. */
   pilot_updateMass( pilot );

   /* Update GUI as necessary. */
   gui_setGeneric( pilot );
}
Beispiel #7
0
/**
 * @brief Recalculates the pilot's stats based on his outfits.
 *
 *    @param pilot Pilot to recalculate his stats.
 */
void pilot_calcStats( Pilot* pilot )
{
   int i;
   double q;
   Outfit* o;
   PilotOutfitSlot *slot;
   double ac, sc, ec, fc; /* temporary health coefficients to set */
   double arel, srel, erel; /* relative health bonuses. */
   ShipStats *s, *os;
   int nfirerate_turret, nfirerate_forward;
   int njammers;
   int ew_ndetect, ew_nhide;

   /* Comfortability. */
   s = &pilot->stats;

   /*
    * set up the basic stuff
    */
   /* mass */
   pilot->solid->mass   = pilot->ship->mass;
   /* movement */
   pilot->thrust        = pilot->ship->thrust;
   pilot->turn_base     = pilot->ship->turn;
   pilot->speed         = pilot->ship->speed;
   /* cpu */
   pilot->cpu_max       = pilot->ship->cpu;
   pilot->cpu           = pilot->cpu_max;
   /* crew */
   pilot->crew          = pilot->ship->crew;
   /* health */
   ac = pilot->armour / pilot->armour_max;
   sc = pilot->shield / pilot->shield_max;
   ec = pilot->energy / pilot->energy_max;
   fc = pilot->fuel   / pilot->fuel_max;
   pilot->armour_max    = pilot->ship->armour;
   pilot->shield_max    = pilot->ship->shield;
   pilot->fuel_max      = pilot->ship->fuel;
   pilot->armour_regen  = pilot->ship->armour_regen;
   pilot->shield_regen  = pilot->ship->shield_regen;
   /* Absorption. */
   pilot->dmg_absorb    = pilot->ship->dmg_absorb;
   /* Energy. */
   pilot->energy_max    = pilot->ship->energy;
   pilot->energy_regen  = pilot->ship->energy_regen;
   /* Jamming */
   pilot->jam_range     = 0.;
   pilot->jam_chance    = 0.;
   /* Stats. */
   memcpy( s, &pilot->ship->stats, sizeof(ShipStats) );

   /* cargo has to be reset */
   pilot_cargoCalc(pilot);

   /*
    * now add outfit changes
    */
   nfirerate_forward = nfirerate_turret = 0;
   pilot->mass_outfit   = 0.;
   njammers             = 0;
   ew_ndetect           = 0;
   ew_nhide             = 0;
   pilot->jam_range     = 0.;
   pilot->jam_chance    = 0.;
   arel                 = 0.;
   srel                 = 0.;
   erel                 = 0.;
   for (i=0; i<pilot->noutfits; i++) {
      slot = pilot->outfits[i];
      o    = slot->outfit;

      if (o==NULL)
         continue;

      q = (double) slot->quantity;

      /* Subtract CPU. */
      pilot->cpu           -= outfit_cpu(o) * q;
      if (outfit_cpu(o) < 0.)
         pilot->cpu_max    -= outfit_cpu(o) * q;

      /* Add mass. */
      pilot->mass_outfit   += o->mass;

      if (outfit_isMod(o)) { /* Modification */
         /* movement */
         pilot->thrust        += o->u.mod.thrust * pilot->ship->mass * q;
         pilot->thrust        += o->u.mod.thrust_rel * pilot->ship->thrust * q;
         pilot->turn_base     += o->u.mod.turn * q;
         pilot->turn_base     += o->u.mod.turn_rel * pilot->ship->turn * q;
         pilot->speed         += o->u.mod.speed * q;
         pilot->speed         += o->u.mod.speed_rel * pilot->ship->speed * q;
         /* health */
         pilot->armour_max    += o->u.mod.armour * q;
         pilot->armour_regen  += o->u.mod.armour_regen * q;
         arel                 += o->u.mod.armour_rel * q;
         pilot->shield_max    += o->u.mod.shield * q;
         pilot->shield_regen  += o->u.mod.shield_regen * q;
         srel                 += o->u.mod.shield_rel * q;
         pilot->energy_max    += o->u.mod.energy * q;
         pilot->energy_regen  += o->u.mod.energy_regen * q;
         erel                 += o->u.mod.energy_rel * q;
         /* fuel */
         pilot->fuel_max      += o->u.mod.fuel * q;
         /* misc */
         pilot->cargo_free    += o->u.mod.cargo * q;
         pilot->mass_outfit   += o->u.mod.mass_rel * pilot->ship->mass * q;
         pilot->crew          += o->u.mod.crew_rel * pilot->ship->crew * q;
         /*
          * Stats.
          */
         os = &o->u.mod.stats;
         /* Freighter. */
         s->jump_delay        += os->jump_delay * q;
         s->jump_range        += os->jump_range * q;
         s->cargo_inertia     += os->cargo_inertia * q;
         /* Scout. */
         if (os->ew_hide != 0.) {
            s->ew_hide           += os->ew_hide * q;
            ew_nhide++;
         }
         if (os->ew_detect != 0.) {
            s->ew_detect         += os->ew_detect * q;
            ew_ndetect++;
         }
         s->jam_range         += os->jam_range * q;
         /* Military. */
         s->heat_dissipation  += os->heat_dissipation * q;
         /* Bomber. */
         s->launch_rate       += os->launch_rate * q;
         s->launch_range      += os->launch_range * q;
         s->jam_counter       += os->jam_counter * q;
         s->ammo_capacity     += os->ammo_capacity * q;
         /* Fighter. */
         s->heat_forward      += os->heat_forward * q;
         s->damage_forward    += os->damage_forward * q;
         s->energy_forward    += os->energy_forward * q;
         if (os->firerate_forward != 0.) {
            s->firerate_forward  += os->firerate_forward * q;
            nfirerate_forward    += q;
         }
         /* Cruiser. */
         s->heat_turret       += os->heat_turret * q;
         s->damage_turret     += os->damage_turret * q;
         s->energy_turret     += os->energy_turret * q;
         if (os->firerate_turret != 0.) {
            s->firerate_turret   += os->firerate_turret * q;
            if (os->firerate_turret > 0.) /* Only modulate bonuses. */
               nfirerate_turret     += q;
         }
         /* Misc. */
         s->nebula_dmg_shield += os->nebula_dmg_shield * q;
         s->nebula_dmg_armour += os->nebula_dmg_armour * q;
      }
      else if (outfit_isAfterburner(o)) /* Afterburner */
         pilot->afterburner = pilot->outfits[i]; /* Set afterburner */
      else if (outfit_isJammer(o)) { /* Jammer */
         pilot->jam_range        += o->u.jam.range * q;
         pilot->jam_chance       += o->u.jam.chance * q;
         pilot->energy_regen     -= o->u.jam.energy * q;
         njammers                += q;;
      }

      /* Add ammo mass. */
      if (outfit_ammo(o) != NULL) {
         if (slot->u.ammo.outfit != NULL)
            pilot->mass_outfit += slot->u.ammo.quantity * slot->u.ammo.outfit->mass;
      }
   }

   /* Set final energy tau. */
   pilot->energy_tau = pilot->energy_max / pilot->energy_regen;

   /*
    * Electronic warfare setting base parameters.
    */
   s->ew_hide           = 1. + s->ew_hide/100. * exp( -0.2 * (double)(MAX(ew_nhide-1,0)) );
   s->ew_detect         = 1. + s->ew_detect/100. * exp( -0.2 * (double)(MAX(ew_ndetect-1,0)) );
   pilot->ew_base_hide  = s->ew_hide;
   pilot->ew_detect     = s->ew_detect;

   /*
    * Normalize stats.
    */
   /* Freighter. */
   s->jump_range        = s->jump_range/100. + 1.;
   s->jump_delay        = s->jump_delay/100. + 1.;
   s->cargo_inertia     = s->cargo_inertia/100. + 1.;
   /* Scout. */
   s->jam_range         = s->jam_range/100. + 1.;
   /* Military. */
   s->heat_dissipation  = s->heat_dissipation/100. + 1.;
   /* Bomber. */
   s->launch_rate       = s->launch_rate/100. + 1.;
   s->launch_range      = s->launch_range/100. + 1.;
   s->jam_counter       = s->jam_counter/100. + 1.;
   s->ammo_capacity     = s->ammo_capacity/100. + 1.;
   /* Fighter. */
   s->heat_forward      = s->heat_forward/100. + 1.;
   s->damage_forward    = s->damage_forward/100. + 1.;
   s->energy_forward    = s->energy_forward/100. + 1.;
   /* Fire rate:
    *  amount = p * exp( -0.15 * (n-1) )
    *  1x 15% -> 15%
    *  2x 15% -> 25.82%
    *  3x 15% -> 33.33%
    *  6x 15% -> 42.51%
    */
   s->firerate_forward  = s->firerate_forward/100.;
   if (nfirerate_forward > 0)
      s->firerate_forward *= exp( -0.15 * (double)(MAX(nfirerate_forward-1,0)) );
   s->firerate_forward += 1.;
   /* Cruiser. */
   s->heat_turret       = s->heat_turret/100. + 1.;
   s->damage_turret     = s->damage_turret/100. + 1.;
   s->energy_turret     = s->energy_turret/100. + 1.;
   s->firerate_turret   = s->firerate_turret/100.;
   if (nfirerate_turret > 0)
      s->firerate_turret  *= exp( -0.15 * (double)(MAX(nfirerate_turret-1,0)) );
   s->firerate_turret  += 1.;
   /* Misc. */
   s->nebula_dmg_shield = s->nebula_dmg_shield/100. + 1.;
   s->nebula_dmg_armour = s->nebula_dmg_armour/100. + 1.;

   /*
    * Calculate jammers.
    *
    * Range is averaged.
    * Diminishing return on chance.
    *  chance = p * exp( -0.2 * (n-1) )
    *  1x 20% -> 20%
    *  2x 20% -> 32%
    *  2x 40% -> 65%
    *  6x 40% -> 88%
    */
   if (njammers > 1) {
      pilot->jam_range  /= (double)njammers;
      pilot->jam_range  *= s->jam_range;
      pilot->jam_chance *= exp( -0.2 * (double)(MAX(njammers-1,0)) );
   }

   /* Increase health by relative bonuses. */
   pilot->armour_max += arel * pilot->ship->armour;
   pilot->shield_max += srel * pilot->ship->shield;
   pilot->energy_max += erel * pilot->ship->energy;

   /* Give the pilot his health proportion back */
   pilot->armour = ac * pilot->armour_max;
   pilot->shield = sc * pilot->shield_max;
   pilot->energy = ec * pilot->energy_max;
   pilot->fuel   = fc * pilot->fuel_max;

   /* Calculate mass. */
   pilot->solid->mass = pilot->ship->mass + s->cargo_inertia*pilot->mass_cargo + pilot->mass_outfit;

   /* Calculate the heat. */
   pilot_heatCalc( pilot );

   /* Modulate by mass. */
   pilot_updateMass( pilot );

   /* Update GUI as necessary. */
   gui_setGeneric( pilot );
}
Beispiel #8
0
/**
 * @brief Checks to see if can equip/remove an outfit from a slot.
 *
 *    @return NULL if can swap, or error message if can't.
 */
const char* pilot_canEquip( Pilot *p, PilotOutfitSlot *s, Outfit *o, int add )
{
   /* Just in case. */
   if ((p==NULL) || (o==NULL))
      return "Nothing selected.";

   /* Check slot type. */
   if ((s != NULL) && !outfit_fitsSlot( o, &s->slot ))
      return "Does not fit slot.";

   /* Adding outfit. */
   if (add) {
      if ((outfit_cpu(o) > 0) && (p->cpu < outfit_cpu(o)))
         return "Insufficient CPU";

      /* Can't add more than one afterburner. */
      if (outfit_isAfterburner(o) &&
            (p->afterburner != NULL))
         return "Already have an afterburner";

      /* Must not drive some things negative. */
      if (outfit_isMod(o)) {
         /*
          * Movement.
          */
         if (((o->u.mod.thrust + o->u.mod.thrust_rel * p->ship->thrust) < 0) &&
               (fabs(o->u.mod.thrust + o->u.mod.thrust_rel * p->ship->thrust) > p->thrust))
            return "Insufficient thrust";
         if (((o->u.mod.speed + o->u.mod.speed_rel * p->ship->speed) < 0) &&
               (fabs(o->u.mod.speed + o->u.mod.speed_rel * p->ship->speed) > p->speed))
            return "Insufficient speed";
         if (((o->u.mod.turn + o->u.mod.turn_rel * p->ship->turn * p->ship->mass/p->solid->mass) < 0) &&
               (fabs(o->u.mod.turn + o->u.mod.turn_rel * p->ship->turn * p->ship->mass/p->solid->mass) > p->turn_base))
            return "Insufficient turn";

         /*
          * Health.
          */
         /* Max. */
         if ((o->u.mod.armour < 0) &&
               (fabs(o->u.mod.armour) > p->armour_max))
            return "Insufficient armour";
         if ((o->u.mod.armour_rel < 0.) &&
               (fabs(o->u.mod.armour_rel * p->ship->armour) > p->armour_max))
            return "Insufficient armour";
         if ((o->u.mod.shield < 0) &&
               (fabs(o->u.mod.shield) > p->shield_max))
            return "Insufficient shield";
         if ((o->u.mod.shield_rel < 0.) &&
               (fabs(o->u.mod.shield_rel * p->ship->shield) > p->shield_max))
            return "Insufficient shield";
         if ((o->u.mod.energy < 0) &&
               (fabs(o->u.mod.energy) > p->armour_max))
            return "Insufficient energy";
         if ((o->u.mod.energy_rel < 0.) &&
               (fabs(o->u.mod.energy_rel * p->ship->energy) > p->energy_max))
            return "Insufficient energy";
         /* Regen. */
         if ((o->u.mod.armour_regen < 0) &&
               (fabs(o->u.mod.armour_regen) > p->armour_regen))
            return "Insufficient energy regeneration";
         if ((o->u.mod.shield_regen < 0) &&
               (fabs(o->u.mod.shield_regen) > p->shield_regen))
            return "Insufficient shield regeneration";
         if ((o->u.mod.energy_regen < 0) &&
               (fabs(o->u.mod.energy_regen) > p->energy_regen))
            return "Insufficient energy regeneration";

         /*
          * Misc.
          */
         if ((o->u.mod.fuel < 0) &&
               (fabs(o->u.mod.fuel) > p->fuel_max))
            return "Insufficient fuel";
         if ((o->u.mod.cargo < 0) &&
               (fabs(o->u.mod.cargo) > p->cargo_free))
            return "Insufficient cargo space";
      }
   }
   /* Removing outfit. */
   else {
      if ((outfit_cpu(o) < 0) && (p->cpu < fabs(outfit_cpu(o))))
         return "Lower CPU usage first";

      /* Must not drive some things negative. */
      if (outfit_isMod(o)) {
         /*
          * Movement.
          */
         if (((o->u.mod.thrust + o->u.mod.thrust_rel * p->ship->thrust) > 0) &&
               (o->u.mod.thrust + o->u.mod.thrust_rel * p->ship->thrust > p->thrust))
            return "Increase thrust first";
         if (((o->u.mod.speed + o->u.mod.speed_rel * p->ship->speed) > 0) &&
               (o->u.mod.speed + o->u.mod.speed_rel * p->ship->speed > p->speed))
            return "Increase speed first";
         if (((o->u.mod.turn + o->u.mod.turn_rel * p->ship->turn * p->ship->mass/p->solid->mass) > 0) &&
               (fabs(o->u.mod.turn + o->u.mod.turn_rel * p->ship->turn * p->ship->mass/p->solid->mass) > p->turn_base))
            return "Increase turn first";

         /*
          * Health.
          */
         /* Max. */
         if ((o->u.mod.armour > 0) &&
               (o->u.mod.armour > p->armour_max))
            return "Increase armour first";
         if ((o->u.mod.shield > 0) &&
               (o->u.mod.shield > p->shield_max))
            return "Increase shield first";
         if ((o->u.mod.energy > 0) &&
               (o->u.mod.energy > p->energy_max))
            return "Increase energy first";
         /* Regen. */
         if ((o->u.mod.armour_regen > 0) &&
               (o->u.mod.armour_regen > p->armour_regen))
            return "Lower energy usage first";
         if ((o->u.mod.shield_regen > 0) &&
               (o->u.mod.shield_regen > p->shield_regen))
            return "Lower shield usage first";
         if ((o->u.mod.energy_regen > 0) &&
               (o->u.mod.energy_regen > p->energy_regen))
            return "Lower energy usage first";

         /*
          * Misc.
          */
         if ((o->u.mod.fuel > 0) &&
               (o->u.mod.fuel > p->fuel_max))
            return "Increase fuel first";
         if ((o->u.mod.cargo > 0) &&
               (o->u.mod.cargo > p->cargo_free))
            return "Increase free cargo space first";

      }
      else if (outfit_isFighterBay(o)) {
         if ((s!=NULL) && (s->u.ammo.deployed > 0))
            return "Recall the fighters first";
      }
   }

   /* Can equip. */
   return NULL;
}
Beispiel #9
0
/**
 * @brief Recalculates the pilot's stats based on his outfits.
 *
 *    @param pilot Pilot to recalculate his stats.
 */
void pilot_calcStats( Pilot* pilot )
{
   int i;
   Outfit* o;
   PilotOutfitSlot *slot;
   double ac, sc, ec, fc; /* temporary health coefficients to set */
   double arel, srel, erel; /* relative health bonuses. */
   ShipStats amount, *s;

   /* @TODO remove old school PILOT_AFTERBURN flags. */
   pilot_rmFlag( pilot, PILOT_AFTERBURNER );

   /*
    * set up the basic stuff
    */
   /* mass */
   pilot->solid->mass   = pilot->ship->mass;
   /* movement */
   pilot->thrust        = pilot->ship->thrust;
   pilot->turn_base     = pilot->ship->turn;
   pilot->speed         = pilot->ship->speed;
   /* cpu */
   pilot->cpu_max       = pilot->ship->cpu;
   pilot->cpu           = pilot->cpu_max;
   /* crew */
   pilot->crew          = pilot->ship->crew;
   /* health */
   ac = pilot->armour / pilot->armour_max;
   sc = pilot->shield / pilot->shield_max;
   ec = pilot->energy / pilot->energy_max;
   fc = pilot->fuel   / pilot->fuel_max;
   pilot->armour_max    = pilot->ship->armour;
   pilot->shield_max    = pilot->ship->shield;
   pilot->fuel_max      = pilot->ship->fuel;
   pilot->armour_regen  = pilot->ship->armour_regen;
   pilot->shield_regen  = pilot->ship->shield_regen;
   /* Absorption. */
   pilot->dmg_absorb    = pilot->ship->dmg_absorb;
   /* Energy. */
   pilot->energy_max    = pilot->ship->energy;
   pilot->energy_regen  = pilot->ship->energy_regen;
   pilot->energy_loss   = 0.; /* Initially no net loss. */
   /* Stats. */ 
   memcpy( &pilot->stats, &pilot->ship->stats_array, sizeof(ShipStats) );
   memset( &amount, 0, sizeof(ShipStats) );

   /* cargo has to be reset */
   pilot_cargoCalc(pilot);

   /* Slot voodoo. */
   s        = &pilot->stats;
   /*
    * Electronic warfare setting base parameters.
    * @TODO ew_hide and ew_detect should be squared so XML-sourced values are linear.
    */
   s->ew_hide           = 1. + (s->ew_hide-1.) * exp( -0.2 * (double)(MAX(amount.ew_hide-1,0)) );
   s->ew_detect         = 1. + (s->ew_detect-1.) * exp( -0.2 * (double)(MAX(amount.ew_detect-1,0)) );
   s->ew_jumpDetect     = 1. + (s->ew_jumpDetect-1.) * exp( -0.2 * (double)(MAX(amount.ew_jumpDetect-1,0)) );
   pilot->ew_base_hide  = s->ew_hide;
   pilot->ew_detect     = s->ew_detect;
   pilot->ew_jumpDetect = pow2(s->ew_jumpDetect);

   /*
    * now add outfit changes
    */
   pilot->mass_outfit   = 0.;
   pilot->jamming       = 0;
   arel                 = 0.;
   srel                 = 0.;
   erel                 = 0.;
   for (i=0; i<pilot->noutfits; i++) {
      slot = pilot->outfits[i];
      o    = slot->outfit;

      /* Outfit must exist. */
      if (o==NULL)
         continue;

      /* Subtract CPU. */
      pilot->cpu           -= outfit_cpu(o);
      if (outfit_cpu(o) < 0.)
         pilot->cpu_max    -= outfit_cpu(o);

      /* Add mass. */
      pilot->mass_outfit   += o->mass;

      /* Add ammo mass. */
      if (outfit_ammo(o) != NULL)
         if (slot->u.ammo.outfit != NULL)
            pilot->mass_outfit += slot->u.ammo.quantity * slot->u.ammo.outfit->mass;

      /* Set afterburner. */
      if (outfit_isAfterburner(o))
         pilot->afterburner = pilot->outfits[i];

      /* Active outfits must be on to affect stuff. */
      if (slot->active && !(slot->state==PILOT_OUTFIT_ON))
         continue;

      if (outfit_isMod(o)) { /* Modification */
         /* movement */
         pilot->thrust        += o->u.mod.thrust * pilot->ship->mass;
         pilot->thrust        += o->u.mod.thrust_rel * pilot->ship->thrust;
         pilot->turn_base     += o->u.mod.turn;
         pilot->turn_base     += o->u.mod.turn_rel * pilot->ship->turn;
         pilot->speed         += o->u.mod.speed;
         pilot->speed         += o->u.mod.speed_rel * pilot->ship->speed;
         /* health */
         pilot->armour_max    += o->u.mod.armour;
         pilot->armour_regen  += o->u.mod.armour_regen;
         arel                 += o->u.mod.armour_rel;
         pilot->shield_max    += o->u.mod.shield;
         pilot->shield_regen  += o->u.mod.shield_regen;
         srel                 += o->u.mod.shield_rel;
         pilot->energy_max    += o->u.mod.energy;
         pilot->energy_regen  += o->u.mod.energy_regen;
         erel                 += o->u.mod.energy_rel;
         /* fuel */
         pilot->fuel_max      += o->u.mod.fuel;
         /* misc */
         pilot->cargo_free    += o->u.mod.cargo;
         pilot->mass_outfit   += o->u.mod.mass_rel * pilot->ship->mass;
         pilot->crew          += o->u.mod.crew_rel * pilot->ship->crew;
         pilot->ew_base_hide  += o->u.mod.hide_rel * pilot->ew_base_hide;
         /*
          * Stats.
          */
         ss_statsModFromList( &pilot->stats, o->u.mod.stats, &amount );
     
      }
      else if (outfit_isAfterburner(o)) { /* Afterburner */
         pilot_setFlag( pilot, PILOT_AFTERBURNER ); /* We use old school flags for this still... */
         pilot->energy_loss += pilot->afterburner->outfit->u.afb.energy; /* energy loss */
         pilot->solid->speed_max = pilot->speed +
               pilot->speed * pilot->afterburner->outfit->u.afb.speed *
               MIN( 1., pilot->afterburner->outfit->u.afb.mass_limit/pilot->solid->mass);
      }
      else if (outfit_isJammer(o)) { /* Jammer */
         pilot->jamming        = 1;
         pilot->energy_loss   += o->u.jam.energy;
      }
   }

   if (!pilot_isFlag( pilot, PILOT_AFTERBURNER ))
      pilot->solid->speed_max = pilot->speed;

   /* Set final energy tau. */
   pilot->energy_tau = pilot->energy_max / pilot->energy_regen;

   /* Fire rate:
    *  amount = p * exp( -0.15 * (n-1) )
    *  1x 15% -> 15%
    *  2x 15% -> 25.82%
    *  3x 15% -> 33.33%
    *  6x 15% -> 42.51%
    */
   if (amount.fwd_firerate > 0) {
      s->fwd_firerate = 1. + (s->fwd_firerate-1.) * exp( -0.15 * (double)(MAX(amount.fwd_firerate-1,0)) );
   }
   /* Cruiser. */
   if (amount.tur_firerate > 0) {
      s->tur_firerate = 1. + (s->tur_firerate-1.) * exp( -0.15 * (double)(MAX(amount.tur_firerate-1,0)) );
   }

   /* Increase health by relative bonuses. */
   pilot->armour_max += arel * pilot->ship->armour;
   pilot->armour_max *= pilot->stats.armour_mod;
   pilot->shield_max += srel * pilot->ship->shield;
   pilot->shield_max *= pilot->stats.shield_mod;
   pilot->energy_max += erel * pilot->ship->energy;
   /* pilot->energy_max *= pilot->stats.energy_mod; */

   /* Give the pilot his health proportion back */
   pilot->armour = ac * pilot->armour_max;
   pilot->shield = sc * pilot->shield_max;
   pilot->energy = ec * pilot->energy_max;
   pilot->fuel   = fc * pilot->fuel_max;

   /* Calculate the heat. */
   pilot_heatCalc( pilot );

   /* Modulate by mass. */
   pilot_updateMass( pilot );

   /* Update GUI as necessary. */
   gui_setGeneric( pilot );
}
Beispiel #10
0
/**
 * @brief Parses and returns Outfit from parent node.
 *
 *    @param temp Outfit to load into.
 *    @param parent Parent node to parse outfit from.
 *    @return 0 on success.
 */
static int outfit_parse( Outfit* temp, const xmlNodePtr parent )
{
   xmlNodePtr cur, node;
   char *prop;

   /* Clear data. */
   memset( temp, 0, sizeof(Outfit) );

   temp->name = xml_nodeProp(parent,"name"); /* already mallocs */
   if (temp->name == NULL) WARN("Outfit in "OUTFIT_DATA" has invalid or no name");

   node = parent->xmlChildrenNode;

   do { /* load all the data */
      if (xml_isNode(node,"general")) {
         cur = node->children;
         do {
            xmlr_int(cur,"max",temp->max);
            xmlr_int(cur,"tech",temp->tech);
            xmlr_strd(cur,"license",temp->license);
            xmlr_int(cur,"mass",temp->mass);
            xmlr_int(cur,"price",temp->price);
            xmlr_strd(cur,"description",temp->description);
            if (xml_isNode(cur,"gfx_store")) {
               temp->gfx_store = xml_parseTexture( cur,
                     OUTFIT_GFX"store/%s.png", 1, 1, 0 );
            }

         } while (xml_nextNode(cur));
      }
      else if (xml_isNode(node,"specific")) { /* has to be processed seperately */

         /* get the type */
         prop = xml_nodeProp(node,"type");
         if (prop == NULL)
            ERR("Outfit '%s' element 'specific' missing property 'type'",temp->name);
         temp->type = outfit_strToOutfitType(prop);
         free(prop);

         /* is secondary weapon? */
         prop = xml_nodeProp(node,"secondary");
         if (prop != NULL) {
            if ((int)atoi(prop)) outfit_setProp(temp, OUTFIT_PROP_WEAP_SECONDARY);
            free(prop);
         }

         if (temp->type==OUTFIT_TYPE_NULL)
            WARN("Outfit '%s' is of type NONE", temp->name);
         else if (outfit_isBolt(temp))
            outfit_parseSBolt( temp, node );
         else if (outfit_isBeam(temp))
            outfit_parseSBeam( temp, node );
         else if (outfit_isLauncher(temp))
            outfit_parseSLauncher( temp, node );
         else if (outfit_isAmmo(temp))
            outfit_parseSAmmo( temp, node );
         else if (outfit_isMod(temp))
            outfit_parseSMod( temp, node );
         else if (outfit_isAfterburner(temp))
            outfit_parseSAfterburner( temp, node );
         else if (outfit_isJammer(temp))
            outfit_parseSJammer( temp, node );
         else if (outfit_isFighterBay(temp))
            outfit_parseSFighterBay( temp, node );
         else if (outfit_isFighter(temp))
            outfit_parseSFighter( temp, node );
         else if (outfit_isMap(temp))
            outfit_parseSMap( temp, node );
         else if (outfit_isLicense(temp))
            outfit_parseSLicense( temp, node );
      }
   } while (xml_nextNode(node));

#define MELEMENT(o,s) \
if (o) WARN("Outfit '%s' missing/invalid '"s"' element", temp->name) /**< Define to help check for data errors. */
   MELEMENT(temp->name==NULL,"name");
   MELEMENT(temp->max==0,"max");
   MELEMENT(temp->tech==0,"tech");
   MELEMENT(temp->gfx_store==NULL,"gfx_store");
   /*MELEMENT(temp->mass==0,"mass"); Not really needed */
   MELEMENT(temp->type==0,"type");
   MELEMENT(temp->price==0,"price");
   MELEMENT(temp->description==NULL,"description");
#undef MELEMENT

   return 0;
}