Ejemplo n.º 1
0
Archivo: weapon.c Proyecto: 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];
}
Ejemplo n.º 2
0
/**
 * @brief Deactivates the afterburner.
 */
void pilot_afterburnOver (Pilot *p)
{
   if (p == NULL)
      return;
   if (p->afterburner == NULL)
      return;

   if (p->afterburner->state == PILOT_OUTFIT_ON) {
      p->afterburner->state  = PILOT_OUTFIT_OFF;
      pilot_rmFlag(p,PILOT_AFTERBURNER);
      pilot_calcStats( p );

      /* @todo Make this part of a more dynamic activated outfit sound system. */
      sound_playPos(p->afterburner->outfit->u.afb.sound_off,
            p->solid->pos.x, p->solid->pos.y, p->solid->vel.x, p->solid->vel.y);
   }
}
Ejemplo n.º 3
0
Archivo: weapon.c Proyecto: zid/naev
/**
 * @brief Weapon hit the pilot.
 *
 *    @param w Weapon involved in the collision.
 *    @param p Pilot that got hit.
 *    @param layer Layer to which the weapon belongs.
 *    @param pos Position of the hit.
 */
static void weapon_hit( Weapon* w, Pilot* p, WeaponLayer layer, Vector2d* pos )
{
   Pilot *parent;
   int spfx;
   double damage;
   DamageType dtype;
   WeaponLayer spfx_layer;
   int s;

   /* Get general details. */
   parent = pilot_get(w->parent);
   damage = w->strength * outfit_damage(w->outfit);
   dtype  = outfit_damageType(w->outfit);

   /* Play sound if they have it. */
   s = outfit_soundHit(w->outfit);
   if (s != -1)
      w->voice = sound_playPos( s,
            w->solid->pos.x,
            w->solid->pos.y,
            w->solid->vel.x,
            w->solid->vel.y);

   /* Have pilot take damage and get real damage done. */
   damage = pilot_hit( p, w->solid, w->parent, dtype, damage );

   /* Get the layer. */
   spfx_layer = (p==player) ? SPFX_LAYER_FRONT : SPFX_LAYER_BACK;
   /* Choose spfx. */
   if (p->shield > 0.)
      spfx = outfit_spfxShield(w->outfit);
   else
      spfx = outfit_spfxArmour(w->outfit);
   /* Add sprite, layer depends on whether player shot or not. */
   spfx_add( spfx, pos->x, pos->y,
         VX(p->solid->vel), VY(p->solid->vel), spfx_layer );

   /* Inform AI that it's been hit. */
   weapon_hitAI( p, parent, damage );

   /* no need for the weapon particle anymore */
   weapon_destroy(w,layer);
}
Ejemplo n.º 4
0
/**
 * @brief Activate the afterburner.
 */
void pilot_afterburn (Pilot *p)
{
   double afb_mod;

   if (p == NULL)
      return;

   if (pilot_isFlag(p, PILOT_HYP_PREP) || pilot_isFlag(p, PILOT_HYPERSPACE) ||
         pilot_isFlag(p, PILOT_LANDING) || pilot_isFlag(p, PILOT_TAKEOFF) ||
         pilot_isDisabled(p) || pilot_isFlag(p, PILOT_COOLDOWN))
      return;

   /* Not under manual control if is player. */
   if (pilot_isFlag( p, PILOT_MANUAL_CONTROL ) && pilot_isFlag( p, PILOT_PLAYER ))
      return;

   /** @todo fancy effect? */
   if (p->afterburner == NULL)
      return;

   /* The afterburner only works if its efficiency is high enough. */
   if (pilot_heatEfficiencyMod( p->afterburner->heat_T,
         p->afterburner->outfit->u.afb.heat_base,
         p->afterburner->outfit->u.afb.heat_cap ) < 0.3)
      return;

   if (p->afterburner->state == PILOT_OUTFIT_OFF) {
      p->afterburner->state  = PILOT_OUTFIT_ON;
      p->afterburner->stimer = outfit_duration( p->afterburner->outfit );
      pilot_setFlag(p,PILOT_AFTERBURNER);
      pilot_calcStats( p );

      /* @todo Make this part of a more dynamic activated outfit sound system. */
      sound_playPos(p->afterburner->outfit->u.afb.sound_on,
            p->solid->pos.x, p->solid->pos.y, p->solid->vel.x, p->solid->vel.y);
   }

   if (pilot_isPlayer(p)) {
      afb_mod = MIN( 1., player.p->afterburner->outfit->u.afb.mass_limit / player.p->solid->mass );
      spfx_shake( afb_mod * player.p->afterburner->outfit->u.afb.rumble * SHAKE_MAX );
   }
}
Ejemplo n.º 5
0
Archivo: weapon.c Proyecto: zid/naev
/**
 * @brief Updates all the weapons in the layer.
 *
 *    @param dt Current delta tick.
 *    @param layer Layer to update.
 */
static void weapons_updateLayer( const double dt, const WeaponLayer layer )
{
   Weapon **wlayer;
   int *nlayer;
   Weapon *w;
   int i;
   int spfx;
   int s;

   /* Choose layer. */
   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!");
   }

   i = 0;
   while (i < *nlayer) {
      w = wlayer[i];
      switch (w->outfit->type) {

         /* most missiles behave the same */
         case OUTFIT_TYPE_AMMO:
         case OUTFIT_TYPE_TURRET_AMMO:
            if (w->lockon > 0.) /* decrement lockon */
               w->lockon -= dt;

            limit_speed( &w->solid->vel, w->outfit->u.amm.speed, dt );
            w->timer -= dt;
            if (w->timer < 0.) {
               spfx = -1;
               /* See if we need armour death sprite. */
               if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_BLOWUP_ARMOUR))
                  spfx = outfit_spfxArmour(w->outfit);
               /* See if we need shield death sprite. */
               else if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_BLOWUP_SHIELD))
                  spfx = outfit_spfxShield(w->outfit);
               /* Add death sprite if needed. */
               if (spfx != -1) {
                  spfx_add( spfx, w->solid->pos.x, w->solid->pos.y,
                        w->solid->vel.x, w->solid->vel.y,
                        SPFX_LAYER_BACK ); /* presume back. */
                  /* Add sound if explodes and has it. */
                  s = outfit_soundHit(w->outfit);
                  if (s != -1)
                     w->voice = sound_playPos(s,
                           w->solid->pos.x,
                           w->solid->pos.y,
                           w->solid->vel.x,
                           w->solid->vel.y);
               }
               weapon_destroy(w,layer);
               break;
            }
            break;

         case OUTFIT_TYPE_BOLT:
         case OUTFIT_TYPE_TURRET_BOLT:
            w->timer -= dt;
            if (w->timer < 0.) {
               spfx = -1;
               /* See if we need armour death sprite. */
               if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_BLOWUP_ARMOUR))
                  spfx = outfit_spfxArmour(w->outfit);
               /* See if we need shield death sprite. */
               else if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_BLOWUP_SHIELD))
                  spfx = outfit_spfxShield(w->outfit);
               /* Add death sprite if needed. */
               if (spfx != -1) {
                  spfx_add( spfx, w->solid->pos.x, w->solid->pos.y,
                        w->solid->vel.x, w->solid->vel.y,
                        SPFX_LAYER_BACK ); /* presume back. */
                  /* Add sound if explodes and has it. */
                  s = outfit_soundHit(w->outfit);
                  if (s != -1)
                     w->voice = sound_playPos(s,
                           w->solid->pos.x,
                           w->solid->pos.y,
                           w->solid->vel.x,
                           w->solid->vel.y);
               }
               weapon_destroy(w,layer);
               break;
            }
            else if (w->timer < w->falloff)
               w->strength = w->timer / w->falloff;
            break;

         /* Beam weapons handled a part. */
         case OUTFIT_TYPE_BEAM:
         case OUTFIT_TYPE_TURRET_BEAM:
            w->timer -= dt;
            if (w->timer < 0.) {
               weapon_destroy(w,layer);
               break;
            }
            /* We use the lockon to tell when we have to create explosions. */
            w->lockon -= dt;
            if (w->lockon < 0.) {
               if (w->lockon < -1.)
                  w->lockon = 0.100;
               else
                  w->lockon = -1.;
            }
            break;
         default:
            WARN("Weapon of type '%s' has no update implemented yet!",
                  w->outfit->name);
            break;
      }

      /* Out of bounds, loop is over. */
      if (i >= *nlayer)
         break;

      /* Only increment if weapon wasn't deleted. */
      if (w == wlayer[i]) {
         weapon_update(w,dt,layer);
         if ((i < *nlayer) && (w == wlayer[i]))
            i++;
      }
   }
}
Ejemplo n.º 6
0
Archivo: weapon.c Proyecto: zid/naev
/**
 * @brief Creates a new weapon.
 *
 *    @param outfit Outfit which spawned the weapon.
 *    @param dir Direction the shooter is facing.
 *    @param pos Position of the shooter.
 *    @param vel Velocity of the shooter.
 *    @param parent Shooter ID.
 *    @param target Target ID of the shooter.
 *    @return A pointer to the newly created weapon.
 */
static Weapon* weapon_create( const Outfit* outfit,
      const double dir, const Vector2d* pos, const Vector2d* vel,
      const unsigned int parent, const unsigned int target )
{
   Vector2d v;
   double mass, rdir;
   Pilot *pilot_target;
   double x,y, t, dist;
   Weapon* w;

   /* Create basic features */
   w = malloc(sizeof(Weapon));
   memset(w, 0, sizeof(Weapon));
   w->faction = pilot_get(parent)->faction; /* non-changeable */
   w->parent = parent; /* non-changeable */
   w->target = target; /* non-changeable */
   w->outfit = outfit; /* non-changeable */
   w->update = weapon_update;
   w->status = WEAPON_STATUS_OK;
   w->strength = 1.;

   switch (outfit->type) {

      /* Bolts treated together */
      case OUTFIT_TYPE_BOLT:
      case OUTFIT_TYPE_TURRET_BOLT:
         /* Only difference is the direction of fire */
         if ((outfit->type == OUTFIT_TYPE_TURRET_BOLT) && (w->parent!=w->target) &&
               (w->target != 0)) { /* Must have valid target */

            pilot_target = pilot_get(w->target);
            if (pilot_target == NULL)
               rdir = dir;

            else {
               /* Get the distance */
               dist = vect_dist( pos, &pilot_target->solid->pos );

               /* Aim. */
               if (dist > outfit->u.blt.range*1.2) {
                  x = pilot_target->solid->pos.x - pos->x;
                  y = pilot_target->solid->pos.y - pos->y;
               }
               else {
                  /* Try to predict where the enemy will be. */
                  /* Time for shots to reach that distance */
                  t = dist / (w->outfit->u.blt.speed + VMOD(*vel));

                  /* Position is calculated on where it should be */
                  x = (pilot_target->solid->pos.x + pilot_target->solid->vel.x*t)
                     - (pos->x + vel->x*t);
                  y = (pilot_target->solid->pos.y + pilot_target->solid->vel.y*t)
                     - (pos->y + vel->y*t);
               }

               /* Set angle to face. */
               rdir = ANGLE(x, y);
            }
         }
         else /* fire straight */
            rdir = dir;

         rdir += RNG_2SIGMA() * outfit->u.blt.accuracy/2. * 1./180.*M_PI;
         if (rdir < 0.)
            rdir += 2.*M_PI;
         else if (rdir >= 2.*M_PI)
            rdir -= 2.*M_PI;

         mass = 1; /* Lasers are presumed to have unitary mass */
         vectcpy( &v, vel );
         vect_cadd( &v, outfit->u.blt.speed*cos(rdir), outfit->u.blt.speed*sin(rdir));
         w->timer = outfit->u.blt.range / outfit->u.blt.speed;
         w->falloff = w->timer - outfit->u.blt.falloff / outfit->u.blt.speed;
         w->solid = solid_create( mass, rdir, pos, &v );
         w->voice = sound_playPos( w->outfit->u.blt.sound,
               w->solid->pos.x,
               w->solid->pos.y,
               w->solid->vel.x,
               w->solid->vel.y);
         break;

      /* Beam weapons are treated together. */
      case OUTFIT_TYPE_BEAM:
      case OUTFIT_TYPE_TURRET_BEAM:
         if ((outfit->type == OUTFIT_TYPE_TURRET_BEAM) && (w->parent!=w->target)) {
            pilot_target = pilot_get(target);
            rdir = (pilot_target == NULL) ? dir :
                  vect_angle(pos, &pilot_target->solid->pos);
         }
         else
            rdir = dir;
         if (rdir < 0.)
            rdir += 2.*M_PI;
         else if (rdir >= 2.*M_PI)
            rdir -= 2.*M_PI;
         mass = 1.; /**< Needs a mass. */
         w->solid = solid_create( mass, rdir, pos, NULL );
         w->think = think_beam;
         w->timer = outfit->u.bem.duration;
         w->voice = sound_playPos( w->outfit->u.bem.sound,
               w->solid->pos.x,
               w->solid->pos.y,
               w->solid->vel.x,
               w->solid->vel.y);
         break;

      /* Treat seekers together. */
      case OUTFIT_TYPE_AMMO:
      case OUTFIT_TYPE_TURRET_AMMO:
         if (w->outfit->type == OUTFIT_TYPE_TURRET_AMMO) {
            pilot_target = pilot_get(w->target);
            if (pilot_target == NULL)
               rdir = dir;

            else {
               /* Get the distance */
               dist = vect_dist( pos, &pilot_target->solid->pos );

               /* Aim. */
               /* Try to predict where the enemy will be. */
               /* Time for shots to reach that distance */
               if (outfit->u.amm.thrust == 0.)
                  t = dist / (w->outfit->u.amm.speed + VMOD(*vel));
               else
                  t = dist / w->outfit->u.amm.speed;

               /* Position is calculated on where it should be */
               x = (pilot_target->solid->pos.x + pilot_target->solid->vel.x*t)
                  - (pos->x + vel->x*t);
               y = (pilot_target->solid->pos.y + pilot_target->solid->vel.y*t)
                  - (pos->y + vel->y*t);

               /* Set angle to face. */
               rdir = ANGLE(x, y);
            }
         }
         else {
            rdir = dir;
         }
         if (outfit->u.amm.accuracy != 0.) {
            rdir += RNG_2SIGMA() * outfit->u.amm.accuracy/2. * 1./180.*M_PI;
            if ((rdir > 2.*M_PI) || (rdir < 0.))
               rdir = fmod(rdir, 2.*M_PI);
         }
         if (rdir < 0.)
            rdir += 2.*M_PI;
         else if (rdir >= 2.*M_PI)
            rdir -= 2.*M_PI;

         /* If thrust is 0. we assume it starts out at speed. */
         vectcpy( &v, vel );
         if (outfit->u.amm.thrust == 0.)
            vect_cadd( &v, cos(rdir) * w->outfit->u.amm.speed,
                  sin(rdir) * w->outfit->u.amm.speed );

         /* Set up ammo details. */
         mass        = w->outfit->mass;
         w->lockon   = outfit->u.amm.lockon;
         w->timer    = outfit->u.amm.duration;
         w->solid    = solid_create( mass, rdir, pos, &v );
         if (w->outfit->u.amm.thrust != 0.)
            weapon_setThrust( w, w->outfit->u.amm.thrust * mass );

         /* Handle seekers. */
         if (w->outfit->u.amm.ai > 0) {
            w->think = think_seeker; /* AI is the same atm. */

            /* If they are seeking a pilot, increment lockon counter. */
            pilot_target = pilot_get(target);
            if (pilot_target != NULL)
               pilot_target->lockons++;
         }

         /* Play sound. */
         w->voice    = sound_playPos(w->outfit->u.amm.sound,
               w->solid->pos.x,
               w->solid->pos.y,
               w->solid->vel.x,
               w->solid->vel.y);
         break;

      /* just dump it where the player is */
      default:
         WARN("Weapon of type '%s' has no create implemented yet!",
               w->outfit->name);
         w->solid = solid_create( 1., dir, pos, vel );
         break;
   }

   /* Set life to timer. */
   w->life = w->timer;

   return w;
}