diff --git a/source/Makefile b/source/Makefile index 1865b179c..ed9b3eda9 100644 --- a/source/Makefile +++ b/source/Makefile @@ -112,7 +112,7 @@ endif ifeq ($(USE_AQTION),TRUE) -CFLAGS += -DUSE_AQTION -DAQTION_EXTENSION +CFLAGS += -DUSE_AQTION -DAQTION_EXTENSION -DUSE_AQ_CURL ifneq (,$(findstring WIN32,$(TNG_BUILD_FOR))$(findstring WIN64,$(TNG_BUILD_FOR))) CFLAGS += -I../q2pro-mgw-sdk/inc -DCURL_STATICLIB @@ -140,6 +140,10 @@ ifdef NO_BOTS CFLAGS+=-DNO_BOTS endif +ifndef NO_PROTOCOL_EXTENSIONS +CFLAGS+=-DUSE_PROTOCOL_EXTENSIONS +endif + ## Use this to build on older glibc/gcc for older dedicated servers ifdef C99COMPAT CFLAGS+=-std=c99 diff --git a/source/a_cmds.c b/source/a_cmds.c index ae1c150ba..913c0c05b 100644 --- a/source/a_cmds.c +++ b/source/a_cmds.c @@ -918,7 +918,7 @@ void SetIDView(edict_t * ent) if (ent->client->chase_mode) { if (ent->client->chase_target && ent->client->chase_target->inuse) { ent->client->ps.stats[STAT_ID_VIEW] = - CS_PLAYERSKINS + (ent->client->chase_target - g_edicts - 1); + game.csr.playerskins + (ent->client->chase_target - g_edicts - 1); } return; } @@ -934,7 +934,7 @@ void SetIDView(edict_t * ent) tr = gi.trace(ent->s.origin, NULL, NULL, forward, ent, MASK_SOLID); POSTTRACE(); if (tr.fraction < 1 && tr.ent && tr.ent->client) { - ent->client->ps.stats[STAT_ID_VIEW] = CS_PLAYERSKINS + (ent - g_edicts - 1); + ent->client->ps.stats[STAT_ID_VIEW] = game.csr.playerskins + (ent - g_edicts - 1); return; } @@ -958,7 +958,7 @@ void SetIDView(edict_t * ent) } } if (best != NULL && bd > 0.90) { - ent->client->ps.stats[STAT_ID_VIEW] = CS_PLAYERSKINS + (best - g_edicts - 1); + ent->client->ps.stats[STAT_ID_VIEW] = game.csr.playerskins + (best - g_edicts - 1); } } diff --git a/source/a_team.c b/source/a_team.c index e9271fcc0..4d7e05c02 100644 --- a/source/a_team.c +++ b/source/a_team.c @@ -1311,7 +1311,7 @@ void AssignSkin (edict_t * ent, const char *s, qboolean nickChanged) } } - gi.configstring(CS_PLAYERSKINS + playernum, skin); + gi.configstring(game.csr.playerskins + playernum, skin); } /* @@ -1516,7 +1516,7 @@ void JoinTeam (edict_t * ent, int desired_team, int skip_menuclose) AddToTransparentList (ent); } - #if USE_AQTION + #ifdef USE_AQTION if (in_warmup && warmup_bots->value) { PutClientInServer (ent); } @@ -2313,7 +2313,7 @@ void RunWarmup () gi.centerprintf(ent, "WARMUP"); } } - #if USE_AQTION + #ifdef USE_AQTION if (warmup_bots->value){ gi.cvar_forceset("am", "1"); gi.cvar_forceset("am_botcount", warmup_bots->string); @@ -2799,7 +2799,7 @@ int CheckTeamRules (void) gi.sound (&g_edicts[0], CHAN_VOICE | CHAN_NO_PHS_ADD, gi.soundindex ("world/10_0.wav"), 1.0, ATTN_NONE, 0.0); - #if USE_AQTION + #ifdef USE_AQTION // Cleanup and remove all bots, it's go time! if (warmup_bots->value){ gi.cvar_forceset("am", "0"); diff --git a/source/g_local.h b/source/g_local.h index 921d61af9..3160406be 100644 --- a/source/g_local.h +++ b/source/g_local.h @@ -298,13 +298,22 @@ #define getEnt(entnum) (edict_t *)((char *)globals.edicts + (globals.edict_size * entnum)) //AQ:TNG Slicer - This was missing #define GAMEVERSION "action" // the "gameversion" client command will print this plus compile date +// features this game supports + +// R1Q2 and Q2PRO specific +#define GMF_CLIENTNUM BIT(0) // game sets clientNum gclient_s field +#define GMF_PROPERINUSE BIT(1) // game maintains edict_s inuse field properly +#define GMF_MVDSPEC BIT(2) // game is dummy MVD client aware +#define GMF_WANT_ALL_DISCONNECTS BIT(3) // game wants ClientDisconnect() for non-spawned clients + +// Q2PRO specific +#define GMF_ENHANCED_SAVEGAMES BIT(10) // game supports safe/portable savegames +#define GMF_VARIABLE_FPS BIT(11) // game supports variable server FPS +#define GMF_EXTRA_USERINFO BIT(12) // game wants extra userinfo after normal userinfo +#define GMF_IPV6_ADDRESS_AWARE BIT(13) // game supports IPv6 addresses +#define GMF_ALLOW_INDEX_OVERFLOW BIT(14) // game wants PF_FindIndex() to return 0 on overflow +#define GMF_PROTOCOL_EXTENSIONS BIT(15) // game supports protocol extensions -#define GMF_CLIENTNUM 0x00000001 -#define GMF_PROPERINUSE 0x00000002 -#define GMF_MVDSPEC 0x00000004 -#define GMF_WANT_ALL_DISCONNECTS 0x00000008 -#define GMF_VARIABLE_FPS 0x00000800 -#define GMF_EXTRA_USERINFO 0x00001000 #ifndef NO_FPS #define G_GMF_VARIABLE_FPS GMF_VARIABLE_FPS @@ -312,7 +321,13 @@ #define G_GMF_VARIABLE_FPS 0 #endif -#define G_FEATURES (GMF_CLIENTNUM | GMF_PROPERINUSE | GMF_MVDSPEC | GMF_WANT_ALL_DISCONNECTS | G_GMF_VARIABLE_FPS) +#ifdef USE_PROTOCOL_EXTENSIONS +#define G_GMF_PROTOCOL_EXTENSIONS GMF_PROTOCOL_EXTENSIONS +#else +#define G_GMF_PROTOCOL_EXTENSIONS 0 +#endif + +#define G_FEATURES (GMF_CLIENTNUM | GMF_PROPERINUSE | GMF_MVDSPEC | GMF_WANT_ALL_DISCONNECTS | G_GMF_VARIABLE_FPS | G_GMF_PROTOCOL_EXTENSIONS) // protocol bytes that can be directly added to messages #define svc_muzzleflash 1 @@ -728,7 +743,6 @@ typedef struct gitem_s } gitem_t; - // // this structure is left intact through an entire game // it should be initialized at dll load time, and read/written to @@ -756,7 +770,10 @@ typedef struct // items int num_items; - + + //q2pro protocol extensions + cs_remap_t csr; + // stats char matchid[MAX_QPATH]; int gamemode; @@ -1163,6 +1180,7 @@ extern cvar_t *maptime; extern cvar_t *capturelimit; extern cvar_t *password; extern cvar_t *g_select_empty; +extern cvar_t *g_protocol_extensions; extern cvar_t *dedicated; extern cvar_t *steamid; @@ -1629,7 +1647,7 @@ void ProduceShotgunDamageReport(edict_t*); //tng_stats.c void StatBotCheck(void); -#if USE_AQTION +#ifdef USE_AQTION void LogKill(edict_t *self, edict_t *inflictor, edict_t *attacker); void LogWorldKill(edict_t *self); void LogCapture(edict_t *capturer); @@ -1731,7 +1749,7 @@ typedef struct ignorelist_t ignorelist; gitem_t *chosenItem2; // Support for item kit mode - #if USE_AQTION + #ifdef USE_AQTION char steamid[24]; char discordid[24]; #endif @@ -2070,6 +2088,63 @@ struct gclient_s unsigned int dimension_observe; }; +#ifdef USE_PROTOCOL_EXTENSIONS + + +#define ENTITYNUM_BITS 13 +#define ENTITYNUM_MASK (BIT(ENTITYNUM_BITS) - 1) + +#define GUNINDEX_BITS 13 // upper 3 bits are skinnum +#define GUNINDEX_MASK (BIT(GUNINDEX_BITS) - 1) + +typedef struct { + int morefx; + float alpha; + float scale; + float loop_volume; + float loop_attenuation; +} entity_state_extension_t; + + +typedef union { + struct { + entity_state_t state; + entity_state_extension_t state_extension; + }; + struct { + entity_state_t s; + entity_state_extension_t x; + }; +} centity_state_t; + +typedef struct centity_s { + centity_state_t current; + centity_state_t prev; // will always be valid, but might just be a copy of current + + vec3_t mins, maxs; + float radius; // from mid point + + int serverframe; // if not current, this ent isn't in the frame + + int trailcount; // for diminishing grenade trails + vec3_t lerp_origin; // for trails (variable hz) + +#ifdef USE_FPS + int prev_frame; + int anim_start; + + int event_frame; +#endif + + int fly_stoptime; + + float flashlightfrac; +} centity_t; + +extern centity_t cl_entities[MAX_EDICTS]; + +#endif + struct edict_s { @@ -2099,7 +2174,7 @@ struct edict_s int clipmask; edict_t *owner; - + entity_state_extension_t x; // DO NOT MODIFY ANYTHING ABOVE THIS, THE SERVER // EXPECTS THE FIELDS IN THAT ORDER! @@ -2323,7 +2398,7 @@ typedef struct gitem_t *weapon; gitem_t *item; // Extended stats - #if USE_AQTION + #ifdef USE_AQTION char steamid[24]; char discordid[24]; #endif @@ -2528,3 +2603,18 @@ extern Message *timedMessages; void addTimedMessage(int teamNum, edict_t *ent, int seconds, char *msg); void FireTimedMessages(); + +/* +===================================================================== + + CONFIG STRING REMAPPING + +===================================================================== +*/ + +#ifdef USE_PROTOCOL_EXTENSIONS + +extern const cs_remap_t cs_remap_old; +extern const cs_remap_t cs_remap_new; + +#endif diff --git a/source/g_main.c b/source/g_main.c index aa9f036cd..af72b2f36 100644 --- a/source/g_main.c +++ b/source/g_main.c @@ -347,6 +347,7 @@ cvar_t *password; cvar_t *maxclients; cvar_t *maxentities; cvar_t *g_select_empty; +cvar_t *g_protocol_extensions; cvar_t *dedicated; cvar_t *steamid; cvar_t *filterban; @@ -1115,7 +1116,7 @@ void CycleLights (void) } temp[0] = brightness[day_cycle_at]; temp[1] = 0; - gi.configstring (CS_LIGHTS + 0, temp); + gi.configstring (game.csr.lights + 0, temp); day_next_cycle = level.time + day_cycle->value; } } diff --git a/source/g_save.c b/source/g_save.c index 6914217ad..1c923d85b 100644 --- a/source/g_save.c +++ b/source/g_save.c @@ -322,7 +322,7 @@ field_t fields[] = { void InitGame( void ) { cvar_t *cv; - + int features = G_FEATURES; InitCommandList(); IRC_init(); @@ -530,6 +530,7 @@ void InitGame( void ) CGF_SFX_InstallGlassSupport(); // william for CGF (glass fx) g_select_empty = gi.cvar( "g_select_empty", "0", CVAR_ARCHIVE ); + g_protocol_extensions = gi.cvar("g_protocol_extensions", "0", CVAR_LATCH); run_pitch = gi.cvar( "run_pitch", "0.002", 0 ); run_roll = gi.cvar( "run_roll", "0.005", 0 ); @@ -540,6 +541,24 @@ void InitGame( void ) // flood control flood_threshold = gi.cvar( "flood_threshold", "4", 0 ); + gi.dprintf( "Reading extra server features\n" ); + cv = gi.cvar( "sv_features", NULL, 0 ); + if (cv) { + game.serverfeatures = (int)cv->value; + + if (game.serverfeatures & GMF_CLIENTNUM) { + gi.dprintf( "...server supports GMF_CLIENTNUM\n" ); + } + + if (game.serverfeatures & GMF_PROTOCOL_EXTENSIONS && (int)g_protocol_extensions->value) { + features |= GMF_PROTOCOL_EXTENSIONS; + gi.dprintf( "...server supports GMF_PROTOCOL_EXTENSIONS\n" ); + game.csr = cs_remap_new; + } else { + game.csr = cs_remap_old; + } + } + jump = gi.cvar ("jump", "0", /*CVAR_SERVERINFO|*/ CVAR_LATCH); // jumping mod -- removed from serverinfo 2022 warmup = gi.cvar( "warmup", "0", CVAR_LATCH ); @@ -649,7 +668,8 @@ void InitGame( void ) // initialize all entities for this game game.maxentities = maxentities->value; - clamp(game.maxentities, globals.num_edicts, MAX_EDICTS); + //clamp(game.maxentities, globals.num_edicts, MAX_EDICTS); + clamp(game.maxentities, (int)maxclients->value + 1, game.csr.max_edicts); g_edicts = gi.TagMalloc( game.maxentities * sizeof(g_edicts[0]), TAG_GAME ); globals.edicts = g_edicts; globals.max_edicts = game.maxentities; @@ -659,16 +679,6 @@ void InitGame( void ) //PG BUND - must be at end of gameinit: vInitGame(); - gi.dprintf( "Reading extra server features\n" ); - cv = gi.cvar( "sv_features", NULL, 0 ); - if (cv) { - game.serverfeatures = (int)cv->value; - - if (game.serverfeatures & GMF_CLIENTNUM) { - gi.dprintf( "...server supports GMF_CLIENTNUM\n" ); - } - } - // setup framerate parameters game.framerate = BASE_FRAMERATE; @@ -712,7 +722,7 @@ void InitGame( void ) } #endif - gi.cvar_forceset("g_features", va("%d", G_FEATURES)); + gi.cvar_forceset("g_features", va("%d", features)); gi.cvar_forceset("g_view_predict", "1"); gi.cvar_forceset("g_view_high", va("%d", STANDING_VIEWHEIGHT)); gi.cvar_forceset("g_view_low", va("%d", CROUCHING_VIEWHEIGHT)); diff --git a/source/g_spawn.c b/source/g_spawn.c index 41610ff5c..258e3e139 100644 --- a/source/g_spawn.c +++ b/source/g_spawn.c @@ -817,6 +817,43 @@ void G_LoadLocations( void ) gi.dprintf( "Found %d locations.\n", ml_count ); } +static char *const lightstyles[] = { + // 0 normal + "m", + + // 1 FLICKER (first variety) + "mmnmmommommnonmmonqnmmo", + + // 2 SLOW STRONG PULSE + "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba", + + // 3 CANDLE (first variety) + "mmmmmaaaaammmmmaaaaaabcdefgabcdefg", + + // 4 FAST STROBE + "mamamamamama", + + // 5 GENTLE PULSE 1 + "jklmnopqrstuvwxyzyxwvutsrqponmlkj", + + // 6 FLICKER (second variety) + "nmonqnmomnmomomno", + + // 7 CANDLE (second variety) + "mmmaaaabcdefgmmmmaaaammmaamm", + + // 8 CANDLE (third variety) + "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa", + + // 9 SLOW STROBE (fourth variety) + "aaaaaaaazzzzzzzz", + + // 10 FLUORESCENT FLICKER + "mmamammmmammamamaaamammma", + + // 11 SLOW PULSE NOT FADE TO BLACK + "abcdefghijklmnopqrrqponmlkjihgfedcba", +}; /* These are distinct game modes; you cannot have a teamdm tourney mode, for example @@ -1652,7 +1689,7 @@ void SP_worldspawn (edict_t * ent) gi.configstring(CS_SKYROTATE, va("%f", st.skyrotate)); gi.configstring(CS_SKYAXIS, va("%f %f %f", st.skyaxis[0], st.skyaxis[1], st.skyaxis[2])); gi.configstring(CS_CDTRACK, va("%i", ent->sounds)); - gi.configstring(CS_MAXCLIENTS, va("%i", game.maxclients)); + gi.configstring(game.csr.maxclients, va("%i", game.maxclients)); G_SetupStatusbar(); gi.configstring(CS_STATUSBAR, level.statusbar); @@ -1877,25 +1914,15 @@ void SP_worldspawn (edict_t * ent) 3 - using the day_cycle to change the lights every xx seconds as defined by day_cycle */ if (darkmatch->value == 1) - gi.configstring (CS_LIGHTS + 0, "a"); // Pitch Black + gi.configstring (game.csr.lights + 0, "a"); // Pitch Black else if (darkmatch->value == 2) - gi.configstring (CS_LIGHTS + 0, "b"); // Dusk + gi.configstring (game.csr.lights + 0, "b"); // Dusk else - gi.configstring (CS_LIGHTS + 0, "m"); // 0 normal - - gi.configstring(CS_LIGHTS + 1, "mmnmmommommnonmmonqnmmo"); // 1 FLICKER (first variety) - gi.configstring(CS_LIGHTS + 2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba"); // 2 SLOW STRONG PULSE - gi.configstring(CS_LIGHTS + 3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg"); // 3 CANDLE (first variety) - gi.configstring(CS_LIGHTS + 4, "mamamamamama"); // 4 FAST STROBE - gi.configstring(CS_LIGHTS + 5, "jklmnopqrstuvwxyzyxwvutsrqponmlkj"); // 5 GENTLE PULSE 1 - gi.configstring(CS_LIGHTS + 6, "nmonqnmomnmomomno"); // 6 FLICKER (second variety) - gi.configstring(CS_LIGHTS + 7, "mmmaaaabcdefgmmmmaaaammmaamm"); // 7 CANDLE (second variety) - gi.configstring(CS_LIGHTS + 8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa"); // 8 CANDLE (third variety) - gi.configstring(CS_LIGHTS + 9, "aaaaaaaazzzzzzzz"); // 9 SLOW STROBE (fourth variety) - gi.configstring(CS_LIGHTS + 10, "mmamammmmammamamaaamammma"); // 10 FLUORESCENT FLICKER - gi.configstring(CS_LIGHTS + 11, "abcdefghijklmnopqrrqponmlkjihgfedcba"); // 11 SLOW PULSE NOT FADE TO BLACK - // styles 32-62 are assigned by the light program for switchable lights - gi.configstring(CS_LIGHTS + 63, "a"); // 63 testing + gi.configstring (game.csr.lights + 0, "m"); // 0 normal + + for (int i = 0; i < q_countof(lightstyles); i++) + gi.configstring(game.csr.lights + i, lightstyles[i]); + gi.configstring(game.csr.lights + 63, "a"); } int LoadFlagsFromFile (const char *mapname) diff --git a/source/game.h b/source/game.h index ee304a804..b760baa48 100644 --- a/source/game.h +++ b/source/game.h @@ -21,9 +21,21 @@ // edict->svflags -#define SVF_NOCLIENT 0x00000001 // don't send entity to clients, even if it has effects -#define SVF_DEADMONSTER 0x00000002 // treat as CONTENTS_DEADMONSTER for collision -#define SVF_MONSTER 0x00000004 // treat as CONTENTS_MONSTER for collision +#define SVF_NOCLIENT BIT(0) // don't send entity to clients, even if it has effects +#define SVF_DEADMONSTER BIT(1) // treat as CONTENTS_DEADMONSTER for collision +#define SVF_MONSTER BIT(2) // treat as CONTENTS_MONSTER for collision + +#ifdef USE_PROTOCOL_EXTENSIONS +#define SVF_PLAYER BIT(3) +#define SVF_BOT BIT(4) +#define SVF_NOBOTS BIT(5) +#define SVF_RESPAWNING BIT(6) +#define SVF_PROJECTILE BIT(7) +#define SVF_INSTANCED BIT(8) +#define SVF_DOOR BIT(9) +#define SVF_NOCULL BIT(10) +#define SVF_HULL BIT(11) +#endif // edict->solid values diff --git a/source/p_client.c b/source/p_client.c index af22273ad..10062d50e 100644 --- a/source/p_client.c +++ b/source/p_client.c @@ -3252,7 +3252,7 @@ qboolean ClientConnect(edict_t * ent, char *userinfo) Q_strncpyz(ent->client->pers.ip, ipaddr_buf, sizeof(ent->client->pers.ip)); Q_strncpyz(ent->client->pers.userinfo, userinfo, sizeof(ent->client->pers.userinfo)); - #if USE_AQTION + #ifdef USE_AQTION value = Info_ValueForKey(userinfo, "steamid"); if (*value) Q_strncpyz(ent->client->pers.steamid, value, sizeof(ent->client->pers.steamid)); @@ -3422,7 +3422,7 @@ void CreateGhost(edict_t * ent) strcpy(ghost->ip, ent->client->pers.ip); strcpy(ghost->netname, ent->client->pers.netname); - #if USE_AQTION + #ifdef USE_AQTION strcpy(ghost->steamid, ent->client->pers.steamid); strcpy(ghost->discordid, ent->client->pers.discordid); #endif diff --git a/source/q_shared.c b/source/q_shared.c index b6ec86438..b01eaae8a 100644 --- a/source/q_shared.c +++ b/source/q_shared.c @@ -1263,3 +1263,53 @@ void Info_SetValueForKey (char *s, const char *key, const char *value) } //==================================================================== + +#ifdef USE_PROTOCOL_EXTENSIONS + +const cs_remap_t cs_remap_old = { + .extended = false, + + .max_edicts = MAX_EDICTS_OLD, + .max_models = MAX_MODELS_OLD, + .max_sounds = MAX_SOUNDS_OLD, + .max_images = MAX_IMAGES_OLD, + + .airaccel = CS_AIRACCEL_OLD, + .maxclients = CS_MAXCLIENTS_OLD, + .mapchecksum = CS_MAPCHECKSUM_OLD, + + .models = CS_MODELS_OLD, + .sounds = CS_SOUNDS_OLD, + .images = CS_IMAGES_OLD, + .lights = CS_LIGHTS_OLD, + .items = CS_ITEMS_OLD, + .playerskins = CS_PLAYERSKINS_OLD, + .general = CS_GENERAL_OLD, + + .end = MAX_CONFIGSTRINGS_OLD +}; + +const cs_remap_t cs_remap_new = { + .extended = true, + + .max_edicts = MAX_EDICTS, + .max_models = MAX_MODELS, + .max_sounds = MAX_SOUNDS, + .max_images = MAX_IMAGES, + + .airaccel = CS_AIRACCEL, + .maxclients = CS_MAXCLIENTS, + .mapchecksum = CS_MAPCHECKSUM, + + .models = CS_MODELS, + .sounds = CS_SOUNDS, + .images = CS_IMAGES, + .lights = CS_LIGHTS, + .items = CS_ITEMS, + .playerskins = CS_PLAYERSKINS, + .general = CS_GENERAL, + + .end = MAX_CONFIGSTRINGS +}; + +#endif \ No newline at end of file diff --git a/source/q_shared.h b/source/q_shared.h index b0b9e835a..398550ee2 100644 --- a/source/q_shared.h +++ b/source/q_shared.h @@ -58,6 +58,10 @@ //FIREBLADE #include //FIREBLADE +//Protocol extension support +#include + +#define q_countof(a) (sizeof(a) / sizeof(a[0])) // legacy ABI support for Windows #if defined(__GNUC__) && defined(WIN32) && ! defined(WIN64) @@ -187,14 +191,26 @@ typedef enum { qfalse = 0, qtrue } qboolean; // // per-level limits // -#define MAX_CLIENTS 256 // absolute limit -#define MAX_EDICTS 1024 // must change protocol to increase more -#define MAX_LIGHTSTYLES 256 -#define MAX_MODELS 256 // these are sent over the net as bytes -#define MAX_SOUNDS 256 // so they cannot be blindly increased -#define MAX_IMAGES 256 -#define MAX_ITEMS 256 -#define MAX_GENERAL (MAX_CLIENTS*2) // general config strings (from 3.20 -FB) +#define MAX_CLIENTS 256 // absolute limit +#define MAX_EDICTS_OLD 1024 // must change protocol to increase more +#define MAX_MODELS_OLD 256 // these are sent over the net as bytes +#define MAX_SOUNDS_OLD 256 // so they cannot be blindly increased +#define MAX_IMAGES_OLD 256 +#define MAX_LIGHTSTYLES 256 +#define MAX_ITEMS 256 +#define MAX_GENERAL (MAX_CLIENTS * 2) // general config strings + +#ifdef USE_PROTOCOL_EXTENSIONS +#define MAX_EDICTS 8192 // sent as ENTITYNUM_BITS, can't be increased +#define MAX_MODELS 8192 // half is reserved for inline BSP models +#define MAX_SOUNDS 2048 +#define MAX_IMAGES 2048 +#else +#define MAX_EDICTS MAX_EDICTS_OLD +#define MAX_MODELS MAX_MODELS_OLD +#define MAX_SOUNDS MAX_SOUNDS_OLD +#define MAX_IMAGES MAX_IMAGES_OLD +#endif // game print flags @@ -257,6 +273,7 @@ typedef int fixed16_t; #define DEG2RAD( a ) (a * M_PI_DIV_180) #define RAD2DEG( a ) (a * M_180_DIV_PI) +#define BIT(n) (1U << (n)) #ifndef max # define max(a,b) ((a) > (b) ? (a) : (b)) @@ -798,45 +815,66 @@ pmove_t; #define EF_GREEN_LIGHT 0x04000040 +// entity_state_t->morefx flags +//KEX +#define EFX_DUALFIRE BIT(0) +#define EFX_HOLOGRAM BIT(1) +#define EFX_FLASHLIGHT BIT(2) +#define EFX_BARREL_EXPLODING BIT(3) +#define EFX_TELEPORTER2 BIT(4) +#define EFX_GRENADE_LIGHT BIT(5) +//KEX + // entity_state_t->renderfx flags -#define RF_MINLIGHT 1 // allways have some light (viewmodel) -#define RF_VIEWERMODEL 2 // don't draw through eyes, only mirrors -#define RF_WEAPONMODEL 4 // only draw through eyes -#define RF_FULLBRIGHT 8 // allways draw full intensity -#define RF_DEPTHHACK 16 // for view weapon Z crunching -#define RF_TRANSLUCENT 32 -#define RF_FRAMELERP 64 -#define RF_BEAM 128 -#define RF_CUSTOMSKIN 256 // skin is an index in image_precache -#define RF_GLOW 512 // pulse lighting for bonus items -#define RF_SHELL_RED 1024 -#define RF_SHELL_GREEN 2048 -#define RF_SHELL_BLUE 4096 - -//ROGUE (FROM 3.20) -#define RF_IR_VISIBLE 0x00008000 // 32768 -#define RF_SHELL_DOUBLE 0x00010000 // 65536 -#define RF_SHELL_HALF_DAM 0x00020000 -#define RF_USE_DISGUISE 0x00040000 +#define RF_MINLIGHT BIT(0) // allways have some light (viewmodel) +#define RF_VIEWERMODEL BIT(1) // don't draw through eyes, only mirrors +#define RF_WEAPONMODEL BIT(2) // only draw through eyes +#define RF_FULLBRIGHT BIT(3) // allways draw full intensity +#define RF_DEPTHHACK BIT(4) // for view weapon Z crunching +#define RF_TRANSLUCENT BIT(5) +#define RF_FRAMELERP BIT(6) +#define RF_BEAM BIT(7) +#define RF_CUSTOMSKIN BIT(8) // skin is an index in image_precache +#define RF_GLOW BIT(9) // pulse lighting for bonus items +#define RF_SHELL_RED BIT(10) +#define RF_SHELL_GREEN BIT(11) +#define RF_SHELL_BLUE BIT(12) +#define RF_NOSHADOW BIT(13) // used by YQ2 +#define RF_CASTSHADOW BIT(14) // used by KEX + //ROGUE +#define RF_IR_VISIBLE BIT(15) +#define RF_SHELL_DOUBLE BIT(16) +#define RF_SHELL_HALF_DAM BIT(17) +#define RF_USE_DISGUISE BIT(18) +//ROGUE + +//KEX +#define RF_SHELL_LITE_GREEN BIT(19) +#define RF_CUSTOM_LIGHT BIT(20) +#define RF_FLARE BIT(21) +#define RF_OLD_FRAME_LERP BIT(22) +#define RF_DOT_SHADOW BIT(23) +#define RF_LOW_PRIORITY BIT(24) +#define RF_NO_LOD BIT(25) +#define RF_STAIR_STEP BIT(26) + +#define RF_NO_STEREO RF_WEAPONMODEL +#define RF_FLARE_LOCK_ANGLE RF_MINLIGHT +#define RF_BEAM_LIGHTNING (RF_BEAM | RF_GLOW) +//KEX // player_state_t->refdef flags -#define RDF_UNDERWATER 1 // warp the screen as apropriate -#define RDF_NOWORLDMODEL 2 // used for player configuration screen +#define RDF_UNDERWATER BIT(0) // warp the screen as apropriate +#define RDF_NOWORLDMODEL BIT(1) // used for player configuration screen //ROGUE -#define RDF_IRGOGGLES 4 -#define RDF_UVGOGGLES 8 -//ROGUE +#define RDF_IRGOGGLES BIT(2) +#define RDF_UVGOGGLES BIT(3) #define RF_INDICATOR (RF_TRANSLUCENT | RF_FULLBRIGHT | RF_DEPTHHACK) #define IS_INDICATOR(rflags) ((rflags & RF_INDICATOR) == RF_INDICATOR) - -// player_state_t->refdef flags -#define RDF_UNDERWATER 1 // warp the screen as apropriate -#define RDF_NOWORLDMODEL 2 // used for player configuration screen - // // muzzle flashes / player effects // @@ -1349,25 +1387,85 @@ temp_event_t; #define CS_SKYROTATE 4 #define CS_STATUSBAR 5 // display program string -// FROM 3.20 -FB -#define CS_AIRACCEL 29 // air acceleration control -// ^^^ -#define CS_MAXCLIENTS 30 -#define CS_MAPCHECKSUM 31 // for catching cheater maps - -#define CS_MODELS 32 +#define CS_AIRACCEL_OLD 29 // air acceleration control +#define CS_MAXCLIENTS_OLD 30 +#define CS_MAPCHECKSUM_OLD 31 // for catching cheater maps +#define CS_MODELS_OLD 32 +#define CS_SOUNDS_OLD (CS_MODELS_OLD + MAX_MODELS_OLD) +#define CS_IMAGES_OLD (CS_SOUNDS_OLD + MAX_SOUNDS_OLD) +#define CS_LIGHTS_OLD (CS_IMAGES_OLD + MAX_IMAGES_OLD) +#define CS_ITEMS_OLD (CS_LIGHTS_OLD + MAX_LIGHTSTYLES) +#define CS_PLAYERSKINS_OLD (CS_ITEMS_OLD + MAX_ITEMS) +#define CS_GENERAL_OLD (CS_PLAYERSKINS_OLD + MAX_CLIENTS) +#define MAX_CONFIGSTRINGS_OLD (CS_GENERAL_OLD + MAX_GENERAL) + +#ifdef USE_PROTOCOL_EXTENSIONS +#define CS_AIRACCEL 59 +#define CS_MAXCLIENTS 60 +#define CS_MAPCHECKSUM 61 +#define CS_MODELS 62 #define CS_SOUNDS (CS_MODELS + MAX_MODELS) #define CS_IMAGES (CS_SOUNDS + MAX_SOUNDS) #define CS_LIGHTS (CS_IMAGES + MAX_IMAGES) #define CS_ITEMS (CS_LIGHTS + MAX_LIGHTSTYLES) #define CS_PLAYERSKINS (CS_ITEMS + MAX_ITEMS) -#define CS_GENERAL (CS_PLAYERSKINS + MAX_CLIENTS) //1568 -#define MAX_CONFIGSTRINGS (CS_GENERAL + MAX_GENERAL) //2080 +#define CS_GENERAL (CS_PLAYERSKINS + MAX_CLIENTS) +#define MAX_CONFIGSTRINGS (CS_GENERAL + MAX_GENERAL) +#else +#define CS_AIRACCEL CS_AIRACCEL_OLD +#define CS_MAXCLIENTS CS_MAXCLIENTS_OLD +#define CS_MAPCHECKSUM CS_MAPCHECKSUM_OLD +#define CS_MODELS CS_MODELS_OLD +#define CS_SOUNDS CS_SOUNDS_OLD +#define CS_IMAGES CS_IMAGES_OLD +#define CS_LIGHTS CS_LIGHTS_OLD +#define CS_ITEMS CS_ITEMS_OLD +#define CS_PLAYERSKINS CS_PLAYERSKINS_OLD +#define CS_GENERAL CS_GENERAL_OLD +#define MAX_CONFIGSTRINGS MAX_CONFIGSTRINGS_OLD + +#endif + +#ifdef USE_PROTOCOL_EXTENSIONS +typedef struct cs_remap_s { + qboolean extended; + + uint16_t max_edicts; + uint16_t max_models; + uint16_t max_sounds; + uint16_t max_images; + + uint16_t airaccel; + uint16_t maxclients; + uint16_t mapchecksum; + + uint16_t models; + uint16_t sounds; + uint16_t images; + uint16_t lights; + uint16_t items; + uint16_t playerskins; + uint16_t general; + + uint16_t end; +} cs_remap_t; + +#endif + //QW// The 2080 magic number comes from q_shared.h of the original game. // No game mod can go over this 2080 limit. -#if (MAX_CONFIGSTRINGS > 2080) -#error MAX_CONFIGSTRINGS > 2080 + +//Protocol extensions adjusted this check + +#ifndef USE_PROTOCOL_EXTENSIONS + #if (MAX_CONFIGSTRINGS > 2080) + #error MAX_CONFIGSTRINGS > 2080 + #endif +#else + #if (MAX_CONFIGSTRINGS > 13962) + #error MAX_CONFIGSTRINGS > 13962 + #endif #endif //============================================== @@ -1377,20 +1475,20 @@ temp_event_t; // ertity events are for effects that take place reletive // to an existing entities origin. Very network efficient. // All muzzle flashes really should be converted to events... -typedef enum -{ - EV_NONE, - EV_ITEM_RESPAWN, - EV_FOOTSTEP, - EV_FALLSHORT, - EV_FALL, - EV_FALLFAR, - EV_PLAYER_TELEPORT, - // FROM 3.20 -FB - EV_OTHER_TELEPORT - // ^^^ -} -entity_event_t; +typedef enum { + EV_NONE, + EV_ITEM_RESPAWN, + EV_FOOTSTEP, + EV_FALLSHORT, + EV_FALL, + EV_FALLFAR, + EV_PLAYER_TELEPORT, + EV_OTHER_TELEPORT, +// KEX + EV_OTHER_FOOTSTEP, + EV_LADDER_STEP, +// KEX +} entity_event_t; // entity_state_t is the information conveyed from the server