From c6e5f060fead405081494cb2d528ccadf7f95088 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Wed, 29 Oct 2014 07:15:12 -0500 Subject: [PATCH] Port Elite Force iorev2231 patch to latest ioq3 Port Thilo Schulz's Elite Force Holomatch patch to latest ioq3. Patch for ioq3 svn r2231. No support for OpenGL2 renderer yet. --- Makefile | 10 +- code/botlib/be_aas_entity.c | 13 + code/botlib/be_ai_chat.c | 25 +- code/botlib/be_ai_chat.h | 5 +- code/botlib/be_ai_goal.c | 4 + code/botlib/be_ai_weap.c | 4 + code/botlib/be_ea.c | 20 + code/botlib/be_ea.h | 7 + code/botlib/be_interface.c | 7 + code/botlib/botlib.h | 14 + code/cgame/cg_public.h | 11 +- code/client/cl_cgame.c | 47 ++- code/client/cl_console.c | 26 +- code/client/cl_input.c | 41 +- code/client/cl_keys.c | 12 +- code/client/cl_main.c | 191 +++++++-- code/client/cl_net_chan.c | 14 +- code/client/cl_parse.c | 53 ++- code/client/cl_scrn.c | 21 +- code/client/cl_ui.c | 63 ++- code/client/client.h | 3 + code/client/snd_codec.c | 37 +- code/client/snd_dma.c | 18 +- code/client/snd_openal.c | 15 + code/game/bg_public.h | 5 + code/game/g_local.h | 1 + code/game/g_public.h | 289 +++++++++++++- code/qcommon/cm_local.h | 13 +- code/qcommon/cm_patch.h | 4 +- code/qcommon/cm_trace.c | 6 + code/qcommon/common.c | 99 ++++- code/qcommon/files.c | 139 ++++++- code/qcommon/msg.c | 640 ++++++++++++++++++++++++++----- code/qcommon/net_chan.c | 122 +++++- code/qcommon/net_ip.c | 4 + code/qcommon/q_math.c | 4 + code/qcommon/q_shared.h | 67 +++- code/qcommon/qcommon.h | 78 +++- code/qcommon/surfaceflags.h | 4 + code/renderercommon/tr_common.h | 10 + code/renderercommon/tr_noise.c | 11 +- code/renderercommon/tr_public.h | 3 + code/renderercommon/tr_types.h | 95 ++++- code/renderergl1/tr_backend.c | 7 + code/renderergl1/tr_init.c | 33 +- code/renderergl1/tr_light.c | 14 + code/renderergl1/tr_local.h | 12 +- code/renderergl1/tr_main.c | 23 +- code/renderergl1/tr_scene.c | 2 + code/renderergl1/tr_shade.c | 32 +- code/renderergl1/tr_shade_calc.c | 6 + code/renderergl1/tr_shader.c | 43 ++- code/renderergl1/tr_surface.c | 609 ++++++++++++++++++++++++++++- code/server/sv_client.c | 127 ++++-- code/server/sv_game.c | 52 ++- code/server/sv_init.c | 18 +- code/server/sv_main.c | 20 +- code/server/sv_net_chan.c | 17 +- code/server/sv_snapshot.c | 23 +- code/server/sv_world.c | 98 ++++- code/sys/sys_unix.c | 12 +- code/ui/ui_public.h | 13 + 62 files changed, 3124 insertions(+), 292 deletions(-) diff --git a/Makefile b/Makefile index 4ac45070..64292e30 100644 --- a/Makefile +++ b/Makefile @@ -96,7 +96,11 @@ endif export CROSS_COMPILING ifndef VERSION -VERSION=1.36 + ifeq ($(BUILD_ELITEFORCE),1) + VERSION=1.38 + else + VERSION=1.36 + endif endif ifndef CLIENTBIN @@ -267,6 +271,10 @@ NSISDIR=misc/nsis SDLHDIR=$(MOUNT_DIR)/SDL2 LIBSDIR=$(MOUNT_DIR)/libs +ifeq ($(BUILD_ELITEFORCE),1) + CFLAGS += -DELITEFORCE +endif + bin_path=$(shell which $(1) 2> /dev/null) # We won't need this if we only build the server diff --git a/code/botlib/be_aas_entity.c b/code/botlib/be_aas_entity.c index 02699bde..68098a79 100644 --- a/code/botlib/be_aas_entity.c +++ b/code/botlib/be_aas_entity.c @@ -51,7 +51,20 @@ enum { ET_PLAYER, ET_ITEM, ET_MISSILE, +#ifdef ELITEFORCE + ET_ALT_MISSILE, + ET_MOVER, + ET_BEAM, + ET_PORTAL, + ET_SPEAKER, + ET_PUSH_TRIGGER, + ET_TELEPORT_TRIGGER, + ET_INVISIBLE, + ET_USEABLE, + ET_EVENTS +#else ET_MOVER +#endif }; //=========================================================================== diff --git a/code/botlib/be_ai_chat.c b/code/botlib/be_ai_chat.c index e90aaddc..f8b4ae21 100644 --- a/code/botlib/be_ai_chat.c +++ b/code/botlib/be_ai_chat.c @@ -2805,10 +2805,17 @@ int BotChatLength(int chatstate) void BotEnterChat(int chatstate, int clientto, int sendto) { bot_chatstate_t *cs; - + int clientnum; + cs = BotChatStateFromHandle(chatstate); if (!cs) return; + #ifdef ELITEFORCE + clientnum = clientto; + #else + clientnum = cs->client; + #endif + if (strlen(cs->chatmessage)) { BotRemoveTildes(cs->chatmessage); @@ -2818,13 +2825,15 @@ void BotEnterChat(int chatstate, int clientto, int sendto) else { switch(sendto) { case CHAT_TEAM: - EA_Command(cs->client, va("say_team %s", cs->chatmessage)); + EA_Command(clientnum, va("say_team %s", cs->chatmessage)); break; +#ifndef ELITEFORCE case CHAT_TELL: - EA_Command(cs->client, va("tell %d %s", clientto, cs->chatmessage)); + EA_Command(clientnum, va("tell %d %s", clientto, cs->chatmessage)); break; +#endif default: //CHAT_ALL - EA_Command(cs->client, va("say %s", cs->chatmessage)); + EA_Command(clientnum, va("say %s", cs->chatmessage)); break; } } @@ -2876,13 +2885,19 @@ void BotSetChatGender(int chatstate, int gender) // Returns: - // Changes Globals: - //=========================================================================== +#ifdef ELITEFORCE +void BotSetChatName(int chatstate, char *name) +#else void BotSetChatName(int chatstate, char *name, int client) +#endif { bot_chatstate_t *cs; cs = BotChatStateFromHandle(chatstate); if (!cs) return; +#ifndef ELITEFORCE cs->client = client; +#endif Com_Memset(cs->name, 0, sizeof(cs->name)); strncpy(cs->name, name, sizeof(cs->name)); cs->name[sizeof(cs->name)-1] = '\0'; @@ -2981,11 +2996,13 @@ int BotSetupChatAI(void) file = LibVarString("matchfile", "match.c"); matchtemplates = BotLoadMatchTemplates(file); // +#ifndef ELITEFORCE if (!LibVarValue("nochat", "0")) { file = LibVarString("rchatfile", "rchat.c"); replychats = BotLoadReplyChat(file); } //end if +#endif InitConsoleMessageHeap(); diff --git a/code/botlib/be_ai_chat.h b/code/botlib/be_ai_chat.h index 53a56d7b..d6c84b40 100644 --- a/code/botlib/be_ai_chat.h +++ b/code/botlib/be_ai_chat.h @@ -109,5 +109,8 @@ int BotLoadChatFile(int chatstate, char *chatfile, char *chatname); //store the gender of the bot in the chat state void BotSetChatGender(int chatstate, int gender); //store the bot name in the chat state +#ifdef ELITEFORCE +void BotSetChatName(int chatstate, char *name); +#else void BotSetChatName(int chatstate, char *name, int client); - +#endif diff --git a/code/botlib/be_ai_goal.c b/code/botlib/be_ai_goal.c index 3a5d01ab..796d0a25 100644 --- a/code/botlib/be_ai_goal.c +++ b/code/botlib/be_ai_goal.c @@ -374,7 +374,11 @@ void InitLevelItemHeap(void) if (levelitemheap) FreeMemory(levelitemheap); +#ifdef ELITEFORCE + max_levelitems = (int) LibVarValue("max_levelitems", "1024"); +#else max_levelitems = (int) LibVarValue("max_levelitems", "256"); +#endif levelitemheap = (levelitem_t *) GetClearedMemory(max_levelitems * sizeof(levelitem_t)); for (i = 0; i < max_levelitems-1; i++) diff --git a/code/botlib/be_ai_weap.c b/code/botlib/be_ai_weap.c index 8fab4d79..ca3b1ebe 100644 --- a/code/botlib/be_ai_weap.c +++ b/code/botlib/be_ai_weap.c @@ -417,7 +417,11 @@ int BotChooseBestFightWeapon(int weaponstate, int *inventory) if (!ws->weaponweightconfig) return 0; bestweight = 0; +#ifdef ELITEFORCE + bestweapon = 1; +#else bestweapon = 0; +#endif for (i = 0; i < wc->numweapons; i++) { if (!wc->weaponinfo[i].valid) continue; diff --git a/code/botlib/be_ea.c b/code/botlib/be_ea.c index 41653fda..0e42bf9f 100644 --- a/code/botlib/be_ea.c +++ b/code/botlib/be_ea.c @@ -171,6 +171,22 @@ void EA_Attack(int client) // Returns: - // Changes Globals: - //=========================================================================== +#ifdef ELITEFORCE +void EA_AltAttack(int client) +{ + bot_input_t *bi; + + bi = &botinputs[client]; + + bi->actionflags |= ACTION_ALTATTACK; +} //end of the function EA_AltAttack +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +#endif void EA_Talk(int client) { bot_input_t *bi; @@ -205,7 +221,11 @@ void EA_Respawn(int client) bi = &botinputs[client]; +#ifdef ELITEFORCE + bi->actionflags |= ACTION_ATTACK; +#else bi->actionflags |= ACTION_RESPAWN; +#endif } //end of the function EA_Respawn //=========================================================================== // diff --git a/code/botlib/be_ea.h b/code/botlib/be_ea.h index 4fb37046..75652c49 100644 --- a/code/botlib/be_ea.h +++ b/code/botlib/be_ea.h @@ -45,6 +45,13 @@ void EA_MoveBack(int client); void EA_MoveLeft(int client); void EA_MoveRight(int client); void EA_Attack(int client); +#ifdef ELITEFORCE +void EA_AltAttack(int client); +void EA_UseItem(int client, char *it); +void EA_DropItem(int client, char *it); +void EA_UseInv(int client, char *inv); +void EA_DropInv(int client, char *inv); +#endif void EA_Respawn(int client); void EA_Talk(int client); void EA_Gesture(int client); diff --git a/code/botlib/be_interface.c b/code/botlib/be_interface.c index 6f599753..dbfc2058 100644 --- a/code/botlib/be_interface.c +++ b/code/botlib/be_interface.c @@ -740,6 +740,13 @@ static void Init_EA_Export( ea_export_t *ea ) { ea->EA_Gesture = EA_Gesture; ea->EA_Talk = EA_Talk; ea->EA_Attack = EA_Attack; +#ifdef ELITEFORCE + ea->EA_AltAttack = EA_AltAttack; + ea->EA_UseItem = EA_UseItem; + ea->EA_DropItem = EA_DropItem; + ea->EA_UseInv = EA_UseInv; + ea->EA_DropInv = EA_DropInv; +#endif ea->EA_Use = EA_Use; ea->EA_Respawn = EA_Respawn; ea->EA_Crouch = EA_Crouch; diff --git a/code/botlib/botlib.h b/code/botlib/botlib.h index abdaa688..5bed78bd 100644 --- a/code/botlib/botlib.h +++ b/code/botlib/botlib.h @@ -81,6 +81,9 @@ struct weaponinfo_s; //action flags #define ACTION_ATTACK 0x00000001 #define ACTION_USE 0x00000002 +#ifdef ELITEFORCE +#define ACTION_ALTATTACK 0x00000004 +#endif #define ACTION_RESPAWN 0x00000008 #define ACTION_JUMP 0x00000010 #define ACTION_MOVEUP 0x00000020 @@ -276,6 +279,13 @@ typedef struct ea_export_s void (*EA_Gesture)(int client); void (*EA_Talk)(int client); void (*EA_Attack)(int client); +#ifdef ELITEFORCE + void (*EA_AltAttack)(int client); + void (*EA_UseItem)(int client, char *it); + void (*EA_DropItem)(int client, char *it); + void (*EA_UseInv)(int client, char *inv); + void (*EA_DropInv)(int client, char *inv); +#endif void (*EA_Use)(int client); void (*EA_Respawn)(int client); void (*EA_MoveUp)(int client); @@ -331,7 +341,11 @@ typedef struct ai_export_s void (*BotReplaceSynonyms)(char *string, unsigned long int context); int (*BotLoadChatFile)(int chatstate, char *chatfile, char *chatname); void (*BotSetChatGender)(int chatstate, int gender); +#ifdef ELITEFORCE + void (*BotSetChatName)(int chatstate, char *name); +#else void (*BotSetChatName)(int chatstate, char *name, int client); +#endif //----------------------------------- // be_ai_goal.h //----------------------------------- diff --git a/code/cgame/cg_public.h b/code/cgame/cg_public.h index 7449d38e..b0df6545 100644 --- a/code/cgame/cg_public.h +++ b/code/cgame/cg_public.h @@ -131,6 +131,7 @@ typedef enum { CG_SETUSERCMDVALUE, CG_R_REGISTERSHADERNOMIP, CG_MEMORY_REMAINING, +#ifndef ELITEFORCE CG_R_REGISTERFONT, CG_KEY_ISDOWN, CG_KEY_GETCATCHER, @@ -170,7 +171,10 @@ typedef enum { CG_STARTCAMERA, CG_GETCAMERAINFO, */ - +#else + CG_R_REGISTERSHADER3D, //59 + CG_CVAR_SET_NO_MODIFY, // 60 +#endif CG_MEMSET = 100, CG_MEMCPY, CG_STRNCPY, @@ -182,7 +186,9 @@ typedef enum { CG_CEIL, CG_TESTPRINTINT, CG_TESTPRINTFLOAT, +#ifndef ELITEFORCE CG_ACOS +#endif } cgameImport_t; @@ -225,7 +231,7 @@ typedef enum { CG_LAST_ATTACKER, // int (*CG_LastAttacker)( void ); - +#ifndef ELITEFORCE CG_KEY_EVENT, // void (*CG_KeyEvent)( int key, qboolean down ); @@ -233,6 +239,7 @@ typedef enum { // void (*CG_MouseEvent)( int dx, int dy ); CG_EVENT_HANDLING // void (*CG_EventHandling)(int type); +#endif } cgameExport_t; //---------------------------------------------- diff --git a/code/client/cl_cgame.c b/code/client/cl_cgame.c index d1e84806..ff4471f7 100644 --- a/code/client/cl_cgame.c +++ b/code/client/cl_cgame.c @@ -291,9 +291,19 @@ rescan: // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=552 // allow server to indicate why they were disconnected if ( argc >= 2 ) + { + #ifdef ELITEFORCE + Cbuf_AddText(va("err_dialog \"%s\"", Cmd_Argv(1))); + #endif Com_Error( ERR_SERVERDISCONNECT, "Server disconnected - %s", Cmd_Argv( 1 ) ); + } else + { + #ifdef ELITEFORCE + Cbuf_AddText(va("err_dialog \"%s\"", Cmd_Argv(1))); + #endif Com_Error( ERR_SERVERDISCONNECT, "Server disconnected" ); + } } if ( !strcmp( cmd, "bcs0" ) ) { @@ -448,17 +458,21 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) { case CG_FS_FCLOSEFILE: FS_FCloseFile( args[1] ); return 0; +#ifndef ELITEFORCE case CG_FS_SEEK: return FS_Seek( args[1], args[2], args[3] ); +#endif case CG_SENDCONSOLECOMMAND: Cbuf_AddText( VMA(1) ); return 0; case CG_ADDCOMMAND: CL_AddCgameCommand( VMA(1) ); return 0; +#ifndef ELITEFORCE case CG_REMOVECOMMAND: Cmd_RemoveCommandSafe( VMA(1) ); return 0; +#endif case CG_SENDCLIENTCOMMAND: CL_AddReliableCommand(VMA(1), qfalse); return 0; @@ -479,8 +493,10 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) { return CM_InlineModel( args[1] ); case CG_CM_TEMPBOXMODEL: return CM_TempBoxModel( VMA(1), VMA(2), /*int capsule*/ qfalse ); +#ifndef ELITEFORCE case CG_CM_TEMPCAPSULEMODEL: return CM_TempBoxModel( VMA(1), VMA(2), /*int capsule*/ qtrue ); +#endif case CG_CM_POINTCONTENTS: return CM_PointContents( VMA(1), args[2] ); case CG_CM_TRANSFORMEDPOINTCONTENTS: @@ -488,15 +504,19 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) { case CG_CM_BOXTRACE: CM_BoxTrace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qfalse ); return 0; +#ifndef ELITEFORCE case CG_CM_CAPSULETRACE: CM_BoxTrace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qtrue ); return 0; +#endif case CG_CM_TRANSFORMEDBOXTRACE: CM_TransformedBoxTrace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], VMA(8), VMA(9), /*int capsule*/ qfalse ); return 0; +#ifndef ELITEFORCE case CG_CM_TRANSFORMEDCAPSULETRACE: CM_TransformedBoxTrace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], VMA(8), VMA(9), /*int capsule*/ qtrue ); return 0; +#endif case CG_CM_MARKFRAGMENTS: return re.MarkFragments( args[1], VMA(2), VMA(3), args[4], VMA(5), args[6], VMA(7) ); case CG_S_STARTSOUND: @@ -511,12 +531,14 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) { case CG_S_ADDLOOPINGSOUND: S_AddLoopingSound( args[1], VMA(2), VMA(3), args[4] ); return 0; +#ifndef ELITEFORCE case CG_S_ADDREALLOOPINGSOUND: S_AddRealLoopingSound( args[1], VMA(2), VMA(3), args[4] ); return 0; case CG_S_STOPLOOPINGSOUND: S_StopLoopingSound( args[1] ); return 0; +#endif case CG_S_UPDATEENTITYPOSITION: S_UpdateEntityPosition( args[1], VMA(2) ); return 0; @@ -526,7 +548,12 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) { case CG_S_REGISTERSOUND: return S_RegisterSound( VMA(1), args[2] ); case CG_S_STARTBACKGROUNDTRACK: - S_StartBackgroundTrack( VMA(1), VMA(2) ); +#ifdef ELITEFORCE + if(!VMA(1) || !*((char *) VMA(1))) + S_StopBackgroundTrack(); + else +#endif + S_StartBackgroundTrack(VMA(1), VMA(2)); return 0; case CG_R_LOADWORLDMAP: re.LoadWorld( VMA(1) ); @@ -539,9 +566,11 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) { return re.RegisterShader( VMA(1) ); case CG_R_REGISTERSHADERNOMIP: return re.RegisterShaderNoMip( VMA(1) ); +#ifndef ELITEFORCE case CG_R_REGISTERFONT: re.RegisterFont( VMA(1), args[2], VMA(3)); return 0; +#endif case CG_R_CLEARSCENE: re.ClearScene(); return 0; @@ -551,17 +580,21 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) { case CG_R_ADDPOLYTOSCENE: re.AddPolyToScene( args[1], args[2], VMA(3), 1 ); return 0; +#ifndef ELITEFORCE case CG_R_ADDPOLYSTOSCENE: re.AddPolyToScene( args[1], args[2], VMA(3), args[4] ); return 0; case CG_R_LIGHTFORPOINT: return re.LightForPoint( VMA(1), VMA(2), VMA(3), VMA(4) ); +#endif case CG_R_ADDLIGHTTOSCENE: re.AddLightToScene( VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) ); return 0; +#ifndef ELITEFORCE case CG_R_ADDADDITIVELIGHTTOSCENE: re.AddAdditiveLightToScene( VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) ); return 0; +#endif case CG_R_RENDERSCENE: re.RenderScene( VMA(1) ); return 0; @@ -598,6 +631,7 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) { return 0; case CG_MEMORY_REMAINING: return Hunk_MemoryRemaining(); +#ifndef ELITEFORCE case CG_KEY_ISDOWN: return Key_IsDown( args[1] ); case CG_KEY_GETCATCHER: @@ -608,7 +642,7 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) { return 0; case CG_KEY_GETKEY: return Key_GetKey( VMA(1) ); - +#endif case CG_MEMSET: @@ -632,9 +666,9 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) { return FloatAsInt( floor( VMF(1) ) ); case CG_CEIL: return FloatAsInt( ceil( VMF(1) ) ); +#ifndef ELITEFORCE case CG_ACOS: return FloatAsInt( Q_acos( VMF(1) ) ); - case CG_PC_ADD_GLOBAL_DEFINE: return botlib_export->PC_AddGlobalDefine( VMA(1) ); case CG_PC_LOAD_SOURCE: @@ -692,7 +726,12 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) { return re.GetEntityToken( VMA(1), args[2] ); case CG_R_INPVS: return re.inPVS( VMA(1), VMA(2) ); - +#else + case CG_R_REGISTERSHADER3D: + return re.RegisterShader3D( VMA(1) ); + case CG_CVAR_SET_NO_MODIFY: + return qfalse; +#endif default: assert(0); Com_Error( ERR_DROP, "Bad cgame system trap: %ld", (long int) args[0] ); diff --git a/code/client/cl_console.c b/code/client/cl_console.c index 7d806e94..74255a79 100644 --- a/code/client/cl_console.c +++ b/code/client/cl_console.c @@ -602,6 +602,21 @@ void Con_DrawNotify (void) // draw the chat line if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE ) { +#ifdef ELITEFORCE + if (chat_team) + { + SCR_DrawSmallString (8, v, "say_team:", 1.0f ); + skip = 11; + } + else + { + SCR_DrawSmallString (8, v, "say:", 1.0f ); + skip = 6; + } + + Field_Draw(&chatField, skip * SMALLCHAR_WIDTH, v, + SCREEN_WIDTH - ( skip + 1 ) * SMALLCHAR_WIDTH, qtrue, qtrue); +#else if (chat_team) { SCR_DrawBigString (8, v, "say_team:", 1.0f, qfalse ); @@ -615,6 +630,7 @@ void Con_DrawNotify (void) Field_BigDraw( &chatField, skip * BIGCHAR_WIDTH, v, SCREEN_WIDTH - ( skip + 1 ) * BIGCHAR_WIDTH, qtrue, qtrue ); +#endif } } @@ -649,10 +665,18 @@ void Con_DrawSolidConsole( float frac ) { // draw the background y = frac * SCREEN_HEIGHT; + if ( y < 1 ) { y = 0; } else { + #ifdef ELITEFORCE + color[0] = 0; + color[1] = 0; + color[2] = 0; + color[3] = 0.85; + re.SetColor(color); + #endif SCR_DrawPic( 0, 0, SCREEN_WIDTH, y, cls.consoleShader ); } @@ -661,8 +685,6 @@ void Con_DrawSolidConsole( float frac ) { color[2] = 0; color[3] = 1; SCR_FillRect( 0, y, SCREEN_WIDTH, 2, color ); - - // draw the version number re.SetColor( g_color_table[ColorIndex(COLOR_RED)] ); diff --git a/code/client/cl_input.c b/code/client/cl_input.c index d35e3c31..84c4ee82 100644 --- a/code/client/cl_input.c +++ b/code/client/cl_input.c @@ -362,8 +362,10 @@ CL_MouseEvent void CL_MouseEvent( int dx, int dy, int time ) { if ( Key_GetCatcher( ) & KEYCATCH_UI ) { VM_Call( uivm, UI_MOUSE_EVENT, dx, dy ); +#ifndef ELITEFORCE } else if (Key_GetCatcher( ) & KEYCATCH_CGAME) { VM_Call (cgvm, CG_MOUSE_EVENT, dx, dy); +#endif } else { cl.mouseDx[cl.mouseIndex] += dx; cl.mouseDy[cl.mouseIndex] += dy; @@ -736,7 +738,10 @@ void CL_WritePacket( void ) { usercmd_t nullcmd; int packetNum; int oldPacketNum; - int count, key; + int count; + #ifndef ELITEFORCE + int key; + #endif // don't send anything if playing back a demo if ( clc.demoplaying || clc.state == CA_CINEMATIC ) { @@ -746,9 +751,21 @@ void CL_WritePacket( void ) { Com_Memset( &nullcmd, 0, sizeof(nullcmd) ); oldcmd = &nullcmd; - MSG_Init( &buf, data, sizeof(data) ); + #ifdef ELITEFORCE + if(clc.compat) + { + MSG_InitOOB( &buf, data, sizeof(data) ); + buf.compat = clc.compat; + } + else + { + #endif + MSG_Init( &buf, data, sizeof(data) ); + MSG_Bitstream( &buf ); + #ifdef ELITEFORCE + } + #endif - MSG_Bitstream( &buf ); // write the current serverId so the server // can tell if this is from the current gameState MSG_WriteLong( &buf, cl.serverId ); @@ -850,18 +867,24 @@ void CL_WritePacket( void ) { // write the command count MSG_WriteByte( &buf, count ); +#ifndef ELITEFORCE // use the checksum feed in the key key = clc.checksumFeed; // also use the message acknowledge key ^= clc.serverMessageSequence; // also use the last acknowledged server command in the key key ^= MSG_HashKey(clc.serverCommands[ clc.serverCommandSequence & (MAX_RELIABLE_COMMANDS-1) ], 32); +#endif // write all the commands, including the predicted command for ( i = 0 ; i < count ; i++ ) { j = (cl.cmdNumber - count + i + 1) & CMD_MASK; cmd = &cl.cmds[j]; +#ifdef ELITEFORCE + MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd); +#else MSG_WriteDeltaUsercmdKey (&buf, key, oldcmd, cmd); +#endif oldcmd = cmd; } } @@ -958,6 +981,12 @@ void CL_InitInput( void ) { Cmd_AddCommand ("-button3", IN_Button3Up); Cmd_AddCommand ("+button4", IN_Button4Down); Cmd_AddCommand ("-button4", IN_Button4Up); +#ifdef ELITEFORCE + Cmd_AddCommand ("+altattack", IN_Button5Down); + Cmd_AddCommand ("-altattack", IN_Button5Up); + Cmd_AddCommand ("+use", IN_Button6Down); + Cmd_AddCommand ("-use", IN_Button6Up); +#endif Cmd_AddCommand ("+button5", IN_Button5Down); Cmd_AddCommand ("-button5", IN_Button5Up); Cmd_AddCommand ("+button6", IN_Button6Down); @@ -1035,6 +1064,12 @@ void CL_ShutdownInput(void) Cmd_RemoveCommand("-button3"); Cmd_RemoveCommand("+button4"); Cmd_RemoveCommand("-button4"); +#ifdef ELITEFORCE + Cmd_RemoveCommand ("+altattack"); + Cmd_RemoveCommand ("-altattack"); + Cmd_RemoveCommand ("+use"); + Cmd_RemoveCommand ("-use"); +#endif Cmd_RemoveCommand("+button5"); Cmd_RemoveCommand("-button5"); Cmd_RemoveCommand("+button6"); diff --git a/code/client/cl_keys.c b/code/client/cl_keys.c index a6173ddf..976d259f 100644 --- a/code/client/cl_keys.c +++ b/code/client/cl_keys.c @@ -1244,13 +1244,14 @@ void CL_KeyDownEvent( int key, unsigned time ) return; } +#ifndef ELITEFORCE // escape always gets out of CGAME stuff if (Key_GetCatcher( ) & KEYCATCH_CGAME) { Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_CGAME ); VM_Call (cgvm, CG_EVENT_HANDLING, CGAME_EVENT_NONE); return; } - +#endif if ( !( Key_GetCatcher( ) & KEYCATCH_UI ) ) { if ( clc.state == CA_ACTIVE && !clc.demoplaying ) { VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_INGAME ); @@ -1262,8 +1263,11 @@ void CL_KeyDownEvent( int key, unsigned time ) } return; } - +#ifdef ELITEFORCE + VM_Call( uivm, UI_KEY_EVENT, key ); +#else VM_Call( uivm, UI_KEY_EVENT, key, qtrue ); +#endif return; } @@ -1277,10 +1281,12 @@ void CL_KeyDownEvent( int key, unsigned time ) if ( uivm ) { VM_Call( uivm, UI_KEY_EVENT, key, qtrue ); } +#ifndef ELITEFORCE } else if ( Key_GetCatcher( ) & KEYCATCH_CGAME ) { if ( cgvm ) { VM_Call( cgvm, CG_KEY_EVENT, key, qtrue ); } +#endif } else if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE ) { Message_Key( key ); } else if ( clc.state == CA_DISCONNECTED ) { @@ -1317,11 +1323,13 @@ void CL_KeyUpEvent( int key, unsigned time ) // CL_ParseBinding( key, qfalse, time ); +#ifndef ELITEFORCE if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) { VM_Call( uivm, UI_KEY_EVENT, key, qfalse ); } else if ( Key_GetCatcher( ) & KEYCATCH_CGAME && cgvm ) { VM_Call( cgvm, CG_KEY_EVENT, key, qfalse ); } +#endif } /* diff --git a/code/client/cl_main.c b/code/client/cl_main.c index 75f0dca0..7a7a7df4 100644 --- a/code/client/cl_main.c +++ b/code/client/cl_main.c @@ -733,9 +733,14 @@ void CL_Record_f( void ) { if ( Cmd_Argc() == 2 ) { s = Cmd_Argv(1); Q_strncpyz( demoName, s, sizeof( demoName ) ); + #ifdef LEGACY_PROTOCOL if(clc.compat) + #ifdef ELITEFORCE + Com_sprintf(name, sizeof(name), "demos/%s.efdemo", demoName); + #else Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_legacyprotocol->integer); + #endif else #endif Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer); @@ -747,7 +752,11 @@ void CL_Record_f( void ) { CL_DemoFilename( number, demoName, sizeof( demoName ) ); #ifdef LEGACY_PROTOCOL if(clc.compat) + #ifdef ELITEFORCE + Com_sprintf(name, sizeof(name), "demos/%s.efdemo", demoName); + #else Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_legacyprotocol->integer); + #endif else #endif Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer); @@ -778,11 +787,23 @@ void CL_Record_f( void ) { clc.demowaiting = qtrue; // write out the gamestate message - MSG_Init (&buf, bufData, sizeof(bufData)); - MSG_Bitstream(&buf); + #ifdef ELITEFORCE + if(clc.compat) + { + MSG_InitOOB(&buf, bufData, sizeof(bufData)); + buf.compat = qtrue; + } + else + { + #endif + MSG_Init (&buf, bufData, sizeof(bufData)); + MSG_Bitstream(&buf); - // NOTE, MRE: all server->client messages now acknowledge - MSG_WriteLong( &buf, clc.reliableSequence ); + // NOTE, MRE: all server->client messages now acknowledge + MSG_WriteLong( &buf, clc.reliableSequence ); + #ifdef ELITEFORCE + } + #endif MSG_WriteByte (&buf, svc_gamestate); MSG_WriteLong (&buf, clc.serverCommandSequence ); @@ -809,17 +830,30 @@ void CL_Record_f( void ) { MSG_WriteDeltaEntity (&buf, &nullstate, ent, qtrue ); } - MSG_WriteByte( &buf, svc_EOF ); + #ifdef ELITEFORCE + if(buf.compat) + MSG_WriteByte(&buf, 0); + else + #endif + MSG_WriteByte( &buf, svc_EOF ); // finished writing the gamestate stuff - // write the client num - MSG_WriteLong(&buf, clc.clientNum); - // write the checksum feed - MSG_WriteLong(&buf, clc.checksumFeed); + #ifdef ELITEFORCE + if(!buf.compat) + { + #endif + // write the client num + MSG_WriteLong(&buf, clc.clientNum); - // finished writing the client packet - MSG_WriteByte( &buf, svc_EOF ); + // write the checksum feed + MSG_WriteLong(&buf, clc.checksumFeed); + + // finished writing the client packet + MSG_WriteByte( &buf, svc_EOF ); + #ifdef ELITEFORCE + } + #endif // write it to the demo file len = LittleLong( clc.serverMessageSequence - 1 ); @@ -962,7 +996,15 @@ void CL_ReadDemoMessage( void ) { clc.serverMessageSequence = LittleLong( s ); // init the message - MSG_Init( &buf, bufData, sizeof( bufData ) ); + #ifdef ELITEFORCE + if(clc.compat) + { + MSG_InitOOB(&buf, bufData, sizeof(bufData)); + buf.compat = qtrue; + } + else + #endif + MSG_Init( &buf, bufData, sizeof( bufData ) ); // get the length r = FS_Read (&buf.cursize, 4, clc.demofile); @@ -999,11 +1041,15 @@ static int CL_WalkDemoExt(char *arg, char *name, int *demofile) { int i = 0; *demofile = 0; - + #ifdef LEGACY_PROTOCOL if(com_legacyprotocol->integer > 0) { +#ifdef ELITEFORCE + Com_sprintf(name, MAX_OSPATH, "demos/%s.efdemo", arg); +#else Com_sprintf(name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_legacyprotocol->integer); +#endif FS_FOpenFileRead(name, demofile, qtrue); if (*demofile) @@ -1094,9 +1140,20 @@ void CL_PlayDemo_f( void ) { // open the demo file arg = Cmd_Argv(1); - - CL_Disconnect( qtrue ); + CL_Disconnect( qtrue ); + +#ifdef ELITEFORCE + ext_test = arg + strlen(arg) - 7; + if(!strcmp(ext_test, ".efdemo")) + { + Com_sprintf (name, sizeof(name), "demos/%s", arg); + FS_FOpenFileRead(name, &clc.demofile, qtrue); + protocol = com_legacyprotocol->integer; + } + else +#endif +{ // check for an extension .DEMOEXT_?? (?? is protocol) ext_test = strrchr(arg, '.'); @@ -1136,6 +1193,7 @@ void CL_PlayDemo_f( void ) { } else protocol = CL_WalkDemoExt(arg, name, &clc.demofile); +} if (!clc.demofile) { Com_Error( ERR_DROP, "couldn't open %s", name); @@ -1869,7 +1927,12 @@ void CL_SendPureChecksums( void ) { char cMsg[MAX_INFO_VALUE]; // if we are pure we need to send back a command with our referenced pk3 checksums - Com_sprintf(cMsg, sizeof(cMsg), "cp %d %s", cl.serverId, FS_ReferencedPakPureChecksums()); +#ifdef ELITEFORCE + if(clc.compat) + Com_sprintf(cMsg, sizeof(cMsg), "cp %s", FS_ReferencedPakPureChecksums()); + else +#endif + Com_sprintf(cMsg, sizeof(cMsg), "cp %d %s", cl.serverId, FS_ReferencedPakPureChecksums()); CL_AddReliableCommand(cMsg, qfalse); } @@ -2369,7 +2432,11 @@ void CL_CheckForResend( void ) { data[10+i] = 0; // NOTE TTimo don't forget to set the right data length! - NET_OutOfBandData( NS_CLIENT, clc.serverAddress, (byte *) &data[0], i+10 ); + #ifdef ELITEFORCE + NET_OutOfBandPrint( NS_CLIENT, clc.serverAddress, "%s", data); + #else + NET_OutOfBandData( NS_CLIENT, clc.serverAddress, (byte *) &data[0], i+10 ); + #endif // the most current userinfo has been sent, so watch for any // newer changes to userinfo variables cvar_modifiedFlags &= ~CVAR_USERINFO; @@ -2447,6 +2514,9 @@ void CL_ServersResponsePacket( const netadr_t* from, msg_t *msg, qboolean extend int numservers; byte* buffptr; byte* buffend; + #ifdef ELITEFORCE + char strbyte[3] = "FF"; + #endif Com_Printf("CL_ServersResponsePacket\n"); @@ -2476,12 +2546,30 @@ void CL_ServersResponsePacket( const netadr_t* from, msg_t *msg, qboolean extend if (*buffptr == '\\') { buffptr++; +#ifdef ELITEFORCE + if (buffend - buffptr < sizeof(addresses[numservers].ip) * 2 + sizeof(addresses[numservers].port) * 2 + 1) + break; + // EliteForce uses a slightly different format with bytes encoded + // in hex values. + for(i = 0; i < 6; i++) + { + strbyte[0] = toupper(*buffptr++); + strbyte[1] = toupper(*buffptr++); + + if(i < 4) + addresses[numservers].ip[i] = strtoul(strbyte, NULL, 16); + else + ((unsigned char *) &addresses[numservers].port)[i - 4] = + strtoul(strbyte, NULL, 16); + } +#else if (buffend - buffptr < sizeof(addresses[numservers].ip) + sizeof(addresses[numservers].port) + 1) break; for(i = 0; i < sizeof(addresses[numservers].ip); i++) addresses[numservers].ip[i] = *buffptr++; +#endif addresses[numservers].type = NA_IP; } @@ -2497,17 +2585,24 @@ void CL_ServersResponsePacket( const netadr_t* from, msg_t *msg, qboolean extend addresses[numservers].ip6[i] = *buffptr++; addresses[numservers].type = NA_IP6; +#ifdef ELITEFORCE + // parse out port + addresses[numservers].port = (*buffptr++) << 8; + addresses[numservers].port += *buffptr++; + addresses[numservers].port = BigShort( addresses[numservers].port ); +#endif addresses[numservers].scope_id = from->scope_id; } else // syntax error! break; +#ifndef ELITEFORCE // parse out port addresses[numservers].port = (*buffptr++) << 8; addresses[numservers].port += *buffptr++; addresses[numservers].port = BigShort( addresses[numservers].port ); - +#endif // syntax check if (*buffptr != '\\' && *buffptr != '/') break; @@ -2708,6 +2803,9 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { clc.challenge, qfalse); #endif + #ifdef ELITEFORCE + clc.netchan.compat = clc.compat; + #endif clc.state = CA_CONNECTED; clc.lastPacketSentTime = -9999; // send first packet immediately return; @@ -2780,7 +2878,10 @@ void CL_PacketEvent( netadr_t from, msg_t *msg ) { int headerBytes; clc.lastPacketTime = cls.realtime; - + #ifdef ELITEFORCE + msg->compat = clc.compat; + #endif + if ( msg->cursize >= 4 && *(int *)msg->data == -1 ) { CL_ConnectionlessPacket( from, msg ); return; @@ -3097,7 +3198,11 @@ void CL_InitRenderer( void ) { re.BeginRegistration( &cls.glconfig ); // load character sets +#ifdef ELITEFORCE + cls.charSetShader = re.RegisterShaderNoMip( "gfx/2d/charsgrid_med" ); +#else cls.charSetShader = re.RegisterShader( "gfx/2d/bigchars" ); +#endif cls.whiteShader = re.RegisterShader( "white" ); cls.consoleShader = re.RegisterShader( "console" ); g_console_field_width = cls.glconfig.vidWidth / SMALLCHAR_WIDTH - 2; @@ -3426,6 +3531,8 @@ void CL_Init( void ) { } cls.realtime = 0; + clc.lastPacketTime = 0; + clc.lastPacketSentTime = -9999; CL_InitInput (); @@ -3460,7 +3567,11 @@ void CL_Init( void ) { cl_pitchspeed = Cvar_Get ("cl_pitchspeed", "140", CVAR_ARCHIVE); cl_anglespeedkey = Cvar_Get ("cl_anglespeedkey", "1.5", 0); +#ifdef ELITEFORCE + cl_maxpackets = Cvar_Get ("cl_maxpackets", "43", CVAR_ARCHIVE ); +#else cl_maxpackets = Cvar_Get ("cl_maxpackets", "30", CVAR_ARCHIVE ); +#endif cl_packetdup = Cvar_Get ("cl_packetdup", "1", CVAR_ARCHIVE ); cl_run = Cvar_Get ("cl_run", "1", CVAR_ARCHIVE); @@ -3541,12 +3652,14 @@ void CL_Init( void ) { Cvar_Get ("name", "UnnamedPlayer", CVAR_USERINFO | CVAR_ARCHIVE ); cl_rate = Cvar_Get ("rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("snaps", "20", CVAR_USERINFO | CVAR_ARCHIVE ); - Cvar_Get ("model", "sarge", CVAR_USERINFO | CVAR_ARCHIVE ); - Cvar_Get ("headmodel", "sarge", CVAR_USERINFO | CVAR_ARCHIVE ); + Cvar_Get ("model", "munro/red", CVAR_USERINFO | CVAR_ARCHIVE ); + #ifndef ELITEFORCE + Cvar_Get ("headmodel", "munro", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("team_model", "james", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("team_headmodel", "*james", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("g_redTeam", "Stroggs", CVAR_SERVERINFO | CVAR_ARCHIVE); Cvar_Get ("g_blueTeam", "Pagans", CVAR_SERVERINFO | CVAR_ARCHIVE); + #endif Cvar_Get ("color1", "4", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("color2", "5", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("handicap", "100", CVAR_USERINFO | CVAR_ARCHIVE ); @@ -3750,6 +3863,19 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) { char *gamename; qboolean gameMismatch; +#ifdef ELITEFORCE + // eliteforce doesn't send a \n after infoResponse.. + infoString = strchr((char *) msg->data, '"'); + if(!infoString) + return; + msg->readcount = (int) ((byte *) ++infoString - msg->data); + msg->bit = msg->readcount << 3; + // find the second " character and empty it. + infoString = strchr(infoString, '"'); + if(infoString) + *infoString = '\0'; +#endif + infoString = MSG_ReadString( msg ); // if this isn't the correct gamename, ignore it @@ -3787,6 +3913,10 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) { { if ( cl_pinglist[i].adr.port && !cl_pinglist[i].time && NET_CompareAdr( from, cl_pinglist[i].adr ) ) { +#ifdef ELITEFORCE + char *str = ""; +#endif + // calc ping time cl_pinglist[i].time = Sys_Milliseconds() - cl_pinglist[i].start; Com_DPrintf( "ping time %dms from %s\n", cl_pinglist[i].time, NET_AdrToString( from ) ); @@ -3801,15 +3931,25 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) { case NA_BROADCAST: case NA_IP: type = 1; +#ifdef ELITEFORCE + str = "udp"; +#endif break; case NA_IP6: type = 2; +#ifdef ELITEFORCE + str = "udp6"; +#endif break; default: type = 0; break; } - Info_SetValueForKey( cl_pinglist[i].info, "nettype", va("%d", type) ); +#ifdef ELITEFORCE + Info_SetValueForKey( cl_pinglist[i].info, "nettype", str); +#else + Info_SetValueForKey( cl_pinglist[i].info, "nettype", va("%d", type)); +#endif CL_SetServerInfoByAddress(from, infoString, cl_pinglist[i].time); return; @@ -4113,7 +4253,7 @@ void CL_GlobalServers_f( void ) { // -1 is used to distinguish a "no response" i = NET_StringToAdr(masteraddress, &to, NA_UNSPEC); - + if(!i) { Com_Printf( "CL_GlobalServers_f: Error: could not resolve address of master %s\n", masteraddress); @@ -4147,8 +4287,13 @@ void CL_GlobalServers_f( void ) { Com_sprintf(command, sizeof(command), "getservers %s", Cmd_Argv(2)); else +#ifdef ELITEFORCE + Com_sprintf(command, sizeof(command), "getservers %s", + Cmd_Argv(2)); +#else Com_sprintf(command, sizeof(command), "getservers %s %s", com_gamename->string, Cmd_Argv(2)); +#endif for (i=3; i < count; i++) { diff --git a/code/client/cl_net_chan.c b/code/client/cl_net_chan.c index 9d9f2399..8a7f9dc3 100644 --- a/code/client/cl_net_chan.c +++ b/code/client/cl_net_chan.c @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../qcommon/qcommon.h" #include "client.h" +#ifndef ELITEFORCE #ifdef LEGACY_PROTOCOL /* ============== @@ -36,6 +37,7 @@ CL_Netchan_Encode ============== */ + static void CL_Netchan_Encode( msg_t *msg ) { int serverId, messageAcknowledge, reliableAcknowledge; int i, index, srdc, sbit, soob; @@ -90,6 +92,7 @@ CL_Netchan_Decode ============== */ + static void CL_Netchan_Decode( msg_t *msg ) { long reliableAcknowledge, i, index; byte key, *string; @@ -127,6 +130,7 @@ static void CL_Netchan_Decode( msg_t *msg ) { } } #endif +#endif /* ================= @@ -150,11 +154,16 @@ CL_Netchan_Transmit ================ */ void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg ) { - MSG_WriteByte( msg, clc_EOF ); +#ifdef ELITEFORCE + if(!chan->compat) +#endif + MSG_WriteByte( msg, clc_EOF ); +#ifndef ELITEFORCE #ifdef LEGACY_PROTOCOL if(chan->compat) CL_Netchan_Encode(msg); +#endif #endif Netchan_Transmit(chan, msg->cursize, msg->data); @@ -177,10 +186,11 @@ qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) { ret = Netchan_Process( chan, msg ); if (!ret) return qfalse; - +#ifndef ELITEFORCE #ifdef LEGACY_PROTOCOL if(chan->compat) CL_Netchan_Decode(msg); +#endif #endif return qtrue; diff --git a/code/client/cl_parse.c b/code/client/cl_parse.c index 5c9c1471..1876264f 100644 --- a/code/client/cl_parse.c +++ b/code/client/cl_parse.c @@ -209,8 +209,11 @@ void CL_ParseSnapshot( msg_t *msg ) { // get the reliable sequence acknowledge number // NOTE: now sent with all server to client messages - //clc.reliableAcknowledge = MSG_ReadLong( msg ); - + #ifdef ELITEFORCE + if(msg->compat) + clc.reliableAcknowledge = MSG_ReadLong( msg ); + #endif + // read in the new snapshot to a temporary buffer // we will only copy to cl.snap if it is valid Com_Memset (&newSnap, 0, sizeof(newSnap)); @@ -482,9 +485,12 @@ void CL_ParseGamestate( msg_t *msg ) { while ( 1 ) { cmd = MSG_ReadByte( msg ); - if ( cmd == svc_EOF ) { + #ifdef ELITEFORCE + if((msg->compat && cmd <= 0) || cmd == svc_EOF) + #else + if ( cmd == svc_EOF ) + #endif break; - } if ( cmd == svc_configstring ) { int len; @@ -517,9 +523,16 @@ void CL_ParseGamestate( msg_t *msg ) { } } - clc.clientNum = MSG_ReadLong(msg); + #ifdef ELITEFORCE + if(!msg->compat) + #endif + clc.clientNum = MSG_ReadLong(msg); + // read the checksum feed - clc.checksumFeed = MSG_ReadLong( msg ); + #ifdef ELITEFORCE + if(!clc.demoplaying || !msg->compat) + #endif + clc.checksumFeed = MSG_ReadLong( msg ); // save old gamedir Cvar_VariableStringBuffer("fs_game", oldGame, sizeof(oldGame)); @@ -872,15 +885,22 @@ void CL_ParseServerMessage( msg_t *msg ) { Com_Printf ("------------------\n"); } - MSG_Bitstream(msg); + #ifdef ELITEFORCE + if(!msg->compat) + { + #endif + MSG_Bitstream(msg); - // get the reliable sequence acknowledge number - clc.reliableAcknowledge = MSG_ReadLong( msg ); - // - if ( clc.reliableAcknowledge < clc.reliableSequence - MAX_RELIABLE_COMMANDS ) { - clc.reliableAcknowledge = clc.reliableSequence; + // get the reliable sequence acknowledge number + clc.reliableAcknowledge = MSG_ReadLong( msg ); + // + if ( clc.reliableAcknowledge < clc.reliableSequence - MAX_RELIABLE_COMMANDS ) { + clc.reliableAcknowledge = clc.reliableSequence; + } + #ifdef ELITEFORCE } - + #endif + // // parse the message // @@ -892,7 +912,12 @@ void CL_ParseServerMessage( msg_t *msg ) { cmd = MSG_ReadByte( msg ); - if (cmd == svc_EOF) { + #ifdef ELITEFORCE + if(cmd == svc_EOF || (msg->compat && cmd == -1)) + #else + if ( cmd == svc_EOF) + #endif + { SHOWNET( msg, "END OF MESSAGE" ); break; } diff --git a/code/client/cl_scrn.c b/code/client/cl_scrn.c index 831d5ef7..18a1f939 100644 --- a/code/client/cl_scrn.c +++ b/code/client/cl_scrn.c @@ -160,7 +160,7 @@ static void SCR_DrawChar( int x, int y, float size, int ch ) { void SCR_DrawSmallChar( int x, int y, int ch ) { int row, col; float frow, fcol; - float size; + float vsize, hsize; ch &= 255; @@ -177,11 +177,16 @@ void SCR_DrawSmallChar( int x, int y, int ch ) { frow = row*0.0625; fcol = col*0.0625; - size = 0.0625; + vsize = 0.0625; +#ifdef ELITEFORCE + hsize = 0.03125; +#else + hsize = 0.0625; +#endif re.DrawStretchPic( x, y, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, fcol, frow, - fcol + size, frow + size, + fcol + hsize, frow + vsize, cls.charSetShader ); } @@ -255,6 +260,16 @@ void SCR_DrawBigStringColor( int x, int y, const char *s, vec4_t color, qboolean SCR_DrawStringExt( x, y, BIGCHAR_WIDTH, s, color, qtrue, noColorEscape ); } +#ifdef ELITEFORCE +void SCR_DrawSmallString(int x, int y, const char *s, float alpha) +{ + float color[4]; + + color[0] = color[1] = color[2] = 1.0; + color[3] = alpha; + SCR_DrawSmallStringExt(x, y, s, color, qfalse, qfalse); +} +#endif /* ================== diff --git a/code/client/cl_ui.c b/code/client/cl_ui.c index 67ec918d..8aa202e5 100644 --- a/code/client/cl_ui.c +++ b/code/client/cl_ui.c @@ -84,7 +84,7 @@ void LAN_SaveServersToCache( void ) { FS_FCloseFile(fileOut); } - +#ifndef ELITEFORCE /* ==================== LAN_ResetPings @@ -204,7 +204,7 @@ static void LAN_RemoveServer(int source, const char *addr) { } } } - +#endif /* ==================== @@ -226,7 +226,6 @@ static int LAN_GetServerCount( int source ) { } return 0; } - /* ==================== LAN_GetLocalServerAddressString @@ -257,6 +256,7 @@ static void LAN_GetServerAddressString( int source, int n, char *buf, int buflen buf[0] = '\0'; } +#ifndef ELITEFORCE /* ==================== LAN_GetServerInfo @@ -365,7 +365,6 @@ static serverInfo_t *LAN_GetServerPtr( int source, int n ) { } return NULL; } - /* ==================== LAN_CompareServers @@ -435,6 +434,8 @@ static int LAN_CompareServers( int source, int sortKey, int sortDir, int s1, int return res; } +#endif + /* ==================== LAN_GetPingQueueCount @@ -471,6 +472,7 @@ static void LAN_GetPingInfo( int n, char *buf, int buflen ) { CL_GetPingInfo( n, buf, buflen ); } +#ifndef ELITEFORCE /* ==================== LAN_MarkServerVisible @@ -549,6 +551,8 @@ static int LAN_ServerIsVisible(int source, int n ) { return qfalse; } +#endif + /* ======================= LAN_UpdateVisiblePings @@ -627,6 +631,7 @@ static void Key_GetBindingBuf( int keynum, char *buf, int buflen ) { CLUI_GetCDKey ==================== */ + #ifndef ELITEFORCE static void CLUI_GetCDKey( char *buf, int buflen ) { #ifndef STANDALONE cvar_t *fs; @@ -642,7 +647,7 @@ static void CLUI_GetCDKey( char *buf, int buflen ) { *buf = 0; #endif } - + #endif /* ==================== @@ -659,7 +664,12 @@ static void CLUI_SetCDKey( char *buf ) { // set the flag so the fle will be written at the next opportunity cvar_modifiedFlags |= CVAR_ARCHIVE; } else { + #ifdef ELITEFORCE + Com_Memcpy(cl_cdkey, buf, 22); + cl_cdkey[22] = '\0'; + #else Com_Memcpy( cl_cdkey, buf, 16 ); + #endif // set the flag so the fle will be written at the next opportunity cvar_modifiedFlags |= CVAR_ARCHIVE; } @@ -794,8 +804,10 @@ intptr_t CL_UISystemCalls( intptr_t *args ) { case UI_FS_GETFILELIST: return FS_GetFileList( VMA(1), VMA(2), VMA(3), args[4] ); +#ifndef ELITEFORCE case UI_FS_SEEK: return FS_Seek( args[1], args[2], args[3] ); +#endif case UI_R_REGISTERMODEL: return re.RegisterModel( VMA(1) ); @@ -902,6 +914,7 @@ intptr_t CL_UISystemCalls( intptr_t *args ) { case UI_GETCONFIGSTRING: return GetConfigString( args[1], VMA(2), args[3] ); +#ifndef ELITEFORCE case UI_LAN_LOADCACHEDSERVERS: LAN_LoadCachedServers(); return 0; @@ -916,6 +929,7 @@ intptr_t CL_UISystemCalls( intptr_t *args ) { case UI_LAN_REMOVESERVER: LAN_RemoveServer(args[1], VMA(2)); return 0; +#endif case UI_LAN_GETPINGQUEUECOUNT: return LAN_GetPingQueueCount(); @@ -932,13 +946,26 @@ intptr_t CL_UISystemCalls( intptr_t *args ) { LAN_GetPingInfo( args[1], VMA(2), args[3] ); return 0; +#ifdef ELITEFORCE + case UI_LAN_GETLOCALSERVERCOUNT: + return LAN_GetServerCount(AS_LOCAL); + + case UI_LAN_GETLOCALSERVERADDRESSSTRING: + LAN_GetServerAddressString( AS_LOCAL, args[1], VMA(2), args[3] ); + return 0; + case UI_LAN_GETGLOBALSERVERCOUNT: + return LAN_GetServerCount(AS_GLOBAL); + + case UI_LAN_GETGLOBALSERVERADDRESSSTRING: + LAN_GetServerAddressString( AS_GLOBAL, args[1], VMA(2), args[3] ); + return 0; +#else case UI_LAN_GETSERVERCOUNT: return LAN_GetServerCount(args[1]); case UI_LAN_GETSERVERADDRESSSTRING: LAN_GetServerAddressString( args[1], args[2], VMA(3), args[4] ); return 0; - case UI_LAN_GETSERVERINFO: LAN_GetServerInfo( args[1], args[2], VMA(3), args[4] ); return 0; @@ -965,26 +992,32 @@ intptr_t CL_UISystemCalls( intptr_t *args ) { case UI_LAN_COMPARESERVERS: return LAN_CompareServers( args[1], args[2], args[3], args[4], args[5] ); +#endif case UI_MEMORY_REMAINING: return Hunk_MemoryRemaining(); + #ifndef ELITEFORCE case UI_GET_CDKEY: CLUI_GetCDKey( VMA(1), args[2] ); return 0; - + #endif case UI_SET_CDKEY: #ifndef STANDALONE CLUI_SetCDKey( VMA(1) ); + #ifdef ELITEFORCE + return qtrue; + #endif #endif return 0; - +#ifndef ELITEFORCE case UI_SET_PBCLSTATUS: return 0; case UI_R_REGISTERFONT: re.RegisterFont( VMA(1), args[2], VMA(3)); return 0; +#endif case UI_MEMSET: Com_Memset( VMA(1), args[2], args[3] ); @@ -1016,6 +1049,7 @@ intptr_t CL_UISystemCalls( intptr_t *args ) { case UI_CEIL: return FloatAsInt( ceil( VMF(1) ) ); +#ifndef ELITEFORCE case UI_PC_ADD_GLOBAL_DEFINE: return botlib_export->PC_AddGlobalDefine( VMA(1) ); case UI_PC_LOAD_SOURCE: @@ -1061,6 +1095,7 @@ intptr_t CL_UISystemCalls( intptr_t *args ) { case UI_VERIFY_CDKEY: return CL_CDKeyValidate(VMA(1), VMA(2)); +#endif default: Com_Error( ERR_DROP, "Bad UI system trap: %ld", (long int) args[0] ); @@ -1117,6 +1152,10 @@ void CL_InitUI( void ) { // Com_Printf(S_COLOR_YELLOW "WARNING: loading old Quake III Arena User Interface version %d\n", v ); // init for this gamestate VM_Call( uivm, UI_INIT, (clc.state >= CA_AUTHORIZING && clc.state < CA_ACTIVE)); + + #ifdef ELITEFORCE + Cvar_SetValue("ui_cdkeychecked2", 1); + #endif } else if (v != UI_API_VERSION) { // Free uivm now, so UI_SHUTDOWN doesn't get called later. @@ -1129,16 +1168,24 @@ void CL_InitUI( void ) { else { // init for this gamestate VM_Call( uivm, UI_INIT, (clc.state >= CA_AUTHORIZING && clc.state < CA_ACTIVE) ); + + #ifdef ELITEFORCE + Cvar_SetValue("ui_cdkeychecked2", 1); + #endif } } #ifndef STANDALONE qboolean UI_usesUniqueCDKey( void ) { +#ifdef ELITEFORCE + return qfalse; +#else if (uivm) { return (VM_Call( uivm, UI_HASUNIQUECDKEY) == qtrue); } else { return qfalse; } +#endif } #endif diff --git a/code/client/client.h b/code/client/client.h index a9b3e51e..50ec58b2 100644 --- a/code/client/client.h +++ b/code/client/client.h @@ -574,6 +574,9 @@ void SCR_DrawNamedPic( float x, float y, float width, float height, const char * void SCR_DrawBigString( int x, int y, const char *s, float alpha, qboolean noColorEscape ); // draws a string with embedded color control characters with fade void SCR_DrawBigStringColor( int x, int y, const char *s, vec4_t color, qboolean noColorEscape ); // ignores embedded color control characters +#ifdef ELITEFORCE +void SCR_DrawSmallString( int x, int y, const char *s, float alpha ); // draws a string with embedded color control characters with fade +#endif void SCR_DrawSmallStringExt( int x, int y, const char *string, float *setColor, qboolean forceColor, qboolean noColorEscape ); void SCR_DrawSmallChar( int x, int y, int ch ); diff --git a/code/client/snd_codec.c b/code/client/snd_codec.c index 6521ae10..d65d0c00 100644 --- a/code/client/snd_codec.c +++ b/code/client/snd_codec.c @@ -26,6 +26,34 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA static snd_codec_t *codecs; +static void *S_CodecGetSound(const char *filename, snd_info_t *info); + +#ifdef ELITEFORCE +int sem = qtrue; +#define VOXDIR "sound/voice" + +void *S_MangleNameEF(char *filename, snd_info_t *info) +{ + char localName[MAX_QPATH]; + + if( + !Q_strncmp(filename, VOXDIR, ARRAY_LEN(VOXDIR) - 1) && + !Q_stricmp(Cvar_VariableString("s_language"), "DEUTSCH") + ) + { + Q_strncpyz(localName, filename, MAX_QPATH - 10); + + localName[8] = 'x'; + localName[9] = '_'; + localName[10] = 'd'; + + return S_CodecGetSound(localName, info); + } + + return NULL; +} +#endif + /* ================= S_CodecGetSound @@ -46,6 +74,12 @@ static void *S_CodecGetSound(const char *filename, snd_info_t *info) Q_strncpyz(localName, filename, MAX_QPATH); + #ifdef ELITEFORCE + rtn = S_MangleNameEF(localName, info); + if(rtn) + return rtn; + #endif + ext = COM_GetExtension(localName); if( *ext ) @@ -110,7 +144,7 @@ static void *S_CodecGetSound(const char *filename, snd_info_t *info) } } - Com_Printf(S_COLOR_YELLOW "WARNING: Failed to %s sound %s!\n", info ? "load" : "open", filename); + Com_DPrintf(S_COLOR_YELLOW "WARNING: Failed to %s sound %s!\n", info ? "load" : "open", filename); return NULL; } @@ -166,6 +200,7 @@ void S_CodecRegister(snd_codec_t *codec) S_CodecLoad ================= */ + void *S_CodecLoad(const char *filename, snd_info_t *info) { return S_CodecGetSound(filename, info); diff --git a/code/client/snd_dma.c b/code/client/snd_dma.c index e243f406..93b61b4e 100644 --- a/code/client/snd_dma.c +++ b/code/client/snd_dma.c @@ -375,10 +375,20 @@ sfxHandle_t S_Base_RegisterSound( const char *name, qboolean compressed ) { sfx->inMemory = qfalse; sfx->soundCompressed = compressed; - S_memoryLoad(sfx); + S_memoryLoad(sfx); if ( sfx->defaultSound ) { + #ifdef ELITEFORCE + int hash = S_HashSFXName(name); + // free the slot up. + sfx->soundName[0] = '\0'; + sfx->inMemory = qfalse; + sfx->defaultSound = qfalse; + // the new entry is head anyways. + sfxHash[hash] = sfx->next; + #else Com_Printf( S_COLOR_YELLOW "WARNING: could not find %s - using default\n", sfx->soundName ); + #endif return 0; } @@ -400,7 +410,11 @@ void S_Base_BeginRegistration( void ) { Com_Memset(s_knownSfx, '\0', sizeof(s_knownSfx)); Com_Memset(sfxHash, '\0', sizeof(sfx_t *) * LOOP_HASH); +#ifdef ELITEFORCE + S_Base_RegisterSound("sound/null.wav", qfalse); // Eliteforce specific sound. +#else S_Base_RegisterSound("sound/feedback/hit.wav", qfalse); // changed to a sound in baseq3 +#endif } } @@ -1399,9 +1413,11 @@ static void S_OpenBackgroundStream( const char *filename ) { return; } + #ifndef ELITEFORCE if(s_backgroundStream->info.channels != 2 || s_backgroundStream->info.rate != 22050) { Com_Printf(S_COLOR_YELLOW "WARNING: music file %s is not 22k stereo\n", filename ); } + #endif } /* diff --git a/code/client/snd_openal.c b/code/client/snd_openal.c index 516368a9..dc8f75bc 100644 --- a/code/client/snd_openal.c +++ b/code/client/snd_openal.c @@ -376,7 +376,12 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache) data = S_CodecLoad(curSfx->filename, &info); if(!data) { +#ifdef ELITEFORCE + S_AL_BufferUnload(sfx); + *knownSfx[sfx].filename = '\0'; +#else S_AL_BufferUseDefault(sfx); +#endif return; } @@ -481,7 +486,11 @@ qboolean S_AL_BufferInit( void ) numSfx = 0; // Load the default sound, and lock it +#ifdef ELITEFORCE + default_sfx = S_AL_BufferFind("sound/null.wav"); +#else default_sfx = S_AL_BufferFind("sound/feedback/hit.wav"); +#endif S_AL_BufferUse(default_sfx); knownSfx[default_sfx].isLocked = qtrue; @@ -529,6 +538,12 @@ sfxHandle_t S_AL_RegisterSound( const char *sample, qboolean compressed ) if((!knownSfx[sfx].inMemory) && (!knownSfx[sfx].isDefault)) S_AL_BufferLoad(sfx, s_alPrecache->integer); + +#ifdef ELITEFORCE + if(! *knownSfx[sfx].filename) + return 0; +#endif + knownSfx[sfx].lastUsedTime = Com_Milliseconds(); if (knownSfx[sfx].isDefault) { diff --git a/code/game/bg_public.h b/code/game/bg_public.h index f61dd4c1..172e3396 100644 --- a/code/game/bg_public.h +++ b/code/game/bg_public.h @@ -263,6 +263,11 @@ typedef enum { #define EF_AWARD_DENIED 0x00040000 // denied #define EF_TEAMVOTED 0x00080000 // already cast a team vote +#ifdef ELITEFORCE +#define EF_SHIELD_BOX_X 0x00000800 +#define EF_SHIELD_BOX_Y 0x00400000 +#endif + // NOTE: may not have more than 16 typedef enum { PW_NONE, diff --git a/code/game/g_local.h b/code/game/g_local.h index d2ff996c..a3d0fcd1 100644 --- a/code/game/g_local.h +++ b/code/game/g_local.h @@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // the "gameversion" client command will print this plus compile date #define GAMEVERSION BASEGAME +#endif #define BODY_QUEUE_SIZE 8 diff --git a/code/game/g_public.h b/code/game/g_public.h index f56a9e1c..b2e27c42 100644 --- a/code/game/g_public.h +++ b/code/game/g_public.h @@ -33,9 +33,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // TTimo // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=551 +#ifdef ELITEFORCE +#define SVF_SHIELD_BBOX 0x00000002 +#define SVF_CLIENTMASK 0x00000004 +#else #define SVF_CLIENTMASK 0x00000002 +#endif #define SVF_BOT 0x00000008 // set if the entity is a bot + +#ifdef ELITEFORCE +#define SVF_ELIMINATED 0x00000010 +#endif + #define SVF_BROADCAST 0x00000020 // send to all connected clients #define SVF_PORTAL 0x00000040 // merge a second pvs at origin2 into snapshots #define SVF_USE_CURRENT_ORIGIN 0x00000080 // entity->r.currentOrigin instead of entity->s.origin @@ -54,8 +64,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA typedef struct { +#ifndef ELITEFORCE entityState_t unused; // apparently this field was put here accidentally - // (and is kept only for compatibility, as a struct pad) +#endif qboolean linked; // qfalse if not in any good cluster int linkcount; @@ -104,6 +115,280 @@ typedef struct { // // system traps provided by the main engine // +#ifdef ELITEFORCE +typedef enum { + //============== general Quake services ================== + + G_PRINT, // ( const char *string ); + // print message on the local console + + G_ERROR, // ( const char *string ); + // abort the game + + G_MILLISECONDS, // ( void ); + // get current time for profiling reasons + // this should NOT be used for any game related tasks, + // because it is not journaled + + // console variable interaction + G_CVAR_REGISTER, // ( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags ); + G_CVAR_UPDATE, // ( vmCvar_t *vmCvar ); + G_CVAR_SET, // ( const char *var_name, const char *value ); + G_CVAR_VARIABLE_INTEGER_VALUE, // ( const char *var_name ); + + G_CVAR_VARIABLE_STRING_BUFFER, // ( const char *var_name, char *buffer, int bufsize ); + + G_ARGC, // ( void ); + // ClientCommand and ServerCommand parameter access + + G_ARGV, // ( int n, char *buffer, int bufferLength ); + + G_FS_FOPEN_FILE, // ( const char *qpath, fileHandle_t *file, fsMode_t mode ); + G_FS_READ, // ( void *buffer, int len, fileHandle_t f ); + G_FS_WRITE, // ( const void *buffer, int len, fileHandle_t f ); + G_FS_FCLOSE_FILE, // ( fileHandle_t f ); + + G_SEND_CONSOLE_COMMAND, // ( const char *text ); + // add commands to the console as if they were typed in + // for map changing, etc + + + //=========== server specific functionality ============= + + G_LOCATE_GAME_DATA, // ( gentity_t *gEnts, int numGEntities, int sizeofGEntity_t, + // playerState_t *clients, int sizeofGameClient ); + // the game needs to let the server system know where and how big the gentities + // are, so it can look at them directly without going through an interface + + G_DROP_CLIENT, // ( int clientNum, const char *reason ); + // kick a client off the server with a message + + G_SEND_SERVER_COMMAND, // ( int clientNum, const char *fmt, ... ); + // reliably sends a command string to be interpreted by the given + // client. If clientNum is -1, it will be sent to all clients + + G_SET_CONFIGSTRING, // ( int num, const char *string ); + // config strings hold all the index strings, and various other information + // that is reliably communicated to all clients + // All of the current configstrings are sent to clients when + // they connect, and changes are sent to all connected clients. + // All confgstrings are cleared at each level start. + + G_GET_CONFIGSTRING, // ( int num, char *buffer, int bufferSize ); + + G_GET_USERINFO, // ( int num, char *buffer, int bufferSize ); + // userinfo strings are maintained by the server system, so they + // are persistant across level loads, while all other game visible + // data is completely reset + + G_SET_USERINFO, // ( int num, const char *buffer ); + + G_GET_SERVERINFO, // ( char *buffer, int bufferSize ); + // the serverinfo info string has all the cvars visible to server browsers + + G_SET_BRUSH_MODEL, // ( gentity_t *ent, const char *name ); + // sets mins and maxs based on the brushmodel name + + G_TRACE, // ( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, + // collision detection against all linked entities + + G_POINT_CONTENTS, // ( const vec3_t point, int passEntityNum ); + // point contents against all linked entities + + G_IN_PVS, // ( const vec3_t p1, const vec3_t p2 ); + + G_IN_PVS_IGNORE_PORTALS, // ( const vec3_t p1, const vec3_t p2 ); + + G_ADJUST_AREA_PORTAL_STATE, // ( gentity_t *ent, qboolean open ); + + G_AREAS_CONNECTED, // ( int area1, int area2 ); + + G_LINKENTITY, // ( gentity_t *ent ); + // 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. + + G_UNLINKENTITY, // ( gentity_t *ent ); + // call before removing an interactive entity + + G_ENTITIES_IN_BOX, // ( const vec3_t mins, const vec3_t maxs, gentity_t **list, int maxcount ); + // EntitiesInBox will return brush models based on their bounding box, + // so exact determination must still be done with EntityContact + + G_ENTITY_CONTACT, // ( const vec3_t mins, const vec3_t maxs, const gentity_t *ent ); + // perform an exact check against inline brush models of non-square shape + + // access for bots to get and free a server client (FIXME?) + G_BOT_ALLOCATE_CLIENT, // ( void ); + + G_BOT_FREE_CLIENT, // ( int clientNum ); + + G_GET_USERCMD, // ( int clientNum, usercmd_t *cmd ) + + G_GET_ENTITY_TOKEN, // qboolean ( char *buffer, int bufferSize ) + // Retrieves the next string token from the entity spawn text, returning + // false when all tokens have been parsed. + // This should only be done at GAME_INIT time. + + G_FS_GETFILELIST, + G_DEBUG_POLYGON_CREATE, + G_DEBUG_POLYGON_DELETE, + + BOTLIB_SETUP = 200, // ( void ); + BOTLIB_SHUTDOWN, // ( void ); + BOTLIB_LIBVAR_SET, + BOTLIB_LIBVAR_GET, + BOTLIB_DEFINE, + BOTLIB_START_FRAME, + BOTLIB_LOAD_MAP, + BOTLIB_UPDATENTITY, + BOTLIB_TEST, + + BOTLIB_GET_SNAPSHOT_ENTITY, // ( int client, int ent ); + BOTLIB_GET_CONSOLE_MESSAGE, // ( int client, char *message, int size ); + BOTLIB_USER_COMMAND, // ( int client, usercmd_t *ucmd ); + + BOTLIB_AAS_ENTITY_VISIBLE = 300, //FIXME: remove + BOTLIB_AAS_IN_FIELD_OF_VISION, //FIXME: remove + BOTLIB_AAS_VISIBLE_CLIENTS, //FIXME: remove + BOTLIB_AAS_ENTITY_INFO, + + BOTLIB_AAS_INITIALIZED, + BOTLIB_AAS_PRESENCE_TYPE_BOUNDING_BOX, + BOTLIB_AAS_TIME, + + BOTLIB_AAS_POINT_AREA_NUM, + BOTLIB_AAS_TRACE_AREAS, + + BOTLIB_AAS_POINT_CONTENTS, + BOTLIB_AAS_NEXT_BSP_ENTITY, + BOTLIB_AAS_VALUE_FOR_BSP_EPAIR_KEY, + BOTLIB_AAS_VECTOR_FOR_BSP_EPAIR_KEY, + BOTLIB_AAS_FLOAT_FOR_BSP_EPAIR_KEY, + BOTLIB_AAS_INT_FOR_BSP_EPAIR_KEY, + + BOTLIB_AAS_AREA_REACHABILITY, + + BOTLIB_AAS_AREA_TRAVEL_TIME_TO_GOAL_AREA, + + BOTLIB_AAS_SWIMMING, + BOTLIB_AAS_PREDICT_CLIENT_MOVEMENT, + + + + BOTLIB_EA_SAY = 400, + BOTLIB_EA_SAY_TEAM, + BOTLIB_EA_USE_ITEM, + BOTLIB_EA_DROP_ITEM, + BOTLIB_EA_USE_INV, + BOTLIB_EA_DROP_INV, + BOTLIB_EA_GESTURE, + BOTLIB_EA_COMMAND, + + BOTLIB_EA_SELECT_WEAPON, + BOTLIB_EA_TALK, + BOTLIB_EA_ATTACK, + BOTLIB_EA_USE, + BOTLIB_EA_RESPAWN, + BOTLIB_EA_JUMP, + BOTLIB_EA_DELAYED_JUMP, + BOTLIB_EA_CROUCH, + BOTLIB_EA_MOVE_UP, + BOTLIB_EA_MOVE_DOWN, + BOTLIB_EA_MOVE_FORWARD, + BOTLIB_EA_MOVE_BACK, + BOTLIB_EA_MOVE_LEFT, + BOTLIB_EA_MOVE_RIGHT, + BOTLIB_EA_MOVE, + BOTLIB_EA_VIEW, + + BOTLIB_EA_END_REGULAR, + BOTLIB_EA_GET_INPUT, + BOTLIB_EA_RESET_INPUT, + BOTLIB_EA_ALT_ATTACK, + + + + BOTLIB_AI_LOAD_CHARACTER = 500, + BOTLIB_AI_FREE_CHARACTER, + BOTLIB_AI_CHARACTERISTIC_FLOAT, + BOTLIB_AI_CHARACTERISTIC_BFLOAT, + BOTLIB_AI_CHARACTERISTIC_INTEGER, + BOTLIB_AI_CHARACTERISTIC_BINTEGER, + BOTLIB_AI_CHARACTERISTIC_STRING, + + BOTLIB_AI_ALLOC_CHAT_STATE, + BOTLIB_AI_FREE_CHAT_STATE, + BOTLIB_AI_QUEUE_CONSOLE_MESSAGE, + BOTLIB_AI_REMOVE_CONSOLE_MESSAGE, + BOTLIB_AI_NEXT_CONSOLE_MESSAGE, + BOTLIB_AI_NUM_CONSOLE_MESSAGE, + BOTLIB_AI_INITIAL_CHAT, + BOTLIB_AI_REPLY_CHAT, + BOTLIB_AI_CHAT_LENGTH, + BOTLIB_AI_ENTER_CHAT, + BOTLIB_AI_STRING_CONTAINS, + BOTLIB_AI_FIND_MATCH, + BOTLIB_AI_MATCH_VARIABLE, + BOTLIB_AI_UNIFY_WHITE_SPACES, + BOTLIB_AI_REPLACE_SYNONYMS, + BOTLIB_AI_LOAD_CHAT_FILE, + BOTLIB_AI_SET_CHAT_GENDER, + BOTLIB_AI_SET_CHAT_NAME, + + BOTLIB_AI_RESET_GOAL_STATE, + BOTLIB_AI_RESET_AVOID_GOALS, + BOTLIB_AI_PUSH_GOAL, + BOTLIB_AI_POP_GOAL, + BOTLIB_AI_EMPTY_GOAL_STACK, + BOTLIB_AI_DUMP_AVOID_GOALS, + BOTLIB_AI_DUMP_GOAL_STACK, + BOTLIB_AI_GOAL_NAME, + BOTLIB_AI_GET_TOP_GOAL, + BOTLIB_AI_GET_SECOND_GOAL, + BOTLIB_AI_CHOOSE_LTG_ITEM, + BOTLIB_AI_CHOOSE_NBG_ITEM, + BOTLIB_AI_TOUCHING_GOAL, + BOTLIB_AI_ITEM_GOAL_IN_VIS_BUT_NOT_VISIBLE, + BOTLIB_AI_GET_LEVEL_ITEM_GOAL, + BOTLIB_AI_AVOID_GOAL_TIME, + BOTLIB_AI_INIT_LEVEL_ITEMS, + BOTLIB_AI_UPDATE_ENTITY_ITEMS, + BOTLIB_AI_LOAD_ITEM_WEIGHTS, + BOTLIB_AI_FREE_ITEM_WEIGHTS, + BOTLIB_AI_SAVE_GOAL_FUZZY_LOGIC, + BOTLIB_AI_ALLOC_GOAL_STATE, + BOTLIB_AI_FREE_GOAL_STATE, + + BOTLIB_AI_RESET_MOVE_STATE, + BOTLIB_AI_MOVE_TO_GOAL, + BOTLIB_AI_MOVE_IN_DIRECTION, + BOTLIB_AI_RESET_AVOID_REACH, + BOTLIB_AI_RESET_LAST_AVOID_REACH, + BOTLIB_AI_REACHABILITY_AREA, + BOTLIB_AI_MOVEMENT_VIEW_TARGET, + BOTLIB_AI_ALLOC_MOVE_STATE, + BOTLIB_AI_FREE_MOVE_STATE, + BOTLIB_AI_INIT_MOVE_STATE, + + BOTLIB_AI_CHOOSE_BEST_FIGHT_WEAPON, + BOTLIB_AI_GET_WEAPON_INFO, + BOTLIB_AI_LOAD_WEAPON_WEIGHTS, + BOTLIB_AI_ALLOC_WEAPON_STATE, + BOTLIB_AI_FREE_WEAPON_STATE, + BOTLIB_AI_RESET_WEAPON_STATE, + + BOTLIB_AI_GENETIC_PARENTS_AND_CHILD_SELECTION, + BOTLIB_AI_INTERBREED_GOAL_FUZZY_LOGIC, + BOTLIB_AI_MUTATE_GOAL_FUZZY_LOGIC, + BOTLIB_AI_GET_NEXT_CAMP_SPOT_GOAL, + BOTLIB_AI_GET_MAP_LOCATION_GOAL, + BOTLIB_AI_NUM_INITIAL_CHATS, + BOTLIB_AI_GET_CHAT_MESSAGE, + BOTLIB_AI_REMOVE_FROM_AVOID_GOALS, + BOTLIB_AI_PREDICT_VISIBLE_POSITION +} gameImport_t; +#else typedef enum { //============== general Quake services ================== @@ -390,7 +675,7 @@ typedef enum { BOTLIB_PC_SOURCE_FILE_AND_LINE } gameImport_t; - +#endif // // functions exported by the game subsystem diff --git a/code/qcommon/cm_local.h b/code/qcommon/cm_local.h index 5848fdc2..157e285a 100644 --- a/code/qcommon/cm_local.h +++ b/code/qcommon/cm_local.h @@ -24,10 +24,15 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "qcommon.h" #include "cm_polylib.h" -#define MAX_SUBMODELS 256 -#define BOX_MODEL_HANDLE 255 -#define CAPSULE_MODEL_HANDLE 254 - +#ifdef ELITEFORCE + #define MAX_SUBMODELS 8192 + #define BOX_MODEL_HANDLE MAX_SUBMODELS-1 + #define CAPSULE_MODEL_HANDLE BOX_MODEL_HANDLE-2 +#else + #define MAX_SUBMODELS 256 + #define BOX_MODEL_HANDLE 255 + #define CAPSULE_MODEL_HANDLE 254 +#endif typedef struct { cplane_t *plane; diff --git a/code/qcommon/cm_patch.h b/code/qcommon/cm_patch.h index f5ba8b8b..f9e0bac2 100644 --- a/code/qcommon/cm_patch.h +++ b/code/qcommon/cm_patch.h @@ -60,8 +60,8 @@ properly. */ -#define MAX_FACETS 1024 -#define MAX_PATCH_PLANES 2048 +#define MAX_FACETS 4096 +#define MAX_PATCH_PLANES 8192 typedef struct { float plane[4]; diff --git a/code/qcommon/cm_trace.c b/code/qcommon/cm_trace.c index a4ac80a5..fce053ac 100644 --- a/code/qcommon/cm_trace.c +++ b/code/qcommon/cm_trace.c @@ -1161,6 +1161,12 @@ void CM_Trace( trace_t *results, const vec3_t start, const vec3_t end, vec3_t mi // fill in a default trace Com_Memset( &tw, 0, sizeof(tw) ); tw.trace.fraction = 1; // assume it goes the entire distance until shown otherwise +#ifdef ELITEFORCE + // obviously Raven fucked this up. They seem to expect a SURF_NOIMPACT flag if the trace + // went through to the end, or the game will crash when firing the dreadnought weapon and + // it doesn't hit anything. + tw.trace.surfaceFlags = SURF_NOIMPACT; +#endif VectorCopy(origin, tw.modelOrigin); if (!cm.numNodes) { diff --git a/code/qcommon/common.c b/code/qcommon/common.c index 3f06c75b..b6343dc1 100644 --- a/code/qcommon/common.c +++ b/code/qcommon/common.c @@ -31,15 +31,24 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #endif +#ifdef ELITEFORCE int demo_protocols[] = +{ 0 }; +#else { 67, 66, 0 }; +#endif #define MAX_NUM_ARGVS 50 #define MIN_DEDICATED_COMHUNKMEGS 1 #define MIN_COMHUNKMEGS 56 #define DEF_COMHUNKMEGS 128 +#ifdef ELITEFORCE +#define DEF_COMZONEMEGS 32 +#else #define DEF_COMZONEMEGS 24 +#endif + #define DEF_COMHUNKMEGS_S XSTRING(DEF_COMHUNKMEGS) #define DEF_COMZONEMEGS_S XSTRING(DEF_COMZONEMEGS) @@ -73,6 +82,7 @@ cvar_t *com_version; cvar_t *com_blood; cvar_t *com_buildScript; // for automated data building scripts cvar_t *com_introPlayed; +cvar_t *com_novmcompat; // set to 1 to indicate VMs are run by the new engine. cvar_t *cl_paused; cvar_t *sv_paused; cvar_t *cl_packetdelay; @@ -2446,8 +2456,14 @@ void Com_ReadCDKey( const char *filename ) { fileHandle_t f; char buffer[33]; char fbuffer[MAX_OSPATH]; - +#ifdef ELITEFORCE + int index = 0; + char curchar; + + sprintf(fbuffer, "%s/efq3.key", filename); +#else Com_sprintf(fbuffer, sizeof(fbuffer), "%s/q3key", filename); +#endif FS_SV_FOpenFileRead( fbuffer, &f ); if ( !f ) { @@ -2457,14 +2473,68 @@ void Com_ReadCDKey( const char *filename ) { Com_Memset( buffer, 0, sizeof(buffer) ); +#ifdef ELITEFORCE + // check for the normal CD key + while(index < 16) + { + if(FS_Read(&curchar, 1, f) != 1) + { + Q_strncpyz( cl_cdkey, " ", 17 ); + FS_FCloseFile(f); + return; + } + + curchar = toupper(curchar); + + if(curchar < '0' || (curchar > '9' && curchar < 'A') || curchar > 'Z') + continue; + + buffer[index] = toupper(curchar); + + index++; + } + FS_FCloseFile(f); + + // check for the expansion pack cd key + sprintf(fbuffer, "%s/expefq3.key", filename); + FS_SV_FOpenFileRead(fbuffer, &f); + + if(f) + { + while(index < 32) + { + // same game + + if(FS_Read(&curchar, 1, f) != 1) + { + Q_strncpyz( cl_cdkey, " ", 17 ); + FS_FCloseFile(f); + return; + } + + curchar = toupper(curchar); + + if(curchar < '0' || (curchar > '9' && curchar < 'A') || curchar > 'Z') + continue; + + buffer[index] = toupper(curchar); + + index++; + } + FS_FCloseFile(f); + } + + Q_strncpyz(cl_cdkey, buffer, index+1); +#else FS_Read( buffer, 16, f ); FS_FCloseFile( f ); - + if (CL_CDKeyValidate(buffer, NULL)) { Q_strncpyz( cl_cdkey, buffer, 17 ); } else { Q_strncpyz( cl_cdkey, " ", 17 ); } +#endif } /* @@ -2506,20 +2576,30 @@ Com_WriteCDKey static void Com_WriteCDKey( const char *filename, const char *ikey ) { fileHandle_t f; char fbuffer[MAX_OSPATH]; +#ifdef ELITEFORCE + char key[23]; +#else char key[17]; +#endif #ifndef _WIN32 mode_t savedumask; #endif - +#ifdef ELITEFORCE + sprintf(fbuffer, "%s/efq3.key", filename); +#else Com_sprintf(fbuffer, sizeof(fbuffer), "%s/q3key", filename); +#endif - +#ifdef ELITEFORCE + Q_strncpyz( key, ikey, 23 ); + key[22] = '\0'; +#else Q_strncpyz( key, ikey, 17 ); - if(!CL_CDKeyValidate(key, NULL) ) { return; } +#endif #ifndef _WIN32 savedumask = umask(0077); @@ -2530,7 +2610,11 @@ static void Com_WriteCDKey( const char *filename, const char *ikey ) { goto out; } +#ifdef ELITEFORCE + FS_Write( key, strlen(key), f ); +#else FS_Write( key, 16, f ); +#endif FS_Printf( f, "\n// generated by quake, do not modify\r\n" ); FS_Printf( f, "// Do not give this file to ANYONE.\r\n" ); @@ -2755,6 +2839,7 @@ void Com_Init( char *commandLine ) { Cvar_Get("com_errorMessage", "", CVAR_ROM | CVAR_NORESTART); com_introPlayed = Cvar_Get( "com_introplayed", "0", CVAR_ARCHIVE); + com_novmcompat = Cvar_Get( "com_novmcompat", "1", CVAR_ROM); s = va("%s %s %s", Q3_VERSION, PLATFORM_STRING, __DATE__ ); com_version = Cvar_Get ("version", s, CVAR_ROM | CVAR_SERVERINFO ); @@ -2803,6 +2888,9 @@ void Com_Init( char *commandLine ) { // add + commands from command line if ( !Com_AddStartupCommands() ) { +#ifdef ELITEFORCE + Cvar_Set( com_introPlayed->name, "1" ); +#else // if the user didn't give any commands, run default action if ( !com_dedicated->integer ) { Cbuf_AddText ("cinematic idlogo.RoQ\n"); @@ -2811,6 +2899,7 @@ void Com_Init( char *commandLine ) { Cvar_Set( "nextmap", "cinematic intro.RoQ" ); } } +#endif } // start in full screen ui mode diff --git a/code/qcommon/files.c b/code/qcommon/files.c index eb51faa9..fc94cb1c 100644 --- a/code/qcommon/files.c +++ b/code/qcommon/files.c @@ -174,6 +174,15 @@ or configs will never get loaded from disk! // every time a new demo pk3 file is built, this checksum must be updated. // the easiest way to get it is to just run the game and see what it spits out +#ifdef ELITEFORCE +static const unsigned pak_checksums[] = +{ + 3376297517u, + 596947475u, + 3960871590u, + 1592359207u, +}; +#else #define DEMO_PAK0_CHECKSUM 2985612116u static const unsigned int pak_checksums[] = { 1566731103u, @@ -186,6 +195,7 @@ static const unsigned int pak_checksums[] = { 908855077u, 977125798u }; +#endif static const unsigned int missionpak_checksums[] = { @@ -3078,6 +3088,12 @@ qboolean FS_ComparePaks( char *neededpaks, int len, qboolean dlstring ) { havepak = qfalse; // never autodownload any of the id paks +#ifdef ELITEFORCE + #ifndef STANDALONE + if(FS_idPak(fs_serverReferencedPakNames[i], BASEGAME, NUM_ID_PAKS)) + continue; + #endif +#else if(FS_idPak(fs_serverReferencedPakNames[i], BASEGAME, NUM_ID_PAKS) #ifndef STANDALONE || FS_idPak(fs_serverReferencedPakNames[i], BASETA, NUM_TA_PAKS) @@ -3086,6 +3102,7 @@ qboolean FS_ComparePaks( char *neededpaks, int len, qboolean dlstring ) { { continue; } +#endif // Make sure the server cannot make us write to non-quake3 directories. if(FS_CheckDirTraversal(fs_serverReferencedPakNames[i])) @@ -3356,6 +3373,7 @@ static void FS_Startup( const char *gameName ) } #ifndef STANDALONE +#ifdef ELITEFORCE /* =================== FS_CheckPak0 @@ -3368,6 +3386,123 @@ Q3 media pak0.pk3, you'll want to remove this by defining STANDALONE in q_shared.h =================== */ + +static void FS_CheckPak0( void ) +{ + searchpath_t *path; + pack_t *curpack; + unsigned int foundPak = 0; + + for( path = fs_searchpaths; path; path = path->next ) + { + const char* pakBasename = path->pack->pakBasename; + + if(!path->pack) + continue; + + curpack = path->pack; + + if(!Q_stricmpn( curpack->pakGamename, BASEGAME, MAX_OSPATH ) + && strlen(pakBasename) == 4 && !Q_stricmpn( pakBasename, "pak", 3 ) + && pakBasename[3] >= '0' && pakBasename[3] <= '0' + NUM_ID_PAKS - 1) + { + if( curpack->checksum != pak_checksums[pakBasename[3]-'0'] ) + { + if(pakBasename[3] == '0') + { + + Com_Printf("\n\n" + "**************************************************\n" + "WARNING: " BASEGAME "/pak0.pk3 is present but its checksum (%u)\n" + "is not correct. Please re-copy pak0.pk3 from your\n" + "legitimate EF CDROM.\n" + "**************************************************\n\n\n", + curpack->checksum ); + } + else + { + Com_Printf("\n\n" + "**************************************************\n" + "WARNING: pak%d.pk3 is present but its checksum (%u)\n" + "is not correct. Please copy the .pk3 files from\n" + "Elite Force patches 1.1 and 1.2 to the baseEF directory.\n" + "**************************************************\n\n\n", + pakBasename[3]-'0', curpack->checksum ); + } + } + + foundPak |= 1<<(pakBasename[3]-'0'); + } + else + { + int index; + + // Finally check whether this pak's checksum is listed because the user tried + // to trick us by renaming the file, and set foundPak's highest bit to indicate this case. + + for(index = 0; index < ARRAY_LEN(pak_checksums); index++) + { + if(curpack->checksum == pak_checksums[index]) + { + Com_Printf("\n\n" + "**************************************************\n" + "WARNING: %s is renamed pak file %s%cpak%d.pk3\n" + "Running in standalone mode won't work\n" + "Please rename, or remove this file\n" + "**************************************************\n\n\n", + curpack->pakFilename, BASEGAME, PATH_SEP, index); + + + foundPak |= 0x80000000; + } + } + } + } + + if(!foundPak && Q_stricmp(com_basegame->string, BASEGAME)) + { + Cvar_Set("com_standalone", "1"); + } + else + Cvar_Set("com_standalone", "0"); + + if(!com_standalone->integer && (foundPak & 0x07) != 0x07) + { + char errorText[MAX_STRING_CHARS] = ""; + + if((foundPak & 0x01) != 0x01) + { + Q_strcat(errorText, sizeof(errorText), + "\"pak0.pk3\" is missing. Please copy it " + "from your legitimate EliteForce CDROM. "); + } + if((foundPak & 0x1fe) != 0x1fe) + { + Q_strcat(errorText, sizeof(errorText), + "Patch files are missing. Please\n" + "copy the .pk3 files from EliteForce patch 1.2 to baseEF.\n"); } + + Q_strcat(errorText, sizeof(errorText), + va("Also check that your EliteForce executable is in " + "the correct place and that every file " + "in the \"%s\" directory is present and readable", BASEGAME)); + + Com_Error(ERR_FATAL, "%s", errorText); + } +} + +#else + +/* +=================== +FS_CheckPak0 + +Checks that pak0.pk3 is present and its checksum is correct +Note: If you're building a game that doesn't depend on the +Q3 media pak0.pk3, you'll want to remove this function +=================== +*/ + static void FS_CheckPak0( void ) { searchpath_t *path; @@ -3399,6 +3534,7 @@ static void FS_CheckPak0( void ) { if(pakBasename[3] == '0') { + Com_Printf("\n\n" "**************************************************\n" "WARNING: " BASEGAME "/pak0.pk3 is present but its checksum (%u)\n" @@ -3515,7 +3651,6 @@ static void FS_CheckPak0( void ) "\"pak0.pk3\" is missing. Please copy it " "from your legitimate Q3 CDROM. "); } - if((foundPak & 0x1fe) != 0x1fe) { Q_strcat(errorText, sizeof(errorText), @@ -3553,6 +3688,7 @@ static void FS_CheckPak0( void ) } } #endif +#endif /* ===================== @@ -4091,6 +4227,7 @@ void FS_FilenameCompletion( const char *dir, const char *ext, callback( filename ); } FS_FreeFileList( filenames ); + } const char *FS_GetCurrentGameDir(void) diff --git a/code/qcommon/msg.c b/code/qcommon/msg.c index d946457c..f125e7cb 100644 --- a/code/qcommon/msg.c +++ b/code/qcommon/msg.c @@ -103,6 +103,15 @@ bit functions int overflows; +#ifdef ELITEFORCE +// Apparently, eliteforce only sends stuff like strings on 1 byte boundaries. +void MSG_RoundBits(msg_t *msg) +{ + if(msg->bit & 0x07) + msg->bit = ++msg->readcount << 3; +} +#endif + // negative bit values include signs void MSG_WriteBits( msg_t *msg, int value, int bits ) { int i; @@ -140,28 +149,59 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) { bits = -bits; } if (msg->oob) { - if(bits==8) +#ifdef ELITEFORCE + if(msg->compat) { - msg->data[msg->cursize] = value; - msg->cursize += 1; - msg->bit += 8; - } - else if(bits==16) - { - short temp = value; + int write, leftover, nbits = bits, location; - CopyLittleShort(&msg->data[msg->cursize], &temp); - msg->cursize += 2; - msg->bit += 16; + // make sure to set all non-used space in value to zero. + if(bits < 32) + value &= ((1 << bits) - 1); + + while(nbits) + { + leftover = msg->bit & 0x07; + write = 8 - leftover; + location = msg->bit >> 3; + + if(write > nbits) + write = nbits; + + msg->data[location] &= (1 << leftover) - 1; + msg->data[location] |= (value & ((1 << write) - 1)) << (leftover); + nbits -= write; + value >>= write; + msg->bit += write; + } + + msg->cursize = (msg->bit >> 3) + ((msg->bit & 0x07) ? 1 : 0); } - else if(bits==32) + else +#endif { - CopyLittleLong(&msg->data[msg->cursize], &value); - msg->cursize += 4; - msg->bit += 32; + if(bits==8) + { + msg->data[msg->cursize] = value; + msg->cursize += 1; + msg->bit += 8; + } + else if(bits==16) + { + short temp = value; + + CopyLittleShort(&msg->data[msg->cursize], &temp); + msg->cursize += 2; + msg->bit += 16; + } + else if(bits==32) + { + CopyLittleLong(&msg->data[msg->cursize], &value); + msg->cursize += 4; + msg->bit += 32; + } + else + Com_Error(ERR_DROP, "can't write %d bits", bits); } - else - Com_Error(ERR_DROP, "can't write %d bits", bits); } else { // fp = fopen("c:\\netchan.bin", "a"); value &= (0xffffffff>>(32-bits)); @@ -203,29 +243,53 @@ int MSG_ReadBits( msg_t *msg, int bits ) { } if (msg->oob) { - if(bits==8) + #ifdef ELITEFORCE + if(msg->compat) { - value = msg->data[msg->readcount]; - msg->readcount += 1; - msg->bit += 8; - } - else if(bits==16) - { - short temp; + nbits = 0; - CopyLittleShort(&temp, &msg->data[msg->readcount]); - value = temp; - msg->readcount += 2; - msg->bit += 16; - } - else if(bits==32) - { - CopyLittleLong(&value, &msg->data[msg->readcount]); - msg->readcount += 4; - msg->bit += 32; + while(nbits < bits) + { + i = msg->bit & 0x07; + get = 8 - i; + + if(get > bits - nbits) + get = bits - nbits; + + value |= ((msg->data[msg->bit >> 3] >> i) & ((1 << get) - 1)) << nbits; + msg->bit += get; + nbits += get; + } + + msg->readcount = (msg->bit >> 3) + ((msg->bit & 0x07) ? 1 : 0); } else - Com_Error(ERR_DROP, "can't read %d bits", bits); + #endif + { + if(bits==8) + { + value = msg->data[msg->readcount]; + msg->readcount += 1; + msg->bit += 8; + } + else if(bits==16) + { + short temp; + + CopyLittleShort(&temp, &msg->data[msg->readcount]); + value = temp; + msg->readcount += 2; + msg->bit += 16; + } + else if(bits==32) + { + CopyLittleLong(&value, &msg->data[msg->readcount]); + msg->readcount += 4; + msg->bit += 32; + } + else + Com_Error(ERR_DROP, "can't read %d bits", bits); + } } else { nbits = 0; if (bits&7) { @@ -256,7 +320,6 @@ int MSG_ReadBits( msg_t *msg, int bits ) { } - //================================================================================ // @@ -283,6 +346,16 @@ void MSG_WriteByte( msg_t *sb, int c ) { void MSG_WriteData( msg_t *buf, const void *data, int length ) { int i; + +#ifdef ELITEFORCE + if(buf->compat) + { + // Start writing on a whole-byte boundary + if(buf->bit & 0x07) + buf->bit = ++buf->cursize << 3; + } +#endif + for(i=0;i 127 || string[i] == '%' ) { string[i] = '.'; } } +#endif MSG_WriteData (sb, string, l+1); } @@ -337,7 +416,11 @@ void MSG_WriteBigString( msg_t *sb, const char *s ) { if ( !s ) { MSG_WriteData (sb, "", 1); } else { +#ifdef ELITEFORCE + int l; +#else int l,i; +#endif char string[BIG_INFO_STRING]; l = strlen( s ); @@ -348,12 +431,14 @@ void MSG_WriteBigString( msg_t *sb, const char *s ) { } Q_strncpyz( string, s, sizeof( string ) ); +#ifndef ELITEFORCE // get rid of 0x80+ and '%' chars, because old clients don't like them for ( i = 0 ; i < l ; i++ ) { if ( ((byte *)string)[i] > 127 || string[i] == '%' ) { string[i] = '.'; } } +#endif MSG_WriteData (sb, string, l+1); } @@ -444,6 +529,11 @@ char *MSG_ReadString( msg_t *msg ) { static char string[MAX_STRING_CHARS]; int l,c; +#ifdef ELITEFORCE + if(msg->compat) + MSG_RoundBits(msg); +#endif + l = 0; do { c = MSG_ReadByte(msg); // use ReadByte so -1 is out of bounds @@ -454,11 +544,12 @@ char *MSG_ReadString( msg_t *msg ) { if ( c == '%' ) { c = '.'; } +#ifndef ELITEFORCE // don't allow higher ascii values if ( c > 127 ) { c = '.'; } - +#endif string[l] = c; l++; } while (l < sizeof(string)-1); @@ -472,6 +563,12 @@ char *MSG_ReadBigString( msg_t *msg ) { static char string[BIG_INFO_STRING]; int l,c; +#ifdef ELITEFORCE + if(msg->compat) + MSG_RoundBits(msg); +#endif + + l = 0; do { c = MSG_ReadByte(msg); // use ReadByte so -1 is out of bounds @@ -482,10 +579,12 @@ char *MSG_ReadBigString( msg_t *msg ) { if ( c == '%' ) { c = '.'; } +#ifndef ELITEFORCE // don't allow higher ascii values if ( c > 127 ) { c = '.'; } +#endif string[l] = c; l++; @@ -500,6 +599,11 @@ char *MSG_ReadStringLine( msg_t *msg ) { static char string[MAX_STRING_CHARS]; int l,c; +#ifdef ELITEFORCE + if(msg->compat) + MSG_RoundBits(msg); +#endif + l = 0; do { c = MSG_ReadByte(msg); // use ReadByte so -1 is out of bounds @@ -510,11 +614,12 @@ char *MSG_ReadStringLine( msg_t *msg ) { if ( c == '%' ) { c = '.'; } +#ifndef ELITEFORCE // don't allow higher ascii values if ( c > 127 ) { c = '.'; } - +#endif string[l] = c; l++; } while (l < sizeof(string)-1); @@ -531,6 +636,11 @@ float MSG_ReadAngle16( msg_t *msg ) { void MSG_ReadData( msg_t *msg, void *data, int len ) { int i; +#ifdef ELITEFORCE + if(msg->compat) + MSG_RoundBits(msg); +#endif + for (i=0 ; iforwardmove, to->forwardmove, 8 ); MSG_WriteDelta( msg, from->rightmove, to->rightmove, 8 ); MSG_WriteDelta( msg, from->upmove, to->upmove, 8 ); +#ifdef ELITEFORCE + MSG_WriteDelta( msg, from->buttons, to->buttons, 8 ); +#else MSG_WriteDelta( msg, from->buttons, to->buttons, 16 ); +#endif MSG_WriteDelta( msg, from->weapon, to->weapon, 8 ); } @@ -713,13 +827,22 @@ void MSG_ReadDeltaUsercmd( msg_t *msg, usercmd_t *from, usercmd_t *to ) { to->upmove = MSG_ReadDelta( msg, from->upmove, 8); if( to->upmove == -128 ) to->upmove = -127; + +#ifdef ELITEFORCE + to->buttons = MSG_ReadDelta( msg, from->buttons, 8); +#else to->buttons = MSG_ReadDelta( msg, from->buttons, 16); +#endif to->weapon = MSG_ReadDelta( msg, from->weapon, 8); } /* ===================== +<<<<<<< Updated upstream MSG_WriteDeltaUsercmd +======= +MSG_WriteDeltaUsercmdKey +>>>>>>> Stashed changes ===================== */ void MSG_WriteDeltaUsercmdKey( msg_t *msg, int key, usercmd_t *from, usercmd_t *to ) { @@ -750,7 +873,11 @@ void MSG_WriteDeltaUsercmdKey( msg_t *msg, int key, usercmd_t *from, usercmd_t * MSG_WriteDeltaKey( msg, key, from->forwardmove, to->forwardmove, 8 ); MSG_WriteDeltaKey( msg, key, from->rightmove, to->rightmove, 8 ); MSG_WriteDeltaKey( msg, key, from->upmove, to->upmove, 8 ); +#ifdef ELITEFORCE + MSG_WriteDeltaKey( msg, key, from->buttons, to->buttons, 8 ); +#else MSG_WriteDeltaKey( msg, key, from->buttons, to->buttons, 16 ); +#endif MSG_WriteDeltaKey( msg, key, from->weapon, to->weapon, 8 ); } @@ -780,7 +907,12 @@ void MSG_ReadDeltaUsercmdKey( msg_t *msg, int key, usercmd_t *from, usercmd_t *t to->upmove = MSG_ReadDeltaKey( msg, key, from->upmove, 8); if( to->upmove == -128 ) to->upmove = -127; + +#ifdef ELITEFORCE + to->buttons = MSG_ReadDeltaKey( msg, key, from->buttons, 8); +#else to->buttons = MSG_ReadDeltaKey( msg, key, from->buttons, 16); +#endif to->weapon = MSG_ReadDeltaKey( msg, key, from->weapon, 8); } else { to->angles[0] = from->angles[0]; @@ -802,6 +934,48 @@ entityState_t communication ============================================================================= */ +#ifdef ELITEFORCE +#define PVECTOR_BITS 5 // amount of bits we need to reference all predefined vectors. +#define PVECTOR_BYTES 8 // length of predefined vector. +#define PVECTOR_NUM (1 << PVECTOR_BITS) - 1 // number of existing predefined vectors. + +byte pVectors[PVECTOR_NUM][PVECTOR_BYTES] = +{ + {0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x20, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x60, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x60, 0x80, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00}, + {0x60, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00}, + {0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xe0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x60, 0xc0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}, + {0x60, 0xc0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00}, + {0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x60, 0xc0, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00}, + {0x60, 0xc0, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00}, + {0x60, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00}, + {0x60, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00}, + {0xe1, 0x00, 0xc0, 0x01, 0x90, 0x00, 0x00, 0x00}, + {0xed, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00}, + {0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}, + {0x62, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}, + {0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00}, + {0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}, +}; + +#endif + /* ================= MSG_ReportChangeVectors_f @@ -827,6 +1001,61 @@ typedef struct { // using the stringizing operator to save typing... #define NETF(x) #x,(size_t)&((entityState_t*)0)->x +#ifdef ELITEFORCE +netField_t entityStateFields[] = +{ +{ NETF(eType), 8 }, +{ NETF(eFlags), 24 }, +{ NETF(pos.trType), 8 }, +{ NETF(pos.trTime), 32 }, +{ NETF(pos.trDuration), 32 }, +{ NETF(pos.trBase[0]), 0 }, +{ NETF(pos.trBase[1]), 0 }, +{ NETF(pos.trBase[2]), 0 }, +{ NETF(pos.trDelta[0]), 0 }, +{ NETF(pos.trDelta[1]), 0 }, +{ NETF(pos.trDelta[2]), 0 }, +{ NETF(apos.trType), 8 }, +{ NETF(apos.trTime), 32 }, +{ NETF(apos.trDuration), 32 }, +{ NETF(apos.trBase[0]), 0 }, +{ NETF(apos.trBase[1]), 0 }, +{ NETF(apos.trBase[2]), 0 }, +{ NETF(apos.trDelta[0]), 0 }, +{ NETF(apos.trDelta[1]), 0 }, +{ NETF(apos.trDelta[2]), 0 }, +{ NETF(time), 32 }, +{ NETF(time2), 32 }, +{ NETF(origin[0]), 0 }, +{ NETF(origin[1]), 0 }, +{ NETF(origin[2]), 0 }, +{ NETF(origin2[0]), 0 }, +{ NETF(origin2[1]), 0 }, +{ NETF(origin2[2]), 0 }, +{ NETF(angles[0]), 0 }, +{ NETF(angles[1]), 0 }, +{ NETF(angles[2]), 0 }, +{ NETF(angles2[0]), 0 }, +{ NETF(angles2[1]), 0 }, +{ NETF(angles2[2]), 0 }, +{ NETF(otherEntityNum), GENTITYNUM_BITS }, +{ NETF(otherEntityNum2), GENTITYNUM_BITS }, +{ NETF(groundEntityNum), GENTITYNUM_BITS }, +{ NETF(loopSound), 16 }, +{ NETF(constantLight), 32 }, +{ NETF(modelindex), 8 }, +{ NETF(modelindex2), 8 }, +{ NETF(frame), 16 }, +{ NETF(clientNum), 8 }, +{ NETF(solid), 24 }, +{ NETF(event), 10 }, +{ NETF(eventParm), 8 }, +{ NETF(powerups), 16 }, +{ NETF(weapon), 8 }, +{ NETF(legsAnim), 8 }, +{ NETF(torsoAnim), 8 }, +}; +#else netField_t entityStateFields[] = { { NETF(pos.trTime), 32 }, @@ -846,7 +1075,7 @@ netField_t entityStateFields[] = { NETF(legsAnim), 8 }, { NETF(groundEntityNum), GENTITYNUM_BITS }, { NETF(pos.trType), 8 }, -{ NETF(eFlags), 19 }, +{ NETF(eFlags), 27 }, { NETF(otherEntityNum), GENTITYNUM_BITS }, { NETF(weapon), 8 }, { NETF(clientNum), 8 }, @@ -881,7 +1110,7 @@ netField_t entityStateFields[] = { NETF(constantLight), 32 }, { NETF(frame), 16 } }; - +#endif // if (int)f == f and (int)f + ( 1<<(FLOAT_INT_BITS-1) ) < ( 1 << FLOAT_INT_BITS ) // the float will be sent with FLOAT_INT_BITS, otherwise all 32 bits will be sent @@ -907,6 +1136,10 @@ void MSG_WriteDeltaEntity( msg_t *msg, struct entityState_s *from, struct entity int trunc; float fullFloat; int *fromF, *toF; +#ifdef ELITEFORCE + byte vector[PVECTOR_BYTES]; + int vectorIndex = -1; +#endif numFields = ARRAY_LEN( entityStateFields ); @@ -930,17 +1163,33 @@ void MSG_WriteDeltaEntity( msg_t *msg, struct entityState_s *from, struct entity Com_Error (ERR_FATAL, "MSG_WriteDeltaEntity: Bad entity number: %i", to->number ); } + #ifdef ELITEFORCE + if(msg->compat) + Com_Memset(vector, 0, sizeof(vector)); + #endif + lc = 0; // build the change vector as bytes so it is endien independent for ( i = 0, field = entityStateFields ; i < numFields ; i++, field++ ) { fromF = (int *)( (byte *)from + field->offset ); toF = (int *)( (byte *)to + field->offset ); if ( *fromF != *toF ) { - lc = i+1; + #ifdef ELITEFORCE + if(msg->compat) + vector[i >> 3] |= 1 << (i & 0x07); + else + #endif + lc = i+1; } } - if ( lc == 0 ) { + #ifdef ELITEFORCE + if((msg->compat && !((int *) vector)[0] && !((int *) vector)[1]) || (!msg->compat && !lc)) + { + #else + if ( lc == 0 ) + { + #endif // nothing at all changed if ( !force ) { return; // nothing at all @@ -952,35 +1201,87 @@ void MSG_WriteDeltaEntity( msg_t *msg, struct entityState_s *from, struct entity return; } + #ifdef ELITEFORCE + if(msg->compat) + { + for (i = 0; i < PVECTOR_NUM; i++) + { + if( ((int *) vector)[0] == ((int *)pVectors[i])[0] && + ((int *) vector)[1] == ((int *)pVectors[i])[1] + ) + { + vectorIndex = i; + break; + } + } + } + #endif + MSG_WriteBits( msg, to->number, GENTITYNUM_BITS ); MSG_WriteBits( msg, 0, 1 ); // not removed MSG_WriteBits( msg, 1, 1 ); // we have a delta - MSG_WriteByte( msg, lc ); // # of changes +#ifdef ELITEFORCE + if(msg->compat) + { + MSG_WriteBits(msg, vectorIndex, PVECTOR_BITS); + + if (vectorIndex < 0) + { + for ( i = 0 ; i + 8 <= numFields ; i += 8 ) + MSG_WriteByte( msg, vector[i >> 3] ); + if ( numFields & 7 ) + MSG_WriteBits( msg, vector[i >> 3], numFields & 7 ); + } + + } + else +#endif + MSG_WriteByte( msg, lc ); // # of changes oldsize += numFields; +#ifdef ELITEFORCE + for ( i = 0, field = entityStateFields ; msg->compat ? (i < numFields) : (i < lc) ; i++, field++ ) { +#else for ( i = 0, field = entityStateFields ; i < lc ; i++, field++ ) { +#endif fromF = (int *)( (byte *)from + field->offset ); toF = (int *)( (byte *)to + field->offset ); if ( *fromF == *toF ) { - MSG_WriteBits( msg, 0, 1 ); // no change + + #ifdef ELITEFORCE + if(!msg->compat) + #endif + MSG_WriteBits( msg, 0, 1 ); // no change continue; } - MSG_WriteBits( msg, 1, 1 ); // changed + #ifdef ELITEFORCE + if(!msg->compat) + #endif + MSG_WriteBits( msg, 1, 1 ); // changed if ( field->bits == 0 ) { // float fullFloat = *(float *)toF; trunc = (int)fullFloat; - if (fullFloat == 0.0f) { - MSG_WriteBits( msg, 0, 1 ); - oldsize += FLOAT_INT_BITS; +#ifdef ELITEFORCE + if(!msg->compat && fullFloat == 0.0f) +#else + if (fullFloat == 0.0f) +#endif + { + MSG_WriteBits( msg, 0, 1 ); + oldsize += FLOAT_INT_BITS; } else { - MSG_WriteBits( msg, 1, 1 ); + #ifdef ELITEFORCE + if(!msg->compat) + #endif + MSG_WriteBits( msg, 1, 1 ); + if ( trunc == fullFloat && trunc + FLOAT_INT_BIAS >= 0 && trunc + FLOAT_INT_BIAS < ( 1 << FLOAT_INT_BITS ) ) { // send as small integer @@ -993,13 +1294,23 @@ void MSG_WriteDeltaEntity( msg_t *msg, struct entityState_s *from, struct entity } } } else { - if (*toF == 0) { - MSG_WriteBits( msg, 0, 1 ); - } else { - MSG_WriteBits( msg, 1, 1 ); - // integer - MSG_WriteBits( msg, *toF, field->bits ); + #ifdef ELITEFORCE + if(msg->compat) + MSG_WriteBits(msg, *toF, field->bits); + else + { + #endif + if (*toF == 0) + MSG_WriteBits( msg, 0, 1 ); + else + { + MSG_WriteBits( msg, 1, 1 ); + // integer + MSG_WriteBits( msg, *toF, field->bits ); + } + #ifdef ELITEFORCE } + #endif } } } @@ -1018,13 +1329,18 @@ Can go from either a baseline or a previous packet_entity */ void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to, int number) { - int i, lc; + int i, lc = 0; int numFields; netField_t *field; int *fromF, *toF; int print; int trunc; int startBit, endBit; +#ifdef ELITEFORCE + int vectorIndex; + byte vector_space[PVECTOR_BYTES]; + byte *vector = vector_space; +#endif if ( number < 0 || number >= MAX_GENTITIES) { Com_Error( ERR_DROP, "Bad delta entity number: %i", number ); @@ -1054,7 +1370,10 @@ void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to, } numFields = ARRAY_LEN( entityStateFields ); - lc = MSG_ReadByte(msg); + #ifdef ELITEFORCE + if(!msg->compat) + #endif + lc = MSG_ReadByte(msg); if ( lc > numFields || lc < 0 ) { Com_Error( ERR_DROP, "invalid entityState field count" ); @@ -1071,19 +1390,48 @@ void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to, to->number = number; +#ifdef ELITEFORCE + if(msg->compat) + { + // Read in the vector index and check whether there is a predefined one or not. + vectorIndex = MSG_ReadBits( msg, PVECTOR_BITS ); + + if (vectorIndex == PVECTOR_NUM) + { + for (i = 0; i + 8 < numFields; i += 8) + vector[i >> 3] = MSG_ReadByte(msg); + if (numFields & 7) + vector[i>>3] = MSG_ReadBits( msg, numFields & 7 ); + } + else + vector = pVectors[vectorIndex]; + } + + for ( i = 0, field = entityStateFields ; msg->compat ? (i < numFields) : (i < lc) ; i++, field++ ) { +#else for ( i = 0, field = entityStateFields ; i < lc ; i++, field++ ) { +#endif fromF = (int *)( (byte *)from + field->offset ); toF = (int *)( (byte *)to + field->offset ); - if ( ! MSG_ReadBits( msg, 1 ) ) { + #ifdef ELITEFORCE + if((msg->compat && ! (vector[i >> 3] & (1 << (i & 7)) )) || (!msg->compat && !MSG_ReadBits(msg, 1))) + #else + if ( ! MSG_ReadBits( msg, 1 ) ) + #endif + { // no change *toF = *fromF; } else { if ( field->bits == 0 ) { // float - if ( MSG_ReadBits( msg, 1 ) == 0 ) { +#ifdef ELITEFORCE + if(!msg->compat && !MSG_ReadBits( msg, 1 )) +#else + if ( MSG_ReadBits( msg, 1 ) == 0 ) +#endif *(float *)toF = 0.0f; - } else { + else { if ( MSG_ReadBits( msg, 1 ) == 0 ) { // integral float trunc = MSG_ReadBits( msg, FLOAT_INT_BITS ); @@ -1102,9 +1450,13 @@ void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to, } } } else { - if ( MSG_ReadBits( msg, 1 ) == 0 ) { + #ifdef ELITEFORCE + if(!msg->compat && !MSG_ReadBits(msg, 1)) + #else + if ( MSG_ReadBits( msg, 1 ) == 0 ) + #endif *toF = 0; - } else { + else { // integer *toF = MSG_ReadBits( msg, field->bits ); if ( print ) { @@ -1115,12 +1467,19 @@ void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to, // pcount[i]++; } } - for ( i = lc, field = &entityStateFields[lc] ; i < numFields ; i++, field++ ) { - fromF = (int *)( (byte *)from + field->offset ); - toF = (int *)( (byte *)to + field->offset ); - // no change - *toF = *fromF; + #ifdef ELITEFORCE + if(!msg->compat) + { + #endif + for ( i = lc, field = &entityStateFields[lc] ; i < numFields ; i++, field++ ) { + fromF = (int *)( (byte *)from + field->offset ); + toF = (int *)( (byte *)to + field->offset ); + // no change + *toF = *fromF; + } + #ifdef ELITEFORCE } + #endif if ( print ) { if ( msg->bit == 0 ) { @@ -1144,6 +1503,59 @@ plyer_state_t communication // using the stringizing operator to save typing... #define PSF(x) #x,(size_t)&((playerState_t*)0)->x +#ifdef ELITEFORCE +netField_t playerStateFields[] = +{ +{ PSF(commandTime), 32 }, +{ PSF(pm_type), 8 }, +{ PSF(bobCycle), 8 }, +{ PSF(pm_flags), 16 }, +{ PSF(pm_time), -16 }, +{ PSF(origin[0]), 0 }, +{ PSF(origin[1]), 0 }, +{ PSF(origin[2]), 0 }, +{ PSF(velocity[0]), 0 }, +{ PSF(velocity[1]), 0 }, +{ PSF(velocity[2]), 0 }, +{ PSF(weaponTime), -16 }, +{ PSF(gravity), 16 }, +{ PSF(speed), 16 }, +{ PSF(delta_angles[0]), 16 }, +{ PSF(delta_angles[1]), 16 }, +{ PSF(delta_angles[2]), 16 }, +{ PSF(groundEntityNum), GENTITYNUM_BITS }, +{ PSF(legsTimer), 8 }, +{ PSF(torsoTimer), 12 }, +{ PSF(legsAnim), 8 }, +{ PSF(torsoAnim), 8 }, +{ PSF(movementDir), 4 }, +{ PSF(eFlags), 16 }, +{ PSF(eventSequence), 16 }, +{ PSF(events[0]), 8 }, +{ PSF(events[1]), 8 }, +{ PSF(events[2]), 8 }, +{ PSF(events[3]), 8 }, +{ PSF(eventParms[0]), 8 }, +{ PSF(eventParms[1]), 8 }, +{ PSF(eventParms[2]), 8 }, +{ PSF(eventParms[3]), 8 }, +{ PSF(externalEvent), 10 }, +{ PSF(externalEventParm), 8 }, +{ PSF(clientNum), 8 }, +{ PSF(weapon), 5 }, +{ PSF(weaponstate), 4 }, +{ PSF(viewangles[0]), 0 }, +{ PSF(viewangles[1]), 0 }, +{ PSF(viewangles[2]), 0 }, +{ PSF(viewheight), -8 }, +{ PSF(damageEvent), 8 }, +{ PSF(damageYaw), 8 }, +{ PSF(damagePitch), 8 }, +{ PSF(damageCount), 8 }, +{ PSF(damageShieldCount), 8 }, +{ PSF(introTime), 32}, +}; +#else netField_t playerStateFields[] = { { PSF(commandTime), 32 }, @@ -1195,7 +1607,7 @@ netField_t playerStateFields[] = { PSF(jumppad_ent), GENTITYNUM_BITS }, { PSF(loopSound), 16 } }; - +#endif /* ============= MSG_WriteDeltaPlayerstate @@ -1213,7 +1625,7 @@ void MSG_WriteDeltaPlayerstate( msg_t *msg, struct playerState_s *from, struct p netField_t *field; int *fromF, *toF; float fullFloat; - int trunc, lc; + int trunc, lc = 0; if (!from) { from = &dummy; @@ -1222,20 +1634,33 @@ void MSG_WriteDeltaPlayerstate( msg_t *msg, struct playerState_s *from, struct p numFields = ARRAY_LEN( playerStateFields ); - lc = 0; - for ( i = 0, field = playerStateFields ; i < numFields ; i++, field++ ) { - fromF = (int *)( (byte *)from + field->offset ); - toF = (int *)( (byte *)to + field->offset ); - if ( *fromF != *toF ) { - lc = i+1; + #ifdef ELITEFORCE + if(!msg->compat) + { + #endif + lc = 0; + for ( i = 0, field = playerStateFields ; i < numFields ; i++, field++ ) { + fromF = (int *)( (byte *)from + field->offset ); + toF = (int *)( (byte *)to + field->offset ); + if ( *fromF != *toF ) { + lc = i+1; + } } + + MSG_WriteByte( msg, lc ); // # of changes + + #ifdef ELITEFORCE } - - MSG_WriteByte( msg, lc ); // # of changes - + #endif + oldsize += numFields - lc; - for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ ) { + #ifdef ELITEFORCE + for ( i = 0, field = playerStateFields ; msg->compat ? (i < numFields) : (i < lc) ; i++, field++ ) + #else + for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ ) + #endif + { fromF = (int *)( (byte *)from + field->offset ); toF = (int *)( (byte *)to + field->offset ); @@ -1297,12 +1722,21 @@ void MSG_WriteDeltaPlayerstate( msg_t *msg, struct playerState_s *from, struct p } } - if (!statsbits && !persistantbits && !ammobits && !powerupbits) { + #ifdef ELITEFORCE + if (!msg->compat && !statsbits && !persistantbits && !ammobits && !powerupbits) + #else + if (!statsbits && !persistantbits && !ammobits && !powerupbits) + #endif + { MSG_WriteBits( msg, 0, 1 ); // no change oldsize += 4; return; } - MSG_WriteBits( msg, 1, 1 ); // changed + + #ifdef ELITEFORCE + if(!msg->compat) + #endif + MSG_WriteBits( msg, 1, 1 ); // changed if ( statsbits ) { MSG_WriteBits( msg, 1, 1 ); // changed @@ -1355,7 +1789,7 @@ MSG_ReadDeltaPlayerstate =================== */ void MSG_ReadDeltaPlayerstate (msg_t *msg, playerState_t *from, playerState_t *to ) { - int i, lc; + int i, lc = 0; int bits; netField_t *field; int numFields; @@ -1387,10 +1821,17 @@ void MSG_ReadDeltaPlayerstate (msg_t *msg, playerState_t *from, playerState_t *t } numFields = ARRAY_LEN( playerStateFields ); - lc = MSG_ReadByte(msg); - if ( lc > numFields || lc < 0 ) { - Com_Error( ERR_DROP, "invalid playerState field count" ); + #ifdef ELITEFORCE + if(msg->compat) + lc = numFields; + else + #endif + { + lc = MSG_ReadByte(msg); + + if(lc > numFields || lc < 0) + Com_Error(ERR_DROP, "invalid entityState field count"); } for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ ) { @@ -1428,16 +1869,27 @@ void MSG_ReadDeltaPlayerstate (msg_t *msg, playerState_t *from, playerState_t *t } } } - for ( i=lc,field = &playerStateFields[lc];ioffset ); - toF = (int *)( (byte *)to + field->offset ); - // no change - *toF = *fromF; + #ifdef ELITEFORCE + if(!msg->compat) + { + #endif + for ( i=lc,field = &playerStateFields[lc];ioffset ); + toF = (int *)( (byte *)to + field->offset ); + // no change + *toF = *fromF; + } + #ifdef ELITEFORCE } - - + #endif + // read the arrays - if (MSG_ReadBits( msg, 1 ) ) { +#ifdef ELITEFORCE + if(msg->compat || MSG_ReadBits( msg, 1 )) +#else + if (MSG_ReadBits( msg, 1 ) ) +#endif + { // parse stats if ( MSG_ReadBits( msg, 1 ) ) { LOG("PS_STATS"); diff --git a/code/qcommon/net_chan.c b/code/qcommon/net_chan.c index 0b099b95..08792633 100644 --- a/code/qcommon/net_chan.c +++ b/code/qcommon/net_chan.c @@ -99,6 +99,102 @@ void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int #endif } +#ifdef ELITEFORCE +/* +============== +Netchan_ScramblePacket + +A probably futile attempt to make proxy hacking somewhat +more difficult. +============== +*/ +#define SCRAMBLE_START 6 +static void Netchan_ScramblePacket( msg_t *buf ) { + unsigned seed; + int i, j, c, mask, temp; + int seq[MAX_PACKETLEN]; + + seed = ( LittleLong( *(unsigned *)buf->data ) * 3 ) ^ ( buf->cursize * 123 ) ^ 0x87243987; + c = buf->cursize; + if ( c <= SCRAMBLE_START ) { + return; + } + if ( c > MAX_PACKETLEN ) { + Com_Error( ERR_DROP, "MAX_PACKETLEN" ); + } + + // generate a sequence of "random" numbers + for (i = 0 ; i < c ; i++) { + seed = (69069 * seed + 1); + seq[i] = seed; + } + + // byte xor the data after the header + for (i = SCRAMBLE_START ; i < c ; i++) { + buf->data[i] ^= seq[i]; + } + + // transpose each character + for ( mask = 1 ; mask < c-SCRAMBLE_START ; mask = ( mask << 1 ) + 1 ) { + } + mask >>= 1; + for (i = SCRAMBLE_START ; i < c ; i++) { + j = SCRAMBLE_START + ( seq[i] & mask ); + temp = buf->data[j]; + buf->data[j] = buf->data[i]; + buf->data[i] = temp; + } + + // byte xor the data after the header +// for (i = SCRAMBLE_START ; i < c ; i++) { +// buf->data[i] ^= seq[i]; +// } +} + +static void Netchan_UnScramblePacket( msg_t *buf ) { + unsigned seed; + int i, j, c, mask, temp; + int seq[MAX_PACKETLEN]; + + seed = ( LittleLong( *(unsigned *)buf->data ) * 3 ) ^ ( buf->cursize * 123 ) ^ 0x87243987; + c = buf->cursize; + if ( c <= SCRAMBLE_START ) { + return; + } + if ( c > MAX_PACKETLEN ) { + Com_Error( ERR_DROP, "MAX_PACKETLEN" ); + } + + // generate a sequence of "random" numbers + for (i = 0 ; i < c ; i++) { + seed = (69069 * seed + 1); + seq[i] = seed; + } + + // byte xor the data after the header +// for (i = SCRAMBLE_START ; i < c ; i++) { +// buf->data[i] ^= seq[i]; +// } + + // transpose each character in reverse order + for ( mask = 1 ; mask < c-SCRAMBLE_START ; mask = ( mask << 1 ) + 1 ) { + } + mask >>= 1; + for (i = c-1 ; i >= SCRAMBLE_START ; i--) { + j = SCRAMBLE_START + ( seq[i] & mask ); + temp = buf->data[j]; + buf->data[j] = buf->data[i]; + buf->data[i] = temp; + } + + + // byte xor the data after the header + for (i = SCRAMBLE_START ; i < c ; i++) { + buf->data[i] ^= seq[i]; + } +} +#endif + /* ================= Netchan_TransmitNextFragment @@ -138,6 +234,14 @@ void Netchan_TransmitNextFragment( netchan_t *chan ) { MSG_WriteShort( &send, fragmentLength ); MSG_WriteData( &send, chan->unsentBuffer + chan->unsentFragmentStart, fragmentLength ); + #ifdef ELITEFORCE + if(chan->compat) + { + // the original eliteforce uses the old scrambling routines only slightly modified. + Netchan_ScramblePacket( &send ); + } + #endif + // send the datagram NET_SendPacket(chan->sock, send.cursize, send.data, chan->remoteAddress); @@ -213,6 +317,14 @@ void Netchan_Transmit( netchan_t *chan, int length, const byte *data ) { MSG_WriteData( &send, data, length ); + #ifdef ELITEFORCE + if(chan->compat) + { + // the original eliteforce uses the old scrambling routines only slightly modified. + Netchan_ScramblePacket( &send ); + } + #endif + // send the datagram NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress ); @@ -247,7 +359,10 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) { qboolean fragmented; // XOR unscramble all data in the packet after the header -// Netchan_UnScramblePacket( msg ); +#ifdef ELITEFORCE + if(chan->compat) + Netchan_UnScramblePacket( msg ); +#endif // get sequence numbers MSG_BeginReadingOOB( msg ); @@ -394,7 +509,10 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) { // TTimo // clients were not acking fragmented messages - chan->incomingSequence = sequence; + #ifdef ELITEFORCE + if(!chan->compat) + #endif + chan->incomingSequence = sequence; return qtrue; } diff --git a/code/qcommon/net_ip.c b/code/qcommon/net_ip.c index 98555b99..dbd0af92 100644 --- a/code/qcommon/net_ip.c +++ b/code/qcommon/net_ip.c @@ -128,7 +128,11 @@ static struct sockaddr_in6 boundto; #endif // use an admin local address per default so that network admins can decide on how to handle quake3 traffic. +#ifdef ELITEFORCE +#define NET_MULTICAST_IP6 "ff04::696f:6566" +#else #define NET_MULTICAST_IP6 "ff04::696f:7175:616b:6533" +#endif #define MAX_IPS 32 diff --git a/code/qcommon/q_math.c b/code/qcommon/q_math.c index ce47317a..d9221347 100644 --- a/code/qcommon/q_math.c +++ b/code/qcommon/q_math.c @@ -972,7 +972,11 @@ void PerpendicularVector( vec3_t dst, const vec3_t src ) /* ** find the smallest magnitude axially aligned vector */ +#ifdef ELITEFORCE + for ( pos = 0, i = 2; i >= 0; i-- ) +#else for ( pos = 0, i = 0; i < 3; i++ ) +#endif { if ( fabs( src[i] ) < minelem ) { diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index 90996a29..dfa8ee17 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -37,19 +37,35 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define GAMENAME_FOR_MASTER "foobar" // must NOT contain whitespace // #define LEGACY_PROTOCOL // You probably don't need this for your standalone game #else - #define PRODUCT_NAME "ioq3" - #define BASEGAME "baseq3" - #define CLIENT_WINDOW_TITLE "ioquake3" - #define CLIENT_WINDOW_MIN_TITLE "ioq3" - #define HOMEPATH_NAME_UNIX ".q3a" - #define HOMEPATH_NAME_WIN "Quake3" - #define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN - #define GAMENAME_FOR_MASTER "Quake3Arena" - #define LEGACY_PROTOCOL + #ifdef ELITEFORCE + #define PRODUCT_NAME "ioST:V HM" + #define BASEGAME "baseEF" + #define CLIENT_WINDOW_TITLE "iostvoyHM" + #define CLIENT_WINDOW_MIN_TITLE "iostvoyHM" + #define HOMEPATH_NAME_UNIX ".stvef" + #define HOMEPATH_NAME_WIN "STVEF" + #define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN + #define GAMENAME_FOR_MASTER "EliteForce" + #define LEGACY_PROTOCOL + #else + #define PRODUCT_NAME "ioq3" + #define BASEGAME "baseq3" + #define CLIENT_WINDOW_TITLE "ioquake3" + #define CLIENT_WINDOW_MIN_TITLE "ioq3" + #define HOMEPATH_NAME_UNIX ".q3a" + #define HOMEPATH_NAME_WIN "Quake3" + #define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN + #define GAMENAME_FOR_MASTER "Quake3Arena" + #define LEGACY_PROTOCOL + #endif #endif // Heartbeat for dpmaster protocol. You shouldn't change this unless you know what you're doing -#define HEARTBEAT_FOR_MASTER "DarkPlaces" +#ifdef ELITEFORCE + #define HEARTBEAT_FOR_MASTER "STEF1" +#else + #define HEARTBEAT_FOR_MASTER "DarkPlaces" +#endif // When com_gamename is LEGACY_MASTER_GAMENAME, use quake3 master protocol. // You shouldn't change this unless you know what you're doing @@ -1113,7 +1129,11 @@ typedef struct { #define MAX_POWERUPS 16 #define MAX_WEAPONS 16 +#ifdef ELITEFORCE +#define MAX_PS_EVENTS 4 +#else #define MAX_PS_EVENTS 2 +#endif #define PS_PMOVEFRAMECOUNTBITS 6 @@ -1137,6 +1157,11 @@ typedef struct playerState_s { vec3_t origin; vec3_t velocity; int weaponTime; +#ifdef ELITEFORCE + int rechargeTime; // for the phaser + short useTime; // use debounce + int introTime; // for the holodoor +#endif int gravity; int speed; int delta_angles[3]; // add to command angles to get view direction @@ -1155,7 +1180,9 @@ typedef struct playerState_s { // when at rest, the value will remain unchanged // used to twist the legs during strafing +#ifndef ELITEFORCE vec3_t grapplePoint; // location of grapple to pull towards if PMF_GRAPPLE_PULL +#endif int eFlags; // copied to entityState_t->eFlags @@ -1179,20 +1206,27 @@ typedef struct playerState_s { int damageYaw; int damagePitch; int damageCount; +#ifdef ELITEFORCE + int damageShieldCount; +#endif int stats[MAX_STATS]; int persistant[MAX_PERSISTANT]; // stats that aren't cleared on death int powerups[MAX_POWERUPS]; // level.time that the powerup runs out int ammo[MAX_WEAPONS]; +#ifndef ELITEFORCE int generic1; int loopSound; int jumppad_ent; // jumppad entity hit this frame +#endif // not communicated over the net at all int ping; // server to game info for scoreboard +#ifndef ELITEFORCE int pmove_framecount; int jumppad_frame; +#endif int entityEventSequence; } playerState_t; @@ -1227,6 +1261,15 @@ typedef struct playerState_s { // then BUTTON_WALKING should be set // usercmd_t is sent to the server each client frame +#ifdef ELITEFORCE +typedef struct usercmd_s { + int serverTime; + byte buttons; + byte weapon; + int angles[3]; + signed char forwardmove, rightmove, upmove; +} usercmd_t; +#else typedef struct usercmd_s { int serverTime; int angles[3]; @@ -1234,7 +1277,7 @@ typedef struct usercmd_s { byte weapon; // weapon signed char forwardmove, rightmove, upmove; } usercmd_t; - +#endif //=================================================================== // if entityState->solid == SOLID_BMODEL, modelindex is an inline model number @@ -1305,7 +1348,9 @@ typedef struct entityState_s { int legsAnim; // mask off ANIM_TOGGLEBIT int torsoAnim; // mask off ANIM_TOGGLEBIT +#ifndef ELITEFORCE int generic1; +#endif } entityState_t; typedef enum { diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h index af37ff4d..f8ceb9cd 100644 --- a/code/qcommon/qcommon.h +++ b/code/qcommon/qcommon.h @@ -23,6 +23,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef _QCOMMON_H_ #define _QCOMMON_H_ +#if defined(ELITEFORCE) && defined(MISSIONPACK) + #undef MISSIONPACK +#endif + #include "../qcommon/cm_public.h" //Ignore __attribute__ on non-gcc platforms @@ -43,6 +47,9 @@ typedef struct { qboolean allowoverflow; // if false, do a Com_Error qboolean overflowed; // set to true if the buffer size failed (with allowoverflow set) qboolean oob; // set to true if the buffer size failed (with allowoverflow set) +#ifdef ELITEFORCE + qboolean compat; // Compatibility mode for old EliteForce servers. +#endif byte *data; int maxsize; int cursize; @@ -254,32 +261,63 @@ PROTOCOL ============================================================== */ -#define PROTOCOL_VERSION 71 -#define PROTOCOL_LEGACY_VERSION 68 +#ifdef ELITEFORCE + #define PROTOCOL_VERSION 26 + #define PROTOCOL_LEGACY_VERSION 24 +#else + #define PROTOCOL_VERSION 71 + #define PROTOCOL_LEGACY_VERSION 68 +#endif // 1.31 - 67 // maintain a list of compatible protocols for demo playing // NOTE: that stuff only works with two digits protocols extern int demo_protocols[]; -#if !defined UPDATE_SERVER_NAME && !defined STANDALONE -#define UPDATE_SERVER_NAME "update.quake3arena.com" -#endif // override on command line, config files etc. -#ifndef MASTER_SERVER_NAME -#define MASTER_SERVER_NAME "master.quake3arena.com" +#ifdef ELITEFORCE + + #if !defined UPDATE_SERVER_NAME && !defined STANDALONE + #define UPDATE_SERVER_NAME "motd.stef1.ravensoft.com" + #endif + #ifndef MASTER_SERVER_NAME + #define MASTER_SERVER_NAME "master.stef1.ravensoft.com" + #endif + + #define PORT_MASTER 27953 + +#else + + #if !defined UPDATE_SERVER_NAME && !defined STANDALONE + #define UPDATE_SERVER_NAME "update.quake3arena.com" + #endif + #define UPDATE_SERVER_NAME "update.quake3arena.com" + #ifndef MASTER_SERVER_NAME + #define MASTER_SERVER_NAME "master.quake3arena.com" + #endif + + #define PORT_MASTER 27950 + #endif #ifndef STANDALONE - #ifndef AUTHORIZE_SERVER_NAME - #define AUTHORIZE_SERVER_NAME "authorize.quake3arena.com" - #endif - #ifndef PORT_AUTHORIZE - #define PORT_AUTHORIZE 27952 + #ifdef ELITEFORCE + #ifndef AUTHORIZE_SERVER_NAME + #define AUTHORIZE_SERVER_NAME "authenticate.stef1.ravensoft.com" + #endif + #ifndef PORT_AUTHORIZE + #define PORT_AUTHORIZE 27953 + #endif + #else + #ifndef AUTHORIZE_SERVER_NAME + #define AUTHORIZE_SERVER_NAME "authorize.quake3arena.com" + #endif + #ifndef PORT_AUTHORIZE + #define PORT_AUTHORIZE 27952 + #endif #endif #endif -#define PORT_MASTER 27950 #define PORT_UPDATE 27951 #define PORT_SERVER 27960 #define NUM_SERVER_PORTS 4 // broadcast scan this many ports after @@ -595,15 +633,23 @@ issues. #define FS_UI_REF 0x02 #define FS_CGAME_REF 0x04 // number of id paks that will never be autodownloaded from baseq3/missionpack +#ifdef ELITEFORCE +#define NUM_ID_PAKS 9 +#else #define NUM_ID_PAKS 9 #define NUM_TA_PAKS 4 +#endif #define MAX_FILE_HANDLES 64 -#ifdef DEDICATED -# define Q3CONFIG_CFG "q3config_server.cfg" +#ifdef ELITEFORCE + #define Q3CONFIG_CFG "hmconfig.cfg" #else -# define Q3CONFIG_CFG "q3config.cfg" + #ifdef DEDICATED + # define Q3CONFIG_CFG "q3config_server.cfg" + #else + # define Q3CONFIG_CFG "q3config.cfg" + #endif #endif qboolean FS_Initialized( void ); diff --git a/code/qcommon/surfaceflags.h b/code/qcommon/surfaceflags.h index b7c10a17..6d1f9b0c 100644 --- a/code/qcommon/surfaceflags.h +++ b/code/qcommon/surfaceflags.h @@ -41,6 +41,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define CONTENTS_PLAYERCLIP 0x10000 #define CONTENTS_MONSTERCLIP 0x20000 +#ifdef ELITEFORCE +#define CONTENTS_SHOTCLIP 0x40000 +#endif + //bot specific contents types #define CONTENTS_TELEPORTER 0x40000 #define CONTENTS_JUMPPAD 0x80000 diff --git a/code/renderercommon/tr_common.h b/code/renderercommon/tr_common.h index 31de1a8f..4de74b5a 100644 --- a/code/renderercommon/tr_common.h +++ b/code/renderercommon/tr_common.h @@ -82,6 +82,12 @@ extern qboolean textureFilterAnisotropic; extern int maxAnisotropy; extern float displayAspect; +// used by shader functions, including noise in renderercommon +#define FOG_TABLE_SIZE 256 +#define FUNCTABLE_SIZE 1024 +#define FUNCTABLE_SIZE2 10 +#define FUNCTABLE_MASK (FUNCTABLE_SIZE-1) + // // cvars // @@ -118,6 +124,7 @@ extern cvar_t *r_saveFontData; qboolean R_GetModeInfo( int *width, int *height, float *windowAspect, int mode ); float R_NoiseGet4f( float x, float y, float z, float t ); +int R_RandomOn( float t ); void R_NoiseInit( void ); image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags ); @@ -127,6 +134,9 @@ void R_IssuePendingRenderCommands( void ); qhandle_t RE_RegisterShaderLightMap( const char *name, int lightmapIndex ); qhandle_t RE_RegisterShader( const char *name ); qhandle_t RE_RegisterShaderNoMip( const char *name ); +#ifdef ELITEFORCE +qhandle_t RE_RegisterShader3D( const char *name ); +#endif qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage); // font stuff diff --git a/code/renderercommon/tr_noise.c b/code/renderercommon/tr_noise.c index 445ef827..463573a2 100644 --- a/code/renderercommon/tr_noise.c +++ b/code/renderercommon/tr_noise.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // tr_noise.c #include "tr_common.h" -#define NOISE_SIZE 256 +#define NOISE_SIZE FUNCTABLE_SIZE #define NOISE_MASK ( NOISE_SIZE - 1 ) #define VAL( a ) s_noise_perm[ ( a ) & ( NOISE_MASK )] @@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA static float s_noise_table[NOISE_SIZE]; static int s_noise_perm[NOISE_SIZE]; +static int s_random[NOISE_SIZE]; static float GetNoiseValue( int x, int y, int z, int t ) { @@ -46,6 +47,7 @@ void R_NoiseInit( void ) { s_noise_table[i] = ( float ) ( ( ( rand() / ( float ) RAND_MAX ) * 2.0 - 1.0 ) ); s_noise_perm[i] = ( unsigned char ) ( rand() / ( float ) RAND_MAX * 255 ); + s_random[i] = rand() & 0x01; } } @@ -89,3 +91,10 @@ float R_NoiseGet4f( float x, float y, float z, float t ) return finalvalue; } + +// used in the shader functions (GF_RANDOM) to implement a quasi random flickering. +#define VALR( a ) s_random[ ( a ) & ( NOISE_MASK )] +int R_RandomOn(float t) +{ + return VALR((unsigned int) floor(t)); +} diff --git a/code/renderercommon/tr_public.h b/code/renderercommon/tr_public.h index 38d647f6..2b32d8b9 100644 --- a/code/renderercommon/tr_public.h +++ b/code/renderercommon/tr_public.h @@ -49,6 +49,9 @@ typedef struct { qhandle_t (*RegisterSkin)( const char *name ); qhandle_t (*RegisterShader)( const char *name ); qhandle_t (*RegisterShaderNoMip)( const char *name ); +#ifdef ELITEFORCE + qhandle_t (*RegisterShader3D)( const char *name ); +#endif void (*LoadWorld)( const char *name ); // the vis data is a large enough block of data that we go to the trouble diff --git a/code/renderercommon/tr_types.h b/code/renderercommon/tr_types.h index dd55e2e7..ed5353b4 100644 --- a/code/renderercommon/tr_types.h +++ b/code/renderercommon/tr_types.h @@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define __TR_TYPES_H -#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces +#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces #define REFENTITYNUM_BITS 10 // can't be increased without changing drawsurf bit packing #define REFENTITYNUM_MASK ((1<lightingOrigin instead of refEntity->origin - // for lighting. This allows entities to sink into the floor - // with their origin going solid, and allows all parts of a - // player to get the same lighting + // for lighting. This allows entities to sink into the floor + // with their origin going solid, and allows all parts of a + // player to get the same lighting #define RF_SHADOW_PLANE 0x0100 // use refEntity->shadowPlane #define RF_WRAP_FRAMES 0x0200 // mod the model frames by the maxframes to allow continuous // animation without needing to know the frame count +#ifdef ELITEFORCE +#define RF_FORCE_ENT_ALPHA 0x0800 // override shader alpha value and take the one from the entity. +#endif + // refdef flags -#define RDF_NOWORLDMODEL 0x0001 // used for player configuration screen -#define RDF_HYPERSPACE 0x0004 // teleportation effect +#define RDF_NOWORLDMODEL 1 // used for player configuration screen +#define RDF_HYPERSPACE 4 // teleportation effect typedef struct { vec3_t xyz; @@ -71,6 +80,27 @@ typedef struct poly_s { polyVert_t *verts; } poly_t; +#ifdef ELITEFORCE +typedef enum { + RT_MODEL, + RT_SPRITE, + RT_ORIENTEDSPRITE, // Replaces RT_POLY, which wasn't used. --Pat + RT_ALPHAVERTPOLY, // Individual alpha levels on each vertex + RT_BEAM, + RT_RAIL_CORE, + RT_RAIL_RINGS, + RT_LIGHTNING, + RT_PORTALSURFACE, // doesn't draw anything, just info for portals + RT_LINE, // New type for Trek MP --Pat + RT_ORIENTEDLINE, + RT_LINE2, // New line type for Trek MP, with taper support --Pat + RT_BEZIER, // what he said --keith + RT_CYLINDER, // Yet another Trek primitive! + RT_ELECTRICITY, // Yet another Trek primitive! + + RT_MAX_REF_ENTITY_TYPE +} refEntityType_t; +#else typedef enum { RT_MODEL, RT_POLY, @@ -83,6 +113,7 @@ typedef enum { RT_MAX_REF_ENTITY_TYPE } refEntityType_t; +#endif typedef struct { refEntityType_t reType; @@ -115,8 +146,49 @@ typedef struct { float shaderTime; // subtracted from refdef time to control effect start times // extra sprite information +#ifdef ELITEFORCE + union + { + struct + { + float rotation; + float radius; + byte vertRGBA[4][4]; + } sprite; + struct + { + float width; + float width2; + float stscale; + } line; + struct // that whole put-the-opening-brace-on-the-same-line-as-the-beginning-of-the-definition coding style is fecal // I agree. + { + float width; + vec3_t control1; + vec3_t control2; + } bezier; + struct + { + float width; + float width2; + float stscale; + float height; + float bias; + qboolean wrap; + } cylinder; + struct + { + float width; + float deviation; + float stscale; + qboolean wrap; + qboolean taper; + } electricity; + } data; +#else float radius; float rotation; +#endif } refEntity_t; @@ -137,8 +209,10 @@ typedef struct { // 1 bits will prevent the associated area from rendering at all byte areamask[MAX_MAP_AREA_BYTES]; +#ifndef ELITEFORCE // text messages for deform text shaders char text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH]; +#endif } refdef_t; @@ -186,7 +260,11 @@ typedef struct { char renderer_string[MAX_STRING_CHARS]; char vendor_string[MAX_STRING_CHARS]; char version_string[MAX_STRING_CHARS]; +#ifdef ELITEFORCE + char extensions_string[2*MAX_STRING_CHARS]; +#else char extensions_string[BIG_INFO_STRING]; +#endif int maxTextureSize; // queried from GL int numTextureUnits; // multitexture ability @@ -199,6 +277,9 @@ typedef struct { qboolean deviceSupportsGamma; textureCompression_t textureCompression; qboolean textureEnvAddAvailable; +#ifdef ELITEFORCE + qboolean textureFilterAnisotropicAvailable; +#endif int vidWidth, vidHeight; // aspect is the screen's physical width / height, which may be different diff --git a/code/renderergl1/tr_backend.c b/code/renderergl1/tr_backend.c index 788f7801..8f4939bb 100644 --- a/code/renderergl1/tr_backend.c +++ b/code/renderergl1/tr_backend.c @@ -448,10 +448,17 @@ void RB_BeginDrawingView (void) { if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) ) { clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used +#ifdef ELITEFORCE + if(r_origfastsky->integer) + qglClearColor(0.8f, 0.7f, 0.4f, 1.0f); + else + qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); +#else #ifdef _DEBUG qglClearColor( 0.8f, 0.7f, 0.4f, 1.0f ); // FIXME: get color of sky #else qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // FIXME: get color of sky +#endif #endif } qglClear( clearBits ); diff --git a/code/renderergl1/tr_init.c b/code/renderergl1/tr_init.c index 15e79729..50a619dd 100644 --- a/code/renderergl1/tr_init.c +++ b/code/renderergl1/tr_init.c @@ -69,6 +69,9 @@ cvar_t *r_measureOverdraw; cvar_t *r_inGameVideo; cvar_t *r_fastsky; +#ifdef ELITEFORCE +cvar_t *r_origfastsky; +#endif cvar_t *r_drawSun; cvar_t *r_dynamiclight; cvar_t *r_dlightBacks; @@ -197,6 +200,10 @@ static void InitOpenGL( void ) GLimp_Init(); +#ifdef ELITEFORCE + glConfig.textureFilterAnisotropicAvailable = textureFilterAnisotropic; +#endif + strcpy( renderer_buffer, glConfig.renderer_string ); Q_strlwr( renderer_buffer ); @@ -1007,7 +1014,11 @@ void R_Register( void ) // latched and archived variables // r_allowExtensions = ri.Cvar_Get( "r_allowExtensions", "1", CVAR_ARCHIVE | CVAR_LATCH ); +#ifdef ELITEFORCE + r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compress_textures", "0", CVAR_ARCHIVE | CVAR_LATCH ); +#else r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compressed_textures", "0", CVAR_ARCHIVE | CVAR_LATCH ); +#endif r_ext_multitexture = ri.Cvar_Get( "r_ext_multitexture", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH); r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "1", CVAR_ARCHIVE | CVAR_LATCH); @@ -1050,7 +1061,11 @@ void R_Register( void ) r_displayRefresh = ri.Cvar_Get( "r_displayRefresh", "0", CVAR_LATCH ); ri.Cvar_CheckRange( r_displayRefresh, 0, 200, qtrue ); r_fullbright = ri.Cvar_Get ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT ); +#ifdef ELITEFORCE + r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "1", CVAR_LATCH ); +#else r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH ); +#endif r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_LATCH ); r_singleShader = ri.Cvar_Get ("r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH ); @@ -1066,6 +1081,9 @@ void R_Register( void ) r_stereoSeparation = ri.Cvar_Get( "r_stereoSeparation", "64", CVAR_ARCHIVE ); r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE ); r_fastsky = ri.Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE ); +#ifdef ELITEFORCE + r_origfastsky = ri.Cvar_Get( "r_origfastsky", "0", CVAR_ARCHIVE ); +#endif r_inGameVideo = ri.Cvar_Get( "r_inGameVideo", "1", CVAR_ARCHIVE ); r_drawSun = ri.Cvar_Get( "r_drawSun", "0", CVAR_ARCHIVE ); r_dynamiclight = ri.Cvar_Get( "r_dynamiclight", "1", CVAR_ARCHIVE ); @@ -1171,8 +1189,15 @@ void R_Init( void ) { Com_Memset( &backEnd, 0, sizeof( backEnd ) ); Com_Memset( &tess, 0, sizeof( tess ) ); +#ifdef ELITEFORCE + if(sizeof(glconfig_t) != 5192) + { + ri.Error( ERR_FATAL, "Mod ABI incompatible: sizeof(glconfig_t) == %u != 5192", (unsigned int) sizeof(glconfig_t)); + } +#else if(sizeof(glconfig_t) != 11332) ri.Error( ERR_FATAL, "Mod ABI incompatible: sizeof(glconfig_t) == %u != 11332", (unsigned int) sizeof(glconfig_t)); +#endif // Swap_Init(); @@ -1181,6 +1206,8 @@ void R_Init( void ) { } Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) ); + R_NoiseInit(); + // // init function tables // @@ -1190,6 +1217,7 @@ void R_Init( void ) { tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f; tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; + tr.noiseTable[i] = R_NoiseGet4f(0, 0, 0, i); if ( i < FUNCTABLE_SIZE / 2 ) { @@ -1210,8 +1238,6 @@ void R_Init( void ) { R_InitFogTable(); - R_NoiseInit(); - R_Register(); max_polys = r_maxpolys->integer; @@ -1338,6 +1364,9 @@ refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) { re.RegisterSkin = RE_RegisterSkin; re.RegisterShader = RE_RegisterShader; re.RegisterShaderNoMip = RE_RegisterShaderNoMip; +#ifdef ELITEFORCE + re.RegisterShader3D = RE_RegisterShader3D; +#endif re.LoadWorld = RE_LoadWorldMap; re.SetWorldVisData = RE_SetWorldVisData; re.EndRegistration = RE_EndRegistration; diff --git a/code/renderergl1/tr_light.c b/code/renderergl1/tr_light.c index fc6af6a9..6d6ff57e 100644 --- a/code/renderergl1/tr_light.c +++ b/code/renderergl1/tr_light.c @@ -294,6 +294,20 @@ void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) { } ent->lightingCalculated = qtrue; +#ifdef ELITEFORCE + if(ent->e.renderfx & RF_FULLBRIGHT) + { +// ent->ambientLight[0] = ent->ambientLight[1] = ent->ambientLight[1] = 0xFF; + ((byte *)&ent->ambientLightInt)[0] = 0x7F; + ((byte *)&ent->ambientLightInt)[1] = 0x7F; + ((byte *)&ent->ambientLightInt)[2] = 0x7F; + ((byte *)&ent->ambientLightInt)[3] = 0xFF; + + ent->lightDir[0] = ent->lightDir[1] = ent->lightDir[2] = 0; + return; + } +#endif + // // trace a sample point down to find ambient light // diff --git a/code/renderergl1/tr_local.h b/code/renderergl1/tr_local.h index c0c62f03..0846f539 100644 --- a/code/renderergl1/tr_local.h +++ b/code/renderergl1/tr_local.h @@ -117,7 +117,8 @@ typedef enum { GF_SAWTOOTH, GF_INVERSE_SAWTOOTH, - GF_NOISE + GF_NOISE, + GF_RANDOM } genFunc_t; @@ -810,11 +811,6 @@ typedef struct { int c_dlightSurfacesCulled; } frontEndCounters_t; -#define FOG_TABLE_SIZE 256 -#define FUNCTABLE_SIZE 1024 -#define FUNCTABLE_SIZE2 10 -#define FUNCTABLE_MASK (FUNCTABLE_SIZE-1) - // the renderer front end should never modify glstate_t typedef struct { @@ -948,6 +944,7 @@ typedef struct { float triangleTable[FUNCTABLE_SIZE]; float sawToothTable[FUNCTABLE_SIZE]; float inverseSawToothTable[FUNCTABLE_SIZE]; + float noiseTable[FUNCTABLE_SIZE]; float fogTable[FOG_TABLE_SIZE]; } trGlobals_t; @@ -988,6 +985,9 @@ extern cvar_t *r_primitives; // "0" = based on compiled vertex array existance extern cvar_t *r_inGameVideo; // controls whether in game video should be draw extern cvar_t *r_fastsky; // controls whether sky should be cleared or drawn +#ifdef ELITEFORCE +extern cvar_t *r_origfastsky; // controls whether fastsky color is like in original EF. +#endif extern cvar_t *r_drawSun; // controls drawing of sun quad extern cvar_t *r_dynamiclight; // dynamic lights enabled/disabled extern cvar_t *r_dlightBacks; // dlight non-facing surfaces for continuity diff --git a/code/renderergl1/tr_main.c b/code/renderergl1/tr_main.c index 6a2118f1..1694f543 100644 --- a/code/renderergl1/tr_main.c +++ b/code/renderergl1/tr_main.c @@ -1006,18 +1006,25 @@ See if a sprite is inside a fog volume int R_SpriteFogNum( trRefEntity_t *ent ) { int i, j; fog_t *fog; + float radius; if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { return 0; } + #ifdef ELITEFORCE + radius = ent->e.data.sprite.radius; + #else + radius = ent->e.radius; + #endif + for ( i = 1 ; i < tr.world->numfogs ; i++ ) { fog = &tr.world->fogs[i]; for ( j = 0 ; j < 3 ; j++ ) { - if ( ent->e.origin[j] - ent->e.radius >= fog->bounds[1][j] ) { + if ( ent->e.origin[j] - radius >= fog->bounds[1][j] ) { break; } - if ( ent->e.origin[j] + ent->e.radius <= fog->bounds[0][j] ) { + if ( ent->e.origin[j] + radius <= fog->bounds[0][j] ) { break; } } @@ -1215,6 +1222,18 @@ void R_AddEntitySurfaces (void) { switch ( ent->e.reType ) { case RT_PORTALSURFACE: break; // don't draw anything + +#ifdef ELITEFORCE + case RT_ORIENTEDSPRITE: + case RT_ALPHAVERTPOLY: + case RT_LINE: + case RT_ORIENTEDLINE: + case RT_LINE2: + case RT_BEZIER: + case RT_CYLINDER: + case RT_ELECTRICITY: +#endif + case RT_SPRITE: case RT_BEAM: case RT_LIGHTNING: diff --git a/code/renderergl1/tr_scene.c b/code/renderergl1/tr_scene.c index 5d7a3dd1..b99273c5 100644 --- a/code/renderergl1/tr_scene.c +++ b/code/renderergl1/tr_scene.c @@ -304,7 +304,9 @@ void RE_RenderScene( const refdef_t *fd ) { ri.Error (ERR_DROP, "R_RenderScene: NULL worldmodel"); } + #ifndef ELITEFORCE Com_Memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) ); + #endif tr.refdef.x = fd->x; tr.refdef.y = fd->y; diff --git a/code/renderergl1/tr_shade.c b/code/renderergl1/tr_shade.c index 08648b2e..f7f497e6 100644 --- a/code/renderergl1/tr_shade.c +++ b/code/renderergl1/tr_shade.c @@ -1109,6 +1109,10 @@ static void ComputeTexCoords( shaderStage_t *pStage ) { static void RB_IterateStagesGeneric( shaderCommands_t *input ) { int stage; +#ifdef ELITEFORCE + qboolean overridealpha; + int oldalphaGen = 0; +#endif for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { @@ -1119,7 +1123,25 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) break; } + #ifdef ELITEFORCE + // Override the shader alpha channel if requested. + if(backEnd.currentEntity->e.renderfx & RF_FORCE_ENT_ALPHA) + { + overridealpha = qtrue; + oldalphaGen = pStage->alphaGen; + pStage->alphaGen = AGEN_ENTITY; + } + else + overridealpha = qfalse; + #endif + ComputeColors( pStage ); + + #ifdef ELITEFORCE + if(overridealpha) + pStage->alphaGen = oldalphaGen; + #endif + ComputeTexCoords( pStage ); if ( !setArraysOnce ) @@ -1147,7 +1169,15 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) // R_BindAnimatedImage( &pStage->bundle[0] ); - GL_State( pStage->stateBits ); + #ifdef ELITEFORCE + if(overridealpha && backEnd.currentEntity->e.shaderRGBA[3] < 0xFF && !(pStage->stateBits & GLS_ATEST_BITS)) + { + GL_State((pStage->stateBits & ~(GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS | GLS_ATEST_BITS)) // remove the shader set values. + | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_ATEST_GT_0); // Now add the default values. + } + else + #endif + GL_State( pStage->stateBits ); // // draw diff --git a/code/renderergl1/tr_shade_calc.c b/code/renderergl1/tr_shade_calc.c index ae33c7fb..2cec6a43 100644 --- a/code/renderergl1/tr_shade_calc.c +++ b/code/renderergl1/tr_shade_calc.c @@ -43,6 +43,8 @@ static float *TableForFunc( genFunc_t func ) return tr.sawToothTable; case GF_INVERSE_SAWTOOTH: return tr.inverseSawToothTable; + case GF_NOISE: + return tr.noiseTable; case GF_NONE: default: break; @@ -577,7 +579,9 @@ void RB_DeformTessGeometry( void ) { case DEFORM_TEXT5: case DEFORM_TEXT6: case DEFORM_TEXT7: +#ifndef ELITEFORCE DeformText( backEnd.refdef.text[ds->deformation - DEFORM_TEXT0] ); +#endif break; } } @@ -688,6 +692,8 @@ void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors ) if ( wf->func == GF_NOISE ) { glow = wf->base + R_NoiseGet4f( 0, 0, 0, ( tess.shaderTime + wf->phase ) * wf->frequency ) * wf->amplitude; + } else if( wf->func == GF_RANDOM ) { + glow = wf->base + R_RandomOn( (tess.shaderTime + wf->phase) * wf->frequency ) * wf->amplitude; } else { glow = EvalWaveForm( wf ) * tr.identityLight; } diff --git a/code/renderergl1/tr_shader.c b/code/renderergl1/tr_shader.c index 43b2beb7..3bb2a7c7 100644 --- a/code/renderergl1/tr_shader.c +++ b/code/renderergl1/tr_shader.c @@ -293,6 +293,10 @@ static genFunc_t NameToGenFunc( const char *funcname ) { return GF_NOISE; } + else if( !Q_stricmp( funcname, "random" ) ) + { + return GF_RANDOM; + } ri.Printf( PRINT_WARNING, "WARNING: invalid genfunc name '%s' in shader '%s'\n", funcname, shader.name ); return GF_SIN; @@ -768,6 +772,12 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) { depthFuncBits = 0; } +#ifdef ELITEFORCE + if ( !Q_stricmp( token, "disable" ) ) + { + depthFuncBits = 0; + } +#endif else if ( !Q_stricmp( token, "equal" ) ) { depthFuncBits = GLS_DEPTHFUNC_EQUAL; @@ -2820,6 +2830,37 @@ qhandle_t RE_RegisterShaderNoMip( const char *name ) { return sh->index; } +#ifdef ELITEFORCE +/* +==================== +RE_RegisterShader3D + +For explicitly defined shaders that need LIGHTMAP_NONE +as lightmapIndex. +==================== +*/ +qhandle_t RE_RegisterShader3D( const char *name ) { + shader_t *sh; + + if ( strlen( name ) >= MAX_QPATH ) { + Com_Printf( "Shader name exceeds MAX_QPATH\n" ); + return 0; + } + + sh = R_FindShader( name, LIGHTMAP_NONE, qfalse ); + + // we want to return 0 if the shader failed to + // load for some reason, but R_FindShader should + // still keep a name allocated for it, so if + // something calls RE_RegisterShader again with + // the same name, we don't try looking for it again + if ( sh->defaultShader ) { + return 0; + } + + return sh->index; +} +#endif /* ==================== @@ -2993,8 +3034,8 @@ static void ScanAndLoadShaderFiles( void ) break; } } - + if (buffers[i]) sum += summand; } diff --git a/code/renderergl1/tr_surface.c b/code/renderergl1/tr_surface.c index 1879fe2c..84fc065b 100644 --- a/code/renderergl1/tr_surface.c +++ b/code/renderergl1/tr_surface.c @@ -156,17 +156,25 @@ RB_SurfaceSprite static void RB_SurfaceSprite( void ) { vec3_t left, up; float radius; + float rotation; // calculate the xyz locations for the four corners + #ifdef ELITEFORCE + radius = backEnd.currentEntity->e.data.sprite.radius; + rotation = backEnd.currentEntity->e.data.sprite.rotation; + #else radius = backEnd.currentEntity->e.radius; - if ( backEnd.currentEntity->e.rotation == 0 ) { + rotation = backEnd.currentEntity->e.rotation; + #endif + + if ( rotation == 0 ) { VectorScale( backEnd.viewParms.or.axis[1], radius, left ); VectorScale( backEnd.viewParms.or.axis[2], radius, up ); } else { float s, c; float ang; - ang = M_PI * backEnd.currentEntity->e.rotation / 180; + ang = M_PI * rotation / 180; s = sin( ang ); c = cos( ang ); @@ -551,6 +559,576 @@ static void RB_SurfaceLightningBolt( void ) { } } +#ifdef ELITEFORCE + +/* +============== +RB_SurfaceOrientedSprite +============== +*/ +static void RB_SurfaceOrientedSprite( void ) +{ + vec3_t left, up; + float radius; + float rotation; + + // calculate the xyz locations for the four corners + radius = backEnd.currentEntity->e.data.sprite.radius; + rotation = backEnd.currentEntity->e.data.sprite.rotation; + + if (rotation == 0) + { + VectorScale( backEnd.currentEntity->e.axis[1], radius, left ); + VectorScale( backEnd.currentEntity->e.axis[2], radius, up ); + } + else + { + float s, c; + float ang; + + ang = M_PI * rotation / 180; + s = sin( ang ); + c = cos( ang ); + + VectorScale( backEnd.currentEntity->e.axis[1], c * radius, left ); + VectorMA( left, -s * radius, backEnd.currentEntity->e.axis[2], left ); + + VectorScale( backEnd.currentEntity->e.axis[2], c * radius, up ); + VectorMA( up, s * radius, backEnd.currentEntity->e.axis[1], up ); + } + if ( backEnd.viewParms.isMirror ) + VectorSubtract( vec3_origin, left, left ); + + RB_AddQuadStamp( backEnd.currentEntity->e.origin, left, up, backEnd.currentEntity->e.shaderRGBA ); +} + +void RB_Line(vec3_t start, vec3_t end, vec3_t linedirection, vec3_t left, + vec3_t *corners, float starttex, float endtex, refEntity_t *e) +{ + int ndx, numind; + color4ub_t *vertcols; + + RB_CHECKOVERFLOW( 4, 6 ); + + // Set up the triangles .. + ndx = tess.numVertexes; + numind = tess.numIndexes; + + tess.indexes[ numind ] = ndx; + tess.indexes[ numind + 1 ] = ndx + 1; + tess.indexes[ numind + 2 ] = ndx + 3; + + tess.indexes[ numind + 3 ] = ndx + 3; + tess.indexes[ numind + 4 ] = ndx + 1; + tess.indexes[ numind + 5 ] = ndx + 2; + + // now create the corner vertices + + if(corners) + { + // we have the corner points for the start already given. + VectorCopy(corners[0], tess.xyz[ndx]); + VectorCopy(corners[1], tess.xyz[ndx+1]); + } + else + { + // start left corner + VectorAdd(start, left, tess.xyz[ndx]); + // start right corner + VectorSubtract(start, left, tess.xyz[ndx+1]); + } + // end right corner + VectorSubtract(end, left, tess.xyz[ndx+2]); + // end left corner + VectorAdd(end, left, tess.xyz[ndx+3]); + + if(corners) + { + // save the end corner points here. + VectorCopy(tess.xyz[ndx+3], corners[0]); + VectorCopy(tess.xyz[ndx+2], corners[1]); + } + + // Texture stuff.... + tess.texCoords[ndx][0][0] = 0; + tess.texCoords[ndx][0][1] = starttex; + + tess.texCoords[ndx+1][0][0] = 1; + tess.texCoords[ndx+1][0][1] = starttex; + + tess.texCoords[ndx+2][0][0] = 1; + tess.texCoords[ndx+2][0][1] = endtex; + + tess.texCoords[ndx+3][0][0] = 0; + tess.texCoords[ndx+3][0][1] = endtex; + + vertcols = tess.vertexColors; + + vertcols[ndx][0] = vertcols[ndx+1][0] = vertcols[ndx+2][0] = vertcols[ndx+3][0] = e->shaderRGBA[0]; + vertcols[ndx][1] = vertcols[ndx+1][1] = vertcols[ndx+2][1] = vertcols[ndx+3][1] = e->shaderRGBA[1]; + vertcols[ndx][2] = vertcols[ndx+1][2] = vertcols[ndx+2][2] = vertcols[ndx+3][2] = e->shaderRGBA[2]; + vertcols[ndx][3] = vertcols[ndx+1][3] = vertcols[ndx+2][3] = vertcols[ndx+3][3] = e->shaderRGBA[3]; + + tess.numVertexes += 4; + tess.numIndexes += 6; + + +} + +// Create a normal vector and scale it to the right length +void RB_LineNormal(vec3_t vec1, vec3_t vec2, float scale, vec3_t result) +{ + // Create the offset vector for the width of the line + CrossProduct(vec1, vec2, result); + // Normalize the offset vector first. + VectorNormalize(result); + // Scale the offset vector to the intended width. + VectorScale(result, scale / 2, result); +} + +// Let's draw a thick line from A to B and dance happily around a christmas tree! +void RB_SurfaceLine( void ) +{ + refEntity_t *e; + vec3_t left; // I vote the green party... + vec3_t start, end, linedirection, start2origin; + shader_t *surfshader; + + e = &backEnd.currentEntity->e; + + // Getting up before 1:00 pm to attend HM I lectures finally paid off.. + + // Get the start and end point of the line + VectorCopy(e->origin, start); + VectorCopy(e->oldorigin, end); + + // Direction vector for the line: + VectorSubtract(end, start, linedirection); + // Direction vector for the start to current point of view + VectorSubtract(backEnd.viewParms.or.origin, start, start2origin); + + RB_LineNormal(start2origin, linedirection, e->data.line.width, left); + RB_Line(start, end, linedirection, left, NULL, 0, e->data.line.stscale, e); + + // Hack to make the dreadnought lightning bolt work: set the correct cull type... + if((surfshader = R_GetShaderByHandle(e->customShader))) + surfshader->cullType = CT_TWO_SIDED; +} + +void RB_SurfaceOrientedLine(void) +{ + refEntity_t *e; + vec3_t left; + vec3_t linedirection; + shader_t *surfshader; + + e = &backEnd.currentEntity->e; + + VectorSubtract(e->oldorigin, e->origin, linedirection); + + VectorCopy(e->axis[1], left); + VectorNormalize(left); + VectorScale(left, e->data.line.width / 2, left); + + RB_Line(e->origin, e->oldorigin, linedirection, left, NULL, 0, 1, e); + + surfshader = R_GetShaderByHandle(e->customShader); + surfshader->cullType = CT_TWO_SIDED; + +} + +// This time it's not a rectangle but a trapezoid I guess ... +void RB_SurfaceLine2( void ) +{ + refEntity_t *e; + vec3_t startleft, endleft; // I still vote the green party... + vec3_t start, end, linedirection, start2origin; + color4ub_t *vertcols; + int ndx, numind; + + RB_CHECKOVERFLOW( 6, 12 ); + + e = &backEnd.currentEntity->e; + + // Set up the triangle .. + ndx = tess.numVertexes; + numind = tess.numIndexes; + + tess.indexes[ numind ] = ndx; + tess.indexes[ numind + 1 ] = ndx + 1; + tess.indexes[ numind + 2 ] = ndx + 5; + tess.indexes[ numind + 3 ] = ndx + 5; + tess.indexes[ numind + 4 ] = ndx + 4; + tess.indexes[ numind + 5 ] = ndx + 1; + tess.indexes[ numind + 6 ] = ndx + 1; + tess.indexes[ numind + 7 ] = ndx + 4; + tess.indexes[ numind + 8 ] = ndx + 3; + tess.indexes[ numind + 9 ] = ndx + 3; + tess.indexes[ numind + 10 ] = ndx + 2; + tess.indexes[ numind + 11 ] = ndx + 1; + + + // Get the start and end point of the line + VectorCopy(e->origin, start); + VectorCopy(e->oldorigin, end); + + // Direction vector for the line: + VectorSubtract(end, start, linedirection); + // Direction vector for the start to current point of view + VectorSubtract(backEnd.viewParms.or.origin, start, start2origin); + + // Create the offset vector for the width of the line + CrossProduct(start2origin, linedirection, startleft); + // Normalize the offset vector first. + VectorNormalize(startleft); + // The normal of the triangle we just thought up: + + + // Scale the offset vector to the intended width. + VectorScale(startleft, e->data.line.width2 / 2, endleft); + VectorScale(startleft, e->data.line.width / 2, startleft); + + // now create the corner vertices + + // start left corner + VectorAdd(start, startleft, tess.xyz[ndx]); + // start point + VectorCopy(start, tess.xyz[ndx+1]); + // start right corner + VectorSubtract(start, startleft, tess.xyz[ndx+2]); + // end right corner + VectorSubtract(end, endleft, tess.xyz[ndx+3]); + // end point + VectorCopy(end, tess.xyz[ndx+4]); + // end left corner + VectorAdd(end, endleft, tess.xyz[ndx+5]); + + // Texture stuff.... + tess.texCoords[ndx][0][0] = 0; + tess.texCoords[ndx][0][1] = 0; + + tess.texCoords[ndx+1][0][0] = 0.5; + tess.texCoords[ndx+1][0][1] = 0; + + tess.texCoords[ndx+2][0][0] = 1; + tess.texCoords[ndx+2][0][1] = 0; + + tess.texCoords[ndx+3][0][0] = 1; + tess.texCoords[ndx+3][0][1] = 1; + + tess.texCoords[ndx+4][0][0] = 0.5; + tess.texCoords[ndx+4][0][1] = 1; + + tess.texCoords[ndx+5][0][0] = 0; + tess.texCoords[ndx+5][0][1] = 1; + + vertcols = tess.vertexColors; + + vertcols[ndx][0] = vertcols[ndx+1][0] = vertcols[ndx+2][0] = + vertcols[ndx+3][0] = vertcols[ndx+4][0] = vertcols[ndx+5][0] = e->shaderRGBA[0]; + vertcols[ndx][1] = vertcols[ndx+1][1] = vertcols[ndx+2][1] = + vertcols[ndx+3][1] = vertcols[ndx+4][1] = vertcols[ndx+5][1] = e->shaderRGBA[1]; + vertcols[ndx][2] = vertcols[ndx+1][2] = vertcols[ndx+2][2] = + vertcols[ndx+3][2] = vertcols[ndx+4][2] = vertcols[ndx+5][2] = e->shaderRGBA[2]; + vertcols[ndx][3] = vertcols[ndx+1][3] = vertcols[ndx+2][3] = + vertcols[ndx+3][3] = vertcols[ndx+4][3] = vertcols[ndx+5][3] = e->shaderRGBA[3]; + + tess.numVertexes += 6; + tess.numIndexes += 12; +} + +// Draw a cubic bezier curve for the imod weapon. +#define BEZIER_SEGMENTS 32 +#define BEZIER_STEPSIZE 1.0 / BEZIER_SEGMENTS + +void RB_SurfaceBezier(void) +{ + refEntity_t *e = &backEnd.currentEntity->e; + double tvar = 0, one_tvar; // use double to not lose as much precision on cubing and squaring. + float starttc, endtc; + vec3_t segstartpos, segendpos, prevend[2]; + vec3_t linedirection, start2origin, left; + int index; + + VectorCopy(e->origin, segstartpos); + + // start of the bezier curve is pointy + VectorCopy(segstartpos, prevend[0]); + VectorCopy(segstartpos, prevend[1]); + + // iterate through all segments we have to create. + while(tvar <= 1.0) + { + // get the texture position for the rectangular approximating the bezier curve. + starttc = tvar / 2.0; + tvar += BEZIER_STEPSIZE; + endtc = tvar / 2.0; + + one_tvar = 1.0 - tvar; + + // get the endpoint for this segment. + + for(index = 0; index < 3; index++) + { + // C(t) = P0 (t-1)^3 + 3 P1 t (t-1)^2 + 3 P2 t^2 (t-1) + P3 t^3 + segendpos[index] = + e->origin[index] * one_tvar * one_tvar * one_tvar + + 3 * e->data.bezier.control1[index] * tvar * one_tvar * one_tvar + + 3 * e->data.bezier.control2[index] * tvar * tvar * one_tvar + + e->oldorigin[index] * tvar * tvar * tvar; + } + + // Direction vector for the line: + VectorSubtract(segendpos, segstartpos, linedirection); + // Direction vector for the start to current point of view + VectorSubtract(backEnd.viewParms.or.origin, segstartpos, start2origin); + + RB_LineNormal(start2origin, linedirection, e->data.bezier.width, left); + RB_Line(segstartpos, segendpos, linedirection, left, prevend, starttc, endtc, e); + + // Our next segment starts where the old one ends. + VectorCopy(segendpos, segstartpos); + } +} + +// this actually isn't a cylinder but a frustum, but for the sake of naming +// conventions we'll keep calling it a cylinder. + +// number of rectangles we'll use to approximate a frustum of a cone. +#define CYLINDER_MAXPLANES 64 +#define LOD_CONSTANT 4.0f + +void RB_SurfaceCylinder(void) +{ + int planes, index = 0; // calculate the number of planes based on the level of detail. + vec3_t bottom, top, bottom2top, zerodeg_bottom, zerodeg_top, faxis; + vec3_t bottomcorner, topcorner, vieworigin; + float anglestep, tcstep = 0, width, width2, height; + int ndx, numind; + color4ub_t *vertcols; + refEntity_t *e = &backEnd.currentEntity->e; + // for LOD calculation: + vec3_t bottom2origin, top2origin, lodcalc, projection; + float maxradius, startdistance, enddistance, distance; + + height = e->data.cylinder.height; + width = e->data.cylinder.width; + width2 = e->data.cylinder.width2; + maxradius = (width > width2) ? width : width2; + + // get the start and end point of the frustum: + + VectorCopy(backEnd.viewParms.or.origin, vieworigin); + VectorCopy(e->axis[0], faxis); + VectorCopy(e->origin, bottom); + VectorScale(faxis, height, bottom2top); + VectorAdd(bottom, bottom2top, top); + + // Get distance from frustum: + // first distance from endpoints + VectorSubtract(vieworigin, bottom, bottom2origin); + VectorSubtract(vieworigin, top, top2origin); + + // get projection of view origin on the middle line: + distance = DotProduct(bottom2origin, faxis); + + startdistance = VectorLength(bottom2origin); + enddistance = VectorLength(top2origin); + + if(distance < 0 || distance > height) + { + // projected point is not between bottom and top. + distance = (startdistance < enddistance) ? startdistance : enddistance; + } + else + { + VectorMA(bottom, distance, faxis, projection); + VectorSubtract(vieworigin, projection, lodcalc); + distance = VectorLength(lodcalc); + + if(startdistance < distance) + distance = startdistance; + if(enddistance < distance) + distance = enddistance; + } + + planes = LOD_CONSTANT * maxradius/distance * CYLINDER_MAXPLANES; + + if(planes < 8) + planes = 8; + else if(planes > CYLINDER_MAXPLANES) + planes = CYLINDER_MAXPLANES; + + RB_CHECKOVERFLOW(4 * planes, 6 * planes); + + // create a normalized perpendicular vector to the frustum height. + PerpendicularVector(zerodeg_bottom, faxis); + + // This vector gets rotated to create the top ring + VectorScale(zerodeg_bottom, width2 / 2.0f, zerodeg_top); + // Likewise the vector for the lower ring: + VectorScale(zerodeg_bottom, width / 2.0f, zerodeg_bottom); + + anglestep = 360.0f / planes; + if(e->data.cylinder.wrap) + tcstep = e->data.cylinder.stscale / planes; + + ndx = tess.numVertexes; + numind = tess.numIndexes; + vertcols = tess.vertexColors; + + // this loop is creating all surface planes. + while(index < planes) + { + index++; + + // Set up the indexes for the new plane: + tess.indexes[numind++] = ndx; + tess.indexes[numind++] = ndx + 2; + tess.indexes[numind++] = ndx + 3; + + tess.indexes[numind++] = ndx; + tess.indexes[numind++] = ndx + 3; + tess.indexes[numind++] = ndx + 1; + + if(index <= 1) + { + VectorAdd(bottom, zerodeg_bottom, tess.xyz[ndx]); + VectorAdd(top, zerodeg_top, tess.xyz[ndx + 1]); + } + else + { + VectorCopy(bottomcorner, tess.xyz[ndx]); + VectorCopy(topcorner, tess.xyz[ndx + 1]); + } + + // Create on the right side two new vertices, first the bottom, then the top one. + if(index >= planes) + { + VectorAdd(bottom, zerodeg_bottom, bottomcorner); + VectorAdd(top, zerodeg_top, topcorner); + } + else + { + RotatePointAroundVector(bottomcorner, faxis, zerodeg_bottom, anglestep * index); + VectorAdd(bottom, bottomcorner, bottomcorner); + RotatePointAroundVector(topcorner, faxis, zerodeg_top, index * anglestep); + VectorAdd(top, topcorner, topcorner); + } + + VectorCopy(bottomcorner, tess.xyz[ndx + 2]); + VectorCopy(topcorner, tess.xyz[ndx + 3]); + + // Take care about the texture stuff + if(e->data.cylinder.wrap) + { + tess.texCoords[ndx][0][0] = tcstep * (index - 1); + tess.texCoords[ndx][0][1] = 0; + + tess.texCoords[ndx+1][0][0] = tcstep * (index - 1); + tess.texCoords[ndx+1][0][1] = 1; + + tess.texCoords[ndx+2][0][0] = tcstep * index; + tess.texCoords[ndx+2][0][1] = 0; + + tess.texCoords[ndx+3][0][0] = tcstep * index; + tess.texCoords[ndx+3][0][1] = 1; + } + else + { + tess.texCoords[ndx][0][0] = 0; + tess.texCoords[ndx][0][1] = 0; + + tess.texCoords[ndx+1][0][0] = 0; + tess.texCoords[ndx+1][0][1] = 1; + + tess.texCoords[ndx+2][0][0] = e->data.cylinder.stscale; + tess.texCoords[ndx+2][0][1] = 0; + + tess.texCoords[ndx+3][0][0] = e->data.cylinder.stscale; + tess.texCoords[ndx+3][0][1] = 1; + } + + vertcols[ndx][0] = vertcols[ndx+1][0] = vertcols[ndx+2][0] = vertcols[ndx+3][0] = e->shaderRGBA[0]; + vertcols[ndx][1] = vertcols[ndx+1][1] = vertcols[ndx+2][1] = vertcols[ndx+3][1] = e->shaderRGBA[1]; + vertcols[ndx][2] = vertcols[ndx+1][2] = vertcols[ndx+2][2] = vertcols[ndx+3][2] = e->shaderRGBA[2]; + vertcols[ndx][3] = vertcols[ndx+1][3] = vertcols[ndx+2][3] = vertcols[ndx+3][3] = 0xff; + + ndx += 4; + } + + tess.numVertexes = ndx; + tess.numIndexes = numind; +} + +// Draws lightning using a multisegment line with jumpy connecting points. +#define ELECTRICITY_SEGMENTS 16 +#define ELECTRICITY_STEPSIZE 1.0 / ELECTRICITY_SEGMENTS + +void RB_SurfaceElectricity(void) +{ + vec3_t start, end, linedirection, segstartpos, segendpos; + vec3_t prevend[2], left, start2origin, start2end; + refEntity_t *e = &backEnd.currentEntity->e; + float width, deviation, veclen; + int index; + + VectorCopy(e->origin, start); + VectorCopy(e->oldorigin, end); + VectorSubtract(end, start, start2end); + veclen = VectorLength(start2end); + + width = e->data.electricity.width; + deviation = e->data.electricity.deviation; + + VectorCopy(start, segendpos); + + for(index = 0; index < ELECTRICITY_SEGMENTS; index++) + { + VectorCopy(segendpos, segstartpos); + + if(index > ELECTRICITY_SEGMENTS - 2) + { + // This is the last segment. + VectorCopy(end, segendpos); + } + else + { + if(index > ELECTRICITY_SEGMENTS - 3) + { + // The line should have somewhat deviated by now. + // Make the last two segments go to the endpoint + + // get the middle point between startpos and endpos + VectorAdd(segstartpos, end, segendpos); + VectorScale(segendpos, 0.5f, segendpos); + } + + // Slightly misplace the next point on the line. + segendpos[PITCH] += (start2end[PITCH] + crandom() * deviation * veclen) * ELECTRICITY_STEPSIZE; + segendpos[YAW] += (start2end[YAW] + crandom() * deviation * veclen) * ELECTRICITY_STEPSIZE; + segendpos[ROLL] += (start2end[ROLL] + crandom() * deviation * veclen / 2.0) * ELECTRICITY_STEPSIZE; + } + + // Direction vector for the line: + VectorSubtract(segendpos, segstartpos, linedirection); + // Direction vector for the start to current point of view + VectorSubtract(backEnd.viewParms.or.origin, segstartpos, start2origin); + + RB_LineNormal(start2origin, linedirection, width, left); + + if(!index) + { + // this is our first segment, create the starting points + VectorAdd(segstartpos, left, prevend[0]); + VectorSubtract(segstartpos, left, prevend[1]); + } + + RB_Line(segstartpos, segendpos, linedirection, left, prevend, 0, e->data.electricity.stscale, e); + } +} +#endif + /* ** VectorArrayNormalize * @@ -1141,7 +1719,6 @@ static void RB_SurfaceGrid( srfGridMesh_t *cv ) { } } - /* =========================================================================== @@ -1186,6 +1763,9 @@ Entities that have a single procedurally generated surface */ static void RB_SurfaceEntity( surfaceType_t *surfType ) { switch( backEnd.currentEntity->e.reType ) { +#ifdef ELITEFORCE + case RT_ALPHAVERTPOLY: +#endif case RT_SPRITE: RB_SurfaceSprite(); break; @@ -1201,6 +1781,29 @@ static void RB_SurfaceEntity( surfaceType_t *surfType ) { case RT_LIGHTNING: RB_SurfaceLightningBolt(); break; +#ifdef ELITEFORCE + case RT_ORIENTEDSPRITE: + RB_SurfaceOrientedSprite(); + break; + case RT_LINE: + RB_SurfaceLine(); + break; + case RT_ORIENTEDLINE: + RB_SurfaceOrientedLine(); + break; + case RT_LINE2: + RB_SurfaceLine2(); + break; + case RT_BEZIER: + RB_SurfaceBezier(); + break; + case RT_CYLINDER: + RB_SurfaceCylinder(); + break; + case RT_ELECTRICITY: + RB_SurfaceElectricity(); + break; +#endif default: RB_SurfaceAxis(); break; diff --git a/code/server/sv_client.c b/code/server/sv_client.c index 4b1895e5..275c49a8 100644 --- a/code/server/sv_client.c +++ b/code/server/sv_client.c @@ -147,7 +147,11 @@ void SV_GetChallenge(netadr_t from) #ifndef STANDALONE // Drop the authorize stuff if this client is coming in via v6 as the auth server does not support ipv6. // Drop also for addresses coming in on local LAN and for stand-alone games independent from id's assets. +#ifdef ELITEFORCE if(challenge->adr.type == NA_IP && !com_standalone->integer && !Sys_IsLANAddress(from)) +#else + if(challenge->adr.type == NA_IP && !com_standalone->integer && !Sys_IsLANAddress(from)) +#endif { // look up the authorize server's IP if (svs.authorizeAddress.type == NA_BAD) @@ -175,12 +179,19 @@ void SV_GetChallenge(netadr_t from) Com_DPrintf( "authorize server timed out\n" ); else { - // otherwise send their ip to the authorize server +#ifndef ELITEFORCE cvar_t *fs; char game[1024]; +#endif Com_DPrintf( "sending getIpAuthorize for %s\n", NET_AdrToString( from )); - + + // otherwise send their ip to the authorize server +#ifdef ELITEFORCE + NET_OutOfBandPrint( NS_SERVER, svs.authorizeAddress, + "getIpAuthorize %i %i.%i.%i.%i ", challenge->challenge, + from.ip[0], from.ip[1], from.ip[2], from.ip[3] ); +#else strcpy(game, BASEGAME); fs = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO ); if (fs && fs->string[0] != 0) { @@ -192,7 +203,7 @@ void SV_GetChallenge(netadr_t from) NET_OutOfBandPrint( NS_SERVER, svs.authorizeAddress, "getIpAuthorize %i %i.%i.%i.%i %s 0 %s", challenge->challenge, from.ip[0], from.ip[1], from.ip[2], from.ip[3], game, sv_strictAuth->string ); - +#endif return; } } @@ -543,6 +554,7 @@ gotnewcl: ent = SV_GentityNum( clientNum ); newcl->gentity = ent; + // save the challenge newcl->challenge = challenge; @@ -669,7 +681,12 @@ void SV_DropClient( client_t *drop, const char *reason ) { VM_Call( gvm, GAME_CLIENT_DISCONNECT, drop - svs.clients ); // add the disconnect command - SV_SendServerCommand( drop, "disconnect \"%s\"", reason); +#ifdef ELITEFORCE + if(drop->compat) + SV_SendServerCommand( drop, "disconnect %s", reason); + else +#endif + SV_SendServerCommand( drop, "disconnect \"%s\"", reason); if ( isBot ) { SV_BotFreeClient( drop - svs.clients ); @@ -728,11 +745,23 @@ static void SV_SendClientGameState( client_t *client ) { // gamestate message was not just sent, forcing a retransmit client->gamestateMessageNum = client->netchan.outgoingSequence; - MSG_Init( &msg, msgBuffer, sizeof( msgBuffer ) ); +#ifdef ELITEFORCE + if(client->compat) + MSG_InitOOB(&msg, msgBuffer, sizeof( msgBuffer ) ); + else +#endif + MSG_Init( &msg, msgBuffer, sizeof( msgBuffer ) ); + +#ifdef ELITEFORCE + msg.compat = client->compat; +#endif // NOTE, MRE: all server->client messages now acknowledge // let the client know which reliable clientCommands we have received - MSG_WriteLong( &msg, client->lastClientCommand ); +#ifdef ELITEFORCE + if(!msg.compat) +#endif + MSG_WriteLong( &msg, client->lastClientCommand ); // send any server commands waiting to be sent first. // we have to do this cause we send the client->reliableSequence @@ -764,9 +793,17 @@ static void SV_SendClientGameState( client_t *client ) { MSG_WriteDeltaEntity( &msg, &nullstate, base, qtrue ); } - MSG_WriteByte( &msg, svc_EOF ); +#ifdef ELITEFORCE + if(msg.compat) + MSG_WriteByte(&msg, 0); + else +#endif + MSG_WriteByte( &msg, svc_EOF ); - MSG_WriteLong( &msg, client - svs.clients); +#ifdef ELITEFORCE + if(!msg.compat) +#endif + MSG_WriteLong( &msg, client - svs.clients); // write the checksum feed MSG_WriteLong( &msg, sv.checksumFeed); @@ -933,6 +970,9 @@ Fill up msg with data, return number of download blocks added int SV_WriteDownloadToClient(client_t *cl, msg_t *msg) { int curindex; +#ifndef ELITEFORCE + int missionPack = 0; +#endif int unreferenced = 1; char errorMessage[1024]; char pakbuf[MAX_QPATH], *pakptr; @@ -944,9 +984,11 @@ int SV_WriteDownloadToClient(client_t *cl, msg_t *msg) if(!cl->download) { qboolean idPack = qfalse; + #ifndef ELITEFORCE #ifndef STANDALONE qboolean missionPack = qfalse; #endif + #endif // Chop off filename extension. Com_sprintf(pakbuf, sizeof(pakbuf), "%s", cl->downloadName); @@ -975,8 +1017,12 @@ int SV_WriteDownloadToClient(client_t *cl, msg_t *msg) // now that we know the file is referenced, // check whether it's legal to download it. #ifndef STANDALONE + #ifdef ELITEFORCE + idPack = FS_idPak(pakbuf, BASEGAME, NUM_ID_PAKS); + #else missionPack = FS_idPak(pakbuf, BASETA, NUM_TA_PAKS); idPack = missionPack; + #endif #endif idPack = idPack || FS_idPak(pakbuf, BASEGAME, NUM_ID_PAKS); @@ -1000,6 +1046,10 @@ int SV_WriteDownloadToClient(client_t *cl, msg_t *msg) Com_sprintf(errorMessage, sizeof(errorMessage), "File \"%s\" is not referenced and cannot be downloaded.", cl->downloadName); } else if (idPack) { +#ifdef ELITEFORCE + Com_Printf("clientDownload: %d : \"%s\" cannot download Raven pk3 files\n", (int) (cl - svs.clients), cl->downloadName); + Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload Raven pk3 file \"%s\"", cl->downloadName); +#else Com_Printf("clientDownload: %d : \"%s\" cannot download id pk3 files\n", (int) (cl - svs.clients), cl->downloadName); #ifndef STANDALONE if(missionPack) @@ -1012,6 +1062,7 @@ int SV_WriteDownloadToClient(client_t *cl, msg_t *msg) { Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload id pk3 file \"%s\"", cl->downloadName); } +#endif } else if ( !(sv_allowDownload->integer & DLF_ENABLE) || (sv_allowDownload->integer & DLF_NO_UDP) ) { @@ -1036,7 +1087,10 @@ int SV_WriteDownloadToClient(client_t *cl, msg_t *msg) MSG_WriteByte( msg, svc_download ); MSG_WriteShort( msg, 0 ); // client is expecting block zero MSG_WriteLong( msg, -1 ); // illegal file size - MSG_WriteString( msg, errorMessage ); + #ifdef ELITEFORCE + if(!msg->compat) + #endif + MSG_WriteString( msg, errorMessage ); *cl->downloadName = 0; @@ -1248,21 +1302,28 @@ static void SV_VerifyPaks_f( client_t *cl ) { // start at arg 2 ( skip serverId cl_paks ) nCurArg = 1; - pArg = Cmd_Argv(nCurArg++); - if(!pArg) { - bGood = qfalse; - } - else + #ifdef ELITEFORCE + if(!cl->compat) { - // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=475 - // we may get incoming cp sequences from a previous checksumFeed, which we need to ignore - // since serverId is a frame count, it always goes up - if (atoi(pArg) < sv.checksumFeedServerId) - { - Com_DPrintf("ignoring outdated cp command from client %s\n", cl->name); - return; + #endif + pArg = Cmd_Argv(nCurArg++); + if(!pArg) { + bGood = qfalse; } + else + { + // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=475 + // we may get incoming cp sequences from a previous checksumFeed, which we need to ignore + // since serverId is a frame count, it always goes up + if (atoi(pArg) < sv.checksumFeedServerId) + { + Com_DPrintf("ignoring outdated cp command from client %s\n", cl->name); + return; + } + } + #ifdef ELITEFORCE } + #endif // we basically use this while loop to avoid using 'goto' :) while (bGood) { @@ -1676,7 +1737,10 @@ each of the backup packets. ================== */ static void SV_UserMove( client_t *cl, msg_t *msg, qboolean delta ) { - int i, key; + int i; +#ifndef ELITEFORCE + int key; +#endif int cmdCount; usercmd_t nullcmd; usercmd_t cmds[MAX_PACKET_USERCMDS]; @@ -1700,6 +1764,7 @@ static void SV_UserMove( client_t *cl, msg_t *msg, qboolean delta ) { return; } + #ifndef ELITEFORCE // use the checksum feed in the key key = sv.checksumFeed; // also use the message acknowledge @@ -1707,11 +1772,17 @@ static void SV_UserMove( client_t *cl, msg_t *msg, qboolean delta ) { // also use the last acknowledged server command in the key key ^= MSG_HashKey(cl->reliableCommands[ cl->reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ], 32); + #endif + Com_Memset( &nullcmd, 0, sizeof(nullcmd) ); oldcmd = &nullcmd; for ( i = 0 ; i < cmdCount ; i++ ) { cmd = &cmds[i]; + #ifdef ELITEFORCE + MSG_ReadDeltaUsercmd( msg, oldcmd, cmd ); + #else MSG_ReadDeltaUsercmdKey( msg, key, oldcmd, cmd ); + #endif oldcmd = cmd; } @@ -1902,7 +1973,10 @@ void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ) { int c; int serverId; - MSG_Bitstream(msg); +#ifdef ELITEFORCE + if(!msg->compat) + MSG_Bitstream(msg); +#endif serverId = MSG_ReadLong( msg ); cl->messageAcknowledge = MSG_ReadLong( msg ); @@ -1968,9 +2042,12 @@ void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ) { do { c = MSG_ReadByte( msg ); - if ( c == clc_EOF ) { + #ifdef ELITEFORCE + if(msg->compat && c == -1) + c = clc_EOF; + #endif + if ( c == clc_EOF ) break; - } if ( c != clc_clientCommand ) { break; diff --git a/code/server/sv_game.c b/code/server/sv_game.c index ebfa726c..2e053533 100644 --- a/code/server/sv_game.c +++ b/code/server/sv_game.c @@ -335,9 +335,10 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { return 0; case G_FS_GETFILELIST: return FS_GetFileList( VMA(1), VMA(2), VMA(3), args[4] ); +#ifndef ELITEFORCE case G_FS_SEEK: return FS_Seek( args[1], args[2], args[3] ); - +#endif case G_LOCATE_GAME_DATA: SV_LocateGameData( VMA(1), args[2], args[3], VMA(4), args[5] ); return 0; @@ -357,14 +358,18 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { return SV_AreaEntities( VMA(1), VMA(2), VMA(3), args[4] ); case G_ENTITY_CONTACT: return SV_EntityContact( VMA(1), VMA(2), VMA(3), /*int capsule*/ qfalse ); +#ifndef ELITEFORCE case G_ENTITY_CONTACTCAPSULE: return SV_EntityContact( VMA(1), VMA(2), VMA(3), /*int capsule*/ qtrue ); +#endif case G_TRACE: SV_Trace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qfalse ); return 0; +#ifndef ELITEFORCE case G_TRACECAPSULE: SV_Trace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qtrue ); return 0; +#endif case G_POINT_CONTENTS: return SV_PointContents( VMA(1), args[2] ); case G_SET_BRUSH_MODEL: @@ -423,12 +428,13 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { case G_DEBUG_POLYGON_DELETE: BotImport_DebugPolygonDelete( args[1] ); return 0; +#ifndef ELITEFORCE case G_REAL_TIME: return Com_RealTime( VMA(1) ); case G_SNAPVECTOR: Q_SnapVector(VMA(1)); return 0; - +#endif //==================================== case BOTLIB_SETUP: @@ -440,6 +446,10 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { case BOTLIB_LIBVAR_GET: return botlib_export->BotLibVarGet( VMA(1), VMA(2), args[3] ); +#ifdef ELITEFORCE + case BOTLIB_DEFINE: + return botlib_export->PC_AddGlobalDefine( VMA(1) ); +#else case BOTLIB_PC_ADD_GLOBAL_DEFINE: return botlib_export->PC_AddGlobalDefine( VMA(1) ); case BOTLIB_PC_LOAD_SOURCE: @@ -450,7 +460,7 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { return botlib_export->PC_ReadTokenHandle( args[1], VMA(2) ); case BOTLIB_PC_SOURCE_FILE_AND_LINE: return botlib_export->PC_SourceFileAndLine( args[1], VMA(2), VMA(3) ); - +#endif case BOTLIB_START_FRAME: return botlib_export->BotLibStartFrame( VMF(1) ); case BOTLIB_LOAD_MAP: @@ -467,13 +477,14 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { case BOTLIB_USER_COMMAND: SV_ClientThink( &svs.clients[args[1]], VMA(2) ); return 0; - +#ifndef ELITEFORCE case BOTLIB_AAS_BBOX_AREAS: return botlib_export->aas.AAS_BBoxAreas( VMA(1), VMA(2), VMA(3), args[4] ); case BOTLIB_AAS_AREA_INFO: return botlib_export->aas.AAS_AreaInfo( args[1], VMA(2) ); case BOTLIB_AAS_ALTERNATIVE_ROUTE_GOAL: return botlib_export->aas.AAS_AlternativeRouteGoals( VMA(1), args[2], VMA(3), args[4], args[5], VMA(6), args[7], args[8] ); +#endif case BOTLIB_AAS_ENTITY_INFO: botlib_export->aas.AAS_EntityInfo( args[1], VMA(2) ); return 0; @@ -488,8 +499,10 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { case BOTLIB_AAS_POINT_AREA_NUM: return botlib_export->aas.AAS_PointAreaNum( VMA(1) ); +#ifndef ELITEFORCE case BOTLIB_AAS_POINT_REACHABILITY_AREA_INDEX: return botlib_export->aas.AAS_PointReachabilityAreaIndex( VMA(1) ); +#endif case BOTLIB_AAS_TRACE_AREAS: return botlib_export->aas.AAS_TraceAreas( VMA(1), VMA(2), VMA(3), VMA(4), args[5] ); @@ -511,11 +524,12 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { case BOTLIB_AAS_AREA_TRAVEL_TIME_TO_GOAL_AREA: return botlib_export->aas.AAS_AreaTravelTimeToGoalArea( args[1], VMA(2), args[3], args[4] ); +#ifndef ELITEFORCE case BOTLIB_AAS_ENABLE_ROUTING_AREA: return botlib_export->aas.AAS_EnableRoutingArea( args[1], args[2] ); case BOTLIB_AAS_PREDICT_ROUTE: return botlib_export->aas.AAS_PredictRoute( VMA(1), args[2], VMA(3), args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11] ); - +#endif case BOTLIB_AAS_SWIMMING: return botlib_export->aas.AAS_Swimming( VMA(1) ); case BOTLIB_AAS_PREDICT_CLIENT_MOVEMENT: @@ -532,9 +546,11 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { botlib_export->ea.EA_Command( args[1], VMA(2) ); return 0; +#ifndef ELITEFORCE case BOTLIB_EA_ACTION: botlib_export->ea.EA_Action( args[1], args[2] ); return 0; +#endif case BOTLIB_EA_GESTURE: botlib_export->ea.EA_Gesture( args[1] ); return 0; @@ -664,7 +680,11 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { botlib_export->ai.BotSetChatGender( args[1], args[2] ); return 0; case BOTLIB_AI_SET_CHAT_NAME: +#ifdef ELITEFORCE + botlib_export->ai.BotSetChatName( args[1], VMA(2)); +#else botlib_export->ai.BotSetChatName( args[1], VMA(2), args[3] ); +#endif return 0; case BOTLIB_AI_RESET_GOAL_STATE: @@ -714,9 +734,11 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { return botlib_export->ai.BotGetMapLocationGoal( VMA(1), VMA(2) ); case BOTLIB_AI_AVOID_GOAL_TIME: return FloatAsInt( botlib_export->ai.BotAvoidGoalTime( args[1], args[2] ) ); +#ifndef ELITEFORCE case BOTLIB_AI_SET_AVOID_GOAL_TIME: botlib_export->ai.BotSetAvoidGoalTime( args[1], args[2], VMF(3)); return 0; +#endif case BOTLIB_AI_INIT_LEVEL_ITEMS: botlib_export->ai.BotInitLevelItems(); return 0; @@ -746,9 +768,11 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { case BOTLIB_AI_RESET_MOVE_STATE: botlib_export->ai.BotResetMoveState( args[1] ); return 0; +#ifndef ELITEFORCE case BOTLIB_AI_ADD_AVOID_SPOT: botlib_export->ai.BotAddAvoidSpot( args[1], VMA(2), VMF(3), args[4] ); return 0; +#endif case BOTLIB_AI_MOVE_TO_GOAL: botlib_export->ai.BotMoveToGoal( VMA(1), args[2], VMA(3), args[4] ); return 0; @@ -836,7 +860,23 @@ intptr_t SV_GameSystemCalls( intptr_t *args ) { case TRAP_CEIL: return FloatAsInt( ceil( VMF(1) ) ); - +#ifdef ELITEFORCE + case BOTLIB_EA_USE_ITEM: + botlib_export->ea.EA_UseItem(args[1], VMA(2)); + return 0; + case BOTLIB_EA_DROP_ITEM: + botlib_export->ea.EA_DropItem(args[1], VMA(2)); + return 0; + case BOTLIB_EA_USE_INV: + botlib_export->ea.EA_UseInv(args[1], VMA(2)); + return 0; + case BOTLIB_EA_DROP_INV: + botlib_export->ea.EA_DropInv(args[1], VMA(2)); + return 0; + case BOTLIB_EA_ALT_ATTACK: + botlib_export->ea.EA_Attack( args[1] ); + return 0; +#endif default: Com_Error( ERR_DROP, "Bad game system trap: %ld", (long int) args[0] ); } diff --git a/code/server/sv_init.c b/code/server/sv_init.c index 7332180b..e7cf7f45 100644 --- a/code/server/sv_init.c +++ b/code/server/sv_init.c @@ -667,7 +667,11 @@ void SV_Init (void) // server vars sv_rconPassword = Cvar_Get ("rconPassword", "", CVAR_TEMP ); sv_privatePassword = Cvar_Get ("sv_privatePassword", "", CVAR_TEMP ); + #ifdef ELITEFORCE + sv_fps = Cvar_Get ("sv_fps", "20", CVAR_SYSTEMINFO | CVAR_TEMP); + #else sv_fps = Cvar_Get ("sv_fps", "20", CVAR_TEMP ); + #endif sv_timeout = Cvar_Get ("sv_timeout", "200", CVAR_TEMP ); sv_zombietime = Cvar_Get ("sv_zombietime", "2", CVAR_TEMP ); Cvar_Get ("nextmap", "", CVAR_TEMP ); @@ -676,8 +680,12 @@ void SV_Init (void) Cvar_Get ("sv_dlURL", "", CVAR_SERVERINFO | CVAR_ARCHIVE); sv_master[0] = Cvar_Get("sv_master1", MASTER_SERVER_NAME, 0); + #ifdef ELITEFORCE + sv_master[1] = Cvar_Get("sv_master2", "efmaster.tjps.eu", CVAR_ARCHIVE); + #else sv_master[1] = Cvar_Get("sv_master2", "master.ioquake3.org", 0); - for(index = 2; index < MAX_MASTER_SERVERS; index++) + #endif + for(index = 1; index < MAX_MASTER_SERVERS; index++) sv_master[index] = Cvar_Get(va("sv_master%d", index + 1), "", CVAR_ARCHIVE); sv_reconnectlimit = Cvar_Get ("sv_reconnectlimit", "3", 0); @@ -723,7 +731,13 @@ void SV_FinalMessage( char *message ) { // don't send a disconnect to a local client if ( cl->netchan.remoteAddress.type != NA_LOOPBACK ) { SV_SendServerCommand( cl, "print \"%s\n\"\n", message ); - SV_SendServerCommand( cl, "disconnect \"%s\"", message ); + + #ifdef ELITEFORCE + if(cl->compat) + SV_SendServerCommand(cl, "disconnect Server shutdown: %s", message); + else + #endif + SV_SendServerCommand( cl, "disconnect \"%s\"", message ); } // force a snapshot to be sent cl->lastSnapshotTime = 0; diff --git a/code/server/sv_main.c b/code/server/sv_main.c index ed50707e..66abe0a9 100644 --- a/code/server/sv_main.c +++ b/code/server/sv_main.c @@ -320,11 +320,19 @@ void SV_MasterHeartbeat(const char *message) // this command should be changed if the server info / status format // ever incompatably changes - + #ifdef ELITEFORCE + if(adr[i][0].type != NA_BAD) + NET_OutOfBandPrint(NS_SERVER, adr[i][0], "\\heartbeat\\%d\\gamename\\%s\\", + Cvar_VariableIntegerValue("net_port"), message); + if(adr[i][1].type != NA_BAD) + NET_OutOfBandPrint(NS_SERVER, adr[i][1], "\\heartbeat\\%d\\gamename\\%s\\", + Cvar_VariableIntegerValue("net_port6"), message); + #else if(adr[i][0].type != NA_BAD) NET_OutOfBandPrint( NS_SERVER, adr[i][0], "heartbeat %s\n", message); if(adr[i][1].type != NA_BAD) NET_OutOfBandPrint( NS_SERVER, adr[i][1], "heartbeat %s\n", message); + #endif } } @@ -681,7 +689,11 @@ void SVC_Info( netadr_t from ) { Info_SetValueForKey( infostring, "game", gamedir ); } +#ifdef ELITEFORCE + NET_OutOfBandPrint( NS_SERVER, from, "infoResponse \"%s\"", infostring ); +#else NET_OutOfBandPrint( NS_SERVER, from, "infoResponse\n%s", infostring ); +#endif } /* @@ -786,9 +798,11 @@ static void SV_ConnectionlessPacket( netadr_t from, msg_t *msg ) { MSG_BeginReadingOOB( msg ); MSG_ReadLong( msg ); // skip the -1 marker +#ifndef ELITEFORCE if (!Q_strncmp("connect", (char *) &msg->data[4], 7)) { Huff_Decompress(msg, 12); } +#endif s = MSG_ReadStringLine( msg ); Cmd_TokenizeString( s ); @@ -866,6 +880,10 @@ void SV_PacketEvent( netadr_t from, msg_t *msg ) { cl->netchan.remoteAddress.port = from.port; } + #ifdef ELITEFORCE + msg->compat = cl->compat; + #endif + // make sure it is a valid, in sequence packet if (SV_Netchan_Process(cl, msg)) { // zombie clients still need to do the Netchan_Process diff --git a/code/server/sv_net_chan.c b/code/server/sv_net_chan.c index 66832630..3f346961 100644 --- a/code/server/sv_net_chan.c +++ b/code/server/sv_net_chan.c @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../qcommon/qcommon.h" #include "server.h" +#ifndef ELITEFORCE #ifdef LEGACY_PROTOCOL /* ============== @@ -130,7 +131,7 @@ static void SV_Netchan_Decode( client_t *client, msg_t *msg ) { } } #endif - +#endif /* @@ -164,9 +165,11 @@ void SV_Netchan_TransmitNextInQueue(client_t *client) Com_DPrintf("#462 Netchan_TransmitNextFragment: popping a queued message for transmit\n"); netbuf = client->netchan_start_queue; +#ifndef ELITEFORCE #ifdef LEGACY_PROTOCOL if(client->compat) SV_Netchan_Encode(client, &netbuf->msg, netbuf->clientCommandString); +#endif #endif Netchan_Transmit(&client->netchan, netbuf->msg.cursize, netbuf->msg.data); @@ -223,7 +226,11 @@ then buffer them and make sure they get sent in correct order void SV_Netchan_Transmit( client_t *client, msg_t *msg) { - MSG_WriteByte( msg, svc_EOF ); + #ifdef ELITEFORCE + if(!msg->compat) + #endif + MSG_WriteByte( msg, svc_EOF ); + if(client->netchan.unsentFragments || client->netchan_start_queue) { @@ -246,9 +253,11 @@ void SV_Netchan_Transmit( client_t *client, msg_t *msg) } else { +#ifndef ELITEFORCE #ifdef LEGACY_PROTOCOL if(client->compat) SV_Netchan_Encode(client, msg, client->lastClientCommandString); +#endif #endif Netchan_Transmit( &client->netchan, msg->cursize, msg->data ); } @@ -264,12 +273,12 @@ qboolean SV_Netchan_Process( client_t *client, msg_t *msg ) { ret = Netchan_Process( &client->netchan, msg ); if (!ret) return qfalse; - +#ifndef ELITEFORCE #ifdef LEGACY_PROTOCOL if(client->compat) SV_Netchan_Decode(client, msg); #endif - +#endif return qtrue; } diff --git a/code/server/sv_snapshot.c b/code/server/sv_snapshot.c index 6e4f2907..f7333ab7 100644 --- a/code/server/sv_snapshot.c +++ b/code/server/sv_snapshot.c @@ -154,6 +154,12 @@ static void SV_WriteSnapshotToClient( client_t *client, msg_t *msg ) { MSG_WriteByte (msg, svc_snapshot); + #ifdef ELITEFORCE + if(msg->compat) + #endif + MSG_WriteLong( msg, client->lastClientCommand ); + + // NOTE, MRE: now sent at the start of every message from server to client // let the client know which reliable clientCommands we have received //MSG_WriteLong( msg, client->lastClientCommand ); @@ -413,6 +419,7 @@ static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *fra // if it's a portal entity, add everything visible from its camera position if ( ent->r.svFlags & SVF_PORTAL ) { +#ifndef ELITEFORCE if ( ent->s.generic1 ) { vec3_t dir; VectorSubtract(ent->s.origin, origin, dir); @@ -420,6 +427,7 @@ static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *fra continue; } } +#endif SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue ); } @@ -607,12 +615,23 @@ void SV_SendClientSnapshot( client_t *client ) { return; } - MSG_Init (&msg, msg_buf, sizeof(msg_buf)); +#ifdef ELITEFORCE + if(client->compat) + { + MSG_InitOOB(&msg, msg_buf, sizeof(msg_buf)); + msg.compat = qtrue; + } + else +#endif + MSG_Init (&msg, msg_buf, sizeof(msg_buf)); msg.allowoverflow = qtrue; // NOTE, MRE: all server->client messages now acknowledge // let the client know which reliable clientCommands we have received - MSG_WriteLong( &msg, client->lastClientCommand ); +#ifdef ELITEFORCE + if(!client->compat) +#endif + MSG_WriteLong( &msg, client->lastClientCommand ); // (re)send any reliable server commands SV_UpdateServerCommandsToClient( client, &msg ); diff --git a/code/server/sv_world.c b/code/server/sv_world.c index 94868142..2c666ef7 100644 --- a/code/server/sv_world.c +++ b/code/server/sv_world.c @@ -222,28 +222,88 @@ void SV_LinkEntity( sharedEntity_t *gEnt ) { // encode the size into the entityState_t for client prediction if ( gEnt->r.bmodel ) { gEnt->s.solid = SOLID_BMODEL; // a solid_box will never create this value +#ifdef ELITEFORCE + } else if ( gEnt->r.contents & ( CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_SHOTCLIP ) ) { + if(gEnt->r.svFlags & SVF_SHIELD_BBOX) + { + if(gEnt->s.time2 & (1 << 24)) + { + i = gEnt->r.maxs[0]; + if (i<1) + i = 1; + if (i>255) + i = 255; + + // z is not symetric + j = -gEnt->r.mins[0]; + if (j<1) + j = 1; + if (j>255) + j = 255; + + // and z maxs can be negative... + k = gEnt->r.maxs[2]; + if (k<1) + k = 1; + if (k>255) + k = 255; + + gEnt->s.eFlags |= EF_SHIELD_BOX_X; + } + else + { + i = gEnt->r.maxs[1]; + if (i<1) + i = 1; + if (i>255) + i = 255; + + // z is not symetric + j = -gEnt->r.mins[1]; + if (j<1) + j = 1; + if (j>255) + j = 255; + + // and z maxs can be negative... + k = gEnt->r.maxs[2]; + if (k<1) + k = 1; + if (k>255) + k = 255; + + gEnt->s.eFlags |= EF_SHIELD_BOX_Y; + } + } + else + { +#else } else if ( gEnt->r.contents & ( CONTENTS_SOLID | CONTENTS_BODY ) ) { - // assume that x/y are equal and symetric - i = gEnt->r.maxs[0]; - if (i<1) - i = 1; - if (i>255) - i = 255; +#endif + // assume that x/y are equal and symetric + i = gEnt->r.maxs[0]; + if (i<1) + i = 1; + if (i>255) + i = 255; - // z is not symetric - j = (-gEnt->r.mins[2]); - if (j<1) - j = 1; - if (j>255) - j = 255; - - // and z maxs can be negative... - k = (gEnt->r.maxs[2]+32); - if (k<1) - k = 1; - if (k>255) - k = 255; + // z is not symetric + j = (-gEnt->r.mins[2]); + if (j<1) + j = 1; + if (j>255) + j = 255; + // and z maxs can be negative... + k = (gEnt->r.maxs[2]+32); + if (k<1) + k = 1; + if (k>255) + k = 255; +#ifdef ELITEFORCE + } +#endif + gEnt->s.solid = (k<<16) | (j<<8) | i; } else { gEnt->s.solid = 0; diff --git a/code/sys/sys_unix.c b/code/sys/sys_unix.c index 98e89dd0..4796a329 100644 --- a/code/sys/sys_unix.c +++ b/code/sys/sys_unix.c @@ -58,7 +58,14 @@ char *Sys_DefaultHomePath(void) if( ( p = getenv( "HOME" ) ) != NULL ) { Com_sprintf(homePath, sizeof(homePath), "%s%c", p, PATH_SEP); -#ifdef MACOS_X +#ifdef ELITEFORCE + #ifdef MACOS_X + Q_strcat(homePath, sizeof(homePath), "/Library/Application Support/STVEF"); + #else + Q_strcat(homePath, sizeof(homePath), "/.stvef"); + #endif +#else + #ifdef MACOS_X Q_strcat(homePath, sizeof(homePath), "Library/Application Support/"); @@ -66,11 +73,12 @@ char *Sys_DefaultHomePath(void) Q_strcat(homePath, sizeof(homePath), com_homepath->string); else Q_strcat(homePath, sizeof(homePath), HOMEPATH_NAME_MACOSX); -#else + #else if(com_homepath->string[0]) Q_strcat(homePath, sizeof(homePath), com_homepath->string); else Q_strcat(homePath, sizeof(homePath), HOMEPATH_NAME_UNIX); + #endif #endif } } diff --git a/code/ui/ui_public.h b/code/ui/ui_public.h index bcc72356..a2eea8ad 100644 --- a/code/ui/ui_public.h +++ b/code/ui/ui_public.h @@ -81,6 +81,12 @@ typedef enum { UI_GETGLCONFIG, UI_GETCLIENTSTATE, UI_GETCONFIGSTRING, +#ifdef ELITEFORCE + UI_LAN_GETLOCALSERVERCOUNT, + UI_LAN_GETLOCALSERVERADDRESSSTRING, + UI_LAN_GETGLOBALSERVERCOUNT, + UI_LAN_GETGLOBALSERVERADDRESSSTRING, +#endif UI_LAN_GETPINGQUEUECOUNT, UI_LAN_CLEARPING, UI_LAN_GETPING, @@ -88,6 +94,10 @@ typedef enum { UI_CVAR_REGISTER, UI_CVAR_UPDATE, UI_MEMORY_REMAINING, +#ifdef ELITEFORCE + UI_SET_CDKEY, + UI_R_MODELBOUNDS, +#else UI_GET_CDKEY, UI_SET_CDKEY, UI_R_REGISTERFONT, @@ -124,6 +134,7 @@ typedef enum { // 1.32 UI_FS_SEEK, UI_SET_PBCLSTATUS, +#endif UI_MEMSET = 100, UI_MEMCPY, @@ -182,7 +193,9 @@ typedef enum { UI_DRAW_CONNECT_SCREEN, // void UI_DrawConnectScreen( qboolean overlay ); +#ifndef ELITEFORCE UI_HASUNIQUECDKEY +#endif // if !overlay, the background will be drawn, otherwise it will be // overlayed over whatever the cgame has drawn. // a GetClientState syscall will be made to get the current strings