src/lib/commands/miss.c

Go to the documentation of this file.
00001 /*
00002  *  Empire - A multi-player, client/server Internet based war game.
00003  *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
00004  *                           Ken Stevens, Steve McClure
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  *  ---
00021  *
00022  *  See files README, COPYING and CREDITS in the root of the source
00023  *  tree for related information and legal notices.  It is expected
00024  *  that future projects/authors will amend these files as needed.
00025  *
00026  *  ---
00027  *
00028  *  miss.c: set missions for ships/planes/units
00029  * 
00030  *  Known contributors to this file:
00031  *     Thomas Ruschak, 1992
00032  *     Steve McClure, 2000
00033  */
00034 
00035 #include <config.h>
00036 
00037 #include "commands.h"
00038 #include "empobj.h"
00039 #include "mission.h"
00040 #include "optlist.h"
00041 #include "path.h"
00042 
00043 /*
00044  *  mission <type> <planes/ships/units> <mission type> <op sector> [<radius>]
00045  */
00046 int
00047 mission(void)
00048 {
00049     static int ef_with_missions[] = { EF_SHIP, EF_LAND, EF_PLANE, EF_BAD };
00050     char *p;
00051     int type;
00052     int mission;
00053     coord x, y;
00054     int desired_radius, radius;
00055     struct sctstr opsect;
00056     union empobj_storage item;
00057     struct empobj *gp;
00058     int num = 0, mobmax, mobused, dist;
00059     struct nstr_item ni;
00060     char prompt[128];
00061     char buf[1024];
00062 
00063     if ((p =
00064          getstarg(player->argp[1], "Ship, plane or land unit (p,sh,la)? ",
00065                   buf)) == 0)
00066         return RET_SYN;
00067     type = ef_byname_from(p, ef_with_missions);
00068     if (type < 0) {
00069         pr("Ships, land units or planes only! (s, l, p)\n");
00070         return RET_SYN;
00071     }
00072     sprintf(prompt, "%s(s)? ", ef_nameof(type));
00073     p = getstarg(player->argp[2], prompt, buf);
00074     if (!snxtitem(&ni, type, p))
00075         return RET_SYN;
00076 
00077     if ((p =
00078          getstarg(player->argp[3],
00079                   "Mission (int, sup, osup, dsup, esc, res, air, query, clear)? ",
00080                   buf)) == 0)
00081         return RET_SYN;
00082 
00083 /* 
00084  * 'i'     interdiction
00085  * 's'     support
00086  * 'o'     support attacks
00087  * 'd'     support defenders
00088  * 'e'     escort
00089  * 'r'     defensive reserve
00090  * 'a'     air defense (intercepts)
00091  */
00092     switch (*p) {
00093     case 'I':
00094     case 'i':
00095         mission = MI_INTERDICT;
00096         break;
00097     case 'O':
00098     case 'o':
00099         mission = MI_OSUPPORT;
00100         break;
00101     case 'D':
00102     case 'd':
00103         mission = MI_DSUPPORT;
00104         break;
00105     case 'S':
00106     case 's':
00107         mission = MI_SUPPORT;
00108         break;
00109     case 'C':
00110     case 'c':
00111         mission = 0;
00112         break;
00113     case 'E':
00114     case 'e':
00115         mission = MI_ESCORT;
00116         break;
00117     case 'R':
00118     case 'r':
00119         mission = MI_RESERVE;
00120         break;
00121     case 'A':
00122     case 'a':
00123         mission = MI_AIR_DEFENSE;
00124         break;
00125     case 'q':
00126         show_mission(type, &ni);
00127         return RET_OK;
00128     default:
00129         pr("bad condition\n");
00130         pr("i\tinterdiction (any)\n");
00131         pr("s\tsupport (tactical planes only)\n");
00132         pr("o\toffensive support (tactical planes only)\n");
00133         pr("d\tdefensive support (tactical planes only)\n");
00134         pr("r\treserve (land units only)\n");
00135         pr("e\tescort (tactical or escort planes only)\n");
00136         pr("a\tair defense (intercept planes only)\n");
00137         pr("c\tclear mission\n");
00138         pr("q\tquery\n");
00139         return RET_SYN;
00140     }
00141 
00142     if (mission && !cando(mission, type)) {
00143         pr("A %s cannot do that mission!\n", ef_nameof(type));
00144         pr("i\tinterdiction (any)\n");
00145         pr("s\tsupport (planes only)\n");
00146         pr("o\toffensive support (planes only)\n");
00147         pr("d\tdefensive support (planes only)\n");
00148         pr("r\treserve (land units only)\n");
00149         pr("e\tescort (planes only)\n");
00150         pr("a\tair defense (planes only)\n");
00151         return RET_FAIL;
00152     }
00153 
00154     if (mission && ((mission != MI_RESERVE) && (mission != MI_ESCORT))) {
00155         if ((p = getstarg(player->argp[4], "operations point? ", buf)) == 0
00156             || *p == 0)
00157             return RET_SYN;
00158 
00159         if (*p != '.') {
00160             if (!sarg_xy(p, &x, &y))
00161                 return RET_SYN;
00162 
00163             if (!getsect(x, y, &opsect))
00164                 return RET_FAIL;
00165         }
00166     } else {
00167         x = 0;
00168         y = 0;
00169     }
00170 
00171     if (player->argp[5] != NULL) {
00172         desired_radius = atoi(player->argp[5]);
00173         if (desired_radius < 0) {
00174             pr("Radius must be greater than zero!\n");
00175             return RET_FAIL;
00176         }
00177     } else {
00178         desired_radius = 9999;
00179     }
00180 
00181     if ((mobmax = get_empobj_mob_max(type)) == -1)
00182         return RET_FAIL;
00183 
00184     mobused = ldround(mission_mob_cost * (double)mobmax, 1);
00185 
00186     while (nxtitem(&ni, &item)) {
00187         gp = (struct empobj *)&item;
00188 
00189         if (!player->owner || gp->own == 0)
00190             continue;
00191 
00192         if ((mission && (gp->mobil < mobused)) && mission_mob_cost) {
00193             pr("%s: not enough mobility! (needs %d)\n",
00194                obj_nameof(gp), mobused);
00195             continue;
00196         }
00197         if (mission == MI_RESERVE && !lnd_can_attack((struct lndstr *)gp)) {
00198             pr("%s is not designed to fight ground troops\n",
00199                obj_nameof(gp));
00200             continue;
00201         }
00202         if (*p == '.') {
00203             x = gp->x;
00204             y = gp->y;
00205             if (!getsect(x, y, &opsect))
00206                 return RET_FAIL;
00207         }
00208 
00209         dist = mapdist(gp->x, gp->y, x, y);
00210         radius = 999;
00211         if ((mission == MI_INTERDICT || mission == MI_SUPPORT ||
00212              mission == MI_OSUPPORT || mission == MI_DSUPPORT ||
00213              mission == MI_AIR_DEFENSE) &&
00214             (oprange(gp, &radius) < dist)) {
00215             pr("%s: out of range! (range %d)\n",
00216                obj_nameof(gp), oprange(gp, &radius));
00217             continue;
00218         }
00219 
00220         if (radius > desired_radius)
00221             radius = desired_radius;
00222 
00223         if ((mission == MI_INTERDICT) && (type == EF_SHIP))
00224             if (mchr[(int)gp->type].m_frnge < 1) {
00225                 pr("%s: cannot fire at range!\n", obj_nameof(gp));
00226                 continue;
00227             }
00228 
00229         if ((mission == MI_INTERDICT) && (type == EF_LAND))
00230             if (lchr[(int)gp->type].l_frg < 1) {
00231                 pr("%s: cannot fire at range!\n", obj_nameof(gp));
00232                 continue;
00233             }
00234 
00235         if ((mission == MI_INTERDICT) && (type == EF_PLANE)) {
00236             struct plchrstr *pcp;
00237 
00238             pcp = &plchr[(int)gp->type];
00239             if (!(pcp->pl_flags & P_T)) {
00240                 pr("Only planes with the tactical ability can interdict.\n"
00241                    "%s #%d is ineligible\n",
00242                    pcp->pl_name, gp->uid);
00243                 continue;
00244             }
00245         }
00246 
00247         if ((mission == MI_AIR_DEFENSE) && (type == EF_PLANE)) {
00248             struct plchrstr *pcp;
00249 
00250             pcp = &plchr[(int)gp->type];
00251             if (!(pcp->pl_flags & P_F)) {
00252                 pr("Only planes with the intercept abilities can perform air defense.\n"
00253                    "%s #%d is ineligible\n",
00254                    pcp->pl_name, gp->uid);
00255                 continue;
00256             }
00257         }
00258 
00259         if ((mission == MI_ESCORT) && (type == EF_PLANE)) {
00260             struct plchrstr *pcp;
00261 
00262             pcp = &plchr[(int)gp->type];
00263             if (!(pcp->pl_flags & P_ESC) && !(pcp->pl_flags & P_F)) {
00264                 pr("Only planes with the escort or intercept abilities can escort.\n"
00265                    "%s #%d is ineligible\n",
00266                    pcp->pl_name, gp->uid);
00267                 continue;
00268             }
00269         }
00270 
00271         if ((mission == MI_SUPPORT || mission == MI_OSUPPORT ||
00272              mission == MI_DSUPPORT) && (type == EF_PLANE)) {
00273             struct plchrstr *pcp;
00274 
00275             pcp = &plchr[(int)gp->type];
00276             if (!(pcp->pl_flags & P_T)) {
00277                 pr("Only planes with the tactical ability can support.\n"
00278                    "%s #%d is ineligible\n",
00279                    pcp->pl_name, gp->uid);
00280                 continue;
00281             }
00282         }
00283 
00284         num++;                  /* good one.. go with it */
00285 
00286         if (mission == MI_INTERDICT || mission == MI_SUPPORT ||
00287             mission == MI_OSUPPORT || mission == MI_DSUPPORT ||
00288             mission == MI_AIR_DEFENSE)
00289             gp->radius = radius;
00290         else
00291             gp->radius = 0;
00292 
00293         if (mission == MI_SUPPORT || mission == MI_OSUPPORT ||
00294             mission == MI_DSUPPORT || mission == MI_INTERDICT ||
00295             mission == MI_AIR_DEFENSE) {
00296             pr("%s on %s mission, centered on %s, radius %d\n",
00297                obj_nameof(gp), mission_name(mission),
00298                xyas(x, y, player->cnum), gp->radius);
00299         } else if (mission == MI_RESERVE) {
00300             int plus = 2;
00301 
00302             if (((struct lndstr *)gp)->lnd_rad_max == 0) {
00303                 plus = 0;
00304             } else {
00305                 getsect(gp->x, gp->y, &opsect);
00306                 if ((opsect.sct_type == SCT_HEADQ)
00307                     && (opsect.sct_effic >= 60))
00308                     plus++;
00309                 plus += ((struct lndstr *)gp)->lnd_rad_max;
00310             }
00311 
00312             pr("%s on %s mission with maximum reaction radius %d\n",
00313                obj_nameof(gp), mission_name(mission), plus);
00314         } else if (mission) {
00315             pr("%s on %s mission\n", obj_nameof(gp),
00316                mission_name(mission));
00317         }
00318 
00319         if (mission)
00320             gp->mobil -= mobused;
00321         gp->mission = mission;
00322         gp->opx = x;
00323         gp->opy = y;
00324         put_empobj(gp);
00325     }
00326     if (num == 0) {
00327         pr("No %s%s\n", ef_nameof(type), splur(num));
00328         return RET_FAIL;
00329     }
00330     pr("%d %s%s\n", num, ef_nameof(type), splur(num));
00331     return RET_OK;
00332 }

Generated on Fri Mar 28 11:01:12 2008 for empserver by  doxygen 1.5.2