ref: a4c4b45d8b2136733c76a4b86c7896bfa939ad25
dir: /ctf/game.h/
typedef struct link_t link_t; typedef struct game_import_t game_import_t; typedef struct game_export_t game_export_t; typedef struct gitem_armor_t gitem_armor_t; typedef struct gitem_t gitem_t; typedef struct game_locals_t game_locals_t; typedef struct level_locals_t level_locals_t; typedef struct spawn_temp_t spawn_temp_t; typedef struct moveinfo_t moveinfo_t; typedef struct mframe_t mframe_t; typedef struct mmove_t mmove_t; typedef struct monsterinfo_t monsterinfo_t; typedef struct field_t field_t; typedef struct pmenuhnd_t pmenuhnd_t; typedef struct pmenu_t pmenu_t; typedef struct client_persistant_t client_persistant_t; typedef struct client_respawn_t client_respawn_t; typedef struct edict_t edict_t; typedef struct gclient_t gclient_t; typedef struct ghost_t ghost_t; typedef void (*SelectFunc_t)(edict_t *, pmenuhnd_t *); enum{ GAME_API_VERSION = 3, /* edict->svflags * if an entity is projectile, the model index/x/y/z/pitch/yaw are * sent, encoded into seven (or eight) bytes. this is to speed up * projectiles. Currently, only the hyperblaster makes use of this. use * for items that are moving with a constant velocity that don't change * direction or model */ SVF_NOCLIENT = 1<<0, // don't send entity to clients, even if it has effects SVF_DEADMONSTER = 1<<1, // treat as CONTENTS_DEADMONSTER for collision SVF_MONSTER = 1<<2, // treat as CONTENTS_MONSTER for collision SVF_PROJECTILE = 1<<3, // entity is simple projectile, used for network optimization MAX_ENT_CLUSTERS = 16 }; /* edict->solid values */ typedef enum solid_t{ SOLID_NOT, // no interaction with other objects SOLID_TRIGGER, // only touch when inside, after moving SOLID_BBOX, // touch on edge SOLID_BSP // bsp clip, touch on edge }solid_t; /* only used for entity area links now */ struct link_t{ link_t *prev; link_t *next; }; struct game_import_t{ void (*bprintf)(int, char *, ...); void (*dprintf)(char *, ...); void (*cprintf)(edict_t *, int, char *, ...); void (*centerprintf)(edict_t *, char *, ...); void (*sound)(edict_t *, int, int, float, float, float); void (*positioned_sound)(vec3_t, edict_t *, int, int, float, float, float); /* config strings hold all the index strings, the lightstyles, and misc * data like the sky definition and cdtrack. all of the current * configstrings are sent to clients when they connect, and changes are * sent to all connected clients. */ void (*configstring)(int, char *); void (*error)(char *, ...); /* the *index functions create configstrings and some internal server * state */ int (*modelindex)(char *); int (*soundindex)(char *); int (*imageindex)(char *); void (*setmodel)(edict_t *, char *); /* collision detection */ trace_t (*trace)(vec3_t, vec3_t, vec3_t, vec3_t, edict_t *, int); int (*pointcontents)(vec3_t); qboolean (*inPVS)(vec3_t, vec3_t); qboolean (*inPHS)(vec3_t, vec3_t); void (*SetAreaPortalState)(int, qboolean); qboolean (*AreasConnected)(int, int); /* an entity will never be sent to a client or used for collision if it * is not passed to linkentity. if the size, position, or solidity * changes, it must be relinked. */ void (*linkentity)(edict_t *); void (*unlinkentity)(edict_t *); // call before removing an interactive edict int (*BoxEdicts)(vec3_t, vec3_t, edict_t **, int, int); void (*Pmove)(pmove_t *); // player movement code common with client prediction /* network messaging */ void (*multicast)(vec3_t, multicast_t); void (*unicast) (edict_t *, qboolean); void (*WriteChar)(int); void (*WriteByte)(int); void (*WriteShort)(int); void (*WriteLong)(int); void (*WriteFloat)(float); void (*WriteString)(char *); void (*WritePosition)(vec3_t); // some fractional bits void (*WriteDir)(vec3_t); // single byte encoded, very coarse void (*WriteAngle)(float); /* managed memory allocation */ void* (*TagMalloc)(int, int); void (*TagFree)(void *); void (*FreeTags)(int); /* console variable interaction */ cvar_t* (*cvar)(char *, char *, int); cvar_t* (*cvar_set)(char *, char *); cvar_t* (*cvar_forceset)(char *, char *); /* ClientCommand and ServerCommand parameter access */ int (*argc)(void); char* (*argv)(int); char* (*args)(void); // concatenation of all argv >= 1 /* add commands to the server console as if they were typed in for map * changing, etc */ void (*AddCommandString)(char *); void (*DebugGraph)(float, int); }; extern game_import_t gi; struct game_export_t{ int apiversion; /* the init function will only be called when a game starts, not each * time a level is loaded. persistant data for clients and the server * can be allocated in init */ void (*Init)(void); void (*Shutdown)(void); /* each new level entered will cause a call to SpawnEntities */ void (*SpawnEntities)(char *, char *, char *); /* Read/Write Game is for storing persistant cross level information * about the world state and the clients. WriteGame is called every * time a level is exited. ReadGame is called on a loadgame. */ void (*WriteGame)(char *, qboolean); void (*ReadGame)(char *); /* ReadLevel is called after the default map information has been * loaded with SpawnEntities */ void (*WriteLevel)(char *); void (*ReadLevel)(char *); qboolean (*ClientConnect)(edict_t *, char *); void (*ClientBegin)(edict_t *); void (*ClientUserinfoChanged)(edict_t *, char *); void (*ClientDisconnect)(edict_t *); void (*ClientCommand)(edict_t *); void (*ClientThink)(edict_t *, usercmd_t *); void (*RunFrame)(void); /* ServerCommand will be called when an "sv <command>" command is * issued on the server console. The game can issue gi.argc() or * gi.argv() commands to get the rest of the parameters */ void (*ServerCommand)(void); /* global variables shared between game and server * The edict array is allocated in the game dll so it can vary in size * from one game to another. The size will be fixed when ge->Init() is * called */ edict_t *edicts; int edict_size; int num_edicts; // current number, <= max_edicts int max_edicts; }; extern game_export_t globals; extern cvar_t *maxentities; extern cvar_t *deathmatch; extern cvar_t *coop; extern cvar_t *dmflags; extern cvar_t *skill; extern cvar_t *fraglimit; extern cvar_t *timelimit; extern cvar_t *capturelimit; extern cvar_t *instantweap; extern cvar_t *password; extern cvar_t *g_select_empty; extern cvar_t *dedicated; extern cvar_t *sv_gravity; extern cvar_t *sv_maxvelocity; extern cvar_t *gun_x; extern cvar_t *gun_y; extern cvar_t *gun_z; extern cvar_t *sv_rollspeed; extern cvar_t *sv_rollangle; extern cvar_t *run_pitch; extern cvar_t *run_roll; extern cvar_t *bob_up; extern cvar_t *bob_pitch; extern cvar_t *bob_roll; extern cvar_t *sv_cheats; extern cvar_t *maxclients; extern cvar_t *flood_msgs; extern cvar_t *flood_persecond; extern cvar_t *flood_waitdelay; extern cvar_t *sv_maplist; extern cvar_t *ctf; #define GAMEVERSION "baseq2" #define DAMAGE_TIME 0.5 #define FALL_TIME 0.3 #define FRAMETIME 0.1 enum{ /* view pitching times */ /* edict->spawnflags: these are set with checkboxes on each entity in * the map editor */ SPAWNFLAG_NOT_EASY = 1<<8, SPAWNFLAG_NOT_MEDIUM = 1<<9, SPAWNFLAG_NOT_HARD = 1<<10, SPAWNFLAG_NOT_DEATHMATCH = 1<<11, SPAWNFLAG_NOT_COOP = 1<<12, /* edict->flags */ FL_FLY = 1<<0, FL_SWIM = 1<<1, // implied immunity to drowining FL_IMMUNE_LASER = 1<<2, FL_INWATER = 1<<3, FL_GODMODE = 1<<4, FL_NOTARGET = 1<<5, FL_IMMUNE_SLIME = 1<<6, FL_IMMUNE_LAVA = 1<<7, FL_PARTIALGROUND = 1<<8, // not all corners are valid FL_WATERJUMP = 1<<9, // player jumping out of water FL_TEAMSLAVE = 1<<10, // not the first on the team FL_NO_KNOCKBACK = 1<<11, FL_POWER_ARMOR = 1<<12, // power armor (if any) is active FL_RESPAWN = 1<<31, // used for item respawning /* memory tags to allow dynamic memory to be cleaned up */ TAG_GAME = 765, // clear when unloading the dll TAG_LEVEL = 766, // clear when loading a new level MELEE_DISTANCE = 80, BODY_QUEUE_SIZE = 8, /* deadflag */ DEAD_NO = 0, DEAD_DYING = 1, DEAD_DEAD = 2, DEAD_RESPAWNABLE = 3, /* range */ RANGE_MELEE = 0, RANGE_NEAR = 1, RANGE_MID = 2, RANGE_FAR = 3, /* gib types */ GIB_ORGANIC = 0, GIB_METALLIC = 1, /* monster ai flags */ AI_STAND_GROUND = 1<<0, AI_TEMP_STAND_GROUND = 1<<1, AI_SOUND_TARGET = 1<<2, AI_LOST_SIGHT = 1<<3, AI_PURSUIT_LAST_SEEN = 1<<4, AI_PURSUE_NEXT = 1<<5, AI_PURSUE_TEMP = 1<<6, AI_HOLD_FRAME = 1<<7, AI_GOOD_GUY = 1<<8, AI_BRUTAL = 1<<9, AI_NOSTEP = 1<<10, AI_DUCKED = 1<<11, AI_COMBAT_POINT = 1<<12, AI_MEDIC = 1<<13, AI_RESURRECTING = 1<<14, /* monster attack state */ AS_STRAIGHT = 1, AS_SLIDING = 2, AS_MELEE = 3, AS_MISSILE = 4, /* armor types */ ARMOR_NONE = 0, ARMOR_JACKET = 1, ARMOR_COMBAT = 2, ARMOR_BODY = 3, ARMOR_SHARD = 4, /* power armor types */ POWER_ARMOR_NONE = 0, POWER_ARMOR_SCREEN = 1, POWER_ARMOR_SHIELD = 2, /* handedness values */ RIGHT_HANDED = 0, LEFT_HANDED = 1, CENTER_HANDED = 2, /* game.serverflags values */ SFL_CROSS_TRIGGER_1 = 1<<0, SFL_CROSS_TRIGGER_2 = 1<<1, SFL_CROSS_TRIGGER_3 = 1<<2, SFL_CROSS_TRIGGER_4 = 1<<3, SFL_CROSS_TRIGGER_5 = 1<<4, SFL_CROSS_TRIGGER_6 = 1<<5, SFL_CROSS_TRIGGER_7 = 1<<6, SFL_CROSS_TRIGGER_8 = 1<<7, SFL_CROSS_TRIGGER_MASK = 0xff, /* noise types for PlayerNoise */ PNOISE_SELF = 0, PNOISE_WEAPON = 1, PNOISE_IMPACT = 2, /* gitem_t->flags */ IT_WEAPON = 1, // use makes active weapon IT_AMMO = 2, IT_ARMOR = 4, IT_STAY_COOP = 8, IT_KEY = 16, IT_POWERUP = 32, IT_TECH = 64, /* gitem_t->weapmodel model index */ WEAP_BLASTER = 1, WEAP_SHOTGUN = 2, WEAP_SUPERSHOTGUN = 3, WEAP_MACHINEGUN = 4, WEAP_CHAINGUN = 5, WEAP_GRENADES = 6, WEAP_GRENADELAUNCHER = 7, WEAP_ROCKETLAUNCHER = 8, WEAP_HYPERBLASTER = 9, WEAP_RAILGUN = 10, WEAP_BFG = 11, WEAP_GRAPPLE = 12, /* means of death */ MOD_UNKNOWN = 0, MOD_BLASTER = 1, MOD_SHOTGUN = 2, MOD_SSHOTGUN = 3, MOD_MACHINEGUN = 4, MOD_CHAINGUN = 5, MOD_GRENADE = 6, MOD_G_SPLASH = 7, MOD_ROCKET = 8, MOD_R_SPLASH = 9, MOD_HYPERBLASTER = 10, MOD_RAILGUN = 11, MOD_BFG_LASER = 12, MOD_BFG_BLAST = 13, MOD_BFG_EFFECT = 14, MOD_HANDGRENADE = 15, MOD_HG_SPLASH = 16, MOD_WATER = 17, MOD_SLIME = 18, MOD_LAVA = 19, MOD_CRUSH = 20, MOD_TELEFRAG = 21, MOD_FALLING = 22, MOD_SUICIDE = 23, MOD_HELD_GRENADE = 24, MOD_EXPLOSIVE = 25, MOD_BARREL = 26, MOD_BOMB = 27, MOD_EXIT = 28, MOD_SPLASH = 29, MOD_TARGET_LASER = 30, MOD_TRIGGER_HURT = 31, MOD_HIT = 32, MOD_TARGET_BLASTER = 33, MOD_GRAPPLE = 34, MOD_FRIENDLY_FIRE = 1<<27, /* item spawnflags */ ITEM_TRIGGER_SPAWN = 1<<0, ITEM_NO_TOUCH = 1<<1, /* 6 bits reserved for editor flags */ /* 8 bits used as power cube id bits for coop games */ DROPPED_ITEM = 1<<16, DROPPED_PLAYER_ITEM = 1<<17, ITEM_TARGETS_USED = 1<<18, /* fields are needed for spawning from the entity string and saving or * loading games */ FFL_SPAWNTEMP = 1, /* damage flags */ DAMAGE_RADIUS = 1<<0, // damage was indirect DAMAGE_NO_ARMOR = 1<<1, // armour does not protect from this damage DAMAGE_ENERGY = 1<<2, // damage is from an energy based weapon DAMAGE_NO_KNOCKBACK = 1<<3, // do not affect velocity, just view angles DAMAGE_BULLET = 1<<4, // damage is from a bullet (used for ricochets) DAMAGE_NO_PROTECTION = 1<<5, // armor, shields, invulnerability, and godmode have no effect DEFAULT_BULLET_HSPREAD = 300, DEFAULT_BULLET_VSPREAD = 500, DEFAULT_SHOTGUN_HSPREAD = 1000, DEFAULT_SHOTGUN_VSPREAD = 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT = 12, DEFAULT_SHOTGUN_COUNT = 12, DEFAULT_SSHOTGUN_COUNT = 20, PMENU_ALIGN_LEFT = 0, PMENU_ALIGN_CENTER, PMENU_ALIGN_RIGHT, /* client_t->anim_priority */ ANIM_BASIC = 0, // stand / run ANIM_WAVE = 1, ANIM_JUMP = 2, ANIM_PAIN = 3, ANIM_ATTACK = 4, ANIM_DEATH = 5, ANIM_REVERSE = 6 }; extern int meansOfDeath; extern int sm_meat_index; extern int snd_fry; typedef enum damage_t{ DAMAGE_NO, DAMAGE_YES, // will take damage if hit DAMAGE_AIM // auto targeting recognizes this }damage_t; typedef enum weaponstate_t{ WEAPON_READY, WEAPON_ACTIVATING, WEAPON_DROPPING, WEAPON_FIRING }weaponstate_t; typedef enum ammo_t{ AMMO_BULLETS, AMMO_SHELLS, AMMO_ROCKETS, AMMO_GRENADES, AMMO_CELLS, AMMO_SLUGS }ammo_t; /* edict->movetype values */ typedef enum movetype_t{ MOVETYPE_NONE, // never moves MOVETYPE_NOCLIP, // origin and angles change with no interaction MOVETYPE_PUSH, // no clip to world, push on box contact MOVETYPE_STOP, // no clip to world, stops on box contact MOVETYPE_WALK, // gravity MOVETYPE_STEP, // gravity, special edge handling MOVETYPE_FLY, MOVETYPE_TOSS, // gravity MOVETYPE_FLYMISSILE, // extra size to monsters MOVETYPE_BOUNCE }movetype_t; struct gitem_armor_t{ int base_count; int max_count; float normal_protection; float energy_protection; int armor; }; struct gitem_t{ char *classname; // spawning name qboolean (*pickup)(edict_t *, edict_t *); void (*use)(edict_t *, gitem_t *); void (*drop)(edict_t *, gitem_t *); void (*weaponthink)(edict_t *); char *pickup_sound; char *world_model; int world_model_flags; char *view_model; /* client side info */ char *icon; char *pickup_name; // for printing on pickup int count_width; // number of digits to display by icon int quantity; // for ammo how much, for weapons how much is used per shot char *ammo; // for weapons int flags; // IT_* flags int weapmodel; // weapon model index (for weapons) void *info; int tag; char *precaches; // string of all models, sounds, and images this item will use }; extern gitem_t itemlist[]; /* this structure is left intact through an entire game. it should be * initialized at dll load time, and read/written to the server.ssv file for * savegames */ struct game_locals_t{ char helpmessage1[512]; char helpmessage2[512]; /* flash F1 icon if non 0, play sound and increment only if 1, 2, or 3 */ int helpchanged; gclient_t *clients; // [maxclients] /* can't store spawnpoint in level, because it would get overwritten by * the savegame restore */ char spawnpoint[512]; // needed for coop respawns /* store latched cvars here that we want to get at often */ int maxclients; int maxentities; /* cross level triggers */ int serverflags; int num_items; qboolean autosaved; }; extern game_locals_t game; /* this structure is cleared as each map is entered. it is read/written to the * level.sav file for savegames */ struct level_locals_t{ int framenum; float time; char level_name[MAX_QPATH]; // the descriptive name (Outer Base, etc) char mapname[MAX_QPATH]; // the server name (base1, etc) char nextmap[MAX_QPATH]; // go here when fraglimit is hit char forcemap[MAX_QPATH]; // go here /* intermission state */ float intermissiontime; // time the intermission was started char *changemap; int exitintermission; vec3_t intermission_origin; vec3_t intermission_angle; edict_t *sight_client; // changed once each frame for coop games edict_t *sight_entity; int sight_entity_framenum; edict_t *sound_entity; int sound_entity_framenum; edict_t *sound2_entity; int sound2_entity_framenum; int pic_health; int total_secrets; int found_secrets; int total_goals; int found_goals; int total_monsters; int killed_monsters; edict_t *current_entity; // entity running from G_RunFrame int body_que; // dead bodies int power_cubes; // ugly necessity for coop }; extern level_locals_t level; /* spawn_temp_t is only used to hold entity field values that can be set from * the editor, but aren't actualy present in edict_t during gameplay */ struct spawn_temp_t{ /* world vars */ char *sky; float skyrotate; vec3_t skyaxis; char *nextmap; int lip; int distance; int height; char *noise; float pausetime; char *item; char *gravity; float minyaw; float maxyaw; float minpitch; float maxpitch; }; extern spawn_temp_t st; struct moveinfo_t{ /* fixed data */ vec3_t start_origin; vec3_t start_angles; vec3_t end_origin; vec3_t end_angles; int sound_start; int sound_middle; int sound_end; float accel; float speed; float decel; float distance; float wait; /* state data */ int state; vec3_t dir; float current_speed; float move_speed; float next_speed; float remaining_distance; float decel_distance; void (*endfunc)(edict_t *); }; struct mframe_t{ void (*aifunc)(edict_t *, float); float dist; void (*thinkfunc)(edict_t *); }; struct mmove_t{ int firstframe; int lastframe; mframe_t *frame; void (*endfunc)(edict_t *); }; struct monsterinfo_t{ mmove_t *currentmove; int aiflags; int nextframe; float scale; void (*stand)(edict_t *); void (*idle)(edict_t *); void (*search)(edict_t *); void (*walk)(edict_t *); void (*run)(edict_t *); void (*dodge)(edict_t *, edict_t *, float); void (*attack)(edict_t *); void (*melee)(edict_t *); void (*sight)(edict_t *, edict_t *); qboolean (*checkattack)(edict_t *); float pausetime; float attack_finished; vec3_t saved_goal; float search_time; float trail_time; vec3_t last_sighting; int attack_state; int lefty; float idle_time; int linkcount; int power_armor_type; int power_armor_power; }; typedef enum fieldtype_t{ F_INT, F_FLOAT, F_LSTRING, // string on disk, pointer in memory, TAG_LEVEL F_GSTRING, // string on disk, pointer in memory, TAG_GAME F_VECTOR, F_ANGLEHACK, F_EDICT, // index on disk, pointer in memory F_ITEM, // index on disk, pointer in memory F_CLIENT, // index on disk, pointer in memory F_IGNORE }fieldtype_t; struct field_t{ char *name; int ofs; fieldtype_t type; int flags; }; extern field_t fields[]; struct pmenu_t{ char *text; int align; SelectFunc_t SelectFunc; }; struct pmenuhnd_t{ pmenu_t *entries; int cur; int num; void *arg; }; /* client data that stays across multiple level loads */ struct client_persistant_t{ char userinfo[MAX_INFO_STRING]; char netname[16]; int hand; /* a loadgame will leave valid entities that just don't have a * connection yet */ qboolean connected; /* values saved and restored from edicts when changing levels */ int health; int max_health; qboolean powerArmorActive; int selected_item; int inventory[MAX_ITEMS]; /* ammo capacities */ int max_bullets; int max_shells; int max_rockets; int max_grenades; int max_cells; int max_slugs; gitem_t *weapon; gitem_t *lastweapon; int power_cubes; // used for tracking the cubes in coop games int score; // for calculating total unit score in coop games }; /* client data that stays across deathmatch respawns */ struct client_respawn_t{ client_persistant_t coop_respawn; // what to set client->pers to on a respawn int enterframe; // level.framenum the client entered the game int score; // frags, etc int ctf_team; int ctf_state; float ctf_lasthurtcarrier; float ctf_lastreturnedflag; float ctf_flagsince; float ctf_lastfraggedcarrier; qboolean id_state; qboolean voted; // for elections qboolean ready; qboolean admin; ghost_t *ghost; // for ghost codes vec3_t cmd_angles; // angles sent over in the last command int game_helpchanged; int helpchanged; }; /* this structure is cleared on each PutClientInServer(), except for .pers */ struct gclient_t{ /* known to server */ player_state_t ps; // communicated by server to clients int ping; /* private to game */ client_persistant_t pers; client_respawn_t resp; pmove_state_t old_pmove; // for detecting out-of-pmove changes qboolean showscores; // set layout stat qboolean inmenu; // in menu pmenuhnd_t *menu; // current menu qboolean showinventory; // set layout stat qboolean showhelp; qboolean showhelpicon; int ammo_index; int buttons; int oldbuttons; int latched_buttons; qboolean weapon_thunk; gitem_t *newweapon; /* sum up damage over an entire frame, so shotgun blasts give a single * big kick */ int damage_armor; // damage absorbed by armor int damage_parmor; // damage absorbed by power armor int damage_blood; // damage taken out of health int damage_knockback; // impact damage vec3_t damage_from; // origin for vector calculation float killer_yaw; // when dead, look at killer weaponstate_t weaponstate; vec3_t kick_angles; // weapon kicks vec3_t kick_origin; float v_dmg_roll; // damage kicks float v_dmg_pitch; float v_dmg_time; float fall_time; // for view drop on fall float fall_value; float damage_alpha; float bonus_alpha; vec3_t damage_blend; vec3_t v_angle; // aiming direction float bobtime; // so off-ground doesn't change it vec3_t oldviewangles; vec3_t oldvelocity; float next_drown_time; int old_waterlevel; int breather_sound; int machinegun_shots; // for weapon raising /* animation vars */ int anim_end; int anim_priority; qboolean anim_duck; qboolean anim_run; /* powerup timers */ float quad_framenum; float invincible_framenum; float breather_framenum; float enviro_framenum; qboolean grenade_blew_up; float grenade_time; int silencer_shots; int weapon_sound; float pickup_msg_time; float flood_locktill; // locked from talking float flood_when[10]; // when messages were said int flood_whenhead; // head pointer for when said float respawn_time; // can respawn when time > this void *ctf_grapple; // entity of grapple int ctf_grapplestate; // true if pulling float ctf_grapplereleasetime; // time of grapple release float ctf_regentime; // regen tech float ctf_techsndtime; float ctf_lasttechmsg; edict_t *chase_target; qboolean update_chase; float menutime; // time to update menu qboolean menudirty; }; struct edict_t{ entity_state_t s; gclient_t *client; // nil if not a player /* the server expects the first part of gclient_s to be a * player_state_t but the rest of it is opaque */ qboolean inuse; int linkcount; // FIXME: move these fields to a server private sv_entity_t link_t area; // linked to a division node or leaf int num_clusters; // if -1, use headnode instead int clusternums[MAX_ENT_CLUSTERS]; int headnode; // unused if num_clusters != -1 int areanum; int areanum2; int svflags; vec3_t mins; vec3_t maxs; vec3_t absmin; vec3_t absmax; vec3_t size; solid_t solid; int clipmask; edict_t *owner; /* DO NOT MODIFY ANYTHING ABOVE THIS, THE SERVER EXPECTS THE FIELDS IN * THAT ORDER! */ int movetype; int flags; char *model; float freetime; // sv.time when the object was freed /* only used locally in game, not by server */ char *message; char *classname; int spawnflags; float timestamp; float angle; // set in qe3, -1 = up, -2 = down char *target; char *targetname; char *killtarget; char *team; char *pathtarget; char *deathtarget; char *combattarget; edict_t *target_ent; float speed; float accel; float decel; vec3_t movedir; vec3_t pos1; vec3_t pos2; vec3_t velocity; vec3_t avelocity; int mass; float air_finished; /* per entity gravity multiplier (1.0 is normal); use for lowgrav * artifact, flares */ float gravity; edict_t *goalentity; edict_t *movetarget; float yaw_speed; float ideal_yaw; float nextthink; void (*prethink)(edict_t *); void (*think)(edict_t *); void (*blocked)(edict_t *, edict_t *); // move to moveinfo? void (*touch)(edict_t *, edict_t *, cplane_t *, csurface_t *); void (*use)(edict_t *, edict_t *, edict_t *); void (*pain)(edict_t *, edict_t *, float, int); void (*die)(edict_t *, edict_t *, edict_t *, int, vec3_t); float touch_debounce_time; // are all these legit? do we need more/less of them? float pain_debounce_time; float damage_debounce_time; float fly_sound_debounce_time; // move to clientinfo float last_move_time; int health; int max_health; int gib_health; int deadflag; qboolean show_hostile; float powerarmor_time; char *map; // target_changelevel int viewheight; // height above origin where eyesight is determined int takedamage; int dmg; int radius_dmg; float dmg_radius; int sounds; // make this a spawntemp var? int count; edict_t *chain; edict_t *enemy; edict_t *oldenemy; edict_t *activator; edict_t *groundentity; int groundentity_linkcount; edict_t *teamchain; edict_t *teammaster; edict_t *mynoise; // can go in client only edict_t *mynoise2; int noise_index; int oise_index2; float volume; float attenuation; /* timing variables */ float wait; float delay; // before firing targets float random; float teleport_time; int watertype; int waterlevel; vec3_t move_origin; vec3_t move_angles; int light_level; // move this to clientinfo? int style; // also used as areaportal number gitem_t *item; // for bonus items /* common data blocks */ moveinfo_t moveinfo; monsterinfo_t monsterinfo; }; extern edict_t *g_edicts; #define CTF_VERSION "1.09b" #define CTF_TEAM1_SKIN "ctf_r" #define CTF_TEAM2_SKIN "ctf_b" enum{ STAT_CTF_TEAM1_PIC = 17, STAT_CTF_TEAM1_CAPS = 18, STAT_CTF_TEAM2_PIC = 19, STAT_CTF_TEAM2_CAPS = 20, STAT_CTF_FLAG_PIC = 21, STAT_CTF_JOINED_TEAM1_PIC = 22, STAT_CTF_JOINED_TEAM2_PIC = 23, STAT_CTF_TEAM1_HEADER = 24, STAT_CTF_TEAM2_HEADER = 25, STAT_CTF_TECH = 26, STAT_CTF_ID_VIEW = 27, STAT_CTF_MATCH = 28, CONFIG_CTF_MATCH = CS_MAXCLIENTS-1, DF_CTF_FORCEJOIN = 131072, DF_ARMOR_PROTECT = 262144, DF_CTF_NO_TECH = 524288, CTF_CAPTURE_BONUS = 15, // what you get for capture CTF_TEAM_BONUS = 10, // what your team gets for capture CTF_RECOVERY_BONUS = 1, // what you get for recovery CTF_FLAG_BONUS = 0, // what you get for picking up enemy flag CTF_FRAG_CARRIER_BONUS = 2, // what you get for fragging enemy flag carrier CTF_FLAG_RETURN_TIME = 40, // seconds until auto return /* bonus for fraggin someone who has recently hurt your flag carrier */ CTF_CARRIER_DANGER_PROTECT_BONUS = 2, /* bonus for fraggin someone while either you or your target are near * your flag carrier */ CTF_CARRIER_PROTECT_BONUS = 1, /* bonus for fraggin someone while either you or your target are near * your flag */ CTF_FLAG_DEFENSE_BONUS = 1, /* awarded for returning a flag that causes a capture to happen almost * immediately */ CTF_RETURN_FLAG_ASSIST_BONUS = 1, /* award for fragging a flag carrier if a capture happens almost * immediately */ CTF_FRAG_CARRIER_ASSIST_BONUS = 2, /* the radius around an object being defended where a target will be * worth extra frags */ CTF_TARGET_PROTECT_RADIUS = 400, /* the radius around an object being defended where an attacker will * get extra frags when making kills */ CTF_ATTACKER_PROTECT_RADIUS = 400, CTF_CARRIER_DANGER_PROTECT_TIMEOUT = 8, CTF_FRAG_CARRIER_ASSIST_TIMEOUT = 10, CTF_RETURN_FLAG_ASSIST_TIMEOUT = 10, /* number of seconds before dropped flag auto-returns */ CTF_AUTO_FLAG_RETURN_TIMEOUT = 30, CTF_TECH_TIMEOUT = 60, // seconds before techs spawn again CTF_GRAPPLE_SPEED = 650, // speed of grapple in flight CTF_GRAPPLE_PULL_SPEED = 650 // speed player is pulled at }; typedef enum ctfteam_t{ CTF_NOTEAM, CTF_TEAM1, CTF_TEAM2 }ctfteam_t; typedef enum ctfgrapplestate_t{ CTF_GRAPPLE_STATE_FLY, CTF_GRAPPLE_STATE_PULL, CTF_GRAPPLE_STATE_HANG }ctfgrapplestate_t; struct ghost_t{ char netname[16]; int number; /* stats */ int deaths; int kills; int caps; int basedef; int carrierdef; int code; // ghost code int team; // team int score; // frags at time of disconnect edict_t *ent; }; extern char *ctf_statusbar; #define WORLD (&g_edicts[0]) #define qrandom() ((rand () & 0x7fff) / ((float)0x7fff)) #define crandom() (2.0 * (qrandom() - 0.5)) #define ITEM_INDEX(x) ((x)-itemlist) #define FOFS(x) (uintptr)&(((edict_t *)0)->x) #define STOFS(x) (uintptr)&(((spawn_temp_t *)0)->x) #define LLOFS(x) (uintptr)&(((level_locals_t *)0)->x) #define CLOFS(x) (uintptr)&(((gclient_t *)0)->x) game_export_t* GetGameAPI(game_import_t *); qboolean CheckFlood(edict_t *); void Cmd_Help_f(edict_t *); void Cmd_Score_f(edict_t *); void PrecacheItem(gitem_t *); void InitItems(void); void SetItemNames(void); gitem_t* FindItem(char *); gitem_t* FindItemByClassname(char *); edict_t* Drop_Item(edict_t *, gitem_t *); void SetRespawn(edict_t *, float); void ChangeWeapon(edict_t *); void SpawnItem(edict_t *, gitem_t *); void Think_Weapon(edict_t *); int ArmorIndex(edict_t *); int PowerArmorType(edict_t *); gitem_t* GetItemByIndex(int); qboolean Add_Ammo(edict_t *, gitem_t *, int); void Touch_Item(edict_t *, edict_t *, cplane_t *, csurface_t *); qboolean KillBox(edict_t *); void G_ProjectSource(vec3_t, vec3_t, vec3_t, vec3_t, vec3_t); edict_t* G_Find(edict_t *, int, char *); edict_t* findradius(edict_t *, vec3_t, float); edict_t* G_PickTarget(char *); void G_UseTargets(edict_t *, edict_t *); void G_SetMovedir(vec3_t, vec3_t); void G_InitEdict(edict_t *); edict_t* G_Spawn(void); void G_FreeEdict(edict_t *); void G_TouchTriggers(edict_t *); void G_TouchSolids(edict_t *); char* G_CopyString(char *); float* tv(float, float, float); char* vtos(vec3_t); float vectoyaw(vec3_t); void vectoangles(vec3_t, vec3_t); qboolean OnSameTeam(edict_t *, edict_t *); qboolean CanDamage(edict_t *, edict_t *); qboolean CheckTeamDamage(edict_t *, edict_t *); void T_Damage(edict_t *, edict_t *, edict_t *, vec3_t, vec3_t, vec3_t, int, int, int, int); void T_RadiusDamage(edict_t *, edict_t *, float, edict_t *, float, int); void monster_fire_bullet(edict_t *, vec3_t, vec3_t, int, int, int, int, int); void monster_fire_shotgun(edict_t *, vec3_t, vec3_t, int, int, int, int, int, int); void monster_fire_blaster(edict_t *, vec3_t, vec3_t, int, int, int, int); void monster_fire_grenade(edict_t *, vec3_t, vec3_t, int, int, int); void monster_fire_rocket(edict_t *, vec3_t, vec3_t, int, int, int); void monster_fire_railgun(edict_t *, vec3_t, vec3_t, int, int, int); void monster_fire_bfg(edict_t *, vec3_t, vec3_t, int, int, int, float, int); void M_droptofloor(edict_t *); void monster_think(edict_t *); void walkmonster_start(edict_t *); void swimmonster_start(edict_t *); void flymonster_start(edict_t *); void AttackFinished(edict_t *, float); void monster_death_use(edict_t *); void M_CatagorizePosition(edict_t *); qboolean M_CheckAttack(edict_t *); void M_FlyCheck(edict_t *); void M_CheckGround(edict_t *); void ThrowHead(edict_t *, char *, int, int); void ThrowClientHead(edict_t *, int); void ThrowGib(edict_t *, char *, int, int); void BecomeExplosion1(edict_t *); void AI_SetSightClient(void); void ai_stand(edict_t *, float); void ai_move(edict_t *, float); void ai_walk(edict_t *, float); void ai_turn(edict_t *, float); void ai_run(edict_t *, float); void ai_charge(edict_t *, float); int range(edict_t *, edict_t *); void FoundTarget(edict_t *); qboolean infront(edict_t *, edict_t *); qboolean visible(edict_t *, edict_t *); qboolean FacingIdeal(edict_t *); void ThrowDebris(edict_t *, char *, float, vec3_t); qboolean fire_hit(edict_t *, vec3_t, int, int); void fire_bullet(edict_t *, vec3_t, vec3_t, int, int, int, int, int); void fire_shotgun(edict_t *, vec3_t, vec3_t, int, int, int, int, int, int); void fire_blaster(edict_t *, vec3_t, vec3_t, int, int, int, qboolean); void fire_grenade(edict_t *, vec3_t, vec3_t, int, int, float, float); void fire_grenade2(edict_t *, vec3_t, vec3_t, int, int, float, float, qboolean); void fire_rocket(edict_t *, vec3_t, vec3_t, int, int, float, int); void fire_rail(edict_t *, vec3_t, vec3_t, int, int); void fire_bfg(edict_t *, vec3_t, vec3_t, int, int, float); void PlayerTrail_Init(void); void PlayerTrail_Add(vec3_t); void PlayerTrail_New(vec3_t); edict_t* PlayerTrail_PickFirst(edict_t *); edict_t* PlayerTrail_PickNext(edict_t *); edict_t* PlayerTrail_LastSpot(void); void respawn(edict_t *); void BeginIntermission(edict_t *); void PutClientInServer(edict_t *); void InitClientPersistant(gclient_t *); void InitClientResp(gclient_t *); void InitBodyQue(void); void ClientBeginServerFrame(edict_t *); void player_pain(edict_t *, edict_t *, float, int); void player_die(edict_t *, edict_t *, edict_t *, int, vec3_t); void ServerCommand(void); void ClientEndServerFrame(edict_t *); void MoveClientToIntermission(edict_t *); void G_SetStats(edict_t *); void ValidateSelectedItem(edict_t *); void DeathmatchScoreboardMessage(edict_t *, edict_t *); void PlayerNoise(edict_t *, vec3_t, int); void P_ProjectSource(gclient_t *, vec3_t, vec3_t, vec3_t, vec3_t, vec3_t); void Weapon_Generic(edict_t *, int, int, int, int, int *, int *, void(*)(edict_t *)); qboolean M_CheckBottom(edict_t *); qboolean M_walkmove(edict_t *, float, float); void M_MoveToGoal(edict_t *, float); void M_ChangeYaw(edict_t *); void G_RunEntity(edict_t *); void SaveClientData(void); void FetchClientEntData(edict_t *); void EndDMLevel(void); pmenuhnd_t* PMenu_Open(edict_t *, pmenu_t *, int, int, void *); void PMenu_Close(edict_t *); void PMenu_UpdateEntry(pmenu_t *, char *, int, SelectFunc_t); void PMenu_Do_Update(edict_t *); void PMenu_Update(edict_t *); void PMenu_Next(edict_t *); void PMenu_Prev(edict_t *); void PMenu_Select(edict_t *); void CTFInit(void); void CTFSpawn(void); void SP_info_player_team1(edict_t *); void SP_info_player_team2(edict_t *); char *CTFTeamName(int); char *CTFOtherTeamName(int); void CTFAssignSkin(edict_t *, char *); void CTFAssignTeam(gclient_t *); edict_t* SelectCTFSpawnPoint(edict_t *); qboolean CTFPickup_Flag(edict_t *, edict_t *); void CTFDrop_Flag(edict_t *, gitem_t *); void CTFEffects(edict_t *); void CTFCalcScores(void); void SetCTFStats(edict_t *); void CTFDeadDropFlag(edict_t *); void CTFScoreboardMessage(edict_t *, edict_t *); void CTFTeam_f(edict_t *); void CTFID_f(edict_t *); void CTFSay_Team(edict_t *, char *); void CTFFlagSetup(edict_t *); void CTFResetFlag(int); void CTFFragBonuses(edict_t *, edict_t *, edict_t *); void CTFCheckHurtCarrier(edict_t *, edict_t *); void CTFWeapon_Grapple(edict_t *); void CTFPlayerResetGrapple(edict_t *); void CTFGrapplePull(edict_t *); void CTFResetGrapple(edict_t *); gitem_t* CTFWhat_Tech(edict_t *); qboolean CTFPickup_Tech(edict_t *, edict_t *); void CTFDrop_Tech(edict_t *, gitem_t *); void CTFDeadDropTech(edict_t *); void CTFSetupTechSpawn(void); int CTFApplyResistance(edict_t *, int); int CTFApplyStrength(edict_t *, int); qboolean CTFApplyStrengthSound(edict_t *); qboolean CTFApplyHaste(edict_t *); void CTFApplyHasteSound(edict_t *); void CTFApplyRegeneration(edict_t *); qboolean CTFHasRegeneration(edict_t *); void CTFRespawnTech(edict_t *); void CTFResetTech(void); void CTFOpenJoinMenu(edict_t *); qboolean CTFStartClient(edict_t *); void CTFVoteYes(edict_t *); void CTFVoteNo(edict_t *); void CTFReady(edict_t *); void CTFNotReady(edict_t *); qboolean CTFNextMap(void); qboolean CTFMatchSetup(void); qboolean CTFMatchOn(void); void CTFGhost(edict_t *); void CTFAdmin(edict_t *); qboolean CTFInMatch(void); void CTFStats(edict_t *); void CTFWarp(edict_t *); void CTFBoot(edict_t *); void CTFPlayerList(edict_t *); qboolean CTFCheckRules(void); void SP_misc_ctf_banner(edict_t *); void SP_misc_ctf_small_banner(edict_t *); void UpdateChaseCam(edict_t *); void ChaseNext(edict_t *); void ChasePrev(edict_t *); void CTFObserver(edict_t *); void SP_trigger_teleport(edict_t *); void SP_info_teleport_destination(edict_t *); void SP_item_health(edict_t *); void SP_item_health_small(edict_t *); void SP_item_health_large(edict_t *); void SP_item_health_mega(edict_t *); void SP_info_player_start(edict_t *); void SP_info_player_deathmatch(edict_t *); void SP_info_player_coop(edict_t *); void SP_info_player_intermission(edict_t *); void SP_func_plat(edict_t *); void SP_func_rotating(edict_t *); void SP_func_button(edict_t *); void SP_func_door(edict_t *); void SP_func_door_secret(edict_t *); void SP_func_door_rotating(edict_t *); void SP_func_water(edict_t *); void SP_func_train(edict_t *); void SP_func_conveyor(edict_t *); void SP_func_wall(edict_t *); void SP_func_object(edict_t *); void SP_func_explosive(edict_t *); void SP_func_timer(edict_t *); void SP_func_areaportal(edict_t *); void SP_func_clock(edict_t *); void SP_func_killbox(edict_t *); void SP_trigger_always(edict_t *); void SP_trigger_once(edict_t *); void SP_trigger_multiple(edict_t *); void SP_trigger_relay(edict_t *); void SP_trigger_push(edict_t *); void SP_trigger_hurt(edict_t *); void SP_trigger_key(edict_t *); void SP_trigger_counter(edict_t *); void SP_trigger_elevator(edict_t *); void SP_trigger_gravity(edict_t *); void SP_trigger_monsterjump(edict_t *); void SP_target_temp_entity(edict_t *); void SP_target_speaker(edict_t *); void SP_target_explosion(edict_t *); void SP_target_changelevel(edict_t *); void SP_target_secret(edict_t *); void SP_target_goal(edict_t *); void SP_target_splash(edict_t *); void SP_target_spawner(edict_t *); void SP_target_blaster(edict_t *); void SP_target_crosslevel_trigger(edict_t *); void SP_target_crosslevel_target(edict_t *); void SP_target_laser(edict_t *); void SP_target_help(edict_t *); void SP_target_actor(edict_t *); void SP_target_lightramp(edict_t *); void SP_target_earthquake(edict_t *); void SP_target_character(edict_t *); void SP_target_string(edict_t *); void SP_worldspawn(edict_t *); void SP_viewthing(edict_t *); void SP_light(edict_t *); void SP_light_mine1(edict_t *); void SP_light_mine2(edict_t *); void SP_info_null(edict_t *); void SP_info_notnull(edict_t *); void SP_path_corner(edict_t *); void SP_point_combat(edict_t *); void SP_misc_explobox(edict_t *); void SP_misc_banner(edict_t *); void SP_misc_satellite_dish(edict_t *); void SP_misc_actor(edict_t *); void SP_misc_gib_arm(edict_t *); void SP_misc_gib_leg(edict_t *); void SP_misc_gib_head(edict_t *); void SP_misc_insane(edict_t *); void SP_misc_deadsoldier(edict_t *); void SP_misc_viper(edict_t *); void SP_misc_viper_bomb(edict_t *); void SP_misc_bigviper(edict_t *); void SP_misc_strogg_ship(edict_t *); void SP_misc_teleporter(edict_t *); void SP_misc_teleporter_dest(edict_t *); void SP_misc_blackhole(edict_t *); void SP_misc_eastertank(edict_t *); void SP_misc_easterchick(edict_t *); void SP_misc_easterchick2(edict_t *); void SP_monster_berserk(edict_t *); void SP_monster_gladiator(edict_t *); void SP_monster_gunner(edict_t *); void SP_monster_infantry(edict_t *); void SP_monster_soldier_light(edict_t *); void SP_monster_soldier(edict_t *); void SP_monster_soldier_ss(edict_t *); void SP_monster_tank(edict_t *); void SP_monster_medic(edict_t *); void SP_monster_flipper(edict_t *); void SP_monster_chick(edict_t *); void SP_monster_parasite(edict_t *); void SP_monster_flyer(edict_t *); void SP_monster_brain(edict_t *); void SP_monster_floater(edict_t *); void SP_monster_hover(edict_t *); void SP_monster_mutant(edict_t *); void SP_monster_supertank(edict_t *); void SP_monster_boss2(edict_t *); void SP_monster_jorg(edict_t *); void SP_monster_boss3_stand(edict_t *); void SP_monster_commander_body(edict_t *); void SP_turret_breach(edict_t *); void SP_turret_base(edict_t *); void SP_turret_driver(edict_t *);