Beispiel #1
0
/**
 * @brief Player attempts to buy a ship.
 *    @param wid Window player is buying ship from.
 *    @param str Unused.
 */
static void shipyard_buy( unsigned int wid, char* str )
{
   (void)str;
   char *shipname, buf[ECON_CRED_STRLEN];
   Ship* ship;

   shipname = toolkit_getImageArray( wid, "iarShipyard" );
   if (strcmp(shipname, "None") == 0)
      return;

   ship = ship_get( shipname );

   credits_t targetprice = ship_buyPrice(ship);

   if (land_errDialogue( shipname, "buyShip" ))
      return;

   credits2str( buf, targetprice, 2 );
   if (dialogue_YesNo("Are you sure?", /* confirm */
         "Do you really want to spend %s on a new ship?", buf )==0)
      return;

   /* player just got a new ship */
   if (player_newShip( ship, NULL, 0, 0 ) == NULL) {
      /* Player actually aborted naming process. */
      return;
   }
   player_modCredits( -targetprice ); /* ouch, paying is hard */

   /* Update shipyard. */
   shipyard_update(wid, NULL);
}
Beispiel #2
0
/**
 * @brief Makes sure it's sane to buy a ship, trading the old one in simultaneously.
 *    @param shipname Ship being bought.
 */
int shipyard_canTrade( char* shipname )
{
   int failure = 0;
   Ship* ship;
   ship = ship_get( shipname );
   credits_t price;

   price = ship_buyPrice( ship );

   /* Must have the necessary license, enough credits, and be able to swap ships. */
   if (!player_hasLicense(ship->license)) {
      land_errDialogueBuild( "You lack the %s.", ship->license );
      failure = 1;
   }
   if (!player_hasCredits( price - player_shipPrice(player.p->name))) {
      credits_t creditdifference = price - (player_shipPrice(player.p->name) + player.p->credits);
      char buf[ECON_CRED_STRLEN];
      credits2str( buf, creditdifference, 2 );
      land_errDialogueBuild( "You need %s more credits.", buf);
      failure = 1;
   }
   if (!can_swap( shipname ))
      failure = 1;
   return !failure;
}
Beispiel #3
0
/**
 * @brief Creates an escort.
 *
 *    @param p Parent of the escort (who he's guarding).
 *    @param ship Name of the ship escort should have.
 *    @param pos Position to create escort at.
 *    @param vel Velocity to create escort with.
 *    @param dir Direction to face.
 *    @param type Type of escort.
 *    @param add Whether or not to add it to the escort list.
 *    @return The ID of the escort on success.
 */
unsigned int escort_create( Pilot *p, char *ship,
      Vector2d *pos, Vector2d *vel, double dir,
      EscortType_t type, int add )
{
   Ship *s;
   Pilot *pe;
   unsigned int e;
   PilotFlags f;
   unsigned int parent;

   /* Get important stuff. */
   parent = p->id;
   s = ship_get(ship);

   /* Set flags. */
   pilot_clearFlagsRaw( f );
   pilot_setFlagRaw( f, PILOT_NOJUMP );
   if (type == ESCORT_TYPE_BAY)
      pilot_setFlagRaw( f, PILOT_CARRIED );

   /* Create the pilot. */
   e = pilot_create( s, NULL, p->faction, "escort", dir, pos, vel, f );
   pe = pilot_get(e);
   pe->parent = parent;

   /* Add to escort list. */
   if (add != 0)
      escort_addList( p, ship, type, e, 1 );

   return e;
}
Beispiel #4
0
/**
 * @brief Player attempts to buy a ship, trading the current ship in.
 *    @param wid Window player is buying ship from.
 *    @param str Unused.
 */
static void shipyard_trade( unsigned int wid, char* str )
{
   (void)str;
   char *shipname, buf[ECON_CRED_STRLEN], buf2[ECON_CRED_STRLEN],
         buf3[ECON_CRED_STRLEN], buf4[ECON_CRED_STRLEN];
   Ship* ship;

   shipname = toolkit_getImageArray( wid, "iarShipyard" );
   if (strcmp(shipname, "None") == 0)
      return;

   ship = ship_get( shipname );

   credits_t targetprice = ship_buyPrice(ship);
   credits_t playerprice = player_shipPrice(player.p->name);

   if (land_errDialogue( shipname, "tradeShip" ))
      return;

   credits2str( buf, targetprice, 2 );
   credits2str( buf2, playerprice, 2 );
   credits2str( buf3, targetprice - playerprice, 2 );
   credits2str( buf4, playerprice - targetprice, 2 );

   /* Display the correct dialogue depending on the new ship's price versus the player's. */
   if ( targetprice == playerprice ) {
      if (dialogue_YesNo("Are you sure?", /* confirm */
         "Your %s is worth %s, exactly as much as the new ship, so no credits need be exchanged. Are you sure you want to trade your ship in?",
               player.p->ship->name, buf2)==0)
         return;
   }
   else if ( targetprice < playerprice ) {
      if (dialogue_YesNo("Are you sure?", /* confirm */
         "Your %s is worth %s credits, more than the new ship. For your ship, you will get the new %s and %s credits. Are you sure you want to trade your ship in?",
               player.p->ship->name, buf2, ship->name, buf4)==0)
         return;
   }
   else if ( targetprice > playerprice ) {
      if (dialogue_YesNo("Are you sure?", /* confirm */
         "Your %s is worth %s, so the new ship will cost %s credits. Are you sure you want to trade your ship in?",
               player.p->ship->name, buf2, buf3)==0)
         return;
   }

   /* player just got a new ship */
   if (player_newShip( ship, NULL, 1, 0 ) == NULL)
      return; /* Player aborted the naming process. */

   player_modCredits( playerprice - targetprice ); /* Modify credits by the difference between ship values. */

   land_refuel();

   /* The newShip call will trigger a loadGUI that will recreate the land windows. Therefore the land ID will
    * be void. We must reload in in order to properly update it again.*/
   wid = land_getWid(LAND_WINDOW_SHIPYARD);

   /* Update shipyard. */
   shipyard_update(wid, NULL);
}
Beispiel #5
0
/**
 * @brief Player attempts to buy a ship, trading the current ship in.
 *    @param wid Window player is buying ship from.
 *    @param str Unused.
 */
static void shipyard_trade( unsigned int wid, char* str )
{
    (void)str;
    char *shipname, buf[ECON_CRED_STRLEN], buf2[ECON_CRED_STRLEN],
         buf3[ECON_CRED_STRLEN], buf4[ECON_CRED_STRLEN];
    Ship* ship;

    shipname = toolkit_getImageArray( wid, "iarShipyard" );
    ship = ship_get( shipname );

    credits_t targetprice = ship->price;
    credits_t playerprice = player_shipPrice(player.p->name);

    if (land_errDialogue( shipname, "trade" ))
        return;

    credits2str( buf, targetprice, 2 );
    credits2str( buf2, playerprice, 2 );
    credits2str( buf3, targetprice - playerprice, 2 );
    credits2str( buf4, playerprice - targetprice, 2 );

    /* Display the correct dialogue depending on the new ship's price versus the player's. */
    if ( targetprice == playerprice ) {
        if (dialogue_YesNo("Are you sure?", /* confirm */
                           "Your %s is worth %s, exactly as much as the new ship, so no credits need be exchanged. Are you sure you want to trade your ship in?",
                           player.p->ship->name, buf2)==0)
            return;
    }
    else if ( targetprice < playerprice ) {
        if (dialogue_YesNo("Are you sure?", /* confirm */
                           "Your %s is worth %s credits, more than the new ship. For your ship, you will get the new %s and %s credits. Are you sure you want to trade your ship in?",
                           player.p->ship->name, buf2, ship->name, buf4)==0)
            return;
    }
    else if ( targetprice > playerprice ) {
        if (dialogue_YesNo("Are you sure?", /* confirm */
                           "Your %s is worth %s, so the new ship will cost %s credits. Are you sure you want to trade your ship in?",
                           player.p->ship->name, buf2, buf3)==0)
            return;
    }

    /* player just got a new ship */
    if (player_newShip( ship, NULL, 1, 0 ) == NULL)
        return; /* Player aborted the naming process. */

    player_modCredits( playerprice - targetprice ); /* Modify credits by the difference between ship values. */

    land_checkAddRefuel();

    /* Update shipyard. */
    shipyard_update(wid, NULL);
}
Beispiel #6
0
/**
 * @brief Makes sure it's sane to change ships.
 *    @param shipname Ship being changed to.
 */
int can_swap( char* shipname )
{
   int failure = 0;
   Ship* ship;
   ship = ship_get( shipname );

   if (pilot_cargoUsed(player.p) > ship->cap_cargo) { /* Current ship has too much cargo. */
      land_errDialogueBuild( "You have %g tons more cargo than the new ship can hold.",
            pilot_cargoUsed(player.p) - ship->cap_cargo, ship->name );
      failure = 1;
   }
   if (pilot_hasDeployed(player.p)) { /* Escorts are in space. */
      land_errDialogueBuild( "You can't strand your fighters in space.");
      failure = 1;
   }
   return !failure;
}
Beispiel #7
0
/**
 * @brief Makes sure it's sane to buy a ship.
 *    @param shipname Ship being bought.
 */
int shipyard_canBuy ( char *shipname )
{
    Ship* ship;
    ship = ship_get( shipname );
    int failure = 0;

    /* Must have enough credits and the necessary license. */
    if (!player_hasLicense(ship->license)) {
        land_errDialogueBuild( "You lack the %s.", ship->license );
        failure = 1;
    }
    if (!player_hasCredits( ship->price )) {
        char buf[ECON_CRED_STRLEN];
        credits2str( buf, ship->price - player.p->credits, 2 );
        land_errDialogueBuild( "You need %s more credits.", buf);
        failure = 1;
    }
    return !failure;
}
Beispiel #8
0
/**
 * @brief Gives the player a new ship.
 *
 * @note Should be given when landed, ideally on a planet with a shipyard.
 *
 * @usage player.addShip( "Pirate Kestrel", "Seiryuu" ) -- Gives the player a Pirate Kestrel named Seiryuu if player cancels the naming.
 *
 *    @luaparam ship Name of the ship to add.
 *    @luaparam name Name to give the ship if player refuses to name it.
 * @luafunc addShip( ship, name )
 */
static int playerL_addShip( lua_State *L )
{
   const char *str, *name;
   Ship *s;

   /* Handle parameters. */
   str  = luaL_checkstring(L, 1);
   name = luaL_checkstring(L, 2);

   /* Get ship. */
   s = ship_get(str);
   if (s==NULL) {
      NLUA_ERROR(L, "Ship '%s' not found.", str);
      return 0;
   }

   /* Add the ship. */
   player_newShip( s, 0., 0, 0., 0., 0., name );
   return 0;
}
Beispiel #9
0
/**
 * @brief Makes sure it's sane to buy a ship.
 *    @param shipname Ship being bought.
 */
int shipyard_canBuy ( char *shipname, Planet *planet )
{
   Ship* ship;
   ship = ship_get( shipname );
   int failure = 0;
   credits_t price;

   price = ship_buyPrice(ship);

   /* Must have enough credits and the necessary license. */
   if ((!player_hasLicense(ship->license)) &&
         ((planet == NULL) || (!planet_isBlackMarket(planet)))) {
      land_errDialogueBuild( "You lack the %s.", ship->license );
      failure = 1;
   }
   if (!player_hasCredits( price )) {
      char buf[ECON_CRED_STRLEN];
      credits2str( buf, price - player.p->credits, 2 );
      land_errDialogueBuild( "You need %s more credits.", buf);
      failure = 1;
   }
   return !failure;
}
Beispiel #10
0
/**
 * @brief Creates an escort.
 *
 *    @param parent Parent of the escort (who he's guarding).
 *    @param ship Name of the ship escort should have.
 *    @param pos Position to create escort at.
 *    @param vel Velocity to create escort with.
 *    @param carried Does escort come out of the parent?
 */
int escort_create( unsigned int parent, char *ship,
      Vector2d *pos, Vector2d *vel, int carried )
{
   Ship *s;
   Pilot *p, *pe;
   char buf[16];
   unsigned int e, f;
   double dir;

   /* Get important stuff. */
   p = pilot_get(parent);
   s = ship_get(ship);
   snprintf(buf, 16, "escort*%u", parent);

   /* Set flags. */
   f = PILOT_ESCORT;
   if (carried) f |= PILOT_CARRIED;

   /* Get the direction. */
   if (carried) dir = p->solid->dir;
   else dir = 0.;

   /* Create the pilot. */
   e = pilot_create( s, NULL, p->faction, buf, dir, pos, vel, f );
   pe = pilot_get(e);
   pe->parent = parent;

   /* Add to escort list. */
   p->nescorts++;
   if (p->nescorts == 1)
      p->escorts = malloc(sizeof(unsigned int) * ESCORT_PREALLOC);
   else if (p->nescorts > ESCORT_PREALLOC)
      p->escorts = realloc( p->escorts, sizeof(unsigned int) * p->nescorts );
   p->escorts[p->nescorts-1] = e;

   return 0;
}
Beispiel #11
0
/**
 * @brief Helper function for playerL_addShip.
 */
static Pilot* playerL_newShip( lua_State *L )
{
   const char *str, *name, *pntname;
   Ship *s;
   Pilot *new_ship;
   Planet *pnt, *t;
   int noname;

   /* Defaults. */
   t = NULL;

   /* Handle parameters. */
   str  = luaL_checkstring(L, 1);
   if (lua_gettop(L) > 1)
      name = luaL_checkstring(L,2);
   else
      name = str;
   if (lua_gettop(L) > 2)
      pntname = luaL_checkstring (L,3);
   else
      pntname = NULL;
   noname = lua_toboolean(L,4);

   /* Get planet. */
   if (pntname != NULL) {
      pnt = planet_get( pntname );
      if (pnt == NULL) {
         NLUA_ERROR(L, "Planet '%s' not found!", pntname);
         return 0;
      }
      /* Horrible hack to swap variables. */
      t = land_planet;
      land_planet = pnt;
   }
   else
      pnt = NULL;

   /* Must be landed if pnt is NULL. */
   if ((pnt == NULL) && (land_planet==NULL)) {
      NLUA_ERROR(L, "Player must be landed to add a ship without location parameter.");
      return 0;
   }

   /* Get ship. */
   s = ship_get(str);
   if (s==NULL) {
      NLUA_ERROR(L, "Ship '%s' not found.", str);
      return 0;
   }

   /* Add the ship, look in case it's cancelled. */
   do {
      new_ship = player_newShip( s, name, 0, noname );
   } while (new_ship == NULL);

   /* Undo the horrible hack. */
   if (t != NULL)
      land_planet = t;

   return new_ship;
}
Beispiel #12
0
/**
 * @brief Updates the ships in the shipyard window.
 *    @param wid Window to update the ships in.
 *    @param str Unused.
 */
void shipyard_update( unsigned int wid, char* str )
{
   (void)str;
   char *shipname, *license_text;
   Ship* ship;
   char buf[PATH_MAX], buf2[ECON_CRED_STRLEN], buf3[ECON_CRED_STRLEN];
   size_t len;

   shipname = toolkit_getImageArray( wid, "iarShipyard" );

   /* No ships */
   if (strcmp(shipname,"None")==0) {
      window_modifyImage( wid, "imgTarget", NULL, 0, 0 );
      window_disableButton( wid, "btnBuyShip");
      window_disableButton( wid, "btnTradeShip");
      nsnprintf( buf, PATH_MAX,
            "None\n"
            "NA\n"
            "NA\n"
            "NA\n"
            "\n"
            "NA\n"
            "NA\n"
            "NA\n"
            "NA\n"
            "NA\n"
            "\n"
            "NA\n"
            "NA\n"
            "NA\n"
            "NA\n"
            "NA\n"
            "NA\n"
            "NA\n"
            "NA\n"
            "NA\n"
            "NA\n" );
      window_modifyImage( wid, "imgTarget", NULL, 0, 0 );
      window_modifyText( wid, "txtStats", NULL );
      window_modifyText( wid, "txtDescription", NULL );
      window_modifyText( wid, "txtDDesc", buf );
      return;
   }

   ship = ship_get( shipname );
   shipyard_selected = ship;

   /* update image */
   window_modifyImage( wid, "imgTarget", ship->gfx_store, 0, 0 );

   /* update text */
   window_modifyText( wid, "txtStats", ship->desc_stats );
   window_modifyText( wid, "txtDescription", ship->description );
   price2str( buf2, ship_buyPrice(ship), player.p->credits, 2 );
   credits2str( buf3, player.p->credits, 2 );

   /* Remove the word " License".  It's redundant and makes the text overflow
      into another text box */
   license_text = ship->license;
   if (license_text) {
      len = strlen(ship->license);
      if (strcmp(" License", ship->license + len - 8) == 0) {
         license_text = malloc(len - 7);
         assert(license_text);
         memcpy(license_text, ship->license, len - 8);
         license_text[len - 8] = '\0';
      }
   }
   nsnprintf( buf, PATH_MAX,
         "%s\n"
         "%s\n"
         "%s\n"
         "%d\n"
         "\n"
         "%.0f teraflops\n"
         "%.0f tons\n"
         "%.0f kN/ton\n"
         "%.0f m/s\n"
         "%.0f deg/s\n"
         "\n"
         "%.0f%% damage\n"
         "%.0f MJ (%.1f MW)\n"
         "%.0f MJ (%.1f MW)\n"
         "%.0f MJ (%.1f MW)\n"
         "%.0f tons\n"
         "%d units\n"
         "%.0f units\n"
         "%s credits\n"
         "%s credits\n"
         "%s\n",
         ship->name,
         ship_class(ship),
         ship->fabricator,
         ship->crew,
         /* Weapons & Manoeuvrability */
         ship->cpu,
         ship->mass,
         ship->thrust,
         ship->speed,
         ship->turn*180/M_PI,
         /* Misc */
         ship->dmg_absorb*100.,
         ship->shield, ship->shield_regen,
         ship->armour, ship->armour_regen,
         ship->energy, ship->energy_regen,
         ship->cap_cargo,
         ship->fuel,
         ship->fuel_consumption,
         buf2,
         buf3,
         (license_text != NULL) ? license_text : "None" );
   window_modifyText( wid,  "txtDDesc", buf );

   if (license_text != ship->license)
      free(license_text);

   if (!shipyard_canBuy( shipname, land_planet ))
      window_disableButtonSoft( wid, "btnBuyShip");
   else
      window_enableButton( wid, "btnBuyShip");

   if (!shipyard_canTrade( shipname ))
      window_disableButtonSoft( wid, "btnTradeShip");
   else
      window_enableButton( wid, "btnTradeShip");
}
Beispiel #13
0
/**
 * @brief Unpersists Lua data.
 *
 *    @param L State to unperisist data into.
 *    @param parent Node containing all the Lua persisted data.
 *    @return 0 on success.
 */
static int nxml_unpersistDataNode( lua_State *L, xmlNodePtr parent )
{
   LuaPlanet p;
   LuaSystem s;
   LuaFaction f;
   LuaShip sh;
   LuaTime lt;
   Planet *pnt;
   StarSystem *ss;
   xmlNodePtr node;
   char *name, *type, *buf, *num;
   int keynum;

   node = parent->xmlChildrenNode;
   do {
      if (xml_isNode(node,"data")) {
         /* Get general info. */
         xmlr_attr(node,"name",name);
         xmlr_attr(node,"type",type);
         /* Check to see if key is a number. */
         xmlr_attr(node,"keynum",num);
         if (num != NULL) {
            keynum = 1;
            lua_pushnumber(L, atof(name));
            free(num);
         }
         else
            lua_pushstring(L, name);

         /* handle data types */
         /* Recursive tables. */
         if (strcmp(type,"table")==0) {
            xmlr_attr(node,"name",buf);
            /* Create new table. */
            lua_newtable(L);
            /* Save data. */
            nxml_unpersistDataNode(L,node);
            /* Set table. */
            free(buf);
         }
         else if (strcmp(type,"number")==0)
            lua_pushnumber(L,xml_getFloat(node));
         else if (strcmp(type,"bool")==0)
            lua_pushboolean(L,xml_getInt(node));
         else if (strcmp(type,"string")==0)
            lua_pushstring(L,xml_get(node));
         else if (strcmp(type,"planet")==0) {
            pnt = planet_get(xml_get(node));
            if (pnt != NULL) {
               p.id = planet_index(pnt);
               lua_pushplanet(L,p);
            }
            else
               WARN("Failed to load unexistent planet '%s'", xml_get(node));
         }
         else if (strcmp(type,"system")==0) {
            ss = system_get(xml_get(node));
            if (ss != NULL) {
               s.id = system_index( ss );
               lua_pushsystem(L,s);
            }
            else
               WARN("Failed to load unexistent system '%s'", xml_get(node));
         }
         else if (strcmp(type,"faction")==0) {
            f.f = faction_get(xml_get(node));
            lua_pushfaction(L,f);
         }
         else if (strcmp(type,"ship")==0) {
            sh.ship = ship_get(xml_get(node));
            lua_pushship(L,sh);
         }
         else if (strcmp(type,"time")==0) {
            lt.t = xml_getLong(node);
            lua_pushtime(L,lt);
         }
         else {
            WARN("Unknown lua data type!");
            lua_pop(L,1);
            return -1;
         }

         /* Set field. */
         lua_settable(L, -3);

         /* cleanup */
         free(type);
         free(name);
      }
   } while (xml_nextNode(node));

   return 0;
}
Beispiel #14
0
/**
 * @brief Parses the fleet node.
 *
 *    @param temp Fleet to load.
 *    @param parent Parent xml node of the fleet in question.
 *    @return A newly allocated fleet loaded with data in parent node.
 */
static int fleet_parse( Fleet *temp, const xmlNodePtr parent )
{
   xmlNodePtr cur, node;
   FleetPilot* pilot;
   char* c;
   int mem;
   node = parent->xmlChildrenNode;

   /* Sane defaults and clean up. */
   memset( temp, 0, sizeof(Fleet) );
   temp->faction = -1;

   temp->name = (char*)xmlGetProp(parent,(xmlChar*)"name"); /* already mallocs */
   if (temp->name == NULL)
      WARN("Fleet in "FLEET_DATA" has invalid or no name");

   do { /* load all the data */
      xml_onlyNodes(node);

      /* Set faction. */
      if (xml_isNode(node,"faction")) {
         temp->faction = faction_get(xml_get(node));
         continue;
      }

      /* Set AI. */
      xmlr_strd(node,"ai",temp->ai);
      if (ai_getProfile ( temp->ai ) == NULL)
         WARN("Fleet '%s' has invalid AI '%s'.", temp->name, temp->ai );

      /* Set flags. */
      if (xml_isNode(node,"flags")){
         cur = node->children;
         do {
            xml_onlyNodes(cur);
            WARN("Fleet '%s' has unknown flag node '%s'.", temp->name, cur->name);
         } while (xml_nextNode(cur));
         continue;
      }

      /* Load pilots. */
      else if (xml_isNode(node,"pilots")) {
         cur = node->children;
         mem = 0;
         do {
            xml_onlyNodes(cur);

            if (xml_isNode(cur,"pilot")) {

               /* See if must grow. */
               temp->npilots++;
               if (temp->npilots > mem) {
                  mem += CHUNK_SIZE;
                  temp->pilots = realloc(temp->pilots, mem * sizeof(FleetPilot));
               }
               pilot = &temp->pilots[temp->npilots-1];

               /* Clear memory. */
               memset( pilot, 0, sizeof(FleetPilot) );

               /* Check for name override */
               xmlr_attr(cur,"name",c);
               pilot->name = c; /* No need to free since it will have to later */

               /* Check for AI override */
               xmlr_attr(cur,"ai",pilot->ai);

               /* Load pilot's ship */
               xmlr_attr(cur,"ship",c);
               if (c==NULL)
                  WARN("Pilot %s in Fleet %s has null ship", pilot->name, temp->name);
               pilot->ship = ship_get(c);
               if (pilot->ship == NULL)
                  WARN("Pilot %s in Fleet %s has invalid ship", pilot->name, temp->name);
               if (c!=NULL)
                  free(c);
               continue;
            }

            WARN("Fleet '%s' has unknown pilot node '%s'.", temp->name, cur->name);
         } while (xml_nextNode(cur));

         /* Resize to minimum. */
         temp->pilots = realloc(temp->pilots, sizeof(FleetPilot)*temp->npilots);
         continue;
      }

      DEBUG("Unknown node '%s' in fleet '%s'",node->name,temp->name);
   } while (xml_nextNode(node));

#define MELEMENT(o,s) \
if (o) WARN("Fleet '%s' missing '"s"' element", temp->name)
/**< Hack to check for missing fields. */
   MELEMENT(temp->ai==NULL,"ai");
   MELEMENT(temp->faction==-1,"faction");
   MELEMENT(temp->pilots==NULL,"pilots");
#undef MELEMENT

   return 0;
}
Beispiel #15
0
/**
 * @brief Updates the ships in the shipyard window.
 *    @param wid Window to update the ships in.
 *    @param str Unused.
 */
void shipyard_update( unsigned int wid, char* str )
{
    (void)str;
    char *shipname;
    Ship* ship;
    char buf[PATH_MAX], buf2[ECON_CRED_STRLEN], buf3[ECON_CRED_STRLEN];

    shipname = toolkit_getImageArray( wid, "iarShipyard" );

    /* No ships */
    if (strcmp(shipname,"None")==0) {
        window_modifyImage( wid, "imgTarget", NULL, 0, 0 );
        window_disableButton( wid, "btnBuyShip");
        window_disableButton( wid, "btnTradeShip");
        snprintf( buf, PATH_MAX,
                  "None\n"
                  "NA\n"
                  "NA\n"
                  "NA\n"
                  "\n"
                  "NA\n"
                  "NA\n"
                  "NA\n"
                  "NA\n"
                  "NA\n"
                  "NA\n"
                  "\n"
                  "NA\n"
                  "NA\n"
                  "NA\n"
                  "NA\n"
                  "NA\n"
                  "NA\n"
                  "NA\n"
                  "NA\n"
                  "NA\n" );
        window_modifyImage( wid, "imgTarget", NULL, 0, 0 );
        window_modifyText( wid, "txtStats", NULL );
        window_modifyText( wid, "txtDescription", NULL );
        window_modifyText( wid, "txtDDesc", buf );
        return;
    }

    ship = ship_get( shipname );
    shipyard_selected = ship;

    /* update image */
    window_modifyImage( wid, "imgTarget", ship->gfx_store, 0, 0 );

    /* update text */
    window_modifyText( wid, "txtStats", ship->desc_stats );
    window_modifyText( wid, "txtDescription", ship->description );
    credits2str( buf2, ship->price, 2 );
    credits2str( buf3, player.p->credits, 2 );
    snprintf( buf, PATH_MAX,
              "%s\n"
              "%s\n"
              "%s\n"
              "%d\n"
              "\n"
              "%.0f teraflops\n"
              "%.0f tons\n"
              "%.1f STU average\n"
              "%.0f kN/ton\n"
              "%.0f m/s\n"
              "%.0f deg/s\n"
              "\n"
              "%.0f%% damage\n"
              "%.0f MJ (%.1f MW)\n"
              "%.0f MJ (%.1f MW)\n"
              "%.0f MJ (%.1f MW)\n"
              "%.0f tons\n"
              "%d units\n"
              "%s credits\n"
              "%s credits\n"
              "%s\n",
              ship->name,
              ship_class(ship),
              ship->fabricator,
              ship->crew,
              /* Weapons & Manoeuvrability */
              ship->cpu,
              ship->mass,
              pow( ship->mass, 1./2.5 ) / 5. * (ship->stats_array.jump_delay/100.+1.), /**< @todo make this more portable. */
              ship->thrust / ship->mass,
              ship->speed,
              ship->turn*180/M_PI,
              /* Misc */
              ship->dmg_absorb*100.,
              ship->shield, ship->shield_regen,
              ship->armour, ship->armour_regen,
              ship->energy, ship->energy_regen,
              ship->cap_cargo,
              ship->fuel,
              buf2,
              buf3,
              (ship->license != NULL) ? ship->license : "None" );
    window_modifyText( wid,  "txtDDesc", buf );

    if (!shipyard_canBuy( shipname ))
        window_disableButton( wid, "btnBuyShip");
    else
        window_enableButton( wid, "btnBuyShip");

    if (!shipyard_canTrade( shipname ))
        window_disableButton( wid, "btnTradeShip");
    else
        window_enableButton( wid, "btnTradeShip");
}