Galactic Bloodshed
launch.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 /* launch.c -- launch or undock a ship (also undock) */
6 
7 #include "gb/launch.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/load.h"
17 #include "gb/max.h"
18 #include "gb/ships.h"
19 #include "gb/shlmisc.h"
20 #include "gb/tweakables.h"
21 #include "gb/utils/rand.h"
22 #include "gb/vars.h"
23 
24 void launch(const command_t &argv, GameObj &g) {
25  player_t Playernum = g.player;
26  governor_t Governor = g.governor;
27  int APcount = 1;
28  Ship *s;
29  shipnum_t shipno;
30  shipnum_t nextshipno;
31  double fuel;
32 
33  if (argv.size() < 2) {
34  g.out << "Launch what?\n";
35  return;
36  }
37 
38  nextshipno = start_shiplist(g, argv[1]);
39 
40  while ((shipno = do_shiplist(&s, &nextshipno)))
41  if (in_list(Playernum, argv[1], *s, &nextshipno) &&
42  authorized(Governor, *s)) {
43  if (!speed_rating(*s) && landed(*s)) {
44  sprintf(buf, "That ship is not designed to be launched.\n");
45  notify(Playernum, Governor, buf);
46  free(s);
47  continue;
48  }
49 
50  if (!(s->docked || s->whatorbits == ScopeLevel::LEVEL_SHIP)) {
51  sprintf(buf, "%s is not landed or docked.\n",
52  ship_to_string(*s).c_str());
53  notify(Playernum, Governor, buf);
54  free(s);
55  continue;
56  }
57  if (!landed(*s)) APcount = 0;
58  if (landed(*s) && s->resource > max_resource(*s)) {
59  sprintf(buf, "%s is too overloaded to launch.\n",
60  ship_to_string(*s).c_str());
61  notify(Playernum, Governor, buf);
62  free(s);
63  continue;
64  }
65  if (s->whatorbits == ScopeLevel::LEVEL_SHIP) {
66  /* Factories cannot be launched once turned on. Maarten */
67  if (s->type == ShipType::OTYPE_FACTORY && s->on) {
68  notify(Playernum, Governor,
69  "Factories cannot be launched once turned on.\n");
70  g.out << "Consider using 'scrap'.\n";
71  free(s);
72  continue;
73  }
74  auto s2 = getship(s->destshipno);
75  if (landed(*s2)) {
76  remove_sh_ship(*s, *s2);
77  auto p = getplanet(s2->storbits, s2->pnumorbits);
78  insert_sh_plan(&p, s);
79  putplanet(p, Stars[s2->storbits], s2->pnumorbits);
80  s->storbits = s2->storbits;
81  s->pnumorbits = s2->pnumorbits;
82  s->destpnum = s2->pnumorbits;
83  s->deststar = s2->deststar;
84  s->xpos = s2->xpos;
85  s->ypos = s2->ypos;
86  s->land_x = s2->land_x;
87  s->land_y = s2->land_y;
88  s->docked = 1;
89  s->whatdest = ScopeLevel::LEVEL_PLAN;
90  s2->mass -= s->mass;
91  s2->hanger -= size(*s);
92  sprintf(buf, "Landed on %s/%s.\n", Stars[s->storbits]->name,
93  Stars[s->storbits]->pnames[s->pnumorbits]);
94  notify(Playernum, Governor, buf);
95  putship(s);
96  putship(&*s2);
97  } else if (s2->whatorbits == ScopeLevel::LEVEL_PLAN) {
98  remove_sh_ship(*s, *s2);
99  sprintf(buf, "%s launched from %s.\n", ship_to_string(*s).c_str(),
100  ship_to_string(*s2).c_str());
101  notify(Playernum, Governor, buf);
102  s->xpos = s2->xpos;
103  s->ypos = s2->ypos;
104  s->docked = 0;
105  s->whatdest = ScopeLevel::LEVEL_UNIV;
106  s2->mass -= s->mass;
107  s2->hanger -= size(*s);
108  auto p = getplanet(s2->storbits, s2->pnumorbits);
109  insert_sh_plan(&p, s);
110  s->storbits = s2->storbits;
111  s->pnumorbits = s2->pnumorbits;
112  putplanet(p, Stars[s2->storbits], s2->pnumorbits);
113  sprintf(buf, "Orbiting %s/%s.\n", Stars[s->storbits]->name,
114  Stars[s->storbits]->pnames[s->pnumorbits]);
115  notify(Playernum, Governor, buf);
116  putship(s);
117  putship(&*s2);
118  } else if (s2->whatorbits == ScopeLevel::LEVEL_STAR) {
119  remove_sh_ship(*s, *s2);
120  sprintf(buf, "%s launched from %s.\n", ship_to_string(*s).c_str(),
121  ship_to_string(*s2).c_str());
122  notify(Playernum, Governor, buf);
123  s->xpos = s2->xpos;
124  s->ypos = s2->ypos;
125  s->docked = 0;
126  s->whatdest = ScopeLevel::LEVEL_UNIV;
127  s2->mass -= s->mass;
128  s2->hanger -= size(*s);
129  getstar(&(Stars[s2->storbits]), (int)s2->storbits);
130  insert_sh_star(Stars[s2->storbits], s);
131  s->storbits = s2->storbits;
132  putstar(Stars[s2->storbits], (int)s2->storbits);
133  sprintf(buf, "Orbiting %s.\n", Stars[s->storbits]->name);
134  notify(Playernum, Governor, buf);
135  putship(s);
136  putship(&*s2);
137  } else if (s2->whatorbits == ScopeLevel::LEVEL_UNIV) {
138  remove_sh_ship(*s, *s2);
139  sprintf(buf, "%s launched from %s.\n", ship_to_string(*s).c_str(),
140  ship_to_string(*s2).c_str());
141  notify(Playernum, Governor, buf);
142  s->xpos = s2->xpos;
143  s->ypos = s2->ypos;
144  s->docked = 0;
145  s->whatdest = ScopeLevel::LEVEL_UNIV;
146  s2->mass -= s->mass;
147  s2->hanger -= size(*s);
148  getsdata(&Sdata);
149  insert_sh_univ(&Sdata, s);
150  g.out << "Universe level.\n";
151  putsdata(&Sdata);
152  putship(s);
153  putship(&*s2);
154  } else {
155  g.out << "You can't launch that ship.\n";
156  free(s);
157  continue;
158  }
159  free(s);
160  } else if (s->whatdest == ScopeLevel::LEVEL_SHIP) {
161  auto s2 = getship(s->destshipno);
162  if (s2->whatorbits == ScopeLevel::LEVEL_UNIV) {
163  if (!enufAP(Playernum, Governor, Sdata.AP[Playernum - 1], APcount)) {
164  free(s);
165  continue;
166  }
167  deductAPs(Playernum, Governor, APcount, 0, 1);
168  } else {
169  if (!enufAP(Playernum, Governor,
170  Stars[s->storbits]->AP[Playernum - 1], APcount)) {
171  free(s);
172  continue;
173  }
174  deductAPs(Playernum, Governor, APcount, (int)s->storbits, 0);
175  }
176  s->docked = 0;
177  s->whatdest = ScopeLevel::LEVEL_UNIV;
178  s->destshipno = 0;
179  s2->docked = 0;
180  s2->whatdest = ScopeLevel::LEVEL_UNIV;
181  s2->destshipno = 0;
182  sprintf(buf, "%s undocked from %s.\n", ship_to_string(*s).c_str(),
183  ship_to_string(*s2).c_str());
184  notify(Playernum, Governor, buf);
185  putship(s);
186  putship(&*s2);
187  free(s);
188  } else {
189  if (!enufAP(Playernum, Governor, Stars[s->storbits]->AP[Playernum - 1],
190  APcount)) {
191  free(s);
192  return;
193  }
194  deductAPs(Playernum, Governor, APcount, (int)s->storbits, 0);
195 
196  /* adjust x,ypos to absolute coords */
197  auto p = getplanet((int)s->storbits, (int)s->pnumorbits);
198  sprintf(buf, "Planet /%s/%s has gravity field of %.2f\n",
199  Stars[s->storbits]->name,
200  Stars[s->storbits]->pnames[s->pnumorbits], gravity(p));
201  notify(Playernum, Governor, buf);
202  s->xpos =
203  Stars[s->storbits]->xpos + p.xpos +
204  (double)int_rand((int)(-DIST_TO_LAND / 4), (int)(DIST_TO_LAND / 4));
205  s->ypos =
206  Stars[s->storbits]->ypos + p.ypos +
207  (double)int_rand((int)(-DIST_TO_LAND / 4), (int)(DIST_TO_LAND / 4));
208 
209  /* subtract fuel from ship */
210  fuel = gravity(p) * s->mass * LAUNCH_GRAV_MASS_FACTOR;
211  if (s->fuel < fuel) {
212  sprintf(buf, "%s does not have enough fuel! (%.1f)\n",
213  ship_to_string(*s).c_str(), fuel);
214  notify(Playernum, Governor, buf);
215  free(s);
216  return;
217  }
218  use_fuel(s, fuel);
219  s->docked = 0;
220  s->whatdest = ScopeLevel::LEVEL_UNIV; /* no destination */
221  switch (s->type) {
222  case ShipType::OTYPE_CANIST:
223  case ShipType::OTYPE_GREEN:
224  s->special.timer.count = 0;
225  break;
226  default:
227  break;
228  }
229  s->notified = 0;
230  putship(s);
231  if (!p.explored) {
232  /* not yet explored by owner; space exploration causes the
233  player to see a whole map */
234  p.explored = 1;
235  putplanet(p, Stars[s->storbits], (int)s->pnumorbits);
236  }
237  sprintf(buf, "%s observed launching from planet /%s/%s.\n",
238  ship_to_string(*s).c_str(), Stars[s->storbits]->name,
239  Stars[s->storbits]->pnames[s->pnumorbits]);
240  for (player_t i = 1; i <= Num_races; i++)
241  if (p.info[i - 1].numsectsowned && i != Playernum)
242  notify(i, (int)Stars[s->storbits]->governor[i - 1], buf);
243 
244  sprintf(buf, "%s launched from planet,", ship_to_string(*s).c_str());
245  notify(Playernum, Governor, buf);
246  sprintf(buf, " using %.1f fuel.\n", fuel);
247  notify(Playernum, Governor, buf);
248 
249  switch (s->type) {
250  case ShipType::OTYPE_CANIST:
251  notify(Playernum, Governor,
252  "A cloud of dust envelopes your planet.\n");
253  break;
254  case ShipType::OTYPE_GREEN:
255  notify(Playernum, Governor,
256  "Green house gases surround the planet.\n");
257  break;
258  default:
259  break;
260  }
261  free(s);
262  }
263  } else
264  free(s);
265 }
void use_fuel(Ship *s, double amt)
Definition: load.cc:876
#define DIST_TO_LAND
Definition: tweakables.h:194
Planet getplanet(const starnum_t star, const planetnum_t pnum)
Definition: files_shl.cc:335
#define LAUNCH_GRAV_MASS_FACTOR
Definition: tweakables.h:125
void deductAPs(const player_t Playernum, const governor_t Governor, unsigned int n, starnum_t snum, int sdata)
Definition: shlmisc.cc:214
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 getsdata(struct stardata *S)
Definition: files_shl.cc:272
void putplanet(const Planet &p, startype *star, const int pnum)
Definition: files_shl.cc:934
void putship(Ship *s)
Definition: files_shl.cc:1317
void launch(const command_t &argv, GameObj &g)
Definition: launch.cc:24
void putsdata(struct stardata *S)
Definition: files_shl.cc:804
double gravity(const Planet &p)
Definition: max.cc:59