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
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.
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.
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
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.
28 * plnsub.c: Plane subroutine stuff
30 * Known contributors to this file:
33 * Steve McClure, 1998-2000
51 #include "prototypes.h"
55 pln_onewaymission(struct sctstr *target, int *shipno, int *flagp)
66 if ((target->sct_own && target->sct_own != player->cnum &&
67 (getrel(getnatp(target->sct_own),player->cnum) != ALLIED)) &&
68 (target->sct_type != SCT_HARBR) &&
69 (target->sct_type != SCT_BSPAN)) {
70 pr("Nowhere to land at sector %s!\n",
71 xyas(target->sct_x, target->sct_y, player->cnum));
74 if (target->sct_type == SCT_MOUNT) {
75 pr("Nowhere to land at sector %s!\n",
76 xyas(target->sct_x, target->sct_y, player->cnum));
80 if (target->sct_type != SCT_AIRPT || target->sct_effic < 60)
82 if (target->sct_type == SCT_WATER || target->sct_type == SCT_HARBR
83 || target->sct_type == SCT_BSPAN) {
84 nships = carriersatxy(target->sct_x, target->sct_y,
85 M_FLY|M_CHOPPER, 0, player->cnum);
87 if (target->sct_type == SCT_WATER){
88 pr("Nowhere to land at sector %s!\n",
89 xyas(target->sct_x, target->sct_y, player->cnum));
92 if ((target->sct_own && target->sct_own != player->cnum)
93 && (getrel(getnatp(target->sct_own),player->cnum) != ALLIED)){
94 pr("Nowhere to land at sector %s!\n",
96 target->sct_y, player->cnum));
107 if (!(p = getstarg(0, "Carrier #? ", buf)) || !*p)
110 if (n < 0 || !getship(n, &ship) || (!player->owner &&
111 (getrel(getnatp(ship.shp_own),player->cnum) != ALLIED))) {
115 if (ship.shp_x != target->sct_x ||
116 ship.shp_y != target->sct_y) {
117 pr("Ship #%d not in %s\n", n,
118 xyas(target->sct_x, target->sct_y, player->cnum));
121 if (!(mchr[(int)ship.shp_type].m_flags & M_FLY)
122 && !(mchr[(int)ship.shp_type].m_flags & M_XLIGHT)
123 && !(mchr[(int)ship.shp_type].m_flags & M_CHOPPER)
125 pr("Can't land on %s.\n", prship(&ship));
128 pr("landing on carrier %d\n",n);
131 if (mchr[(int)ship.shp_type].m_flags & M_FLY)
133 if (mchr[(int)ship.shp_type].m_flags & M_CHOPPER)
135 if (mchr[(int)ship.shp_type].m_flags & M_XLIGHT)
138 if ((target->sct_own && target->sct_own != player->cnum) &&
139 (getrel(getnatp(target->sct_own),player->cnum)!= ALLIED) &&
141 pr("Nowhere to land at sector %s!\n",
142 xyas(target->sct_x, target->sct_y, player->cnum));
147 if ((target->sct_own == 0) && (cno < 0)) {
148 pr("Nowhere to land at sector %s!\n",
149 xyas(target->sct_x, target->sct_y, player->cnum));
159 pln_newlanding(struct emp_qelem *list, coord tx, coord ty, int cno)
161 struct emp_qelem *qp;
168 for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
169 plp = (struct plist *)qp;
170 /* XXX - need to restrict # of planes per ship */
173 if (!can_be_on_ship(plp->plane.pln_uid,ship.shp_uid))
174 pr("\t%s cannot land on ship #%d! %s aborts!\n",prplane(&plp->plane),cno,prplane(&plp->plane));
175 else if (!put_plane_on_ship(&plp->plane,&ship))
176 pr("\tNo room on ship #%d! %s aborts!\n",cno,prplane(&plp->plane));
178 if (plp->plane.pln_own != ship.shp_own){
179 /* plp->plane.pln_own = ship.shp_own;*/
181 "%s %s lands on your %s\n",
183 prplane(&plp->plane),
189 plp->plane.pln_x = tx;
190 plp->plane.pln_y = ty;
191 getsect(tx,ty,§);
192 if (plp->plane.pln_own != sect.sct_own){
193 /* plp->plane.pln_own = sect.sct_own;*/
195 "%s %s lands at your sector %s\n",
197 prplane(&plp->plane),
198 xyas(tx,ty,sect.sct_own));
200 plp->plane.pln_ship = cno;
204 putship(ship.shp_uid, &ship);
208 pln_dropoff(struct emp_qelem *list, struct ichrstr *ip, coord tx, coord ty, s_char *ptr, int type)
210 struct emp_qelem *qp;
222 for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
223 plp = (struct plist *)qp;
226 if (type == EF_SECTOR &&
227 (((struct sctstr *)ptr)->sct_type == SCT_WATER) &&
228 ip->i_vtype == V_SHELL){
229 mines_there = getvar(V_MINE, ptr, EF_SECTOR);
230 putvar(V_MINE, amt + mines_there, ptr, EF_SECTOR);
231 pr("%d mines laid in %s.\n", amt,
232 xyas(((struct sctstr *)ptr)->sct_x,
233 ((struct sctstr *)ptr)->sct_y, player->cnum));
235 map_set(player->cnum, ((struct sctstr *)ptr)->sct_x,
236 ((struct sctstr *)ptr)->sct_y, 'X', 0))
237 writemap(player->cnum);
238 putsect((struct sctstr *) ptr);
240 there = getvar(ip->i_vtype, ptr, type) + amt;
242 if (type == EF_SHIP) {
243 ship = (struct shpstr *) ptr;
244 mp = &mchr[(int)ship->shp_type];
245 max = vl_find(ip->i_vtype, mp->m_vtype,
246 mp->m_vamt, (int)mp->m_nv);
249 pr("%d excess %s discarded\n", max-there, ip->i_name);
253 putvar(ip->i_vtype, there, ptr, type);
254 pr("%d %s landed safely", amt, ip->i_name);
255 if (type == EF_SECTOR) {
256 struct sctstr *sectp = (struct sctstr *)ptr;
257 if (sectp->sct_own != player->cnum)
258 wu(0, sectp->sct_own, "%s planes drop %d %s in %s\n",
259 cname(player->cnum),amt,ip->i_name,
260 xyas(sectp->sct_x,sectp->sct_y,
262 pr(" at %s\n", xyas(tx, ty, player->cnum));
263 putsect((struct sctstr *) ptr);
265 struct shpstr *sp = (struct shpstr *)ptr;
266 if (sp->shp_own != player->cnum)
267 wu(0, sp->shp_own, "%s planes land %d %s on carrier %d\n",
268 cname(player->cnum),amt,ip->i_name,sp->shp_uid);
269 pr(" on carrier #%d\n", ship->shp_uid);
270 putship(ship->shp_uid, ship);
276 pln_sel(struct nstr_item *ni, struct emp_qelem *list, struct sctstr *ap, int ap_to_target, int rangemult, int wantflags, int nowantflags)
283 struct plchrstr *pcp;
286 register int bad,bad1;
290 while (nxtitem(ni, (s_char *)&plane)) {
293 if (plane.pln_mobil <= (s_char)0)
296 if (ontradingblock(EF_PLANE, (int *)&plane)) {
297 pr("plane #%d inelligible - it's for sale.\n", plane.pln_uid);
302 range = mapdist(plane.pln_x, plane.pln_y, ap->sct_x, ap->sct_y);
304 pr("%s too far from assembly point\n",
308 if (plane.pln_effic < 40) {
309 pr("%s not efficient enough (must be 40%%)\n", prplane(&plane));
312 range += ap_to_target;
313 pcp = &plchr[(int)plane.pln_type];
317 for(x=0;x<sizeof(wantflags)*8;x++){
319 if ((wantflags & y) == y)
320 if ((pcp->pl_flags & y) != y){
336 if ((pcp->pl_flags & P_ESC) ||
337 (pcp->pl_flags & P_F))
341 if ((wantflags & P_L) && (pcp->pl_flags & P_L))
343 if ((wantflags & P_K) && (pcp->pl_flags & P_K))
345 if ((wantflags & P_E) && (pcp->pl_flags & P_E))
354 for(x=0;x<sizeof(nowantflags)*8;x++){
356 if ((nowantflags & y) == y)
357 if ((pcp->pl_flags & y) == y)
364 if (plane.pln_range < range) {
365 pr("%s out of range (%d:%d)\n", prplane(&plane),
366 plane.pln_range, range);
369 if (plane.pln_ship >= 0) {
370 if (!getship(plane.pln_ship, &ship) ||
371 plane.pln_own != player->cnum) {
374 pr("(note) ship not valid for %s\n",
376 putplane(plane.pln_uid, &plane);
379 if (!can_be_on_ship(plane.pln_uid,ship.shp_uid))
381 if (ship.shp_effic < SHIP_MINEFF)
383 if (ship.shp_effic < 50)
385 /* Can't fly off non-owned ships or non-allied ship */
386 if ((ship.shp_own != player->cnum) &&
387 (getrel(getnatp(ship.shp_own), player->cnum) != ALLIED)) {
388 pr("(note) An ally does not own the ship %s is on\n",
393 if (plane.pln_land >= 0) {
394 if (!getland(plane.pln_land, &land) ||
395 (plane.pln_own != player->cnum)) {
398 pr("(note) land unit not valid for %s\n",
400 putplane(plane.pln_uid, &plane);
403 if (!(plchr[(int)plane.pln_type].pl_flags & P_E))
405 if (land.lnd_effic < LAND_MINEFF)
407 if (land.lnd_effic < 50)
409 /* Can't fly off units in ships or other units */
410 if ((land.lnd_ship >= 0) || (land.lnd_land >= 0))
412 /* Can't fly off non-owned units or non-allied unit */
413 if ((land.lnd_own != player->cnum) &&
414 (getrel(getnatp(land.lnd_own), player->cnum) != ALLIED)) {
415 pr("(note) An ally does not own the unit %s is on\n",
420 /* Now, check the sector status if not on a plane or unit */
421 if ((plane.pln_ship < 0) && (plane.pln_land < 0)) {
422 if (!getsect(plane.pln_x, plane.pln_y, §))
424 /* First, check allied status */
425 /* Can't fly from non-owned sectors or non-allied sectors */
426 if ((sect.sct_own != player->cnum) &&
427 (getrel(getnatp(sect.sct_own), player->cnum) != ALLIED)) {
428 pr("(note) An ally does not own the sector %s is in\n",
433 if ((pcp->pl_flags & P_V) == 0) {
434 if (sect.sct_type != SCT_AIRPT) {
435 pr("%s not at airport\n", prplane(&plane));
438 if (sect.sct_effic < 40) {
439 pr("%s is not 40%% efficient, %s can't take off from there.\n",
440 xyas(sect.sct_x,sect.sct_y,plane.pln_own),
444 if (rangemult == 2 && sect.sct_effic < 60) {
445 pr("%s is not 60%% efficient, %s can't land there.\n",
446 xyas(sect.sct_x,sect.sct_y,plane.pln_own),
452 pr("%s standing by\n", prplane(&plane));
453 plane.pln_mission = 0;
454 putplane(plane.pln_uid, &plane);
455 plp = (struct plist *) malloc(sizeof(struct plist));
460 bcopy((s_char *)&plane, (s_char *)&plp->plane,
461 sizeof(struct plnstr));
462 emp_insque(&plp->queue, list);
467 pln_arm(struct emp_qelem *list, int dist, int mission, struct ichrstr *ip, int flags, int mission_flags, int *tech)
469 struct emp_qelem *qp;
470 struct emp_qelem *next;
475 for (qp = list->q_forw; qp != list; qp = next) {
477 plp = (struct plist *) qp;
478 if (pln_equip(plp, ip, flags, mission) < 0) {
483 if (flags & (P_S|P_I)) {
484 if(plp->pcp->pl_flags & P_S)
485 mission_flags |= P_S;
486 if(plp->pcp->pl_flags & P_I)
487 mission_flags |= P_I;
489 if (*tech > plp->plane.pln_tech)
490 *tech = plp->plane.pln_tech;
491 if (!(plp->pcp->pl_flags & P_H))
492 /* no stealth on this mission */
493 mission_flags &= ~P_H;
494 if (!(plp->pcp->pl_flags & P_X))
495 /* no stealth on this mission */
496 mission_flags &= ~P_X;
497 if (!(plp->pcp->pl_flags & P_A)) {
498 /* no asw on this mission */
499 mission_flags &= ~P_A;
501 if (!(plp->pcp->pl_flags & P_MINE)) {
502 /* no asw on this mission */
503 mission_flags &= ~P_MINE;
505 plp->plane.pln_mobil -= pln_mobcost(dist,&plp->plane,flags);
506 pr("%s equipped\n", prplane(&plp->plane));
508 return mission_flags;
512 pln_equip(struct plist *plp, struct ichrstr *ip, int flags, s_char mission)
514 register struct plchrstr *pcp;
529 if (pp->pln_ship >= 0) {
530 getship(pp->pln_ship, &ship);
532 ptr = (s_char *) &ship;
534 } else if (pp->pln_land >= 0) {
535 getland(pp->pln_land, &land);
537 ptr = (s_char *) &land;
540 getsect(pp->pln_x, pp->pln_y, §);
542 ptr = (s_char *) §
543 own = sect.sct_oldown;
546 if (ip->i_vtype == V_CIVIL) {
547 if (pp->pln_own != own) {
548 pr("You don't control those civilians!\n");
553 getvec(VT_ITEM, vec, ptr, type);
554 if (pcp->pl_fuel > vec[I_PETROL]) {
555 pr("%s not enough petrol there!\n", prplane(pp));
558 vec[I_PETROL] -= pcp->pl_fuel;
560 if ((flags & P_F) == 0) {
566 if (pp->pln_nuketype == -1) {
568 needed = pp->pln_load;
572 if ((pcp->pl_flags & P_C) == 0 || ip == 0)
575 needed = (pp->pln_load * 2) / ip->i_lbs;
579 needed = (pp->pln_load * 2) / ip->i_lbs;
580 /* Is this mine dropping excursion? */
581 if ((item == I_SHELL) && (pcp->pl_flags & P_MINE))
583 /* Is this a cargo drop? */
584 if ((pcp->pl_flags & P_C) == 0 || ip == 0) {
591 if ((pcp->pl_flags & (P_V|P_C)) == 0)
594 needed = pp->pln_load / ip->i_lbs;
597 if (pp->pln_nuketype == (s_char)-1)
603 if (rval < 0 || (item && needed <= 0)) {
604 pr("%s can't contribute to mission\n", prplane(pp));
608 /* Supply is broken somewhere, so don't use it for now */
609 if ((vec[item] < needed) && (item == I_SHELL))
610 vec[item] += supply_commod(plp->plane.pln_own,
611 plp->plane.pln_x,plp->plane.pln_y,I_SHELL,
614 if (vec[item] < needed) {
615 pr("Not enough %s for %s\n",
616 ichr[item].i_name, prplane(pp));
621 if (item == I_SHELL && (mission == 's' || mission == 'p'))
626 putvec(VT_ITEM, vec, ptr, type);
627 if (type == EF_SHIP) {
628 if (pp->pln_own != ship.shp_own) {
629 wu(0, ship.shp_own, "%s %s prepares for takeoff from ship %s\n",
630 cname(pp->pln_own), prplane(pp), prship(&ship));
632 putship(ship.shp_uid,&ship);
633 } else if (type == EF_LAND) {
634 if (pp->pln_own != land.lnd_own) {
635 wu(0, land.lnd_own, "%s %s prepares for takeoff from unit %s\n",
636 cname(pp->pln_own), prplane(pp), prland(&land));
638 putland(land.lnd_uid,&land);
640 if (pp->pln_own != sect.sct_own) {
641 wu(0, sect.sct_own, "%s %s prepares for takeoff from %s\n",
642 cname(pp->pln_own), prplane(pp), xyas(sect.sct_x, sect.sct_y, sect.sct_own));
650 pln_put(struct emp_qelem *list)
652 register struct emp_qelem *qp;
653 register struct emp_qelem *newqp;
659 /* Here is where planes return home from bombing runs.
660 We need to make sure they still have somewhere to return
664 plp = (struct plist *) qp;
666 /* Ok, check out where it wants to land */
667 if (pp->pln_ship >= 0) {
668 /* It is landing on a carrier */
669 getship(pp->pln_ship, &ship);
670 /* We should do more, like make sure it's really
671 a carrier, etc. but for now just make sure it's
673 if (ship.shp_effic < SHIP_MINEFF) {
674 mpr(pp->pln_own, "Ship #%d has been sunk, plane #%d has nowhere to land, and\nsplashes into the sea.\n", pp->pln_ship, pp->pln_uid);
678 /* Presume we are landing back in a sector. */
679 getsect(pp->pln_x, pp->pln_y, §);
680 if (sect.sct_type == SCT_WATER ||
681 sect.sct_type == SCT_WASTE) {
682 mpr(pp->pln_own, "Nowwhere to land at %s, plane #%d crashes and burns...\n", xyas(pp->pln_x, pp->pln_y, pp->pln_own), pp->pln_uid);
686 putplane(pp->pln_uid, pp);
695 pln_removedupes(struct emp_qelem *bomb_list, struct emp_qelem *esc_list)
697 struct emp_qelem *bomb;
698 struct emp_qelem *esc;
702 if (QEMPTY(bomb_list) || QEMPTY(esc_list))
704 bomb = bomb_list->q_forw;
705 while (bomb != bomb_list) {
706 if (QEMPTY(esc_list)) {
710 esc = esc_list->q_forw;
711 bombp = (struct plist *) bomb;
712 while (esc != esc_list) {
713 escp = (struct plist *) esc;
714 if (escp->plane.pln_uid == bombp->plane.pln_uid) {
726 put_plane_on_ship(struct plnstr *plane, struct shpstr *ship)
728 struct plchrstr *pcp;
731 pcp = &plchr[(int)plane->pln_type];
732 mcp = &mchr[(int)ship->shp_type];
734 if (((int)plane->pln_ship) == ((int)ship->shp_uid))
735 return 1; /* Already on ship */
737 /* Try to put on ship as a chopper plane */
738 if ((pcp->pl_flags & P_K) &&
739 (mcp->m_flags & M_CHOPPER) &&
740 (ship->shp_nchoppers < mcp->m_nchoppers)){
742 ship->shp_nchoppers++;
743 plane->pln_x = ship->shp_x;
744 plane->pln_y = ship->shp_y;
745 plane->pln_ship = ship->shp_uid;
746 putship(ship->shp_uid,ship);
747 putplane(plane->pln_uid,plane);
751 /* Try to put on ship as an xlight plane */
752 if ((pcp->pl_flags & P_E) &&
753 (mcp->m_flags & M_XLIGHT) &&
754 (ship->shp_nxlight < mcp->m_nxlight)){
757 plane->pln_x = ship->shp_x;
758 plane->pln_y = ship->shp_y;
759 plane->pln_ship = ship->shp_uid;
760 putship(ship->shp_uid,ship);
761 putplane(plane->pln_uid,plane);
765 /* Try to put on ship as a normal plane */
766 if ( ( ((pcp->pl_flags & P_L) && (mcp->m_flags & M_FLY)) ||
767 ((pcp->pl_flags & P_M) && (pcp->pl_flags & P_L) &&
768 (mcp->m_flags & M_MSL)) ) &&
769 (ship->shp_nplane < mcp->m_nplanes)){
772 plane->pln_x = ship->shp_x;
773 plane->pln_y = ship->shp_y;
774 plane->pln_ship = ship->shp_uid;
775 putship(ship->shp_uid,ship);
776 putplane(plane->pln_uid,plane);
785 take_plane_off_ship(struct plnstr *plane, struct shpstr *ship)
787 struct plchrstr *pcp;
790 pcp = &plchr[(int)plane->pln_type];
791 mcp = &mchr[(int)ship->shp_type];
793 /* Try to take off ship as a chopper plane */
794 if ((pcp->pl_flags & P_K) &&
795 (mcp->m_flags & M_CHOPPER) &&
796 (ship->shp_nchoppers)){
798 ship->shp_nchoppers--;
799 plane->pln_ship = -1;
800 putship(ship->shp_uid,ship);
801 putplane(plane->pln_uid,plane);
805 /* Try to take off ship as an xlight plane */
806 if ((pcp->pl_flags & P_E) &&
807 (mcp->m_flags & M_XLIGHT) &&
808 (ship->shp_nxlight)){
811 plane->pln_ship = -1;
812 putship(ship->shp_uid,ship);
813 putplane(plane->pln_uid,plane);
817 /* Try to take off ship as a normal plane */
818 if ( ( ((pcp->pl_flags & P_L) && (mcp->m_flags & M_FLY)) ||
819 ((pcp->pl_flags & P_M) && (pcp->pl_flags & P_L) &&
820 (mcp->m_flags & M_MSL)) ) &&
824 plane->pln_ship = -1;
825 putship(ship->shp_uid,ship);
826 putplane(plane->pln_uid,plane);
835 take_plane_off_land(struct plnstr *plane, struct lndstr *land)
837 struct plchrstr *pcp;
840 pcp = &plchr[(int)plane->pln_type];
841 lcp = &lchr[(int)land->lnd_type];
843 /* Try to take off ship as an xlight plane */
844 if ((pcp->pl_flags & P_E) &&
845 (lcp->l_flags & L_XLIGHT) &&
846 (land->lnd_nxlight)){
849 plane->pln_land = -1;
850 putland(land->lnd_uid,land);
851 putplane(plane->pln_uid,plane);
860 can_be_on_ship(int p, int s)
864 struct plchrstr *pcp;
870 pcp = &plchr[(int)plane.pln_type];
871 mcp = &mchr[(int)ship.shp_type];
873 if (pcp->pl_flags & P_L)
874 if (mcp->m_flags & M_FLY)
877 if (pcp->pl_flags & P_K)
878 if (mcp->m_flags & M_CHOPPER)
881 if (pcp->pl_flags & P_M)
882 if (mcp->m_flags & M_MSL)
885 if (pcp->pl_flags & P_E)
886 if (mcp->m_flags & M_XLIGHT)
893 plane_sweep(struct emp_qelem *plane_list, coord x, coord y)
896 struct plchrstr *pcp;
897 struct emp_qelem *qp;
898 struct emp_qelem *next;
905 mines_there = getvar(V_MINE, (s_char *)§, EF_SECTOR);
907 if (mines_there == 0)
910 if ((sect.sct_type != SCT_WATER) && (sect.sct_type != SCT_HARBR))
913 for (qp=plane_list->q_forw;((qp!=plane_list)&&(mines_there));qp=next) {
915 ip = (struct plist *) qp;
918 if (!(pcp->pl_flags & P_SWEEP)) /* if it isn't an sweep plane */
921 if (chance( ((double) (100-pp->pln_acc))/100.0 )){
923 xyas(sect.sct_x,sect.sct_y,pp->pln_own));
929 if (found && map_set(player->cnum, sect.sct_x, sect.sct_y, 'X', 0))
930 writemap(player->cnum);
931 putvar(V_MINE, mines_there, (s_char *)§, EF_SECTOR);
936 count_planes(struct shpstr *sp)
940 struct plchrstr *pcp;
946 if (sp->shp_effic < SHIP_MINEFF)
949 mcp = &mchr[(int)sp->shp_type];
950 snxtitem_xy(&ni, EF_PLANE, sp->shp_x, sp->shp_y);
951 while (nxtitem(&ni, (s_char *)&plane)){
952 if (plane.pln_own == 0)
954 if (plane.pln_ship == sp->shp_uid){
955 pcp = &plchr[(int)plane.pln_type];
956 if ((pcp->pl_flags & P_K) &&
957 (nchoppers < mcp->m_nchoppers))
960 if ((pcp->pl_flags & P_E) &&
961 (nxlight < mcp->m_nxlight))
964 if ((pcp->pl_flags & P_L) || (pcp->pl_flags & P_M))
969 if (nplane != sp->shp_nplane ||
970 nxlight != sp->shp_nxlight ||
971 nchoppers != sp->shp_nchoppers) {
972 sp->shp_nplane = nplane;
973 sp->shp_nxlight = nxlight;
974 sp->shp_nchoppers = nchoppers;
975 putship(sp->shp_uid, sp);
980 count_land_planes(struct lndstr *lp)
986 if (lp->lnd_effic < LAND_MINEFF)
989 snxtitem_all(&ni, EF_PLANE);
990 while (nxtitem(&ni, (s_char *)&plane)) {
991 if (plane.pln_own == 0)
993 if (plane.pln_land == lp->lnd_uid)
997 if (lp->lnd_nxlight != nplane) {
998 lp->lnd_nxlight = nplane;
999 putland(lp->lnd_uid,lp);
1004 count_sect_planes(struct sctstr *sp)
1007 struct nstr_item ni;
1008 struct plnstr plane;
1010 snxtitem_all(&ni, EF_PLANE);
1011 while (nxtitem(&ni, (s_char *)&plane)) {
1014 if (plane.pln_flags & PLN_LAUNCHED)
1016 if (plane.pln_x == sp->sct_x && plane.pln_y == sp->sct_y)
1024 put_plane_on_land(struct plnstr *plane, struct lndstr *land)
1026 struct plchrstr *pcp;
1027 struct lchrstr *lcp;
1029 pcp = &plchr[(int)plane->pln_type];
1030 lcp = &lchr[(int)land->lnd_type];
1032 if (((int)plane->pln_land) == ((int)land->lnd_uid))
1033 return 1; /* Already on unit */
1035 /* Try to put on unit as an xlight plane */
1036 if ((pcp->pl_flags & P_E) &&
1037 (lcp->l_flags & L_XLIGHT) &&
1038 (land->lnd_nxlight < lcp->l_nxlight)){
1040 land->lnd_nxlight++;
1041 plane->pln_x = land->lnd_x;
1042 plane->pln_y = land->lnd_y;
1043 plane->pln_land = land->lnd_uid;
1044 putland(land->lnd_uid,land);
1045 putplane(plane->pln_uid,plane);
1049 /* We have failed */
1054 pln_hitchance(struct plnstr *pp, int hardtarget, int type)
1056 struct plchrstr *pcp = plchr + pp->pln_type;
1057 float tfact = (float)(pp->pln_tech - pcp->pl_tech) /
1058 (pp->pln_tech - pcp->pl_tech / 2);
1059 int acc = pp->pln_acc;
1062 if (type == EF_SHIP) {
1063 if (pcp->pl_flags & P_A)
1065 if (!(pcp->pl_flags & P_T))
1068 hitchance = (int)(pp->pln_effic * (1.0 - 0.1 * tfact) *
1069 (1.0 - (float)acc / 100.0)) - hardtarget;
1071 /* smooth out the bottom of the graph with asymtote at 5 -KHS */
1073 hitchance = 5 + ldround(300.0 / (40.0 - hitchance), 1);
1074 if (hitchance > 100)
1079 /* return 0 if there was a nuclear detonation */
1082 pln_damage(struct plnstr *pp, coord x, coord y, s_char type, int *nukedamp, int noisy)
1084 struct plchrstr *pcp = plchr + pp->pln_type;
1092 if (pp->pln_nuketype != (s_char)-1) {
1093 mpr(pp->pln_own, "Releasing RV's for %s detonation...\n",
1094 pp->pln_flags & PLN_AIRBURST?"airburst":"groundburst");
1095 *nukedamp = detonate(pp, x, y);
1100 if (!pp->pln_load) /* e.g. ab, blowing up on launch pad */
1103 i = roll(pp->pln_load) + 1;
1104 if (i > pp->pln_load)
1107 if (pcp->pl_flags & P_M) {
1108 if (pcp->pl_flags & P_MAR)
1110 } else if (pcp->pl_flags & P_T)
1113 aim = 100 - pp->pln_acc;
1127 hitroll = roll(100);
1128 if (hitroll >= 90) {
1131 mpr(pp->pln_own, "BLAM");
1132 } else if (hitroll < aim) {
1135 mpr(pp->pln_own, "Blam");
1139 mpr(pp->pln_own, "blam");
1142 mpr(pp->pln_own, "-");
1145 mpr(pp->pln_own, "\n");
1152 pln_identchance(struct plnstr *pp, int hardtarget, int type)
1154 double misschance = (100.0-pln_hitchance(pp, hardtarget, type))/100.0;
1155 return (int)(100 - 100 * misschance * misschance);
1159 pln_mobcost(int dist, struct plnstr *pp, int flags)
1163 if ((flags & P_F) || (flags & P_ESC))
1164 cost = 10 * 100 / pp->pln_effic;
1166 cost = 20 * 100 / pp->pln_effic;
1168 cost = ldround((double)cost * dist/pp->pln_range_max, 1);
1170 return min(32 + pp->pln_mobil, cost + 5);