00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <config.h>
00037
00038 #include "commands.h"
00039 #include "damage.h"
00040 #include "mission.h"
00041 #include "news.h"
00042 #include "optlist.h"
00043 #include "path.h"
00044 #include "plane.h"
00045 #include "ship.h"
00046
00047 static int launch_as(struct plnstr *pp);
00048 static int launch_missile(struct plnstr *pp, int sublaunch);
00049 static int launch_sat(struct plnstr *pp, int sublaunch);
00050
00051
00052
00053
00054 int
00055 laun(void)
00056 {
00057 struct nstr_item nstr;
00058 struct plnstr plane;
00059 struct shpstr ship;
00060 struct sctstr sect;
00061 int sublaunch;
00062 struct plchrstr *pcp;
00063 int rel, retval, gone;
00064 struct natstr *natp;
00065
00066 if (!snxtitem(&nstr, EF_PLANE, player->argp[1]))
00067 return RET_SYN;
00068 while (nxtitem(&nstr, &plane)) {
00069 if (plane.pln_own != player->cnum)
00070 continue;
00071 pcp = &plchr[(int)plane.pln_type];
00072 if ((pcp->pl_flags & (P_M | P_O)) == 0) {
00073 pr("%s isn't a missile!\n", prplane(&plane));
00074 continue;
00075 }
00076 if (pcp->pl_flags & P_F) {
00077 pr("%s is a surface-to-air missile!\n", prplane(&plane));
00078 continue;
00079 }
00080 if (pcp->pl_flags & P_N) {
00081 pr("%s is an anti-ballistic-missile missile!\n",
00082 prplane(&plane));
00083 continue;
00084 }
00085 if ((plane.pln_flags & PLN_LAUNCHED) && (pcp->pl_flags & P_O)) {
00086 pr("%s already in orbit!\n", prplane(&plane));
00087 continue;
00088 }
00089 if (opt_MARKET) {
00090 if (ontradingblock(EF_PLANE, &plane)) {
00091 pr("plane #%d inelligible - it's for sale.\n",
00092 plane.pln_uid);
00093 continue;
00094 }
00095 }
00096
00097 sublaunch = 0;
00098 if (plane.pln_ship >= 0) {
00099 getship(plane.pln_ship, &ship);
00100 if (!ship.shp_own) {
00101 pr("%s: ship #%d was sunk!\n",
00102 prplane(&plane), ship.shp_uid);
00103 plane.pln_effic = 0;
00104 putplane(plane.pln_uid, &plane);
00105 continue;
00106 }
00107 natp = getnatp(ship.shp_own);
00108 rel = getrel(natp, player->cnum);
00109 if (ship.shp_own != player->cnum && rel != ALLIED) {
00110 pr("%s: you or an ally do not own ship #%d\n",
00111 prplane(&plane), ship.shp_uid);
00112 plane.pln_effic = 0;
00113 putplane(plane.pln_uid, &plane);
00114 continue;
00115 }
00116 if (mchr[(int)ship.shp_type].m_flags & M_SUB)
00117 sublaunch = 1;
00118 } else {
00119 sublaunch = 0;
00120 getsect(plane.pln_x, plane.pln_y, §);
00121 natp = getnatp(sect.sct_own);
00122 rel = getrel(natp, player->cnum);
00123 if (sect.sct_own && sect.sct_own != player->cnum
00124 && rel != ALLIED) {
00125 pr("%s: you or an ally do not own sector %s!\n",
00126 prplane(&plane), xyas(plane.pln_x, plane.pln_y,
00127 player->cnum));
00128 continue;
00129 }
00130 }
00131 if (plane.pln_effic < 60) {
00132 pr("%s is damaged (%d%%)\n", prplane(&plane), plane.pln_effic);
00133 continue;
00134 }
00135 pr("%s at %s; range %d, eff %d%%\n", prplane(&plane),
00136 xyas(plane.pln_x, plane.pln_y, player->cnum),
00137 plane.pln_range, plane.pln_effic);
00138 if (!(pcp->pl_flags & P_O)) {
00139 retval = launch_missile(&plane, sublaunch);
00140 gone = 1;
00141 } else if ((pcp->pl_flags & (P_M | P_O)) == (P_M | P_O)) {
00142 retval = launch_as(&plane);
00143 gone = 1;
00144 } else {
00145 retval = launch_sat(&plane, sublaunch);
00146 gone = !(plane.pln_flags & PLN_LAUNCHED);
00147 }
00148 if (retval != RET_OK)
00149 return retval;
00150 if (gone) {
00151 plane.pln_effic = 0;
00152 putplane(plane.pln_uid, &plane);
00153 }
00154 }
00155 return RET_OK;
00156 }
00157
00158
00159
00160
00161
00162
00163 static int
00164 launch_as(struct plnstr *pp)
00165 {
00166 coord sx, sy;
00167 char *cp, buf[1024];
00168 struct plnstr plane;
00169 struct nstr_item ni;
00170 int goodtarget;
00171 int dam, nukedam;
00172 natid oldown;
00173
00174 if (msl_equip(pp) < 0) {
00175 pr("%s not enough petrol or shells!\n", prplane(pp));
00176 return RET_FAIL;
00177 }
00178 cp = getstarg(player->argp[2], "Target sector? ", buf);
00179 if (!check_plane_ok(pp))
00180 return RET_FAIL;
00181 if (!cp || !*cp)
00182 return RET_SYN;
00183 if (!sarg_xy(cp, &sx, &sy)) {
00184 pr("Bad sector designation!\n");
00185 return RET_SYN;
00186 }
00187 if (mapdist(pp->pln_x, pp->pln_y, sx, sy) > pp->pln_range) {
00188 pr("Range too great!\n");
00189 return RET_FAIL;
00190 }
00191 goodtarget = 0;
00192 snxtitem_dist(&ni, EF_PLANE, sx, sy, 0);
00193 while (!goodtarget && nxtitem(&ni, &plane)) {
00194 if (!plane.pln_own)
00195 continue;
00196 if (!(plane.pln_flags & PLN_LAUNCHED))
00197 continue;
00198 goodtarget = 1;
00199
00200 }
00201 if (!goodtarget) {
00202 pr("No satellites there!\n");
00203 return RET_FAIL;
00204 }
00205 if (msl_hit(pp, plane.pln_def, EF_PLANE, N_SAT_KILL, N_SAT_KILL,
00206 prplane(&plane), sx, sy, plane.pln_own)) {
00207 dam = pln_damage(pp, sx, sy, 'p', &nukedam, 1);
00208 oldown = plane.pln_own;
00209 planedamage(&plane, dam);
00210 pr("Hit satellite for %d%% damage!\n", dam);
00211 mpr(oldown, "%s anti-sat did %d%% damage to %s over %s\n",
00212 cname(player->cnum), dam, prplane(&plane),
00213 xyas(plane.pln_x, plane.pln_y, plane.pln_own));
00214 putplane(plane.pln_uid, &plane);
00215 if (!plane.pln_own)
00216 mpr(oldown, "Satellite shot down\n");
00217 }
00218 return RET_OK;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227 static int
00228 launch_missile(struct plnstr *pp, int sublaunch)
00229 {
00230 struct plchrstr *pcp = plchr + pp->pln_type;
00231 coord sx, sy;
00232 int n, dam;
00233 char *cp;
00234 struct mchrstr *mcp;
00235 struct shpstr target_ship;
00236 struct sctstr sect;
00237 int nukedam;
00238 int rel;
00239 struct natstr *natp;
00240 char buf[1024];
00241
00242 if (pcp->pl_flags & P_MAR)
00243 cp = getstarg(player->argp[2], "Target ship? ", buf);
00244 else
00245 cp = getstarg(player->argp[2], "Target sector? ", buf);
00246 if (!cp || !*cp)
00247 return RET_SYN;
00248 if (!check_plane_ok(pp))
00249 return RET_FAIL;
00250 if (opt_PINPOINTMISSILE && sarg_type(cp) == NS_LIST) {
00251 if (!(pcp->pl_flags & P_MAR)) {
00252 pr("Missile not designed to attack ships!\n");
00253 return RET_FAIL;
00254 }
00255 n = atoi(cp);
00256 if ((n < 0) || !getship(n, &target_ship) ||
00257 !target_ship.shp_own) {
00258 pr("Bad ship number!\n");
00259 return RET_FAIL;
00260 }
00261 sx = target_ship.shp_x;
00262 sy = target_ship.shp_y;
00263 mcp = &mchr[(int)target_ship.shp_type];
00264 if (mcp->m_flags & M_SUB) {
00265 pr("Bad ship number!\n");
00266 return RET_FAIL;
00267 }
00268 }
00269 else if (!sarg_xy(cp, &sx, &sy)) {
00270 pr("Not a sector!\n");
00271 return RET_FAIL;
00272 } else if (opt_PINPOINTMISSILE) {
00273 if (pcp->pl_flags & P_MAR) {
00274 pr("Missile designed to attack ships!\n");
00275 return RET_FAIL;
00276 }
00277 }
00278
00279 if (mapdist(pp->pln_x, pp->pln_y, sx, sy) > pp->pln_range) {
00280 pr("Range too great; try again!\n");
00281 return RET_FAIL;
00282 }
00283 if (msl_equip(pp) < 0) {
00284 pr("%s not enough shells!\n", prplane(pp));
00285 return RET_FAIL;
00286 }
00287 if (opt_PINPOINTMISSILE == 0 || !(pcp->pl_flags & P_MAR)) {
00288 getsect(sx, sy, §);
00289 if (opt_SLOW_WAR) {
00290 natp = getnatp(player->cnum);
00291 rel = getrel(natp, sect.sct_own);
00292 if ((rel != AT_WAR) && (sect.sct_own != player->cnum) &&
00293 (sect.sct_own) && (sect.sct_oldown != player->cnum)) {
00294 pr("You are not at war with the player->owner of the target sector!\n");
00295 pr_beep();
00296 pr("Kaboom!!!\n");
00297 pr("Missile monitoring officer destroys RV before detonation.\n");
00298 return RET_OK;
00299 }
00300 }
00301 if (!msl_hit(pp, SECT_HARDTARGET, EF_SECTOR, N_SCT_MISS,
00302 N_SCT_SMISS, "sector", sx, sy, sect.sct_own)) {
00303
00304
00305
00306
00307 return RET_OK;
00308 }
00309 dam = pln_damage(pp, sect.sct_x, sect.sct_y, 's', &nukedam, 1);
00310 if (!nukedam) {
00311 pr("did %d damage in %s\n", PERCENT_DAMAGE(dam),
00312 xyas(sx, sy, player->cnum));
00313 if (sect.sct_own != 0) {
00314 if (sublaunch)
00315 wu(0, sect.sct_own,
00316 "Sub missile attack did %d damage in %s\n",
00317 dam, xyas(sx, sy, sect.sct_own));
00318 else
00319 wu(0, sect.sct_own,
00320 "%s missile attack did %d damage in %s\n",
00321 cname(player->cnum), dam,
00322 xyas(sx, sy, sect.sct_own));
00323 }
00324 sectdamage(§, dam, 0);
00325 putsect(§);
00326 }
00327 }
00328 else if (opt_PINPOINTMISSILE) {
00329 if (!msl_hit(pp, shp_hardtarget(&target_ship), EF_SHIP,
00330 N_SHP_MISS, N_SHP_SMISS, prship(&target_ship),
00331 target_ship.shp_x, target_ship.shp_y,
00332 target_ship.shp_own)) {
00333 pr("splash\n");
00334
00335
00336
00337
00338 return RET_OK;
00339 }
00340 dam =
00341 pln_damage(pp, target_ship.shp_x, target_ship.shp_y, 'p',
00342 &nukedam, 1);
00343 if (!nukedam) {
00344 check_retreat_and_do_shipdamage(&target_ship, dam);
00345 if (target_ship.shp_effic < SHIP_MINEFF)
00346 pr("\t%s sunk!\n", prship(&target_ship));
00347 putship(target_ship.shp_uid, &target_ship);
00348 }
00349 getship(target_ship.shp_uid, &target_ship);
00350 if (!target_ship.shp_own)
00351 pr("%s sunk!\n", prship(&target_ship));
00352 }
00353
00354 return RET_OK;
00355 }
00356
00357
00358
00359
00360
00361
00362 static int
00363 launch_sat(struct plnstr *pp, int sublaunch)
00364 {
00365 struct plchrstr *pcp = plchr + pp->pln_type;
00366 coord sx, sy;
00367 int i;
00368 int dist;
00369 int dir;
00370 char *cp;
00371 char *p;
00372 char buf[1024];
00373
00374 pr("\n");
00375 cp = getstarg(player->argp[2], "Target sector? ", buf);
00376 if (!check_plane_ok(pp))
00377 return RET_FAIL;
00378 if (!cp || !*cp)
00379 return RET_SYN;
00380 if (!sarg_xy(cp, &sx, &sy)) {
00381 pr("Bad sector designation!\n");
00382 return RET_SYN;
00383 }
00384 if ((dist = mapdist(pp->pln_x, pp->pln_y, sx, sy)) > pp->pln_range) {
00385 pr("Range too great; try again!\n");
00386 return RET_FAIL;
00387 }
00388 p = getstring("Geostationary orbit? ", buf);
00389 if (p == 0)
00390 return RET_SYN;
00391 if (!check_plane_ok(pp))
00392 return RET_FAIL;
00393 pp->pln_theta = 0;
00394 pp->pln_flags |= PLN_SYNCHRONOUS;
00395 if (*p == 0 || *p == 'n')
00396 pp->pln_flags &= ~(PLN_SYNCHRONOUS);
00397 pr("3... 2... 1... Blastoff!!!\n");
00398 if (chance(0.07 + (100 - pp->pln_effic) / 100.0)) {
00399 pr("KABOOOOM! Range safety officer detonates booster!\n");
00400 pp->pln_effic = 0;
00401 return RET_OK;
00402 }
00403 i = pp->pln_tech + pp->pln_effic;
00404 if (chance(1.0 - (i / (i + 50.0)))) {
00405 dir = (random() % 6) + 1;
00406 sx += diroff[dir][0];
00407 sy += diroff[dir][1];
00408 pr("Your trajectory was a little off.\n");
00409 }
00410 nreport(player->cnum, N_LAUNCH, 0, 1);
00411 pr("%s positioned over %s", prplane(pp), xyas(sx, sy, player->cnum));
00412 if (msl_intercept(sx, sy, pp->pln_own, pcp->pl_def, sublaunch, P_O, 0)) {
00413 return RET_OK;
00414 }
00415 pp->pln_x = sx;
00416 pp->pln_y = sy;
00417 pp->pln_flags |= PLN_LAUNCHED;
00418 pp->pln_mobil = pp->pln_mobil > dist ? pp->pln_mobil - dist : 0;
00419 putplane(pp->pln_uid, pp);
00420 pr(", will be ready for use in %d time units\n",
00421 plane_mob_max - pp->pln_mobil);
00422 return RET_OK;
00423 }