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.
This commit is contained in:
Zack Middleton 2014-10-29 07:15:12 -05:00
parent 4d666212b2
commit c6e5f060fe
62 changed files with 3124 additions and 292 deletions

View File

@ -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

View File

@ -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
};
//===========================================================================

View File

@ -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();

View File

@ -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

View File

@ -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++)

View File

@ -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;

View File

@ -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
//===========================================================================
//

View File

@ -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);

View File

@ -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;

View File

@ -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
//-----------------------------------

View File

@ -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;
//----------------------------------------------

View File

@ -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] );

View File

@ -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)] );

View File

@ -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");

View File

@ -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
}
/*

View File

@ -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++)
{

View File

@ -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;

View File

@ -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;
}

View File

@ -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
/*
==================

View File

@ -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

View File

@ -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 );

View File

@ -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);

View File

@ -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
}
/*

View File

@ -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) {

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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];

View File

@ -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) {

View File

@ -31,15 +31,24 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <winsock.h>
#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

View File

@ -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)

View File

@ -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<length;i++) {
MSG_WriteByte(buf, ((byte *)data)[i]);
}
@ -311,7 +384,11 @@ void MSG_WriteString( msg_t *sb, const char *s ) {
if ( !s ) {
MSG_WriteData (sb, "", 1);
} else {
#ifdef ELITEFORCE
int l;
#else
int l,i;
#endif
char string[MAX_STRING_CHARS];
l = strlen( s );
@ -322,12 +399,14 @@ void MSG_WriteString( 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);
}
@ -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 ; i<len ; i++) {
((byte *)data)[i] = MSG_ReadByte (msg);
}
@ -685,7 +795,11 @@ void MSG_WriteDeltaUsercmd( msg_t *msg, usercmd_t *from, usercmd_t *to ) {
MSG_WriteDelta( msg, from->forwardmove, 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];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 = &playerStateFields[lc];i<numFields; i++, field++) {
fromF = (int *)( (byte *)from + field->offset );
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");

View File

@ -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;
}

View File

@ -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

View File

@ -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 )
{

View File

@ -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 {

View File

@ -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 );

View File

@ -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

View File

@ -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

View File

@ -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));
}

View File

@ -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

View File

@ -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<<REFENTITYNUM_BITS) - 1)
@ -39,25 +39,34 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define RF_FIRST_PERSON 0x0004 // only draw through eyes (view weapon, damage blood blob)
#define RF_DEPTHHACK 0x0008 // for view weapon Z crunching
#define RF_CROSSHAIR 0x0010 // This item is a cross hair and will draw over everything similar to
#ifdef ELITEFORCE
#define RF_FULLBRIGHT 0x0010
#define RF_CROSSHAIR 0x0020 // This item is a cross hair and will draw over everything similar to
// DEPTHHACK in stereo rendering mode, with the difference that the
// projection matrix won't be hacked to reduce the stereo separation as
// is done for the gun.
#else
#define RF_CROSSHAIR 0x0010
#endif
#define RF_NOSHADOW 0x0040 // don't add stencil shadows
#define RF_LIGHTING_ORIGIN 0x0080 // use refEntity->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

View File

@ -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 );

View File

@ -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;

View File

@ -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
//

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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] );
}

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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 );

View File

@ -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;

View File

@ -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
}
}

View File

@ -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