]> git.pond.sub.org Git - empserver/blob - src/lib/subs/unitsub.c
Rewrite the broken code to move cargo with its carrier
[empserver] / src / lib / subs / unitsub.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2008, 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  *  unitsub.c: Common subroutines for multiple type of units
29  * 
30  *  Known contributors to this file:
31  *     Ron Koenderink, 2007
32  *     Markus Armbruster, 2008
33  */
34
35 #include <config.h>
36
37 #include "empobj.h"
38 #include "file.h"
39 #include "player.h"
40 #include "prototypes.h"
41 #include "unit.h"
42
43 void
44 unit_list(struct emp_qelem *unit_list)
45 {
46     struct emp_qelem *qp;
47     struct emp_qelem *next;
48     struct ulist *ulp;
49     int type, npln, nch, nxl;
50     struct empobj *unit;
51     struct lndstr *lnd;
52     struct shpstr *shp;
53
54     if (CANT_HAPPEN(QEMPTY(unit_list)))
55         return;
56     qp = unit_list->q_back;
57     ulp = (struct ulist *)qp;
58     type = ulp->unit.ef_type;
59     if (CANT_HAPPEN(type != EF_LAND && type != EF_SHIP))
60         return;
61
62     if (type == EF_LAND)
63         pr("lnd#     land type       x,y    a  eff  sh gun xl  mu tech retr\n");
64     else
65         pr("shp#     ship type       x,y   fl  eff mil  sh gun pn he xl ln mob tech\n");
66
67     for (; qp != unit_list; qp = next) {
68         next = qp->q_back;
69         ulp = (struct ulist *)qp;
70         lnd = &ulp->unit.land;
71         shp = &ulp->unit.ship;
72         unit = &ulp->unit.gen;
73         if (CANT_HAPPEN(type != unit->ef_type))
74             continue;
75         pr("%4d ", unit->uid);
76         pr("%-16.16s ", empobj_chr_name(unit));
77         prxy("%4d,%-4d ", unit->x, unit->y, unit->own);
78         pr("%1.1s", &unit->group);
79         pr("%4d%%", unit->effic);
80         if (type == EF_LAND) {
81             pr("%4d", lnd->lnd_item[I_SHELL]);
82             pr("%4d", lnd->lnd_item[I_GUN]);
83             pr("%3d", lnd_nxlight(lnd));
84         } else {
85             pr("%4d", shp->shp_item[I_MILIT]);
86             pr("%4d", shp->shp_item[I_SHELL]);
87             pr("%4d", shp->shp_item[I_GUN]);
88             npln = shp_nplane(shp, &nch, &nxl, NULL);
89             pr("%3d%3d%3d", npln - nch - nxl, nch, nxl);
90             pr("%3d", shp_nland(shp));
91         }
92         pr("%4d", unit->mobil);
93         pr("%4d", unit->tech);
94         if (type == EF_LAND) {
95             pr("%4d%%", lnd->lnd_retreat);
96         }
97         pr("\n");
98     }
99 }
100
101 void
102 unit_put(struct emp_qelem *list, natid actor)
103 {
104     struct emp_qelem *qp;
105     struct emp_qelem *newqp;
106     struct ulist *ulp;
107     struct empobj *unit;
108
109     qp = list->q_back;
110     while (qp != list) {
111         ulp = (struct ulist *)qp;
112         unit = &ulp->unit.gen;
113         if (CANT_HAPPEN(unit->ef_type != EF_LAND
114                         && unit->ef_type != EF_SHIP))
115             continue;
116         if (actor) {
117             mpr(actor, "%s stopped at %s\n", obj_nameof(unit),
118                 xyas(unit->x, unit->y, unit->own));
119             if (unit->ef_type == EF_LAND) {
120                 if (ulp->mobil < -127)
121                     ulp->mobil = -127;
122                 unit->mobil = ulp->mobil;
123             }
124         }
125         if (unit->ef_type == EF_SHIP)
126             unit->mobil = (int)ulp->mobil;
127         put_empobj(unit->ef_type, unit->uid, unit);
128         newqp = qp->q_back;
129         emp_remque(qp);
130         free(qp);
131         qp = newqp;
132     }
133 }
134
135 char *
136 unit_path(int together, struct empobj *unit, char *buf)
137 {
138     coord destx;
139     coord desty;
140     struct sctstr d_sect, sect;
141     char *cp;
142     double dummy;
143     int mtype;
144
145     if (CANT_HAPPEN(unit->ef_type != EF_LAND && unit->ef_type != EF_SHIP))
146         return NULL;
147
148     if (!sarg_xy(buf, &destx, &desty))
149         return 0;
150     if (!together) {
151         pr("Cannot go to a destination sector if not all starting in the same sector\n");
152         return 0;
153     }
154     if (!getsect(destx, desty, &d_sect)) {
155         pr("%d,%d is not a sector\n", destx, desty);
156         return 0;
157     }
158     if (unit->ef_type == EF_SHIP) {
159         cp = BestShipPath(buf, unit->x, unit->y,
160                           d_sect.sct_x, d_sect.sct_y, player->cnum);
161         if (!cp || unit->mobil <= 0) {
162             pr("Can't get to '%s' right now.\n",
163                 xyas(d_sect.sct_x, d_sect.sct_y, player->cnum));
164             return 0;
165         }
166     } else {
167         getsect(unit->x, unit->y, &sect);
168         mtype = lnd_mobtype((struct lndstr *)unit);
169         cp = BestLandPath(buf, &sect, &d_sect, &dummy, mtype);
170         if (!cp) {
171             pr("No owned %s from %s to %s!\n",
172                mtype == MOB_RAIL ? "railway" : "path",
173                xyas(unit->x, unit->y, player->cnum),
174                xyas(d_sect.sct_x, d_sect.sct_y, player->cnum));
175             return 0;
176         }
177         pr("Using path '%s'\n", cp);
178     }
179     return cp;
180 }
181
182 void
183 unit_view(struct emp_qelem *list)
184 {
185     struct sctstr sect;
186     struct emp_qelem *qp;
187     struct emp_qelem *next;
188     struct ulist *ulp;
189
190     for (qp = list->q_back; qp != list; qp = next) {
191         next = qp->q_back;
192         ulp = (struct ulist *)qp;
193         if (CANT_HAPPEN(!(ef_flags(ulp->unit.ef_type) & EFF_XY)))
194             continue;
195         getsect(ulp->unit.gen.x, ulp->unit.gen.y, &sect);
196         if (ulp->unit.ef_type == EF_SHIP) {
197             if (((struct mchrstr *)ulp->chrp)->m_flags & M_FOOD)
198                 pr("[fert:%d] ", sect.sct_fertil);
199             if (((struct mchrstr *)ulp->chrp)->m_flags & M_OIL)
200                 pr("[oil:%d] ", sect.sct_oil);
201         }
202         pr("%s @ %s %d%% %s\n", obj_nameof(&ulp->unit.gen),
203             xyas(ulp->unit.gen.x, ulp->unit.gen.y, player->cnum),
204             sect.sct_effic, dchr[sect.sct_type].d_name);
205     }
206 }
207
208 /*
209  * Update cargo of CARRIER for movement or destruction.
210  * If the carrier is destroyed, destroy its cargo (planes, land units,
211  * nukes).
212  * Else update their location to the carrier's.  Any op sectors equal
213  * to location get updated, too.
214  */
215 void
216 unit_update_cargo(struct empobj *carrier)
217 {
218     int cargo_type;
219     struct nstr_item ni;
220     union empobj_storage obj;
221
222     for (cargo_type = EF_PLANE; cargo_type <= EF_NUKE; cargo_type++) {
223         snxtitem_cargo(&ni, cargo_type, carrier->ef_type, carrier->uid);
224         while (nxtitem(&ni, &obj)) {
225             if (!carrier->own) {
226                 mpr(obj.gen.own, "%s lost!\n", obj_nameof(&obj.gen));
227                 obj.gen.effic = 0;
228             } else {
229                 /* mission op-area centered on the obj travels with it */
230                 if (obj.gen.opx == obj.gen.x && obj.gen.opy == obj.gen.y) {
231                     obj.gen.opx = carrier->x;
232                     obj.gen.opy = carrier->y;
233                 }
234                 obj.gen.x = carrier->x;
235                 obj.gen.y = carrier->y;
236             }
237             put_empobj(cargo_type, obj.gen.uid, &obj);
238         }
239     }
240 }