diff src/interface.c @ 4:aa38447a4b21

First entry of Paradise Server 2.9 patch 10 Beta
author darius
date Sat, 06 Dec 1997 04:37:03 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interface.c	Sat Dec 06 04:37:03 1997 +0000
@@ -0,0 +1,1236 @@
+/*--------------------------------------------------------------------------
+NETREK II -- Paradise
+
+Permission to use, copy, modify, and distribute this software and its
+documentation, or any derivative works thereof, for any NON-COMMERCIAL
+purpose and without fee is hereby granted, provided that this copyright
+notice appear in all copies.  No representations are made about the
+suitability of this software for any purpose.  This software is provided
+"as is" without express or implied warranty.
+
+    Xtrek Copyright 1986                            Chris Guthrie
+    Netrek (Xtrek II) Copyright 1989                Kevin P. Smith
+                                                    Scott Silvey
+    Paradise II (Netrek II) Copyright 1993          Larry Denys
+                                                    Kurt Olsen
+                                                    Brandon Gillespie
+--------------------------------------------------------------------------*/
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <math.h>
+#include <signal.h>
+#include "defs.h"
+#include "struct.h"
+#include "data.h"
+#include "shmem.h"
+
+void cloak_off();
+void cloak_on();
+int numShips();
+void sendwarn();
+extern int pmessage2();
+int allowed_ship();
+int numPlanets();
+void suspendPrep();
+void unsuspendPrep();
+
+/*-----------------------------VISIBLE FUNCTIONS---------------------------*/
+
+/*--------------------------------SETSPEED---------------------------------*/
+/*
+ * This function takes the desired speed from the client and translates it
+ * into impulse, afterburners, or warp.  99 = warp.  98 = afterburners. 97 =
+ * suspend warp prep, 96 = resume warp prep, 0-x = impulse.  This function is
+ * used for both requests to set a ships speed from the client and from the
+ * server.  The client requests are requests that are received directly from
+ * the client.  A speed of 99 is treated as a request for warp speed.  A
+ * request of 98 is a request for afterburners.
+ */
+
+
+
+void
+set_speed(speed, type)
+  int speed;			/* the desired speed */
+  int type;			/* type of request. 0=server 1=client */
+{
+  if (me->p_flags & PFDOCK)
+  {				/* if docked then */
+    if (players[me->p_docked].p_speed > 4)
+    {				/* you cannot get off >= 4 */
+      warning("You are going too fast to disengage safely");
+      return;
+    }
+    else
+      undock_player(me);
+  }
+  speed = (speed < 0) ? 0 : speed;	/* no negative speeds */
+  /* suspend warp  [BDyess] */
+  if (speed == 97 && configvals->warpprep_suspendable)
+  {				/* suspend warp */
+    suspendPrep();
+  }
+  else if (speed == 96 && configvals->warpprep_suspendable)
+  {
+    /* unsuspend warp [BDyess] */
+    unsuspendPrep();
+  }
+  else if ((speed == 98) && (configvals->afterburners))
+  {				/* afterburners */
+    /* turn off warp, warpprep, and warp suspended flags */
+    me->p_flags &= ~(PFWARP | PFWARPPREP | PFWPSUSPENDED);
+    me->p_warptime = 0;
+    me->p_flags |= PFAFTER;	/* turn on after burners */
+    me->p_desspeed = me->p_ship.s_after.maxspeed;	/* set speed of
+							 * afterburn */
+    /*
+     * go to warp if speed 99 is sent, OR if the speed sent is greater than
+     * max impulse and the VARIABLE_WARP sysdef is set, AND the ship can warp
+     * [BDyess]
+     */
+  }
+  else if ((speed == 99
+	    || (configvals->variable_warp
+		&& speed > me->p_ship.s_imp.maxspeed
+		&& me->p_flags & (PFWARPPREP | PFWARP | PFWPSUSPENDED))
+	    )
+	   && (me->p_ship.s_nflags & SFNCANWARP))
+  {
+    int maxspeed = me->p_ship.s_warp.maxspeed;
+    int preptime = myship->s_warpinittime;	/* timer before warping */
+
+    if (configvals->warpzone)
+    {
+      if (me->p_zone < 0)
+      {
+	warning("The enemy is neutralizing our warp field, sir!");
+	return;
+      }
+      else if (me->p_zone > 0)
+      {
+	maxspeed = maxspeed * 3 / 2;	/* can go faster with boost [BDyess] */
+	if (maxspeed > 99)
+	  maxspeed = 99;
+	preptime /= 2;		/* takes less time to build up when you have
+				 * help */
+	if (preptime == 0)
+	  preptime = 1;
+	warning("warp boost!");
+      }
+    }
+
+    speed = (speed > maxspeed)
+      ? maxspeed
+      : speed;			/* cap the request at max warp */
+
+    me->p_warpdesspeed = speed;	/* remember how fast to warp for later
+				 * [BDyess] */
+    if (me->p_warptime > 0)
+    {
+      warning("Hold your horses, Speed Racer.  These things take time.");
+      return;
+    }
+    if (me->p_flags & PFWARP)
+    {
+      me->p_desspeed = speed;
+      return;
+    }
+    if (me->p_damage > me->p_ship.s_maxdamage / 2)
+    {
+      warning("We are too damaged to risk warp speeds, Captain.");
+      return;
+    }
+    if (me->p_fuel < me->p_ship.s_warpinitcost)
+    {
+      warning("Not enough fuel for warp, Captain!");
+      return;
+    }
+    me->p_desspeed = myship->s_warpprepspeed;	/* slow ship down */
+    me->p_flags |= PFWARPPREP;	/* set warp prep flag [BDyess] */
+    if (!configvals->cloakduringwarpprep)
+      cloak_off();
+
+    if (me->p_speed < me->p_desspeed)
+      me->p_speed = me->p_desspeed;
+
+    /* turn off after burners and warpprep suspended flag [BDyess] */
+    me->p_flags &= ~(PFAFTER | PFWPSUSPENDED);
+    me->p_warptime = preptime;	/* timer before warping */
+    me->p_fuel -= me->p_ship.s_warpinitcost;	/* subtract off fuel */
+    warning("Warp drive engaged!");	/* let him know its working */
+  }
+  else if (type == 0)
+  {				/* else if server request */
+    me->p_desspeed = speed;	/* grant speed request */
+  }
+  else
+  {				/* else client request for impulse */
+
+    if (!configvals->warpdecel)
+      me->p_flags &= ~(PFWARP | PFAFTER);
+
+    me->p_warptime = 0;
+    me->p_flags &= ~(PFWARPPREP | PFWPSUSPENDED);	/* turn off warpprep
+							 * flag [BDyess] */
+    speed = (speed > me->p_ship.s_imp.maxspeed) ? me->p_ship.s_imp.maxspeed :
+      speed;
+    me->p_desspeed = speed;	/* set the speed */
+  }
+#if 0
+  if (me->p_flags & PFORBIT)	/* if we were orbiting */
+    planets[me->p_planet].pl_torbit &= ~me->p_team;
+#endif
+  me->p_flags &= ~(PFREPAIR | PFBOMB | PFORBIT | PFDOCK | PFBEAMUP | PFBEAMDOWN);
+  me->p_lastman = 0;
+}
+
+
+
+
+/*--------------------------------SET_COURSE-------------------------------*/
+/*
+ * Set the players course.  This function takes a direction and sets the
+ * players direction to it.  Certain flags are cleared.
+ */
+
+void
+set_course(dir)
+  unsigned char dir;
+{
+  me->p_desdir = dir;		/* set the desired direction */
+  if (me->p_flags & PFDOCK)
+  {				/* if player is docked then he cannot */
+    if (players[me->p_docked].p_speed > 4)
+    {				/* undock if dockee going fast */
+      warning("It's unsafe to disengage from bases while moving more that warp 4.");
+      return;
+    }
+    else
+      undock_player(me);
+
+  }
+#if 0
+  if (me->p_flags & PFORBIT)	/* if in orbit then take */
+    planets[me->p_planet].pl_torbit &= ~me->p_team;	/* team out of orbit */
+#endif
+  me->p_flags &= ~(PFBOMB | PFORBIT | PFDOCK | PFBEAMUP | PFBEAMDOWN);
+  me->p_lastman = 0;		/* not beamin all armies up */
+}
+
+
+
+
+/*----------------------------------SHIELD_UP-----------------------------*/
+/* This function raises the players shields.  */
+
+void
+shield_up()
+{
+  me->p_flags |= PFSHIELD;	/* some flags go up and some down */
+  me->p_flags &= ~(PFBOMB | PFREPAIR | PFBEAMUP | PFBEAMDOWN);
+  me->p_lastman = 0;		/* not beaming up all armies */
+}
+
+
+
+
+/*---------------------------------SHIELD_DOWN----------------------------*/
+/* This function lowers the players shields.  */
+
+void
+shield_down()
+{
+  me->p_flags &= ~PFSHIELD;	/* shield flag clear */
+}
+
+
+
+
+/*--------------------------------SHIELD_TOGGLE---------------------------*/
+/* This function toggles the players shields on and off.  */
+
+void
+shield_tog()
+{
+  me->p_flags ^= PFSHIELD;	/* toggle shield flag */
+  me->p_flags &= ~(PFBOMB | PFREPAIR | PFBEAMUP | PFBEAMDOWN);
+  me->p_lastman = 0;
+}
+
+
+
+
+/*--------------------------------BOMB_PLANET------------------------------*/
+/*
+ * This function sets the bomb flag if certain conditions are met, such as
+ * you are bombing enemy planets.
+ */
+
+void
+bomb_planet()
+{
+  static int bombsOutOfTmode = 0;	/* confirm bomb out of t-mode */
+  int owner;			/* owner of planet */
+
+  owner = planets[me->p_planet].pl_owner;	/* get planet's owner */
+  if (!(me->p_flags & PFORBIT))
+  {				/* can't bomb anything in */
+    warning("Must be orbiting to bomb");	/* open space, now can you? */
+    return;
+  }
+  if (me->p_team == planets[me->p_planet].pl_owner)
+  {
+    warning("Can't bomb your own armies.  Have you been reading Catch-22 again?");	/* can't bomb own armies */
+    return;
+  }
+  if (!((me->p_swar | me->p_hostile) & owner) && (owner != 0))
+  {
+    warning("Must declare war first (no Pearl Harbor syndrome allowed here).");
+    return;			/* can't bomb friendlies */
+  }
+  if ((!status->tourn) && (bombsOutOfTmode == 0))
+  {
+    warning("Bomb out of T-mode?  Please verify your order to bomb.");
+    bombsOutOfTmode++;		/* warning about bombing out of T */
+    return;
+  }
+  if ((!status->tourn) && (bombsOutOfTmode == 1))
+  {
+    warning("Hoser!");		/* if he really wants to bomb, then */
+    bombsOutOfTmode++;		/* let him bomb out of T.  Hoser */
+  }				/* warning */
+  if (!numShips(planets[me->p_planet].pl_owner)
+      && (planets[me->p_planet].pl_owner != NOBODY))
+  {
+    warning("You can't break the peace treaty, Captain");
+    return;
+  }
+  if (status->tourn)		/* reset the bombs out of t-mode */
+    bombsOutOfTmode = 0;	/* variable */
+  me->p_flags |= PFBOMB;	/* set the bomb flag */
+#if 1
+  planets[me->p_planet].pl_hostile |= me->p_team;
+#else
+  planets[me->p_planet].pl_torbit |= (me->p_team) << 4;
+#endif
+  me->p_flags &= ~(PFSHIELD | PFREPAIR | PFBEAMUP | PFBEAMDOWN);
+}
+
+
+
+
+/*---------------------------------BEAM_UP---------------------------------*/
+/* This function set the beam up flag if it is allowable to beam men up.  */
+
+void
+beam_up()
+{
+  if (!status2->starttourn && configvals->nopregamebeamup)
+  {
+    warning("You can't beam up armies before a game starts");
+    return;
+  }
+  if (!(me->p_flags & (PFORBIT | PFDOCK)))
+  {
+    warning("Must be orbiting or docked to beam up.");
+    return;			/* have to be orbiting or docked */
+  }
+  if (me->p_flags & PFORBIT)
+  {				/* if orbiting and not owner */
+    if (me->p_team != planets[me->p_planet].pl_owner)
+    {
+      warning("Those aren't our men.");
+      return;
+    }
+    if (me->p_lastman == 0)	/* if we have not signalled to pick */
+      me->p_lastman = 1;	/* up all armies */
+    else if (planets[me->p_planet].pl_armies <= 4)
+    {				/* else if less than 5 */
+      if (numPlanets((int) me->p_team && configvals->beamlastarmies) == 1)
+      {
+	warning("You can't take those armies, they're on your only planet!");
+	return;
+      }
+      me->p_lastman = 2;	/* set status to beaming up all */
+    }
+  }
+  else if (me->p_flags & PFDOCK)
+  {				/* if docked must be to own team ship */
+    if (me->p_team != players[me->p_docked].p_team)
+    {
+      warning("Comm Officer: Uhhh, they aren't our men!");
+      return;
+    }
+  }
+  me->p_flags |= PFBEAMUP;	/* set the beam up flag */
+  me->p_flags &= ~(PFSHIELD | PFREPAIR | PFBOMB | PFBEAMDOWN);
+}
+
+
+
+
+/*--------------------------------BEAM_DOWN--------------------------------*/
+/* This function sets the beam up flag if certain conditions are met */
+
+void
+beam_down()
+{
+  int i;			/* looping var */
+  struct planet *pl;		/* to access planets */
+  int total;			/* for total number of planets */
+  char buf[80];
+
+  if (!(me->p_flags & (PFORBIT | PFDOCK)))
+  {
+    warning("Must be orbiting or docked to beam down.");
+    return;			/* have to be docked or orbiting */
+  }
+  if ((!((me->p_swar | me->p_hostile) & planets[me->p_planet].pl_owner))
+      && (me->p_team != planets[me->p_planet].pl_owner)
+      && (planets[me->p_planet].pl_owner != NOBODY))
+  {
+    warning("You can't beam down, you have not declared war");
+    return;			/* no beaming down if not hostile */
+  }
+  if (!numShips(planets[me->p_planet].pl_owner)
+      && (planets[me->p_planet].pl_owner != NOBODY))
+  {
+    warning("You can't break the peace treaty, Captain");
+    return;
+  }
+  if (me->p_flags & PFDOCK)
+  {
+    if (me->p_team != players[me->p_docked].p_team)
+    {
+      warning("Comm Officer: Starbase refuses permission to beam our troops over.");	/* no beaming to foreign
+											 * bases */
+      return;
+    }
+  }
+
+  else if (configvals->planetlimittype)
+  {				/* new planet limit */
+    total = numPlanets(me->p_team);
+
+    if (total >= configvals->planetsinplay
+	&& planets[me->p_planet].pl_owner == NOBODY
+	&& planets[me->p_planet].pl_armies)
+    {
+      sprintf(buf, "You may only take enemy planets when your team has %d or more planets.",
+	      configvals->planetsinplay);
+      warning(buf);
+      me->p_flags &= ~(PFBOMB);
+      return;
+    }
+  }
+  else
+  {
+    int ns[MAXTEAM];
+    for (i = 0; i < NUMTEAM; i++)
+      ns[1 << i] = numShips(1 << i);
+
+    total = 0;
+    for (i = 0, pl = &planets[i]; i < NUMPLANETS; i++, pl++)
+    {
+      if (pl->pl_owner && ns[pl->pl_owner] > configvals->tournplayers - 1)
+	total++;
+    }
+    if ((total >= configvals->planetsinplay)
+	&& (!(me->p_flags & PFDOCK))
+	&& (planets[me->p_planet].pl_owner == NOBODY))
+    {
+      sprintf(buf, "Sorry, there are already %d planets in play.",
+	      configvals->planetsinplay);
+      warning(buf);
+      me->p_flags &= ~(PFBOMB);
+      return;
+    }
+  }
+  me->p_flags |= PFBEAMDOWN;	/* set beam down flag */
+  me->p_flags &= ~(PFSHIELD | PFREPAIR | PFBOMB | PFBEAMUP);
+  me->p_lastman = 0;
+}
+
+
+
+
+/*---------------------------------REPAIR---------------------------------*/
+/*
+ * This function sets the reapair flag and turns off other flags.  You cannot
+ * repair while in warp.
+ */
+
+void
+repair()
+{
+#if !defined(AEDILE) || !defined(REPAIR_IN_WARP)
+  if (me->p_flags & PFWARP)
+  {				/* no repairing in warp */
+    warning("You cannot repair while in warp!");
+    return;
+  }
+#endif
+  me->p_desspeed = 0;		/* speed goes to zero */
+  me->p_warptime = 0;		/* turn off warp prep */
+  me->p_flags |= PFREPAIR;	/* reair flag goes up */
+  me->p_flags &= ~(PFSHIELD | PFBOMB | PFBEAMUP | PFBEAMDOWN | PFPLOCK | PFPLLOCK | PFWARP | PFAFTER | PFWARPPREP | PFWPSUSPENDED);
+  me->p_lastman = 0;		/* not beaming all armies */
+}
+
+
+
+
+/*--------------------------------REPAIR_OFF------------------------------*/
+/* This function takes the repair flag off.  */
+
+void
+repair_off()
+{
+  me->p_flags &= ~PFREPAIR;
+}
+
+
+
+
+/*---------------------------------REPEAT---------------------------------*/
+/* This function repeats the last message.  */
+
+void
+repeat_message()
+{
+  if (++lastm == MAXMESSAGE)	/* go to next message */
+    lastm = 0;			/* account for rollover */
+}
+
+
+
+
+/*---------------------------------CLOAK----------------------------------*/
+/*
+ * This function toggles the cloak flag.  Tractors and pressor are turned
+ * off.
+ */
+
+void
+cloak()
+{
+  if (me->p_flags & PFCLOAK)
+    cloak_off();
+  else
+    cloak_on();
+}
+
+
+
+
+/*---------------------------------CLOAK_ON-------------------------------*/
+/* This function turns cloak on.  Tractors and pressors are turned off.  */
+
+void
+cloak_on()
+{
+  if (me->p_warptime && !configvals->cloakduringwarpprep)
+  {
+    warning("Can't cloak during warp preparation.");
+    return;
+  }
+  if (me->p_flags & PFWARP && !configvals->cloakwhilewarping)
+  {
+    warning("Can't cloak while warp engines are engaged.");
+    return;
+  }
+  me->p_flags |= PFCLOAK;
+  me->p_flags &= ~(PFTRACT | PFPRESS);
+}
+
+
+
+
+/*---------------------------------CLOAK_OFF------------------------------*/
+/* This function turns the cloak off.  */
+
+void
+cloak_off()
+{
+  me->p_flags &= ~PFCLOAK;
+}
+
+
+
+
+/*-------------------------------LOCK_PLANET-----------------------------*/
+/* This function locks the player onto a planet.  */
+
+void
+lock_planet(planet)
+  int planet;			/* planet locking onto */
+{
+  char buf[80];			/* to sprintf into */
+
+  if ((planet < 0) || (planet >= NUMPLANETS))	/* bad planet number? */
+    return;
+
+  if (me->p_status == POBSERVE)
+  {
+    if (planets[planet].pl_owner != me->p_team)
+    {
+      warning("Unable to observe enemy planets.");
+      me->p_flags &= ~(PFPLLOCK | PFPLOCK);
+      return;
+    }
+    else if (!(planets[planet].pl_owner & me->p_teamspy))
+    {
+      warning("That team has barred you from observing.");
+      me->p_flags &= ~(PFPLLOCK | PFPLOCK);
+      return;
+    }
+  }
+
+  me->p_flags |= PFPLLOCK;	/* turn on the lock */
+#if 0
+  if (me->p_flags & PFORBIT)	/* if orbiting then leave torbit var */
+    planets[me->p_planet].pl_torbit &= ~me->p_team;
+#endif
+  me->p_flags &= ~(PFPLOCK | PFORBIT | PFBEAMUP | PFBEAMDOWN | PFBOMB);
+  me->p_lastman = 0;
+  me->p_planet = planet;	/* set planet locked onto */
+  sprintf(buf, "Locking onto %s", planets[planet].pl_name);
+  warning(buf);			/* send message to player */
+}
+
+
+
+
+/*-------------------------------LOCK_PLAYER-------------------------------*/
+/* This function locks the player onto another player.  */
+
+void
+lock_player(player)
+  int player;			/* player locking onto */
+{
+  char buf[80];
+
+  if ((player < 0) || (player >= MAXPLAYER))	/* bad planet num? */
+    return;
+  if (players[player].p_status != PALIVE)	/* player not alive? */
+    return;
+  if (players[player].p_flags & PFCLOAK)	/* player is cloaked */
+    return;
+
+  if (me->p_status == POBSERVE && players[player].p_team != me->p_team)
+  {
+    sprintf(buf, "Unable to observe enemy players.");
+    warning(buf);
+    me->p_flags &= ~(PFPLLOCK | PFPLOCK);
+    return;
+  }
+
+  me->p_flags |= PFPLOCK;	/* set player lock flag */
+#if 0
+  if (me->p_flags & PFORBIT)	/* if in orbit take team out */
+    planets[me->p_planet].pl_torbit &= ~me->p_team;	/* of torbit */
+#endif
+  me->p_flags &= ~(PFPLLOCK | PFORBIT | PFBEAMUP | PFBEAMDOWN | PFBOMB);
+  me->p_lastman = 0;		/* turn off taking all armies */
+  me->p_playerl = player;	/* set player loked oto */
+  /* player locking onto own base */
+  if ((players[player].p_team == me->p_team) &&
+      allows_docking(players[player].p_ship))
+    sprintf(buf, "Locking onto %s (%s) (docking is %s)",
+	    players[player].p_name, twoletters(&players[player]),
+	    (players[player].p_flags & PFDOCKOK) ? "enabled" : "disabled");
+  else				/* message for locking onto player */
+    sprintf(buf, "Locking onto %s (%s)", players[player].p_name,
+	    twoletters(&players[player]));
+  warning(buf);
+}
+
+
+
+
+/*-------------------------------TRACTOR_PLAYER----------------------------*/
+/*
+ * This function does the tractoring for the player.  There are a few times
+ * when the tractor cannot be used.
+ */
+
+void
+tractor_player(player)
+  int player;
+{
+  struct player *victim;
+
+  if (weaponsallowed[WP_TRACTOR] == 0)	/* tractors allowed?  */
+    return;
+  if ((player < 0) || (player > MAXPLAYER))
+  {				/* out of bounds = cancel */
+    me->p_flags &= ~(PFTRACT | PFPRESS);
+    return;
+  }
+  if (me->p_flags & PFCLOAK)	/* no tractoring while */
+    return;			/* cloaked */
+  if (player == me->p_no)	/* can't tractor yourself */
+    return;
+  victim = &players[player];	/* get player number */
+  if (victim->p_flags & PFCLOAK)
+    return;
+  if (ihypot(me->p_x - victim->p_x, me->p_y - victim->p_y) <
+      (TRACTDIST) * me->p_ship.s_tractrng)
+  {
+    if (me->p_flags & PFDOCK && players[me->p_docked].p_speed > 4)
+    {
+      warning("It's unsafe to tractor while docked and base is moving more then warp 4.");
+      return;
+    }
+#if 0
+    undock_player(victim);	/* harmless if not docked, handles js */
+    undock_player(me);
+
+#if 0
+    if (me->p_flags & PFORBIT)	/* are we orbiting */
+      planets[me->p_planet].pl_torbit &= ~me->p_team;
+    if (victim->p_flags & PFORBIT)	/* is victim orbiting */
+      planets[victim->p_planet].pl_torbit &= ~victim->p_team;
+    victim->p_flags &= ~(PFORBIT | PFDOCK);	/* clear DOCK/ORBIT flags */
+#endif
+    me->p_flags &= ~(PFORBIT | PFDOCK);
+#endif
+    me->p_tractor = player;	/* set victim number */
+    me->p_flags |= PFTRACT;	/* set tractor flag */
+  }
+}
+
+
+
+
+/*---------------------------------PRESSOR--------------------------------*/
+/*
+ * This function activates the tractors for the player.  There are a number
+ * of conditions where tractors will not work.
+ */
+
+void
+pressor_player(player)
+  int player;			/* the player to presoor */
+{
+  int target;
+  struct player *victim;
+
+  if (weaponsallowed[WP_TRACTOR] == 0)
+  {				/* tractors allowed? */
+    warning("Pressor beams haven't been invented yet.");
+    return;
+  }
+  target = player;		/* save target */
+  if ((target < 0) || (target > MAXPLAYER))
+  {				/* out of bounds = cancel */
+    me->p_flags &= ~(PFTRACT | PFPRESS);
+    return;
+  }
+  if (me->p_flags & PFPRESS)	/* already pressoring? */
+    return;
+  if (me->p_flags & PFCLOAK)
+  {				/* cloaked? */
+    warning("Weapons's Officer:  Cannot pressor while cloaked, sir!");
+    return;
+  }
+  victim = &players[target];	/* get victim's struct */
+  if (victim->p_flags & PFCLOAK)/* victim cloaked */
+    return;
+  if (ihypot(me->p_x - victim->p_x, me->p_y - victim->p_y) <
+      (TRACTDIST) * me->p_ship.s_tractrng)
+  {
+    if (me->p_flags & PFDOCK && players[me->p_docked].p_speed > 4)
+    {
+      warning("It's unsafe to pressor while docked and base is moving more then warp 4.");
+      return;
+    }
+#if 0
+    undock_player(victim);
+    undock_player(me);
+
+#if 0
+    if (me->p_flags & PFORBIT)	/* are we orbiting */
+      planets[me->p_planet].pl_torbit &= ~me->p_team;
+    if (victim->p_flags & PFORBIT)	/* is victim orbiting */
+      planets[victim->p_planet].pl_torbit &= ~victim->p_team;
+#endif
+    victim->p_flags &= ~(PFORBIT | PFDOCK);	/* clear orbit and dock flags */
+    me->p_flags &= ~(PFORBIT | PFDOCK);
+#endif
+    me->p_tractor = target;	/* set the target */
+    me->p_flags |= (PFTRACT | PFPRESS);	/* set the tract and press */
+  }
+  /* flags */
+  else
+    warning("Weapon's Officer:  Vessel is out of range of our pressor beam.");
+}
+
+
+
+
+/*-------------------------------DECLARE_WAR-----------------------------*/
+/* This function changes the war mask of a player.  */
+
+void
+declare_war(mask)
+  int mask;			/* who are we declaring war against */
+{
+  int changes;			/* to hold changes in war mask */
+  int i;			/* looping var */
+
+  mask &= ALLTEAM;		/* mask off extraneous bits */
+  mask &= ~me->p_team;		/* mask out our team bit */
+  mask |= me->p_swar;
+  changes = mask ^ me->p_hostile;	/* determine changes */
+  if (changes == 0)		/* if no changes then we are done */
+    return;
+  if (changes & FED)		/* if Fed status changed then warn them */
+    sendwarn("Federation", mask & FED, FED);
+  if (changes & ROM)		/* if Rom status changed then warn them */
+    sendwarn("Romulans", mask & ROM, ROM);
+  if (changes & KLI)		/* if Kli status changed then warn them */
+    sendwarn("Klingons", mask & KLI, KLI);
+  if (changes & ORI)		/* if Orion status changed then warn them */
+    sendwarn("Orions", mask & ORI, ORI);
+  if (me->p_flags & PFDOCK)
+  {				/* if docked and now at war with */
+    if (players[me->p_docked].p_team & mask)
+    {				/* dockee then undock */
+      undock_player(me);
+    }
+  }
+  else if (allows_docking(me->p_ship))
+  {				/* if ship is dockable then */
+    if (me->p_docked > 0)
+    {				/* go through ports and */
+      for (i = 0; i < me->p_ship.s_numports; i++)
+      {				/* kick off warring ships */
+	if (me->p_port[i] >= 0 &&
+	    (mask & players[me->p_port[i]].p_team))
+	{
+	  base_undock(me, i);
+	}
+      }
+    }
+  }
+  if (mask & ~me->p_hostile)
+  {				/* no sudden changing of */
+    me->p_flags |= PFWAR;	/* war status */
+    delay = me->p_updates + 100;
+    warning("Pausing ten seconds to re-program battle computers.");
+  }
+  me->p_hostile = mask;		/* new hostile mask */
+}
+
+
+
+
+/*-----------------------------------SENDWARN------------------------------*/
+/*
+ * This function sends the warning message to the other players when a player
+ * switches his war status with that team.
+ */
+
+void
+sendwarn(string, atwar, team)
+  char *string;			/* the name of the team changing status
+				 * towards */
+  int atwar;			/* 1 if declarig war 0 if decalring peace */
+  int team;			/* name of team we are switching in regards
+				 * to */
+{
+  char buf[BUFSIZ];		/* to hold sprintfed message */
+  char addrbuf[10];		/* to hold ship number and team letter */
+
+  if (atwar)
+  {				/* if decalring war */
+    (void) sprintf(buf, "%s (%s) declaring war on the %s",
+		   me->p_name, twoletters(me), string);
+  }
+  else
+  {				/* else decalring peace */
+    (void) sprintf(buf, "%s (%s) declaring peace with the %s",
+		   me->p_name, twoletters(me), string);
+  }
+  (void) sprintf(addrbuf, " %s->%-3s", twoletters(me), teams[team].shortname);
+  pmessage2(buf, team, MTEAM, addrbuf, me->p_no);
+}
+
+
+/* switches the special weapon of the player */
+
+void
+switch_special_weapon()
+{
+  int mask = 0;
+  int currflag;
+  int i, j;
+
+  mask = me->p_ship.s_nflags & (SFNHASMISSILE | SFNPLASMAARMED);
+
+  if (!mask)
+  {
+    warning("This ship is not armed with any special weapons");
+    me->p_specweap = 0;
+    return;
+  }
+  for (i = 0; i < sizeof(int) * 8; i++)
+  {
+    currflag = 1 << i;
+    if (!mask & currflag)
+      continue;
+    if (me->p_specweap & currflag)
+    {
+      i++;
+      break;
+    }
+  }
+
+  for (j = 0; j < sizeof(int) * 8; i++, j++)
+  {
+    if (i > sizeof(int) * 8)
+      i = 0;
+    currflag = 1 << i;
+    if (mask & currflag)
+    {
+      me->p_specweap = currflag;
+      break;
+    }
+  }
+
+  if (me->p_specweap & SFNHASMISSILE)
+  {
+    if (me->p_ship.s_nflags & SFNHASFIGHTERS)
+      warning("Fighters ready");
+    else
+      warning("Missiles armed");
+  }
+  else if (me->p_specweap & SFNPLASMAARMED)
+  {
+    warning("Plasmas armed");
+  }
+}
+
+/*-------------------------------DO_REFIT---------------------------------*/
+/*
+ * This function will attempt to refit a player to another ship.  There are
+ * all sorts of nasty reasons why it might fail.
+ */
+
+void
+do_refit(type)
+  int type;			/* type of ship to refit to */
+{
+  int i;			/* looping var */
+
+  if (type < 0 || type >= NUM_TYPES)	/* ship type select out of range */
+    return;
+  if (me->p_flags & PFORBIT)
+  {				/* if orbiting must be a shipyard */
+    if (!(planets[me->p_planet].pl_flags & PLSHIPYARD))
+    {
+      warning("You can change ships at a planet with a shipyard on it.");
+      return;
+    }
+#if 0
+    if (planets[me->p_planet].pl_owner != me->p_team)
+    {
+      warning("You can only refit on planets that your team owns.");
+      return;
+    }
+#endif
+  }
+  else if (me->p_flags & PFDOCK)
+  {				/* if docked then */
+    if (allows_docking(shipvals[type]))
+    {				/* cannot refit to a starbase */
+      warning("Can only refit to a base in a shipyard");
+      return;
+    }
+    if (players[me->p_docked].p_team != me->p_team)
+    {
+      warning("You must dock with YOUR base to apply for command reassignment!");	/* no refitting on enemy
+											 * SB's */
+      return;
+    }
+    if (!(players[me->p_docked].p_ship.s_nflags & SFNCANREFIT))
+    {
+      warning("This base can not provide you with a new ship.");
+      return;
+    }
+  }
+  else
+  {				/* planet does not have shipyard */
+    warning("Must orbit a shipyard or dock with your base to apply for command reassignment!");
+    return;
+  }
+  if ((me->p_damage > ((float) me->p_ship.s_maxdamage) * .75) ||
+      (me->p_shield < ((float) me->p_ship.s_maxshield) * .75) ||
+      (me->p_fuel < ((float) me->p_ship.s_maxfuel) * .75))
+  {
+    warning("Central Command refuses to accept a ship in this condition!");
+    return;			/* ship must be in good condition */
+  }
+  if ((me->p_armies > 0))
+  {				/* no refitting with armies on board */
+    warning("You must beam your armies down before moving to your new ship");
+    return;
+  }
+
+  {
+    int oldt, oldd, oldp, allowed;
+    oldt = me->p_ship.s_type;
+    oldd = me->p_ship.s_numdefn;
+    oldp = me->p_ship.s_numplan;
+    me->p_ship.s_type = -1;
+    me->p_ship.s_numdefn = 0;
+    me->p_ship.s_numplan = 0;
+    allowed = allowed_ship(me->p_team, me->p_stats.st_rank,
+			   me->p_stats.st_royal, type);
+    me->p_ship.s_type = oldt;
+    me->p_ship.s_numdefn = oldd;
+    me->p_ship.s_numplan = oldp;
+    if (!allowed)
+      return;
+  }
+
+  if (me->p_ship.s_type == STARBASE ||
+      me->p_ship.s_type == WARBASE ||
+      me->p_ship.s_type == CARRIER)
+    me->p_kills = 0;		/* reset kills to zero if coming */
+  /* from a base */
+
+  if (allows_docking(me->p_ship))
+  {				/* if ship dockable then */
+    for (i = 0; i < me->p_ship.s_numports; i++)
+    {				/* dump all ship out of dock */
+      base_undock(me, i);
+    }
+  }
+  get_ship_for_player(me, type);/* place ship in player strct */
+
+  switch_special_weapon();
+
+  if (me->p_flags & PFORBIT)
+  {
+    char buf[120];
+    me->p_lastrefit = me->p_planet;
+    sprintf(buf, "%s is now your home port", planets[me->p_lastrefit].pl_name);
+    warning(buf);
+  }
+
+  me->p_flags &= ~(PFREFIT);
+  me->p_flags |= PFREFITTING;
+  rdelay = me->p_updates + 50;
+  warning("You are being transported to your new vessel .... ");
+}
+
+
+/*
+ * Is a person with this rank on this team able to requisition a ship of this
+ * type?
+ */
+int
+allowed_ship(team, rank, royal, type)
+  int team;
+  int rank;
+  int royal;
+  int type;
+{
+  struct ship *tempship;
+  int shipcount;
+  int used_teamstr;		/* people required to support flying bases */
+  int used_planstr;		/* planets required to support flying bases */
+  int i, maxrank = 0;
+
+  if (!shipsallowed[type])
+  {
+    warning("That ship hasn't been designed yet.");
+    return 0;
+  }
+  tempship = &shipvals[type];
+
+#ifdef LEAGUE_SUPPORT
+  if (status2->league == 1)
+    return 1;
+
+  if (!status2->league)
+  {
+#endif
+    if (configvals->baserankstyle)
+    {
+      for (i = 0; i < MAXPLAYER; i++)
+	if ((players[i].p_status == PALIVE ||
+	     players[i].p_status == POUTFIT)
+	    && players[i].p_team == team)
+	  maxrank = MAX(rank, players[i].p_stats.st_rank);
+    }
+    else
+      maxrank = NUMRANKS;
+
+    if ((rank < MIN(tempship->s_rank, maxrank) && !(royal > GODLIKE)) &&
+	!(shipvals[tmpPick].s_nflags & SFNMASSPRODUCED))
+    {
+      char buf[100];
+      sprintf(buf, "Sorry %s, a rank of %s is required to command that ship.",
+	      ranks[rank].name, ranks[tempship->s_rank].name);
+      warning(buf);
+      return 0;
+    }
+#ifdef LEAGUE_SUPPORT
+  }
+#endif
+  used_teamstr = used_planstr = 0;
+  shipcount = 0;		/* How many ships of that type */
+  /* are on our team already? */
+  for (i = 0; i < MAXPLAYER; i++)
+  {
+    if (players[i].p_status == PALIVE && players[i].p_team == team)
+    {
+      if (players[i].p_ship.s_type == type)
+	shipcount++;
+      used_teamstr += players[i].p_ship.s_numdefn;
+      used_planstr += players[i].p_ship.s_numplan;
+    }
+  }
+  /*
+   * if you are in a base, and near the limits, you will sometimes have to
+   * switch into a normal ship before changing into another base
+   */
+
+  if ((shipcount >= tempship->s_maxnum) && !(shipvals[tmpPick].s_nflags & SFNMASSPRODUCED))
+  {
+    char buf[100];
+    sprintf(buf, "We already have %d %ss.", shipcount, tempship->s_name);
+    warning(buf);
+    return 0;
+  }
+  if ((teams[team].s_turns[type] >
+       (tempship->s_maxnum - shipcount - 1) * tempship->s_timer) &&
+      !(shipvals[tmpPick].s_nflags & SFNMASSPRODUCED))
+  {
+    char buf[100];
+    int turnsleft = teams[team].s_turns[type] -
+    (tempship->s_maxnum - shipcount - 1) * tempship->s_timer;
+    if (teams[team].s_turns[type] > 1)
+    {
+      sprintf(buf, "We are still building that ship (%d minutes until finished.)", turnsleft);
+      warning(buf);
+    }
+    else
+      warning("We are still building that ship (1 minute until finished.)");
+    return 0;
+  }
+  if ((tempship->s_numdefn &&
+       numShips(team) < tempship->s_numdefn + used_teamstr) &&
+      !(shipvals[tmpPick].s_nflags & SFNMASSPRODUCED))
+  {
+    char buf[100];
+    sprintf(buf, "Your team is not strong enough to defend a %s (%d+%d players needed).",
+	    tempship->s_name, tempship->s_numdefn, used_teamstr);
+    warning(buf);
+    return 0;
+  }
+  if ((tempship->s_numplan &&
+       numPlanets(team) < tempship->s_numplan + used_planstr) &&
+      !(shipvals[tmpPick].s_nflags & SFNMASSPRODUCED))
+  {
+    char buf[100];
+    sprintf(buf, "Your team's struggling economy cannot support a %s (%d+%d planets needed).", tempship->s_name, tempship->s_numplan, used_planstr);
+    warning(buf);
+    return 0;			/* have enough planets? */
+  }
+  return 1;
+}
+
+
+/*----------------------------------NUMSHIPS------------------------------*/
+/* This function counts the number of players on a team.  */
+
+int
+numShips(owner)
+  int owner;			/* the team to count for */
+{
+  int i;			/* looping var */
+  int num;			/* to hold player count */
+  struct player *p;		/* to point to players */
+
+  num = 0;			/* zero the count */
+  for (i = 0, p = players; i < MAXPLAYER; i++, p++)
+  {				/* go throgh players */
+    if (p->p_status != PFREE && p->p_team == owner)	/* if alive then */
+      num++;			/* inc player count */
+  }
+  return (num);			/* return number of ships */
+}
+
+
+
+
+/*------------------------------NUMPLANETS--------------------------------*/
+/* This function counts the number of planets a team has.  */
+
+int
+numPlanets(owner)
+  int owner;			/* the team to check for */
+{
+  int i;			/* looping var */
+  int num;			/* to hold count */
+  struct planet *p;		/* to point to a planet */
+
+  num = 0;			/* no planets found yet */
+  for (i = 0, p = planets; i < MAXPLANETS; i++, p++)
+  {
+    if (p->pl_owner == owner)	/* if planet owned by team then inc */
+      num++;
+  }
+  return (num);			/* return number of planets */
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Suspends warp prep [BDyess]
+ */
+void
+suspendPrep()
+{
+  /* check to see if the server allows warp prep to be suspended [BDyess] */
+  if (!configvals->warpprep_suspendable)
+    return;
+  if (me->p_flags & PFWARPPREP)
+  {
+    me->p_flags |= PFWPSUSPENDED;	/* turn on suspended flag */
+    warning("Warp prep suspended.");
+  }
+  else
+  {
+    warning("Not in warp prep!");
+  }
+}
+
+/*
+ * Unsuspends warp prep [BDyess]
+ */
+void
+unsuspendPrep()
+{
+  /* check to see if the server allows warp prep to be suspended [BDyess] */
+  if (!configvals->warpprep_suspendable)
+    return;
+  if (me->p_flags & PFWARPPREP)
+  {
+    me->p_flags &= ~PFWPSUSPENDED;	/* turn off suspended flag */
+    warning("Warp prep continued.");
+  }
+  else
+  {
+    warning("Not in warp prep!");
+  }
+}
+
+/*-------END OF LINE----*/