OctaCore/src/game/game.hh

566 lines
20 KiB
C++

#ifndef __GAME_H__
#define __GAME_H__
#include "cube.hh"
// animations
enum
{
ANIM_DEAD = ANIM_GAMESPECIFIC, ANIM_DYING,
ANIM_IDLE, ANIM_RUN_N, ANIM_RUN_NE, ANIM_RUN_E, ANIM_RUN_SE, ANIM_RUN_S, ANIM_RUN_SW, ANIM_RUN_W, ANIM_RUN_NW,
ANIM_JUMP, ANIM_JUMP_N, ANIM_JUMP_NE, ANIM_JUMP_E, ANIM_JUMP_SE, ANIM_JUMP_S, ANIM_JUMP_SW, ANIM_JUMP_W, ANIM_JUMP_NW,
ANIM_SINK, ANIM_SWIM,
ANIM_CROUCH, ANIM_CROUCH_N, ANIM_CROUCH_NE, ANIM_CROUCH_E, ANIM_CROUCH_SE, ANIM_CROUCH_S, ANIM_CROUCH_SW, ANIM_CROUCH_W, ANIM_CROUCH_NW,
ANIM_CROUCH_JUMP, ANIM_CROUCH_JUMP_N, ANIM_CROUCH_JUMP_NE, ANIM_CROUCH_JUMP_E, ANIM_CROUCH_JUMP_SE, ANIM_CROUCH_JUMP_S, ANIM_CROUCH_JUMP_SW, ANIM_CROUCH_JUMP_W, ANIM_CROUCH_JUMP_NW,
ANIM_CROUCH_SINK, ANIM_CROUCH_SWIM,
ANIM_SHOOT, ANIM_MELEE,
ANIM_PAIN,
ANIM_EDIT, ANIM_LAG, ANIM_TAUNT, ANIM_WIN, ANIM_LOSE,
ANIM_GUN_IDLE, ANIM_GUN_SHOOT, ANIM_GUN_MELEE,
ANIM_VWEP_IDLE, ANIM_VWEP_SHOOT, ANIM_VWEP_MELEE,
NUMANIMS
};
static const char * const animnames[] =
{
"mapmodel",
"dead", "dying",
"idle", "run N", "run NE", "run E", "run SE", "run S", "run SW", "run W", "run NW",
"jump", "jump N", "jump NE", "jump E", "jump SE", "jump S", "jump SW", "jump W", "jump NW",
"sink", "swim",
"crouch", "crouch N", "crouch NE", "crouch E", "crouch SE", "crouch S", "crouch SW", "crouch W", "crouch NW",
"crouch jump", "crouch jump N", "crouch jump NE", "crouch jump E", "crouch jump SE", "crouch jump S", "crouch jump SW", "crouch jump W", "crouch jump NW",
"crouch sink", "crouch swim",
"shoot", "melee",
"pain",
"edit", "lag", "taunt", "win", "lose",
"gun idle", "gun shoot", "gun melee",
"vwep idle", "vwep shoot", "vwep melee"
};
// console message types
enum
{
CON_CHAT = 1<<8,
CON_TEAMCHAT = 1<<9,
CON_GAMEINFO = 1<<10,
CON_FRAG_SELF = 1<<11,
CON_FRAG_OTHER = 1<<12,
CON_TEAMKILL = 1<<13
};
// network quantization scale
#define DMF 16.0f // for world locations
#define DNF 100.0f // for normalized vectors
#define DVELF 1.0f // for playerspeed based velocity vectors
enum // static entity types
{
NOTUSED = ET_EMPTY, // entity slot not in use in map
LIGHT = ET_LIGHT, // lightsource, attr1 = radius, attr2 = intensity
MAPMODEL = ET_MAPMODEL, // attr1 = idx, attr2 = yaw, attr3 = pitch, attr4 = roll, attr5 = scale
PLAYERSTART, // attr1 = angle, attr2 = team
ENVMAP = ET_ENVMAP, // attr1 = radius
PARTICLES = ET_PARTICLES,
MAPSOUND = ET_SOUND,
SPOTLIGHT = ET_SPOTLIGHT,
DECAL = ET_DECAL,
TELEPORT, // attr1 = idx, attr2 = model, attr3 = tag
TELEDEST, // attr1 = angle, attr2 = idx
JUMPPAD, // attr1 = zpush, attr2 = ypush, attr3 = xpush
FLAG, // attr1 = angle, attr2 = team
MAXENTTYPES,
I_FIRST = 0,
I_LAST = -1
};
struct gameentity : extentity
{
};
enum { GUN_RAIL = 0, GUN_PULSE, NUMGUNS };
enum { ACT_IDLE = 0, ACT_SHOOT, ACT_MELEE, NUMACTS };
enum { ATK_RAIL_SHOOT = 0, ATK_RAIL_MELEE, ATK_PULSE_SHOOT, ATK_PULSE_MELEE, NUMATKS };
#define validgun(n) ((n) >= 0 && (n) < NUMGUNS)
#define validact(n) ((n) >= 0 && (n) < NUMACTS)
#define validatk(n) ((n) >= 0 && (n) < NUMATKS)
enum
{
M_TEAM = 1<<0,
M_OVERTIME = 1<<1,
M_EDIT = 1<<2,
M_DEMO = 1<<3,
M_LOCAL = 1<<4,
M_LOBBY = 1<<5,
M_RAIL = 1<<6,
M_PULSE = 1<<7
};
static struct gamemodeinfo
{
const char *name, *prettyname;
int flags;
const char *info;
} gamemodes[] =
{
{ "demo", "Demo", M_DEMO | M_LOCAL, NULL},
{ "edit", "Edit", M_EDIT, "Cooperative Editing:\nEdit maps with multiple players simultaneously." },
{ "rdm", "rDM", M_LOBBY | M_RAIL, "Railgun Deathmatch:\nFrag everyone with railguns to score points." },
{ "pdm", "pDM", M_LOBBY | M_PULSE, "Pulse Rifle Deathmatch:\nFrag everyone with pulse rifles to score points." },
{ "rtdm", "rTDM", M_TEAM | M_RAIL, "Railgun Team Deathmatch:\nFrag \fs\f3the enemy team\fr with railguns to score points for \fs\f1your team\fr." },
{ "ptdm", "pTDM", M_TEAM | M_PULSE, "Pulse Rifle Team Deathmatch:\nFrag \fs\f3the enemy team\fr with pulse rifles to score points for \fs\f1your team\fr." },
};
#define STARTGAMEMODE (-1)
#define NUMGAMEMODES ((int)(sizeof(gamemodes)/sizeof(gamemodes[0])))
#define m_valid(mode) ((mode) >= STARTGAMEMODE && (mode) < STARTGAMEMODE + NUMGAMEMODES)
#define m_check(mode, flag) (m_valid(mode) && gamemodes[(mode) - STARTGAMEMODE].flags&(flag))
#define m_checknot(mode, flag) (m_valid(mode) && !(gamemodes[(mode) - STARTGAMEMODE].flags&(flag)))
#define m_checkall(mode, flag) (m_valid(mode) && (gamemodes[(mode) - STARTGAMEMODE].flags&(flag)) == (flag))
#define m_teammode false
#define m_overtime false
#define isteam(a,b) false
#define m_rail false
#define m_pulse false
#define m_demo false
#define m_edit true
#define m_lobby false
#define m_timed false
#define m_botmode false
#define m_mp(mode) false
enum { MM_AUTH = -1, MM_OPEN = 0, MM_VETO, MM_LOCKED, MM_PRIVATE, MM_PASSWORD, MM_START = MM_AUTH, MM_INVALID = MM_START - 1 };
static const char * const mastermodenames[] = { "auth", "open", "veto", "locked", "private", "password" };
static const char * const mastermodecolors[] = { "", "\f0", "\f2", "\f2", "\f3", "\f3" };
static const char * const mastermodeicons[] = { "server", "server", "serverlock", "serverlock", "serverpriv", "serverpriv" };
// hardcoded sounds, defined in sounds.cfg
enum
{
S_JUMP = 0, S_LAND,
S_SPLASHIN, S_SPLASHOUT, S_BURN,
S_ITEMSPAWN, S_TELEPORT, S_JUMPPAD,
S_MELEE, S_PULSE1, S_PULSE2, S_PULSEEXPLODE, S_RAIL1, S_RAIL2,
S_WEAPLOAD, S_NOAMMO, S_HIT,
S_PAIN1, S_PAIN2, S_DIE1, S_DIE2
};
// network messages codes, c2s, c2c, s2c
enum { PRIV_NONE = 0, PRIV_MASTER, PRIV_AUTH, PRIV_ADMIN };
enum
{
N_CONNECT = 0, N_SERVINFO, N_WELCOME, N_INITCLIENT, N_POS, N_TEXT, N_SOUND, N_CDIS,
N_SHOOT, N_EXPLODE, N_SUICIDE,
N_DIED, N_DAMAGE, N_HITPUSH, N_SHOTFX, N_EXPLODEFX,
N_TRYSPAWN, N_SPAWNSTATE, N_SPAWN, N_FORCEDEATH,
N_GUNSELECT, N_TAUNT,
N_MAPCHANGE, N_MAPVOTE, N_TEAMINFO, N_ITEMSPAWN, N_ITEMPICKUP, N_ITEMACC, N_TELEPORT, N_JUMPPAD,
N_PING, N_PONG, N_CLIENTPING,
N_TIMEUP, N_FORCEINTERMISSION,
N_SERVMSG, N_ITEMLIST, N_RESUME,
N_EDITMODE, N_EDITENT, N_EDITF, N_EDITT, N_EDITM, N_FLIP, N_COPY, N_PASTE, N_ROTATE, N_REPLACE, N_DELCUBE, N_CALCLIGHT, N_REMIP, N_EDITVSLOT, N_UNDO, N_REDO, N_NEWMAP, N_GETMAP, N_SENDMAP, N_CLIPBOARD, N_EDITVAR,
N_SPECTATOR, N_SETTEAM,
N_SAYTEAM,
N_CLIENT,
N_PAUSEGAME, N_GAMESPEED,
N_MAPCRC, N_CHECKMAPS,
N_SWITCHNAME, N_SWITCHMODEL, N_SWITCHCOLOR, N_SWITCHTEAM,
N_SERVCMD,
NUMMSG
};
static const int msgsizes[] = // size inclusive message token, 0 for variable or not-checked sizes
{
N_CONNECT, 0, N_SERVINFO, 0, N_WELCOME, 1, N_INITCLIENT, 0, N_POS, 0, N_TEXT, 0, N_SOUND, 2, N_CDIS, 2,
N_SHOOT, 0, N_EXPLODE, 0, N_SUICIDE, 1,
N_DIED, 5, N_DAMAGE, 5, N_HITPUSH, 7, N_SHOTFX, 10, N_EXPLODEFX, 4,
N_TRYSPAWN, 1, N_SPAWNSTATE, 8, N_SPAWN, 3, N_FORCEDEATH, 2,
N_GUNSELECT, 2, N_TAUNT, 1,
N_MAPCHANGE, 0, N_MAPVOTE, 0, N_TEAMINFO, 0, N_ITEMSPAWN, 2, N_ITEMPICKUP, 2, N_ITEMACC, 3,
N_PING, 2, N_PONG, 2, N_CLIENTPING, 2,
N_TIMEUP, 2, N_FORCEINTERMISSION, 1,
N_SERVMSG, 0, N_ITEMLIST, 0, N_RESUME, 0,
N_EDITMODE, 2, N_EDITENT, 11, N_EDITF, 16, N_EDITT, 16, N_EDITM, 16, N_FLIP, 14, N_COPY, 14, N_PASTE, 14, N_ROTATE, 15, N_REPLACE, 17, N_DELCUBE, 14, N_CALCLIGHT, 1, N_REMIP, 1, N_EDITVSLOT, 16, N_UNDO, 0, N_REDO, 0, N_NEWMAP, 2, N_GETMAP, 1, N_SENDMAP, 0, N_EDITVAR, 0,
N_SPECTATOR, 3, N_SETTEAM, 0,
N_SAYTEAM, 0,
N_CLIENT, 0,
N_PAUSEGAME, 0, N_GAMESPEED, 0,
N_MAPCRC, 0, N_CHECKMAPS, 1,
N_SWITCHNAME, 0, N_SWITCHMODEL, 2, N_SWITCHCOLOR, 2, N_SWITCHTEAM, 2,
N_SERVCMD, 0,
-1
};
#define TESSERACT_SERVER_PORT 42000
#define TESSERACT_LANINFO_PORT 41998
#define TESSERACT_MASTER_PORT 41999
#define PROTOCOL_VERSION 2 // bump when protocol changes
#define DEMO_VERSION 1 // bump when demo format changes
#define DEMO_MAGIC "TESSERACT_DEMO\0\0"
struct demoheader
{
char magic[16];
int version, protocol;
};
#define MAXNAMELEN 15
enum
{
HICON_RED_FLAG = 0,
HICON_BLUE_FLAG,
HICON_X = 20,
HICON_Y = 1650,
HICON_TEXTY = 1644,
HICON_STEP = 490,
HICON_SIZE = 120,
HICON_SPACE = 40
};
#if 0
static struct itemstat { int add, max, sound; const char *name; int icon, info; } itemstats[] =
{
};
#endif
#define validitem(n) false
#define MAXRAYS 1
#define EXP_SELFDAMDIV 2
#define EXP_SELFPUSH 2.5f
#define EXP_DISTSCALE 0.5f
static const struct attackinfo { int gun, action, anim, vwepanim, hudanim, sound, hudsound, attackdelay, damage, spread, margin, projspeed, kickamount, range, rays, hitpush, exprad, ttl, use; } attacks[NUMATKS] =
{
{ GUN_RAIL, ACT_SHOOT, ANIM_SHOOT, ANIM_VWEP_SHOOT, ANIM_GUN_SHOOT, S_RAIL1, S_RAIL2, 1300, 1, 0, 0, 0, 30, 2048, 1, 5000, 0, 0, 0 },
{ GUN_RAIL, ACT_MELEE, ANIM_MELEE, ANIM_VWEP_MELEE, ANIM_GUN_MELEE, S_MELEE, S_MELEE, 500, 1, 0, 2, 0, 0, 14, 1, 0, 0, 0, 0 },
{ GUN_PULSE, ACT_SHOOT, ANIM_SHOOT, ANIM_VWEP_SHOOT, ANIM_GUN_SHOOT, S_PULSE1, S_PULSE2, 700, 1, 0, 1, 1000, 30, 1024, 1, 5000, 15, 0, 0 },
{ GUN_PULSE, ACT_MELEE, ANIM_MELEE, ANIM_VWEP_MELEE, ANIM_GUN_MELEE, S_MELEE, S_MELEE, 500, 1, 0, 2, 0, 0, 14, 1, 0, 0, 0, 0 }
};
static const struct guninfo { const char *name, *file, *vwep; int attacks[NUMACTS]; } guns[NUMGUNS] =
{
{ "railgun", "railgun", "worldgun/railgun", { -1, ATK_RAIL_SHOOT, ATK_RAIL_MELEE }, },
{ "pulse rifle", "pulserifle", "worldgun/pulserifle", { -1, ATK_PULSE_SHOOT, ATK_PULSE_MELEE } }
};
// inherited by gameent and server clients
struct gamestate
{
int health, maxhealth;
int gunselect, gunwait;
int ammo[NUMGUNS];
gamestate() : maxhealth(1) {}
bool canpickup(int type)
{
return validitem(type);
}
void pickup(int type)
{
}
void respawn()
{
health = maxhealth;
gunselect = GUN_RAIL;
gunwait = 0;
loopi(NUMGUNS) ammo[i] = 0;
}
void spawnstate(int gamemode)
{
if(m_rail)
{
gunselect = GUN_RAIL;
ammo[GUN_RAIL] = 1;
}
else if(m_pulse)
{
gunselect = GUN_PULSE;
ammo[GUN_PULSE] = 1;
}
else if(m_edit)
{
gunselect = GUN_RAIL;
loopi(NUMGUNS) ammo[i] = 1;
}
}
// just subtract damage here, can set death, etc. later in code calling this
int dodamage(int damage)
{
health -= damage;
return damage;
}
int hasammo(int gun, int exclude = -1)
{
return validgun(gun) && gun != exclude && ammo[gun] > 0;
}
};
#define MAXTEAMS 2
static const char * const teamnames[1+MAXTEAMS] = { "", "azul", "rojo" };
static const char * const teamtextcode[1+MAXTEAMS] = { "\f0", "\f1", "\f3" };
static const int teamtextcolor[1+MAXTEAMS] = { 0x1EC850, 0x6496FF, 0xFF4B19 };
static const char * const teamblipcolor[1+MAXTEAMS] = { "_neutral", "_blue", "_red" };
static inline int teamnumber(const char *name) { loopi(MAXTEAMS) if(!strcmp(teamnames[1+i], name)) return 1+i; return 0; }
#define validteam(n) ((n) >= 1 && (n) <= MAXTEAMS)
#define teamname(n) (teamnames[validteam(n) ? (n) : 0])
struct gameent : dynent, gamestate
{
int weight; // affects the effectiveness of hitpush
int clientnum, lastupdate, plag, ping;
int lifesequence; // sequence id for each respawn, used in damage test
int respawned, suicided;
int lastpain;
int lastaction, lastattack;
int attacking;
int lasttaunt;
int lastpickup, lastpickupmillis, flagpickup;
int frags, flags, deaths, totaldamage, totalshots;
editinfo *edit;
float deltayaw, deltapitch, deltaroll, newyaw, newpitch, newroll;
int smoothmillis;
string name, info;
int team, playermodel, playercolor;
int ownernum, lastnode;
vec muzzle;
gameent() : weight(100), clientnum(-1), lastupdate(0), plag(0), ping(0), lifesequence(0), respawned(-1), suicided(-1), lastpain(0), frags(0), flags(0), deaths(0), totaldamage(0), totalshots(0), edit(NULL), smoothmillis(-1), team(0), playermodel(-1), playercolor(0), ownernum(-1), muzzle(-1, -1, -1)
{
name[0] = info[0] = 0;
respawn();
}
~gameent()
{
freeeditinfo(edit);
}
void hitpush(int damage, const vec &dir, gameent *actor, int atk)
{
vec push(dir);
push.mul((actor==this && attacks[atk].exprad ? EXP_SELFPUSH : 1.0f)*attacks[atk].hitpush*damage/weight);
vel.add(push);
}
void respawn()
{
dynent::reset();
gamestate::respawn();
respawned = suicided = -1;
lastaction = 0;
lastattack = -1;
attacking = ACT_IDLE;
lasttaunt = 0;
lastpickup = -1;
lastpickupmillis = 0;
flagpickup = 0;
lastnode = -1;
}
int respawnwait(int secs, int delay = 0)
{
return max(0, secs - (::lastmillis - lastpain - delay)/1000);
}
void startgame()
{
frags = flags = deaths = 0;
totaldamage = totalshots = 0;
maxhealth = 1;
lifesequence = -1;
respawned = suicided = -2;
}
};
struct teaminfo
{
int frags;
teaminfo() { reset(); }
void reset() { frags = 0; }
};
namespace entities
{
extern vector<extentity *> ents;
extern const char *entmdlname(int type);
extern const char *itemname(int i);
extern int itemicon(int i);
extern void preloadentities();
extern void renderentities();
extern void checkitems(gameent *d);
extern void resetspawns();
extern void spawnitems(bool force = false);
extern void putitems(packetbuf &p);
extern void setspawn(int i, bool on);
extern void teleport(int n, gameent *d);
extern void pickupeffects(int n, gameent *d);
extern void teleporteffects(gameent *d, int tp, int td, bool local = true);
extern void jumppadeffects(gameent *d, int jp, bool local = true);
}
namespace game
{
struct clientmode
{
virtual ~clientmode() {}
virtual void preload() {}
virtual float clipconsole(float w, float h) { return 0; }
virtual void drawhud(gameent *d, int w, int h) {}
virtual void rendergame() {}
virtual void respawned(gameent *d) {}
virtual void setup() {}
virtual void checkitems(gameent *d) {}
virtual int respawnwait(gameent *d, int delay = 0) { return 0; }
virtual void pickspawn(gameent *d) { findplayerspawn(d, -1, m_teammode ? d->team : 0); }
virtual void senditems(packetbuf &p) {}
virtual void removeplayer(gameent *d) {}
virtual void gameover() {}
virtual bool hidefrags() { return false; }
};
extern clientmode *cmode;
extern void setclientmode();
// game
extern string clientmap;
extern bool intermission;
extern int maptime, maprealtime, maplimit;
extern gameent *player1;
extern vector<gameent *> players, clients;
extern int lastspawnattempt;
extern int lasthit;
extern int following;
extern int smoothmove, smoothdist;
extern bool clientoption(const char *arg);
extern gameent *getclient(int cn);
extern gameent *newclient(int cn);
extern const char *colorname(gameent *d, const char *name = NULL, const char *alt = NULL, const char *color = "");
extern const char *teamcolorname(gameent *d, const char *alt = "you");
extern const char *teamcolor(const char *prefix, const char *suffix, int team, const char *alt);
extern void teamsound(bool sameteam, int n, const vec *loc = NULL);
extern void teamsound(gameent *d, int n, const vec *loc = NULL);
extern gameent *pointatplayer();
extern gameent *hudplayer();
extern gameent *followingplayer(gameent *fallback = NULL);
extern void stopfollowing();
extern void checkfollow();
extern void nextfollow(int dir = 1);
extern void clientdisconnected(int cn, bool notify = true);
extern void clearclients(bool notify = true);
extern void startgame();
extern void spawnplayer(gameent *);
extern void deathstate(gameent *d, bool restore = false);
extern void damaged(int damage, gameent *d, gameent *actor, bool local = true);
extern void killed(gameent *d, gameent *actor);
extern void timeupdate(int timeremain);
extern void msgsound(int n, physent *d = NULL);
extern void drawicon(int icon, float x, float y, float sz = 120);
const char *mastermodecolor(int n, const char *unknown);
const char *mastermodeicon(int n, const char *unknown);
// client
extern bool connected, remote, demoplayback;
extern string servdesc;
extern vector<uchar> messages;
extern int parseplayer(const char *arg);
extern bool addmsg(int type, const char *fmt = NULL, ...);
extern void switchname(const char *name);
extern void switchteam(const char *name);
extern void switchplayermodel(int playermodel);
extern void switchplayercolor(int playercolor);
extern void sendmapinfo();
extern void changemap(const char *name, int mode);
extern void c2sinfo(bool force = false);
extern void sendposition(gameent *d, bool reliable = false);
// weapon
extern int getweapon(const char *name);
extern void shoot(gameent *d, const vec &targ);
extern void shoteffects(int atk, const vec &from, const vec &to, gameent *d, bool local, int id, int prevaction);
extern void explode(bool local, gameent *owner, const vec &v, const vec &vel, dynent *safe, int dam, int atk);
extern void explodeeffects(int atk, gameent *d, bool local, int id = 0);
extern void damageeffect(int damage, gameent *d, bool thirdperson = true);
extern void gibeffect(int damage, const vec &vel, gameent *d);
extern float intersectdist;
extern bool intersect(dynent *d, const vec &from, const vec &to, float margin = 0, float &dist = intersectdist);
extern dynent *intersectclosest(const vec &from, const vec &to, gameent *at, float margin = 0, float &dist = intersectdist);
extern void clearbouncers();
extern void updatebouncers(int curtime);
extern void removebouncers(gameent *owner);
extern void renderbouncers();
extern void clearprojectiles();
extern void updateprojectiles(int curtime);
extern void removeprojectiles(gameent *owner);
extern void renderprojectiles();
extern void preloadbouncers();
extern void removeweapons(gameent *owner);
extern void updateweapons(int curtime);
extern void gunselect(int gun, gameent *d);
extern void weaponswitch(gameent *d);
// render
struct playermodelinfo
{
const char *model[1+MAXTEAMS], *hudguns[1+MAXTEAMS],
*icon[1+MAXTEAMS];
bool ragdoll;
};
extern void saveragdoll(gameent *d);
extern void clearragdolls();
extern void moveragdolls();
extern const playermodelinfo &getplayermodelinfo(gameent *d);
extern int getplayercolor(gameent *d, int team);
extern int chooserandomplayermodel(int seed);
extern void syncplayer();
extern void swayhudgun(int curtime);
extern vec hudgunorigin(int gun, const vec &from, const vec &to, gameent *d);
}
namespace server
{
extern const char *modename(int n, const char *unknown = "unknown");
extern const char *modeprettyname(int n, const char *unknown = "unknown");
extern const char *mastermodename(int n, const char *unknown = "unknown");
extern void startintermission();
extern void stopdemo();
extern void forcemap(const char *map, int mode);
extern void forcepaused(bool paused);
extern void forcegamespeed(int speed);
extern void hashpassword(int cn, int sessionid, const char *pwd, char *result, int maxlen = MAXSTRLEN);
extern int msgsizelookup(int msg);
extern bool serveroption(const char *arg);
extern bool delayspawn(int type);
}
#endif