]> git.pond.sub.org Git - empserver/blob - src/lib/commands/upgr.c
a4d886e1bdbd88e407a6a35070c0097dbc773d7f
[empserver] / src / lib / commands / upgr.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2021, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                Ken Stevens, Steve McClure, Markus Armbruster
5  *
6  *  Empire 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 3 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, see <http://www.gnu.org/licenses/>.
18  *
19  *  ---
20  *
21  *  See files README, COPYING and CREDITS in the root of the source
22  *  tree for related information and legal notices.  It is expected
23  *  that future projects/authors will amend these files as needed.
24  *
25  *  ---
26  *
27  *  upgr.c: Upgrade tech of ships/planes/units
28  *
29  *  Known contributors to this file:
30  *     Dave Pare, 1986
31  *     Steve McClure, 1996-2000
32  *     Markus Armbruster, 2004-2016
33  */
34
35 #include <config.h>
36
37 #include "commands.h"
38 #include "land.h"
39 #include "plane.h"
40 #include "ship.h"
41
42 enum {
43     UPGR_COST = 15,             /* how much avail and money to charge */
44     UPGR_EFF = 35               /* efficiency reduction */
45 };
46
47 static int lupgr(void);
48 static int pupgr(void);
49 static int supgr(void);
50
51 int
52 upgr(void)
53 {
54     char *p;
55     char buf[1024];
56
57     if (!(p = getstarg(player->argp[1], "Ship, land, or plane? ", buf)))
58         return RET_SYN;
59     switch (*p) {
60     case 's':
61     case 'S':
62         return supgr();
63     case 'p':
64     case 'P':
65         return pupgr();
66     case 'l':
67     case 'L':
68         return lupgr();
69     default:
70         break;
71     }
72     pr("Ships, land units or planes only!\n");
73     return RET_SYN;
74 }
75
76 static int
77 lupgr(void)
78 {
79     struct sctstr sect;
80     struct natstr *natp;
81     struct nstr_item ni;
82     struct lndstr land;
83     struct lchrstr *lp;
84     int n;
85     int tlev;
86     int avail, cost;
87     int cash;
88
89     if (!snxtitem(&ni, EF_LAND, player->argp[2], NULL))
90         return RET_SYN;
91     natp = getnatp(player->cnum);
92     cash = natp->nat_money;
93     tlev = (int)natp->nat_level[NAT_TLEV];
94     n = 0;
95     while (nxtitem(&ni, &land)) {
96         if (land.lnd_own == 0)
97             continue;
98         getsect(land.lnd_x, land.lnd_y, &sect);
99         if (sect.sct_own != player->cnum)
100             continue;
101         if (sect.sct_type != SCT_HEADQ || sect.sct_effic < 60)
102             continue;
103         if (relations_with(land.lnd_own, sect.sct_own) < FRIENDLY) {
104             pr("You are not on friendly terms with the owner of unit %d!\n",
105                land.lnd_uid);
106             continue;
107         }
108         n++;
109         lp = &lchr[(int)land.lnd_type];
110         avail = (lp->l_bwork * UPGR_COST + 99) / 100;
111         if (sect.sct_avail < avail) {
112             pr("Not enough available work in %s to upgrade a %s\n",
113                xyas(sect.sct_x, sect.sct_y, player->cnum), lp->l_name);
114             pr(" (%d available work required)\n", avail);
115             continue;
116         }
117         if (land.lnd_effic < 60) {
118             pr("%s is too damaged to upgrade!\n", prland(&land));
119             continue;
120         }
121         if (land.lnd_tech >= tlev) {
122             pr("%s tech: %d, yours is only %d\n",
123                prland(&land), land.lnd_tech, tlev);
124             continue;
125         }
126         cost = lp->l_cost * UPGR_COST / 100;
127         if (cost + player->dolcost > cash) {
128             pr("You don't have enough money to upgrade %s!\n",
129                prland(&land));
130             continue;
131         }
132
133         sect.sct_avail -= avail;
134         land.lnd_effic -= UPGR_EFF;
135         lnd_set_tech(&land, tlev);
136         land.lnd_harden = 0;
137         land.lnd_mission = 0;
138
139         putland(land.lnd_uid, &land);
140         putsect(&sect);
141         player->dolcost += cost;
142         pr("%s upgraded to tech %d, at a cost of %d\n",
143            prland(&land), land.lnd_tech, cost);
144         if (land.lnd_own != player->cnum)
145             wu(0, land.lnd_own,
146                "%s upgraded by %s to tech %d, at a cost of %d\n",
147                prland(&land), cname(player->cnum), land.lnd_tech, cost);
148     }
149     if (n == 0) {
150         pr("No land units\n");
151         return RET_SYN;
152     }
153     return RET_OK;
154 }
155
156 static int
157 supgr(void)
158 {
159     struct sctstr sect;
160     struct natstr *natp;
161     struct nstr_item ni;
162     struct shpstr ship;
163     struct mchrstr *mp;
164     int n;
165     int tlev;
166     int avail, cost;
167     int cash;
168
169     if (!snxtitem(&ni, EF_SHIP, player->argp[2], NULL))
170         return RET_SYN;
171     natp = getnatp(player->cnum);
172     cash = natp->nat_money;
173     tlev = (int)natp->nat_level[NAT_TLEV];
174     n = 0;
175     while (nxtitem(&ni, &ship)) {
176         if (ship.shp_own == 0)
177             continue;
178         getsect(ship.shp_x, ship.shp_y, &sect);
179         if (sect.sct_own != player->cnum)
180             continue;
181         if (sect.sct_type != SCT_HARBR || sect.sct_effic < 60)
182             continue;
183         if (relations_with(ship.shp_own, sect.sct_own) < FRIENDLY) {
184             pr("You are not on friendly terms with the owner of ship %d!\n",
185                ship.shp_uid);
186             continue;
187         }
188         n++;
189         mp = &mchr[(int)ship.shp_type];
190         avail = (mp->m_bwork * UPGR_COST + 99) / 100;
191         if (sect.sct_avail < avail) {
192             pr("Not enough available work in %s to upgrade a %s\n",
193                xyas(sect.sct_x, sect.sct_y, player->cnum), mp->m_name);
194             pr(" (%d available work required)\n", avail);
195             continue;
196         }
197         if (ship.shp_effic < 60) {
198             pr("%s is too damaged to upgrade!\n", prship(&ship));
199             continue;
200         }
201         if (ship.shp_tech >= tlev) {
202             pr("%s tech: %d, yours is only %d\n",
203                prship(&ship), ship.shp_tech, tlev);
204             continue;
205         }
206         cost = mp->m_cost * UPGR_COST / 100;
207         if (cost + player->dolcost > cash) {
208             pr("You don't have enough money to upgrade %s!\n",
209                prship(&ship));
210             continue;
211         }
212
213         sect.sct_avail -= avail;
214         ship.shp_effic -= UPGR_EFF;
215         shp_set_tech(&ship, tlev);
216         ship.shp_mission = 0;
217
218         putship(ship.shp_uid, &ship);
219         putsect(&sect);
220         player->dolcost += cost;
221         pr("%s upgraded to tech %d, at a cost of %d\n",
222            prship(&ship), ship.shp_tech, cost);
223         if (ship.shp_own != player->cnum)
224             wu(0, ship.shp_own,
225                "%s upgraded by %s to tech %d, at a cost of %d\n",
226                prship(&ship), cname(player->cnum), ship.shp_tech, cost);
227     }
228     if (n == 0) {
229         pr("No ships\n");
230         return RET_SYN;
231     }
232     return RET_OK;
233 }
234
235 static int
236 pupgr(void)
237 {
238     struct sctstr sect;
239     struct natstr *natp;
240     struct nstr_item ni;
241     struct plnstr plane;
242     struct plchrstr *pp;
243     int n;
244     int tlev;
245     int avail, cost;
246     int cash;
247
248     if (!snxtitem(&ni, EF_PLANE, player->argp[2], NULL))
249         return RET_SYN;
250     natp = getnatp(player->cnum);
251     cash = natp->nat_money;
252     tlev = (int)natp->nat_level[NAT_TLEV];
253     n = 0;
254     while (nxtitem(&ni, &plane)) {
255         if (plane.pln_own == 0)
256             continue;
257         getsect(plane.pln_x, plane.pln_y, &sect);
258         if (sect.sct_own != player->cnum)
259             continue;
260         if (sect.sct_type != SCT_AIRPT || sect.sct_effic < 60)
261             continue;
262         if (relations_with(plane.pln_own, sect.sct_own) < FRIENDLY) {
263             pr("You are not on friendly terms with the owner of plane %d!\n",
264                plane.pln_uid);
265             continue;
266         }
267         if (pln_is_in_orbit(&plane)) {
268             pr("Plane %s is in orbit!\n", prplane(&plane));
269             continue;
270         }
271         if (plane.pln_flags & PLN_LAUNCHED)
272             continue;
273         n++;
274         pp = &plchr[(int)plane.pln_type];
275         avail = (pp->pl_bwork * UPGR_COST + 99) / 100;
276         if (sect.sct_avail < avail) {
277             pr("Not enough available work in %s to upgrade a %s\n",
278                xyas(sect.sct_x, sect.sct_y, player->cnum), pp->pl_name);
279             pr(" (%d available work required)\n", avail);
280             continue;
281         }
282         if (plane.pln_effic < 60) {
283             pr("%s is too damaged to upgrade!\n", prplane(&plane));
284             continue;
285         }
286         if (plane.pln_tech >= tlev) {
287             pr("%s tech: %d, yours is only %d\n",
288                prplane(&plane), plane.pln_tech, tlev);
289             continue;
290         }
291         cost = pp->pl_cost * UPGR_COST / 100;
292         if (cost + player->dolcost > cash) {
293             pr("You don't have enough money to upgrade %s!\n",
294                prplane(&plane));
295             continue;
296         }
297
298         sect.sct_avail -= avail;
299         plane.pln_effic -= UPGR_EFF;
300         pln_set_tech(&plane, tlev);
301         plane.pln_harden = 0;
302         plane.pln_mission = 0;
303
304         putplane(plane.pln_uid, &plane);
305         putsect(&sect);
306         player->dolcost += cost;
307         pr("%s upgraded to tech %d, at a cost of %d\n",
308            prplane(&plane), plane.pln_tech, cost);
309         if (plane.pln_own != player->cnum)
310             wu(0, plane.pln_own,
311                "%s upgraded by %s to tech %d, at a cost of %d\n",
312                prplane(&plane), cname(player->cnum), plane.pln_tech, cost);
313     }
314     if (n == 0) {
315         pr("No planes.\n");
316         return RET_SYN;
317     }
318     return RET_OK;
319 }