/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2014, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2018, 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-2014
+ * Markus Armbruster, 2004-2016
*/
#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;
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("Not enough mil on ship #%d\n", item.ship.shp_uid);
continue;
}
- if (mchr[item.ship.shp_type].m_glim == 0
- && !(mchr[fship.shp_type].m_flags & M_DCH)) {
+ if (mchr[item.ship.shp_type].m_glim == 0) {
pr("Ships %d cannot fire guns!\n", item.ship.shp_uid);
continue;
}
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 (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;
}
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 (CANT_HAPPEN(dam < 0)) {
- pr("Klick! ...\n");
- continue;
- }
if (opt_NOMOBCOST == 0) {
fship.shp_mobil = MAX(fship.shp_mobil - 15, -100);
putship(fship.shp_uid, &fship);
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 (CANT_HAPPEN(dam < 0)) {
- pr("Klick! ...\n");
- continue;
- }
if (target == targ_ship) {
if (chance(lnd_acc(&fland) / 100.0))
dam = ldround(dam / 2.0, 1);
}
dam = fort_fire(&fsect);
putsect(&fsect);
- 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();
- }
+
+ if (CANT_HAPPEN(dam < 0)) {
+ pr("Jammed!\n");
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;
- }
-
+ pr("range is %d.00 (%.2f)\n", range2, range);
nfiring++;
switch (target) {
case targ_sub:
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:
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');
+ 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');
putship(vship.shp_uid, &vship);
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();
else
odds = 1.0;
do_defdam(&fired, odds);
+ free_flist(&fired);
return RET_OK;
}
if (vict)
wu(0, vict,
"Return fire hit %s in %s for %d damage.\n",
- prsub(&ship), xyas(ship.shp_x, ship.shp_y, vict), dam);
+ prship(&ship), xyas(ship.shp_x, ship.shp_y, vict), dam);
shipdamage(&ship, dam);
putship(ship.shp_uid, &ship);
} else {
wu(0, vict, "Return fire hit sector %s for %d damage.\n",
xyas(fp->x, fp->y, vict), dam);
}
- emp_remque(&fp->queue);
- free(fp);
}
}
}
static int
-uid_eq(struct emp_qelem *elem, void *key)
+flist_eq(struct emp_qelem *elem, void *key)
{
- return ((struct flist *)elem)->uid == ((struct empobj *)key)->uid;
+ struct flist *e = (struct flist *)elem;
+ struct flist *k = key;
+
+ return e->type == k->type && e->uid == k->uid;
}
static struct flist *
search_flist(struct emp_qelem *list, struct empobj *gp)
{
- return (struct flist *)emp_searchque(list, gp, uid_eq);
+ return (struct flist *)emp_searchque(list, gp, flist_eq);
}