14 #include "gb/GB_server.h" 15 #include "gb/buffers.h" 16 #include "gb/config.h" 17 #include "gb/doship.h" 19 #include "gb/files_shl.h" 20 #include "gb/getplace.h" 24 #include "gb/shlmisc.h" 25 #include "gb/shootblast.h" 27 #include "gb/tweakables.h" 28 #include "gb/utils/rand.h" 37 Shiplist shiplist(shipno);
38 for (
const auto &ship : shiplist) {
39 if (ship.alive && ship.type == ShipType::OTYPE_PLANDEF &&
40 ship.owner != Playernum) {
49 void fire(
const command_t &argv, GameObj &g) {
50 player_t Playernum = g.player;
51 governor_t Governor = g.governor;
55 if (argv[0] ==
"fire-from-dock") {
60 }
else if (argv[0] ==
"cew") {
81 bzero((
char *)Nuked,
sizeof(Nuked));
83 if (argv.size() < 3) {
85 "Syntax: '" + argv[0] +
" <ship> <target> [<strength>]'.\n";
86 notify(Playernum, Governor, msg);
90 nextshipno = start_shiplist(g, argv[1]);
92 if (in_list(Playernum, argv[1], *from, &nextshipno) &&
93 authorized(Governor, *from)) {
95 sprintf(buf,
"%s is irradiated and inactive.\n",
96 ship_to_string(*from).c_str());
97 notify(Playernum, Governor, buf);
101 if (from->whatorbits == ScopeLevel::LEVEL_UNIV) {
102 if (!
enufAP(Playernum
, Governor
, Sdata.AP[Playernum - 1]
, APcount
)) {
107 Stars[from->storbits]->AP[Playernum - 1]
, APcount
)) {
113 notify(Playernum, Governor,
114 "That ship is not equipped to fire CEWs.\n");
118 if (!from->mounted) {
119 notify(Playernum, Governor,
120 "You need to have a crystal mounted to fire CEWs.\n");
125 auto toshiptmp = string_to_shipnum(argv[1]);
126 if (!toshiptmp || *toshiptmp <= 0) {
127 g.out <<
"Bad ship number.\n";
132 if (toship == fromship) {
133 g.out <<
"Get real.\n";
137 auto to = getship(toship);
143 check_retal_strength(&*to, &retal);
144 bcopy(&*to, &dummy,
sizeof(Ship));
146 if (from->type == ShipType::OTYPE_AFV) {
147 if (!landed(*from)) {
148 sprintf(buf,
"%s isn't landed on a planet!\n",
149 ship_to_string(*from).c_str());
150 notify(Playernum, Governor, buf);
155 sprintf(buf,
"%s isn't landed on a planet!\n",
156 ship_to_string(*from).c_str());
157 notify(Playernum, Governor, buf);
162 if (landed(*from) && landed(*to)) {
163 if ((from->storbits != to->storbits) ||
164 (from->pnumorbits != to->pnumorbits)) {
165 notify(Playernum, Governor,
166 "Landed ships can only attack other " 167 "landed ships if they are on the same " 172 const auto p =
getplanet(from->storbits
, from->pnumorbits
);
173 if (!adjacent((
int)from->land_x, (
int)from->land_y, (
int)to->land_x,
174 (
int)to->land_y, p)) {
175 g.out <<
"You are not adjacent to your target!\n";
181 if (from->fuel < (
double)from->cew) {
182 sprintf(buf,
"You need %d fuel to fire CEWs.\n", from->cew);
183 notify(Playernum, Governor, buf);
187 if (landed(*from) || landed(*to)) {
188 notify(Playernum, Governor,
189 "CEWs cannot originate from or targeted " 190 "to ships landed on planets.\n");
194 sprintf(buf,
"CEW strength %d.\n", from->cew);
195 notify(Playernum, Governor, buf);
196 strength = from->cew / 2;
201 if (argv.size() >= 4)
202 strength = std::stoi(argv[3]);
206 if (strength > maxstrength) {
207 strength = maxstrength;
208 sprintf(buf,
"%s set to %d\n",
209 laser_on(*from) ?
"Laser strength" :
"Guns", strength);
210 notify(Playernum, Governor, buf);
218 sprintf(buf,
"No attack.\n");
219 notify(Playernum, Governor, buf);
226 shoot_ship_to_ship(from, &*to, strength, cew, 0, long_buf, short_buf);
229 g.out <<
"Illegal attack.\n";
234 if (laser_on(*from) || cew)
240 notify_star(Playernum, Governor, from->storbits, short_buf);
241 warn(to->owner, to->governor, long_buf);
242 notify(Playernum, Governor, long_buf);
246 if (retal && damage && to->protect.self) {
248 if (laser_on(*to)) check_overload(&*to, 0, &strength);
253 use_fuel(&*to, 2.0 * (
double)strength);
255 use_destruct(&*to, strength);
257 notify_star(Playernum, Governor, from->storbits, short_buf);
258 notify(Playernum, Governor, long_buf);
259 warn(to->owner, to->governor, long_buf);
264 if (damage && from->alive && from->type != ShipType::OTYPE_AFV) {
265 if (to->whatorbits == ScopeLevel::LEVEL_STAR)
266 sh = Stars[to->storbits]->ships;
267 if (to->whatorbits == ScopeLevel::LEVEL_PLAN) {
268 const auto p = getplanet(to->storbits, to->pnumorbits);
271 Shiplist shiplist(sh);
272 for (
auto &ship : shiplist) {
273 if (!from->alive)
break;
274 if (ship.protect.on && (ship.protect.ship == toship) &&
275 (ship.protect.ship == toship) && ship.number != fromship &&
276 ship.number != toship && ship.alive && ship.active) {
281 long_buf
, short_buf
)) >= 0) {
287 notify_star(Playernum, Governor, from->storbits, short_buf);
288 notify(Playernum, Governor, long_buf);
289 warn(ship.owner, ship.governor, long_buf);
305 void bombard(
const command_t &argv, GameObj &g) {
306 int Playernum = g.player;
307 int Governor = g.governor;
310 shipnum_t nextshipno;
322 bzero((
char *)Nuked,
sizeof(Nuked));
324 if (argv.size() < 2) {
325 notify(Playernum, Governor,
326 "Syntax: 'bombard <ship> [<x,y> [<strength>]]'.\n");
330 nextshipno = start_shiplist(g, argv[1]);
332 if (in_list(Playernum, argv[1], *from, &nextshipno) &&
333 authorized(Governor, *from)) {
335 sprintf(buf,
"%s is irradiated and inactive.\n",
336 ship_to_string(*from).c_str());
337 notify(Playernum, Governor, buf);
342 if (from->whatorbits != ScopeLevel::LEVEL_PLAN) {
343 notify(Playernum, Governor,
344 "You must be in orbit around a planet to bombard.\n");
348 if (from->type == ShipType::OTYPE_AFV && !landed(*from)) {
349 g.out <<
"This ship is not landed on the planet.\n";
353 if (!
enufAP(Playernum
, Governor
, Stars[from->storbits]->AP[Playernum - 1]
, 362 strength = std::stoi(argv[3]);
366 if (strength > maxstrength) {
367 strength = maxstrength;
368 sprintf(buf,
"%s set to %d\n",
369 laser_on(*from) ?
"Laser strength" :
"Guns", strength);
370 notify(Playernum, Governor, buf);
377 sprintf(buf,
"No attack.\n");
378 notify(Playernum, Governor, buf);
385 auto p =
getplanet((
int)from->storbits
, (
int)from->pnumorbits
);
387 if (argv.size() > 2) {
388 sscanf(argv[2].c_str(),
"%d,%d", &x, &y);
389 if (x < 0 || x > p.Maxx - 1 || y < 0 || y > p.Maxy - 1) {
390 g.out <<
"Illegal sector.\n";
395 x = int_rand(0, (
int)p.Maxx - 1);
396 y = int_rand(0, (
int)p.Maxy - 1);
400 g.out <<
"You are not adjacent to that sector.\n";
407 if (has_defense && !landed(*from)) {
408 g.out <<
"Target has planetary defense networks.\n";
409 g.out <<
"These have to be eliminated before you can attack sectors.\n";
416 long_buf
, short_buf
);
420 g.out <<
"Illegal attack.\n";
431 notify_star(Playernum, Governor, from->storbits, short_buf);
432 for (i = 1; i <= Num_races; i++)
434 warn(i, Stars[from->storbits]->governor[i - 1], long_buf);
435 notify(Playernum, Governor, long_buf);
439 if (numdest && from->type != ShipType::OTYPE_AFV) {
441 for (i = 1; i <= Num_races; i++)
442 if (Nuked[i - 1] && !p.slaved_to) {
444 alien = races[i - 1];
445 strength =
MIN(p.info[i - 1].destruct, p.info[i - 1].guns);
447 p.info[i - 1].destruct -= strength;
451 warn(i, Stars[from->storbits]->governor[i - 1], long_buf);
452 notify(Playernum, Governor, long_buf);
454 notify_star(Playernum, Governor, from->storbits, short_buf);
461 if (numdest && from->alive && from->type != ShipType::OTYPE_AFV) {
462 Shiplist shiplist(p.ships);
463 for (
auto ship : shiplist) {
464 if (ship.protect.planet && ship.number != fromship && ship.alive &&
471 long_buf
, short_buf
)) >= 0) {
477 notify_star(Playernum, Governor, from->storbits, short_buf);
478 warn(ship.owner, ship.governor, long_buf);
479 notify(Playernum, Governor, long_buf);
482 if (!from->alive)
break;
498 void defend(
const command_t &argv, GameObj &g) {
499 player_t Playernum = g.player;
500 governor_t Governor = g.governor;
515 bzero((
char *)Nuked,
sizeof(Nuked));
518 if (g.level != ScopeLevel::LEVEL_PLAN) {
519 g.out <<
"You have to set scope to the planet first.\n";
523 if (argv.size() < 3) {
524 notify(Playernum, Governor,
525 "Syntax: 'defend <ship> <sector> [<strength>]'.\n");
528 if (Governor && Stars[g.snum]->governor[Playernum - 1] != Governor) {
529 notify(Playernum, Governor,
530 "You are not authorized to do that in this system.\n");
533 auto toshiptmp = string_to_shipnum(argv[1]);
534 if (!toshiptmp || *toshiptmp <= 0) {
535 g.out <<
"Bad ship number.\n";
540 if (!
enufAP(Playernum
, Governor
, Stars[g.snum]->AP[Playernum - 1]
, APcount
)) {
546 if (!p.info[Playernum - 1].numsectsowned) {
547 g.out <<
"You do not occupy any sectors here.\n";
551 if (p.slaved_to && p.slaved_to != Playernum) {
552 g.out <<
"This planet is enslaved.\n";
556 auto to = getship(toship);
561 if (to->whatorbits != ScopeLevel::LEVEL_PLAN) {
562 g.out <<
"The ship is not in planet orbit.\n";
566 if (to->storbits != g.snum || to->pnumorbits != g.pnum) {
567 g.out <<
"Target is not in orbit around this planet.\n";
572 g.out <<
"Planet guns can't fire on landed ships.\n";
577 check_retal_strength(&*to, &retal);
578 bcopy(&*to, &dummy,
sizeof(Ship));
580 sscanf(argv[2].c_str(),
"%d,%d", &x, &y);
582 if (x < 0 || x > p.Maxx - 1 || y < 0 || y > p.Maxy - 1) {
583 g.out <<
"Illegal sector.\n";
589 if (sect.owner != Playernum) {
590 g.out <<
"Nice try.\n";
594 if (argv.size() >= 4)
595 strength = std::stoi(argv[3]);
597 strength = p.info[Playernum - 1].guns;
599 strength =
MIN(strength, p.info[Playernum - 1].destruct);
600 strength =
MIN(strength, p.info[Playernum - 1].guns);
603 sprintf(buf,
"No attack - %d guns, %dd\n", p.info[Playernum - 1].guns,
604 p.info[Playernum - 1].destruct);
605 notify(Playernum, Governor, buf);
608 Race = races[Playernum - 1];
610 damage = shoot_planet_to_ship(Race, &*to, strength, long_buf, short_buf);
612 if (!to->alive && to->type == ShipType::OTYPE_TOXWC) {
618 sprintf(buf,
"Target out of range %d!\n",
SYSTEMSIZE);
619 notify(Playernum, Governor, buf);
623 p.info[Playernum - 1].destruct -= strength;
625 notify_star(Playernum, Governor, to->storbits, short_buf);
626 warn(to->owner, to->governor, long_buf);
627 notify(Playernum, Governor, long_buf);
632 if (retal && damage && to->protect.self) {
634 if (laser_on(*to)) check_overload(&*to, 0, &strength);
638 long_buf
, short_buf
)) >= 0) {
640 use_fuel(&*to, 2.0 * (
double)strength);
642 use_destruct(&*to, strength);
645 notify_star(Playernum, Governor, to->storbits, short_buf);
646 notify(Playernum, Governor, long_buf);
647 warn(to->owner, to->governor, long_buf);
656 (
void)getship(&ship, sh);
657 if (ship->protect.on && (ship->protect.ship == toship) &&
658 (ship->protect.ship == toship) && sh != toship && ship->alive &&
665 0
, long_buf
, short_buf
)) >= 0) {
671 notify_star(Playernum, Governor, ship->storbits, short_buf);
672 notify(Playernum, Governor, long_buf);
673 warn(ship->owner, ship->governor, long_buf);
692 const player_t Playernum = g.player;
693 const governor_t Governor = g.governor;
695 if (argv.size() < 3) {
696 std::string msg =
"Syntax: '" + argv[0] +
" <mine>'\n";
697 notify(Playernum, Governor, msg);
703 shipnum_t nextshipno;
705 nextshipno = start_shiplist(g, argv[1]);
708 if (in_list(Playernum, argv[1], *s, &nextshipno) &&
709 authorized(Governor, *s)) {
710 if (s->type != ShipType::STYPE_MINE) {
711 g.out <<
"That is not a mine.\n";
716 g.out <<
"The mine is not activated.\n";
720 if (s->docked || s->whatorbits == ScopeLevel::LEVEL_SHIP) {
721 g.out <<
"The mine is docked or landed.\n";
735 if (!s->alive)
return 0;
736 if (!Shipdata[s->type][ABIL_SPEED] && !landed(*s))
return 0;
738 if (!s->popn && (s->type != ShipType::OTYPE_BERS))
return 0;
741 avail = (s->type == ShipType::STYPE_FIGHTER ||
742 s->type == ShipType::OTYPE_AFV || s->type == ShipType::OTYPE_BERS)
744 :
MIN(s->popn, s->primary);
746 avail = (s->type == ShipType::STYPE_FIGHTER ||
747 s->type == ShipType::OTYPE_AFV || s->type == ShipType::OTYPE_BERS)
749 :
MIN(s->popn, s->secondary);
753 avail =
MIN(s->retaliate, avail);
754 strength =
MIN(s->destruct, avail);
758 int adjacent(
int fx,
int fy,
int tx,
int ty,
const Planet &p) {
759 if (abs(fy - ty) <= 1) {
760 if (abs(fx - tx) <= 1)
return 1;
761 if (fx == p.Maxx - 1 && tx == 0)
return 1;
762 if (fx == 0 && tx == p.Maxx - 1)
return 1;
770 if ((ship->laser && ship->fire_laser) || cew) {
771 if (int_rand(0, *strength) >
772 (
int)((1.0 - .01 * ship->damage) * ship->tech / 2.0)) {
775 "%s: Matter-antimatter EXPLOSION from overloaded crystal on %s\n",
776 Dispshiploc(ship), ship_to_string(*ship).c_str());
777 kill_ship((
int)(ship->owner), ship);
779 warn(ship->owner, ship->governor, buf);
781 notify_star(ship->owner, ship->governor, ship->storbits, buf);
782 }
else if (int_rand(0, *strength) >
783 (
int)((1.0 - .01 * ship->damage) * ship->tech / 4.0)) {
784 sprintf(buf,
"%s: Crystal damaged from overloading on %s.\n",
785 Dispshiploc(ship), ship_to_string(*ship).c_str());
786 ship->fire_laser = 0;
789 warn(ship->owner, ship->governor, buf);
796 if (ship->active && ship->alive) {
798 *strength =
MIN(ship->fire_laser, (
int)ship->fuel / 2);
void use_fuel(Ship *s, double amt)
void post(const char *origmsg, int type)
int retal_strength(Ship *s)
void detonate(const command_t &argv, GameObj &g)
Planet getplanet(const starnum_t star, const planetnum_t pnum)
void fire(const command_t &argv, GameObj &g)
void defend(const command_t &argv, GameObj &g)
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 *)
bool has_planet_defense(const shipnum_t shipno, const player_t Playernum)
static void check_overload(Ship *, int, int *)
static void check_retal_strength(Ship *, int *)
void putsmap(SectorMap &map, Planet &p)
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)
int shoot_planet_to_ship(Race *, Ship *, int, char *, char *)
void use_destruct(Ship *s, int amt)
shipnum_t do_shiplist(Ship **s, shipnum_t *nextshipno)
void putplanet(const Planet &p, startype *star, const int pnum)
SectorMap getsmap(const Planet &p)
int adjacent(int fx, int fy, int tx, int ty, const Planet &p)
Sector getsector(const Planet &p, const int x, const int y)
void bombard(const command_t &argv, GameObj &g)