]> git.pond.sub.org Git - empserver/blob - src/lib/commands/fuel.c
Import of Empire 4.2.12
[empserver] / src / lib / commands / fuel.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, 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 the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  fuel.c: fuel ships/land units
29  * 
30  *  Known contributors to this file:
31  *     
32  */
33
34 #include "misc.h"
35 #include "player.h"
36 #include "var.h"
37 #include "xy.h"
38 #include "ship.h"
39 #include "plane.h"
40 #include "land.h"
41 #include "nat.h"
42 #include "nsc.h"
43 #include "deity.h"
44 #include "file.h"
45 #include "sect.h"
46 #include "optlist.h"
47 #include "commands.h"
48
49
50 union item_u {
51         struct shpstr ship;
52         struct lndstr land;
53 };
54
55 int
56 fuel(void)
57 {
58         struct  nstr_item ni;
59         union   item_u item, item2;
60         int     type;
61         struct  mchrstr *mp;
62         struct  lchrstr *lcp;
63         s_char  *p;
64         int     fueled;
65         int     land_fuel, ship_fuel;
66         int     oil_amt, pet_amt, fuel_amt, tot_fuel, max_amt;
67         int     move_amt;
68         float   extra;
69         struct  sctstr sect;
70         struct  natstr *natp;
71         int     harbor,sector;
72         int     fuelled_ship = -1;
73         struct  nstr_item tender, ltender;
74         s_char  prompt[128];
75         s_char  buf[1024];
76
77         if (opt_FUEL == 0) {
78                 pr ("Option 'FUEL' not enabled\n");
79                 return RET_SYN;
80         }
81         if ((p = getstarg(player->argp[1], "Ship or land unit (s,l)? ", buf)) == 0)
82                 return RET_SYN;
83         type = ef_byname(p);
84         if (type == EF_SECTOR)
85                 type = EF_SHIP;
86         if (type != EF_SHIP && type != EF_LAND){
87                 pr("Ships or land units only! (s, l)\n" );
88                 return RET_SYN;
89         }
90         sprintf(prompt, "%s(s)? ", ef_nameof(type));
91         p = getstarg(player->argp[2], prompt, buf);
92         if (!snxtitem(&ni, type, p))
93                 return RET_SYN;
94         if (isdigit(*p))
95                 fuelled_ship = atoi(p);
96         p = getstarg(player->argp[3], "Amount: ", buf);
97         if (p == 0 || *p == 0)
98                 return RET_SYN;
99         fuel_amt = atoi(p);
100         if (fuel_amt <= 0){
101                 pr("Fuel amount must be positive!\n");
102                 return RET_FAIL;
103         }
104
105         ni.flags &= ~(EFF_OWNER);
106
107         while (nxtitem(&ni, (s_char *)&item)) {
108                 fueled = 0;
109                 if (type == EF_SHIP) {
110                         if (item.ship.shp_own != player->cnum){
111                                 int     rel;
112
113                                 if (item.ship.shp_uid != fuelled_ship)
114                                         continue;
115                                 natp=getnatp(player->cnum);
116                                 rel=getrel(natp,item.ship.shp_own);
117                                 if (rel < FRIENDLY)
118                                         continue;
119                         }
120                         if (!getsect(item.ship.shp_x, item.ship.shp_y, &sect))
121                                 continue;
122                         if (!item.ship.shp_own)
123                                 continue;
124
125                         if ((sect.sct_type != SCT_HARBR)  && (sect.sct_type != SCT_WATER) && (sect.sct_type != SCT_BSPAN) && (!opt_BIG_CITY || sect.sct_type != SCT_CAPIT)){
126                                 pr("Sector %s is not a harbor, bridge span, or sea.\n",
127                                         xyas(item.ship.shp_x, item.ship.shp_y,
128                                         item.ship.shp_own));
129                                 continue;
130                         }
131
132                         mp = &mchr[(int)item.ship.shp_type];
133
134                         harbor=0;
135                         if (sect.sct_type == SCT_HARBR || (opt_BIG_CITY && sect.sct_type == SCT_CAPIT)){
136                                 harbor=1;
137                                 oil_amt = getvar(V_OIL, (s_char *)&sect, EF_SECTOR);
138                                 pet_amt = getvar(V_PETROL, (s_char *)&sect, EF_SECTOR);
139                                 if ((oil_amt+pet_amt) == 0)
140                                         harbor=0;
141
142                                 if (sect.sct_effic < 2) {
143                                         pr("The harbor at %s is not 2%% efficient yet.\n",
144                                                 xyas(item.ship.shp_x,
145                                                         item.ship.shp_y,
146                                                         player->cnum));
147                                         harbor=0;
148                                 }
149                                 if ((sect.sct_own != player->cnum) && sect.sct_own)
150                                         harbor=0;
151                         }
152
153                         if ((mp->m_fuelu == 0) && (item.ship.shp_own == player->cnum)){
154                                 pr("%s does not use fuel!\n", prship(&item.ship));                              continue;
155                         }
156
157                         if (harbor){
158                                 ship_fuel = item.ship.shp_fuel;
159                                 oil_amt = getvar(V_OIL, (s_char *)&sect, EF_SECTOR);
160                                 pet_amt = getvar(V_PETROL, (s_char *)&sect, EF_SECTOR);
161                                 max_amt = mp->m_fuelc-ship_fuel;
162
163                                 if (max_amt == 0){
164                                         pr("%s already has a full fuel load.\n",prship(&item.ship));
165                                         continue;
166                                 }
167                                 tot_fuel = (oil_amt*50 + pet_amt*5);
168                                 if (tot_fuel == 0){
169                                         pr("No fuel in the harbor at %s!\n",
170                                                 xyas(sect.sct_x,sect.sct_y,
171                                                         player->cnum));
172                                         continue;
173                                 }
174                                 move_amt = min(tot_fuel, fuel_amt);
175                                 move_amt = min(move_amt, max_amt);
176
177                                 if (move_amt == 0)
178                                         continue;
179
180                                 item.ship.shp_fuel += move_amt;
181
182                                 fueled=1;
183                                 if ((pet_amt*5) >= move_amt){
184                                         extra = ((float)move_amt/5.0)-(move_amt/5);
185                                         if (extra > 0.0)
186                                                 putvar(V_PETROL,
187                                                         max((pet_amt-(move_amt/5))-1,0),
188                                                         (s_char *)&sect, EF_SECTOR);
189                                         else
190                                                 putvar(V_PETROL,
191                                                         max((pet_amt-(move_amt/5)),0),
192                                                         (s_char *)&sect, EF_SECTOR);
193                                 }else{
194                                         putvar(V_PETROL, 0, (s_char *)&sect, EF_SECTOR);
195                                         move_amt -= pet_amt*5;
196                                         extra = ((float)move_amt/50.0)-(move_amt/50);
197                                         putvar(V_OIL, max(oil_amt-(move_amt/50), 0),
198                                                 (s_char *)&sect, EF_SECTOR);
199                                         if (extra > 0.0)
200                                                 putvar(V_OIL,
201                                                         max((oil_amt-(move_amt/50))-1,0),
202                                                         (s_char *)&sect, EF_SECTOR);
203                                         else
204                                                 putvar(V_OIL,
205                                                         max((oil_amt-(move_amt/50)),0),
206                                                         (s_char *)&sect, EF_SECTOR);
207                                 }
208
209                                 /* load plague */
210                                 if (getvar(V_PSTAGE, (s_char *)&sect, EF_SECTOR) ==
211                                         PLG_INFECT && getvar(V_PSTAGE,
212                                         (s_char *)&item.ship, EF_SHIP) == PLG_HEALTHY)
213                                         putvar(V_PSTAGE, PLG_EXPOSED,
214                                                 (s_char *)&item.ship, EF_SHIP);
215
216                                 putsect(&sect);
217                                 putship(item.ship.shp_uid, &item.ship);
218                         }
219                         else{   /* not in a harbor */
220                                 if (!player->argp[4])
221                                         pr("%s is not in a supplied, efficient harbor\n", prship(&item.ship));
222                                 if (!snxtitem(&tender, EF_SHIP, getstarg(player->argp[4], "Oiler? ", buf)))
223                                         continue;
224
225                                 if (!check_ship_ok(&item.ship))
226                                     continue;
227
228                                 if (!nxtitem(&tender, (s_char *)&item2))
229                                         continue;
230
231                                 if (!(mchr[(int)item2.ship.shp_type].m_flags & M_OILER)){
232                                         pr("%s is not an oiler!\n",
233                                            prship(&item2.ship));
234                                         continue;
235                                 }
236                                 if (item2.ship.shp_own != player->cnum){
237                                         pr("You don't own that oiler!\n");
238                                         continue;
239                                 }
240
241                                 if ((item2.ship.shp_x != item.ship.shp_x) ||
242                                         (item2.ship.shp_y != item.ship.shp_y)){
243                                         pr("Not in the same sector!\n");
244                                         continue;
245                                 }
246                                 ship_fuel = item.ship.shp_fuel;
247                                 oil_amt = getvar(V_OIL, (s_char *)&item2.ship, EF_SHIP);
248                                 pet_amt = getvar(V_PETROL, (s_char *)&item2.ship, EF_SHIP);
249                                 max_amt = mp->m_fuelc-ship_fuel;
250
251                                 if (max_amt == 0){
252                                         pr("%s already has a full fuel load.\n", prship(&item.ship));
253                                         continue;
254                                 }
255                                 tot_fuel = oil_amt*50 + pet_amt*5;
256                                 move_amt = min(tot_fuel, fuel_amt);
257                                 move_amt = min(move_amt, max_amt);
258
259                                 if (move_amt == 0)
260                                         continue;
261
262                                 item.ship.shp_fuel += move_amt;
263
264                                 fueled=1;
265                                 if ((pet_amt*5) >= move_amt){
266                                         extra = ((float)move_amt/5.0)-(move_amt/5);
267                                         if (extra > 0.0)
268                                                 putvar(V_PETROL,
269                                                         max((pet_amt-(move_amt/5))-1,0),
270                                                         (s_char *)&item2.ship, EF_SHIP);
271                                         else
272                                                 putvar(V_PETROL,
273                                                         max((pet_amt-(move_amt/5)),0),
274                                                         (s_char *)&item2.ship, EF_SHIP);
275                                 }else{
276                                         putvar(V_PETROL, 0, (s_char *)&item2.ship, EF_SHIP);
277                                         move_amt -= pet_amt*5;
278                                         extra = ((float)move_amt/50.0)-(move_amt/50);
279                                         putvar(V_OIL, max(oil_amt-(move_amt/50), 0),
280                                                 (s_char *)&item2.ship, EF_SHIP);
281                                         if (extra > 0.0)
282                                                 putvar(V_OIL,
283                                                         max((oil_amt-(move_amt/50))-1,0),
284                                                         (s_char *)&item2.ship, EF_SHIP);
285                                         else
286                                                 putvar(V_OIL,
287                                                         max((oil_amt-(move_amt/50)),0),
288                                                         (s_char *)&item2.ship, EF_SHIP);
289                                 }
290
291                                 /* load plague */
292                                 if (getvar(V_PSTAGE, (s_char *)&item2.ship, EF_SHIP) ==
293                                         PLG_INFECT && getvar(V_PSTAGE,
294                                         (s_char *)&item.ship, EF_SHIP) == PLG_HEALTHY)
295                                         putvar(V_PSTAGE, PLG_EXPOSED,
296                                                 (s_char *)&item.ship, EF_SHIP);
297
298                                 putship(item.ship.shp_uid, &item.ship);
299                                 /* quick hack -KHS */
300                                 if (item.ship.shp_uid == item2.ship.shp_uid)
301                                         item2.ship.shp_fuel = item.ship.shp_fuel;
302                                 putship(item2.ship.shp_uid, &item2.ship);
303                         }
304                         pr("%s",prship(&item.ship));
305                 }
306                 else {
307                         if (item.land.lnd_own != player->cnum)
308                                 continue;
309
310                         if (!getsect(item.land.lnd_x, item.land.lnd_y, &sect))
311                                 continue;
312
313                         if (!player->owner)
314                                 continue;
315
316                         lcp = &lchr[(int)item.land.lnd_type];
317
318                         sector=1;
319                         oil_amt = getvar(V_OIL, (s_char *)&sect, EF_SECTOR);
320                         pet_amt = getvar(V_PETROL, (s_char *)&sect, EF_SECTOR);
321
322                         if ((oil_amt+pet_amt) == 0)
323                                 sector=0;
324
325                         if ((item.land.lnd_fuelu == 0) && (item.land.lnd_own == player->cnum)){
326                                 pr("%s does not use fuel!\n", prland(&item.land));
327                                 continue;
328                         }
329
330                         if (sector){
331                                 land_fuel = item.land.lnd_fuel;
332                                 oil_amt = getvar(V_OIL, (s_char *)&sect,
333                                                 EF_SECTOR);
334                                 pet_amt = getvar(V_PETROL, (s_char *)&sect,
335                                                 EF_SECTOR);
336                                 max_amt = item.land.lnd_fuelc-land_fuel;
337
338                                 if (max_amt == 0){
339                                         pr("%s already has a full fuel load.\n", prland(&item.land));
340                                         continue;
341                                 }
342                                 tot_fuel = (oil_amt*50 + pet_amt*5);
343                                 if (tot_fuel == 0){
344                                         pr("No fuel in the sector at %s!\n",
345                                                 xyas(sect.sct_x,sect.sct_y,
346                                                         player->cnum));
347                                         continue;
348                                 }
349                                 move_amt = min(tot_fuel, fuel_amt);
350                                 move_amt = min(move_amt, max_amt);
351
352                                 if (move_amt == 0)
353                                         continue;
354
355                                 item.land.lnd_fuel += move_amt;
356
357                                 fueled=1;
358                                 if ((pet_amt*5) >= move_amt){
359                                         extra = ((float)move_amt/5.0)-(move_amt/5);
360                                         if (extra > 0.0)
361                                                 putvar(V_PETROL,
362                                                         max((pet_amt-(move_amt/5))-1,0),
363                                                         (s_char *)&sect, EF_SECTOR);
364                                         else
365                                                 putvar(V_PETROL,
366                                                         max((pet_amt-(move_amt/5)),0),
367                                                         (s_char *)&sect, EF_SECTOR);
368                                 }else{
369                                         putvar(V_PETROL, 0, (s_char *)&sect, EF_SECTOR);
370                                         move_amt -= pet_amt*5;
371                                         extra = ((float)move_amt/50.0)-(move_amt/50);
372                                         putvar(V_OIL, max(oil_amt-(move_amt/50), 0),
373                                                 (s_char *)&sect, EF_SECTOR);
374                                         if (extra > 0.0)
375                                                 putvar(V_OIL,
376                                                         max((oil_amt-(move_amt/50))-1,0),
377                                                         (s_char *)&sect, EF_SECTOR);
378                                         else
379                                                 putvar(V_OIL,
380                                                         max((oil_amt-(move_amt/50)),0),
381                                                         (s_char *)&sect, EF_SECTOR);
382                                 }
383
384                                 /* load plague */
385                                 if (getvar(V_PSTAGE, (s_char *)&sect, EF_SECTOR) ==
386                                         PLG_INFECT && getvar(V_PSTAGE,
387                                         (s_char *)&item.land, EF_LAND) == PLG_HEALTHY)
388                                         putvar(V_PSTAGE, PLG_EXPOSED,
389                                                 (s_char *)&item.land, EF_LAND);
390
391                                 putsect(&sect);
392                                 putland(item.land.lnd_uid, &item.land);
393                         }
394                         else{   /* not in a sector */
395                                 if (!player->argp[4])
396                                         pr("%s is not in a supplied sector\n",
397                                            prland(&item.land));
398                                 if (!snxtitem(&ltender, EF_LAND,
399                                         getstarg(player->argp[4], "Supply unit? ", buf)))
400                                         continue;
401
402                                 if (!check_land_ok(&item.land))
403                                     continue;
404
405                                 if (!nxtitem(&ltender, (s_char *)&item2))
406                                         continue;
407
408                                 if (!(lchr[(int)item2.land.lnd_type].l_flags & L_SUPPLY)){
409                                         pr("%s is not a supply unit!\n",
410                                            prland(&item2.land));
411                                         continue;
412                                 }
413                                 if (item2.land.lnd_own != player->cnum){
414                                         pr("You don't own that unit!\n");
415                                         continue;
416                                 }
417
418                                 if ((item2.land.lnd_x != item.land.lnd_x) ||
419                                         (item2.land.lnd_y != item.land.lnd_y)){
420                                         pr("Not in the same sector!\n");
421                                         continue;
422                                 }
423                                 land_fuel = item.land.lnd_fuel;
424                                 oil_amt = getvar(V_OIL, (s_char *)&item2.land, EF_LAND);
425                                 pet_amt = getvar(V_PETROL, (s_char *)&item2.land, EF_LAND);
426                                 max_amt = item.land.lnd_fuelc-land_fuel;
427
428                                 if (max_amt == 0){
429                                         pr("%s already has a full fuel load.\n", prland(&item.land));
430                                         continue;
431                                 }
432                                 tot_fuel = oil_amt*50 + pet_amt*5;
433                                 move_amt = min(tot_fuel, fuel_amt);
434                                 move_amt = min(move_amt, max_amt);
435
436                                 if (move_amt == 0)
437                                         continue;
438
439                                 item.land.lnd_fuel += move_amt;
440
441                                 fueled=1;
442                                 if ((pet_amt*5) >= move_amt){
443                                         extra = ((float)move_amt/5.0)-(move_amt/5);
444                                         if (extra > 0.0)
445                                                 putvar(V_PETROL,
446                                                         max((pet_amt-(move_amt/5))-1,0),
447                                                         (s_char *)&item2.land, EF_LAND);
448                                         else
449                                                 putvar(V_PETROL,
450                                                         max((pet_amt-(move_amt/5)),0),
451                                                         (s_char *)&item2.land, EF_LAND);
452                                 }else{
453                                         putvar(V_PETROL, 0, (s_char *)&item2.land, EF_LAND);
454                                         move_amt -= pet_amt*5;
455                                         extra = ((float)move_amt/50.0)-(move_amt/50);
456                                         putvar(V_OIL, max(oil_amt-(move_amt/50), 0),
457                                                 (s_char *)&item2.land, EF_LAND);
458                                         if (extra > 0.0)
459                                                 putvar(V_OIL,
460                                                         max((oil_amt-(move_amt/50))-1,0),
461                                                         (s_char *)&item2.land, EF_LAND);
462                                         else
463                                                 putvar(V_OIL,
464                                                         max((oil_amt-(move_amt/50)),0),
465                                                         (s_char *)&item2.land, EF_LAND);
466                                 }
467
468                                 /* load plague */
469                                 if (getvar(V_PSTAGE, (s_char *)&item2.land, EF_LAND) ==
470                                         PLG_INFECT && getvar(V_PSTAGE,
471                                         (s_char *)&item.land, EF_LAND) == PLG_HEALTHY)
472                                         putvar(V_PSTAGE, PLG_EXPOSED,
473                                                 (s_char *)&item.land, EF_LAND);
474
475                                 putland(item.land.lnd_uid, &item.land);
476                                 /* quick hack -KHS */
477                                 if (item2.land.lnd_uid == item.land.lnd_uid)
478                                         item2.land.lnd_fuel = item.land.lnd_fuel;
479                                 putland(item2.land.lnd_uid, &item2.land);
480                         }
481                         pr("%s",prland(&item.land));
482                 }
483                 if (fueled){
484                         pr(" takes on %d fuel in %s\n",
485                         move_amt,
486                         xyas(item.ship.shp_x, item.ship.shp_y , player->cnum));
487                         if (player->cnum != item.ship.shp_own)
488                                 wu(0, item.ship.shp_own,
489                                    "%s takes on %d fuel in %s courtesy of %s\n",
490                                    prship(&item.ship),
491                                    move_amt,
492                                    xyas(item.ship.shp_x, item.ship.shp_y , 
493                                         item.ship.shp_own), 
494                                 cname(player->cnum));
495                 }
496         }
497         return RET_OK;
498 }