Пример #1
0
char *
unit_nameof(struct empobj *gp)
{
    switch (gp->ef_type) {
    case EF_SHIP:
	return prship((struct shpstr *)gp);
    case EF_PLANE:
	return prplane((struct plnstr *)gp);
    case EF_LAND:
	return prland((struct lndstr *)gp);
    case EF_NUKE:
	return prnuke((struct nukstr *)gp);
    }
    CANT_REACH();
    return "The Beast #666";
}
Пример #2
0
/* Knock down a bridge span.  Note that this does NOT write the
 * sector out to the database, it's up to the caller to do that. */
static void
knockdown(struct sctstr *sp)
{
    struct lndstr land;
    struct plnstr plane;
    struct nukstr nuke;
    struct nstr_item ni;

    mpr(sp->sct_own,
	"Crumble... SCREEEECH!  Splash! Bridge%s falls at %s!\n",
	sp->sct_type == SCT_BTOWER ? " tower" : "",
	xyas(sp->sct_x, sp->sct_y, sp->sct_own));
    if (!SCT_MINES_ARE_SEAMINES(sp))
	sp->sct_mines = 0;
    sp->sct_type = SCT_WATER;
    sp->sct_newtype = SCT_WATER;
    sp->sct_own = 0;
    sp->sct_oldown = 0;
    sp->sct_mobil = 0;
    sp->sct_effic = 0;

    /* Sink all the units */
    snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y);
    while (nxtitem(&ni, &land)) {
	if (land.lnd_own == 0)
	    continue;
	if (land.lnd_ship >= 0)
	    continue;
	mpr(land.lnd_own, "     AARGH! %s tumbles to its doom!\n",
	    prland(&land));
	land.lnd_effic = 0;
	putland(land.lnd_uid, &land);
    }
    /* Sink all the planes */
    snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y);
    while (nxtitem(&ni, &plane)) {
	if (plane.pln_own == 0)
	    continue;
	if (plane.pln_flags & PLN_LAUNCHED)
	    continue;
	if (plane.pln_ship >= 0)
	    continue;
	mpr(plane.pln_own, "     AARGH! %s tumbles to its doom!\n",
	    prplane(&plane));
	plane.pln_effic = 0;
	putplane(plane.pln_uid, &plane);
    }
    /* Sink all the nukes */
    snxtitem_xy(&ni, EF_NUKE, sp->sct_x, sp->sct_y);
    while (nxtitem(&ni, &nuke)) {
	if (nuke.nuk_own == 0)
	    continue;
	if (nuke.nuk_plane >= 0)
	    continue;
	mpr(nuke.nuk_own, "     %s sinks to the bottom of the sea!\n",
	    prnuke(&nuke));
	nuke.nuk_effic = 0;
	putnuke(nuke.nuk_uid, &nuke);
    }
    memset(sp->sct_item, 0, sizeof(sp->sct_item));
    memset(sp->sct_del, 0, sizeof(sp->sct_del));
    memset(sp->sct_dist, 0, sizeof(sp->sct_dist));
    sp->sct_pstage = PLG_HEALTHY;
    sp->sct_ptime = 0;
    sp->sct_che = 0;
    sp->sct_che_target = 0;
}
Пример #3
0
int
detonate(struct nukstr *np, coord x, coord y, int airburst)
{
    int nuketype = np->nuk_type;
    struct nchrstr *ncp;
    struct plnstr plane;
    struct sctstr sect;
    struct shpstr ship;
    struct lndstr land;
    struct nukstr nuke;
    natid own;
    int type;
    int damage;
    int fallout;
    int rad;
    struct nstr_sect ns;
    struct nstr_item ni;
    int changed = 0;

    pr("Releasing RV's for %s detonation...\n",
       airburst ? "airburst" : "groundburst");

    getsect(x, y, &sect);
    ncp = &nchr[nuketype];
    kaboom(x, y, ncp->n_blast);
    rad = ncp->n_blast;
    if (!airburst)
        rad = rad * 2 / 3;
    if (sect.sct_type == SCT_WATER)
        rad = 0;     /* Nukes falling on water affect only 1 sector */
    np->nuk_effic = 0;
    putnuke(np->nuk_uid, np);

    snxtsct_dist(&ns, x, y, rad);
    while (nxtsct(&ns, &sect)) {
        own = sect.sct_own;
        type = sect.sct_type;
        if ((damage = nukedamage(ncp, ns.curdist, airburst)) <= 0)
            continue;
        if (type == SCT_SANCT) {
            pr("bounced off %s\n", xyas(ns.x, ns.y, player->cnum));
            mpr(own, "%s nuclear device bounced off %s\n",
                cname(player->cnum), xyas(ns.x, ns.y, own));
            nreport(player->cnum, N_NUKE, own, 1);
            continue;
        }
        sect_damage(&sect, damage);
        if (opt_FALLOUT) {
            fallout = sect.sct_fallout;
            if (ncp->n_flags & N_NEUT)
                fallout += damage * 30;
            else
                fallout += damage * 3;
            sect.sct_fallout = MIN(fallout, FALLOUT_MAX);
        }
        if (damage > 100) {
            sect.sct_oldown = 0;
            sect.sct_own = 0;
            if (type == SCT_WATER || type == SCT_BSPAN ||
                    type == SCT_BTOWER) {
                if (type != SCT_WATER) {
                    pr("left nothing but water in %s\n",
                       xyas(ns.x, ns.y, player->cnum));
                    if (own != player->cnum)
                        mpr(own,
                            "%s nuclear device left nothing but water in %s\n",
                            cname(player->cnum), xyas(ns.x, ns.y, own));
                    sect.sct_newtype = SCT_WATER;
                    sect.sct_type = SCT_WATER;
                }
            } else {
                sect.sct_newtype = SCT_WASTE;
                sect.sct_type = SCT_WASTE;
                pr("turned %s into a radioactive wasteland\n",
                   xyas(ns.x, ns.y, player->cnum));
                if (own != player->cnum)
                    mpr(own,
                        "%s nuclear device turned %s into a radioactive wasteland\n",
                        cname(player->cnum), xyas(ns.x, ns.y, own));
            }
            changed |= map_set(player->cnum, sect.sct_x, sect.sct_y,
                               dchr[sect.sct_type].d_mnem, 0);
        } else {
            pr("did %d%% damage in %s\n",
               damage, xyas(ns.x, ns.y, player->cnum));
            if (own != player->cnum)
                mpr(own, "%s nuclear device did %d%% damage in %s\n",
                    cname(player->cnum), damage, xyas(ns.x, ns.y, own));
        }
        (void)putsect(&sect);
        if (type != SCT_WATER)
            nreport(player->cnum, N_NUKE, own, 1);
    }

    if (changed)
        writebmap(player->cnum);

    snxtitem_dist(&ni, EF_PLANE, x, y, rad);
    while (nxtitem(&ni, &plane)) {
        if ((own = plane.pln_own) == 0)
            continue;
        if (plane.pln_flags & PLN_LAUNCHED)
            continue;
        damage = nukedamage(ncp, ni.curdist, airburst) - plane.pln_harden;
        if (damage <= 0)
            continue;
        if (plane.pln_ship >= 0) {
            /* Are we on a sub? */
            getship(plane.pln_ship, &ship);

            if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
                struct sctstr sect1;

                /* Should we damage this sub? */
                getsect(ship.shp_x, ship.shp_y, &sect1);

                if (sect1.sct_type == SCT_BSPAN ||
                        sect1.sct_type == SCT_BTOWER ||
                        sect1.sct_type == SCT_WATER) {
                    /* Ok, we're not in a harbor or trapped
                       inland.  Now, did we get pasted
                       directly? */
                    if (ship.shp_x != x || ship.shp_y != y) {
                        /* Nope, so don't mess with it */
                        continue;
                    }
                }
            }
        }
        planedamage(&plane, damage);
        if (own == player->cnum) {
            pr("%s at %s reports %d%% damage\n",
               prplane(&plane),
               xyas(plane.pln_x, plane.pln_y, player->cnum), damage);
        } else {
            mpr(own, "%s nuclear device did %d%% damage to %s at %s\n",
                cname(player->cnum), damage,
                prplane(&plane), xyas(plane.pln_x, plane.pln_y, own));
        }
        putplane(ni.cur, &plane);
    }

    snxtitem_dist(&ni, EF_LAND, x, y, rad);
    while (nxtitem(&ni, &land)) {
        if ((own = land.lnd_own) == 0)
            continue;
        if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0)
            continue;

        if (land.lnd_ship >= 0) {
            /* Are we on a sub? */
            getship(land.lnd_ship, &ship);

            if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
                struct sctstr sect1;

                /* Should we damage this sub? */
                getsect(ship.shp_x, ship.shp_y, &sect1);

                if (sect1.sct_type == SCT_BSPAN ||
                        sect1.sct_type == SCT_BTOWER ||
                        sect1.sct_type == SCT_WATER) {
                    /* Ok, we're not in a harbor or trapped
                       inland.  Now, did we get pasted
                       directly? */
                    if (ship.shp_x != x || ship.shp_y != y) {
                        /* Nope, so don't mess with it */
                        continue;
                    }
                }
            }
        }
        land_damage(&land, damage);
        if (own == player->cnum) {
            pr("%s at %s reports %d%% damage\n",
               prland(&land), xyas(land.lnd_x, land.lnd_y, player->cnum),
               damage);
        } else {
            mpr(own, "%s nuclear device did %d%% damage to %s at %s\n",
                cname(player->cnum), damage,
                prland(&land), xyas(land.lnd_x, land.lnd_y, own));
        }
        putland(land.lnd_uid, &land);
    }

    snxtitem_dist(&ni, EF_SHIP, x, y, rad);
    while (nxtitem(&ni, &ship)) {
        if ((own = ship.shp_own) == 0)
            continue;
        if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0)
            continue;
        if (mchr[(int)ship.shp_type].m_flags & M_SUB) {
            struct sctstr sect1;

            /* Should we damage this sub? */
            getsect(ship.shp_x, ship.shp_y, &sect1);

            if (sect1.sct_type == SCT_BSPAN ||
                    sect1.sct_type == SCT_BTOWER ||
                    sect1.sct_type == SCT_WATER) {
                /* Ok, we're not in a harbor or trapped
                   inland.  Now, did we get pasted
                   directly? */
                if (ship.shp_x != x || ship.shp_y != y) {
                    /* Nope, so don't mess with it */
                    continue;
                }
            }
        }
        ship_damage(&ship, damage);
        if (own == player->cnum) {
            pr("%s at %s reports %d%% damage\n",
               prship(&ship), xyas(ship.shp_x, ship.shp_y, player->cnum),
               damage);
        } else {
            mpr(own, "%s nuclear device did %d%% damage to %s at %s\n",
                cname(player->cnum), damage, prship(&ship),
                xyas(ship.shp_x, ship.shp_y, own));
        }
        putship(ship.shp_uid, &ship);
    }

    snxtitem_dist(&ni, EF_NUKE, x, y, rad);
    while (nxtitem(&ni, &nuke)) {
        if ((own = nuke.nuk_own) == 0)
            continue;
        if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0)
            continue;
        if (!pct_chance(damage))
            continue;
        nuke.nuk_effic = 0;
        if (own == player->cnum) {
            pr("%s at %s destroyed\n",
               prnuke(&nuke), xyas(nuke.nuk_x, nuke.nuk_y, player->cnum));
        } else {
            mpr(own, "%s nuclear device destroyed %s at %s\n",
                cname(player->cnum), prnuke(&nuke),
                xyas(nuke.nuk_x, nuke.nuk_y, own));
        }
        putnuke(ni.cur, &nuke);
    }

    return nukedamage(ncp, 0, airburst);
}
Пример #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;
}