14 #include "gb/GB_server.h" 16 #include "gb/buffers.h" 18 #include "gb/doturn.h" 20 #include "gb/files_shl.h" 24 #include "gb/moveship.h" 29 #include "gb/shlmisc.h" 30 #include "gb/shootblast.h" 32 #include "gb/tweakables.h" 33 #include "gb/utils/rand.h" 38 static void do_ap(Ship *);
41 static void do_god(Ship *);
45 static void do_oap(Ship *);
46 static void do_pod(Ship *);
50 void doship(Ship *ship,
int update) {
56 if (!ship->owner) ship->alive = 0;
65 if (success(ship->rad)) ship->active = 0;
67 ship->popn = round_rand(ship->popn * .80);
68 ship->troops = round_rand(ship->troops * .80);
72 ship->rad -= int_rand(0, (
int)ship->rad);
77 if (!ship->popn && max_crew(*ship) && !ship->docked)
78 ship->whatdest = ScopeLevel::LEVEL_UNIV;
80 if (ship->whatorbits != ScopeLevel::LEVEL_UNIV &&
81 Stars[ship->storbits]->nova_stage > 0) {
84 ship->damage += 5 * Stars[ship->storbits]->nova_stage /
85 ((armor(*ship) + 1) * segments);
86 if (ship->damage >= 100) {
87 kill_ship((
int)(ship->owner), ship);
92 if (ship->type == ShipType::OTYPE_FACTORY && !ship->on) {
93 Race = races[ship->owner - 1];
94 ship->tech = Race->tech;
99 ship->size = ship_size(*ship);
101 if (ship->whatorbits == ScopeLevel::LEVEL_SHIP) {
102 auto ship2 = getship(ship->destshipno);
103 if (ship2->owner != ship->owner) {
104 ship2->owner = ship->owner;
105 ship2->governor = ship->governor;
109 }
else if (ship->whatorbits != ScopeLevel::LEVEL_UNIV &&
110 (ship->popn || ship->type == ShipType::OTYPE_PROBE)) {
116 StarsInhab[ship->storbits] = 1;
117 setbit(Stars[ship->storbits]->inhabited, ship->owner);
118 setbit(Stars[ship->storbits]->explored, ship->owner);
119 if (ship->whatorbits == ScopeLevel::LEVEL_PLAN) {
120 planets[ship->storbits][ship->pnumorbits]
121 ->info[ship->owner - 1]
128 Power[ship->owner - 1].ships_owned++;
129 Power[ship->owner - 1].resource += ship->resource;
130 Power[ship->owner - 1].fuel += ship->fuel;
131 Power[ship->owner - 1].destruct += ship->destruct;
132 Power[ship->owner - 1].popn += ship->popn;
133 Power[ship->owner - 1].troops += ship->troops;
136 if (ship->whatorbits == ScopeLevel::LEVEL_UNIV) {
137 Sdatanumships[ship->owner - 1]++;
138 Sdatapopns[ship->owner] += ship->popn;
140 starnumships[ship->storbits][ship->owner - 1]++;
142 starpopns[ship->storbits][ship->owner - 1] += ship->popn;
145 if (ship->popn || ship->type == ShipType::OTYPE_PROBE) {
146 StarsInhab[ship->storbits] = 1;
147 setbit(Stars[ship->storbits]->inhabited, ship->owner);
148 setbit(Stars[ship->storbits]->explored, ship->owner);
154 if (can_bombard(*ship) && ship->bombard &&
155 ship->whatorbits == ScopeLevel::LEVEL_PLAN &&
156 ship->whatdest == ScopeLevel::LEVEL_PLAN &&
157 ship->deststar == ship->storbits &&
158 ship->destpnum == ship->pnumorbits) {
160 Stinfo[ship->storbits][ship->pnumorbits].inhab = 1;
166 if (ship->damage && repair(*ship))
do_repair(ship
);
168 if (update)
switch (ship->type) {
169 case ShipType::OTYPE_CANIST:
172 case ShipType::OTYPE_GREEN:
175 case ShipType::STYPE_MIRROR:
178 case ShipType::STYPE_GOD:
181 case ShipType::OTYPE_AP:
184 case ShipType::OTYPE_VN:
185 case ShipType::OTYPE_BERS:
186 if (!ship->special.mind.progenitor)
187 ship->special.mind.progenitor = 1;
190 case ShipType::STYPE_OAP:
193 case ShipType::STYPE_HABITAT:
199 if (ship->type == ShipType::STYPE_POD)
do_pod(ship
);
208 rmass = races[ship->owner - 1]->mass;
215 ship->mass += ships[sh]->mass;
216 ship->hanger += ships[sh]->size;
217 sh = ships[sh]->nextship;
219 ship->mass += getmass(*ship);
220 ship->mass += (
double)(ship->popn + ship->troops) * rmass;
231 ships[sh]->owner = ship->owner;
232 ships[sh]->governor = ship->governor;
233 sh = ships[sh]->nextship;
246 if (!ship->alive || !ship->owner)
return;
247 if (!ship->on || ship->docked)
return;
250 if (ship->whatdest == ScopeLevel::LEVEL_PLAN &&
251 ship->whatorbits == ScopeLevel::LEVEL_PLAN &&
252 ship->destpnum == ship->pnumorbits) {
253 auto p = planets[ship->storbits][ship->pnumorbits];
257 while (sh2 && !pdn) {
258 if (ships[sh2]->alive && ships[sh2]->type == ShipType::OTYPE_PLANDEF) {
261 ScopeLevel::LEVEL_SHIP;
262 ship->xpos = ships[sh2]->xpos;
263 ship->ypos = ships[sh2]->ypos;
264 ship->destshipno = sh2;
267 sh2 = ships[sh2]->nextship;
270 if (ship->special.impact.scatter) {
271 bombx = int_rand(1, (
int)p->Maxx) - 1;
272 bomby = int_rand(1, (
int)p->Maxy) - 1;
274 bombx = ship->special.impact.x % p->Maxx;
275 bomby = ship->special.impact.y % p->Maxy;
277 sprintf(buf,
"%s dropped on sector %d,%d at planet %s.\n",
278 ship_to_string(*ship).c_str(), bombx, bomby,
279 prin_ship_orbits(ship));
283 smap
, 0
, GTYPE_HEAVY
, long_buf
, short_buf
);
285 push_telegram((
int)ship->owner, (
int)ship->governor, long_buf);
286 kill_ship((
int)ship->owner, ship);
287 sprintf(buf,
"%s dropped on %s.\n\t%d sectors destroyed.\n",
288 ship_to_string(*ship).c_str(), prin_ship_orbits(ship), numdest);
289 for (i = 1; i <= Num_races; i++)
290 if (p->info[i - 1].numsectsowned && i != ship->owner)
291 push_telegram(i, Stars[ship->storbits]->governor[i - 1], buf);
293 sprintf(buf,
"%s dropped on %s.\n", ship_to_string(*ship).c_str(),
294 prin_ship_orbits(ship));
298 }
else if (ship->whatdest == ScopeLevel::LEVEL_SHIP) {
299 sh2 = ship->destshipno;
301 Distsq(ship->xpos, ship->ypos, ships[sh2]->xpos, ships[sh2]->ypos));
303 (100.0 - (
double)ship->damage) / 100.0)) {
306 long_buf
, short_buf
);
307 push_telegram((
int)ship->owner, (
int)ship->governor, long_buf);
308 push_telegram((
int)ships[sh2]->owner, (
int)ships[sh2]->governor,
310 kill_ship((
int)ship->owner, ship);
321 auto ship = getship(shipno);
323 if (ship->type != ShipType::STYPE_MINE || !ship->alive || !ship->owner) {
327 if (ship->on || detonate) {
332 switch (ship->whatorbits) {
333 case ScopeLevel::LEVEL_STAR:
334 sh = Stars[ship->storbits]->ships;
336 case ScopeLevel::LEVEL_PLAN: {
337 const auto planet = getplanet(ship->storbits, ship->pnumorbits);
347 r = races[ship->owner - 1];
348 Shiplist shiplist(sh);
349 for (
auto s : shiplist) {
350 xd = s.xpos - ship->xpos;
351 yd = s.ypos - ship->ypos;
352 range = sqrt(xd * xd + yd * yd);
353 if (!
isset(r->allied, s.owner) && (s.owner != ship->owner) &&
354 ((
int)range <= ship->special.trigger.radius)) {
363 sprintf(buf,
"%s detonated at %s\n", ship_to_string(*ship).c_str(),
364 prin_ship_orbits(&*ship));
366 notify_star(ship->owner, ship->governor, ship->storbits, buf);
367 Shiplist shiplist(sh);
368 for (
auto s : shiplist) {
369 if (sh != shipno && s.alive && (s.type != ShipType::OTYPE_CANIST) &&
370 (s.type != ShipType::OTYPE_GREEN)) {
371 auto damage = shoot_ship_to_ship(&*ship, &s, (
int)(ship->destruct), 0,
372 0, long_buf, short_buf);
375 warn(s.owner, s.governor, long_buf);
382 if (ship->whatorbits == ScopeLevel::LEVEL_PLAN) {
387 auto planet = getplanet((
int)ship->storbits, (
int)ship->pnumorbits);
392 x = int_rand(0, (
int)planet.Maxx - 1);
393 y = int_rand(0, (
int)planet.Maxy - 1);
395 auto smap = getsmap(planet);
397 shoot_ship_to_planet(&*ship, &planet, (
int)(ship->destruct), x, y,
398 smap, 0, GTYPE_LIGHT, long_buf, short_buf);
399 putsmap(smap, planet);
400 putplanet(planet, Stars[ship->storbits], (
int)ship->pnumorbits);
402 sprintf(telegram_buf,
"%s", buf);
404 sprintf(buf,
" - %d sectors destroyed.", numdest);
405 strcat(telegram_buf, buf);
407 strcat(telegram_buf,
"\n");
408 for (i = 1; i <= Num_races; i++)
410 warn(i, Stars[ship->storbits]->governor[i - 1], telegram_buf);
411 notify((ship->owner), ship->governor, telegram_buf);
413 kill_ship((ship->owner), &*ship);
423 if (!ship->alive || !ship->owner)
return;
424 if (!ship->on || !ship->retaliate || !ship->destruct)
return;
427 const auto &p = planets[ship->storbits][ship->pnumorbits];
430 while (sh2 && ship->destruct) {
431 if (ships[sh2]->alive &&
432 ((ships[sh2]->type == ShipType::STYPE_MISSILE) ||
433 (ships[sh2]->type == ShipType::STYPE_MINE)) &&
434 (ships[sh2]->owner != ship->owner) &&
435 !(
isset(races[ship->owner - 1]->allied, ships[sh2]->owner) &&
436 isset(races[ships[sh2]->owner - 1]->allied, ship->owner))) {
441 numdest =
MIN(numdest, ship->destruct);
442 numdest =
MIN(numdest, ship->retaliate);
443 ship->destruct -= numdest;
446 push_telegram((
int)(ship->owner), (
int)ship->governor, long_buf);
447 push_telegram((
int)(ships[sh2]->owner), (
int)ships[sh2]->governor,
451 sh2 = ships[sh2]->nextship;
463 if (Shipdata[ship->type][ABIL_REPAIR])
465 else if (ship->docked && ship->whatdest == ScopeLevel::LEVEL_SHIP &&
466 ships[ship->destshipno]->type == ShipType::STYPE_STATION)
468 else if (ship->docked && ship->whatorbits == ScopeLevel::LEVEL_SHIP &&
469 ships[ship->destshipno]->type == ShipType::STYPE_STATION)
472 maxrep *= (
double)(ship->popn) / (
double)ship->max_crew;
473 cost = (
int)(0.005 * maxrep * shipcost(*ship));
475 if (cost <= ship->resource) {
478 ship->damage = std::max(0, (
int)(ship->damage) - drep);
481 drep = (
int)(maxrep * ((
double)ship->resource / (
int)cost));
483 ship->damage = std::max(0, (
int)(ship->damage) - drep);
494 fuse = ship->fuel * ((
double)ship->popn / (
double)ship->max_crew) *
495 (1.0 - .01 * (
double)ship->damage);
496 add = (
int)fuse / 20;
497 if (ship->resource + add > ship->max_resource)
498 add = ship->max_resource - ship->resource;
499 fuse = 20.0 * (
double)add;
505 if (ships[sh]->type == ShipType::OTYPE_WPLANT)
507 sh = ships[sh]->nextship;
510 add = round_rand((
double)ship->popn * races[ship->owner - 1]->birthrate);
511 if (ship->popn + add > max_crew(*ship)) add = max_crew(*ship) - ship->popn;
512 rcv_popn(ship, add, races[ship->owner - 1]->mass);
518 if (ship->whatorbits == ScopeLevel::LEVEL_STAR) {
520 i = int_rand(0, (
int)Stars[ship->storbits]->numplanets - 1);
521 sprintf(telegram_buf,
"%s has warmed and exploded at %s\n",
522 ship_to_string(*ship).c_str(), prin_ship_orbits(ship));
524 sprintf(buf,
"\tmeta-colony established on %s.",
525 Stars[ship->storbits]->pnames[i]);
527 sprintf(buf,
"\tno spores have survived.");
528 strcat(telegram_buf, buf);
529 push_telegram((
int)(ship->owner), (
int)ship->governor, telegram_buf);
530 kill_ship((
int)(ship->owner), ship);
532 ship->special.pod.temperature += round_rand(
533 (
double)Stars[ship->storbits]->temperature / (
double)segments);
534 }
else if (ship->whatorbits == ScopeLevel::LEVEL_PLAN) {
535 if (ship->special.pod.decay >=
POD_DECAY) {
536 sprintf(telegram_buf,
"%s has decayed at %s\n",
537 ship_to_string(*ship).c_str(), prin_ship_orbits(ship));
538 push_telegram((
int)ship->owner, (
int)ship->governor, telegram_buf);
539 kill_ship((
int)ship->owner, ship);
541 ship->special.pod.decay += round_rand(1.0 / (
double)segments);
561 bzero((
char *)Sectinfo,
sizeof(Sectinfo));
562 x = int_rand(0, p->Maxx - 1);
563 y = int_rand(0, p->Maxy - 1);
564 owner = smap.get(x, y).owner;
567 (
double)int_rand(1, 100) >
569 (1.0 - exp(-((
double)(smap.get(x, y).troops *
570 races[owner - 1]->fighters / 50.0)))))) {
571 p->info[who - 1].explored = 1;
572 p->info[who - 1].numsectsowned += 1;
573 smap.get(x, y).troops = 0;
574 smap.get(x, y).popn = races[who - 1]->number_sexes;
575 smap.get(x, y).owner = who;
576 smap.get(x, y).condition = smap.get(x, y).type;
578 smap.get(x, y).condition = races[who - 1]->likesbest;
585 if (ship->whatorbits == ScopeLevel::LEVEL_PLAN && !landed(*ship)) {
586 if (++ship->special.timer.count <
DISSIPATE) {
587 if (Stinfo[ship->storbits][ship->pnumorbits].temp_add < -90)
588 Stinfo[ship->storbits][ship->pnumorbits].temp_add = -100;
590 Stinfo[ship->storbits][ship->pnumorbits].temp_add -= 10;
593 kill_ship((
int)(ship->owner), ship);
594 sprintf(telegram_buf,
595 "Canister of dust previously covering %s has dissipated.\n",
597 for (j = 1; j <= Num_races; j++)
598 if (planets[ship->storbits][ship->pnumorbits]
601 push_telegram(j, (
int)Stars[ship->storbits]->governor[j - 1],
608 if (ship->whatorbits == ScopeLevel::LEVEL_PLAN && !landed(*ship)) {
609 if (++ship->special.timer.count <
DISSIPATE) {
610 if (Stinfo[ship->storbits][ship->pnumorbits].temp_add > 90)
611 Stinfo[ship->storbits][ship->pnumorbits].temp_add = 100;
613 Stinfo[ship->storbits][ship->pnumorbits].temp_add += 10;
617 kill_ship((
int)(ship->owner), ship);
618 sprintf(telegram_buf,
"Greenhouse gases at %s have dissipated.\n",
620 for (j = 1; j <= Num_races; j++)
621 if (planets[ship->storbits][ship->pnumorbits]
624 push_telegram(j, (
int)Stars[ship->storbits]->governor[j - 1],
631 switch (ship->special.aimed_at.level) {
632 case ScopeLevel::LEVEL_SHIP:
634 if ((ship->whatorbits == ScopeLevel::LEVEL_STAR ||
635 ship->whatorbits == ScopeLevel::LEVEL_PLAN) &&
636 (ships[ship->special.aimed_at.shipno] !=
nullptr) &&
637 (ships[ship->special.aimed_at.shipno]->whatorbits ==
638 ScopeLevel::LEVEL_STAR ||
639 ships[ship->special.aimed_at.shipno]->whatorbits ==
640 ScopeLevel::LEVEL_PLAN) &&
641 ship->storbits == ships[ship->special.aimed_at.shipno]->storbits &&
642 ships[ship->special.aimed_at.shipno]->alive) {
646 s = ships[ship->special.aimed_at.shipno];
647 range = sqrt(
Distsq(ship->xpos, ship->ypos, s->xpos, s->ypos));
648 i = int_rand(0, round_rand((2. / ((
double)(shipbody(*s)))) *
649 (
double)(ship->special.aimed_at.intensity) /
651 sprintf(telegram_buf,
"%s aimed at %s\n", ship_to_string(*ship).c_str(),
652 ship_to_string(*s).c_str());
655 sprintf(buf,
"%d%% damage done.\n", i);
656 strcat(telegram_buf, buf);
658 if (s->damage >= 100) {
659 sprintf(buf,
"%s DESTROYED!!!\n", ship_to_string(*s).c_str());
660 strcat(telegram_buf, buf);
661 kill_ship((
int)(ship->owner), s);
663 push_telegram((
int)s->owner, (
int)s->governor, telegram_buf);
664 push_telegram((
int)ship->owner, (
int)ship->governor, telegram_buf);
667 case ScopeLevel::LEVEL_PLAN: {
670 range = sqrt(
Distsq(ship->xpos, ship->ypos,
671 Stars[ship->storbits]->xpos +
672 planets[ship->storbits][ship->pnumorbits]->xpos,
673 Stars[ship->storbits]->ypos +
674 planets[ship->storbits][ship->pnumorbits]->ypos));
676 i =
PLORBITSIZE * ship->special.aimed_at.intensity / range;
678 i = ship->special.aimed_at.intensity;
680 i = round_rand(.01 * (100.0 - (
double)(ship->damage)) * (
double)i);
681 Stinfo[ship->storbits][ship->special.aimed_at.pnum].temp_add += i;
683 case ScopeLevel::LEVEL_STAR: {
686 if (ship->special.aimed_at.snum > 0 &&
687 ship->special.aimed_at.snum < Sdata.numstars &&
688 ship->whatorbits > ScopeLevel::LEVEL_UNIV &&
689 ship->special.aimed_at.snum == ship->storbits)
690 Stars[ship->special.aimed_at.snum]->stability += random() & 01;
692 case ScopeLevel::LEVEL_UNIV:
699 if (races[ship->owner - 1]->God) {
700 ship->fuel = max_fuel(*ship);
701 ship->destruct = max_destruct(*ship);
702 ship->resource = max_resource(*ship);
710 if (landed(*ship) && ship->on) {
715 auto p = planets[ship->storbits][ship->pnumorbits];
716 Race = races[ship->owner - 1];
717 if (ship->fuel >= 3.0) {
721 (
double)(Race->conditions[j] - p->conditions[j]));
722 if (d) p->conditions[j] += d;
724 }
else if (!ship->notified) {
735 if (!(maxcrew = Shipdata[ship->type][ABIL_MAXCREW]))
return 0.0;
736 return ((
double)ship->popn / (
double)maxcrew);
742 x = (
double)p->Maxx * (
double)p->Maxy;
748 if (ship->whatorbits == ScopeLevel::LEVEL_PLAN)
749 Stinfo[ship->storbits][ship->pnumorbits].intimidated = 1;
755 maxrate = (
int)(races[ship->owner - 1]->tech / 2.0);
759 (1. - .01 * (
double)ship->damage) * (
double)ship->popn /
760 (
double)ship->max_crew);
761 rate = std::min(rate, maxrate);
void use_fuel(Ship *s, double amt)
#define Distsq(x1, y1, x2, y2)
void post(const char *origmsg, int type)
static double ap_planet_factor(Planet *)
static void do_god(Ship *)
int retal_strength(Ship *s)
void rcv_resource(Ship *s, int amt)
static void do_ap(Ship *)
void PermuteSects(const Planet &planet)
static void do_meta_infect(int, Planet *)
int do_weapon_plant(Ship *)
static void do_canister(Ship *)
int shoot_ship_to_ship(Ship *, Ship *, int, int, int, char *, char *)
int shoot_ship_to_planet(Ship *, Planet *, int, int, int, SectorMap &, int, int, char *, char *)
static void do_pod(Ship *)
static void do_repair(Ship *)
char * prin_ship_orbits(Ship *s)
static int infect_planet(int, int, int)
void putsmap(SectorMap &map, Planet &p)
#define SPORE_SUCCESS_RATE
static void do_habitat(Ship *)
void use_resource(Ship *s, int amt)
void moveship(Ship *, int, int, int)
static void do_mirror(Ship *)
SectorMap getsmap(const Planet &p)
void rcv_destruct(Ship *s, int amt)
static void do_oap(Ship *)
#define STRIKE_DISTANCE_FACTOR
static double crew_factor(Ship *)
static void do_greenhouse(Ship *)