Exemplo n.º 1
0
/**
 * @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;
}
Exemplo n.º 2
0
/**
 * @brief Updates the shake position.
 */
static void spfx_updateShake( double dt )
{
   double mod, vmod, angle;
   double force_x, force_y;
   int forced;

   /* Must still be on. */
   if (shake_off)
      return;

   /* The shake decays over time */
   forced = 0;
   if (shake_force_mod > 0.) {
      shake_force_mod -= SHAKE_DECAY*dt;
      if (shake_force_mod < 0.)
         shake_force_mod   = 0.;
      else
         forced            = 1;
   }

   /* See if it's settled down. */
   mod      = VMOD( shake_pos );
   vmod     = VMOD( shake_vel );
   if (!forced && (mod < 0.01) && (vmod < 0.01)) {
      shake_off      = 1;
      if (shake_force_ang > 1e3)
         shake_force_ang = RNGF();
      return;
   }

   /* Calculate force. */
   force_x  = -SHAKE_K*shake_pos.x + -SHAKE_B*shake_vel.x;
   force_y  = -SHAKE_K*shake_pos.y + -SHAKE_B*shake_vel.y;

   /* Apply force if necessary. */
   if (forced) {
      shake_force_ang  += dt;
      angle             = noise_simplex1( shake_noise, &shake_force_ang ) * 5.*M_PI;
      force_x          += shake_force_mod * cos(angle);
      force_y          += shake_force_mod * sin(angle);
   }


   /* Update velocity. */
   vect_cadd( &shake_vel, (1./SHAKE_MASS) * force_x * dt, (1./SHAKE_MASS) * force_y * dt );

   /* Update position. */
   vect_cadd( &shake_pos, shake_vel.x * dt, shake_vel.y * dt );
}
Exemplo n.º 3
0
/**
 * @brief Updates the camera zoom.
 */
static void cam_updatePilotZoom( Pilot *follow, Pilot *target, double dt )
{
   double d, x,y, z,tz, dx, dy;
   double zfar, znear;
   double c;

   /* Must have auto zoom enabled. */
   if (conf.zoom_manual)
      return;

   /* Minimum depends on velocity normally.
    *
    * w*h = A, cte    area constant
    * w/h = K, cte    proportion constant
    * d^2 = A, cte    geometric longitud
    *
    * A_v = A*(1+v/d)   area of view is based on speed
    * A_v / A = (1 + v/d)
    *
    * z = A / A_v = 1. / (1 + v/d)
    */
   d     = sqrt(SCREEN_W*SCREEN_H);
   znear = MIN( conf.zoom_near, 1. / (0.8 + VMOD(follow->solid->vel)/d) );

   /* Maximum is limited by nebulae. */
   if (cur_system->nebu_density > 0.) {
      c     = MIN( SCREEN_W, SCREEN_H ) / 2;
      zfar  = CLAMP( conf.zoom_far, conf.zoom_near, c / nebu_getSightRadius() );
   }
   else
      zfar = conf.zoom_far;
   znear = MAX( znear, zfar );

   /*
    * Set Zoom to pilot target.
    */
   z = cam_getZoom();
   if (target != NULL) {
      /* Get current relative target position. */
      gui_getOffset( &x, &y );
      x += target->solid->pos.x - follow->solid->pos.x;
      y += target->solid->pos.y - follow->solid->pos.y;

      /* Get distance ratio. */
      dx = (SCREEN_W/2.) / (FABS(x) + 2*target->ship->gfx_space->sw);
      dy = (SCREEN_H/2.) / (FABS(y) + 2*target->ship->gfx_space->sh);

      /* Get zoom. */
      tz = MIN( dx, dy );
   }
   else
      tz = znear; /* Aim at in. */

   /* Gradually zoom in/out. */
   d  = CLAMP(-conf.zoom_speed, conf.zoom_speed, tz - z);
   d *= dt / dt_mod; /* Remove dt dependence. */
   if (d < 0) /** Speed up if needed. */
      d *= 2.;
   camera_Z =  CLAMP( zfar, znear, z + d);
}
Exemplo n.º 4
0
/**
 * @brief Gets the modulus of the vector.
 *    @luaparam v Vector to get modulus of.
 *    @luareturn The modulus of the vector.
 * @luafunc mod(v)
 */
static int vectorL_mod( lua_State *L )
{
    LuaVector *v;

    v = luaL_checkvector(L,1);
    lua_pushnumber(L, VMOD(v->vec));
    return 1;
}
Exemplo n.º 5
0
/**
 * @brief Gets the modulus of the vector.
 *    @luaparam v Vector to get modulus of.
 *    @luareturn The modulus of the vector.
 * @luafunc mod(v)
 */
static int vectorL_mod( lua_State *L )
{
   Vector2d *v;

   v = luaL_checkvector(L,1);
   lua_pushnumber(L, VMOD(*v));
   return 1;
}
Exemplo n.º 6
0
Arquivo: spfx.c Projeto: zid/naev
/**
 * @brief Prepares the rendering for the special effects.
 *
 * Should be called at the beginning of the rendering loop.
 *
 *    @param dt Current delta tick.
 */
void spfx_begin( const double dt )
{
   GLdouble bx, by, x, y;
   double inc;

   /* Save cycles. */
   if (shake_off == 1)
      return;

#if SDL_VERSION_ATLEAST(1,3,0)
   /* Decrement the haptic timer. */
   if (haptic_lastUpdate > 0.)
      haptic_lastUpdate -= dt;
#endif /* SDL_VERSION_ATLEAST(1,3,0) */

   /* set defaults */
   bx = SCREEN_W/2;
   by = SCREEN_H/2;

   if (!paused) {
      inc = dt*100000.;

      /* calculate new position */
      if (shake_rad > 0.01) {
         vect_cadd( &shake_pos, shake_vel.x * inc, shake_vel.y * inc );

         if (VMOD(shake_pos) > shake_rad) { /* change direction */
            vect_pset( &shake_pos, shake_rad, VANGLE(shake_pos) );
            vect_pset( &shake_vel, SHAKE_VEL_MOD*shake_rad, 
                  -VANGLE(shake_pos) + (RNGF()-0.5) * M_PI );
         }

         /* the shake decays over time */
         shake_rad -= SHAKE_DECAY*dt;
         if (shake_rad < 0.)
            shake_rad = 0.;

         x = shake_pos.x;
         y = shake_pos.y;  
      }
      else {
         shake_rad = 0.;
         shake_off = 1;
         x = 0.;
         y = 0.;
      }
   }
   else {
      x = 0.;
      y = 0.;
   }

   /* set the new viewport */
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho( -bx+x, bx+x, -by+y, by+y, -1., 1. );
}
Exemplo n.º 7
0
/**
 * @brief Updates the pilot's dynamic electronic warfare properties.
 *
 *    @param p Pilot to update.
 */
void pilot_ewUpdateDynamic( Pilot *p )
{
   /* Update hide. */
   p->ew_heat     = pilot_ewHeat( p->heat_T );
   p->ew_hide     = p->ew_base_hide * p->ew_mass * p->ew_heat;

   /* Update evasion. */
   p->ew_movement = pilot_ewMovement( VMOD(p->solid->vel) );
   p->ew_evasion  = p->ew_hide * EVASION_SCALE;
}
Exemplo n.º 8
0
/**
 * @brief Gets polar coordinates of a vector.
 *
 * The angle is in degrees, not radians.
 *
 * @usage modulus, angle = my_vec:polar()
 *
 *    @luaparam v Vector to get polar coordinates of.
 *    @luareturn The modulus and angle of the vector.
 * @luafunc polar(v)
 */
static int vectorL_polar( lua_State *L )
{
    LuaVector *v1;

    /* Get self. */
    v1 = luaL_checkvector(L,1);

    lua_pushnumber(L, VMOD(v1->vec));
    lua_pushnumber(L, VANGLE(v1->vec)*180./M_PI);
    return 2;
}
Exemplo n.º 9
0
/**
 * @brief Gets polar coordinates of a vector.
 *
 * The angle is in degrees, not radians.
 *
 * @usage modulus, angle = my_vec:polar()
 *
 *    @luaparam v Vector to get polar coordinates of.
 *    @luareturn The modulus and angle of the vector.
 * @luafunc polar(v)
 */
static int vectorL_polar( lua_State *L )
{
   Vector2d *v1;

   /* Get self. */
   v1 = luaL_checkvector(L,1);

   lua_pushnumber(L, VMOD(*v1));
   lua_pushnumber(L, VANGLE(*v1)*180./M_PI);
   return 2;
}
Exemplo n.º 10
0
/**
 * @brief Handles approaching a position with autonav.
 *
 *    @param[in] pos Position to go to.
 *    @param[out] dist2 Square distance left to target.
 *    @param count_target If 1 it subtracts the braking distance from dist2. Otherwise it returns the full distance.
 *    @return 1 on completion.
 */
static int player_autonavApproach( const Vector2d *pos, double *dist2, int count_target )
{
   double d, t, vel, dist;

   /* Only accelerate if facing move dir. */
   d = pilot_face( player.p, vect_angle( &player.p->solid->pos, pos ) );
   if (FABS(d) < MIN_DIR_ERR) {
      if (player_acc < 1.)
         player_accel( 1. );
   }
   else if (player_acc > 0.)
      player_accelOver();

   /* Get current time to reach target. */
   t  = MIN( 1.5*player.p->speed, VMOD(player.p->solid->vel) ) /
      (player.p->thrust / player.p->solid->mass);

   /* Get velocity. */
   vel   = MIN( player.p->speed, VMOD(player.p->solid->vel) );

   /* Get distance. */
   dist  = vel*(t+1.1*M_PI/player.p->turn) -
      0.5*(player.p->thrust/player.p->solid->mass)*t*t;

   /* Output distance^2 */
   d        = vect_dist( pos, &player.p->solid->pos );
   dist     = d - dist;
   if (count_target)
      *dist2   = dist;
   else
      *dist2   = d;

   /* See if should start braking. */
   if (dist < 0.) {
      player_accelOver();
      return 1;
   }
   return 0;
}
Exemplo n.º 11
0
/**
 * @brief Handles common time accel ramp-down for autonav to positions and planets.
 */
static void player_autonavRampdown( double d )
{
   double t, tint;
   double vel;

   vel   = MIN( 1.5*player.p->speed, VMOD(player.p->solid->vel) );
   t     = d / vel * (1. - 0.075 * tc_base);
   tint  = 3. + 0.5*(3.*(tc_mod-tc_base));
   if (t < tint) {
      tc_rampdown = 1;
      tc_down     = (tc_mod-tc_base) / 3.;
   }
}
Exemplo n.º 12
0
/**
 * @brief Renders the starry background.
 *
 *    @param dt Current delta tick.
 */
void background_renderStars( const double dt )
{
   (void) dt;
   unsigned int i;
   GLfloat hh, hw, h, w;
   GLfloat x, y, m, b;
   GLfloat brightness;
   double z;
   double sx, sy;
   int shade_mode;
   int j, n;


   /*
    * gprof claims it's the slowest thing in the game!
    */

   /* Do some scaling for now. */
   z = cam_getZoom();
   z = 1. * (1. - conf.zoom_stars) + z * conf.zoom_stars;
   gl_matrixPush();
      gl_matrixTranslate( SCREEN_W/2., SCREEN_H/2. );
      gl_matrixScale( z, z );

   if (!paused && (player.p != NULL) && !player_isFlag(PLAYER_DESTROYED) &&
         !player_isFlag(PLAYER_CREATING)) { /* update position */

      /* Calculate some dimensions. */
      w  = (SCREEN_W + 2.*STAR_BUF);
      w += conf.zoom_stars * (w / conf.zoom_far - 1.);
      h  = (SCREEN_H + 2.*STAR_BUF);
      h += conf.zoom_stars * (h / conf.zoom_far - 1.);
      hw = w/2.;
      hh = h/2.;

      if ((star_x > SCREEN_W) || (star_y > SCREEN_H)) {
         sx = ceil( star_x / SCREEN_W );
         sy = ceil( star_y / SCREEN_H );
         n  = MAX( sx, sy );
         star_x /= (double)n;
         star_y /= (double)n;
      }
      else
         n = 1;

      /* Calculate new star positions. */
      for (j=0; j < n; j++) {
         for (i=0; i < nstars; i++) {

            /* calculate new position */
            b = 1./(9. - 10.*star_colour[8*i+3]);
            star_vertex[4*i+0] = star_vertex[4*i+0] + star_x*b;
            star_vertex[4*i+1] = star_vertex[4*i+1] + star_y*b;

            /* check boundaries */
            if (star_vertex[4*i+0] > hw)
               star_vertex[4*i+0] -= w;
            else if (star_vertex[4*i+0] < -hw)
               star_vertex[4*i+0] += w;
            if (star_vertex[4*i+1] > hh)
               star_vertex[4*i+1] -= h;
            else if (star_vertex[4*i+1] < -hh)
               star_vertex[4*i+1] += h;
         }
      }

      /* Upload the data. */
      gl_vboSubData( star_vertexVBO, 0, nstars * 4 * sizeof(GLfloat), star_vertex );
   }

   /* Decide on shade mode. */
   shade_mode = 0;
   if ((player.p != NULL) && !player_isFlag(PLAYER_DESTROYED) &&
         !player_isFlag(PLAYER_CREATING)) {

      if (pilot_isFlag(player.p,PILOT_HYPERSPACE) && /* hyperspace fancy effects */
            (player.p->ptimer < HYPERSPACE_STARS_BLUR)) {

         glShadeModel(GL_SMOOTH);
         shade_mode = 1;

         /* lines will be based on velocity */
         m  = HYPERSPACE_STARS_BLUR-player.p->ptimer;
         m /= HYPERSPACE_STARS_BLUR;
         m *= HYPERSPACE_STARS_LENGTH;
         x = m*cos(VANGLE(player.p->solid->vel));
         y = m*sin(VANGLE(player.p->solid->vel));
      }
      else if (dt_mod > 3.) {

         glShadeModel(GL_SMOOTH);
         shade_mode = 1;

         /* lines will be based on velocity */
         m = (dt_mod-3.)*VMOD(player.p->solid->vel)/10.;
         x = m*cos(VANGLE(player.p->solid->vel));
         y = m*sin(VANGLE(player.p->solid->vel));
      }

      if (shade_mode) {
         /* Generate lines. */
         for (i=0; i < nstars; i++) {
            brightness = star_colour[8*i+3];
            star_vertex[4*i+2] = star_vertex[4*i+0] + x*brightness;
            star_vertex[4*i+3] = star_vertex[4*i+1] + y*brightness;
         }

         /* Upload new data. */
         gl_vboSubData( star_vertexVBO, 0, nstars * 4 * sizeof(GLfloat), star_vertex );
      }
   }

   /* Render. */
   gl_vboActivate( star_vertexVBO, GL_VERTEX_ARRAY, 2, GL_FLOAT, 2 * sizeof(GLfloat) );
   gl_vboActivate( star_colourVBO, GL_COLOR_ARRAY,  4, GL_FLOAT, 4 * sizeof(GLfloat) );
   if (shade_mode) {
      glDrawArrays( GL_LINES, 0, nstars );
      glDrawArrays( GL_POINTS, 0, nstars ); /* This second pass is when the lines are very short that they "lose" intensity. */
      glShadeModel(GL_FLAT);
   }
   else {
      glDrawArrays( GL_POINTS, 0, nstars );
   }

   /* Clear star movement. */
   star_x = 0.;
   star_y = 0.;

   /* Disable vertex array. */
   gl_vboDeactivate();

   /* Pop matrix. */
   gl_matrixPop();

   /* Check for errors. */
   gl_checkErr();
}
Exemplo n.º 13
0
Arquivo: weapon.c Projeto: zid/naev
/**
 * @brief The AI of seeker missiles.
 *
 *    @param w Weapon to do the thinking.
 *    @param dt Current delta tick.
 */
static void think_seeker( Weapon* w, const double dt )
{
   double diff;
   double vel;
   Pilot *p;
   int effect;
   Vector2d v;
   double t;

   if (w->target == w->parent) return; /* no self shooting */

   p = pilot_get(w->target); /* no null pilot_nstack */
   if (p==NULL) {
      weapon_setThrust( w, 0. );
      weapon_setTurn( w, 0. );
      return;
   }

   /* Handle by status. */
   switch (w->status) {
      case WEAPON_STATUS_OK:
         if (w->lockon < 0.)
            w->status = WEAPON_STATUS_LOCKEDON;
         break;

      case WEAPON_STATUS_LOCKEDON: /* Check to see if can get jammed */
         if ((p->jam_range != 0.) &&  /* Target has jammer and weapon is in range */
               (vect_dist(&w->solid->pos,&p->solid->pos) < p->jam_range)) {

            /* Check to see if weapon gets jammed */
            if (RNGF() < p->jam_chance - w->outfit->u.amm.resist) {
               w->status = WEAPON_STATUS_JAMMED;
               /* Give it a nice random effect */
               effect = RNG(0,3);
               switch (effect) {
                  case 0: /* Stuck in left loop */
                     weapon_setTurn( w, w->outfit->u.amm.turn );
                     break;
                  case 1: /* Stuck in right loop */
                     weapon_setTurn( w, -w->outfit->u.amm.turn );
                     break;

                  default: /* Blow up. */
                     w->timer = -1.;
                     break;
               }
            }
            else /* Can't get jammed anymore */
               w->status = WEAPON_STATUS_UNJAMMED;
         }

      /* Purpose fallthrough */
      case WEAPON_STATUS_UNJAMMED: /* Work as expected */

         /* Smart seekers take into account ship velocity. */
         if (w->outfit->u.amm.ai == 2) {

            /* Calculate time to reach target. */
            vect_cset( &v, p->solid->pos.x - w->solid->pos.x,
                  p->solid->pos.y - w->solid->pos.y );
            t = vect_odist( &v ) / w->outfit->u.amm.speed;

            /* Calculate target's movement. */
            vect_cset( &v, v.x + t*(p->solid->vel.x - w->solid->vel.x),
                  v.y + t*(p->solid->vel.y - w->solid->vel.y) );

            /* Get the angle now. */
            diff = angle_diff(w->solid->dir, VANGLE(v) );
         }
         /* Other seekers are stupid. */
         else {
            diff = angle_diff(w->solid->dir, /* Get angle to target pos */
                  vect_angle(&w->solid->pos, &p->solid->pos));
         }

         /* Set turn. */
         weapon_setTurn( w, CLAMP( -w->outfit->u.amm.turn, w->outfit->u.amm.turn,
                  10 * diff * w->outfit->u.amm.turn ));
         break;

      case WEAPON_STATUS_JAMMED: /* Continue doing whatever */
         /* Do nothing, dir_vel should be set already if needed */
         break;

      default:
         WARN("Unknown weapon status for '%s'", w->outfit->name);
         break;
   }

   /* Limit speed here */
   vel = MIN(w->outfit->u.amm.speed, VMOD(w->solid->vel) + w->outfit->u.amm.thrust*dt);
   vect_pset( &w->solid->vel, vel, w->solid->dir );
   /*limit_speed( &w->solid->vel, w->outfit->u.amm.speed, dt );*/
}
Exemplo n.º 14
0
Arquivo: weapon.c Projeto: 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;
}
Exemplo n.º 15
0
/**
 * @brief Handles the autonavigation process for the player.
 */
static void player_autonav (void)
{
   JumpPoint *jp;
   int ret;
   double d, t, tint;
   double vel;

   switch (player.autonav) {
      case AUTONAV_JUMP_APPROACH:
         /* Target jump. */
         jp    = &cur_system->jumps[ player.p->nav_hyperspace ];
         ret   = player_autonavApproach( &jp->pos, &d, 0 );
         if (ret)
            player.autonav = AUTONAV_JUMP_BRAKE;
         else if (!tc_rampdown && (map_npath<=1)) {
            vel   = MIN( 1.5*player.p->speed, VMOD(player.p->solid->vel) );
            t     = d / vel * (1.2 - .1 * tc_base);
            /* tint is the integral of the time in per time units.
             *
             * tc_mod
             *    ^
             *    |
             *    |\
             *    | \
             *    |  \___
             *    |
             *    +------> time
             *    0   3
             *
             * We decompose integral in a rectangle (3*1) and a triangle (3*(tc_mod-1.))/2.
             *  This is the "elapsed time" when linearly decreasing the tc_mod. Which we can
             *  use to calculate the actual "game time" that'll pass when decreasing the
             *  tc_mod to 1 during 3 seconds. This can be used then to compare when we want to
             *  start decrementing.
             */
            tint  = 3. + 0.5*(3.*(tc_mod-tc_base));
            if (t < tint) {
               tc_rampdown = 1;
               tc_down     = (tc_mod-tc_base) / 3.;
            }
         }
         break;

      case AUTONAV_JUMP_BRAKE:
         /* Target jump. */
         jp    = &cur_system->jumps[ player.p->nav_hyperspace ];
         if (player.p->stats.misc_instant_jump) {
            ret = pilot_interceptPos( player.p, jp->pos.x, jp->pos.y );
            if (!ret && space_canHyperspace(player.p))
               ret = 1;
            player_acc = player.p->solid->thrust / player.p->thrust;
         }
         else
            ret = player_autonavBrake();

         /* Try to jump or see if braked. */
         if (ret) {
            if (space_canHyperspace(player.p))
               player_jump();
            player.autonav = AUTONAV_JUMP_APPROACH;
         }

         /* See if should ramp down. */
         if (!tc_rampdown && (map_npath<=1)) {
            tc_rampdown = 1;
            tc_down     = (tc_mod-tc_base) / 3.;
         }
         break;

      case AUTONAV_POS_APPROACH:
         ret = player_autonavApproach( &player.autonav_pos, &d, 1 );
         if (ret) {
            player_message( _("\apAutonav arrived at position.") );
            player_autonavEnd();
         }
         else if (!tc_rampdown)
            player_autonavRampdown(d);
         break;
      case AUTONAV_PNT_APPROACH:
         ret = player_autonavApproach( &player.autonav_pos, &d, 1 );
         if (ret) {
            player_message( _("\apAutonav arrived at \a%c%s\a\0."),
                  planet_getColourChar( planet_get(player.autonavmsg) ),
                  player.autonavmsg );
            player_autonavEnd();
         }
         else if (!tc_rampdown)
            player_autonavRampdown(d);
         break;
   }
}