]> git.pond.sub.org Git - empserver/blob - src/lib/commands/tran.c
601b1f7b58c46d28884fc52cca9c6dbcaafd0ddf
[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  *     Markus Armbruster, 2006
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_pmap(coord curx, coord cury, char *arg);
52 static int tran_nmap(coord curx, coord cury, char *arg);
53 static int tran_nuke(void);
54 static int tran_plane(void);
55
56 int
57 tran(void)
58 {
59     char *what;
60     char buf[1024];
61
62     what = getstarg(player->argp[1], "transport what (nuke or plane): ",
63                     buf);
64     if (what == 0)
65         return RET_SYN;
66     if (*what == 'n')
67         return tran_nuke();
68     else if (*what == 'p')
69         return tran_plane();
70     return RET_SYN;
71 }
72
73 static int
74 tran_nuke(void)
75 {
76     coord srcx, srcy;
77     coord dstx, dsty;
78     int mcost;
79     int weight, count;
80     int type, dam;
81     struct nstr_item nstr;
82     struct nukstr nuke;
83     struct sctstr sect;
84     struct sctstr endsect;
85
86     weight = 0;
87     count = 0;
88     if (!snxtitem(&nstr, EF_NUKE, player->argp[2]))
89         return RET_SYN;
90     while (nxtitem(&nstr, &nuke)) {
91         if (!player->owner)
92             continue;
93         type = nuke.nuk_type;
94         if (nuke.nuk_plane >= 0) {
95             pr("%s is armed and can't be transported\n", prnuke(&nuke));
96             return RET_FAIL;
97         }
98         if (count == 0) {
99             srcx = nuke.nuk_x;
100             srcy = nuke.nuk_y;
101         } else {
102             if (nuke.nuk_x != srcx || nuke.nuk_y != srcy) {
103                 pr("All nukes must be in the same sector.\n");
104                 return RET_FAIL;
105             }
106         }
107         weight += nchr[type].n_weight;
108         ++count;
109     }
110     if (count == 0) {
111         pr("No nukes\n");
112         return RET_FAIL;
113     }
114     if (!getsect(srcx, srcy, &sect) || !player->owner) {
115         pr("You don't own %s\n", xyas(srcx, srcy, player->cnum));
116         return RET_FAIL;
117     }
118     if (!military_control(&sect)) {
119         pr("Military control required to move nukes.\n");
120         return RET_FAIL;
121     }
122     dam = 0;
123     mcost = move_ground(&sect, &endsect, weight,
124                         player->argp[3], tran_nmap, 0, &dam);
125     if (mcost < 0)
126         return 0;
127
128     dstx = endsect.sct_x;
129     dsty = endsect.sct_y;
130     snxtitem_rewind(&nstr);
131     while (nxtitem(&nstr, &nuke)) {
132         if (!player->owner)
133             continue;
134         /* TODO apply dam */
135         nuke.nuk_x = dstx;
136         nuke.nuk_y = dsty;
137         nuke.nuk_mission = 0;
138         putnuke(nuke.nuk_uid, &nuke);
139     }
140     if (mcost > 0)
141         pr("Total movement cost = %d\n", mcost);
142     else
143         pr("No mobility used\n");
144     getsect(srcx, srcy, &sect);
145     sect.sct_mobil -= mcost;
146     if (sect.sct_mobil < 0)
147         sect.sct_mobil = 0;
148     putsect(&sect);
149     return RET_OK;
150 }
151
152 static int
153 tran_plane(void)
154 {
155     coord srcx, srcy;
156     coord dstx, dsty;
157     int mcost;
158     int weight, count;
159     int type, dam;
160     struct nstr_item nstr;
161     struct plnstr plane;
162     struct sctstr sect;
163     struct sctstr endsect;
164
165     weight = 0;
166     count = 0;
167     if (!snxtitem(&nstr, EF_PLANE, player->argp[2]))
168         return RET_SYN;
169     /*
170      * First do some sanity checks: make sure that they are all in the,
171      * same sector, not on ships, owned, etc.
172      * No one could seriously want to move planes in parallel from
173      * several sectors!
174      */
175     while (nxtitem(&nstr, &plane)) {
176         if (!player->owner)
177             continue;
178         type = plane.pln_type;
179         if (plane.pln_ship >= 0) {
180             pr("%s is at sea and can't be transported\n", prplane(&plane));
181             return RET_FAIL;
182         } else if (plane.pln_harden != 0) {
183             pr("%s has been hardened and can't be transported\n",
184                prplane(&plane));
185             return RET_FAIL;
186         } else if ((plane.pln_flags & PLN_LAUNCHED) &&
187                    (plchr[type].pl_flags & P_O)) {
188             pr("%s is in space and can't be transported\n",
189                prplane(&plane));
190             return RET_FAIL;
191         }
192         if (count == 0) {
193             srcx = plane.pln_x;
194             srcy = plane.pln_y;
195         } else {
196             if (plane.pln_x != srcx || plane.pln_y != srcy) {
197                 pr("All planes must be in the same sector.\n");
198                 return RET_FAIL;
199             }
200         }
201         weight += plchr[type].pl_lcm + (plchr[type].pl_hcm * 2);
202         ++count;
203     }
204     if (count == 0) {
205         pr("No planes\n");
206         return RET_FAIL;
207     }
208     if (!getsect(srcx, srcy, &sect) || !player->owner) {
209         pr("You don't own %s\n", xyas(srcx, srcy, player->cnum));
210         return RET_FAIL;
211     }
212     if (!military_control(&sect)) {
213         pr("Military control required to move planes.\n");
214         return RET_FAIL;
215     }
216     dam = 1;
217     mcost = move_ground(&sect, &endsect, weight,
218                         player->argp[3], tran_pmap, 0, &dam);
219     dam /= count;
220     if (mcost < 0)
221         return 0;
222
223     dstx = endsect.sct_x;
224     dsty = endsect.sct_y;
225     snxtitem_rewind(&nstr);
226     while (nxtitem(&nstr, &plane)) {
227         if (!player->owner)
228             continue;
229         if (dam)
230             planedamage(&plane, dam);
231         plane.pln_x = dstx;
232         plane.pln_y = dsty;
233         plane.pln_mission = 0;
234         putplane(plane.pln_uid, &plane);
235     }
236     if (mcost > 0)
237         pr("Total movement cost = %d\n", mcost);
238     else
239         pr("No mobility used\n");
240     getsect(srcx, srcy, &sect);
241     sect.sct_mobil -= mcost;
242     if (sect.sct_mobil < 0)
243         sect.sct_mobil = 0;
244     putsect(&sect);
245     return RET_OK;
246 }
247
248 /*
249  * Pretty tacky, but it works.
250  * If more commands start doing this, then
251  * rewrite map to do the right thing.
252  */
253 /*ARGSUSED*/
254 static int
255 tran_pmap(coord curx, coord cury, char *arg)
256 {
257     return display_region_map("pmap", curx, cury, arg);
258 }
259
260 static int
261 tran_nmap(coord curx, coord cury, char *arg)
262 {
263     return display_region_map("nmap", curx, cury, arg);
264 }
265