From 89fd3509e973724b76535bf8a8a62eb97d535a20 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Fri, 4 Oct 2013 01:34:05 +0100
Subject: [PATCH] [Add] OHHHHHH YEAAAAHHHHH!!! You can sell your ships now
 ladies!

---
 src/land.c   | 47 ++++++++++++++++++++++++++++++++++++++-
 src/outfit.c |  2 +-
 src/player.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/player.h | 14 +++++++-----
 src/ship.c   | 37 ++++++++++++++++++++++---------
 src/ship.h   |  1 +
 6 files changed, 145 insertions(+), 18 deletions(-)

diff --git a/src/land.c b/src/land.c
index de3436d..b184d98 100644
--- a/src/land.c
+++ b/src/land.c
@@ -103,6 +103,7 @@ static void shipyard_yours_open(char* str);
 static void shipyard_yours_close(char* str);
 static void shipyard_yoursUpdate(char* str);
 static void shipyard_yoursChange(char* str);
+static void shipyard_yoursSell(char* str);
 static void shipyard_yoursTransport(char* str);
 static int  shipyard_yoursTransportPrice(char* shipname);
 /* Spaceport bar. */
@@ -691,9 +692,11 @@ static void shipyard_yours_open(char* str) {
   char** ships;
   int nships;
 
+  /* Create window. */
   terciary_wid = window_create("Your Ships",
       -1, -1, SHIPYARD_WIDTH, SHIPYARD_HEIGHT);
 
+  /* Buttons. */
   window_addButton(terciary_wid, -20, 20,
                    BUTTON_WIDTH, BUTTON_HEIGHT, "btnCloseYourShips",
                    "Shipyard", shipyard_yours_close);
@@ -706,12 +709,18 @@ static void shipyard_yours_open(char* str) {
                    BUTTON_WIDTH, BUTTON_HEIGHT, "btnTransportShip",
                    "Transport Ship", shipyard_yoursTransport);
 
+  window_addButton(terciary_wid, -20, 40+BUTTON_HEIGHT,
+                    BUTTON_WIDTH, BUTTON_HEIGHT, "btnSellShip",
+                    "Sell Ship", shipyard_yoursSell);
+
+  /* Image. */
   window_addRect(terciary_wid, -40, -50,
                  128, 96, "rctTarget", &cBlack, 0);
 
   window_addImage(terciary_wid, -40-128, -50-96,
                   "imgTarget", NULL, 1);
 
+  /* Text. */
   window_addText(terciary_wid, 40+200+40, -55,
                  100, 96, 0, "txtSDesc", &gl_smallFont, &cDConsole,
                  "Name:\n"
@@ -736,6 +745,7 @@ static void shipyard_yours_open(char* str) {
                  SHIPYARD_WIDTH-40-200-40-20, 200, 0, "txtDOutfits",
                  &gl_smallFont, &cBlack, NULL);
 
+  /* Ship list. */
   ships = player_ships(&nships);
   window_addList(terciary_wid, 20, 40,
                  200, SHIPYARD_HEIGHT-80, "lstYourShips",
@@ -763,6 +773,7 @@ static void shipyard_yoursUpdate(char* str) {
     /* No ships. */
     window_disableButton(terciary_wid, "btnChangeShip");
     window_disableButton(terciary_wid, "btnTransportShip");
+    window_disableButton(terciary_wid, "btnSellShip");
     return;
   }
   ship = player_getShip(shipname);
@@ -774,8 +785,8 @@ static void shipyard_yoursUpdate(char* str) {
 
   /* Update text. */
   credits2str(buf2, price, 2); /* Transport. */
+  credits2str(buf3, player_shipPrice(shipname), 2); /* Sell price. */
 
-  credits2str(buf3, 0, 2); /* Sell price. */
   snprintf(buf, 256,
       "%s\n"
       "%s\n"
@@ -813,6 +824,8 @@ static void shipyard_yoursUpdate(char* str) {
     window_enableButton(terciary_wid, "btnChangeShip");
     window_disableButton(terciary_wid, "btnTransportShip");
   }
+  /* If ship is there you can always sell. */
+  window_enableButton(terciary_wid, "btnSellShip");
 }
 
 static void shipyard_yoursChange(char* str) {
@@ -847,6 +860,38 @@ static void shipyard_yoursChange(char* str) {
   shipyard_yours_open(NULL);
 }
 
+static void shipyard_yoursSell(char* str) {
+  (void)str;
+  char* shipname, buf[16];
+  int price;
+
+  shipname = toolkit_getList(terciary_wid, "lstYourShips");
+  if(strcmp(shipname, "None")==0) { /* No ships. */
+    dialogue_alert("You can't sell nothing!");
+    return;
+  }
+
+  /* Calculate price. */
+  price = player_shipPrice(shipname);
+  credits2str(buf, price, 2);
+
+  /* Check if player really wants to sell. */
+  if(!dialogue_YesNo("Sell Ship",
+        "Are you sure you wish to sell your ship %s for %s SCred?", shipname, buf)) {
+    return;
+  }
+
+  /* Sold. */
+  player->credits += price;
+  player_rmShip(shipname);
+  dialogue_msg("Ship Sold", "You have sold your ship %s for %s SCred.",
+      shipname, buf);
+
+  /* Recreate the window. */
+  shipyard_yours_close(NULL);
+  shipyard_yours_open(NULL);
+}
+
 static void shipyard_yoursTransport(char* str) {
   (void)str;
   int price;
diff --git a/src/outfit.c b/src/outfit.c
index 9b16f14..41cacba 100644
--- a/src/outfit.c
+++ b/src/outfit.c
@@ -887,7 +887,7 @@ int outfit_load(void) {
     if(xml_isNode(node,  XML_OUTFIT_TAG)) {
       tmp = outfit_parse(node);
       outfit_stack = realloc(outfit_stack, sizeof(Outfit)*(++outfit_nstack));
-      memcpy(outfit_stack+outfit_nstack-1, tmp, sizeof(Outfit));
+      memmove(outfit_stack+outfit_nstack-1, tmp, sizeof(Outfit));
       free(tmp);
     }
   } while((node = node->next));
diff --git a/src/player.c b/src/player.c
index 7eb426a..462914f 100644
--- a/src/player.c
+++ b/src/player.c
@@ -447,6 +447,68 @@ void player_swapShip(char* shipname) {
   WARN("Unable to swap player with ship '%s': Ship does not exist!", shipname);
 }
 
+/**
+ * @fn int player_shipPrice(char* shipname)
+ *
+ * @brief Calculate the price of one of the players ships.
+ *    @param shipname Name of the ship.
+ *    @return The price of the ship in credits.
+ */
+int player_shipPrice(char* shipname) {
+  int i;
+  int price;
+  Pilot* ship;
+
+  /* Find ship. */
+  for(i = 0; i < player_nstack; i++) {
+    if(strcmp(shipname, player_stack[i]->name)==0) {
+      ship = player_stack[i];
+
+      /* Ship price is base price + outfit prices. */
+      price = ship_basePrice(ship->ship);
+      for(i = 0; i < ship->noutfits; i++)
+        price += ship->outfits[i].quantity * ship->outfits[i].outfit->price;
+
+      return price;
+    }
+  }
+
+  WARN("Unable to find price for players ship '%s': ship does not exist!", shipname);
+  return -1;
+}
+
+/**
+ * @fn void player_rmShip(char* shipname)
+ *
+ * @brief Remove one of the players ships.
+ *    @param shipname Name of the ship to remove.
+ */
+void player_rmShip(char* shipname) {
+  int i;
+
+  for(i = 0; i < player_nstack; i++) {
+    if(strcmp(shipname, player_stack[i]->name)==0) {
+      /* Free player ship and location. */
+      pilot_free(player_stack[i]);
+      free(player_lstack[i]);
+
+      /* Move memory to make adjacent. */
+      memmove(player_stack+i, player_stack+i+1,
+          sizeof(Pilot*) * (player_nstack-i-1));
+      memmove(player_lstack+i, player_lstack+i+1,
+          sizeof(char*) * (player_nstack-i-1));
+
+      player_nstack--;  /* Shrink stack. */
+      
+      /* Realloc memory to smaller size. */
+      player_stack = realloc(player_stack,
+          sizeof(Pilot*) * (player_nstack));
+      player_lstack = realloc(player_lstack,
+          sizeof(char*) * (player_nstack));
+    }
+  }
+}
+
 /**
  * @brief void player_cleanup(void
  *
diff --git a/src/player.h b/src/player.h
index db48164..cad55cd 100644
--- a/src/player.h
+++ b/src/player.h
@@ -57,12 +57,14 @@ int player_cargoOwned(const char* commodityname);
 void player_rmMissionCargo(unsigned int cargo_id);
 
 /* Pilot ships. */
-char** player_ships(int* nships);
-int    player_nships(void);
-Pilot* player_getShip(char* shipname);
-char*  player_getLoc(char* shipname);
-void   player_setLoc(char* shipname, char* loc);
-void   player_swapShip(char* shipname);
+char**  player_ships(int* nships);
+int     player_nships(void);
+Pilot*  player_getShip(char* shipname);
+char*   player_getLoc(char* shipname);
+void    player_setLoc(char* shipname, char* loc);
+void    player_swapShip(char* shipname);
+int     player_shipPrice(char* shipname);
+void    player_rmShip(char* shipname);
 
 /* Player missions. */
 void player_missionFinished(int id);
diff --git a/src/ship.c b/src/ship.c
index 148bc8a..853a941 100644
--- a/src/ship.c
+++ b/src/ship.c
@@ -42,16 +42,6 @@ Ship* ship_get(const char* name) {
   return tmp+i;
 }
 
-/* Get the ship's classname. */
-static char* ship_classes[] = {
-  "NULL",
-  "Civialian Light", "Civilian Medium", "Civilian Heavy"
-  "Military Light", "Military Medium", "Military Heavy"
-  "Robotic Light", "Robotic Medium", "Robotic Heavy"
-  "Hybrid Light", "Hybrid Medium", "Hybrid Heavy"
-
-};
-
 /* Return all the ships in text form. */
 char** ship_getTech(int* n, const int* tech, const int techmax) {
   int i, j, k, num, price;
@@ -106,10 +96,37 @@ char** ship_getTech(int* n, const int* tech, const int techmax) {
   return shipnames;
 }
 
+/* Get the ship's classname. */
+static char* ship_classes[] = {
+  "NULL",
+  "Civialian Light", "Civilian Medium", "Civilian Heavy"
+  "Military Light", "Military Medium", "Military Heavy"
+  "Robotic Light", "Robotic Medium", "Robotic Heavy"
+  "Hybrid Light", "Hybrid Medium", "Hybrid Heavy"
+
+};
+
 char* ship_class(Ship* s) {
   return ship_classes[s->class];
 }
 
+/**
+ * @fn int ship_basePrice(Ship* s)
+ *
+ * @brief Get the ships base price (no outfits).
+ */
+int ship_basePrice(Ship* s) {
+  int price;
+  ShipOutfit* o;
+
+  /* Base price is ships price minus it's outfits. */
+  price = s->price;
+  for(o = s->outfit; o != NULL; o = o->next)
+    price -= o->quantity * o->data->price;
+
+  return price;
+}
+
 static Ship* ship_parse(xmlNodePtr parent) {
   xmlNodePtr cur, node;
   Ship* tmp = CALLOC_L(Ship);
diff --git a/src/ship.h b/src/ship.h
index f934c58..644af96 100644
--- a/src/ship.h
+++ b/src/ship.h
@@ -75,6 +75,7 @@ typedef struct Ship_ {
 Ship* ship_get(const char* name);
 char** ship_getTech(int* n, const int* tech, const int techmax);
 char* ship_class(Ship* p);
+int ship_basePrice(Ship* s);
 
 /* Load/quit. */
 int ships_load(void);