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 "item.h"
00040 #include "land.h"
00041 #include "plague.h"
00042 #include "plane.h"
00043 #include "ship.h"
00044
00045 static void expose_ship(struct shpstr *s1, struct shpstr *s2);
00046 static int tend_land(struct shpstr *tenderp, char *units);
00047
00048 int
00049 tend(void)
00050 {
00051 struct nstr_item targets;
00052 struct nstr_item tenders;
00053 struct shpstr tender;
00054 struct shpstr target;
00055 struct ichrstr *ip;
00056 struct mchrstr *vbase;
00057 int amt;
00058 int retval;
00059 int ontender;
00060 int ontarget;
00061 int maxtender;
00062 int maxtarget;
00063 int transfer;
00064 int total;
00065 int type;
00066 char *p;
00067 char prompt[512];
00068 char buf[1024];
00069
00070 if (!(p = getstarg(player->argp[1],
00071 "Tend what commodity (or 'land')? ", buf)) || !*p)
00072 return RET_SYN;
00073
00074 if (!strncmp(p, "land", 4))
00075 type = EF_LAND;
00076 else if (NULL != (ip = item_by_name(p)))
00077 type = EF_SECTOR;
00078 else {
00079 pr("Can't tend '%s'\n", p);
00080 return RET_SYN;
00081 }
00082
00083 if (!snxtitem(&tenders, EF_SHIP,
00084 getstarg(player->argp[2], "Tender(s)? ", buf)))
00085 return RET_SYN;
00086
00087 while (nxtitem(&tenders, &tender)) {
00088 if (!player->owner)
00089 continue;
00090 if (type == EF_LAND) {
00091 sprintf(prompt, "Land unit(s) to tend from %s? ",
00092 prship(&tender));
00093 if (!(p = getstarg(player->argp[3], prompt, buf)) || !*p)
00094 continue;
00095 if (!check_ship_ok(&tender))
00096 return RET_SYN;
00097 if (0 != (retval = tend_land(&tender, p)))
00098 return retval;
00099 continue;
00100 }
00101 sprintf(prompt, "Number of %s to tend from %s? ",
00102 ip->i_name, prship(&tender));
00103 if (!(p = getstarg(player->argp[3], prompt, buf)) || !*p)
00104 continue;
00105 if (!check_ship_ok(&tender))
00106 return RET_SYN;
00107 if (!(amt = atoi(p))) {
00108 pr("Amount must be non-zero!\n");
00109 return RET_SYN;
00110 }
00111 ontender = tender.shp_item[ip->i_uid];
00112 if (ontender == 0 && amt > 0) {
00113 pr("No %s on %s\n", ip->i_name, prship(&tender));
00114 return RET_FAIL;
00115 }
00116 vbase = &mchr[(int)tender.shp_type];
00117 maxtender = vbase->m_item[ip->i_uid];
00118 if (maxtender == 0) {
00119 pr("A %s cannot hold any %s\n",
00120 mchr[(int)tender.shp_type].m_name, ip->i_name);
00121 break;
00122 }
00123 if (!snxtitem(&targets, EF_SHIP,
00124 getstarg(player->argp[4], "Ships to be tended? ",
00125 buf)))
00126 break;
00127 if (!check_ship_ok(&tender))
00128 return RET_SYN;
00129 total = 0;
00130 while (nxtitem(&targets, &target)) {
00131 if (!player->owner &&
00132 (getrel(getnatp(target.shp_own), player->cnum) < FRIENDLY))
00133 continue;
00134 if (target.shp_uid == tender.shp_uid)
00135 continue;
00136 if (tender.shp_x != target.shp_x ||
00137 tender.shp_y != target.shp_y)
00138 continue;
00139 ontarget = target.shp_item[ip->i_uid];
00140 if (ontarget == 0 && amt < 0) {
00141 pr("No %s on %s\n", ip->i_name, prship(&target));
00142 continue;
00143 }
00144 vbase = &mchr[(int)target.shp_type];
00145 maxtarget = vbase->m_item[ip->i_uid];
00146 if (amt < 0) {
00147 if (!player->owner)
00148 amt = 0;
00149
00150
00151 transfer = MIN(ontarget, -amt);
00152 transfer = MIN(maxtender - ontender, transfer);
00153 if (transfer == 0)
00154 continue;
00155 target.shp_item[ip->i_uid] = ontarget - transfer;
00156 ontender += transfer;
00157 total += transfer;
00158 } else {
00159
00160 transfer = MIN(ontender, amt);
00161 transfer = MIN(transfer, maxtarget - ontarget);
00162 if (transfer == 0)
00163 continue;
00164 target.shp_item[ip->i_uid] = ontarget + transfer;
00165 ontender -= transfer;
00166 total += transfer;
00167 if (transfer && target.shp_own != player->cnum) {
00168 wu(0, target.shp_own, "%s tended %d %s to %s\n",
00169 cname(player->cnum), total, ip->i_name,
00170 prship(&target));
00171 }
00172 }
00173 expose_ship(&tender, &target);
00174 putship(target.shp_uid, &target);
00175 if (amt > 0 && ontender == 0) {
00176 pr("%s out of %s\n", prship(&tender), ip->i_name);
00177 break;
00178 }
00179 }
00180 pr("%d total %s transferred %s %s\n",
00181 total, ip->i_name, (amt > 0) ? "off of" : "to",
00182 prship(&tender));
00183 tender.shp_item[ip->i_uid] = ontender;
00184 tender.shp_mission = 0;
00185 putship(tender.shp_uid, &tender);
00186 }
00187 return RET_OK;
00188 }
00189
00190 static void
00191 expose_ship(struct shpstr *s1, struct shpstr *s2)
00192 {
00193 if (s1->shp_pstage == PLG_INFECT && s2->shp_pstage == PLG_HEALTHY)
00194 s2->shp_pstage = PLG_EXPOSED;
00195 if (s2->shp_pstage == PLG_INFECT && s1->shp_pstage == PLG_HEALTHY)
00196 s1->shp_pstage = PLG_EXPOSED;
00197 }
00198
00199 static int
00200 tend_land(struct shpstr *tenderp, char *units)
00201 {
00202 struct nstr_item lni;
00203 struct nstr_item targets;
00204 struct shpstr target;
00205 struct lndstr land;
00206 struct plnstr plane;
00207 struct nstr_item pni;
00208 char buf[1024];
00209
00210 if (!snxtitem(&lni, EF_LAND, units))
00211 return RET_SYN;
00212
00213 while (nxtitem(&lni, &land)) {
00214 if (!player->owner)
00215 continue;
00216 if (land.lnd_ship != tenderp->shp_uid) {
00217 pr("%s is not on %s!\n", prland(&land), prship(tenderp));
00218 continue;
00219 }
00220 if (!(lchr[(int)land.lnd_type].l_flags & L_ASSAULT)) {
00221 pr("%s does not have \"assault\" capability and can't be tended\n",
00222 prland(&land));
00223 continue;
00224 }
00225 if (!snxtitem(&targets, EF_SHIP,
00226 getstarg(player->argp[4], "Ship to be tended? ",
00227 buf)))
00228 break;
00229 if (!check_land_ok(&land))
00230 return RET_SYN;
00231 while (nxtitem(&targets, &target)) {
00232 if (!player->owner &&
00233 (getrel(getnatp(target.shp_own), player->cnum) < FRIENDLY))
00234 continue;
00235 if (target.shp_uid == tenderp->shp_uid)
00236 continue;
00237 if (tenderp->shp_x != target.shp_x ||
00238 tenderp->shp_y != target.shp_y)
00239 continue;
00240
00241
00242 count_units(&target);
00243 getship(target.shp_uid, &target);
00244
00245 if ((!(lchr[(int)land.lnd_type].l_flags & L_LIGHT)) &&
00246 (!((mchr[(int)target.shp_type].m_flags & M_SUPPLY) &&
00247 (!(mchr[(int)target.shp_type].m_flags & M_SUB))))) {
00248 pr("You can only load light units onto ships,\n"
00249 "unless the ship is a non-sub supply ship\n"
00250 "%s not tended\n", prland(&land));
00251 continue;
00252 }
00253
00254 if ((mchr[(int)target.shp_type].m_flags & M_SUB) &&
00255 (lchr[(int)land.lnd_type].l_flags & L_SPY) &&
00256 !mchr[(int)target.shp_type].m_nland) {
00257 if (target.shp_nland > 1) {
00258 pr("%s doesn't have room for more than two spy units!\n",
00259 prship(&target));
00260 continue;
00261 }
00262 } else if (target.shp_nland >= mchr[(int)target.shp_type].m_nland) {
00263 if (mchr[(int)target.shp_type].m_nland)
00264 pr("%s doesn't have room for any more land units!\n",
00265 prship(&target));
00266 else
00267 pr("%s doesn't carry land units!\n", prship(&target));
00268 continue;
00269 }
00270 pr("%s transferred from %s to %s\n",
00271 prland(&land), prship(tenderp), prship(&target));
00272 sprintf(buf, "loaded on your %s at %s",
00273 prship(&target), xyas(target.shp_x, target.shp_y,
00274 target.shp_own));
00275 gift(target.shp_own, player->cnum, &land, buf);
00276 land.lnd_ship = target.shp_uid;
00277 land.lnd_harden = 0;
00278 land.lnd_mission = 0;
00279 target.shp_nland++;
00280 putland(land.lnd_uid, &land);
00281 expose_ship(tenderp, &target);
00282 putship(target.shp_uid, &target);
00283 count_units(tenderp);
00284 putship(tenderp->shp_uid, tenderp);
00285 snxtitem_xy(&pni, EF_PLANE, land.lnd_x, land.lnd_y);
00286 while (nxtitem(&pni, &plane)) {
00287 if (plane.pln_flags & PLN_LAUNCHED)
00288 continue;
00289 if (plane.pln_land != land.lnd_uid)
00290 continue;
00291 sprintf(buf, "loaded on %s", prship(&target));
00292 gift(target.shp_own, player->cnum, &plane, buf);
00293 plane.pln_mission = 0;
00294 putplane(plane.pln_uid, &plane);
00295 }
00296 }
00297 }
00298 return 0;
00299 }