]> git.pond.sub.org Git - empserver/blob - src/lib/commands/tran.c
(nukstr): Make it a struct genitem: add members nuk_effic, nuk_mobil,
[empserver] / src / lib / commands / tran.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2006, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See files README, COPYING and CREDITS in the root of the source
23  *  tree for related information and legal notices.  It is expected
24  *  that future projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  tran.c: Transport nuclear devices and planes
29  * 
30  *  Known contributors to this file:
31  *     Steve McClure, 2000
32  *  
33  */
34
35 #include <config.h>
36
37 #include <string.h>
38 #include "misc.h"
39 #include "player.h"
40 #include "sect.h"
41 #include "nuke.h"
42 #include "xy.h"
43 #include "nsc.h"
44 #include "plane.h"
45 #include "ship.h"
46 #include "file.h"
47 #include "nat.h"
48 #include "land.h"
49 #include "commands.h"
50
51 static int tran_map(coord curx, coord cury, char *arg);
52 static int tran_nuke(void);
53 static int tran_plane(void);
54
55 int
56 tran(void)
57 {
58     char *what;
59     char buf[1024];
60
61     what = getstarg(player->argp[1], "transport what (nuke or plane): ",
62                     buf);
63     if (what == 0)
64         return RET_SYN;
65     if (*what == 'n')
66         return tran_nuke();
67     else if (*what == 'p')
68         return tran_plane();
69     return RET_SYN;
70 }
71
72 static int
73 tran_nuke(void)
74 {
75     coord srcx, srcy;
76     coord dstx, dsty;
77     int mcost;
78     int weight, count;
79     int type, dam;
80     struct nstr_item nstr;
81     struct nukstr nuke;
82     struct sctstr sect;
83     struct sctstr endsect;
84
85     weight = 0;
86     count = 0;
87     if (!snxtitem(&nstr, EF_NUKE, player->argp[2]))
88         return RET_SYN;
89     while (nxtitem(&nstr, &nuke)) {
90         if (!player->owner)
91             continue;
92         type = nuke.nuk_type;
93         if (nuke.nuk_plane >= 0) {
94             pr("%s is armed and can't be transported\n", prnuke(&nuke));
95             return RET_FAIL;
96         }
97         if (count == 0) {
98             srcx = nuke.nuk_x;
99             srcy = nuke.nuk_y;
100         } else {
101             if (nuke.nuk_x != srcx || nuke.nuk_y != srcy) {
102                 pr("All nukes must be in the same sector.\n");
103                 return RET_FAIL;
104             }
105         }
106         weight += nchr[type].n_weight;
107         ++count;
108     }
109     if (count == 0) {
110         pr("No planes\n");
111         return RET_FAIL;
112     }
113     if (!getsect(srcx, srcy, &sect) || !player->owner) {
114         pr("You don't own %s\n", xyas(srcx, srcy, player->cnum));
115         return RET_FAIL;
116     }
117     if (!military_control(&sect)) {
118         pr("Military control required to move nukes.\n");
119         return RET_FAIL;
120     }
121     dam = 0;
122     mcost = move_ground(&sect, &endsect, weight,
123                         player->argp[3], tran_map, 0, &dam);
124     if (mcost < 0)
125         return 0;
126
127     dstx = endsect.sct_x;
128     dsty = endsect.sct_y;
129     snxtitem_rewind(&nstr);
130     while (nxtitem(&nstr, &nuke)) {
131         if (!player->owner)
132             continue;
133         /* TODO apply dam */
134         nuke.nuk_x = dstx;
135         nuke.nuk_y = dsty;
136         nuke.nuk_mission = 0;
137         putnuke(nuke.nuk_uid, &nuke);
138     }
139     if (mcost > 0)
140         pr("Total movement cost = %d\n", mcost);
141     else
142         pr("No mobility used\n");
143     getsect(srcx, srcy, &sect);
144     sect.sct_mobil -= mcost;
145     if (sect.sct_mobil < 0)
146         sect.sct_mobil = 0;
147     putsect(&sect);
148     return RET_OK;
149 }
150
151 static int
152 tran_plane(void)
153 {
154     coord srcx, srcy;
155     coord dstx, dsty;
156     int mcost;
157     int weight, count;
158     int type, dam;
159     struct nstr_item nstr;
160     struct plnstr plane;
161     struct sctstr sect;
162     struct sctstr endsect;
163
164     weight = 0;
165     count = 0;
166     if (!snxtitem(&nstr, EF_PLANE, player->argp[2]))
167         return RET_SYN;
168     /*
169      * First do some sanity checks: make sure that they are all in the,
170      * same sector, not on ships, owned, etc.
171      * No one could seriously want to move planes in parallel from
172      * several sectors!
173      */
174     while (nxtitem(&nstr, &plane)) {
175         if (!player->owner)
176             continue;
177         type = plane.pln_type;
178         if (plane.pln_ship >= 0) {
179             pr("%s is at sea and can't be transported\n", prplane(&plane));
180             return RET_FAIL;
181         } else if (plane.pln_harden != 0) {
182             pr("%s has been hardened and can't be transported\n",
183                prplane(&plane));
184             return RET_FAIL;
185         } else if ((plane.pln_flags & PLN_LAUNCHED) &&
186                    (plchr[type].pl_flags & P_O)) {
187             pr("%s is in space and can't be transported\n",
188                prplane(&plane));
189             return RET_FAIL;
190         }
191         if (count == 0) {
192             srcx = plane.pln_x;
193             srcy = plane.pln_y;
194         } else {
195             if (plane.pln_x != srcx || plane.pln_y != srcy) {
196                 pr("All planes must be in the same sector.\n");
197                 return RET_FAIL;
198             }
199         }
200         weight += plchr[type].pl_lcm + (plchr[type].pl_hcm * 2);
201         ++count;
202     }
203     if (count == 0) {
204         pr("No planes\n");
205         return RET_FAIL;
206     }
207     if (!getsect(srcx, srcy, &sect) || !player->owner) {
208         pr("You don't own %s\n", xyas(srcx, srcy, player->cnum));
209         return RET_FAIL;
210     }
211     if (!military_control(&sect)) {
212         pr("Military control required to move planes.\n");
213         return RET_FAIL;
214     }
215     dam = 1;
216     mcost = move_ground(&sect, &endsect, weight,
217                         player->argp[3], tran_map, 0, &dam);
218     dam /= count;
219     if (mcost < 0)
220         return 0;
221
222     dstx = endsect.sct_x;
223     dsty = endsect.sct_y;
224     snxtitem_rewind(&nstr);
225     while (nxtitem(&nstr, &plane)) {
226         if (!player->owner)
227             continue;
228         if (dam)
229             planedamage(&plane, dam);
230         plane.pln_x = dstx;
231         plane.pln_y = dsty;
232         plane.pln_mission = 0;
233         putplane(plane.pln_uid, &plane);
234     }
235     if (mcost > 0)
236         pr("Total movement cost = %d\n", mcost);
237     else
238         pr("No mobility used\n");
239     getsect(srcx, srcy, &sect);
240     sect.sct_mobil -= mcost;
241     if (sect.sct_mobil < 0)
242         sect.sct_mobil = 0;
243     putsect(&sect);
244     return RET_OK;
245 }
246
247 /*
248  * Pretty tacky, but it works.
249  * If more commands start doing this, then
250  * rewrite map to do the right thing.
251  */
252 /*ARGSUSED*/
253 static int
254 tran_map(coord curx, coord cury, char *arg)
255 {
256     player->argp[0] = "map";
257     player->argp[1] = arg;
258     player->argp[2] = NULL;
259     player->condarg = NULL;
260     return map();
261 }