예제 #1
0
파일: pilot_weapon.c 프로젝트: Ttech/naev
/**
 * @brief Have pilot stop shooting his weapon.
 *
 * Only really deals with beam weapons.
 *
 *    @param p Pilot that was shooting.
 *    @param level Level of the shot.
 */
void pilot_shootStop( Pilot* p, int level )
{
   int i;
   PilotWeaponSet *ws;

   /* Get active set. */
   ws = pilot_weapSet( p, p->active_set );

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

   /* Stop all beams. */
   for (i=0; i<array_size(ws->slots); i++) {

      /* Must have assosciated outfit. */
      if (ws->slots[i].slot->outfit == NULL)
         continue;

      /* Must match level. */
      if ((level != -1) && (ws->slots[i].level != level))
         continue;

      /* Only handle beams. */
      if (!outfit_isBeam(ws->slots[i].slot->outfit))
         continue;
      
      /* Stop beam. */
      if (ws->slots[i].slot->u.beamid > 0) {
         beam_end( p->id, ws->slots[i].slot->u.beamid );
         ws->slots[i].slot->u.beamid = 0;
      }
   }
}
예제 #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 )
{
   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;
}
예제 #3
0
파일: outfit.c 프로젝트: pegue/naev
/**
 * @brief Gets the outfit's graphic effect.
 *    @param o Outfit to get information from.
 */
glTexture* outfit_gfx( const Outfit* o )
{
   if (outfit_isBolt(o)) return o->u.blt.gfx_space;
   else if (outfit_isBeam(o)) return o->u.bem.gfx;
   else if (outfit_isAmmo(o)) return o->u.amm.gfx_space;
   return NULL;
}
예제 #4
0
파일: outfit.c 프로젝트: pegue/naev
/**
 * @brief Gets the outfit's energy usage.
 *    @param o Outfit to get information from.
 */
double outfit_energy( const Outfit* o )
{
   if (outfit_isBolt(o)) return o->u.blt.energy;
   else if (outfit_isBeam(o)) return o->u.bem.energy;
   else if (outfit_isAmmo(o)) return o->u.amm.energy;
   return -1.;
}
예제 #5
0
파일: outfit.c 프로젝트: pegue/naev
/**
 * @brief Gets the outfit's range.
 *    @param o Outfit to get information from.
 */
double outfit_range( const Outfit* o )
{
   if (outfit_isBolt(o)) return o->u.blt.range;
   else if (outfit_isBeam(o)) return o->u.bem.range;
   else if (outfit_isAmmo(o)) return 0.8*o->u.amm.speed*o->u.amm.duration;
   return -1.;
}
예제 #6
0
파일: outfit.c 프로젝트: pegue/naev
/**
 * @brief Gets the outfit's damage type.
 *    @param o Outfit to get information from.
 */
DamageType outfit_damageType( const Outfit* o )
{
   if (outfit_isBolt(o)) return o->u.blt.dtype;
   else if (outfit_isBeam(o)) return o->u.bem.dtype;
   else if (outfit_isAmmo(o)) return o->u.amm.dtype;
   return DAMAGE_TYPE_NULL;
}
예제 #7
0
파일: outfit.c 프로젝트: pegue/naev
/**
 * @brief Gets the outfit's damage.
 *    @param o Outfit to get information from.
 */
double outfit_damage( const Outfit* o )
{
   if (outfit_isBolt(o)) return o->u.blt.damage;
   else if (outfit_isBeam(o)) return o->u.bem.damage;
   else if (outfit_isAmmo(o)) return o->u.amm.damage;
   return -1.;
}
예제 #8
0
파일: outfit.c 프로젝트: pegue/naev
/**
 * @brief Gets the outfit's sound effect.
 *    @param o Outfit to get information from.
 */
int outfit_spfxShield( const Outfit* o )
{
   if (outfit_isBolt(o)) return o->u.blt.spfx_shield;
   else if (outfit_isBeam(o)) return o->u.bem.spfx_shield;
   else if (outfit_isAmmo(o)) return o->u.amm.spfx_shield;
   return -1;
}
예제 #9
0
파일: outfit.c 프로젝트: pegue/naev
/**
 * @brief Gets the outfit's sound effect.
 *    @param o Outfit to get information from.
 */
int outfit_spfxArmour( const Outfit* o )
{
   if (outfit_isBolt(o)) return o->u.blt.spfx_armour;
   else if (outfit_isBeam(o)) return o->u.bem.spfx_armour;
   else if (outfit_isAmmo(o)) return o->u.amm.spfx_armour;
   return -1;
}
예제 #10
0
파일: pilot_weapon.c 프로젝트: nenau/naev
/**
 * @brief Computes an estimation of ammo flying time
 *
 *    @param w the weapon that shoot
 *    @param parent Parent of the weapon
 *    @param target Target of the weapon
 */
double pilot_weapFlyTime( Outfit *o, Pilot *parent, Vector2d *pos, Vector2d *vel)
{
   Vector2d approach_vector, relative_location, orthoradial_vector;
   double speed, radial_speed, orthoradial_speed, dist, t;

   dist = vect_dist( &parent->solid->pos, pos );

   /* Beam weapons */
   if (outfit_isBeam(o))
      {
      if (dist > o->u.bem.range)
         return INFINITY;
      return 0.;
      }

   /* A bay doesn't have range issues */
   if (outfit_isFighterBay(o))
      return 0.;

   /* Rockets use absolute velocity while bolt use relative vel */
   if (outfit_isLauncher(o))
         vect_cset( &approach_vector, - vel->x, - vel->y );
   else
         vect_cset( &approach_vector, VX(parent->solid->vel) - vel->x,
               VY(parent->solid->vel) - vel->y );

   speed = outfit_speed(o);

   /* Get the vector : shooter -> target */
   vect_cset( &relative_location, pos->x - VX(parent->solid->pos),
         pos->y - VY(parent->solid->pos) );

   /* Get the orthogonal vector */
   vect_cset(&orthoradial_vector, VY(parent->solid->pos) - pos->y,
         pos->x -  VX(parent->solid->pos) );

   radial_speed = vect_dot( &approach_vector, &relative_location );
   radial_speed = radial_speed / VMOD(relative_location);

   orthoradial_speed = vect_dot(&approach_vector, &orthoradial_vector);
   orthoradial_speed = orthoradial_speed / VMOD(relative_location);

   if( ((speed*speed - VMOD(approach_vector)*VMOD(approach_vector)) != 0) && (speed*speed - orthoradial_speed*orthoradial_speed) > 0)
      t = dist * (sqrt( speed*speed - orthoradial_speed*orthoradial_speed ) - radial_speed) /
            (speed*speed - VMOD(approach_vector)*VMOD(approach_vector));
   else
      return INFINITY;

   /* if t < 0, try the other solution */
   if (t < 0)
      t = - dist * (sqrt( speed*speed - orthoradial_speed*orthoradial_speed ) + radial_speed) /
            (speed*speed - VMOD(approach_vector)*VMOD(approach_vector));

   /* if t still < 0, no solution */
   if (t < 0)
      return INFINITY;

   return t;
}
예제 #11
0
파일: outfit.c 프로젝트: pegue/naev
/**
 * @brief Gets the outfit's delay.
 *    @param o Outfit to get information from.
 */
int outfit_delay( const Outfit* o )
{
   if (outfit_isBolt(o)) return o->u.blt.delay;
   else if (outfit_isBeam(o)) return o->u.bem.delay;
   else if (outfit_isLauncher(o)) return o->u.lau.delay;
   else if (outfit_isFighterBay(o)) return o->u.bay.delay;
   return -1;
}
예제 #12
0
파일: pilot_weapon.c 프로젝트: nenau/naev
/**
 * @brief Have pilot stop shooting their weapon.
 *
 * Only really deals with beam weapons.
 *
 *    @param p Pilot that was shooting.
 *    @param level Level of the shot.
 */
void pilot_shootStop( Pilot* p, int level )
{
   int i, recalc;
   PilotWeaponSet *ws;
   PilotOutfitSlot *slot;

   /* Get active set. */
   ws = pilot_weapSet( p, p->active_set );

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

   /* Stop all beams. */
   recalc = 0;
   for (i=0; i<array_size(ws->slots); i++) {
      slot = ws->slots[i].slot;

      /* Must have associated outfit. */
      if (ws->slots[i].slot->outfit == NULL)
         continue;

      /* Must match level. */
      if ((level != -1) && (ws->slots[i].level != level))
         continue;

      /* Only handle beams. */
      if (!outfit_isBeam(slot->outfit)) {
         /* Turn off the state. */
         if (outfit_isMod( slot->outfit )) {
            slot->state = PILOT_OUTFIT_OFF;
            recalc = 1;
         }
         continue;
      }

      /* Stop beam. */
      if (ws->slots[i].slot->u.beamid > 0) {
         /* Enforce minimum duration if set. */
         if (slot->outfit->u.bem.min_duration > 0.) {

            slot->stimer = slot->outfit->u.bem.min_duration -
                  (slot->outfit->u.bem.duration - slot->timer);

            if (slot->stimer > 0.)
               continue;
         }

         beam_end( p->id, slot->u.beamid );
         pilot_stopBeam(p, slot);
      }
   }

   /* Must recalculate. */
   if (recalc)
      pilot_calcStats( p );
}
예제 #13
0
/**
 * @brief Dumps the beam weapon data to csv.
 */
void dout_csvBeam( const char *path )
{
   Outfit *o, *o_all;
   int i, n, l;
   SDL_RWops *rw;
   char buf[ 1024 ];
   Damage *dmg;

   /* File to output to. */
   rw = SDL_RWFromFile( path, "w" );
   if (rw == NULL) {
      WARN("Unable to open '%s' for writing: %s", path, SDL_GetError());
      return;
   }

   /* Write "header" */
   l = nsnprintf( buf, sizeof(buf),
      "name,type,slot,size,"
      "license,mass,price,cpu,"
      "delay,warmup,duration,min_duration,"
      "range,turn,energy,heatup,"
      "penetrate,dtype,damage,disable\n"
      );
   SDL_RWwrite( rw, buf, l, 1 );

   o_all = outfit_getAll( &n );
   for (i=0; i<n; i++) {
      o = &o_all[i];

      /* Only handle bolt weapons. */
      if (!outfit_isBeam(o))
         continue;

      dmg = &o->u.bem.dmg;
      l = nsnprintf( buf, sizeof(buf),
            "%s,%s,%s,%s,"
            "%s,%f,%"CREDITS_PRI",%f,"
            "%f,%f,%f,%f,"
            "%f,%f,%f,%f,"
            "%f,%s,%f,%f\n",
            o->name, outfit_getType(o), outfit_slotName(o), outfit_slotSize(o),
            o->license, o->mass, o->price, o->cpu,
            o->u.bem.delay, o->u.bem.warmup, o->u.bem.duration, o->u.bem.min_duration,
            o->u.bem.range, o->u.bem.turn * 180. / M_PI, o->u.bem.energy, o->u.bem.heatup,
            dmg->penetration*100, dtype_damageTypeToStr(dmg->type), dmg->damage, dmg->disable
            );
      SDL_RWwrite( rw, buf, l, 1 );
   }

   /* Close file. */
   SDL_RWclose( rw );
}
예제 #14
0
파일: weapon.c 프로젝트: zid/naev
/**
 * @brief Destroys a weapon.
 *
 *    @param w Weapon to destroy.
 *    @param layer Layer to which the weapon belongs.
 */
static void weapon_destroy( Weapon* w, WeaponLayer layer )
{
   int i;
   Weapon** wlayer;
   int *nlayer;
   Pilot *pilot_target;

   /* Decrement target lockons if needed */
   if (outfit_isSeeker(w->outfit)) {
      pilot_target = pilot_get( w->target );
      if (pilot_target != NULL)
         pilot_target->lockons--;
   }

   /* Stop playing sound if beam weapon. */
   if (outfit_isBeam(w->outfit)) {
      sound_stop( w->voice );
      sound_playPos(w->outfit->u.bem.sound_off,
            w->solid->pos.x,
            w->solid->pos.y,
            w->solid->vel.x,
            w->solid->vel.y);
   }

   switch (layer) {
      case WEAPON_LAYER_BG:
         wlayer = wbackLayer;
         nlayer = &nwbackLayer;
         break;
      case WEAPON_LAYER_FG:
         wlayer = wfrontLayer;
         nlayer = &nwfrontLayer;
         break;

      default:
         WARN("Unknown weapon layer!");
   }

   for (i=0; (wlayer[i] != w) && (i < *nlayer); i++); /* get to the curent position */
   if (i >= *nlayer) {
      WARN("Trying to destroy weapon not found in stack!");
      return;
   }

   weapon_free(wlayer[i]);
   wlayer[i] = NULL;
   (*nlayer)--;

   for ( ; i < (*nlayer); i++)
      wlayer[i] = wlayer[i+1];
}
예제 #15
0
파일: outfit.c 프로젝트: pegue/naev
/**
 * @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";
}
예제 #16
0
파일: pilot_weapon.c 프로젝트: Ttech/naev
/**
 * @brief Adds an outfit to a weapon set.
 *
 *    @param p Pilot to manipulate.
 *    @param id ID of the weapon set.
 *    @param o Outfit to add.
 *    @param level Level of the trigger.
 */
void pilot_weapSetAdd( Pilot* p, int id, PilotOutfitSlot *o, int level )
{
   PilotWeaponSet *ws;
   PilotWeaponSetOutfit *slot;
   Outfit *oo;
   int i;

   ws = pilot_weapSet(p,id);

   /* Make sure outfit is valid. */
   oo = o->outfit;
   if (oo == NULL)
      return;

   /* Make sure outfit type is weapon (or usable). */
   if (!(outfit_isBeam(oo) || outfit_isBolt(oo) ||
            outfit_isLauncher(oo) || outfit_isFighterBay(oo)))
      return;

   /* Create if needed. */
   if (ws->slots == NULL)
      ws->slots = array_create( PilotWeaponSetOutfit );

   /* Check if already there. */
   for (i=0; i<array_size(ws->slots); i++) {
      if (ws->slots[i].slot == o) {
         ws->slots[i].level = level;

         /* Update if needed. */
         if (id == p->active_set)
            pilot_weapSetUpdateOutfits( p, ws );
         return;
      }
   }

   /* Add it. */
   slot        = &array_grow( &ws->slots );
   slot->level = level;
   slot->slot  = o;

   /* Update range. */
   pilot_weapSetUpdateRange( ws );

   /* Update if needed. */
   if (id == p->active_set)
      pilot_weapSetUpdateOutfits( p, ws );
}
예제 #17
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;
}
예제 #18
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;
   s->quantity = 1; /* Sort of pointless, but hey. */

   /* 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_setFlag(pilot, PILOT_HASTURRET);

   if (outfit_isBeam(outfit)) { /* Used to speed up some calculations. */
      s->u.beamid = -1;
      pilot_setFlag(pilot, PILOT_HASBEAMS);
   }
   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;
   if (outfit_isForward(o) || outfit_isTurret(o) || outfit_isLauncher(o) || outfit_isFighterBay(o))
      s->active = 1;
   else
      s->active = 0;

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

   return 0;
}
예제 #19
0
/**
 * @brief Removes an outfit from the pilot without doing any checks.
 *
 * @note Does not run pilot_calcStats().
 *
 *    @param pilot Pilot to remove the outfit from.
 *    @param s Slot to remove.
 *    @return 0 on success.
 */
int pilot_rmOutfitRaw( Pilot* pilot, PilotOutfitSlot *s )
{
   int ret;

   /* Decrement counters if necessary. */
   if (s->outfit != NULL) {
      if (outfit_isTurret(s->outfit))
         pilot->nturrets--;
      else if (outfit_isBolt(s->outfit))
         pilot->ncannons--;
      if (outfit_isBeam(s->outfit))
         pilot->nbeams--;
   }

   /* Remove the outfit. */
   ret         = (s->outfit==NULL);
   s->outfit   = NULL;

   /* Remove secondary and such if necessary. */
   if (pilot->afterburner == s)
      pilot->afterburner = NULL;

   return ret;
}
예제 #20
0
파일: pilot_weapon.c 프로젝트: Ttech/naev
/**
 * @brief Tries to automatically set and create the pilot's weapon set.
 *
 * Weapon set 0 is for all weapons. <br />
 * Weapon set 1 is for forward weapons. Ammo using weapons are secondaries. <br />
 * Weapon set 2 is for turret weapons. Ammo using weapons are secondaries. <br />
 * Weapon set 3 is for all weapons. Forwards are primaries and turrets are secondaries. <br />
 * Weapon set 4 is for seeking weapons. High payload variants are secondaries. <br />
 * Weapon set 5 is for fighter bays. <br />
 *
 *    @param p Pilot to automagically generate weapon lists.
 */
void pilot_weaponAuto( Pilot *p )
{
   PilotOutfitSlot *slot;
   Outfit *o;
   int i, level, id;

   /* Clear weapons. */
   pilot_weaponClear( p );

   /* Set modes. */
   pilot_weapSetMode( p, 0, 0 );
   pilot_weapSetMode( p, 1, 0 );
   pilot_weapSetMode( p, 2, 0 );
   pilot_weapSetMode( p, 3, 0 );
   pilot_weapSetMode( p, 4, 1 );
   pilot_weapSetMode( p, 5, 1 );
   pilot_weapSetMode( p, 6, 0 );
   pilot_weapSetMode( p, 7, 0 );
   pilot_weapSetMode( p, 8, 0 );
   pilot_weapSetMode( p, 9, 0 );

   /* Set names. */
   pilot_weapSetNameSet( p, 0, "All" );
   pilot_weapSetNameSet( p, 1, "Forward" );
   pilot_weapSetNameSet( p, 2, "Turret" );
   pilot_weapSetNameSet( p, 3, "Fwd/Tur" );
   pilot_weapSetNameSet( p, 4, "Seekers" );
   pilot_weapSetNameSet( p, 5, "Fighter Bays" );
   pilot_weapSetNameSet( p, 6, "Weaponset 7" );
   pilot_weapSetNameSet( p, 7, "Weaponset 8" );
   pilot_weapSetNameSet( p, 8, "Weaponset 9" );
   pilot_weapSetNameSet( p, 9, "Weaponset 0" );

   /* Iterate through all the outfits. */
   for (i=0; i<p->outfit_nweapon; i++) {
      slot = &p->outfit_weapon[i];
      o    = slot->outfit;

      /* Must have outfit. */
      if (o == NULL) {
         slot->level = -1; /* Clear level. */
         continue;
      }

      /* Bolts and beams. */
      if (outfit_isBolt(o) || outfit_isBeam(o) ||
            (outfit_isLauncher(o) && !outfit_isSeeker(o->u.lau.ammo))) {
         id    = outfit_isTurret(o) ? 2 : 1;
         level = (outfit_ammo(o) != NULL) ? 1 : 0;
      }
      /* Seekers. */
      else if (outfit_isLauncher(o) && outfit_isSeeker(o->u.lau.ammo)) {
         id    = 4;
         level = 1;
      }
      /* Fighter bays. */
      else if (outfit_isFighterBay(o)) {
         id    = 5;
         level = 0;
      }
      /* Ignore rest. */
      else
         continue;
   
      /* Add to it's base group. */
      pilot_weapSetAdd( p, id, slot, level );
   
      /* Also add another copy to another group. */
      if (id == 1) { /* Forward. */
         pilot_weapSetAdd( p, 0, slot, level ); /* Also get added to 'All'. */
         pilot_weapSetAdd( p, 3, slot, 0 );     /* Also get added to 'Fwd/Tur'. */
      }
      else if (id == 2) { /* Turrets. */
         pilot_weapSetAdd( p, 0, slot, level ); /* Also get added to 'All'. */
         pilot_weapSetAdd( p, 3, slot, 1 );     /* Also get added to 'Fwd/Tur'. */
      }
      else if (id == 4) { /* Seekers */
         pilot_weapSetAdd( p, 0, slot, level ); /* Also get added to 'All'. */
      }
   }
}
예제 #21
0
파일: pilot_weapon.c 프로젝트: nenau/naev
/**
 * @brief Tries to automatically set and create the pilot's weapon set.
 *
 * Weapon set 0 is for all weapons. <br />
 * Weapon set 1 is for forward weapons. Ammo using weapons are secondaries. <br />
 * Weapon set 2 is for turret weapons. Ammo using weapons are secondaries. <br />
 * Weapon set 3 is for all weapons. Forwards are primaries and turrets are secondaries. <br />
 * Weapon set 4 is for seeking weapons. High payload variants are secondaries. <br />
 * Weapon set 5 is for fighter bays. <br />
 *
 *    @param p Pilot to automagically generate weapon lists.
 */
void pilot_weaponAuto( Pilot *p )
{
   PilotOutfitSlot *slot;
   Outfit *o;
   int i, level, id;

   /* Clear weapons. */
   pilot_weaponClear( p );

   /* Set modes. */
   pilot_weapSetType( p, 0, WEAPSET_TYPE_CHANGE );
   pilot_weapSetType( p, 1, WEAPSET_TYPE_CHANGE );
   pilot_weapSetType( p, 2, WEAPSET_TYPE_CHANGE );
   pilot_weapSetType( p, 3, WEAPSET_TYPE_CHANGE );
   pilot_weapSetType( p, 4, WEAPSET_TYPE_WEAPON );
   pilot_weapSetType( p, 5, WEAPSET_TYPE_WEAPON );
   pilot_weapSetType( p, 6, WEAPSET_TYPE_ACTIVE );
   pilot_weapSetType( p, 7, WEAPSET_TYPE_ACTIVE );
   pilot_weapSetType( p, 8, WEAPSET_TYPE_ACTIVE );
   pilot_weapSetType( p, 9, WEAPSET_TYPE_ACTIVE );

   /* All should be inrange. */
   if (!pilot_isPlayer(p))
      for (i=0; i<PILOT_WEAPON_SETS; i++){
         pilot_weapSetInrange( p, i, 1 );
         /* Update range and speed (at 0)*/
         pilot_weapSetUpdateRange( &p->weapon_sets[i] );
      }

   /* Iterate through all the outfits. */
   for (i=0; i<p->noutfits; i++) {
      slot = p->outfits[i];
      o    = slot->outfit;

      /* Must be non-empty, and a weapon or active outfit. */
      if ((o == NULL) || !outfit_isActive(o)) {
         slot->level   = -1; /* Clear level. */
         slot->weapset = -1;
         continue;
      }

      /* Manually defined group preempts others. */
      if (o->group) {
         id    = o->group;
      }
      /* Bolts and beams. */
      else if (outfit_isBolt(o) || outfit_isBeam(o) ||
            (outfit_isLauncher(o) && !outfit_isSeeker(o->u.lau.ammo))) {
         id    = outfit_isTurret(o) ? 2 : 1;
      }
      /* Seekers. */
      else if (outfit_isLauncher(o) && outfit_isSeeker(o->u.lau.ammo)) {
         id    = 4;
      }
      /* Fighter bays. */
      else if (outfit_isFighterBay(o)) {
         id    = 5;
      }
      /* Ignore rest. */
      else {
         slot->level = -1;
         continue;
      }

      /* Set level based on secondary flag. */
      level = outfit_isSecondary(o);

      /* Add to its base group. */
      pilot_weapSetAdd( p, id, slot, level );

      /* Also add another copy to another group. */
      if (id == 1) { /* Forward. */
         pilot_weapSetAdd( p, 0, slot, level ); /* Also get added to 'All'. */
         pilot_weapSetAdd( p, 3, slot, 0 );     /* Also get added to 'Fwd/Tur'. */
      }
      else if (id == 2) { /* Turrets. */
         pilot_weapSetAdd( p, 0, slot, level ); /* Also get added to 'All'. */
         pilot_weapSetAdd( p, 3, slot, 1 );     /* Also get added to 'Fwd/Tur'. */
      }
      else if (id == 4) /* Seekers */
         pilot_weapSetAdd( p, 0, slot, level ); /* Also get added to 'All'. */
   }

   /* Update active weapon set. */
   pilot_weapSetUpdateOutfits( p, &p->weapon_sets[ p->active_set ] );
}
예제 #22
0
파일: pilot_weapon.c 프로젝트: nenau/naev
/**
 * @brief Actually handles the shooting, how often the player.p can shoot and such.
 *
 *    @param p Pilot that is shooting.
 *    @param w Pilot's outfit to shoot.
 *    @param time Expected flight time.
 *    @return 0 if nothing was shot and 1 if something was shot.
 */
static int pilot_shootWeapon( Pilot* p, PilotOutfitSlot* w, double time )
{
   Vector2d vp, vv;
   double rate_mod, energy_mod;
   double energy;
   int j;

   /* Make sure weapon has outfit. */
   if (w->outfit == NULL)
      return 0;

   /* Reset beam shut-off if needed. */
   if (outfit_isBeam(w->outfit) && w->outfit->u.bem.min_duration)
      w->stimer = INFINITY;

   /* check to see if weapon is ready */
   if (w->timer > 0.)
      return 0;

   /* Calculate rate modifier. */
   pilot_getRateMod( &rate_mod, &energy_mod, p, w->outfit );

   /* Get weapon mount position. */
   pilot_getMount( p, w, &vp );
   vp.x += p->solid->pos.x;
   vp.y += p->solid->pos.y;

   /* Modify velocity to take into account the rotation. */
   vect_cset( &vv, p->solid->vel.x + vp.x*p->solid->dir_vel,
         p->solid->vel.y + vp.y*p->solid->dir_vel );

   /*
    * regular bolt weapons
    */
   if (outfit_isBolt(w->outfit)) {

      /* enough energy? */
      if (outfit_energy(w->outfit)*energy_mod > p->energy)
         return 0;

      energy      = outfit_energy(w->outfit)*energy_mod;
      p->energy  -= energy;
      pilot_heatAddSlot( p, w );
      weapon_add( w->outfit, w->heat_T, p->solid->dir,
            &vp, &p->solid->vel, p, p->target, time );
   }

   /*
    * Beam weapons.
    */
   else if (outfit_isBeam(w->outfit)) {
      /* Don't fire if the existing beam hasn't been destroyed yet. */
      if (w->u.beamid > 0)
         return 0;

      /* Check if enough energy to last a second. */
      if (outfit_energy(w->outfit)*energy_mod > p->energy)
         return 0;

      /** @todo Handle warmup stage. */
      w->state = PILOT_OUTFIT_ON;
      w->u.beamid = beam_start( w->outfit, p->solid->dir,
            &vp, &p->solid->vel, p, p->target, w );

      w->timer = w->outfit->u.bem.duration;

      return 1; /* Return early due to custom timer logic. */
   }

   /*
    * missile launchers
    *
    * must be a secondary weapon
    */
   else if (outfit_isLauncher(w->outfit)) {

      /* Shooter can't be the target - sanity check for the player.p */
      if ((w->outfit->u.lau.ammo->u.amm.ai != AMMO_AI_DUMB) && (p->id==p->target))
         return 0;

      /* Must have ammo left. */
      if ((w->u.ammo.outfit == NULL) || (w->u.ammo.quantity <= 0))
         return 0;

      /* enough energy? */
      if (outfit_energy(w->u.ammo.outfit)*energy_mod > p->energy)
         return 0;

      energy      = outfit_energy(w->u.ammo.outfit)*energy_mod;
      p->energy  -= energy;
      pilot_heatAddSlot( p, w );
      weapon_add( w->outfit, w->heat_T, p->solid->dir,
            &vp, &p->solid->vel, p, p->target, time );

      w->u.ammo.quantity -= 1; /* we just shot it */
      p->mass_outfit     -= w->u.ammo.outfit->mass;
      p->solid->mass     -= w->u.ammo.outfit->mass;

      pilot_updateMass( p );

      /* If last ammo was shot, update the range */
      if (w->u.ammo.quantity <= 0) {
         for (j=0; j<PILOT_WEAPON_SETS; j++)
            pilot_weapSetUpdateRange( &p->weapon_sets[j] );
      }
   }

   /*
    * Fighter bays.
    */
   else if (outfit_isFighterBay(w->outfit)) {

      /* Must have ammo left. */
      if ((w->u.ammo.outfit == NULL) || (w->u.ammo.quantity <= 0))
         return 0;

      /* Create the escort. */
      escort_create( p, w->u.ammo.outfit->u.fig.ship,
            &vp, &p->solid->vel, p->solid->dir, ESCORT_TYPE_BAY, 1 );

      w->u.ammo.quantity -= 1; /* we just shot it */
      p->mass_outfit     -= w->u.ammo.outfit->mass;
      w->u.ammo.deployed += 1; /* Mark as deployed. */
      pilot_updateMass( p );
   }
   else
      WARN(_("Shooting unknown weapon type: %s"), w->outfit->name);


   /* Reset timer. */
   w->timer += rate_mod * outfit_delay( w->outfit );

   return 1;
}
예제 #23
0
파일: weapon.c 프로젝트: zid/naev
/**
 * @brief Updates an individual weapon.
 *
 *    @param w Weapon to update.
 *    @param dt Current delta tick.
 *    @param layer Layer to which the weapon belongs.
 */
static void weapon_update( Weapon* w, const double dt, WeaponLayer layer )
{
   int i, psx,psy;
   glTexture *gfx;
   Vector2d crash[2];
   Pilot *p;

   /* Get the sprite direction to speed up calculations. */
   if (!outfit_isBeam(w->outfit)) {
      gfx = outfit_gfx(w->outfit);
      gl_getSpriteFromDir( &w->sx, &w->sy, gfx, w->solid->dir );
   }

   for (i=0; i<pilot_nstack; i++) {

      p = pilot_stack[i];

      psx = pilot_stack[i]->tsx;
      psy = pilot_stack[i]->tsy;

      if (w->parent == pilot_stack[i]->id) continue; /* pilot is self */

      /* Beam weapons have special collisions. */
      if (outfit_isBeam(w->outfit)) {
         /* Check for collision. */
         if (weapon_checkCanHit(w,p) &&
               CollideLineSprite( &w->solid->pos, w->solid->dir,
                     w->outfit->u.bem.range,
                     p->ship->gfx_space, psx, psy,
                     &p->solid->pos,
                     crash)) {
            weapon_hitBeam( w, p, layer, crash, dt );
            /* No return because beam can still think, it's not
             * destroyed like the other weapons.*/
         }
      }
      /* smart weapons only collide with their target */
      else if (weapon_isSmart(w)) {

         if ((pilot_stack[i]->id == w->target) &&
               (w->status != WEAPON_STATUS_OK) && /* Must not be locking on. */
               weapon_checkCanHit(w,p) &&
               CollideSprite( gfx, w->sx, w->sy, &w->solid->pos,
                     p->ship->gfx_space, psx, psy,
                     &p->solid->pos,
                     &crash[0] )) {
            weapon_hit( w, p, layer, &crash[0] );
            return; /* Weapon is destroyed. */
         }
      }
      /* dumb weapons hit anything not of the same faction */
      else {
         if (weapon_checkCanHit(w,p) &&
               CollideSprite( gfx, w->sx, w->sy, &w->solid->pos,
                     p->ship->gfx_space, psx, psy,
                     &p->solid->pos,
                     &crash[0] )) {
            weapon_hit( w, p, layer, &crash[0] );
            return; /* Weapon is destroyed. */
         }
      }
   }

   /* smart weapons also get to think their next move */
   if (weapon_isSmart(w))
      (*w->think)(w,dt);

   /* Update the solid position. */
   (*w->solid->update)(w->solid, dt);

   /* Update the sound. */
   sound_updatePos(w->voice, w->solid->pos.x, w->solid->pos.y,
         w->solid->vel.x, w->solid->vel.y);
}
예제 #24
0
파일: weapon.c 프로젝트: zid/naev
/**
 * @brief Starts a beam weaapon.
 *
 *    @param outfit Outfit which spawns the weapon.
 *    @param dir Direction of the shooter.
 *    @param pos Position of the shooter.
 *    @param vel Velocity of the shooter.
 *    @param parent Pilot ID of the shooter.
 *    @param target Target ID that is getting shot.
 *    @param mount Mount on the ship.
 *    @return The identifier of the beam weapon.
 *
 * @sa beam_end
 */
int beam_start( const Outfit* outfit,
      const double dir, const Vector2d* pos, const Vector2d* vel,
      const unsigned int parent, const unsigned int target,
      const PilotOutfitSlot *mount )
{
   WeaponLayer layer;
   Weapon *w;
   Weapon **curLayer;
   int *mLayer, *nLayer;
   GLsizei size;

   if (!outfit_isBeam(outfit)) {
      ERR("Trying to create a Beam Weapon from a non-beam outfit.");
      return -1;
   }

   layer = (parent==PLAYER_ID) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG;
   w = weapon_create( outfit, dir, pos, vel, parent, target );
   w->ID = ++beam_idgen;
   w->mount = mount;

   /* set the proper layer */
   switch (layer) {
      case WEAPON_LAYER_BG:
         curLayer = wbackLayer;
         nLayer = &nwbackLayer;
         mLayer = &mwbacklayer;
         break;
      case WEAPON_LAYER_FG:
         curLayer = wfrontLayer;
         nLayer = &nwfrontLayer;
         mLayer = &mwfrontLayer;
         break;

      default:
         ERR("Invalid WEAPON_LAYER specified");
         return -1;
   }

   if (*mLayer > *nLayer) /* more memory alloced than needed */
      curLayer[(*nLayer)++] = w;
   else { /* need to allocate more memory */
      switch (layer) {
         case WEAPON_LAYER_BG:
            (*mLayer) += WEAPON_CHUNK;
            curLayer = wbackLayer = realloc(curLayer, (*mLayer)*sizeof(Weapon*));
            break;
         case WEAPON_LAYER_FG:
            (*mLayer) += WEAPON_CHUNK;
            curLayer = wfrontLayer = realloc(curLayer, (*mLayer)*sizeof(Weapon*));
            break;
      }
      curLayer[(*nLayer)++] = w;

      /* Grow the vertex stuff. */
      weapon_vboSize = mwfrontLayer + mwbacklayer;
      size = sizeof(GLfloat) * (2+4) * weapon_vboSize;
      weapon_vboData = realloc( weapon_vboData, size );
      if (weapon_vbo == NULL)
         weapon_vbo = gl_vboCreateStream( size, NULL );
   }

   return w->ID;
}
예제 #25
0
/**
 * @brief Actually handles the shooting, how often the player.p can shoot and such.
 *
 *    @param p Pilot that is shooting.
 *    @param w Pilot's outfit to shoot.
 *    @return 0 if nothing was shot and 1 if something was shot.
 */
static int pilot_shootWeapon( Pilot* p, PilotOutfitSlot* w )
{
   Vector2d vp, vv;
   double rate_mod, energy_mod;
   double energy;

   /* Make sure weapon has outfit. */
   if (w->outfit == NULL)
      return 0;

   /* check to see if weapon is ready */
   if (w->timer > 0.)
      return 0;

   /* Calculate rate modifier. */
   pilot_getRateMod( &rate_mod, &energy_mod, p, w->outfit );

   /* Get weapon mount position. */
   pilot_getMount( p, w, &vp );
   vp.x += p->solid->pos.x;
   vp.y += p->solid->pos.y;

   /* Modify velocity to take into account the rotation. */
   vect_cset( &vv, p->solid->vel.x + vp.x*p->solid->dir_vel,
         p->solid->vel.y + vp.y*p->solid->dir_vel );

   /*
    * regular bolt weapons
    */
   if (outfit_isBolt(w->outfit)) {

      /* enough energy? */
      if (outfit_energy(w->outfit)*energy_mod > p->energy)
         return 0;

      energy      = outfit_energy(w->outfit)*energy_mod;
      p->energy  -= energy;
      pilot_heatAddSlot( p, w );
      weapon_add( w->outfit, w->heat_T, p->solid->dir,
            &vp, &p->solid->vel, p, p->target );
   }

   /*
    * Beam weapons.
    */
   else if (outfit_isBeam(w->outfit)) {

      /* Check if enough energy to last a second. */
      if (outfit_energy(w->outfit)*energy_mod > p->energy)
         return 0;

      /** @todo Handle warmup stage. */
      w->state = PILOT_OUTFIT_ON;
      w->u.beamid = beam_start( w->outfit, p->solid->dir,
            &vp, &p->solid->vel, p, p->target, w );
   }

   /*
    * missile launchers
    *
    * must be a secondary weapon
    */
   else if (outfit_isLauncher(w->outfit)) {

      /* Shooter can't be the target - sanity check for the player.p */
      if ((w->outfit->u.lau.ammo->u.amm.ai > 0) && (p->id==p->target))
         return 0;

      /* Must have ammo left. */
      if ((w->u.ammo.outfit == NULL) || (w->u.ammo.quantity <= 0))
         return 0;

      /* enough energy? */
      if (outfit_energy(w->u.ammo.outfit)*energy_mod > p->energy)
         return 0;

      energy      = outfit_energy(w->u.ammo.outfit)*energy_mod;
      p->energy  -= energy;
      pilot_heatAddSlot( p, w );
      weapon_add( w->outfit, w->heat_T, p->solid->dir,
            &vp, &p->solid->vel, p, p->target );

      w->u.ammo.quantity -= 1; /* we just shot it */
      p->mass_outfit     -= w->u.ammo.outfit->mass;
      pilot_updateMass( p );
   }

   /*
    * Fighter bays.
    */
   else if (outfit_isFighterBay(w->outfit)) {

      /* Must have ammo left. */
      if ((w->u.ammo.outfit == NULL) || (w->u.ammo.quantity <= 0))
         return 0;

      /* Create the escort. */
      escort_create( p, w->u.ammo.outfit->u.fig.ship,
            &vp, &p->solid->vel, p->solid->dir, ESCORT_TYPE_BAY, 1 );

      w->u.ammo.quantity -= 1; /* we just shot it */
      p->mass_outfit     -= w->u.ammo.outfit->mass;
      w->u.ammo.deployed += 1; /* Mark as deployed. */
      pilot_updateMass( p );
   }
   else
      WARN("Shooting unknown weapon type: %s", w->outfit->name);


   /* Reset timer. */
   w->timer += rate_mod * outfit_delay( w->outfit );

   return 1;
}
예제 #26
0
파일: pilot_weapon.c 프로젝트: nenau/naev
/**
 * @brief Calculates and shoots the appropriate weapons in a weapon set matching an outfit.
 */
static int pilot_shootWeaponSetOutfit( Pilot* p, PilotWeaponSet *ws, Outfit *o, int level, double time )
{
   int i, ret;
   int is_launcher, is_bay;
   double rate_mod, energy_mod;
   PilotOutfitSlot *w;
   int maxp, minh;
   double q, maxt;

   /* Store number of shots. */
   ret = 0;

   /** @TODO Make beams not fire all at once. */
   if (outfit_isBeam(o)) {
      for (i=0; i<array_size(ws->slots); i++)
         if (ws->slots[i].slot->outfit == o)
            ret += pilot_shootWeapon( p, ws->slots[i].slot, 0 );
      return ret;
   }

   /* Stores if it is a launcher. */
   is_launcher = outfit_isLauncher(o);

   is_bay = outfit_isFighterBay(o);

   /* Calculate rate modifier. */
   pilot_getRateMod( &rate_mod, &energy_mod, p, o );

   /* Find optimal outfit, coolest that can fire. */
   minh  = -1;
   maxt  = 0.;
   maxp  = -1;
   q     = 0.;
   for (i=0; i<array_size(ws->slots); i++) {
      /* Only matching outfits. */
      if (ws->slots[i].slot->outfit != o)
         continue;

      /* Only match levels. */
      if ((level != -1) && (ws->slots[i].level != level))
         continue;

      /* Simplicity. */
      w = ws->slots[i].slot;

      /* Launcher only counts with ammo. */
      if ((is_launcher || is_bay) && ((w->u.ammo.outfit == NULL) || (w->u.ammo.quantity <= 0)))
         continue;

      /* Get coolest that can fire. */
      if (w->timer <= 0.) {
         if (is_launcher) {
            if ((minh < 0) || (ws->slots[minh].slot->u.ammo.quantity < w->u.ammo.quantity))
               minh = i;
         }
         else {
            if ((minh < 0) || (ws->slots[minh].slot->heat_T > w->heat_T))
               minh = i;
         }
      }

      /* Save some stuff. */
      if ((maxp < 0) || (w->timer > maxt)) {
         maxp = i;
         maxt = w->timer;
      }
      q += 1.;
   }

   /* No weapon can fire. */
   if (minh < 0)
      return 0;

   /* Only fire if the last weapon to fire fired more than (q-1)/q ago. */
   if (maxt > rate_mod * outfit_delay(o) * ((q-1.) / q))
      return 0;

   /* Shoot the weapon. */
   ret += pilot_shootWeapon( p, ws->slots[minh].slot, time );

   return ret;
}
예제 #27
0
파일: outfit.c 프로젝트: pegue/naev
/**
 * @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;
}