示例#1
0
static int
fire_torp(struct shpstr *sp, struct shpstr *targ, int ntargets)
{
    int range, erange, dam;

    if ((mchr[targ->shp_type].m_flags & M_SUB)
	&& (mchr[sp->shp_type].m_flags & M_SUBT) == 0)
	return 0;		/* need sub-torp to torpedo a sub */

    erange = roundrange(torprange(sp));
    range = mapdist(sp->shp_x, sp->shp_y, targ->shp_x, targ->shp_y);
    if (range > erange)
	return 0;

    if (!line_of_sight(NULL, sp->shp_x, sp->shp_y,
		       targ->shp_x, targ->shp_y))
	return 0;
    dam = shp_torp(sp, 1);
    putship(sp->shp_uid, sp);
    if (dam < 0)
	return 0;

    pr("Captain! Torpedoes sighted!\n");

    if (chance(shp_torp_hitchance(sp, range))) {
	pr("BOOM!...\n");
	if (!(mchr[targ->shp_type].m_flags & M_SUB)) {
	    if (mchr[sp->shp_type].m_flags & M_SUB)
		nreport(targ->shp_own, N_TORP_SHIP, 0, 1);
	    else
		nreport(targ->shp_own, N_SHIP_TORP, sp->shp_own, 1);
	}
	if (sp->shp_own != 0)
	    wu(0, sp->shp_own, "%s @ %s torpedoed %s\n",
	       prship(sp),
	       xyas(sp->shp_x, sp->shp_y, sp->shp_own), prsub(targ));
	if (ntargets > 2)
	    dam /= ntargets / 2;

	shipdamage(targ, dam);
	putship(targ->shp_uid, targ);

    } else {
	pr("Missed!\n");
	if (sp->shp_own != 0)
	    wu(0, sp->shp_own,
	       "%s missed %s with a torpedo at %s\n",
	       prship(sp), prsub(targ),
	       xyas(sp->shp_x, sp->shp_y, sp->shp_own));
    }

    return 1;
}
示例#2
0
static void
fire_dchrg(struct shpstr *sp, struct shpstr *targ, int ntargets)
{
    int range, erange, dam;

    erange = roundrange(shp_fire_range(sp));
    range = mapdist(sp->shp_x, sp->shp_y, targ->shp_x, targ->shp_y);
    if (range > erange)
	return;

    if ((mchr[(int)targ->shp_type].m_flags & M_SUB) == 0) {
	/* Return fire to a torpedo boat */
	if (mchr[sp->shp_type].m_flags & M_SUB)
	    return;		/* sub deck gun can't return fire */
	dam = shp_fire(sp);
	putship(sp->shp_uid, sp);
	if (dam < 0)
	    return;
	if (ntargets > 2)
	    dam /= ntargets / 2;

	pr_beep();
	pr("Kaboom!!! Incoming shells!\n");
	if (sp->shp_own != 0)
	    wu(0, sp->shp_own,
	       "%s fired at %s\n", prship(sp), prship(targ));
	pr_beep();
	pr("BLAM! %d damage!\n", dam);
    } else {
	/* Return fire to a submarine */
	dam = shp_dchrg(sp);
	putship(sp->shp_uid, sp);
	if (dam < 0)
	    return;
	if (ntargets > 2)
	    dam /= ntargets / 2;

	pr("\nCAPTAIN!  !!Depth charges!!...\n");
	if (sp->shp_own != 0)
	    wu(0, sp->shp_own,
	       "%s depth charged %s\n", prship(sp), prsub(targ));
	pr("click...WHAM!  %d damage!\n", dam);
    }
    shipdamage(targ, dam);
    putship(targ->shp_uid, targ);
}
示例#3
0
int
torp(void)
{
    natid vshipown;
    int range;
    int dam;
    int subno;
    int victno;
    int erange;
    double hitchance;
    struct shpstr vship;
    struct shpstr sub;
    struct mchrstr *sub_mcp;
    char *ptr;
    struct nstr_item nbst;
    char buf[1024];
    int ntorping = 0;
    char prompt[128];

    if (!snxtitem(&nbst, EF_SHIP, player->argp[1], "From ship(s)? "))
	return RET_SYN;
    while (nxtitem(&nbst, &sub)) {
	if (sub.shp_own != player->cnum)
	    continue;
	if ((mchr[(int)sub.shp_type].m_flags & M_TORP) == 0)
	    continue;
	if (sub.shp_item[I_GUN] == 0
	    || sub.shp_item[I_SHELL] < SHP_TORP_SHELLS)
	    continue;
	if (sub.shp_item[I_MILIT] < 1)
	    continue;
	if (sub.shp_effic < 60)
	    continue;
	if (sub.shp_mobil <= 0)
	    continue;
	ntorping++;
    }
    pr("%d ships are eligible to torpedo\n", ntorping);
    snxtitem_rewind(&nbst);
    while (nxtitem(&nbst, &sub)) {
	if (!sub.shp_own)
	    continue;
	if (sub.shp_own != player->cnum) {
	    continue;
	}
	sub_mcp = &mchr[sub.shp_type];
	if (!(sub_mcp->m_flags & M_TORP)) {
	    pr("Ship # %d: A %s can't fire torpedoes!\n",
	       sub.shp_uid, sub_mcp->m_name);
	    continue;
	}
	if (sub.shp_item[I_GUN] == 0
	    || sub.shp_item[I_SHELL] < SHP_TORP_SHELLS) {
	    pr("Ship #%d has insufficient armament\n", sub.shp_uid);
	    continue;
	}
	if (sub.shp_item[I_MILIT] < 1) {
	    pr("Ship #%d has insufficient crew\n", sub.shp_uid);
	    continue;
	}
	if (sub.shp_effic < 60) {
	    pr("Ship #%d torpedo tubes inoperative.\n", sub.shp_uid);
	    continue;
	}
	if (sub.shp_mobil <= 0) {
	    pr("Ship #%d has insufficient mobility\n", sub.shp_uid);
	    continue;
	}
	subno = sub.shp_uid;
	sprintf(prompt, "Ship %d, target? ", sub.shp_uid);
	if (!(ptr = getstarg(player->argp[2], prompt, buf)))
	    return RET_SYN;
	if (!check_ship_ok(&sub))
	    return RET_FAIL;
	if ((victno = atoi(ptr)) < 0)
	    return RET_SYN;
	if (!getship(victno, &vship))
	    return RET_FAIL;
	if (!vship.shp_own)
	    return RET_FAIL;
	vshipown = vship.shp_own;
	if (victno == subno) {
	    pr("Shooting yourself, eh?  How strange...\n");
	    continue;
	}
	if (mchr[(int)vship.shp_type].m_flags & M_SUB) {
	    if (!(sub_mcp->m_flags & M_SUBT)) {
		pr("You can't torpedo a submarine!\n");
		continue;
	    }
	}
	dam = shp_torp(&sub, 1);
	sub.shp_mission = 0;
	putship(sub.shp_uid, &sub);
	if (CANT_HAPPEN(dam < 0)) {
	    pr("Ship #%d has insufficient armament\n", sub.shp_uid);
	    continue;
	}

	if (!(sub_mcp->m_flags & M_SUB)) {
	    pr("Starting our attack run...\n");
	    anti_torp(sub.shp_uid, ntorping, vshipown);
	}
	getship(sub.shp_uid, &sub);
	if (sub.shp_own == 0)
	    continue;

	erange = roundrange(torprange(&sub));
	pr("Effective torpedo range is %d.0\n", erange);
	pr("Whooosh... ");
	getship(victno, &vship);
	vshipown = vship.shp_own;
	range = mapdist(sub.shp_x, sub.shp_y, vship.shp_x, vship.shp_y);
	hitchance = shp_torp_hitchance(&sub, range);
	if (range <= erange) {
	    pr("Hitchance = %.0f%%\n", hitchance * 100);
	}
	if (range > erange)
	    pr("Out of range\n");
	else if (!line_of_sight(NULL, sub.shp_x, sub.shp_y,
				vship.shp_x, vship.shp_y)) {
	    pr("BOOM!... Torpedo slams into land before reaching target.\n");
	    /* We only tell the victim if we were within range. */
	    if (vshipown != 0 && vshipown != player->cnum)
		wu(0, vshipown, "Torpedo sighted @ %s by %s\n",
		   xyas(sub.shp_x, sub.shp_y, vshipown),
		   prship(&vship));
	} else if (chance(hitchance)) {
	    pr("BOOM!...\n");
	    if (vshipown != 0 && vshipown != player->cnum)
		wu(0, vshipown, "%s in %s torpedoed %s for %d damage.\n",
		   sub_mcp->m_flags & M_SUB ? "sub" : prship(&sub),
		   xyas(sub.shp_x, sub.shp_y, vshipown),
		   prship(&vship), dam);
	    pr("Torpedo hit %s for %d damage.\n", prsub(&vship), dam);
	    if (!(mchr[vship.shp_type].m_flags & M_SUB)) {
		if (mchr[sub.shp_type].m_flags & M_SUB)
		    nreport(vshipown, N_TORP_SHIP, 0, 1);
		else
		    nreport(vshipown, N_SHIP_TORP, player->cnum, 1);
	    }
	    shipdamage(&vship, dam);
	    if (vship.shp_effic < SHIP_MINEFF)
		pr("%s sunk!\n", prsub(&vship));
	    if (vship.shp_rflags & RET_TORPED)
		retreat_ship(&vship, vshipown, 't');
	    putship(vship.shp_uid, &vship);
	} else {
	    pr("Missed\n");
	    if (vshipown != 0 && vshipown != player->cnum)
		wu(0, vshipown, "Torpedo sighted @ %s by %s\n",
		   xyas(sub.shp_x, sub.shp_y, vshipown), prship(&vship));
	}

	if (sub_mcp->m_flags & M_SUB)
	    anti_torp(sub.shp_uid, ntorping, vshipown);
    }
    return RET_OK;
}
示例#4
0
int
msl_launch(struct plnstr *pp, int type, char *what, coord x, coord y,
	   natid victim, int *sublaunchp)
{
    struct shpstr ship;
    struct nukstr nuke;
    int sublaunch = 0;
    char *base, *in_or_at, *from;

    mpr(pp->pln_own, "Preparing to launch %s at %s %s %s%s\n",
	prplane(pp),
	cname(victim),
	what,
	type != EF_SECTOR ? "in " : "",
	xyas(x, y, pp->pln_own));
    if (pp->pln_ship >= 0) {
	getship(pp->pln_ship, &ship);
	base = prship(&ship);
	in_or_at = " in ";
	if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
	    sublaunch = 1;
	    from = "in hatch";
	} else
	    from = "on deck";
    } else {
	if (pp->pln_harden > 0) {
	    base = "missile silo";
	    in_or_at = " at ";
	    from = "in silo";
	} else {
	    base = in_or_at = "";
	    from = "on launch pad";
	}
    }
    mpr(pp->pln_own, "\tLaunching from %s%s%s\n",
	base, in_or_at, xyas(pp->pln_x, pp->pln_y, pp->pln_own));

    CANT_HAPPEN(pp->pln_flags & PLN_LAUNCHED);
    pp->pln_flags |= PLN_LAUNCHED;
    putplane(pp->pln_uid, pp);

    if (chance((0.05 + (100 - pp->pln_effic) / 100.0)
	       * (1 - techfact(pp->pln_tech, 1.0)))) {
	mpr(pp->pln_own, "KABOOOOM!  Missile explodes %s!\n", from);
	if (getnuke(nuk_on_plane(pp), &nuke)) {
	    mpr(pp->pln_own, "%s lost!\n", prnuke(&nuke));
	    nuke.nuk_effic = 0;
	    putnuke(nuke.nuk_uid, &nuke);
	}
#if 0
	/*
	 * Disabled for now, because it breaks callers that call
	 * msl_launch() for each member of a list of planes, created
	 * by msl_sel() or perform_mission().  Damage to the base can
	 * damage other planes.  Any copies of them in the list become
	 * stale.  When msl_launch() modifies and writes back such a
	 * stale copy, the damage gets wiped out, triggering a seqno
	 * oops.
	 */
	if (chance(0.33)) {
	    struct sctstr sect;
	    int dam;

	    dam = pln_damage(pp, 'p', NULL) / 2;
	    if (pp->pln_ship >= 0) {
		shipdamage(&ship, dam);
		putship(ship.shp_uid, &ship);
	    } else {
		mpr(pp->pln_own, "Explosion damages %s %d%%\n",
		    xyas(pp->pln_x, pp->pln_y, pp->pln_own), dam);
		getsect(pp->pln_x, pp->pln_y, &sect);
		sectdamage(&sect, dam);
		putsect(&sect);
	    }
	}
#endif
	return -1;
    }

    mpr(pp->pln_own, "\tSHWOOOOOSH!  Missile launched!\n");

    if (type != EF_PLANE)
	mpr(victim, "Incoming %s missile sighted at %s...\n",
	    sublaunch ? "sub-launched" : cname(pp->pln_own),
	    xyas(x, y, victim));

    if (type == EF_SECTOR || type == EF_LAND) {
	if (msl_abm_intercept(pp, x, y, sublaunch))
	    return -1;
    }
    if (type == EF_SHIP) {
	if (shp_missile_defense(x, y, pp->pln_own, pln_def(pp))) {
	    return -1;
	}
    }

    if (sublaunchp)
	*sublaunchp = sublaunch;
    return 0;
}