8 #include "gb/moveship.h" 15 #include "gb/GB_server.h" 16 #include "gb/buffers.h" 17 #include "gb/files_shl.h" 25 #include "gb/shlmisc.h" 27 #include "gb/tweakables.h" 35 static const double SpeedConsts[] = {0.0, 0.61, 1.26, 1.50, 1.73,
36 1.81, 1.90, 1.93, 1.96, 1.97};
41 void moveship(Ship *s,
int mode,
int send_messages,
int checking_fuel) {
61 if (s->hyper_drive.has && s->hyper_drive.on) {
63 if (s->hyper_drive.ready) {
64 dist = sqrt(
Distsq(s->xpos, s->ypos, Stars[s->deststar]->xpos,
65 Stars[s->deststar]->ypos));
67 if (s->mounted && dist > distfac)
75 "%s at system %s does not have %.1ff to do hyperspace jump.",
76 ship_to_string(*s).c_str(), prin_ship_orbits(s), fuse);
78 push_telegram((
int)(s->owner), (
int)s->governor, telegram_buf);
79 s->hyper_drive.on = 0;
83 heading = atan2(Stars[s->deststar]->xpos - s->xpos,
84 Stars[s->deststar]->ypos - s->ypos);
87 s->xpos = Stars[s->deststar]->xpos - sn * 0.9 *
SYSTEMSIZE;
88 s->ypos = Stars[s->deststar]->ypos - cs * 0.9 *
SYSTEMSIZE;
89 s->whatorbits = ScopeLevel::LEVEL_STAR;
90 s->storbits = s->deststar;
91 s->protect.planet = 0;
92 s->hyper_drive.on = 0;
93 s->hyper_drive.ready = 0;
94 s->hyper_drive.charge = 0;
95 sprintf(telegram_buf,
"%s arrived at %s.", ship_to_string(*s).c_str(),
98 push_telegram((
int)(s->owner), (
int)s->governor, telegram_buf);
99 }
else if (s->mounted) {
100 s->hyper_drive.ready = 1;
104 s->hyper_drive.ready = 1;
106 s->hyper_drive.charge += 1;
110 if (s->speed && !s->docked && s->alive &&
111 (s->whatdest != ScopeLevel::LEVEL_UNIV || s->navigate.on)) {
112 fuse = 0.5 * s->speed * (1 + s->protect.evade) * s->mass *
FUEL_USE /
114 if (s->fuel < fuse) {
116 if (s->whatorbits == ScopeLevel::LEVEL_UNIV &&
117 (s->build_cost <= 50 || s->type == ShipType::OTYPE_VN ||
118 s->type == ShipType::OTYPE_BERS)) {
119 sprintf(telegram_buf,
"%s has been lost in deep space.",
120 ship_to_string(*s).c_str());
122 push_telegram((
int)(s->owner), (
int)s->governor, telegram_buf);
123 if (send_messages) kill_ship((
int)(s->owner), s);
127 if (s->navigate.on) {
128 heading = .0174329252 * s->navigate.bearing;
135 xdest = sn * mfactor;
136 ydest = -cs * mfactor;
140 if (!s->navigate.turns) s->navigate.on = 0;
142 ost = Stars[s->storbits];
143 const auto &opl = planets[s->storbits][s->pnumorbits];
144 if (s->whatorbits == ScopeLevel::LEVEL_PLAN) {
145 dist = sqrt(
Distsq(s->xpos, s->ypos, ost->xpos + opl->xpos,
146 ost->ypos + opl->ypos));
148 s->whatorbits = ScopeLevel::LEVEL_STAR;
149 s->protect.planet = 0;
151 }
else if (s->whatorbits == ScopeLevel::LEVEL_STAR) {
152 dist = sqrt(
Distsq(s->xpos, s->ypos, ost->xpos, ost->ypos));
154 s->whatorbits = ScopeLevel::LEVEL_UNIV;
155 s->protect.evade = 0;
156 s->protect.planet = 0;
160 destlevel = s->whatdest;
161 if (destlevel == ScopeLevel::LEVEL_SHIP) {
162 dsh = ships[s->destshipno];
163 s->deststar = dsh->storbits;
164 s->destpnum = dsh->pnumorbits;
167 switch (dsh->whatorbits) {
168 case ScopeLevel::LEVEL_UNIV:
170 case ScopeLevel::LEVEL_PLAN:
171 if (s->whatorbits != dsh->whatorbits ||
172 s->pnumorbits != dsh->pnumorbits)
173 destlevel = ScopeLevel::LEVEL_PLAN;
175 case ScopeLevel::LEVEL_STAR:
176 if (s->whatorbits != dsh->whatorbits ||
177 s->storbits != dsh->storbits)
178 destlevel = ScopeLevel::LEVEL_STAR;
180 case ScopeLevel::LEVEL_SHIP:
193 if (destlevel == ScopeLevel::LEVEL_STAR ||
194 (destlevel == ScopeLevel::LEVEL_PLAN &&
195 (s->storbits != s->deststar ||
196 s->whatorbits == ScopeLevel::LEVEL_UNIV))) {
197 destlevel = ScopeLevel::LEVEL_STAR;
198 deststar = s->deststar;
199 xdest = Stars[deststar]->xpos;
200 ydest = Stars[deststar]->ypos;
201 }
else if (destlevel == ScopeLevel::LEVEL_PLAN &&
202 s->storbits == s->deststar) {
203 destlevel = ScopeLevel::LEVEL_PLAN;
204 deststar = s->deststar;
205 destpnum = s->destpnum;
206 xdest = Stars[deststar]->xpos + planets[deststar][destpnum]->xpos;
207 ydest = Stars[deststar]->ypos + planets[deststar][destpnum]->ypos;
209 destlevel = ScopeLevel::LEVEL_UNIV;
211 dst = Stars[deststar];
212 ost = Stars[s->storbits];
213 const auto &dpl = planets[deststar][destpnum];
214 const auto &opl = planets[s->storbits][s->pnumorbits];
215 truedist = movedist = sqrt(
Distsq(s->xpos, s->ypos, xdest, ydest));
218 if (truedist <
DIST_TO_LAND && s->whatorbits == destlevel &&
219 s->storbits == deststar && s->pnumorbits == destpnum)
221 heading = atan2((
double)(xdest - s->xpos), (
double)(-ydest + s->ypos));
223 (1. - .01 * (
double)s->damage) *
SpeedConsts[s->speed] *
227 if (destlevel == ScopeLevel::LEVEL_STAR &&
228 (s->storbits != deststar || s->whatorbits == ScopeLevel::LEVEL_UNIV))
230 else if (destlevel == ScopeLevel::LEVEL_PLAN &&
231 s->whatorbits == ScopeLevel::LEVEL_STAR &&
232 s->storbits == deststar && truedist >=
PLORBITSIZE)
235 if (s->whatdest == ScopeLevel::LEVEL_SHIP &&
237 s->whatdest = ScopeLevel::LEVEL_UNIV;
238 s->protect.evade = 0;
239 sprintf(telegram_buf,
"%s at %s lost sight of destination ship #%ld.",
240 ship_to_string(*s).c_str(), prin_ship_orbits(s), s->destshipno);
242 push_telegram((
int)(s->owner), (
int)s->governor, telegram_buf);
250 xdest = sn * mfactor;
251 ydest = -cs * mfactor;
252 if (hypot(xdest, ydest) > movedist) {
253 xdest = sn * movedist;
254 ydest = -cs * movedist;
261 if (s->whatorbits == ScopeLevel::LEVEL_PLAN) {
262 dist = sqrt(
Distsq(s->xpos, s->ypos, ost->xpos + opl->xpos,
263 ost->ypos + opl->ypos));
265 s->whatorbits = ScopeLevel::LEVEL_STAR;
266 s->protect.planet = 0;
268 }
else if (s->whatorbits == ScopeLevel::LEVEL_STAR) {
269 dist = sqrt(
Distsq(s->xpos, s->ypos, ost->xpos, ost->ypos));
271 s->whatorbits = ScopeLevel::LEVEL_UNIV;
272 s->protect.evade = 0;
273 s->protect.planet = 0;
278 if (destlevel == ScopeLevel::LEVEL_STAR ||
279 (destlevel == ScopeLevel::LEVEL_PLAN &&
280 (s->storbits != deststar ||
281 s->whatorbits == ScopeLevel::LEVEL_UNIV))) {
282 stardist = sqrt(
Distsq(s->xpos, s->ypos, dst->xpos, dst->ypos));
284 s->whatorbits = ScopeLevel::LEVEL_STAR;
285 s->protect.planet = 0;
286 s->storbits = deststar;
289 if (!checking_fuel && (s->popn || s->type == ShipType::OTYPE_PROBE)) {
290 if (!
isset(dst->inhabited, (
int)s->owner))
291 dst->governor[s->owner - 1] = s->governor;
292 setbit(dst->explored, (
int)s->owner);
293 setbit(dst->inhabited, (
int)s->owner);
295 if (s->type != ShipType::OTYPE_VN) {
296 sprintf(telegram_buf,
"%s arrived at %s.",
297 ship_to_string(*s).c_str(), prin_ship_orbits(s));
299 push_telegram((
int)(s->owner), (
int)s->governor, telegram_buf);
301 if (s->whatdest == ScopeLevel::LEVEL_STAR)
302 s->whatdest = ScopeLevel::LEVEL_UNIV;
304 }
else if (destlevel == ScopeLevel::LEVEL_PLAN &&
305 deststar == s->storbits) {
307 dist = sqrt(
Distsq(s->xpos, s->ypos, dst->xpos + dpl->xpos,
308 dst->ypos + dpl->ypos));
310 if (!checking_fuel && (s->popn || s->type == ShipType::OTYPE_PROBE)) {
311 dpl->info[s->owner - 1].explored = 1;
312 setbit(dst->explored, (
int)(s->owner));
313 setbit(dst->inhabited, (
int)(s->owner));
315 s->whatorbits = ScopeLevel::LEVEL_PLAN;
316 s->pnumorbits = destpnum;
318 sprintf(telegram_buf,
"%s within landing distance of %s.",
319 ship_to_string(*s).c_str(), prin_ship_orbits(s));
321 if (s->whatdest == ScopeLevel::LEVEL_PLAN)
322 s->whatdest = ScopeLevel::LEVEL_UNIV;
324 sprintf(telegram_buf,
"%s arriving at %s.",
325 ship_to_string(*s).c_str(), prin_ship_orbits(s));
327 if (s->type == ShipType::STYPE_OAP) {
328 sprintf(buf,
"\nEnslavement of the planet is now possible.");
329 strcat(telegram_buf, buf);
331 if (send_messages && s->type != ShipType::OTYPE_VN)
332 push_telegram((
int)(s->owner), (
int)s->governor, telegram_buf);
334 }
else if (destlevel == ScopeLevel::LEVEL_SHIP) {
335 dist = sqrt(
Distsq(s->xpos, s->ypos, dsh->xpos, dsh->ypos));
337 if (dsh->whatorbits == ScopeLevel::LEVEL_PLAN) {
338 s->whatorbits = ScopeLevel::LEVEL_PLAN;
339 s->storbits = dsh->storbits;
340 s->pnumorbits = dsh->pnumorbits;
341 }
else if (dsh->whatorbits == ScopeLevel::LEVEL_STAR) {
342 s->whatorbits = ScopeLevel::LEVEL_STAR;
343 s->storbits = dsh->storbits;
344 s->protect.planet = 0;
356 sprintf(buf,
"%s is out of fuel at %s.", ship_to_string(*s).c_str(),
357 prin_ship_orbits(s));
358 push_telegram((
int)(s->owner), (
int)s->governor, buf);
369 if (!s2->alive || !s1->active || s2->whatorbits == ScopeLevel::LEVEL_SHIP)
372 dx = s1->xpos - s2->xpos;
373 dy = s1->ypos - s2->ypos;
375 range = 4.0 * logscale((
int)(s1->tech + 1.0)) *
SYSTEMSIZE;
377 r = races[s2->owner - 1];
378 allied[0] = r->allied[0];
379 allied[1] = r->allied[1];
381 return (s1->owner == s2->owner) || (
isset(allied, (
int)s1->owner)) ||
382 (sqrt(dx * dx + dy * dy) <= range);
399 if (!s->merchant || !p->info[i].route[j].set)
402 auto sect =
getsector(*p
, p->info[i].route[j].x
, p->info[i].route[j].y
);
403 if (sect.owner && (sect.owner != s->owner)) {
409 if (s->fuel < fuel) {
410 s->whatdest = ScopeLevel::LEVEL_UNIV;
411 strcat(telegram_buf,
"\t\tNot enough fuel to land!\n");
414 s->land_x = p->info[i].route[j].x;
415 s->land_y = p->info[i].route[j].y;
416 sprintf(buf,
"\t\tLanded on sector %d,%d\n", s->land_x, s->land_y);
417 strcat(telegram_buf, buf);
418 s->xpos = p->xpos + Stars[s->storbits]->xpos;
419 s->ypos = p->ypos + Stars[s->storbits]->ypos;
422 s->whatdest = ScopeLevel::LEVEL_PLAN;
423 s->deststar = s->storbits;
424 s->destpnum = s->pnumorbits;
427 load = p->info[i].route[j].load;
428 unload = p->info[i].route[j].unload;
430 strcat(telegram_buf,
"\t\t");
432 amount = (
int)s->max_fuel - (
int)s->fuel;
433 if (amount > p->info[i].fuel) amount = p->info[i].fuel;
434 p->info[i].fuel -= amount;
436 sprintf(buf,
"%df ", amount);
437 strcat(telegram_buf, buf);
440 amount = (
int)s->max_resource - (
int)s->resource;
441 if (amount > p->info[i].resource) amount = p->info[i].resource;
442 p->info[i].resource -= amount;
444 sprintf(buf,
"%dr ", amount);
445 strcat(telegram_buf, buf);
448 amount = p->info[i].crystals;
449 p->info[i].crystals -= amount;
450 s->crystals += amount;
451 sprintf(buf,
"%dx ", amount);
452 strcat(telegram_buf, buf);
455 amount = (
int)s->max_destruct - (
int)s->destruct;
456 if (amount > p->info[i].destruct) amount = p->info[i].destruct;
457 p->info[i].destruct -= amount;
459 sprintf(buf,
"%dd ", amount);
460 strcat(telegram_buf, buf);
462 strcat(telegram_buf,
"loaded\n");
465 strcat(telegram_buf,
"\t\t");
467 amount = (
int)s->fuel;
468 p->info[i].fuel += amount;
469 sprintf(buf,
"%df ", amount);
470 strcat(telegram_buf, buf);
474 amount = s->resource;
475 p->info[i].resource += amount;
476 sprintf(buf,
"%dr ", amount);
477 strcat(telegram_buf, buf);
481 amount = s->crystals;
482 p->info[i].crystals += amount;
483 sprintf(buf,
"%dx ", amount);
484 strcat(telegram_buf, buf);
485 s->crystals -= amount;
488 amount = s->destruct;
489 p->info[i].destruct += amount;
490 sprintf(buf,
"%dd ", amount);
491 strcat(telegram_buf, buf);
494 strcat(telegram_buf,
"unloaded\n");
499 if (s->fuel < fuel) {
500 strcat(telegram_buf,
"\t\tNot enough fuel to launch!\n");
504 s->whatdest = ScopeLevel::LEVEL_PLAN;
505 s->deststar = p->info[i].route[j].dest_star;
506 s->destpnum = p->info[i].route[j].dest_planet;
509 sprintf(buf,
"\t\tDestination set to %s\n", prin_ship_dest(*s).c_str());
510 strcat(telegram_buf, buf);
511 if (s->hyper_drive.has) {
512 if (s->storbits != s->deststar) {
514 s->hyper_drive.on = 1;
516 s->hyper_drive.charge = 1;
517 s->hyper_drive.ready = 1;
519 s->hyper_drive.charge = 0;
520 s->hyper_drive.ready = 0;
522 strcat(telegram_buf,
"\t\tJump orders set\n");
void use_fuel(Ship *s, double amt)
#define LAND_GRAV_MASS_FACTOR
#define Distsq(x1, y1, x2, y2)
static const double SpeedConsts[]
void rcv_resource(Ship *s, int amt)
void rcv_fuel(Ship *s, double amt)
#define HYPER_DIST_FACTOR
#define HYPER_DRIVE_FUEL_USE
#define HYPER_DRIVE_READY_CHARGE
#define LAUNCH_GRAV_MASS_FACTOR
int followable(Ship *, Ship *)
void use_destruct(Ship *s, int amt)
void use_resource(Ship *s, int amt)
void moveship(Ship *, int, int, int)
void rcv_destruct(Ship *s, int amt)
double gravity(const Planet &p)
static const double MoveConsts[]
static int do_merchant(Ship *, Planet *)
Sector getsector(const Planet &p, const int x, const int y)