16 #include "gb/GB_server.h" 17 #include "gb/buffers.h" 18 #include "gb/config.h" 20 #include "gb/files_shl.h" 22 #include "gb/getplace.h" 27 #include "gb/shlmisc.h" 28 #include "gb/shootblast.h" 30 #include "gb/tweakables.h" 31 #include "gb/utils/rand.h" 35 static std::tuple<
bool,
int>
crash(
const Ship *s,
const double fuel)
noexcept {
37 if (s->fuel < fuel)
return {
true, 0};
40 if (
auto roll = int_rand(1, 100); roll <= s->damage)
return {
true, roll};
46 void land(
const command_t &argv, GameObj &g) {
47 player_t Playernum = g.player;
48 governor_t Governor = g.governor;
66 if (argv.size() < 2) {
67 g.out <<
"Land what?\n";
71 nextshipno = start_shiplist(g, argv[1]);
74 if (in_list(Playernum, argv[1], *s, &nextshipno) &&
75 authorized(Governor, *s)) {
77 sprintf(buf,
"%s is too overloaded to land.\n",
78 ship_to_string(*s).c_str());
79 notify(Playernum, Governor, buf);
83 if (s->type == ShipType::OTYPE_QUARRY) {
84 g.out <<
"You can't load quarries onto ship.\n";
89 g.out <<
"That ship is docked to another ship.\n";
95 if (argv[2][0] ==
'#') {
96 auto ship2tmp = string_to_shipnum(argv[2]);
98 sprintf(buf,
"Ship %s wasn't found.\n", argv[2].c_str());
99 notify(Playernum, Governor, buf);
103 auto s2 = getship(*ship2tmp);
105 sprintf(buf,
"Ship #%lu wasn't found.\n", *ship2tmp);
106 notify(Playernum, Governor, buf);
110 auto ship2no = *ship2tmp;
111 if (testship(Playernum, Governor, *s2)) {
112 g.out <<
"Illegal format.\n";
116 if (s2->type == ShipType::OTYPE_FACTORY) {
117 g.out <<
"Can't land on factories.\n";
123 sprintf(buf,
"%s is not landed on a planet.\n",
124 ship_to_string(*s2).c_str());
125 notify(Playernum, Governor, buf);
129 if (s2->storbits != s->storbits) {
130 notify(Playernum, Governor,
131 "These ships are not in the same star system.\n");
135 if (s2->pnumorbits != s->pnumorbits) {
136 notify(Playernum, Governor,
137 "These ships are not landed on the same planet.\n");
141 if ((s2->land_x != s->land_x) || (s2->land_y != s->land_y)) {
142 notify(Playernum, Governor,
143 "These ships are not in the same sector.\n");
148 sprintf(buf,
"%s must be turned off before loading.\n",
149 ship_to_string(*s).c_str());
150 notify(Playernum, Governor, buf);
154 if (size(*s) > hanger(*s2)) {
156 "Mothership does not have %d hanger space available " 159 notify(Playernum, Governor, buf);
167 s2 = getship(ship2no);
168 insert_sh_ship(s, &*s2);
171 s2->hanger += size(*s);
173 sprintf(buf,
"%s loaded onto %s using %.1f fuel.\n",
174 ship_to_string(*s).c_str(), ship_to_string(*s2).c_str(),
176 notify(Playernum, Governor, buf);
179 }
else if (s->docked) {
180 sprintf(buf,
"%s is already docked or landed.\n",
181 ship_to_string(*s).c_str());
182 notify(Playernum, Governor, buf);
187 if (s->whatorbits != s2->whatorbits) {
188 notify(Playernum, Governor,
189 "Those ships are not in the same scope.\n");
195 Dist = sqrt((
double)
Distsq(s2->xpos, s2->ypos, s->xpos, s->ypos));
197 sprintf(buf,
"%s must be %.2f or closer to %s.\n",
199 ship_to_string(*s2).c_str());
200 notify(Playernum, Governor, buf);
204 fuel = 0.05 + Dist * 0.025 * sqrt(s->mass);
205 if (s->fuel < fuel) {
206 sprintf(buf,
"Not enough fuel.\n");
207 notify(Playernum, Governor, buf);
211 if (size(*s) > hanger(*s2)) {
213 "Mothership does not have %d hanger space available " 216 notify(Playernum, Governor, buf);
223 if (s->whatorbits == ScopeLevel::LEVEL_PLAN)
225 else if (s->whatorbits == ScopeLevel::LEVEL_STAR)
228 g.out <<
"Ship is not in planet or star scope.\n";
234 s2 = getship(ship2no);
235 insert_sh_ship(s, &*s2);
238 s2->hanger += size(*s);
239 sprintf(buf,
"%s landed on %s using %.1f fuel.\n",
240 ship_to_string(*s).c_str(), ship_to_string(*s2).c_str(),
242 notify(Playernum, Governor, buf);
248 sprintf(buf,
"%s is docked.\n", ship_to_string(*s).c_str());
249 notify(Playernum, Governor, buf);
253 sscanf(argv[2].c_str(),
"%d,%d", &x, &y);
254 if (s->whatorbits != ScopeLevel::LEVEL_PLAN) {
255 sprintf(buf,
"%s doesn't orbit a planet.\n",
256 ship_to_string(*s).c_str());
257 notify(Playernum, Governor, buf);
261 if (!Shipdata[s->type][ABIL_CANLAND]) {
262 sprintf(buf,
"This ship is not equipped to land.\n");
263 notify(Playernum, Governor, buf);
267 if ((s->storbits != g.snum) || (s->pnumorbits != g.pnum)) {
268 sprintf(buf,
"You have to cs to the planet it orbits.\n");
269 notify(Playernum, Governor, buf);
273 if (!speed_rating(*s)) {
274 sprintf(buf,
"This ship is not rated for maneuvering.\n");
275 notify(Playernum, Governor, buf);
279 if (!
enufAP(Playernum
, Governor
, Stars[s->storbits]->AP[Playernum - 1]
, 285 auto p =
getplanet((
int)s->storbits
, (
int)s->pnumorbits
);
287 sprintf(buf,
"Planet /%s/%s has gravity field of %.2f.\n",
288 Stars[s->storbits]->name,
289 Stars[s->storbits]->pnames[s->pnumorbits],
gravity(p
));
290 notify(Playernum, Governor, buf);
292 sprintf(buf,
"Distance to planet: %.2f.\n",
293 Dist = sqrt((
double)
Distsq(Stars[s->storbits]->xpos + p.xpos,
294 Stars[s->storbits]->ypos + p.ypos,
296 notify(Playernum, Governor, buf);
299 sprintf(buf,
"%s must be %.3g or closer to the planet (%.2f).\n",
301 notify(Playernum, Governor, buf);
308 if ((x < 0) || (y < 0) || (x > p.Maxx - 1) || (y > p.Maxy - 1)) {
309 sprintf(buf,
"Illegal coordinates.\n");
310 notify(Playernum, Governor, buf);
317 for (i = 1; i <= Num_races; i++)
318 if (s->alive && i != Playernum && p.info[i - 1].popn &&
319 p.info[i - 1].guns && p.info[i - 1].destruct) {
320 alien = races[i - 1];
321 if (
isset(alien->atwar, (
int)s->owner)) {
324 MIN((
int)p.info[i - 1].guns, (
int)p.info[i - 1].destruct);
327 notify_star(0, 0, s->storbits, temp);
328 warn(i, Stars[s->storbits]->governor[i - 1], buf);
329 notify((
int)s->owner, (
int)s->governor, buf);
330 p.info[i - 1].destruct -= strength;
342 if (
auto [did_crash, roll] = crash(s, fuel); did_crash) {
346 s
, &p
, round_rand((
double)(s->destruct) / 3.)
, x
, y
, smap
, 0
, 347 GTYPE_HEAVY
, long_buf
, short_buf
);
351 "BOOM!! %s crashes on sector %d,%d with blast radius of %d.\n",
352 ship_to_string(*s).c_str(), x, y, numdest);
353 for (i = 1; i <= Num_races; i++)
354 if (p.info[i - 1].numsectsowned || i == Playernum)
355 warn(i, Stars[s->storbits]->governor[i - 1], buf);
357 sprintf(buf,
"Ship damage %d%% (you rolled a %d)\n", (
int)s->damage,
360 sprintf(buf,
"You had %.1ff while the landing required %.1ff\n",
362 notify(Playernum, Governor, buf);
363 kill_ship((
int)s->owner, s);
367 s->xpos = p.xpos + Stars[s->storbits]->xpos;
368 s->ypos = p.ypos + Stars[s->storbits]->ypos;
371 s->whatdest = ScopeLevel::LEVEL_PLAN;
372 s->deststar = s->storbits;
373 s->destpnum = s->pnumorbits;
378 if (sect.condition == SectorType::SEC_WASTED) {
379 sprintf(buf,
"Warning: That sector is a wasteland!\n");
380 notify(Playernum, Governor, buf);
381 }
else if (sect.owner && sect.owner != Playernum) {
382 Race = races[Playernum - 1];
383 alien = races[sect.owner - 1];
384 if (!(
isset(Race->allied, sect.owner) &&
385 isset(alien->allied, Playernum))) {
386 sprintf(buf,
"You have landed on an alien sector (%s).\n",
388 notify(Playernum, Governor, buf);
390 sprintf(buf,
"You have landed on allied sector (%s).\n",
392 notify(Playernum, Governor, buf);
395 if (s->whatorbits == ScopeLevel::LEVEL_UNIV)
405 sprintf(buf,
"%s observed landing on sector %d,%d,planet /%s/%s.\n",
406 ship_to_string(*s).c_str(), s->land_x, s->land_y,
407 Stars[s->storbits]->name,
408 Stars[s->storbits]->pnames[s->pnumorbits]);
409 for (i = 1; i <= Num_races; i++)
410 if (p.info[i - 1].numsectsowned && i != Playernum)
411 notify(i, (
int)Stars[s->storbits]->governor[i - 1], buf);
413 sprintf(buf,
"%s landed on planet.\n", ship_to_string(*s).c_str());
414 notify(Playernum, Governor, buf);
423 return (s->docked && s->whatdest == ScopeLevel::LEVEL_SHIP);
427 return ((s->resource > max_resource(*s)) || (s->fuel > max_fuel(*s)) ||
428 (s->popn + s->troops > s->max_crew) ||
429 (s->destruct > max_destruct(*s)));
void use_fuel(Ship *s, double amt)
#define LAND_GRAV_MASS_FACTOR
#define Distsq(x1, y1, x2, y2)
void post(const char *origmsg, int type)
Planet getplanet(const starnum_t star, const planetnum_t pnum)
void land(const command_t &argv, GameObj &g)
void putsector(const Sector &s, const Planet &p, const int x, const int y)
int shoot_ship_to_planet(Ship *, Planet *, int, int, int, SectorMap &, int, int, char *, char *)
void putsmap(SectorMap &map, Planet &p)
static std::tuple< bool, int > crash(const Ship *s, const double fuel) noexcept
Determine whether the ship crashed or not.
void deductAPs(const player_t Playernum, const governor_t Governor, unsigned int n, starnum_t snum, int sdata)
int enufAP(int Playernum, int Governor, unsigned short AP, int x)
shipnum_t do_shiplist(Ship **s, shipnum_t *nextshipno)
void putplanet(const Planet &p, startype *star, const int pnum)
SectorMap getsmap(const Planet &p)
double gravity(const Planet &p)
Sector getsector(const Planet &p, const int x, const int y)