Galactic Bloodshed
fire.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 /// \file fire.c
6 /// \brief Fire at ship or planet from ship or planet
7 
8 #include "gb/fire.h"
9 
10 #include <cstdio>
11 #include <cstdlib>
12 #include <cstring>
13 
14 #include "gb/GB_server.h"
15 #include "gb/buffers.h"
16 #include "gb/config.h"
17 #include "gb/doship.h"
18 #include "gb/files.h"
19 #include "gb/files_shl.h"
20 #include "gb/getplace.h"
21 #include "gb/load.h"
22 #include "gb/races.h"
23 #include "gb/ships.h"
24 #include "gb/shlmisc.h"
25 #include "gb/shootblast.h"
26 #include "gb/tele.h"
27 #include "gb/tweakables.h"
28 #include "gb/utils/rand.h"
29 #include "gb/vars.h"
30 
31 static void check_overload(Ship *, int, int *);
32 static void check_retal_strength(Ship *, int *);
33 
34 namespace {
35 // check to see if there are any planetary defense networks on the planet
36 bool has_planet_defense(const shipnum_t shipno, const player_t Playernum) {
37  Shiplist shiplist(shipno);
38  for (const auto &ship : shiplist) {
39  if (ship.alive && ship.type == ShipType::OTYPE_PLANDEF &&
40  ship.owner != Playernum) {
41  return true;
42  }
43  }
44  return false;
45 }
46 } // namespace
47 
48 /*! Ship vs ship */
49 void fire(const command_t &argv, GameObj &g) {
50  player_t Playernum = g.player;
51  governor_t Governor = g.governor;
52  int APcount;
53  int cew;
54  // This is called from dock.cc.
55  if (argv[0] == "fire-from-dock") {
56  // TODO(jeffbailey): It's not clear that cew is ever used as anything other
57  // than a true/false value.
58  cew = 3;
59  APcount = 0;
60  } else if (argv[0] == "cew") {
61  cew = 1;
62  APcount = 1;
63  } else { // argv[0] = fire
64  cew = 0;
65  APcount = 1;
66  }
67  shipnum_t fromship;
68  shipnum_t toship;
69  shipnum_t sh;
70  shipnum_t nextshipno;
71  Ship *from;
72  Ship dummy;
73  int strength;
74  int maxstrength;
75  int retal;
76  int damage;
77 
78  sh = 0; // TODO(jeffbailey): No idea what this is, init to 0.
79 
80  /* for telegramming and retaliating */
81  bzero((char *)Nuked, sizeof(Nuked));
82 
83  if (argv.size() < 3) {
84  std::string msg =
85  "Syntax: '" + argv[0] + " <ship> <target> [<strength>]'.\n";
86  notify(Playernum, Governor, msg);
87  return;
88  }
89 
90  nextshipno = start_shiplist(g, argv[1]);
91  while ((fromship = do_shiplist(&from, &nextshipno)))
92  if (in_list(Playernum, argv[1], *from, &nextshipno) &&
93  authorized(Governor, *from)) {
94  if (!from->active) {
95  sprintf(buf, "%s is irradiated and inactive.\n",
96  ship_to_string(*from).c_str());
97  notify(Playernum, Governor, buf);
98  free(from);
99  continue;
100  }
101  if (from->whatorbits == ScopeLevel::LEVEL_UNIV) {
102  if (!enufAP(Playernum, Governor, Sdata.AP[Playernum - 1], APcount)) {
103  free(from);
104  continue;
105  }
106  } else if (!enufAP(Playernum, Governor,
107  Stars[from->storbits]->AP[Playernum - 1], APcount)) {
108  free(from);
109  continue;
110  }
111  if (cew) {
112  if (!from->cew) {
113  notify(Playernum, Governor,
114  "That ship is not equipped to fire CEWs.\n");
115  free(from);
116  continue;
117  }
118  if (!from->mounted) {
119  notify(Playernum, Governor,
120  "You need to have a crystal mounted to fire CEWs.\n");
121  free(from);
122  continue;
123  }
124  }
125  auto toshiptmp = string_to_shipnum(argv[1]);
126  if (!toshiptmp || *toshiptmp <= 0) {
127  g.out << "Bad ship number.\n";
128  free(from);
129  return;
130  }
131  toship = *toshiptmp;
132  if (toship == fromship) {
133  g.out << "Get real.\n";
134  free(from);
135  continue;
136  }
137  auto to = getship(toship);
138  if (!to) {
139  continue;
140  }
141 
142  /* save defense attack strength for retaliation */
143  check_retal_strength(&*to, &retal);
144  bcopy(&*to, &dummy, sizeof(Ship));
145 
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);
151  free(from);
152  continue;
153  }
154  if (!landed(*to)) {
155  sprintf(buf, "%s isn't landed on a planet!\n",
156  ship_to_string(*from).c_str());
157  notify(Playernum, Governor, buf);
158  free(from);
159  continue;
160  }
161  }
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 "
168  "planet!\n");
169  free(from);
170  continue;
171  }
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";
176  free(from);
177  continue;
178  }
179  }
180  if (cew) {
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);
184  free(from);
185  continue;
186  }
187  if (landed(*from) || landed(*to)) {
188  notify(Playernum, Governor,
189  "CEWs cannot originate from or targeted "
190  "to ships landed on planets.\n");
191  free(from);
192  continue;
193  }
194  sprintf(buf, "CEW strength %d.\n", from->cew);
195  notify(Playernum, Governor, buf);
196  strength = from->cew / 2;
197 
198  } else {
199  check_retal_strength(from, &maxstrength);
200 
201  if (argv.size() >= 4)
202  strength = std::stoi(argv[3]);
203  else
204  check_retal_strength(from, &strength);
205 
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);
211  }
212  }
213 
214  /* check to see if there is crystal overloads */
215  if (laser_on(*from) || cew) check_overload(from, cew, &strength);
216 
217  if (strength <= 0) {
218  sprintf(buf, "No attack.\n");
219  notify(Playernum, Governor, buf);
220  putship(from);
221  free(from);
222  continue;
223  }
224 
225  damage =
226  shoot_ship_to_ship(from, &*to, strength, cew, 0, long_buf, short_buf);
227 
228  if (damage < 0) {
229  g.out << "Illegal attack.\n";
230  free(from);
231  continue;
232  }
233 
234  if (laser_on(*from) || cew)
235  use_fuel(from, 2.0 * (double)strength);
236  else
237  use_destruct(from, strength);
238 
239  if (!to->alive) post(short_buf, COMBAT);
240  notify_star(Playernum, Governor, from->storbits, short_buf);
241  warn(to->owner, to->governor, long_buf);
242  notify(Playernum, Governor, long_buf);
243  /* defending ship retaliates */
244 
245  strength = 0;
246  if (retal && damage && to->protect.self) {
247  strength = retal;
248  if (laser_on(*to)) check_overload(&*to, 0, &strength);
249 
250  if ((damage = shoot_ship_to_ship(&dummy, from, strength, 0, 1, long_buf,
251  short_buf)) >= 0) {
252  if (laser_on(*to))
253  use_fuel(&*to, 2.0 * (double)strength);
254  else
255  use_destruct(&*to, strength);
256  if (!from->alive) post(short_buf, COMBAT);
257  notify_star(Playernum, Governor, from->storbits, short_buf);
258  notify(Playernum, Governor, long_buf);
259  warn(to->owner, to->governor, long_buf);
260  }
261  }
262  /* protecting ships retaliate individually if damage was inflicted */
263  /* AFVs immune to retaliation of this type */
264  if (damage && from->alive && from->type != ShipType::OTYPE_AFV) {
265  if (to->whatorbits == ScopeLevel::LEVEL_STAR) /* star level ships */
266  sh = Stars[to->storbits]->ships;
267  if (to->whatorbits == ScopeLevel::LEVEL_PLAN) { /* planet level ships */
268  const auto p = getplanet(to->storbits, to->pnumorbits);
269  sh = p.ships;
270  }
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) {
277  check_retal_strength(&ship, &strength);
278  if (laser_on(ship)) check_overload(&ship, 0, &strength);
279 
280  if ((damage = shoot_ship_to_ship(&ship, from, strength, 0, 0,
281  long_buf, short_buf)) >= 0) {
282  if (laser_on(ship))
283  use_fuel(&ship, 2.0 * (double)strength);
284  else
285  use_destruct(&ship, strength);
286  if (!from->alive) post(short_buf, COMBAT);
287  notify_star(Playernum, Governor, from->storbits, short_buf);
288  notify(Playernum, Governor, long_buf);
289  warn(ship.owner, ship.governor, long_buf);
290  }
291  putship(&ship);
292  }
293  }
294  }
295  putship(from);
296  putship(&*to);
297  deductAPs(Playernum, Governor, APcount, (int)from->storbits, 0);
298 
299  free(from);
300  } else
301  free(from);
302 }
303 
304 /*! Ship vs planet */
305 void bombard(const command_t &argv, GameObj &g) {
306  int Playernum = g.player;
307  int Governor = g.governor;
308  int APcount = 1;
309  shipnum_t fromship;
310  shipnum_t nextshipno;
311  Ship *from;
312  int strength;
313  int maxstrength;
314  int x;
315  int y;
316  int numdest;
317  int damage;
318  int i;
319  racetype *alien;
320 
321  /* for telegramming and retaliating */
322  bzero((char *)Nuked, sizeof(Nuked));
323 
324  if (argv.size() < 2) {
325  notify(Playernum, Governor,
326  "Syntax: 'bombard <ship> [<x,y> [<strength>]]'.\n");
327  return;
328  }
329 
330  nextshipno = start_shiplist(g, argv[1]);
331  while ((fromship = do_shiplist(&from, &nextshipno)))
332  if (in_list(Playernum, argv[1], *from, &nextshipno) &&
333  authorized(Governor, *from)) {
334  if (!from->active) {
335  sprintf(buf, "%s is irradiated and inactive.\n",
336  ship_to_string(*from).c_str());
337  notify(Playernum, Governor, buf);
338  free(from);
339  continue;
340  }
341 
342  if (from->whatorbits != ScopeLevel::LEVEL_PLAN) {
343  notify(Playernum, Governor,
344  "You must be in orbit around a planet to bombard.\n");
345  free(from);
346  continue;
347  }
348  if (from->type == ShipType::OTYPE_AFV && !landed(*from)) {
349  g.out << "This ship is not landed on the planet.\n";
350  free(from);
351  continue;
352  }
353  if (!enufAP(Playernum, Governor, Stars[from->storbits]->AP[Playernum - 1],
354  APcount)) {
355  free(from);
356  continue;
357  }
358 
359  check_retal_strength(from, &maxstrength);
360 
361  if (argv.size() > 3)
362  strength = std::stoi(argv[3]);
363  else
364  check_retal_strength(from, &strength);
365 
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);
371  }
372 
373  /* check to see if there is crystal overload */
374  if (laser_on(*from)) check_overload(from, 0, &strength);
375 
376  if (strength <= 0) {
377  sprintf(buf, "No attack.\n");
378  notify(Playernum, Governor, buf);
379  putship(from);
380  free(from);
381  continue;
382  }
383 
384  /* get planet */
385  auto p = getplanet((int)from->storbits, (int)from->pnumorbits);
386 
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";
391  free(from);
392  continue;
393  }
394  } else {
395  x = int_rand(0, (int)p.Maxx - 1);
396  y = int_rand(0, (int)p.Maxy - 1);
397  }
398  if (landed(*from) &&
399  !adjacent((int)from->land_x, (int)from->land_y, x, y, p)) {
400  g.out << "You are not adjacent to that sector.\n";
401  free(from);
402  continue;
403  }
404 
405  bool has_defense = has_planet_defense(p.ships, Playernum);
406 
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";
410  free(from);
411  continue;
412  }
413 
414  auto smap = getsmap(p);
415  numdest = shoot_ship_to_planet(from, &p, strength, x, y, smap, 0, 0,
416  long_buf, short_buf);
417  putsmap(smap, p);
418 
419  if (numdest < 0) {
420  g.out << "Illegal attack.\n";
421  free(from);
422  continue;
423  }
424 
425  if (laser_on(*from))
426  use_fuel(from, 2.0 * (double)strength);
427  else
428  use_destruct(from, strength);
429 
430  post(short_buf, COMBAT);
431  notify_star(Playernum, Governor, from->storbits, short_buf);
432  for (i = 1; i <= Num_races; i++)
433  if (Nuked[i - 1])
434  warn(i, Stars[from->storbits]->governor[i - 1], long_buf);
435  notify(Playernum, Governor, long_buf);
436 
437 #ifdef DEFENSE
438  /* planet retaliates - AFVs are immune to this */
439  if (numdest && from->type != ShipType::OTYPE_AFV) {
440  damage = 0;
441  for (i = 1; i <= Num_races; i++)
442  if (Nuked[i - 1] && !p.slaved_to) {
443  /* add planet defense strength */
444  alien = races[i - 1];
445  strength = MIN(p.info[i - 1].destruct, p.info[i - 1].guns);
446 
447  p.info[i - 1].destruct -= strength;
448 
449  damage = shoot_planet_to_ship(alien, from, strength, long_buf,
450  short_buf);
451  warn(i, Stars[from->storbits]->governor[i - 1], long_buf);
452  notify(Playernum, Governor, long_buf);
453  if (!from->alive) post(short_buf, COMBAT);
454  notify_star(Playernum, Governor, from->storbits, short_buf);
455  }
456  }
457 #endif
458 
459  /* protecting ships retaliate individually if damage was inflicted */
460  /* AFVs are immune to this */
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 &&
465  ship.active) {
466  if (laser_on(ship)) check_overload(&ship, 0, &strength);
467 
468  check_retal_strength(&ship, &strength);
469 
470  if ((damage = shoot_ship_to_ship(&ship, from, strength, 0, 0,
471  long_buf, short_buf)) >= 0) {
472  if (laser_on(ship))
473  use_fuel(&ship, 2.0 * (double)strength);
474  else
475  use_destruct(&ship, strength);
476  if (!from->alive) post(short_buf, COMBAT);
477  notify_star(Playernum, Governor, from->storbits, short_buf);
478  warn(ship.owner, ship.governor, long_buf);
479  notify(Playernum, Governor, long_buf);
480  }
481  }
482  if (!from->alive) break;
483  }
484  }
485 
486  /* write the stuff to disk */
487  putship(from);
488  putplanet(p, Stars[from->storbits], (int)from->pnumorbits);
489  deductAPs(Playernum, Governor, APcount, (int)from->storbits, 0);
490 
491  free(from);
492  } else
493  free(from);
494 }
495 
496 #ifdef DEFENSE
497 /*! Planet vs ship */
498 void defend(const command_t &argv, GameObj &g) {
499  player_t Playernum = g.player;
500  governor_t Governor = g.governor;
501  int APcount = 1;
502  int toship;
503  int sh;
504  Ship *ship;
505  Ship dummy;
506  int strength;
507  int retal;
508  int damage;
509  int x;
510  int y;
511  int numdest;
512  racetype *Race;
513 
514  /* for telegramming and retaliating */
515  bzero((char *)Nuked, sizeof(Nuked));
516 
517  /* get the planet from the players current scope */
518  if (g.level != ScopeLevel::LEVEL_PLAN) {
519  g.out << "You have to set scope to the planet first.\n";
520  return;
521  }
522 
523  if (argv.size() < 3) {
524  notify(Playernum, Governor,
525  "Syntax: 'defend <ship> <sector> [<strength>]'.\n");
526  return;
527  }
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");
531  return;
532  }
533  auto toshiptmp = string_to_shipnum(argv[1]);
534  if (!toshiptmp || *toshiptmp <= 0) {
535  g.out << "Bad ship number.\n";
536  return;
537  }
538  toship = *toshiptmp;
539 
540  if (!enufAP(Playernum, Governor, Stars[g.snum]->AP[Playernum - 1], APcount)) {
541  return;
542  }
543 
544  auto p = getplanet(g.snum, g.pnum);
545 
546  if (!p.info[Playernum - 1].numsectsowned) {
547  g.out << "You do not occupy any sectors here.\n";
548  return;
549  }
550 
551  if (p.slaved_to && p.slaved_to != Playernum) {
552  g.out << "This planet is enslaved.\n";
553  return;
554  }
555 
556  auto to = getship(toship);
557  if (!to) {
558  return;
559  }
560 
561  if (to->whatorbits != ScopeLevel::LEVEL_PLAN) {
562  g.out << "The ship is not in planet orbit.\n";
563  return;
564  }
565 
566  if (to->storbits != g.snum || to->pnumorbits != g.pnum) {
567  g.out << "Target is not in orbit around this planet.\n";
568  return;
569  }
570 
571  if (landed(*to)) {
572  g.out << "Planet guns can't fire on landed ships.\n";
573  return;
574  }
575 
576  /* save defense strength for retaliation */
577  check_retal_strength(&*to, &retal);
578  bcopy(&*to, &dummy, sizeof(Ship));
579 
580  sscanf(argv[2].c_str(), "%d,%d", &x, &y);
581 
582  if (x < 0 || x > p.Maxx - 1 || y < 0 || y > p.Maxy - 1) {
583  g.out << "Illegal sector.\n";
584  return;
585  }
586 
587  /* check to see if you own the sector */
588  auto sect = getsector(p, x, y);
589  if (sect.owner != Playernum) {
590  g.out << "Nice try.\n";
591  return;
592  }
593 
594  if (argv.size() >= 4)
595  strength = std::stoi(argv[3]);
596  else
597  strength = p.info[Playernum - 1].guns;
598 
599  strength = MIN(strength, p.info[Playernum - 1].destruct);
600  strength = MIN(strength, p.info[Playernum - 1].guns);
601 
602  if (strength <= 0) {
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);
606  return;
607  }
608  Race = races[Playernum - 1];
609 
610  damage = shoot_planet_to_ship(Race, &*to, strength, long_buf, short_buf);
611 
612  if (!to->alive && to->type == ShipType::OTYPE_TOXWC) {
613  /* get planet again since toxicity probably has changed */
614  p = getplanet(g.snum, g.pnum);
615  }
616 
617  if (damage < 0) {
618  sprintf(buf, "Target out of range %d!\n", SYSTEMSIZE);
619  notify(Playernum, Governor, buf);
620  return;
621  }
622 
623  p.info[Playernum - 1].destruct -= strength;
624  if (!to->alive) post(short_buf, COMBAT);
625  notify_star(Playernum, Governor, to->storbits, short_buf);
626  warn(to->owner, to->governor, long_buf);
627  notify(Playernum, Governor, long_buf);
628 
629  /* defending ship retaliates */
630 
631  strength = 0;
632  if (retal && damage && to->protect.self) {
633  strength = retal;
634  if (laser_on(*to)) check_overload(&*to, 0, &strength);
635 
636  auto smap = getsmap(p);
637  if ((numdest = shoot_ship_to_planet(&dummy, &p, strength, x, y, smap, 0, 0,
638  long_buf, short_buf)) >= 0) {
639  if (laser_on(*to))
640  use_fuel(&*to, 2.0 * (double)strength);
641  else
642  use_destruct(&*to, strength);
643 
644  post(short_buf, COMBAT);
645  notify_star(Playernum, Governor, to->storbits, short_buf);
646  notify(Playernum, Governor, long_buf);
647  warn(to->owner, to->governor, long_buf);
648  }
649  putsmap(smap, p);
650  }
651 
652  /* protecting ships retaliate individually if damage was inflicted */
653  if (damage) {
654  sh = p.ships;
655  while (sh) {
656  (void)getship(&ship, sh);
657  if (ship->protect.on && (ship->protect.ship == toship) &&
658  (ship->protect.ship == toship) && sh != toship && ship->alive &&
659  ship->active) {
660  if (laser_on(*ship)) check_overload(ship, 0, &strength);
661  check_retal_strength(ship, &strength);
662 
663  auto smap = getsmap(p);
664  if ((numdest = shoot_ship_to_planet(ship, &p, strength, x, y, smap, 0,
665  0, long_buf, short_buf)) >= 0) {
666  if (laser_on(*ship))
667  use_fuel(ship, 2.0 * (double)strength);
668  else
669  use_destruct(ship, strength);
670  post(short_buf, COMBAT);
671  notify_star(Playernum, Governor, ship->storbits, short_buf);
672  notify(Playernum, Governor, long_buf);
673  warn(ship->owner, ship->governor, long_buf);
674  }
675  putsmap(smap, p);
676  putship(ship);
677  }
678  sh = ship->nextship;
679  free(ship);
680  }
681  }
682 
683  /* write the ship stuff out to disk */
684  putship(&*to);
685  putplanet(p, Stars[g.snum], g.pnum);
686 
687  deductAPs(Playernum, Governor, APcount, g.snum, 0);
688 }
689 #endif
690 
691 void detonate(const command_t &argv, GameObj &g) {
692  const player_t Playernum = g.player;
693  const governor_t Governor = g.governor;
694 
695  if (argv.size() < 3) {
696  std::string msg = "Syntax: '" + argv[0] + " <mine>'\n";
697  notify(Playernum, Governor, msg);
698  return;
699  }
700 
701  Ship *s;
702  shipnum_t shipno;
703  shipnum_t nextshipno;
704 
705  nextshipno = start_shiplist(g, argv[1]);
706 
707  while ((shipno = do_shiplist(&s, &nextshipno)))
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";
712  free(s);
713  continue;
714  }
715  if (!s->on) {
716  g.out << "The mine is not activated.\n";
717  free(s);
718  continue;
719  }
720  if (s->docked || s->whatorbits == ScopeLevel::LEVEL_SHIP) {
721  g.out << "The mine is docked or landed.\n";
722  free(s);
723  continue;
724  }
725  free(s);
726  domine(shipno, 1);
727  } else
728  free(s);
729 }
730 
731 int retal_strength(Ship *s) {
732  int strength = 0;
733  int avail = 0;
734 
735  if (!s->alive) return 0;
736  if (!Shipdata[s->type][ABIL_SPEED] && !landed(*s)) return 0;
737  /* land based ships */
738  if (!s->popn && (s->type != ShipType::OTYPE_BERS)) return 0;
739 
740  if (s->guns == PRIMARY)
741  avail = (s->type == ShipType::STYPE_FIGHTER ||
742  s->type == ShipType::OTYPE_AFV || s->type == ShipType::OTYPE_BERS)
743  ? s->primary
744  : MIN(s->popn, s->primary);
745  else if (s->guns == SECONDARY)
746  avail = (s->type == ShipType::STYPE_FIGHTER ||
747  s->type == ShipType::OTYPE_AFV || s->type == ShipType::OTYPE_BERS)
748  ? s->secondary
749  : MIN(s->popn, s->secondary);
750  else
751  avail = 0;
752 
753  avail = MIN(s->retaliate, avail);
754  strength = MIN(s->destruct, avail);
755  return strength;
756 }
757 
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;
763 
764  return 0;
765  }
766  return 0;
767 }
768 
769 static void check_overload(Ship *ship, int cew, int *strength) {
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)) {
773  /* check to see if the ship blows up */
774  sprintf(buf,
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);
778  *strength = 0;
779  warn(ship->owner, ship->governor, buf);
780  post(buf, COMBAT);
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;
787  ship->mounted = 0;
788  *strength = 0;
789  warn(ship->owner, ship->governor, buf);
790  }
791  }
792 }
793 
794 static void check_retal_strength(Ship *ship, int *strength) {
795  *strength = 0;
796  if (ship->active && ship->alive) { /* irradiated ships dont retaliate */
797  if (laser_on(*ship))
798  *strength = MIN(ship->fire_laser, (int)ship->fuel / 2);
799  else
800  *strength = retal_strength(ship);
801  }
802 }
void use_fuel(Ship *s, double amt)
Definition: load.cc:876
void post(const char *origmsg, int type)
Definition: tele.cc:63
int retal_strength(Ship *s)
Definition: fire.cc:731
#define SYSTEMSIZE
Definition: tweakables.h:81
void detonate(const command_t &argv, GameObj &g)
Definition: fire.cc:691
Planet getplanet(const starnum_t star, const planetnum_t pnum)
Definition: files_shl.cc:335
void fire(const command_t &argv, GameObj &g)
Definition: fire.cc:49
void defend(const command_t &argv, GameObj &g)
Definition: fire.cc:498
#define SECONDARY
Definition: ships.h:16
int shoot_ship_to_ship(Ship *, Ship *, int, int, int, char *, char *)
Definition: shootblast.cc:43
int shoot_ship_to_planet(Ship *, Planet *, int, int, int, SectorMap &, int, int, char *, char *)
Definition: shootblast.cc:188
bool has_planet_defense(const shipnum_t shipno, const player_t Playernum)
Definition: fire.cc:36
static void check_overload(Ship *, int, int *)
Definition: fire.cc:769
#define PRIMARY
Definition: ships.h:15
static void check_retal_strength(Ship *, int *)
Definition: fire.cc:794
#define MIN(x, y)
Definition: tweakables.h:213
void putsmap(SectorMap &map, Planet &p)
Definition: files_shl.cc:1108
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
#define DEFENSE
Definition: config.h:30
int shoot_planet_to_ship(Race *, Ship *, int, char *, char *)
void use_destruct(Ship *s, int amt)
Definition: load.cc:881
shipnum_t do_shiplist(Ship **s, shipnum_t *nextshipno)
Definition: shlmisc.cc:94
void putplanet(const Planet &p, startype *star, const int pnum)
Definition: files_shl.cc:934
void putship(Ship *s)
Definition: files_shl.cc:1317
SectorMap getsmap(const Planet &p)
Definition: files_shl.cc:522
#define COMBAT
Definition: files.h:19
int adjacent(int fx, int fy, int tx, int ty, const Planet &p)
Definition: fire.cc:758
void domine(int, int)
Definition: doship.cc:316
Sector getsector(const Planet &p, const int x, const int y)
Definition: files_shl.cc:480
void bombard(const command_t &argv, GameObj &g)
Definition: fire.cc:305