/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2013, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
*
* Known contributors to this file:
* Steve McClure, 2000
- * Markus Armbruster, 2004-2011
+ * Markus Armbruster, 2004-2015
*/
#include <config.h>
#include "optlist.h"
#include "retreat.h"
-enum targ_type {
- targ_land, targ_ship, targ_sub, targ_bogus
+enum targ_type { /* Targeting... */
+ targ_land, /* a sector with guns */
+ targ_ship, /* a ship with guns */
+ targ_sub, /* a submarine with depth charges */
+ targ_bogus /* a bogus sector with guns */
};
struct flist {
struct shpstr fship;
struct lndstr fland;
struct sctstr fsect;
+ char *sep = "";
struct shpstr vship;
struct sctstr vsect;
enum targ_type target;
fland.lnd_uid, LAND_MINFIREEFF);
continue;
}
+ if (fland.lnd_item[I_GUN] == 0) {
+ pr("%s -- not enough guns\n", prland(&fland));
+ continue;
+ }
+
if (fland.lnd_item[I_SHELL] == 0) {
pr("%s -- not enough shells\n", prland(&fland));
continue;
}
+ pr("%s%s ready to fire\n", sep, prland(&fland));
fx = fland.lnd_x;
fy = fland.lnd_y;
} else if (type == EF_SHIP) {
pr("Ship #%d is crippled!\n", item.ship.shp_uid);
continue;
}
+ pr("%s%s ready to fire\n", sep, prship(&fship));
fx = fship.shp_x;
fy = fship.shp_y;
} else {
xyas(item.sect.sct_x, item.sect.sct_y, player->cnum));
continue;
}
- pr("\nSector %s firing\n",
+ pr("%sSector %s ready to fire\n", sep,
xyas(item.sect.sct_x, item.sect.sct_y, player->cnum));
fx = fsect.sct_x;
fy = fsect.sct_y;
}
+ sep = "\n";
ptr = getstarg(player->argp[3], "Firing at? ", buf);
if (!ptr)
pr("No such ship exists!\n");
continue;
}
- target = (mchr[(int)vship.shp_type].m_flags & M_SUB) ?
- targ_sub : targ_ship;
+ target = targ_ship; /* targ_ship vs. targ_sub decided below */
vict = vship.shp_own;
x = vship.shp_x;
y = vship.shp_y;
if (type == EF_SHIP) {
if (!check_ship_ok(&fship))
return RET_FAIL;
- if (fship.shp_own != player->cnum) {
- pr("Not your ship!\n");
- continue;
- }
- if (target == targ_sub || target == targ_ship) {
+ if (target == targ_ship) {
if (fship.shp_uid == vship.shp_uid) {
pr("You can't fire upon yourself!\n");
continue;
}
}
- if (fship.shp_item[I_MILIT] < 1) {
- pr("Not enough military for firing crew.\n");
- continue;
- }
- if (fship.shp_effic < 60) {
- pr("Ship #%d is crippled (%d%%)\n",
- fship.shp_uid, fship.shp_effic);
- continue;
- }
range = shp_fire_range(&fship);
range2 = roundrange(range);
pr("range is %d.00 (%.2f)\n", range2, range);
- if (target == targ_sub
- && trange <= range2
- && (mchr[(int)fship.shp_type].m_flags & M_DCH)) {
+ /* Use depth charges against subs, but only when in range */
+ if (target == targ_ship && trange <= range2
+ && (mchr[vship.shp_type].m_flags & M_SUB)
+ && (mchr[fship.shp_type].m_flags & M_DCH))
+ target = targ_sub;
+ if (target == targ_sub)
dam = shp_dchrg(&fship);
- } else {
- if (target == targ_sub)
- /* Don't tell it's a sub */
- range2 = -1;
- if (fship.shp_item[I_GUN] == 0) {
- pr("Insufficient arms.\n");
- continue;
- }
+ else
dam = shp_fire(&fship);
- }
+ fship.shp_mission = 0;
putship(fship.shp_uid, &fship);
- if (dam <= 0) {
+ if (CANT_HAPPEN(dam < 0)) {
pr("Klick! ...\n");
continue;
}
} else if (type == EF_LAND) {
if (!check_land_ok(&fland))
return RET_FAIL;
- if (fland.lnd_own != player->cnum) {
- pr("Not your unit!\n");
- continue;
- }
-
if (target == targ_land) {
if (fland.lnd_x == vsect.sct_x
&& fland.lnd_y == vsect.sct_y) {
continue;
}
}
-
- if (lchr[fland.lnd_type].l_dam == 0) {
- pr("Unit %d cannot fire!\n", fland.lnd_uid);
- continue;
- }
- if (fland.lnd_item[I_GUN] == 0) {
- pr("%s -- not enough guns\n", prland(&fland));
- continue;
- }
-
range = lnd_fire_range(&fland);
range2 = roundrange(range);
pr("range is %d.00 (%.2f)\n", range2, range);
- if (target == targ_sub) {
- /* Don't tell it's a sub */
- range2 = -1;
- }
-
dam = lnd_fire(&fland);
+ fland.lnd_mission = 0;
putland(fland.lnd_uid, &fland);
- if (dam < 0) {
+ if (CANT_HAPPEN(dam < 0)) {
pr("Klick! ...\n");
continue;
}
} else {
if (!check_sect_ok(&fsect))
return RET_FAIL;
- if (fsect.sct_own != player->cnum ||
- fsect.sct_type != SCT_FORTR) {
- pr("No fortress at %s\n",
- xyas(fsect.sct_x, fsect.sct_y, player->cnum));
- continue;
- }
if (target == targ_land) {
if (fsect.sct_x == vsect.sct_x
&& fsect.sct_y == vsect.sct_y) {
continue;
}
}
- if (fsect.sct_item[I_GUN] == 0) {
- pr("Insufficient arms.\n");
- continue;
- }
- if (fsect.sct_item[I_MILIT] < 5) {
- pr("Not enough military for firing crew.\n");
- continue;
- }
dam = fort_fire(&fsect);
putsect(&fsect);
- if (dam < 0) {
+ if (CANT_HAPPEN(dam < 0)) {
pr("Klick! ...\n");
continue;
}
range = fortrange(&fsect);
range2 = roundrange(range);
pr("range is %d.00 (%.2f)\n", range2, range);
- if (target == targ_sub) {
- /* Don't tell it's a sub */
- range2 = -1;
- }
- }
- if (trange > range2) {
- pr("Target out of range.\n");
- switch (type) {
- case EF_SECTOR:
- putsect(&fsect);
- break;
- case EF_LAND:
- fland.lnd_mission = 0;
- putland(fland.lnd_uid, &fland);
- break;
- case EF_SHIP:
- fship.shp_mission = 0;
- putship(fship.shp_uid, &fship);
- break;
- default:
- CANT_REACH();
- }
- continue;
- }
- switch (target) {
- case targ_ship:
- if (!trechk(player->cnum, vict, SEAFIR))
- continue;
- break;
- case targ_sub:
- if (!trechk(player->cnum, vict, SUBFIR))
- continue;
- break;
- case targ_land:
- if (!trechk(player->cnum, vict, LANFIR))
- continue;
- break;
- default:
- break;
}
nfiring++;
pr("Kaboom!!!\n");
break;
}
+
+ /*
+ * If the player fires guns at a submarine, take care not to
+ * disclose it's a submarine: pretend the target is out of range.
+ */
+ if (target == targ_ship && (mchr[vship.shp_type].m_flags & M_SUB))
+ range2 = -1;
+ if (trange > range2) {
+ pr("Target out of range.\n");
+ continue;
+ }
+
switch (target) {
case targ_bogus:
case targ_land:
nreport(player->cnum, N_SHP_SHELL, vict, 1);
/* fall through */
default:
- if (vict) {
+ if (vict && vict != player->cnum) {
wu(0, vict,
"Country #%d shelled %s in %s for %d damage.\n",
player->cnum, prship(&vship),
break;
default:
getship(vshipno, &vship);
- check_retreat_and_do_shipdamage(&vship, dam);
+ shipdamage(&vship, dam);
if (vship.shp_effic < SHIP_MINEFF)
pr("%s sunk!\n", prsub(&vship));
- else if (target == targ_sub
- && (vship.shp_rflags & RET_DCHRGED)
- && !(vship.shp_rflags & RET_INJURED))
- retreat_ship(&vship, 'd');
putship(vship.shp_uid, &vship);
+ if (dam && (vship.shp_rflags & RET_INJURED))
+ retreat_ship(&vship, vict, 'i');
+ else if (target == targ_sub && (vship.shp_rflags & RET_DCHRGED))
+ retreat_ship(&vship, vict, 'd');
+ else if (totaldefdam == 0 && (vship.shp_rflags & RET_HELPLESS))
+ retreat_ship(&vship, vict, 'h');
break;
}
- if (totaldefdam == 0 && target == targ_ship
- && (vship.shp_rflags & RET_HELPLESS)
- && !(vship.shp_rflags & RET_INJURED))
- retreat_ship(&vship, 'h');
switch (attgp->ef_type) {
case EF_SECTOR:
- putsect(&fsect);
break;
case EF_SHIP:
if ((target == targ_ship) || (target == targ_sub)) {
if (fship.shp_effic > SHIP_MINEFF) {
shp_missdef(&fship, vict);
- };
- };
- putship(fship.shp_uid, &fship);
+ }
+ }
break;
default:
CANT_REACH();