mirror of
https://github.com/YGGverse/xash3d-fwgs.git
synced 2025-01-24 22:04:21 +00:00
Dedicated build
This commit is contained in:
parent
40094f2867
commit
5d13112e25
@ -2769,7 +2769,7 @@ void CL_Init( void )
|
||||
IN_TouchInit();
|
||||
|
||||
COM_ResetLibraryError();
|
||||
if( !CL_LoadProgs( va( "%s/%s", GI->dll_path, GI->client_lib)))
|
||||
if( !CL_LoadProgs( va( "%s/%s", GI->dll_path, SI.clientlib)))
|
||||
Host_Error( "can't initialize client.dll\n" );
|
||||
|
||||
cls.initialized = true;
|
||||
|
@ -1238,72 +1238,6 @@ void Con_Print( const char *txt )
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Con_Printf
|
||||
|
||||
=============
|
||||
*/
|
||||
void Con_Printf( char *szFmt, ... )
|
||||
{
|
||||
static char buffer[MAX_PRINT_MSG];
|
||||
va_list args;
|
||||
|
||||
if( !host.allow_console )
|
||||
return;
|
||||
|
||||
va_start( args, szFmt );
|
||||
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
|
||||
va_end( args );
|
||||
|
||||
Sys_Print( buffer );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Con_DPrintf
|
||||
|
||||
=============
|
||||
*/
|
||||
void Con_DPrintf( char *szFmt, ... )
|
||||
{
|
||||
static char buffer[MAX_PRINT_MSG];
|
||||
va_list args;
|
||||
|
||||
if( host_developer.value < DEV_NORMAL )
|
||||
return;
|
||||
|
||||
va_start( args, szFmt );
|
||||
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
|
||||
va_end( args );
|
||||
|
||||
if( buffer[0] == '0' && buffer[1] == '\n' && buffer[2] == '\0' )
|
||||
return; // hlrally spam
|
||||
|
||||
Sys_Print( buffer );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Con_Reportf
|
||||
|
||||
=============
|
||||
*/
|
||||
void Con_Reportf( char *szFmt, ... )
|
||||
{
|
||||
static char buffer[MAX_PRINT_MSG];
|
||||
va_list args;
|
||||
|
||||
if( host_developer.value < DEV_EXTENDED )
|
||||
return;
|
||||
|
||||
va_start( args, szFmt );
|
||||
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
|
||||
va_end( args );
|
||||
|
||||
Sys_Print( buffer );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Con_NPrint
|
||||
|
@ -718,56 +718,6 @@ float CL_GetSequenceDuration( cl_entity_t *ent, int sequence )
|
||||
return 0.1f;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioGetAnim
|
||||
|
||||
====================
|
||||
*/
|
||||
void *R_StudioGetAnim( studiohdr_t *m_pStudioHeader, model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc )
|
||||
{
|
||||
mstudioseqgroup_t *pseqgroup;
|
||||
cache_user_t *paSequences;
|
||||
size_t filesize;
|
||||
byte *buf;
|
||||
|
||||
pseqgroup = (mstudioseqgroup_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqgroupindex) + pseqdesc->seqgroup;
|
||||
if( pseqdesc->seqgroup == 0 )
|
||||
return ((byte *)m_pStudioHeader + pseqgroup->data + pseqdesc->animindex);
|
||||
|
||||
paSequences = (cache_user_t *)m_pSubModel->submodels;
|
||||
|
||||
if( paSequences == NULL )
|
||||
{
|
||||
paSequences = (cache_user_t *)Mem_Alloc( com_studiocache, MAXSTUDIOGROUPS * sizeof( cache_user_t ));
|
||||
m_pSubModel->submodels = (void *)paSequences;
|
||||
}
|
||||
|
||||
// check for already loaded
|
||||
if( !Mod_CacheCheck(( cache_user_t *)&( paSequences[pseqdesc->seqgroup] )))
|
||||
{
|
||||
string filepath, modelname, modelpath;
|
||||
|
||||
COM_FileBase( m_pSubModel->name, modelname );
|
||||
COM_ExtractFilePath( m_pSubModel->name, modelpath );
|
||||
|
||||
// NOTE: here we build real sub-animation filename because stupid user may rename model without recompile
|
||||
Q_snprintf( filepath, sizeof( filepath ), "%s/%s%i%i.mdl", modelpath, modelname, pseqdesc->seqgroup / 10, pseqdesc->seqgroup % 10 );
|
||||
|
||||
buf = FS_LoadFile( filepath, &filesize, false );
|
||||
if( !buf || !filesize ) Host_Error( "StudioGetAnim: can't load %s\n", filepath );
|
||||
if( IDSEQGRPHEADER != *(uint *)buf ) Host_Error( "StudioGetAnim: %s is corrupted\n", filepath );
|
||||
|
||||
Con_Printf( "loading: %s\n", filepath );
|
||||
|
||||
paSequences[pseqdesc->seqgroup].data = Mem_Alloc( com_studiocache, filesize );
|
||||
memcpy( paSequences[pseqdesc->seqgroup].data, buf, filesize );
|
||||
Mem_Free( buf );
|
||||
}
|
||||
|
||||
return ((byte *)paSequences[pseqdesc->seqgroup].data + pseqdesc->animindex);
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioFxTransform
|
||||
@ -877,197 +827,6 @@ void R_StudioCalcBoneAdj( float dadt, float *adj, const byte *pcontroller1, cons
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioCalcBoneQuaternion
|
||||
|
||||
====================
|
||||
*/
|
||||
void R_StudioCalcBoneQuaternion( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, vec4_t q )
|
||||
{
|
||||
vec3_t angles1;
|
||||
vec3_t angles2;
|
||||
int j, k;
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
if( !panim || panim->offset[j+3] == 0 )
|
||||
{
|
||||
angles2[j] = angles1[j] = pbone->value[j+3]; // default;
|
||||
}
|
||||
else
|
||||
{
|
||||
mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]);
|
||||
|
||||
k = frame;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
|
||||
// find span of values that includes the frame we want
|
||||
while( panimvalue->num.total <= k )
|
||||
{
|
||||
k -= panimvalue->num.total;
|
||||
panimvalue += panimvalue->num.valid + 1;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
}
|
||||
|
||||
// bah, missing blend!
|
||||
if( panimvalue->num.valid > k )
|
||||
{
|
||||
angles1[j] = panimvalue[k+1].value;
|
||||
|
||||
if( panimvalue->num.valid > k + 1 )
|
||||
{
|
||||
angles2[j] = panimvalue[k+2].value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
angles2[j] = angles1[j];
|
||||
else angles2[j] = panimvalue[panimvalue->num.valid+2].value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
angles1[j] = panimvalue[panimvalue->num.valid].value;
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
angles2[j] = angles1[j];
|
||||
else angles2[j] = panimvalue[panimvalue->num.valid+2].value;
|
||||
}
|
||||
|
||||
angles1[j] = pbone->value[j+3] + angles1[j] * pbone->scale[j+3];
|
||||
angles2[j] = pbone->value[j+3] + angles2[j] * pbone->scale[j+3];
|
||||
}
|
||||
|
||||
if( pbone->bonecontroller[j+3] != -1 && adj != NULL )
|
||||
{
|
||||
angles1[j] += adj[pbone->bonecontroller[j+3]];
|
||||
angles2[j] += adj[pbone->bonecontroller[j+3]];
|
||||
}
|
||||
}
|
||||
|
||||
if( !VectorCompare( angles1, angles2 ))
|
||||
{
|
||||
vec4_t q1, q2;
|
||||
|
||||
AngleQuaternion( angles1, q1, true );
|
||||
AngleQuaternion( angles2, q2, true );
|
||||
QuaternionSlerp( q1, q2, s, q );
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleQuaternion( angles1, q, true );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioCalcBonePosition
|
||||
|
||||
====================
|
||||
*/
|
||||
void R_StudioCalcBonePosition( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, vec3_t pos )
|
||||
{
|
||||
vec3_t origin1;
|
||||
vec3_t origin2;
|
||||
int j, k;
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
if( !panim || panim->offset[j] == 0 )
|
||||
{
|
||||
origin2[j] = origin1[j] = pbone->value[j]; // default;
|
||||
}
|
||||
else
|
||||
{
|
||||
mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]);
|
||||
|
||||
k = frame;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
|
||||
// find span of values that includes the frame we want
|
||||
while( panimvalue->num.total <= k )
|
||||
{
|
||||
k -= panimvalue->num.total;
|
||||
panimvalue += panimvalue->num.valid + 1;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
}
|
||||
|
||||
// bah, missing blend!
|
||||
if( panimvalue->num.valid > k )
|
||||
{
|
||||
origin1[j] = panimvalue[k+1].value;
|
||||
|
||||
if( panimvalue->num.valid > k + 1 )
|
||||
{
|
||||
origin2[j] = panimvalue[k+2].value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
origin2[j] = origin1[j];
|
||||
else origin2[j] = panimvalue[panimvalue->num.valid+2].value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
origin1[j] = panimvalue[panimvalue->num.valid].value;
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
origin2[j] = origin1[j];
|
||||
else origin2[j] = panimvalue[panimvalue->num.valid+2].value;
|
||||
}
|
||||
|
||||
origin1[j] = pbone->value[j] + origin1[j] * pbone->scale[j];
|
||||
origin2[j] = pbone->value[j] + origin2[j] * pbone->scale[j];
|
||||
}
|
||||
|
||||
if( pbone->bonecontroller[j] != -1 && adj != NULL )
|
||||
{
|
||||
origin1[j] += adj[pbone->bonecontroller[j]];
|
||||
origin2[j] += adj[pbone->bonecontroller[j]];
|
||||
}
|
||||
}
|
||||
|
||||
if( !VectorCompare( origin1, origin2 ))
|
||||
{
|
||||
VectorLerp( origin1, s, origin2, pos );
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy( origin1, pos );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioSlerpBones
|
||||
|
||||
====================
|
||||
*/
|
||||
void R_StudioSlerpBones( int numbones, vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s )
|
||||
{
|
||||
int i;
|
||||
|
||||
s = bound( 0.0f, s, 1.0f );
|
||||
|
||||
for( i = 0; i < numbones; i++ )
|
||||
{
|
||||
QuaternionSlerp( q1[i], q2[i], s, q1[i] );
|
||||
VectorLerp( pos1[i], s, pos2[i], pos1[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioCalcRotations
|
||||
|
@ -977,13 +977,16 @@ void Cmd_ExecuteString( char *text )
|
||||
if( host.apply_game_config )
|
||||
return; // don't send nothing to server: we is a server!
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
// forward the command line to the server, so the entity DLL can parse it
|
||||
if( host.type == HOST_NORMAL )
|
||||
{
|
||||
if( cls.state >= ca_connected )
|
||||
Cmd_ForwardToServer();
|
||||
}
|
||||
else if( text[0] != '@' && host.type == HOST_NORMAL )
|
||||
else
|
||||
#endif
|
||||
if( text[0] != '@' && host.type == HOST_NORMAL )
|
||||
{
|
||||
// commands with leading '@' are hidden system commands
|
||||
Con_Printf( S_WARN "Unknown command \"%s\"\n", text );
|
||||
@ -999,6 +1002,7 @@ things like godmode, noclip, etc, are commands directed to the server,
|
||||
so when they are typed in at the console, they will need to be forwarded.
|
||||
===================
|
||||
*/
|
||||
#ifndef XASH_DEDICATED
|
||||
void Cmd_ForwardToServer( void )
|
||||
{
|
||||
char str[MAX_CMD_BUFFER];
|
||||
@ -1032,6 +1036,7 @@ void Cmd_ForwardToServer( void )
|
||||
|
||||
MSG_WriteString( &cls.netchan.message, str );
|
||||
}
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
/*
|
||||
============
|
||||
@ -1141,7 +1146,9 @@ void Cmd_Init( void )
|
||||
Cmd_AddCommand( "wait", Cmd_Wait_f, "make script execution wait for some rendered frames" );
|
||||
Cmd_AddCommand( "cmdlist", Cmd_List_f, "display all console commands beginning with the specified prefix" );
|
||||
Cmd_AddCommand( "stuffcmds", Cmd_StuffCmds_f, "execute commandline parameters (must be present in .rc script)" );
|
||||
#ifndef XASH_DEDICATED
|
||||
Cmd_AddCommand( "cmd", Cmd_ForwardToServer, "send a console commandline to the server" );
|
||||
#endif
|
||||
Cmd_AddCommand( "alias", Cmd_Alias_f, "create a script function. Without arguments show the list of all alias" );
|
||||
Cmd_AddCommand( "unalias", Cmd_UnAlias_f, "remove a script function" );
|
||||
Cmd_AddCommand( "if", Cmd_If_f, "compare and set condition bits" );
|
||||
|
@ -301,6 +301,8 @@ typedef struct sysinfo_s
|
||||
string exeName; // exe.filename
|
||||
string rcName; // .rc script name
|
||||
string basedirName; // name of base directory
|
||||
string gamedll;
|
||||
string clientlib;
|
||||
gameinfo_t *GameInfo; // current GameInfo
|
||||
gameinfo_t *games[MAX_MODS]; // environment games (founded at each engine start)
|
||||
int numgames;
|
||||
|
@ -464,6 +464,7 @@ qboolean Cmd_GetSoundList( const char *s, char *completedname, int length )
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetItemsList
|
||||
@ -510,6 +511,7 @@ qboolean Cmd_GetItemsList( const char *s, char *completedname, int length )
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
=====================================
|
||||
@ -817,8 +819,10 @@ autocomplete_list_t cmd_list[] =
|
||||
{ "music", Cmd_GetMusicList, },
|
||||
{ "movie", Cmd_GetMovieList },
|
||||
{ "exec", Cmd_GetConfigList },
|
||||
#ifndef XASH_DEDICATED
|
||||
{ "give", Cmd_GetItemsList },
|
||||
{ "drop", Cmd_GetItemsList },
|
||||
#endif
|
||||
{ "game", Cmd_GetGamesList },
|
||||
{ "save", Cmd_GetSavesList },
|
||||
{ "load", Cmd_GetSavesList },
|
||||
@ -901,6 +905,7 @@ void Cmd_WriteOpenGLVariables( file_t *f )
|
||||
Cvar_LookupVars( FCVAR_GLCONFIG, NULL, f, Cmd_WriteOpenGLCvar );
|
||||
}
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
/*
|
||||
===============
|
||||
Host_WriteConfig
|
||||
@ -946,6 +951,7 @@ void Host_WriteConfig( void )
|
||||
}
|
||||
else MsgDev( D_ERROR, "Couldn't write config.cfg.\n" );
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
===============
|
||||
|
@ -44,11 +44,13 @@ void COM_ClearCustomizationList( customization_t *pHead, qboolean bCleanDecals )
|
||||
|
||||
if( pCurrent->bInUse && pCurrent->pInfo )
|
||||
{
|
||||
#ifndef XASH_DEDICATED
|
||||
if( pCurrent->resource.type == t_decal )
|
||||
{
|
||||
if( bCleanDecals && CL_Active( ))
|
||||
R_DecalRemoveAll( pCurrent->nUserData1 );
|
||||
}
|
||||
#endif
|
||||
|
||||
FS_FreeImage( pCurrent->pInfo );
|
||||
}
|
||||
|
@ -90,12 +90,13 @@ static qboolean Cvar_UpdateInfo( convar_t *var, const char *value, qboolean noti
|
||||
{
|
||||
if( FBitSet( var->flags, FCVAR_USERINFO ))
|
||||
{
|
||||
if ( host.type == HOST_DEDICATED )
|
||||
if ( Host_IsDedicated() )
|
||||
{
|
||||
// g-cont. this is a very strange behavior...
|
||||
Info_SetValueForKey( SV_Serverinfo(), var->name, value, MAX_SERVERINFO_STRING ),
|
||||
SV_BroadcastCommand( "fullserverinfo \"%s\"\n", SV_Serverinfo( ));
|
||||
}
|
||||
#ifndef XASH_DEDICATED
|
||||
else
|
||||
{
|
||||
if( !Info_SetValueForKey( CL_Userinfo(), var->name, value, MAX_INFO_STRING ))
|
||||
@ -104,6 +105,7 @@ static qboolean Cvar_UpdateInfo( convar_t *var, const char *value, qboolean noti
|
||||
// time to update server copy of userinfo
|
||||
CL_ServerCommand( true, "setinfo \"%s\" \"%s\"\n", var->name, value );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if( FBitSet( var->flags, FCVAR_SERVER ) && notify )
|
||||
|
497
engine/common/dedicated.c
Normal file
497
engine/common/dedicated.c
Normal file
@ -0,0 +1,497 @@
|
||||
/*
|
||||
dedicated.c - stubs for dedicated server
|
||||
Copyright (C) 2018 a1batross, mittorn
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
#ifdef XASH_DEDICATED
|
||||
#include "common.h"
|
||||
#include "mathlib.h"
|
||||
|
||||
const char *svc_strings[256] =
|
||||
{
|
||||
"svc_bad",
|
||||
"svc_nop",
|
||||
"svc_disconnect",
|
||||
"svc_changing",
|
||||
"svc_version",
|
||||
"svc_setview",
|
||||
"svc_sound",
|
||||
"svc_time",
|
||||
"svc_print",
|
||||
"svc_stufftext",
|
||||
"svc_setangle",
|
||||
"svc_serverdata",
|
||||
"svc_lightstyle",
|
||||
"svc_updateuserinfo",
|
||||
"svc_deltatable",
|
||||
"svc_clientdata",
|
||||
"svc_stopsound",
|
||||
"svc_updatepings",
|
||||
"svc_particle",
|
||||
"svc_restoresound",
|
||||
"svc_spawnstatic",
|
||||
"svc_event_reliable",
|
||||
"svc_spawnbaseline",
|
||||
"svc_temp_entity",
|
||||
"svc_setpause",
|
||||
"svc_signonnum",
|
||||
"svc_centerprint",
|
||||
"svc_event",
|
||||
"svc_soundindex",
|
||||
"svc_ambientsound",
|
||||
"svc_intermission",
|
||||
"svc_modelindex",
|
||||
"svc_cdtrack",
|
||||
"svc_serverinfo",
|
||||
"svc_eventindex",
|
||||
"svc_weaponanim",
|
||||
"svc_bspdecal",
|
||||
"svc_roomtype",
|
||||
"svc_addangle",
|
||||
"svc_usermessage",
|
||||
"svc_packetentities",
|
||||
"svc_deltapacketentities",
|
||||
"svc_chokecount",
|
||||
"svc_resourcelist",
|
||||
"svc_deltamovevars",
|
||||
"svc_customization",
|
||||
"svc_unused46",
|
||||
"svc_crosshairangle",
|
||||
"svc_soundfade",
|
||||
"svc_unused49",
|
||||
"svc_unused50",
|
||||
"svc_director",
|
||||
"svc_studiodecal",
|
||||
"svc_unused53",
|
||||
"svc_unused54",
|
||||
"svc_unused55",
|
||||
"svc_unused56",
|
||||
"svc_querycvarvalue",
|
||||
"svc_querycvarvalue2",
|
||||
"svc_unused59",
|
||||
"svc_unused60",
|
||||
"svc_unused61",
|
||||
"svc_unused62",
|
||||
"svc_unused63",
|
||||
};
|
||||
|
||||
qboolean CL_Active( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_Initialized( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_IsInGame( void )
|
||||
{
|
||||
return true; // always active for dedicated servers
|
||||
}
|
||||
|
||||
qboolean CL_IsInMenu( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_IsInConsole( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_IsIntermission( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_IsPlaybackDemo( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_IsRecordDemo( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
qboolean CL_DisableVisibility( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_IsBackgroundDemo( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_IsBackgroundMap( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void CL_Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Key_Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IN_Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CL_Drop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CL_ClearEdicts()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Key_SetKeyDest(int key_dest)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UI_SetActiveMenu( qboolean fActive )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CL_WriteMessageHistory()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Host_ClientBegin()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Host_ClientFrame()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Host_InputFrame()
|
||||
{
|
||||
Cbuf_Execute();
|
||||
}
|
||||
|
||||
void VID_InitDefaultResolution()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Con_Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void R_ClearAllDecals()
|
||||
{
|
||||
|
||||
}
|
||||
int R_CreateDecalList( struct decallist_s *pList )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void S_StopSound(int entnum, int channel, const char *soundname)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int S_GetCurrentStaticSounds( soundlist_t *pout, int size )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CL_GetMaxClients()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void IN_TouchInitConfig()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CL_Disconnect()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CL_Shutdown()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void R_ClearStaticEntities()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Host_Credits()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
qboolean UI_CreditsActive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void GL_FreeImage( const char *name )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void S_StopBackgroundTrack()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SCR_BeginLoadingPlaque( qboolean is_background )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int S_GetCurrentDynamicSounds( soundlist_t *pout, int size )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void S_StopAllSounds( qboolean ambient )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Con_NPrintf( int idx, char *fmt, ... )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Con_NXPrintf( struct con_nprint_s *info, char *fmt, ... )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const byte *GL_TextureData( unsigned int texnum )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SCR_CheckStartupVids()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
imgfilter_t *R_FindTexFilter( const char *texname )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#include "sprite.h"
|
||||
|
||||
/*
|
||||
====================
|
||||
Mod_LoadSpriteModel
|
||||
|
||||
load sprite model
|
||||
====================
|
||||
*/
|
||||
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags )
|
||||
{
|
||||
dsprite_q1_t *pinq1;
|
||||
dsprite_hl_t *pinhl;
|
||||
dsprite_t *pin;
|
||||
short *numi = NULL;
|
||||
dframetype_t *pframetype;
|
||||
msprite_t *psprite;
|
||||
int i, size;
|
||||
|
||||
if( loaded ) *loaded = false;
|
||||
pin = (dsprite_t *)buffer;
|
||||
mod->type = mod_sprite;
|
||||
i = pin->version;
|
||||
|
||||
if( pin->ident != IDSPRITEHEADER )
|
||||
{
|
||||
MsgDev( D_ERROR, "%s has wrong id (%x should be %x)\n", mod->name, pin->ident, IDSPRITEHEADER );
|
||||
return;
|
||||
}
|
||||
|
||||
if( i != SPRITE_VERSION_Q1 && i != SPRITE_VERSION_HL && i != SPRITE_VERSION_32 )
|
||||
{
|
||||
MsgDev( D_ERROR, "%s has wrong version number (%i should be %i or %i)\n", mod->name, i, SPRITE_VERSION_Q1, SPRITE_VERSION_HL );
|
||||
return;
|
||||
}
|
||||
|
||||
mod->mempool = Mem_AllocPool( va( "^2%s^7", mod->name ));
|
||||
|
||||
if( i == SPRITE_VERSION_Q1 || i == SPRITE_VERSION_32 )
|
||||
{
|
||||
pinq1 = (dsprite_q1_t *)buffer;
|
||||
size = sizeof( msprite_t ) + ( pinq1->numframes - 1 ) * sizeof( psprite->frames );
|
||||
psprite = Mem_Alloc( mod->mempool, size );
|
||||
mod->cache.data = psprite; // make link to extradata
|
||||
|
||||
psprite->type = pinq1->type;
|
||||
psprite->texFormat = SPR_ADDITIVE; //SPR_ALPHTEST;
|
||||
psprite->numframes = mod->numframes = pinq1->numframes;
|
||||
psprite->facecull = SPR_CULL_FRONT;
|
||||
psprite->radius = pinq1->boundingradius;
|
||||
psprite->synctype = pinq1->synctype;
|
||||
|
||||
mod->mins[0] = mod->mins[1] = -pinq1->bounds[0] * 0.5f;
|
||||
mod->maxs[0] = mod->maxs[1] = pinq1->bounds[0] * 0.5f;
|
||||
mod->mins[2] = -pinq1->bounds[1] * 0.5f;
|
||||
mod->maxs[2] = pinq1->bounds[1] * 0.5f;
|
||||
numi = NULL;
|
||||
}
|
||||
else if( i == SPRITE_VERSION_HL )
|
||||
{
|
||||
pinhl = (dsprite_hl_t *)buffer;
|
||||
size = sizeof( msprite_t ) + ( pinhl->numframes - 1 ) * sizeof( psprite->frames );
|
||||
psprite = Mem_Alloc( mod->mempool, size );
|
||||
mod->cache.data = psprite; // make link to extradata
|
||||
|
||||
psprite->type = pinhl->type;
|
||||
psprite->texFormat = pinhl->texFormat;
|
||||
psprite->numframes = mod->numframes = pinhl->numframes;
|
||||
psprite->facecull = pinhl->facetype;
|
||||
psprite->radius = pinhl->boundingradius;
|
||||
psprite->synctype = pinhl->synctype;
|
||||
|
||||
mod->mins[0] = mod->mins[1] = -pinhl->bounds[0] * 0.5f;
|
||||
mod->maxs[0] = mod->maxs[1] = pinhl->bounds[0] * 0.5f;
|
||||
mod->mins[2] = -pinhl->bounds[1] * 0.5f;
|
||||
mod->maxs[2] = pinhl->bounds[1] * 0.5f;
|
||||
numi = (short *)(pinhl + 1);
|
||||
}
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
{
|
||||
// skip frames loading
|
||||
if( loaded ) *loaded = true; // done
|
||||
psprite->numframes = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if( numi == NULL )
|
||||
{
|
||||
rgbdata_t *pal;
|
||||
|
||||
pal = FS_LoadImage( "#id.pal", (byte *)&i, 768 );
|
||||
pframetype = (dframetype_t *)(pinq1 + 1);
|
||||
FS_FreeImage( pal ); // palette installed, no reason to keep this data
|
||||
}
|
||||
else if( *numi == 256 )
|
||||
{
|
||||
byte *src = (byte *)(numi+1);
|
||||
rgbdata_t *pal;
|
||||
|
||||
// install palette
|
||||
switch( psprite->texFormat )
|
||||
{
|
||||
case SPR_INDEXALPHA:
|
||||
pal = FS_LoadImage( "#gradient.pal", src, 768 );
|
||||
break;
|
||||
case SPR_ALPHTEST:
|
||||
pal = FS_LoadImage( "#masked.pal", src, 768 );
|
||||
break;
|
||||
default:
|
||||
pal = FS_LoadImage( "#normal.pal", src, 768 );
|
||||
break;
|
||||
}
|
||||
|
||||
pframetype = (dframetype_t *)(src + 768);
|
||||
FS_FreeImage( pal ); // palette installed, no reason to keep this data
|
||||
}
|
||||
else
|
||||
{
|
||||
MsgDev( D_ERROR, "%s has wrong number of palette colors %i (should be 256)\n", mod->name, *numi );
|
||||
return;
|
||||
}
|
||||
|
||||
if( mod->numframes < 1 )
|
||||
{
|
||||
MsgDev( D_ERROR, "%s has invalid # of frames: %d\n", mod->name, mod->numframes );
|
||||
return;
|
||||
}
|
||||
|
||||
if( loaded ) *loaded = true; // done
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
Mod_UnloadSpriteModel
|
||||
|
||||
release sprite model and frames
|
||||
====================
|
||||
*/
|
||||
void Mod_UnloadSpriteModel( model_t *mod )
|
||||
{
|
||||
msprite_t *psprite;
|
||||
mspritegroup_t *pspritegroup;
|
||||
mspriteframe_t *pspriteframe;
|
||||
int i, j;
|
||||
|
||||
Assert( mod != NULL );
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
if( mod->type == mod_sprite )
|
||||
{
|
||||
if( host.type != HOST_DEDICATED )
|
||||
{
|
||||
psprite = mod->cache.data;
|
||||
|
||||
if( psprite )
|
||||
{
|
||||
// release all textures
|
||||
for( i = 0; i < psprite->numframes; i++ )
|
||||
{
|
||||
if( psprite->frames[i].type == SPR_SINGLE )
|
||||
{
|
||||
pspriteframe = psprite->frames[i].frameptr;
|
||||
GL_FreeTexture( pspriteframe->gl_texturenum );
|
||||
}
|
||||
else
|
||||
{
|
||||
pspritegroup = (mspritegroup_t *)psprite->frames[i].frameptr;
|
||||
|
||||
for( j = 0; j < pspritegroup->numframes; j++ )
|
||||
{
|
||||
pspriteframe = pspritegroup->frames[i];
|
||||
GL_FreeTexture( pspriteframe->gl_texturenum );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Mem_FreePool( &mod->mempool );
|
||||
memset( mod, 0, sizeof( *mod ));
|
||||
}
|
||||
|
||||
#endif // XASH_DEDICATED
|
@ -1386,6 +1386,27 @@ void FS_LoadGameInfo( const char *rootfolder )
|
||||
Sys_Error( "Couldn't find game directory '%s'\n", fs_gamedir );
|
||||
|
||||
SI.GameInfo = SI.games[i];
|
||||
if( !Sys_GetParmFromCmdLine( "-dll", SI.gamedll ) )
|
||||
{
|
||||
#ifdef XASH_INTERNAL_GAMELIBS
|
||||
Q_strncpy( SI.gamedll, "server", sizeof( SI.gamedll ) );
|
||||
#elif defined(_WIN32)
|
||||
Q_strncpy( SI.gamedll, GI->game_dll, sizeof( SI.gamedll ) );
|
||||
#elif defined(__APPLE__)
|
||||
Q_strncpy( SI.gamedll, GI->game_dll_osx, sizeof( SI.gamedll ) );
|
||||
#else
|
||||
Q_strncpy( SI.gamedll, GI->game_dll_linux, sizeof( SI.gamedll ) );
|
||||
#endif
|
||||
}
|
||||
if( !Sys_GetParmFromCmdLine( "-clientlib", SI.clientlib ) )
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
Q_strncpy( SI.clientlib, CLIENTDLL, sizeof( SI.clientlib ) );
|
||||
#else
|
||||
Q_strncpy( SI.clientlib, GI->client_lib, sizeof( SI.clientlib ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
FS_Rescan(); // create new filesystem
|
||||
|
||||
Host_InitDecals (); // reload decals
|
||||
|
@ -116,11 +116,13 @@ void Host_EndGame( qboolean abort, const char *message, ... )
|
||||
MsgDev( D_INFO, "Host_EndGame: %s\n", string );
|
||||
|
||||
SV_Shutdown( "\n" );
|
||||
#ifndef XASH_DEDICATED
|
||||
CL_Disconnect();
|
||||
|
||||
// recreate world if needs
|
||||
CL_ClearEdicts ();
|
||||
|
||||
#endif
|
||||
|
||||
// release all models
|
||||
Mod_FreeAll();
|
||||
|
||||
@ -412,17 +414,20 @@ double Host_CalcFPS( void )
|
||||
double fps = 0.0;
|
||||
|
||||
// NOTE: we should play demos with same fps as it was recorded
|
||||
#ifndef XASH_DEDICATED
|
||||
if( CL_IsPlaybackDemo() || CL_IsRecordDemo( ))
|
||||
fps = CL_GetDemoFramerate();
|
||||
else if( Host_IsLocalGame( ))
|
||||
else
|
||||
#endif
|
||||
if( Host_IsLocalGame( ))
|
||||
fps = host_maxfps->value;
|
||||
else
|
||||
{
|
||||
fps = host_maxfps->value;
|
||||
if( fps == 0.0 ) fps = HOST_FPS; // default for multiplayer
|
||||
fps = bound( MIN_FPS, fps, MAX_FPS );
|
||||
}
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
// probably left part of this condition is redundant :-)
|
||||
if( host.type != HOST_DEDICATED && Host_IsLocalGame( ) && !CL_IsTimeDemo( ))
|
||||
{
|
||||
@ -434,6 +439,7 @@ double Host_CalcFPS( void )
|
||||
else fps = 60.0; // default
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return fps;
|
||||
}
|
||||
@ -962,8 +968,10 @@ void EXPORT Host_Shutdown( void )
|
||||
if( host.status != HOST_ERR_FATAL ) host.status = HOST_SHUTDOWN; // prepare host to normal shutdown
|
||||
if( !host.change_game ) Q_strncpy( host.finalmsg, "Server shutdown", sizeof( host.finalmsg ));
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
if( host.type == HOST_NORMAL )
|
||||
Host_WriteConfig();
|
||||
#endif
|
||||
|
||||
SV_Shutdown( "" );
|
||||
CL_Shutdown();
|
||||
|
@ -130,6 +130,7 @@ qboolean Info_IsValid( const char *s )
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
/*
|
||||
==============
|
||||
Info_WriteVars
|
||||
@ -177,6 +178,7 @@ void Info_WriteVars( file_t *f )
|
||||
s++;
|
||||
}
|
||||
}
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
/*
|
||||
===============
|
||||
|
109
engine/common/launcher.c
Normal file
109
engine/common/launcher.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
launcher.c - direct xash3d launcher
|
||||
Copyright (C) 2015 Mittorn
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifdef SINGLE_BINARY
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef XASH_SDLMAIN
|
||||
#include "SDL.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
typedef void (*pfnChangeGame)( const char *progname );
|
||||
|
||||
char szGameDir[128]; // safe place to keep gamedir
|
||||
int g_iArgc;
|
||||
|
||||
void Host_Shutdown( void );
|
||||
void Launcher_ChangeGame( const char *progname );
|
||||
void *Com_LoadLibrary( char *, int );
|
||||
int Host_Main( int szArgc, char **szArgv, const char *szGameDir, int chg, pfnChangeGame callback );
|
||||
|
||||
char **g_pszArgv;
|
||||
|
||||
void Launcher_ChangeGame( const char *progname )
|
||||
{
|
||||
strncpy( szGameDir, progname, sizeof( szGameDir ) - 1 );
|
||||
Host_Shutdown( );
|
||||
exit( Host_Main( g_iArgc, g_pszArgv, szGameDir, 1, &Launcher_ChangeGame ) );
|
||||
}
|
||||
|
||||
#ifdef XASH_NOCONHOST
|
||||
#include <windows.h>
|
||||
int __stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int nShow)
|
||||
{
|
||||
int szArgc;
|
||||
char **szArgv;
|
||||
LPWSTR* lpArgv = CommandLineToArgvW(GetCommandLineW(), &szArgc);
|
||||
int size, i = 0;
|
||||
szArgv = (char**)malloc(szArgc*sizeof(char*));
|
||||
for (; i < szArgc; ++i)
|
||||
{
|
||||
size = wcslen(lpArgv[i]) + 1;
|
||||
szArgv[i] = (char*)malloc(size);
|
||||
wcstombs(szArgv[i], lpArgv[i], size);
|
||||
}
|
||||
LocalFree(lpArgv);
|
||||
main( szArgc, szArgv );
|
||||
}
|
||||
#endif
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
char gamedir_buf[32] = "";
|
||||
const char *gamedir = getenv("XASH3D_GAMEDIR");
|
||||
|
||||
if( !gamedir )
|
||||
{
|
||||
gamedir = "valve";
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy( gamedir_buf, gamedir, 32 );
|
||||
gamedir = gamedir_buf;
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#ifdef EMSCRIPTEN_LIB_FS
|
||||
// For some unknown reason emscripten refusing to load libraries later
|
||||
Com_LoadLibrary("menu", 0 );
|
||||
Com_LoadLibrary("server", 0 );
|
||||
Com_LoadLibrary("client", 0 );
|
||||
#endif
|
||||
#ifdef XASH_DEDICATED
|
||||
// NodeJS support for debug
|
||||
EM_ASM(try{
|
||||
FS.mkdir('/xash');
|
||||
FS.mount(NODEFS, { root: '.'}, '/xash' );
|
||||
FS.chdir('/xash');
|
||||
}catch(e){};);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
g_iArgc = argc;
|
||||
g_pszArgv = argv;
|
||||
#if TARGET_OS_IPHONE
|
||||
{
|
||||
void IOS_LaunchDialog( void );
|
||||
IOS_LaunchDialog();
|
||||
}
|
||||
#endif
|
||||
return Host_Main( g_iArgc, g_pszArgv, gamedir, 0, &Launcher_ChangeGame );
|
||||
}
|
||||
|
||||
#endif
|
@ -1778,11 +1778,13 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
|
||||
|
||||
if( bmod->isworld )
|
||||
{
|
||||
#ifndef XASH_DEDICATED
|
||||
// release old sky layers first
|
||||
GL_FreeTexture( tr.solidskyTexture );
|
||||
GL_FreeTexture( tr.alphaskyTexture );
|
||||
tr.solidskyTexture = 0;
|
||||
tr.alphaskyTexture = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if( !bmod->texdatasize )
|
||||
@ -1805,8 +1807,10 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
|
||||
loadmodel->textures[i] = tx;
|
||||
|
||||
Q_strncpy( tx->name, "*default", sizeof( tx->name ));
|
||||
#ifndef XASH_DEDICATED
|
||||
tx->gl_texturenum = tr.defaultTexture;
|
||||
tx->width = tx->height = 16;
|
||||
#endif
|
||||
continue; // missed
|
||||
}
|
||||
|
||||
@ -1851,6 +1855,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
|
||||
if( remaining >= 770 ) custom_palette = true;
|
||||
}
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
// check for multi-layered sky texture (quake1 specific)
|
||||
if( bmod->isworld && !Q_strncmp( mt->name, "sky", 3 ) && (( mt->width / mt->height ) == 2 ))
|
||||
{
|
||||
@ -1943,6 +1948,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
|
||||
if( src ) Mem_Free( src );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// sequence the animations and detail textures
|
||||
@ -2224,8 +2230,10 @@ static void Mod_LoadSurfaces( dbspmodel_t *bmod )
|
||||
next_lightofs = 99999999;
|
||||
}
|
||||
|
||||
#ifndef XASH_DEDICATED // TODO: Do we need subdivide on server?
|
||||
if( FBitSet( out->flags, SURF_DRAWTURB ))
|
||||
GL_SubdivideSurface( out ); // cut up polygon for warps
|
||||
#endif
|
||||
}
|
||||
|
||||
// now we have enough data to trying determine samplecount per lightmap pixel
|
||||
@ -2794,6 +2802,7 @@ void Mod_UnloadBrushModel( model_t *mod )
|
||||
|
||||
if( mod->name[0] != '*' )
|
||||
{
|
||||
#ifndef XASH_DEDICATED
|
||||
for( i = 0; i < mod->numtextures; i++ )
|
||||
{
|
||||
tx = mod->textures[i];
|
||||
@ -2803,6 +2812,7 @@ void Mod_UnloadBrushModel( model_t *mod )
|
||||
GL_FreeTexture( tx->gl_texturenum ); // main texture
|
||||
GL_FreeTexture( tx->fb_texturenum ); // luma texture
|
||||
}
|
||||
#endif
|
||||
Mem_FreePool( &mod->mempool );
|
||||
}
|
||||
|
||||
|
@ -396,6 +396,247 @@ static void Mod_StudioCalcRotations( int boneused[], int numbones, const byte *p
|
||||
if( pseqdesc->motiontype & STUDIO_Z ) pos[pseqdesc->motionbone][2] = 0.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioCalcBoneQuaternion
|
||||
|
||||
====================
|
||||
*/
|
||||
void R_StudioCalcBoneQuaternion( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, vec4_t q )
|
||||
{
|
||||
vec3_t angles1;
|
||||
vec3_t angles2;
|
||||
int j, k;
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
if( !panim || panim->offset[j+3] == 0 )
|
||||
{
|
||||
angles2[j] = angles1[j] = pbone->value[j+3]; // default;
|
||||
}
|
||||
else
|
||||
{
|
||||
mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]);
|
||||
|
||||
k = frame;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
|
||||
// find span of values that includes the frame we want
|
||||
while( panimvalue->num.total <= k )
|
||||
{
|
||||
k -= panimvalue->num.total;
|
||||
panimvalue += panimvalue->num.valid + 1;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
}
|
||||
|
||||
// bah, missing blend!
|
||||
if( panimvalue->num.valid > k )
|
||||
{
|
||||
angles1[j] = panimvalue[k+1].value;
|
||||
|
||||
if( panimvalue->num.valid > k + 1 )
|
||||
{
|
||||
angles2[j] = panimvalue[k+2].value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
angles2[j] = angles1[j];
|
||||
else angles2[j] = panimvalue[panimvalue->num.valid+2].value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
angles1[j] = panimvalue[panimvalue->num.valid].value;
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
angles2[j] = angles1[j];
|
||||
else angles2[j] = panimvalue[panimvalue->num.valid+2].value;
|
||||
}
|
||||
|
||||
angles1[j] = pbone->value[j+3] + angles1[j] * pbone->scale[j+3];
|
||||
angles2[j] = pbone->value[j+3] + angles2[j] * pbone->scale[j+3];
|
||||
}
|
||||
|
||||
if( pbone->bonecontroller[j+3] != -1 && adj != NULL )
|
||||
{
|
||||
angles1[j] += adj[pbone->bonecontroller[j+3]];
|
||||
angles2[j] += adj[pbone->bonecontroller[j+3]];
|
||||
}
|
||||
}
|
||||
|
||||
if( !VectorCompare( angles1, angles2 ))
|
||||
{
|
||||
vec4_t q1, q2;
|
||||
|
||||
AngleQuaternion( angles1, q1, true );
|
||||
AngleQuaternion( angles2, q2, true );
|
||||
QuaternionSlerp( q1, q2, s, q );
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleQuaternion( angles1, q, true );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioCalcBonePosition
|
||||
|
||||
====================
|
||||
*/
|
||||
void R_StudioCalcBonePosition( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, vec3_t pos )
|
||||
{
|
||||
vec3_t origin1;
|
||||
vec3_t origin2;
|
||||
int j, k;
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
if( !panim || panim->offset[j] == 0 )
|
||||
{
|
||||
origin2[j] = origin1[j] = pbone->value[j]; // default;
|
||||
}
|
||||
else
|
||||
{
|
||||
mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]);
|
||||
|
||||
k = frame;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
|
||||
// find span of values that includes the frame we want
|
||||
while( panimvalue->num.total <= k )
|
||||
{
|
||||
k -= panimvalue->num.total;
|
||||
panimvalue += panimvalue->num.valid + 1;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
}
|
||||
|
||||
// bah, missing blend!
|
||||
if( panimvalue->num.valid > k )
|
||||
{
|
||||
origin1[j] = panimvalue[k+1].value;
|
||||
|
||||
if( panimvalue->num.valid > k + 1 )
|
||||
{
|
||||
origin2[j] = panimvalue[k+2].value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
origin2[j] = origin1[j];
|
||||
else origin2[j] = panimvalue[panimvalue->num.valid+2].value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
origin1[j] = panimvalue[panimvalue->num.valid].value;
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
origin2[j] = origin1[j];
|
||||
else origin2[j] = panimvalue[panimvalue->num.valid+2].value;
|
||||
}
|
||||
|
||||
origin1[j] = pbone->value[j] + origin1[j] * pbone->scale[j];
|
||||
origin2[j] = pbone->value[j] + origin2[j] * pbone->scale[j];
|
||||
}
|
||||
|
||||
if( pbone->bonecontroller[j] != -1 && adj != NULL )
|
||||
{
|
||||
origin1[j] += adj[pbone->bonecontroller[j]];
|
||||
origin2[j] += adj[pbone->bonecontroller[j]];
|
||||
}
|
||||
}
|
||||
|
||||
if( !VectorCompare( origin1, origin2 ))
|
||||
{
|
||||
VectorLerp( origin1, s, origin2, pos );
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy( origin1, pos );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioSlerpBones
|
||||
|
||||
====================
|
||||
*/
|
||||
void R_StudioSlerpBones( int numbones, vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s )
|
||||
{
|
||||
int i;
|
||||
|
||||
s = bound( 0.0f, s, 1.0f );
|
||||
|
||||
for( i = 0; i < numbones; i++ )
|
||||
{
|
||||
QuaternionSlerp( q1[i], q2[i], s, q1[i] );
|
||||
VectorLerp( pos1[i], s, pos2[i], pos1[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioGetAnim
|
||||
|
||||
====================
|
||||
*/
|
||||
void *R_StudioGetAnim( studiohdr_t *m_pStudioHeader, model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc )
|
||||
{
|
||||
mstudioseqgroup_t *pseqgroup;
|
||||
cache_user_t *paSequences;
|
||||
size_t filesize;
|
||||
byte *buf;
|
||||
|
||||
pseqgroup = (mstudioseqgroup_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqgroupindex) + pseqdesc->seqgroup;
|
||||
if( pseqdesc->seqgroup == 0 )
|
||||
return ((byte *)m_pStudioHeader + pseqgroup->data + pseqdesc->animindex);
|
||||
|
||||
paSequences = (cache_user_t *)m_pSubModel->submodels;
|
||||
|
||||
if( paSequences == NULL )
|
||||
{
|
||||
paSequences = (cache_user_t *)Mem_Alloc( com_studiocache, MAXSTUDIOGROUPS * sizeof( cache_user_t ));
|
||||
m_pSubModel->submodels = (void *)paSequences;
|
||||
}
|
||||
|
||||
// check for already loaded
|
||||
if( !Mod_CacheCheck(( cache_user_t *)&( paSequences[pseqdesc->seqgroup] )))
|
||||
{
|
||||
string filepath, modelname, modelpath;
|
||||
|
||||
COM_FileBase( m_pSubModel->name, modelname );
|
||||
COM_ExtractFilePath( m_pSubModel->name, modelpath );
|
||||
|
||||
// NOTE: here we build real sub-animation filename because stupid user may rename model without recompile
|
||||
Q_snprintf( filepath, sizeof( filepath ), "%s/%s%i%i.mdl", modelpath, modelname, pseqdesc->seqgroup / 10, pseqdesc->seqgroup % 10 );
|
||||
|
||||
buf = FS_LoadFile( filepath, &filesize, false );
|
||||
if( !buf || !filesize ) Host_Error( "StudioGetAnim: can't load %s\n", filepath );
|
||||
if( IDSEQGRPHEADER != *(uint *)buf ) Host_Error( "StudioGetAnim: %s is corrupted\n", filepath );
|
||||
|
||||
Con_Printf( "loading: %s\n", filepath );
|
||||
|
||||
paSequences[pseqdesc->seqgroup].data = Mem_Alloc( com_studiocache, filesize );
|
||||
memcpy( paSequences[pseqdesc->seqgroup].data, buf, filesize );
|
||||
Mem_Free( buf );
|
||||
}
|
||||
|
||||
return ((byte *)paSequences[pseqdesc->seqgroup].data + pseqdesc->animindex);
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioSetupBones
|
||||
@ -806,6 +1047,7 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
phdr = R_StudioLoadHeader( mod, buffer );
|
||||
if( !phdr ) return; // bad model
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
if( phdr->numtextures == 0 )
|
||||
{
|
||||
studiohdr_t *thdr;
|
||||
@ -821,8 +1063,8 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
MsgDev( D_WARN, "Mod_LoadStudioModel: %s missing textures file\n", mod->name );
|
||||
if( buffer2 ) Mem_Free( buffer2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
else
|
||||
{
|
||||
Mod_StudioLoadTextures( mod, thdr );
|
||||
|
||||
// give space for textures and skinrefs
|
||||
@ -857,6 +1099,13 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
phdr = (studiohdr_t *)loadmodel->cache.data; // get the new pointer on studiohdr
|
||||
phdr->length = phdr->texturedataindex; // update model size
|
||||
}
|
||||
#else
|
||||
// just copy model into memory
|
||||
loadmodel->cache.data = Mem_Alloc( loadmodel->mempool, phdr->length );
|
||||
memcpy( loadmodel->cache.data, buffer, phdr->length );
|
||||
|
||||
phdr = loadmodel->cache.data;
|
||||
#endif
|
||||
|
||||
// setup bounding box
|
||||
if( !VectorCompare( vec3_origin, phdr->bbmin ))
|
||||
@ -898,7 +1147,9 @@ void Mod_UnloadStudioModel( model_t *mod )
|
||||
if( mod->type != mod_studio )
|
||||
return; // not a studio
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
Mod_StudioUnloadTextures( mod->cache.data );
|
||||
#endif
|
||||
Mem_FreePool( &mod->mempool );
|
||||
memset( mod, 0, sizeof( *mod ));
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ static void Mod_FreeUserData( model_t *mod )
|
||||
if( !mod->name[0] || mod->name[0] == '*' )
|
||||
return;
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
if( Host_IsDedicated() )
|
||||
{
|
||||
if( svgame.physFuncs.Mod_ProcessUserData != NULL )
|
||||
{
|
||||
@ -85,6 +85,7 @@ static void Mod_FreeUserData( model_t *mod )
|
||||
svgame.physFuncs.Mod_ProcessUserData( mod, false, NULL );
|
||||
}
|
||||
}
|
||||
#ifndef XASH_DEDICATED
|
||||
else
|
||||
{
|
||||
if( clgame.drawFuncs.Mod_ProcessUserData != NULL )
|
||||
@ -93,6 +94,7 @@ static void Mod_FreeUserData( model_t *mod )
|
||||
clgame.drawFuncs.Mod_ProcessUserData( mod, false, NULL );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -115,15 +117,17 @@ static void Mod_FreeModel( model_t *mod )
|
||||
case mod_sprite:
|
||||
Mod_UnloadSpriteModel( mod );
|
||||
break;
|
||||
#ifndef XASH_DEDICATED
|
||||
case mod_alias:
|
||||
Mod_UnloadAliasModel( mod );
|
||||
break;
|
||||
#endif
|
||||
case mod_studio:
|
||||
Mod_UnloadStudioModel( mod );
|
||||
break;
|
||||
case mod_brush:
|
||||
Mod_UnloadBrushModel( mod );
|
||||
break;
|
||||
case mod_alias:
|
||||
Mod_UnloadAliasModel( mod );
|
||||
break;
|
||||
}
|
||||
|
||||
memset( mod, 0, sizeof( *mod ));
|
||||
@ -302,9 +306,12 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
case IDSPRITEHEADER:
|
||||
Mod_LoadSpriteModel( mod, buf, &loaded, 0 );
|
||||
break;
|
||||
// TODO: Load alias models on dedicated too?
|
||||
#ifndef XASH_DEDICATED
|
||||
case IDALIASHEADER:
|
||||
Mod_LoadAliasModel( mod, buf, &loaded );
|
||||
break;
|
||||
#endif
|
||||
case Q1BSP_VERSION:
|
||||
case HLBSP_VERSION:
|
||||
case QBSP2_VERSION:
|
||||
@ -332,7 +339,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
if( world.loading )
|
||||
SetBits( mod->flags, MODEL_WORLD ); // mark worldmodel
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
if( Host_IsDedicated() )
|
||||
{
|
||||
if( svgame.physFuncs.Mod_ProcessUserData != NULL )
|
||||
{
|
||||
@ -340,6 +347,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
svgame.physFuncs.Mod_ProcessUserData( mod, true, buf );
|
||||
}
|
||||
}
|
||||
#ifndef XASH_DEDICATED
|
||||
else
|
||||
{
|
||||
if( clgame.drawFuncs.Mod_ProcessUserData != NULL )
|
||||
@ -348,6 +356,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
clgame.drawFuncs.Mod_ProcessUserData( mod, true, buf );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
p = &mod_crcinfo[mod - mod_known];
|
||||
|
@ -1180,6 +1180,7 @@ Netchan_UpdateProgress
|
||||
*/
|
||||
void Netchan_UpdateProgress( netchan_t *chan )
|
||||
{
|
||||
#ifndef XASH_DEDICATED
|
||||
fragbuf_t *p;
|
||||
int i, c = 0;
|
||||
int total = 0;
|
||||
@ -1256,6 +1257,7 @@ void Netchan_UpdateProgress( netchan_t *chan )
|
||||
}
|
||||
|
||||
scr_download->value = bestpercent;
|
||||
#endif // XASH_DEDICATED
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1798,6 +1798,7 @@ Can go from either a baseline or a previous packet_entity
|
||||
*/
|
||||
qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state_t *to, int number, qboolean player, float timebase )
|
||||
{
|
||||
#ifndef XASH_DEDICATED
|
||||
delta_info_t *dt = NULL;
|
||||
delta_t *pField;
|
||||
int i, fRemoveType;
|
||||
@ -1877,7 +1878,7 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state
|
||||
{
|
||||
Delta_ReadField( msg, pField, from, to, timebase );
|
||||
}
|
||||
|
||||
#endif // XASH_DEDICATED
|
||||
// message parsed
|
||||
return true;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ draw line from particles
|
||||
*/
|
||||
void PM_ParticleLine( const vec3_t start, const vec3_t end, int pcolor, float life, float zvel )
|
||||
{
|
||||
#ifndef XASH_DEDICATED
|
||||
float len, curdist;
|
||||
vec3_t diff, pos;
|
||||
|
||||
@ -43,6 +44,7 @@ void PM_ParticleLine( const vec3_t start, const vec3_t end, int pcolor, float li
|
||||
CL_Particle( pos, pcolor, life, 0, zvel );
|
||||
curdist += 2.0f;
|
||||
}
|
||||
#endif // XASH_DEDICATED
|
||||
}
|
||||
|
||||
/*
|
||||
@ -67,6 +69,7 @@ PM_DrawBBox
|
||||
*/
|
||||
void PM_DrawBBox( const vec3_t mins, const vec3_t maxs, const vec3_t origin, int pcolor, float life )
|
||||
{
|
||||
#ifndef XASH_DEDICATED
|
||||
vec3_t p[8], tmp;
|
||||
float gap = BOX_GAP;
|
||||
int i;
|
||||
@ -85,4 +88,5 @@ void PM_DrawBBox( const vec3_t mins, const vec3_t maxs, const vec3_t origin, int
|
||||
{
|
||||
PM_DrawRectangle( p[boxpnt[i][1]], p[boxpnt[i][0]], p[boxpnt[i][2]], p[boxpnt[i][3]], pcolor, life );
|
||||
}
|
||||
#endif // XASH_DEDICATED
|
||||
}
|
@ -461,7 +461,9 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
|
||||
// run custom sweep callback
|
||||
if( pmove->server || Host_IsLocalClient( ))
|
||||
SV_ClipPMoveToEntity( pe, start, mins, maxs, end, &trace_bbox );
|
||||
#ifndef XASH_DEDICATED
|
||||
else CL_ClipPMoveToEntity( pe, start, mins, maxs, end, &trace_bbox );
|
||||
#endif
|
||||
}
|
||||
else if( hullcount == 1 )
|
||||
{
|
||||
@ -628,7 +630,9 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
|
||||
// run custom sweep callback
|
||||
if( pmove->server || Host_IsLocalClient( ))
|
||||
SV_ClipPMoveToEntity( pe, pos, mins, maxs, pos, &trace );
|
||||
#ifndef XASH_DEDICATED
|
||||
else CL_ClipPMoveToEntity( pe, pos, mins, maxs, pos, &trace );
|
||||
#endif
|
||||
|
||||
// if we inside the custom hull
|
||||
if( trace.allsolid )
|
||||
|
@ -221,3 +221,76 @@ void Sys_PrintLog( const char *pMsg )
|
||||
fprintf( s_ld.logfile, "%s %s", logtime, pMsg );
|
||||
fflush( s_ld.logfile );
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
CONSOLE PRINT
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
/*
|
||||
=============
|
||||
Con_Printf
|
||||
|
||||
=============
|
||||
*/
|
||||
void Con_Printf( char *szFmt, ... )
|
||||
{
|
||||
static char buffer[MAX_PRINT_MSG];
|
||||
va_list args;
|
||||
|
||||
if( !host.allow_console )
|
||||
return;
|
||||
|
||||
va_start( args, szFmt );
|
||||
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
|
||||
va_end( args );
|
||||
|
||||
Sys_Print( buffer );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Con_DPrintf
|
||||
|
||||
=============
|
||||
*/
|
||||
void Con_DPrintf( char *szFmt, ... )
|
||||
{
|
||||
static char buffer[MAX_PRINT_MSG];
|
||||
va_list args;
|
||||
|
||||
if( host_developer.value < DEV_NORMAL )
|
||||
return;
|
||||
|
||||
va_start( args, szFmt );
|
||||
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
|
||||
va_end( args );
|
||||
|
||||
if( buffer[0] == '0' && buffer[1] == '\n' && buffer[2] == '\0' )
|
||||
return; // hlrally spam
|
||||
|
||||
Sys_Print( buffer );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Con_Reportf
|
||||
|
||||
=============
|
||||
*/
|
||||
void Con_Reportf( char *szFmt, ... )
|
||||
{
|
||||
static char buffer[MAX_PRINT_MSG];
|
||||
va_list args;
|
||||
|
||||
if( host_developer.value < DEV_EXTENDED )
|
||||
return;
|
||||
|
||||
va_start( args, szFmt );
|
||||
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
|
||||
va_end( args );
|
||||
|
||||
Sys_Print( buffer );
|
||||
}
|
@ -584,11 +584,13 @@ void SV_RestartAmbientSounds( void )
|
||||
SV_StartSound( pfnPEntityOfEntIndex( si->entnum ), CHAN_STATIC, si->name, si->volume, si->attenuation, 0, si->pitch );
|
||||
}
|
||||
|
||||
#ifndef XASH_DEDICATED // TODO: ???
|
||||
// restart soundtrack
|
||||
if( S_StreamGetCurrentState( curtrack, looptrack, &position ))
|
||||
{
|
||||
SV_StartMusic( curtrack, looptrack, position );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -645,9 +645,10 @@ qboolean SV_InitGame( void )
|
||||
return true; // already initialized ?
|
||||
|
||||
// first initialize?
|
||||
if( !SV_LoadProgs( GI->game_dll ))
|
||||
COM_ResetLibraryError();
|
||||
if( !SV_LoadProgs( SI.gamedll ))
|
||||
{
|
||||
Con_Printf( S_ERROR "can't initialize %s\n", GI->game_dll );
|
||||
Con_Printf( S_ERROR "can't initialize %s: %s\n", SI.gamedll, COM_GetLibraryError() );
|
||||
return false; // failed to loading server.dll
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,9 @@ GNU General Public License for more details.
|
||||
#include "gl_export.h"
|
||||
|
||||
typedef int (*PHYSICAPI)( int, server_physics_api_t*, physics_interface_t* );
|
||||
#ifndef XASH_DEDICATED
|
||||
extern triangleapi_t gTriApi;
|
||||
#endif
|
||||
|
||||
/*
|
||||
pushmove objects do not obey gravity, and do not interact with each other or trigger fields,
|
||||
@ -2004,10 +2006,17 @@ static server_physics_api_t gPhysicsAPI =
|
||||
SV_GetHeadNode,
|
||||
SV_ServerState,
|
||||
Host_Error,
|
||||
#ifndef XASH_DEDICATED
|
||||
&gTriApi, // ouch!
|
||||
pfnDrawConsoleString,
|
||||
pfnDrawSetTextColor,
|
||||
pfnDrawConsoleStringLen,
|
||||
#else
|
||||
NULL, // ouch! ouch!
|
||||
NULL, // ouch! ouch!
|
||||
NULL, // ouch! ouch!
|
||||
NULL, // ouch! ouch!
|
||||
#endif
|
||||
Con_NPrintf,
|
||||
Con_NXPrintf,
|
||||
SV_GetLightStyle,
|
||||
|
@ -323,6 +323,27 @@ void SV_AddLaddersToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3
|
||||
SV_AddLaddersToPmove( node->children[1], pmove_mins, pmove_maxs );
|
||||
}
|
||||
|
||||
static void pfnParticle( float *origin, int color, float life, int zpos, int zvel )
|
||||
{
|
||||
int v;
|
||||
|
||||
if( !origin )
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_StartParticle: NULL origin. Ignored\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
MSG_WriteByte( &sv.reliable_datagram, svc_particle );
|
||||
MSG_WriteVec3Coord( &sv.reliable_datagram, origin );
|
||||
MSG_WriteChar( &sv.reliable_datagram, 0 ); // no x-vel
|
||||
MSG_WriteChar( &sv.reliable_datagram, 0 ); // no y-vel
|
||||
v = bound( -128, (zpos * zvel) * 16.0f, 127 );
|
||||
MSG_WriteChar( &sv.reliable_datagram, v ); // write z-vel
|
||||
MSG_WriteByte( &sv.reliable_datagram, 1 );
|
||||
MSG_WriteByte( &sv.reliable_datagram, color );
|
||||
MSG_WriteByte( &sv.reliable_datagram, bound( 0, life * 8, 255 ));
|
||||
}
|
||||
|
||||
static int pfnTestPlayerPosition( float *pos, pmtrace_t *ptrace )
|
||||
{
|
||||
return PM_TestPlayerPosition( svgame.pmove, pos, ptrace, NULL );
|
||||
@ -564,7 +585,7 @@ void SV_InitClientMove( void )
|
||||
|
||||
// common utilities
|
||||
svgame.pmove->PM_Info_ValueForKey = Info_ValueForKey;
|
||||
svgame.pmove->PM_Particle = CL_Particle; // for local system only
|
||||
svgame.pmove->PM_Particle = pfnParticle;
|
||||
svgame.pmove->PM_TestPlayerPosition = pfnTestPlayerPosition;
|
||||
svgame.pmove->Con_NPrintf = Con_NPrintf;
|
||||
svgame.pmove->Con_DPrintf = Con_DPrintf;
|
||||
|
@ -1118,8 +1118,10 @@ static void SaveClientState( SAVERESTOREDATA *pSaveData, const char *level, int
|
||||
{
|
||||
// sounds won't going across transition
|
||||
header.soundCount = S_GetCurrentDynamicSounds( soundInfo, MAX_CHANNELS );
|
||||
#ifndef XASH_DEDICATED
|
||||
// music not reqiured to save position: it's just continue playing on a next level
|
||||
S_StreamGetCurrentState( header.introTrack, header.mainTrack, &header.trackPosition );
|
||||
#endif
|
||||
}
|
||||
|
||||
// save viewentity to allow camera works after save\restore
|
||||
@ -2098,8 +2100,10 @@ void SV_SaveGame( const char *pName )
|
||||
SaveBuildComment( comment, sizeof( comment ));
|
||||
result = SaveGameSlot( savename, comment );
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
if( result && !FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
CL_HudMessage( "GAMESAVED" ); // defined in titles.txt
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user