Galactic Bloodshed
scrap.cc
Go to the documentation of this file.
1 // Copyright 2014 The Galactic Bloodshed Authors. All rights reserved.
2 // Use of this source code is governed by a license that can be
3 // found in the COPYING file.
4 
5 /* scrap.c -- turn a ship to junk */
6 
7 #include "gb/commands/scrap.h"
8 
9 #include <cstdio>
10 #include <cstdlib>
11 
12 #include "gb/GB_server.h"
13 #include "gb/buffers.h"
14 #include "gb/files_shl.h"
15 #include "gb/fire.h"
16 #include "gb/land.h"
17 #include "gb/load.h"
18 #include "gb/races.h"
19 #include "gb/ships.h"
20 #include "gb/shlmisc.h"
21 #include "gb/vars.h"
22 
23 void scrap(const command_t &argv, GameObj &g) {
24  int APcount = 1;
25  Sector sect;
26  Ship *s;
27  shipnum_t shipno;
28  shipnum_t nextshipno;
29  int scrapval = 0;
30  int destval = 0;
31  int crewval = 0;
32  int xtalval = 0;
33  int troopval = 0;
34  double fuelval = 0.0;
35  racetype *Race;
36 
37  if (argv.size() < 2) {
38  g.out << "Scrap what?\n";
39  return;
40  }
41 
42  nextshipno = start_shiplist(g, argv[1]);
43 
44  while ((shipno = do_shiplist(&s, &nextshipno)))
45  if (in_list(g.player, argv[1], *s, &nextshipno) &&
46  authorized(g.governor, *s)) {
47  if (s->max_crew && !s->popn) {
48  notify(g.player, g.governor, "Can't scrap that ship - no crew.\n");
49  free(s);
50  continue;
51  }
52  if (s->whatorbits == ScopeLevel::LEVEL_UNIV) {
53  continue;
54  }
55  if (!enufAP(g.player, g.governor, Stars[s->storbits]->AP[g.player - 1],
56  APcount)) {
57  free(s);
58  continue;
59  }
60  if (s->whatorbits == ScopeLevel::LEVEL_PLAN &&
61  s->type == ShipType::OTYPE_TOXWC) {
62  sprintf(buf,
63  "WARNING: This will release %d toxin points back into the "
64  "atmosphere!!\n",
65  s->special.waste.toxic);
66  notify(g.player, g.governor, buf);
67  }
68  if (!s->docked) {
69  sprintf(buf,
70  "%s is not landed or docked.\nNo resources can be reclaimed.\n",
71  ship_to_string(*s).c_str());
72  notify(g.player, g.governor, buf);
73  }
74  if (s->whatorbits == ScopeLevel::LEVEL_PLAN) {
75  /* wc's release poison */
76  const auto planet = getplanet(s->storbits, s->pnumorbits);
77  if (landed(*s)) sect = getsector(planet, s->land_x, s->land_y);
78  }
79  std::optional<Ship> s2;
80  if (docked(s)) {
81  s2 = getship(s->destshipno);
82  if (!s2) {
83  continue;
84  }
85  // TODO(jeffbailey): Changed from !s->whatorbits, which didn't make any
86  // sense.
87  if (!(s2->docked && s2->destshipno == s->number) &&
88  s->whatorbits != ScopeLevel::LEVEL_SHIP) {
89  g.out << "Warning, other ship not docked..\n";
90  free(s);
91  continue;
92  }
93  }
94 
95  scrapval = shipcost(*s) / 2 + s->resource;
96 
97  if (s->docked) {
98  sprintf(buf, "%s: original cost: %ld\n", ship_to_string(*s).c_str(),
99  shipcost(*s));
100  notify(g.player, g.governor, buf);
101  sprintf(buf, " scrap value%s: %d rp's.\n",
102  s->resource ? "(with stockpile) " : "", scrapval);
103  notify(g.player, g.governor, buf);
104 
105  if (s->whatdest == ScopeLevel::LEVEL_SHIP &&
106  s2->resource + scrapval > max_resource(*s2) &&
107  s2->type != ShipType::STYPE_SHUTTLE) {
108  scrapval = max_resource(*s2) - s2->resource;
109  sprintf(buf, "(There is only room for %d resources.)\n", scrapval);
110  notify(g.player, g.governor, buf);
111  }
112  if (s->fuel) {
113  sprintf(buf, "Fuel recovery: %.0f.\n", s->fuel);
114  notify(g.player, g.governor, buf);
115  fuelval = s->fuel;
116  if (s->whatdest == ScopeLevel::LEVEL_SHIP &&
117  s2->fuel + fuelval > max_fuel(*s2)) {
118  fuelval = max_fuel(*s2) - s2->fuel;
119  sprintf(buf, "(There is only room for %.2f fuel.)\n", fuelval);
120  notify(g.player, g.governor, buf);
121  }
122  } else
123  fuelval = 0.0;
124 
125  if (s->destruct) {
126  sprintf(buf, "Weapons recovery: %d.\n", s->destruct);
127  notify(g.player, g.governor, buf);
128  destval = s->destruct;
129  if (s->whatdest == ScopeLevel::LEVEL_SHIP &&
130  s2->destruct + destval > max_destruct(*s2)) {
131  destval = max_destruct(*s2) - s2->destruct;
132  sprintf(buf, "(There is only room for %d destruct.)\n", destval);
133  notify(g.player, g.governor, buf);
134  }
135  } else
136  destval = 0;
137 
138  if (s->popn + s->troops) {
139  if (s->whatdest == ScopeLevel::LEVEL_PLAN && sect.owner > 0 &&
140  sect.owner != g.player) {
141  g.out << "You don't own this sector; no crew can be recovered.\n";
142  } else {
143  sprintf(buf, "Population/Troops recovery: %lu/%lu.\n", s->popn,
144  s->troops);
145  notify(g.player, g.governor, buf);
146  troopval = s->troops;
147  if (s->whatdest == ScopeLevel::LEVEL_SHIP &&
148  s2->troops + troopval > max_mil(*s2)) {
149  troopval = max_mil(*s2) - s2->troops;
150  sprintf(buf, "(There is only room for %d troops.)\n", troopval);
151  notify(g.player, g.governor, buf);
152  }
153  crewval = s->popn;
154  if (s->whatdest == ScopeLevel::LEVEL_SHIP &&
155  s2->popn + crewval > max_crew(*s2)) {
156  crewval = max_crew(*s2) - s2->popn;
157  sprintf(buf, "(There is only room for %d crew.)\n", crewval);
158  notify(g.player, g.governor, buf);
159  }
160  }
161  } else {
162  crewval = 0;
163  troopval = 0;
164  }
165 
166  if (s->crystals + s->mounted) {
167  if (s->whatdest == ScopeLevel::LEVEL_PLAN && sect.owner > 0 &&
168  sect.owner != g.player) {
169  g.out
170  << "You don't own this sector; no crystals can be recovered.\n";
171  } else {
172  xtalval = s->crystals + s->mounted;
173  if (s->whatdest == ScopeLevel::LEVEL_SHIP &&
174  s2->crystals + xtalval > max_crystals(*s2)) {
175  xtalval = max_crystals(*s2) - s2->crystals;
176  sprintf(buf, "(There is only room for %d crystals.)\n", xtalval);
177  notify(g.player, g.governor, buf);
178  }
179  sprintf(buf, "Crystal recovery: %d.\n", xtalval);
180  notify(g.player, g.governor, buf);
181  }
182  } else
183  xtalval = 0;
184  }
185 
186  /* more adjustments needed here for hanger. Maarten */
187  if (s->whatorbits == ScopeLevel::LEVEL_SHIP) s2->hanger -= s->size;
188 
189  if (s->whatorbits == ScopeLevel::LEVEL_UNIV)
190  deductAPs(g.player, g.governor, APcount, 0, 1);
191  else
192  deductAPs(g.player, g.governor, APcount, s->storbits, 0);
193 
194  Race = races[g.player - 1];
195 
196  // TODO(jeffbailey): kill_ship gets and saves the ship, which looks like
197  // it'll be overwritten maybe here?
198  kill_ship(g.player, s);
199  putship(s);
200  if (docked(s)) {
201  s2->crystals += xtalval;
202  rcv_fuel(&*s2, (double)fuelval);
203  rcv_destruct(&*s2, destval);
204  rcv_resource(&*s2, scrapval);
205  rcv_troops(&*s2, troopval, Race->mass);
206  rcv_popn(&*s2, crewval, Race->mass);
207  /* check for docking status in case scrapped ship is landed. Maarten */
208  if (!(s->whatorbits == ScopeLevel::LEVEL_SHIP)) {
209  s2->docked = 0; /* undock the surviving ship */
210  s2->whatdest = ScopeLevel::LEVEL_UNIV;
211  s2->destshipno = 0;
212  }
213  putship(&*s2);
214  }
215 
216  if (s->whatorbits == ScopeLevel::LEVEL_PLAN) {
217  auto planet = getplanet(s->storbits, s->pnumorbits);
218  if (landed(*s)) {
219  if (sect.owner == g.player) {
220  sect.popn += troopval;
221  sect.popn += crewval;
222  } else if (sect.owner == 0) {
223  sect.owner = g.player;
224  sect.popn += crewval;
225  sect.troops += troopval;
226  planet.info[g.player - 1].numsectsowned++;
227  planet.info[g.player - 1].popn += crewval;
228  planet.info[g.player - 1].popn += troopval;
229  sprintf(buf, "Sector %d,%d Colonized.\n", s->land_x, s->land_y);
230  notify(g.player, g.governor, buf);
231  }
232  planet.info[g.player - 1].resource += scrapval;
233  planet.popn += crewval;
234  planet.info[g.player - 1].destruct += destval;
235  planet.info[g.player - 1].fuel += (int)fuelval;
236  planet.info[g.player - 1].crystals += (int)xtalval;
237  putsector(sect, planet, s->land_x, s->land_y);
238  }
239  putplanet(planet, Stars[s->storbits], (int)s->pnumorbits);
240  }
241  if (landed(*s)) {
242  g.out << "\nScrapped.\n";
243  } else {
244  g.out << "\nDestroyed.\n";
245  }
246  free(s);
247  } else
248  free(s);
249 }
Planet getplanet(const starnum_t star, const planetnum_t pnum)
Definition: files_shl.cc:335
void putsector(const Sector &s, const Planet &p, const int x, const int y)
Definition: files_shl.cc:1076
int docked(Ship *s)
Definition: land.cc:422
void deductAPs(const player_t Playernum, const governor_t Governor, unsigned int n, starnum_t snum, int sdata)
Definition: shlmisc.cc:214
void scrap(const command_t &argv, GameObj &g)
Definition: scrap.cc:23
int enufAP(int Playernum, int Governor, unsigned short AP, int x)
Definition: shlmisc.cc:131
shipnum_t do_shiplist(Ship **s, shipnum_t *nextshipno)
Definition: shlmisc.cc:94
void putplanet(const Planet &p, startype *star, const int pnum)
Definition: files_shl.cc:934
void putship(Ship *s)
Definition: files_shl.cc:1317
Sector getsector(const Planet &p, const int x, const int y)
Definition: files_shl.cc:480