static void ModelCallback (void *unused) { char scratch[MAX_QPATH]; s_player_skin_box.itemnames = s_pmi[s_player_model_box.curvalue].skindisplaynames; s_player_skin_box.curvalue = 0; // only register model and skin on starup or when changed Com_sprintf( scratch, sizeof(scratch), "players/%s/tris.md2", s_pmi[s_player_model_box.curvalue].directory ); playermodel = R_RegisterModel (scratch); Com_sprintf( scratch, sizeof(scratch), "players/%s/%s.pcx", s_pmi[s_player_model_box.curvalue].directory, s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] ); playerskin = R_RegisterSkin (scratch); // show current weapon model (if any) if (currentweaponmodel && strlen(currentweaponmodel)) { Com_sprintf (scratch, sizeof(scratch), "players/%s/%s", s_pmi[s_player_model_box.curvalue].directory, currentweaponmodel); weaponmodel = R_RegisterModel(scratch); if (!weaponmodel) { Com_sprintf (scratch, sizeof(scratch), "players/%s/weapon.md2", s_pmi[s_player_model_box.curvalue].directory); weaponmodel = R_RegisterModel (scratch); } } else { Com_sprintf (scratch, sizeof(scratch), "players/%s/weapon.md2", s_pmi[s_player_model_box.curvalue].directory); weaponmodel = R_RegisterModel (scratch); } }
// only register skin on starup and when changed static void SkinCallback (void *unused) { char scratch[MAX_QPATH]; Com_sprintf(scratch, sizeof(scratch), "players/%s/%s.pcx", s_pmi[s_player_model_box.curvalue].directory, s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue]); playerskin = R_RegisterSkin(scratch); }
/* * SkinFile_ParseBuffer */ static int SkinFile_ParseBuffer( char *buffer, mesh_shader_pair_t *pairs ) { int numpairs; char *ptr, *t, *token; ptr = buffer; numpairs = 0; while( ptr ) { token = COM_ParseExt( &ptr, qfalse ); if( !token[0] ) continue; t = strchr( token, ',' ); if( !t ) continue; if( *( t+1 ) == '\0' || *( t+1 ) == '\n' ) continue; if( pairs ) { *t = 0; pairs[numpairs].meshname = SkinFile_CopyString( token ); pairs[numpairs].shader = R_RegisterSkin( token + strlen( token ) + 1 ); } numpairs++; } return numpairs; }
void QCBUILTIN PF_shaderforname (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { const char *str = PR_GetStringOfs(prinst, OFS_PARM0); const char *defaultbody = PF_VarString(prinst, 1, pr_globals); shader_t *shad; if (*defaultbody) shad = R_RegisterShader(str, SUF_NONE, defaultbody); else shad = R_RegisterSkin(str, NULL); if (shad) G_FLOAT(OFS_RETURN) = shad->id+1; else G_FLOAT(OFS_RETURN) = 0; }
/* ================ CL_LoadClientinfo ================ */ void CL_LoadClientinfo (clientinfo_t *ci, char *s) { int32_t i; char *t; char model_name[MAX_QPATH]; char skin_name[MAX_QPATH]; char model_filename[MAX_QPATH]; char skin_filename[MAX_QPATH]; char weapon_filename[MAX_QPATH]; strncpy(ci->cinfo, s, sizeof(ci->cinfo)); ci->cinfo[sizeof(ci->cinfo)-1] = 0; // isolate the player's name strncpy(ci->name, s, sizeof(ci->name)); ci->name[sizeof(ci->name)-1] = 0; t = strstr (s, "\\"); if (t) { ci->name[t-s] = 0; s = t+1; } if (cl_noskins->value || *s == 0) { Com_sprintf (model_filename, sizeof(model_filename), "players/male/tris.md2"); Com_sprintf (weapon_filename, sizeof(weapon_filename), "players/male/weapon.md2"); Com_sprintf (skin_filename, sizeof(skin_filename), "players/male/grunt.pcx"); Com_sprintf (ci->iconname, sizeof(ci->iconname), "/players/male/grunt_i.pcx"); ci->model = R_RegisterModel (model_filename); memset(ci->weaponmodel, 0, sizeof(ci->weaponmodel)); ci->weaponmodel[0] = R_RegisterModel (weapon_filename); ci->skin = R_RegisterSkin (skin_filename); ci->icon = R_DrawFindPic (ci->iconname); } else { // isolate the model name strcpy (model_name, s); t = strstr(model_name, "/"); if (!t) t = strstr(model_name, "\\"); if (!t) t = model_name; *t = 0; // isolate the skin name strcpy (skin_name, s + strlen(model_name) + 1); // model file Com_sprintf (model_filename, sizeof(model_filename), "players/%s/tris.md2", model_name); ci->model = R_RegisterModel (model_filename); if (!ci->model) { strcpy(model_name, "male"); Com_sprintf (model_filename, sizeof(model_filename), "players/male/tris.md2"); ci->model = R_RegisterModel (model_filename); } // skin file Com_sprintf (skin_filename, sizeof(skin_filename), "players/%s/%s.pcx", model_name, skin_name); ci->skin = R_RegisterSkin (skin_filename); // if we don't have the skin and the model wasn't male, // see if the male has it (this is for CTF's skins) if (!ci->skin && Q_strcasecmp(model_name, "male")) { // change model to male strcpy(model_name, "male"); Com_sprintf (model_filename, sizeof(model_filename), "players/male/tris.md2"); ci->model = R_RegisterModel (model_filename); // see if the skin exists for the male model Com_sprintf (skin_filename, sizeof(skin_filename), "players/%s/%s.pcx", model_name, skin_name); ci->skin = R_RegisterSkin (skin_filename); } // if we still don't have a skin, it means that the male model didn't have // it, so default to grunt if (!ci->skin) { // see if the skin exists for the male model Com_sprintf (skin_filename, sizeof(skin_filename), "players/%s/grunt.pcx", model_name, skin_name); ci->skin = R_RegisterSkin (skin_filename); } // weapon file for (i = 0; i < num_cl_weaponmodels; i++) { Com_sprintf (weapon_filename, sizeof(weapon_filename), "players/%s/%s", model_name, cl_weaponmodels[i]); ci->weaponmodel[i] = R_RegisterModel(weapon_filename); if (!ci->weaponmodel[i] && strcmp(model_name, "cyborg") == 0) { // try male Com_sprintf (weapon_filename, sizeof(weapon_filename), "players/male/%s", cl_weaponmodels[i]); ci->weaponmodel[i] = R_RegisterModel(weapon_filename); } if (!cl_vwep->value) break; // only one when vwep is off } // icon file Com_sprintf (ci->iconname, sizeof(ci->iconname), "/players/%s/%s_i.pcx", model_name, skin_name); ci->icon = R_DrawFindPic (ci->iconname); } // must have loaded all data types to be valud if (!ci->skin || !ci->icon || !ci->model || !ci->weaponmodel[0]) { ci->skin = NULL; ci->icon = NULL; ci->model = NULL; ci->weaponmodel[0] = NULL; return; } }
// The cgame module is making a system call qintptr CLWS_CgameSystemCalls( qintptr* args ) { switch ( args[ 0 ] ) { case WSCG_PRINT: common->Printf( "%s", ( char* )VMA( 1 ) ); return 0; case WSCG_ERROR: common->Error( "%s", ( char* )VMA( 1 ) ); return 0; case WSCG_MILLISECONDS: return Sys_Milliseconds(); case WSCG_CVAR_REGISTER: Cvar_Register( ( vmCvar_t* )VMA( 1 ), ( char* )VMA( 2 ), ( char* )VMA( 3 ), args[ 4 ] ); return 0; case WSCG_CVAR_UPDATE: Cvar_Update( ( vmCvar_t* )VMA( 1 ) ); return 0; case WSCG_CVAR_SET: Cvar_Set( ( char* )VMA( 1 ), ( char* )VMA( 2 ) ); return 0; case WSCG_CVAR_VARIABLESTRINGBUFFER: Cvar_VariableStringBuffer( ( char* )VMA( 1 ), ( char* )VMA( 2 ), args[ 3 ] ); return 0; case WSCG_ARGC: return Cmd_Argc(); case WSCG_ARGV: Cmd_ArgvBuffer( args[ 1 ], ( char* )VMA( 2 ), args[ 3 ] ); return 0; case WSCG_ARGS: Cmd_ArgsBuffer( ( char* )VMA( 1 ), args[ 2 ] ); return 0; case WSCG_FS_FOPENFILE: return FS_FOpenFileByMode( ( char* )VMA( 1 ), ( fileHandle_t* )VMA( 2 ), ( fsMode_t )args[ 3 ] ); case WSCG_FS_READ: FS_Read( VMA( 1 ), args[ 2 ], args[ 3 ] ); return 0; case WSCG_FS_WRITE: return FS_Write( VMA( 1 ), args[ 2 ], args[ 3 ] ); case WSCG_FS_FCLOSEFILE: FS_FCloseFile( args[ 1 ] ); return 0; case WSCG_SENDCONSOLECOMMAND: Cbuf_AddText( ( char* )VMA( 1 ) ); return 0; case WSCG_ADDCOMMAND: CLT3_AddCgameCommand( ( char* )VMA( 1 ) ); return 0; case WSCG_REMOVECOMMAND: Cmd_RemoveCommand( ( char* )VMA( 1 ) ); return 0; case WSCG_SENDCLIENTCOMMAND: CL_AddReliableCommand( ( char* )VMA( 1 ) ); return 0; case WSCG_UPDATESCREEN: SCR_UpdateScreen(); return 0; case WSCG_CM_LOADMAP: CLT3_CM_LoadMap( ( char* )VMA( 1 ) ); return 0; case WSCG_CM_NUMINLINEMODELS: return CM_NumInlineModels(); case WSCG_CM_INLINEMODEL: return CM_InlineModel( args[ 1 ] ); case WSCG_CM_TEMPBOXMODEL: return CM_TempBoxModel( ( float* )VMA( 1 ), ( float* )VMA( 2 ), false ); case WSCG_CM_TEMPCAPSULEMODEL: return CM_TempBoxModel( ( float* )VMA( 1 ), ( float* )VMA( 2 ), true ); case WSCG_CM_POINTCONTENTS: return CM_PointContentsQ3( ( float* )VMA( 1 ), args[ 2 ] ); case WSCG_CM_TRANSFORMEDPOINTCONTENTS: return CM_TransformedPointContentsQ3( ( float* )VMA( 1 ), args[ 2 ], ( float* )VMA( 3 ), ( float* )VMA( 4 ) ); case WSCG_CM_BOXTRACE: CM_BoxTraceQ3( ( q3trace_t* )VMA( 1 ), ( float* )VMA( 2 ), ( float* )VMA( 3 ), ( float* )VMA( 4 ), ( float* )VMA( 5 ), args[ 6 ], args[ 7 ], false ); return 0; case WSCG_CM_TRANSFORMEDBOXTRACE: CM_TransformedBoxTraceQ3( ( q3trace_t* )VMA( 1 ), ( float* )VMA( 2 ), ( float* )VMA( 3 ), ( float* )VMA( 4 ), ( float* )VMA( 5 ), args[ 6 ], args[ 7 ], ( float* )VMA( 8 ), ( float* )VMA( 9 ), false ); return 0; case WSCG_CM_CAPSULETRACE: CM_BoxTraceQ3( ( q3trace_t* )VMA( 1 ), ( float* )VMA( 2 ), ( float* )VMA( 3 ), ( float* )VMA( 4 ), ( float* )VMA( 5 ), args[ 6 ], args[ 7 ], true ); return 0; case WSCG_CM_TRANSFORMEDCAPSULETRACE: CM_TransformedBoxTraceQ3( ( q3trace_t* )VMA( 1 ), ( float* )VMA( 2 ), ( float* )VMA( 3 ), ( float* )VMA( 4 ), ( float* )VMA( 5 ), args[ 6 ], args[ 7 ], ( float* )VMA( 8 ), ( float* )VMA( 9 ), true ); return 0; case WSCG_CM_MARKFRAGMENTS: return R_MarkFragmentsWolf( args[ 1 ], ( const vec3_t* )VMA( 2 ), ( float* )VMA( 3 ), args[ 4 ], ( float* )VMA( 5 ), args[ 6 ], ( markFragment_t* )VMA( 7 ) ); case WSCG_S_STARTSOUND: S_StartSound( ( float* )VMA( 1 ), args[ 2 ], args[ 3 ], args[ 4 ], 0.5 ); return 0; case WSCG_S_STARTSOUNDEX: S_StartSoundEx( ( float* )VMA( 1 ), args[ 2 ], args[ 3 ], args[ 4 ], args[ 5 ], 127 ); return 0; case WSCG_S_STARTLOCALSOUND: S_StartLocalSound( args[ 1 ], args[ 2 ], 127 ); return 0; case WSCG_S_CLEARLOOPINGSOUNDS: CLWS_ClearLoopingSounds( args[ 1 ] ); return 0; case WSCG_S_ADDLOOPINGSOUND: // FIXME MrE: handling of looping sounds changed S_AddLoopingSound( args[ 1 ], ( float* )VMA( 2 ), ( float* )VMA( 3 ), args[ 4 ], args[ 5 ], args[ 6 ], 0 ); return 0; case WSCG_S_STOPSTREAMINGSOUND: S_StopEntStreamingSound( args[ 1 ] ); return 0; case WSCG_S_STOPLOOPINGSOUND: // RF, not functional anymore, since we reverted to old looping code return 0; case WSCG_S_UPDATEENTITYPOSITION: S_UpdateEntityPosition( args[ 1 ], ( float* )VMA( 2 ) ); return 0; case WSCG_S_GETVOICEAMPLITUDE: return S_GetVoiceAmplitude( args[ 1 ] ); case WSCG_S_RESPATIALIZE: S_Respatialize( args[ 1 ], ( float* )VMA( 2 ), ( vec3_t* )VMA( 3 ), args[ 4 ] ); return 0; case WSCG_S_REGISTERSOUND: return S_RegisterSound( ( char* )VMA( 1 ) ); case WSCG_S_STARTBACKGROUNDTRACK: S_StartBackgroundTrack( ( char* )VMA( 1 ), ( char* )VMA( 2 ), args[ 3 ] ); //----(SA) added fadeup time return 0; case WSCG_S_FADESTREAMINGSOUND: S_FadeStreamingSound( VMF( 1 ), args[ 2 ], args[ 3 ] ); //----(SA) added music/all-streaming options return 0; case WSCG_S_STARTSTREAMINGSOUND: S_StartStreamingSound( ( char* )VMA( 1 ), ( char* )VMA( 2 ), args[ 3 ], args[ 4 ], args[ 5 ] ); return 0; case WSCG_S_FADEALLSOUNDS: S_FadeAllSounds( VMF( 1 ), args[ 2 ], false ); //----(SA) added return 0; case WSCG_R_LOADWORLDMAP: R_LoadWorld( ( char* )VMA( 1 ) ); return 0; case WSCG_R_REGISTERMODEL: return R_RegisterModel( ( char* )VMA( 1 ) ); case WSCG_R_REGISTERSKIN: return R_RegisterSkin( ( char* )VMA( 1 ) ); case WSCG_R_GETSKINMODEL: return R_GetSkinModel( args[ 1 ], ( char* )VMA( 2 ), ( char* )VMA( 3 ) ); case WSCG_R_GETMODELSHADER: return R_GetShaderFromModel( args[ 1 ], args[ 2 ], args[ 3 ] ); case WSCG_R_REGISTERSHADER: return R_RegisterShader( ( char* )VMA( 1 ) ); case WSCG_R_REGISTERFONT: R_RegisterFont( ( char* )VMA( 1 ), args[ 2 ], ( fontInfo_t* )VMA( 3 ) ); case WSCG_R_REGISTERSHADERNOMIP: return R_RegisterShaderNoMip( ( char* )VMA( 1 ) ); case WSCG_R_CLEARSCENE: R_ClearScene(); return 0; case WSCG_R_ADDREFENTITYTOSCENE: CLWS_AddRefEntityToScene( ( wsrefEntity_t* )VMA( 1 ) ); return 0; case WSCG_R_ADDPOLYTOSCENE: R_AddPolyToScene( args[ 1 ], args[ 2 ], ( polyVert_t* )VMA( 3 ), 1 ); return 0; case WSCG_R_ADDPOLYSTOSCENE: R_AddPolyToScene( args[ 1 ], args[ 2 ], ( polyVert_t* )VMA( 3 ), args[ 4 ] ); return 0; case WSCG_RB_ZOMBIEFXADDNEWHIT: return 0; case WSCG_R_ADDLIGHTTOSCENE: R_AddLightToScene( ( float* )VMA( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), args[ 6 ] ); return 0; case WSCG_R_ADDCORONATOSCENE: R_AddCoronaToScene( ( float* )VMA( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), args[ 6 ], args[ 7 ] ); return 0; case WSCG_R_SETFOG: R_SetFog( args[ 1 ], args[ 2 ], args[ 3 ], VMF( 4 ), VMF( 5 ), VMF( 6 ), VMF( 7 ) ); return 0; case WSCG_R_RENDERSCENE: CLWS_RenderScene( ( wsrefdef_t* )VMA( 1 ) ); return 0; case WSCG_R_SETCOLOR: R_SetColor( ( float* )VMA( 1 ) ); return 0; case WSCG_R_DRAWSTRETCHPIC: R_StretchPic( VMF( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), VMF( 6 ), VMF( 7 ), VMF( 8 ), args[ 9 ] ); return 0; case WSCG_R_DRAWSTRETCHPIC_GRADIENT: R_StretchPicGradient( VMF( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), VMF( 6 ), VMF( 7 ), VMF( 8 ), args[ 9 ], ( float* )VMA( 10 ), args[ 11 ] ); return 0; case WSCG_R_MODELBOUNDS: R_ModelBounds( args[ 1 ], ( float* )VMA( 2 ), ( float* )VMA( 3 ) ); return 0; case WSCG_R_LERPTAG: return CLWS_LerpTag( ( orientation_t* )VMA( 1 ), ( wsrefEntity_t* )VMA( 2 ), ( char* )VMA( 3 ), args[ 4 ] ); case WSCG_GETGLCONFIG: CLWS_GetGlconfig( ( wsglconfig_t* )VMA( 1 ) ); return 0; case WSCG_GETGAMESTATE: CLWS_GetGameState( ( wsgameState_t* )VMA( 1 ) ); return 0; case WSCG_GETCURRENTSNAPSHOTNUMBER: CLWS_GetCurrentSnapshotNumber( ( int* )VMA( 1 ), ( int* )VMA( 2 ) ); return 0; case WSCG_GETSNAPSHOT: return CLWS_GetSnapshot( args[ 1 ], ( wssnapshot_t* )VMA( 2 ) ); case WSCG_GETSERVERCOMMAND: return CLT3_GetServerCommand( args[ 1 ] ); case WSCG_GETCURRENTCMDNUMBER: return CLT3_GetCurrentCmdNumber(); case WSCG_GETUSERCMD: return CLWS_GetUserCmd( args[ 1 ], ( wsusercmd_t* )VMA( 2 ) ); case WSCG_SETUSERCMDVALUE: CLWS_SetUserCmdValue( args[ 1 ], args[ 2 ], VMF( 3 ), args[ 4 ] ); //----(SA) modified // NERVE - SMF - added fourth arg [cld] return 0; case WSCG_MEMORY_REMAINING: return 0x4000000; case WSCG_KEY_ISDOWN: return Key_IsDown( args[ 1 ] ); case WSCG_KEY_GETCATCHER: return Key_GetCatcher(); case WSCG_KEY_SETCATCHER: KeyQ3_SetCatcher( args[ 1 ] ); return 0; case WSCG_KEY_GETKEY: return Key_GetKey( ( char* )VMA( 1 ) ); case WSCG_MEMSET: return ( qintptr )memset( VMA( 1 ), args[ 2 ], args[ 3 ] ); case WSCG_MEMCPY: return ( qintptr )memcpy( VMA( 1 ), VMA( 2 ), args[ 3 ] ); case WSCG_STRNCPY: String::NCpy( ( char* )VMA( 1 ), ( char* )VMA( 2 ), args[ 3 ] ); return args[ 1 ]; case WSCG_SIN: return FloatAsInt( sin( VMF( 1 ) ) ); case WSCG_COS: return FloatAsInt( cos( VMF( 1 ) ) ); case WSCG_ATAN2: return FloatAsInt( atan2( VMF( 1 ), VMF( 2 ) ) ); case WSCG_SQRT: return FloatAsInt( sqrt( VMF( 1 ) ) ); case WSCG_FLOOR: return FloatAsInt( floor( VMF( 1 ) ) ); case WSCG_CEIL: return FloatAsInt( ceil( VMF( 1 ) ) ); case WSCG_ACOS: return FloatAsInt( idMath::ACos( VMF( 1 ) ) ); case WSCG_PC_ADD_GLOBAL_DEFINE: return PC_AddGlobalDefine( ( char* )VMA( 1 ) ); case WSCG_PC_LOAD_SOURCE: return PC_LoadSourceHandle( ( char* )VMA( 1 ) ); case WSCG_PC_FREE_SOURCE: return PC_FreeSourceHandle( args[ 1 ] ); case WSCG_PC_READ_TOKEN: return PC_ReadTokenHandleQ3( args[ 1 ], ( q3pc_token_t* )VMA( 2 ) ); case WSCG_PC_SOURCE_FILE_AND_LINE: return PC_SourceFileAndLine( args[ 1 ], ( char* )VMA( 2 ), ( int* )VMA( 3 ) ); case WSCG_S_STOPBACKGROUNDTRACK: S_StopBackgroundTrack(); return 0; case WSCG_REAL_TIME: return Com_RealTime( ( qtime_t* )VMA( 1 ) ); case WSCG_SNAPVECTOR: Sys_SnapVector( ( float* )VMA( 1 ) ); return 0; case WSCG_SENDMOVESPEEDSTOGAME: SVWS_SendMoveSpeedsToGame( args[ 1 ], ( char* )VMA( 2 ) ); return 0; case WSCG_CIN_PLAYCINEMATIC: return CIN_PlayCinematicStretched( ( char* )VMA( 1 ), args[ 2 ], args[ 3 ], args[ 4 ], args[ 5 ], args[ 6 ] ); case WSCG_CIN_STOPCINEMATIC: return CIN_StopCinematic( args[ 1 ] ); case WSCG_CIN_RUNCINEMATIC: return CIN_RunCinematic( args[ 1 ] ); case WSCG_CIN_DRAWCINEMATIC: CIN_DrawCinematic( args[ 1 ] ); return 0; case WSCG_CIN_SETEXTENTS: CIN_SetExtents( args[ 1 ], args[ 2 ], args[ 3 ], args[ 4 ], args[ 5 ] ); return 0; case WSCG_R_REMAP_SHADER: R_RemapShader( ( char* )VMA( 1 ), ( char* )VMA( 2 ), ( char* )VMA( 3 ) ); return 0; case WSCG_TESTPRINTINT: common->Printf( "%s%i\n", ( char* )VMA( 1 ), static_cast<int>( args[ 2 ] ) ); return 0; case WSCG_TESTPRINTFLOAT: common->Printf( "%s%f\n", ( char* )VMA( 1 ), VMF( 2 ) ); return 0; case WSCG_LOADCAMERA: return loadCamera( args[ 1 ], ( char* )VMA( 2 ) ); case WSCG_STARTCAMERA: CLWS_StartCamera( args[ 1 ], args[ 2 ] ); return 0; case WSCG_STOPCAMERA: CLWS_StopCamera( args[ 1 ] ); return 0; case WSCG_GETCAMERAINFO: return getCameraInfo( args[ 1 ], args[ 2 ], ( float* )VMA( 3 ), ( float* )VMA( 4 ), ( float* )VMA( 5 ) ); case WSCG_GET_ENTITY_TOKEN: return R_GetEntityToken( ( char* )VMA( 1 ), args[ 2 ] ); case WSCG_INGAME_POPUP: CLWS_InGamePopup( ( char* )VMA( 1 ) ); return 0; case WSCG_INGAME_CLOSEPOPUP: UIT3_KeyEvent( K_ESCAPE, true ); return 0; case WSCG_LIMBOCHAT: CLT3_AddToLimboChat( ( char* )VMA( 1 ) ); return 0; case WSCG_GETMODELINFO: return SVWS_GetModelInfo( args[ 1 ], ( char* )VMA( 2 ), ( animModelInfo_t** )VMA( 3 ) ); default: common->Error( "Bad cgame system trap: %i", static_cast<int>( args[ 0 ] ) ); } return 0; }
// The ui module is making a system call qintptr CLWM_UISystemCalls( qintptr* args ) { switch ( args[ 0 ] ) { case WMUI_ERROR: common->Error( "%s", ( char* )VMA( 1 ) ); return 0; case WMUI_PRINT: common->Printf( "%s", ( char* )VMA( 1 ) ); return 0; case WMUI_MILLISECONDS: return Sys_Milliseconds(); case WMUI_CVAR_REGISTER: Cvar_Register( ( vmCvar_t* )VMA( 1 ), ( char* )VMA( 2 ), ( char* )VMA( 3 ), args[ 4 ] ); return 0; case WMUI_CVAR_UPDATE: Cvar_Update( ( vmCvar_t* )VMA( 1 ) ); return 0; case WMUI_CVAR_SET: Cvar_Set( ( char* )VMA( 1 ), ( char* )VMA( 2 ) ); return 0; case WMUI_CVAR_VARIABLEVALUE: return FloatAsInt( Cvar_VariableValue( ( char* )VMA( 1 ) ) ); case WMUI_CVAR_VARIABLESTRINGBUFFER: Cvar_VariableStringBuffer( ( char* )VMA( 1 ), ( char* )VMA( 2 ), args[ 3 ] ); return 0; case WMUI_CVAR_SETVALUE: Cvar_SetValue( ( char* )VMA( 1 ), VMF( 2 ) ); return 0; case WMUI_CVAR_RESET: Cvar_Reset( ( char* )VMA( 1 ) ); return 0; case WMUI_CVAR_CREATE: Cvar_Get( ( char* )VMA( 1 ), ( char* )VMA( 2 ), args[ 3 ] ); return 0; case WMUI_CVAR_INFOSTRINGBUFFER: Cvar_InfoStringBuffer( args[ 1 ], MAX_INFO_STRING_Q3, ( char* )VMA( 2 ), args[ 3 ] ); return 0; case WMUI_ARGC: return Cmd_Argc(); case WMUI_ARGV: Cmd_ArgvBuffer( args[ 1 ], ( char* )VMA( 2 ), args[ 3 ] ); return 0; case WMUI_CMD_EXECUTETEXT: Cbuf_ExecuteText( args[ 1 ], ( char* )VMA( 2 ) ); return 0; case WMUI_FS_FOPENFILE: return FS_FOpenFileByMode( ( char* )VMA( 1 ), ( fileHandle_t* )VMA( 2 ), ( fsMode_t )args[ 3 ] ); case WMUI_FS_READ: FS_Read( VMA( 1 ), args[ 2 ], args[ 3 ] ); return 0; case WMUI_FS_WRITE: FS_Write( VMA( 1 ), args[ 2 ], args[ 3 ] ); return 0; case WMUI_FS_FCLOSEFILE: FS_FCloseFile( args[ 1 ] ); return 0; case WMUI_FS_DELETEFILE: return FS_Delete( ( char* )VMA( 1 ) ); case WMUI_FS_GETFILELIST: return FS_GetFileList( ( char* )VMA( 1 ), ( char* )VMA( 2 ), ( char* )VMA( 3 ), args[ 4 ] ); case WMUI_R_REGISTERMODEL: return R_RegisterModel( ( char* )VMA( 1 ) ); case WMUI_R_REGISTERSKIN: return R_RegisterSkin( ( char* )VMA( 1 ) ); case WMUI_R_REGISTERSHADERNOMIP: return R_RegisterShaderNoMip( ( char* )VMA( 1 ) ); case WMUI_R_CLEARSCENE: R_ClearScene(); return 0; case WMUI_R_ADDREFENTITYTOSCENE: CLWM_AddRefEntityToScene( ( wmrefEntity_t* )VMA( 1 ) ); return 0; case WMUI_R_ADDPOLYTOSCENE: R_AddPolyToScene( args[ 1 ], args[ 2 ], ( polyVert_t* )VMA( 3 ), 1 ); return 0; case WMUI_R_ADDPOLYSTOSCENE: R_AddPolyToScene( args[ 1 ], args[ 2 ], ( polyVert_t* )VMA( 3 ), args[ 4 ] ); return 0; case WMUI_R_ADDLIGHTTOSCENE: R_AddLightToScene( ( float* )VMA( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), args[ 6 ] ); return 0; case WMUI_R_ADDCORONATOSCENE: R_AddCoronaToScene( ( float* )VMA( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), args[ 6 ], args[ 7 ] ); return 0; case WMUI_R_RENDERSCENE: CLWM_RenderScene( ( wmrefdef_t* )VMA( 1 ) ); return 0; case WMUI_R_SETCOLOR: R_SetColor( ( float* )VMA( 1 ) ); return 0; case WMUI_R_DRAWSTRETCHPIC: R_StretchPic( VMF( 1 ), VMF( 2 ), VMF( 3 ), VMF( 4 ), VMF( 5 ), VMF( 6 ), VMF( 7 ), VMF( 8 ), args[ 9 ] ); return 0; case WMUI_R_MODELBOUNDS: R_ModelBounds( args[ 1 ], ( float* )VMA( 2 ), ( float* )VMA( 3 ) ); return 0; case WMUI_UPDATESCREEN: SCR_UpdateScreen(); return 0; case WMUI_CM_LERPTAG: return CLWM_LerpTag( ( orientation_t* )VMA( 1 ), ( wmrefEntity_t* )VMA( 2 ), ( char* )VMA( 3 ), args[ 4 ] ); case WMUI_S_REGISTERSOUND: return S_RegisterSound( ( char* )VMA( 1 ) ); case WMUI_S_STARTLOCALSOUND: S_StartLocalSound( args[ 1 ], args[ 2 ], 127 ); return 0; case WMUI_KEY_KEYNUMTOSTRINGBUF: Key_KeynumToStringBuf( args[ 1 ], ( char* )VMA( 2 ), args[ 3 ] ); return 0; case WMUI_KEY_GETBINDINGBUF: Key_GetBindingBuf( args[ 1 ], ( char* )VMA( 2 ), args[ 3 ] ); return 0; case WMUI_KEY_SETBINDING: Key_SetBinding( args[ 1 ], ( char* )VMA( 2 ) ); return 0; case WMUI_KEY_ISDOWN: return Key_IsDown( args[ 1 ] ); case WMUI_KEY_GETOVERSTRIKEMODE: return Key_GetOverstrikeMode(); case WMUI_KEY_SETOVERSTRIKEMODE: Key_SetOverstrikeMode( args[ 1 ] ); return 0; case WMUI_KEY_CLEARSTATES: Key_ClearStates(); return 0; case WMUI_KEY_GETCATCHER: return Key_GetCatcher(); case WMUI_KEY_SETCATCHER: KeyWM_SetCatcher( args[ 1 ] ); return 0; case WMUI_GETCLIPBOARDDATA: CLT3_GetClipboardData( ( char* )VMA( 1 ), args[ 2 ] ); return 0; case WMUI_GETCLIENTSTATE: UIT3_GetClientState( ( uiClientState_t* )VMA( 1 ) ); return 0; case WMUI_GETGLCONFIG: CLWM_GetGlconfig( ( wmglconfig_t* )VMA( 1 ) ); return 0; case WMUI_GETCONFIGSTRING: return CLWM_GetConfigString( args[ 1 ], ( char* )VMA( 2 ), args[ 3 ] ); case WMUI_LAN_LOADCACHEDSERVERS: LAN_LoadCachedServers(); return 0; case WMUI_LAN_SAVECACHEDSERVERS: LAN_SaveServersToCache(); return 0; case WMUI_LAN_ADDSERVER: return LAN_AddServer( args[ 1 ], ( char* )VMA( 2 ), ( char* )VMA( 3 ) ); case WMUI_LAN_REMOVESERVER: LAN_RemoveServer( args[ 1 ], ( char* )VMA( 2 ) ); return 0; case WMUI_LAN_GETPINGQUEUECOUNT: return CLT3_GetPingQueueCount(); case WMUI_LAN_CLEARPING: CLT3_ClearPing( args[ 1 ] ); return 0; case WMUI_LAN_GETPING: CLT3_GetPing( args[ 1 ], ( char* )VMA( 2 ), args[ 3 ], ( int* )VMA( 4 ) ); return 0; case WMUI_LAN_GETPINGINFO: CLT3_GetPingInfo( args[ 1 ], ( char* )VMA( 2 ), args[ 3 ] ); return 0; case WMUI_LAN_GETSERVERCOUNT: return LAN_GetServerCount( args[ 1 ] ); case WMUI_LAN_GETSERVERADDRESSSTRING: LAN_GetServerAddressString( args[ 1 ], args[ 2 ], ( char* )VMA( 3 ), args[ 4 ] ); return 0; case WMUI_LAN_GETSERVERINFO: LAN_GetServerInfo( args[ 1 ], args[ 2 ], ( char* )VMA( 3 ), args[ 4 ] ); return 0; case WMUI_LAN_GETSERVERPING: return LAN_GetServerPing( args[ 1 ], args[ 2 ] ); case WMUI_LAN_MARKSERVERVISIBLE: LAN_MarkServerVisible( args[ 1 ], args[ 2 ], args[ 3 ] ); return 0; case WMUI_LAN_SERVERISVISIBLE: return LAN_ServerIsVisible( args[ 1 ], args[ 2 ] ); case WMUI_LAN_UPDATEVISIBLEPINGS: return CLT3_UpdateVisiblePings( args[ 1 ] ); case WMUI_LAN_RESETPINGS: LAN_ResetPings( args[ 1 ] ); return 0; case WMUI_LAN_SERVERSTATUS: return CLT3_ServerStatus( ( char* )VMA( 1 ), ( char* )VMA( 2 ), args[ 3 ] ); case WMUI_SET_PBCLSTATUS: return 0; case WMUI_SET_PBSVSTATUS: return 0; case WMUI_LAN_COMPARESERVERS: return LAN_CompareServers( args[ 1 ], args[ 2 ], args[ 3 ], args[ 4 ], args[ 5 ] ); case WMUI_MEMORY_REMAINING: return 0x4000000; case WMUI_GET_CDKEY: CLT3UI_GetCDKey( ( char* )VMA( 1 ), args[ 2 ] ); return 0; case WMUI_SET_CDKEY: CLT3UI_SetCDKey( ( char* )VMA( 1 ) ); return 0; case WMUI_R_REGISTERFONT: R_RegisterFont( ( char* )VMA( 1 ), args[ 2 ], ( fontInfo_t* )VMA( 3 ) ); return 0; case WMUI_MEMSET: return ( qintptr )memset( VMA( 1 ), args[ 2 ], args[ 3 ] ); case WMUI_MEMCPY: return ( qintptr )memcpy( VMA( 1 ), VMA( 2 ), args[ 3 ] ); case WMUI_STRNCPY: String::NCpy( ( char* )VMA( 1 ), ( char* )VMA( 2 ), args[ 3 ] ); return args[ 1 ]; case WMUI_SIN: return FloatAsInt( sin( VMF( 1 ) ) ); case WMUI_COS: return FloatAsInt( cos( VMF( 1 ) ) ); case WMUI_ATAN2: return FloatAsInt( atan2( VMF( 1 ), VMF( 2 ) ) ); case WMUI_SQRT: return FloatAsInt( sqrt( VMF( 1 ) ) ); case WMUI_FLOOR: return FloatAsInt( floor( VMF( 1 ) ) ); case WMUI_CEIL: return FloatAsInt( ceil( VMF( 1 ) ) ); case WMUI_PC_ADD_GLOBAL_DEFINE: return PC_AddGlobalDefine( ( char* )VMA( 1 ) ); case WMUI_PC_LOAD_SOURCE: return PC_LoadSourceHandle( ( char* )VMA( 1 ) ); case WMUI_PC_FREE_SOURCE: return PC_FreeSourceHandle( args[ 1 ] ); case WMUI_PC_READ_TOKEN: return PC_ReadTokenHandleQ3( args[ 1 ], ( q3pc_token_t* )VMA( 2 ) ); case WMUI_PC_SOURCE_FILE_AND_LINE: return PC_SourceFileAndLine( args[ 1 ], ( char* )VMA( 2 ), ( int* )VMA( 3 ) ); case WMUI_S_STOPBACKGROUNDTRACK: S_StopBackgroundTrack(); return 0; case WMUI_S_STARTBACKGROUNDTRACK: S_StartBackgroundTrack( ( char* )VMA( 1 ), ( char* )VMA( 2 ), 0 ); return 0; case WMUI_REAL_TIME: return Com_RealTime( ( qtime_t* )VMA( 1 ) ); case WMUI_CIN_PLAYCINEMATIC: return CIN_PlayCinematicStretched( ( char* )VMA( 1 ), args[ 2 ], args[ 3 ], args[ 4 ], args[ 5 ], args[ 6 ] ); case WMUI_CIN_STOPCINEMATIC: return CIN_StopCinematic( args[ 1 ] ); case WMUI_CIN_RUNCINEMATIC: return CIN_RunCinematic( args[ 1 ] ); case WMUI_CIN_DRAWCINEMATIC: CIN_DrawCinematic( args[ 1 ] ); return 0; case WMUI_CIN_SETEXTENTS: CIN_SetExtents( args[ 1 ], args[ 2 ], args[ 3 ], args[ 4 ], args[ 5 ] ); return 0; case WMUI_R_REMAP_SHADER: R_RemapShader( ( char* )VMA( 1 ), ( char* )VMA( 2 ), ( char* )VMA( 3 ) ); return 0; case WMUI_VERIFY_CDKEY: return CLT3_CDKeyValidate( ( char* )VMA( 1 ), ( char* )VMA( 2 ) ); case WMUI_CL_GETLIMBOSTRING: return CLT3_GetLimboString( args[ 1 ], ( char* )VMA( 2 ) ); case WMUI_CL_TRANSLATE_STRING: CL_TranslateString( ( char* )VMA( 1 ), ( char* )VMA( 2 ) ); return 0; case WMUI_CHECKAUTOUPDATE: return 0; case WMUI_GET_AUTOUPDATE: return 0; case WMUI_OPENURL: CLT3_OpenURL( ( const char* )VMA( 1 ) ); return 0; default: common->Error( "Bad UI system trap: %i", static_cast<int>( args[ 0 ] ) ); } return 0; }
/* * Mod_LoadSkeletalModel */ void Mod_LoadSkeletalModel( model_t *mod, const model_t *parent, void *buffer, bspFormatDesc_t *unused ) { unsigned int i, j, k; size_t filesize; qbyte *pbase; size_t memsize; qbyte *pmem; iqmheader_t *header; char *texts; iqmvertexarray_t *va; iqmjoint_t *joints; bonepose_t *baseposes; iqmpose_t *poses; unsigned short *framedata; const int *inelems; elem_t *outelems; iqmmesh_t *inmesh; iqmbounds_t *inbounds; float *vposition, *vtexcoord, *vnormal, *vtangent; qbyte *vblendindices_byte, *vblendweights_byte; int *vblendindexes_int; float *vblendweights_float; mskmodel_t *poutmodel; baseposes = NULL; header = ( iqmheader_t * )buffer; // check IQM magic if( memcmp( header->magic, "INTERQUAKEMODEL", 16 ) ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s is not an Inter-Quake Model\n", mod->name ); goto error; } // check header version header->version = LittleLong( header->version ); if( header->version != IQM_VERSION ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s has wrong type number (%i should be %i)\n", mod->name, header->version, IQM_VERSION ); goto error; } // byteswap header #define H_SWAP(s) (header->s = LittleLong( header->s )) H_SWAP( filesize ); H_SWAP( flags ); H_SWAP( num_text ); H_SWAP( ofs_text ); H_SWAP( num_meshes ); H_SWAP( ofs_meshes ); H_SWAP( num_vertexarrays ); H_SWAP( num_vertexes ); H_SWAP( ofs_vertexarrays ); H_SWAP( num_triangles ); H_SWAP( ofs_triangles ); H_SWAP( ofs_adjacency ); H_SWAP( num_joints ); H_SWAP( ofs_joints ); H_SWAP( num_poses ); H_SWAP( ofs_poses ); H_SWAP( num_anims ); H_SWAP( ofs_anims ); H_SWAP( num_frames ); H_SWAP( num_framechannels ); H_SWAP( ofs_frames ); H_SWAP( ofs_bounds ); H_SWAP( num_comment ); H_SWAP( ofs_comment ); H_SWAP( num_extensions ); H_SWAP( ofs_extensions ); #undef H_SWAP if( header->num_triangles < 1 || header->num_vertexes < 3 || header->num_vertexarrays < 1 || header->num_meshes < 1 ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s has no geometry\n", mod->name ); goto error; } if( header->num_frames < 1 || header->num_anims < 1 ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s has no animations\n", mod->name ); goto error; } if( header->num_joints != header->num_poses ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s has an invalid number of poses: %i vs %i\n", mod->name, header->num_joints, header->num_poses ); goto error; } if( !header->ofs_bounds ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s has no frame bounds\n", mod->name ); goto error; } pbase = ( qbyte * )buffer; filesize = header->filesize; // check data offsets against the filesize if( header->ofs_text + header->num_text > filesize || header->ofs_vertexarrays + header->num_vertexarrays * sizeof( iqmvertexarray_t ) > filesize || header->ofs_joints + header->num_joints * sizeof( iqmjoint_t ) > filesize || header->ofs_frames + header->num_frames * header->num_framechannels * sizeof( unsigned short ) > filesize || header->ofs_triangles + header->num_triangles * sizeof( int[3] ) > filesize || header->ofs_meshes + header->num_meshes * sizeof( iqmmesh_t ) > filesize || header->ofs_bounds + header->num_frames * sizeof( iqmbounds_t ) > filesize ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s has invalid size or offset information\n", mod->name ); goto error; } poutmodel = mod->extradata = Mod_Malloc( mod, sizeof( *poutmodel ) ); // load text texts = Mod_Malloc( mod, header->num_text + 1 ); if( header->ofs_text ) { memcpy( texts, (const char *)(pbase + header->ofs_text), header->num_text ); } texts[header->ofs_text] = '\0'; // load vertex arrays vposition = NULL; vtexcoord = NULL; vnormal = NULL; vtangent = NULL; vblendindices_byte = NULL; vblendindexes_int = NULL; vblendweights_byte = NULL; vblendweights_float = NULL; va = ( iqmvertexarray_t * )( pbase + header->ofs_vertexarrays ); for( i = 0; i < header->num_vertexarrays; i++ ) { size_t vsize; va[i].type = LittleLong( va[i].type ); va[i].flags = LittleLong( va[i].flags ); va[i].format = LittleLong( va[i].format ); va[i].size = LittleLong( va[i].size ); va[i].offset = LittleLong( va[i].offset ); vsize = header->num_vertexes*va[i].size; switch( va[i].format ) { case IQM_FLOAT: vsize *= sizeof( float ); break; case IQM_INT: case IQM_UINT: vsize *= sizeof( int ); break; case IQM_BYTE: case IQM_UBYTE: vsize *= sizeof( unsigned char ); break; default: continue; } if( va[i].offset + vsize > filesize ) { continue; } switch( va[i].type ) { case IQM_POSITION: if( va[i].format == IQM_FLOAT && va[i].size == 3 ) { vposition = ( float * )( pbase + va[i].offset ); } break; case IQM_TEXCOORD: if( va[i].format == IQM_FLOAT && va[i].size == 2 ) { vtexcoord = ( float * )( pbase + va[i].offset ); } break; case IQM_NORMAL: if( va[i].format == IQM_FLOAT && va[i].size == 3 ) { vnormal = ( float * )( pbase + va[i].offset ); } break; case IQM_TANGENT: if( va[i].format == IQM_FLOAT && va[i].size == 4 ) { vtangent = ( float * )( pbase + va[i].offset ); } break; case IQM_BLENDINDEXES: if( va[i].size != SKM_MAX_WEIGHTS ) break; if( va[i].format == IQM_BYTE || va[i].format == IQM_UBYTE ) { vblendindices_byte = ( qbyte * )( pbase + va[i].offset ); } else if( va[i].format == IQM_INT || va[i].format == IQM_UINT ) { vblendindexes_int = ( int * )( pbase + va[i].offset ); } break; case IQM_BLENDWEIGHTS: if( va[i].size != SKM_MAX_WEIGHTS ) break; if( va[i].format == IQM_UBYTE ) { vblendweights_byte = ( qbyte * )( pbase + va[i].offset ); } else if( va[i].format == IQM_FLOAT ) { vblendweights_float = ( float * )( pbase + va[i].offset ); } break; default: break; } } if( !vposition || !vtexcoord || !(vblendindices_byte || vblendindexes_int) || !(vblendweights_byte || vblendweights_float) ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s is missing vertex array data\n", mod->name ); goto error; } // load joints memsize = 0; memsize += sizeof( bonepose_t ) * header->num_joints; pmem = Mod_Malloc( mod, memsize ); baseposes = ( void * )pmem; pmem += sizeof( *baseposes ); memsize = 0; memsize += sizeof( mskbone_t ) * header->num_joints; memsize += sizeof( bonepose_t ) * header->num_joints; pmem = Mod_Malloc( mod, memsize ); poutmodel->numbones = header->num_joints; poutmodel->bones = ( void * )pmem; pmem += sizeof( *poutmodel->bones ) * poutmodel->numbones; poutmodel->invbaseposes = ( void * )pmem; pmem += sizeof( *poutmodel->invbaseposes ) * poutmodel->numbones; joints = ( iqmjoint_t * )( pbase + header->ofs_joints ); for( i = 0; i < poutmodel->numbones; i++ ) { joints[i].name = LittleLong( joints[i].name ); joints[i].parent = LittleLong( joints[i].parent ); for( j = 0; j < 3; j++ ) { joints[i].translate[j] = LittleFloat( joints[i].translate[j] ); joints[i].rotate[j] = LittleFloat( joints[i].rotate[j] ); joints[i].scale[j] = LittleFloat( joints[i].scale[j] ); } if( joints[i].parent >= (int)i ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s bone[%i].parent(%i) >= %i\n", mod->name, i, joints[i].parent, i ); goto error; } poutmodel->bones[i].name = texts + joints[i].name; poutmodel->bones[i].parent = joints[i].parent; DualQuat_FromQuat3AndVector( joints[i].rotate, joints[i].translate, baseposes[i].dualquat ); // scale is unused // reconstruct invserse bone pose if( joints[i].parent >= 0 ) { bonepose_t bp, *pbp; bp = baseposes[i]; pbp = &baseposes[joints[i].parent]; DualQuat_Multiply( pbp->dualquat, bp.dualquat, baseposes[i].dualquat ); } DualQuat_Copy( baseposes[i].dualquat, poutmodel->invbaseposes[i].dualquat ); DualQuat_Invert( poutmodel->invbaseposes[i].dualquat ); } // load frames poses = ( iqmpose_t * )( pbase + header->ofs_poses ); for( i = 0; i < header->num_poses; i++ ) { poses[i].parent = LittleLong( poses[i].parent ); poses[i].mask = LittleLong( poses[i].mask ); for( j = 0; j < 10; j++ ) { poses[i].channeloffset[j] = LittleFloat( poses[i].channeloffset[j] ); poses[i].channelscale[j] = LittleFloat( poses[i].channelscale[j] ); } } memsize = 0; memsize += sizeof( mskframe_t ) * header->num_frames; memsize += sizeof( bonepose_t ) * header->num_joints * header->num_frames; pmem = Mod_Malloc( mod, memsize ); poutmodel->numframes = header->num_frames; poutmodel->frames = ( mskframe_t * )pmem; pmem += sizeof( mskframe_t ) * poutmodel->numframes; framedata = ( unsigned short * )( pbase + header->ofs_frames ); for( i = 0; i < header->num_frames; i++ ) { bonepose_t *pbp; vec3_t translate; quat_t rotate; poutmodel->frames[i].boneposes = ( bonepose_t * )pmem; pmem += sizeof( bonepose_t ) * poutmodel->numbones; for( j = 0, pbp = poutmodel->frames[i].boneposes; j < header->num_poses; j++, pbp++ ) { translate[0] = poses[j].channeloffset[0]; if( poses[j].mask & 0x01 ) translate[0] += *framedata++ * poses[j].channelscale[0]; translate[1] = poses[j].channeloffset[1]; if( poses[j].mask & 0x02 ) translate[1] += *framedata++ * poses[j].channelscale[1]; translate[2] = poses[j].channeloffset[2]; if( poses[j].mask & 0x04 ) translate[2] += *framedata++ * poses[j].channelscale[2]; rotate[0] = poses[j].channeloffset[3]; if( poses[j].mask & 0x08 ) rotate[0] += *framedata++ * poses[j].channelscale[3]; rotate[1] = poses[j].channeloffset[4]; if( poses[j].mask & 0x10 ) rotate[1] += *framedata++ * poses[j].channelscale[4]; rotate[2] = poses[j].channeloffset[5]; if( poses[j].mask & 0x20 ) rotate[2] += *framedata++ * poses[j].channelscale[5]; rotate[3] = poses[j].channeloffset[6]; if( poses[j].mask & 0x40 ) rotate[3] += *framedata++ * poses[j].channelscale[6]; if( rotate[3] > 0 ) { Vector4Inverse( rotate ); } Vector4Normalize( rotate ); // scale is unused if( poses[j].mask & 0x80 ) framedata++; if( poses[j].mask & 0x100 ) framedata++; if( poses[j].mask & 0x200 ) framedata++; DualQuat_FromQuatAndVector( rotate, translate, pbp->dualquat ); } } // load triangles memsize = 0; memsize += sizeof( *outelems ) * header->num_triangles * 3; pmem = Mod_Malloc( mod, memsize ); poutmodel->numtris = header->num_triangles; poutmodel->elems = ( elem_t * )pmem; pmem += sizeof( *outelems ) * header->num_triangles * 3; inelems = ( const int * )(pbase + header->ofs_triangles); outelems = poutmodel->elems; for( i = 0; i < header->num_triangles; i++ ) { for( j = 0; j < 3; j++ ) { outelems[j] = LittleLong( inelems[j] ); } inelems += 3; outelems += 3; } // load vertices memsize = 0; memsize += sizeof( *poutmodel->sVectorsArray ) * header->num_vertexes; // 16-bytes aligned memsize += sizeof( *poutmodel->xyzArray ) * header->num_vertexes; memsize += sizeof( *poutmodel->normalsArray ) * header->num_vertexes; memsize += sizeof( *poutmodel->stArray ) * header->num_vertexes; memsize += sizeof( *poutmodel->blendWeights ) * header->num_vertexes * SKM_MAX_WEIGHTS; memsize += sizeof( *poutmodel->blendIndices ) * header->num_vertexes * SKM_MAX_WEIGHTS; pmem = Mod_Malloc( mod, memsize ); poutmodel->numverts = header->num_vertexes; // S-vectors poutmodel->sVectorsArray = ( vec4_t * )pmem; pmem += sizeof( *poutmodel->sVectorsArray ) * header->num_vertexes; if( vtangent ) { for( i = 0; i < header->num_vertexes; i++ ) { for( j = 0; j < 4; j++ ) { poutmodel->sVectorsArray[i][j] = LittleFloat( vtangent[j] ); } vtangent += 4; } } // XYZ positions poutmodel->xyzArray = ( vec4_t * )pmem; pmem += sizeof( *poutmodel->xyzArray ) * header->num_vertexes; for( i = 0; i < header->num_vertexes; i++ ) { for( j = 0; j < 3; j++ ) { poutmodel->xyzArray[i][j] = LittleFloat( vposition[j] ); } poutmodel->xyzArray[i][3] = 1; vposition += 3; } // normals poutmodel->normalsArray = ( vec4_t * )pmem; pmem += sizeof( *poutmodel->normalsArray ) * header->num_vertexes; for( i = 0; i < header->num_vertexes; i++ ) { for( j = 0; j < 3; j++ ) { poutmodel->normalsArray[i][j] = LittleFloat( vnormal[j] ); } poutmodel->normalsArray[i][3] = 0; vnormal += 3; } // texture coordinates poutmodel->stArray = ( vec2_t * )pmem; pmem += sizeof( *poutmodel->stArray ) * header->num_vertexes; for( i = 0; i < header->num_vertexes; i++ ) { for( j = 0; j < 2; j++ ) { poutmodel->stArray[i][j] = LittleFloat( vtexcoord[j] ); } vtexcoord += 2; } if( !vtangent ) { // if the loaded file is missing precomputed S-vectors, compute them now R_BuildTangentVectors( poutmodel->numverts, poutmodel->xyzArray, poutmodel->normalsArray, poutmodel->stArray, poutmodel->numtris, poutmodel->elems, poutmodel->sVectorsArray ); } // blend indices poutmodel->blendIndices = ( qbyte * )pmem; pmem += sizeof( *poutmodel->blendIndices ) * header->num_vertexes * SKM_MAX_WEIGHTS; if( vblendindices_byte ) { memcpy( poutmodel->blendIndices, vblendindices_byte, sizeof( qbyte ) * header->num_vertexes * SKM_MAX_WEIGHTS ); } else if( vblendindexes_int ) { for( j = 0; j < header->num_vertexes * SKM_MAX_WEIGHTS; j++ ) { poutmodel->blendIndices[j] = LittleLong( vblendindexes_int[j] ); } } // blend weights poutmodel->blendWeights = ( qbyte * )pmem; pmem += sizeof( *poutmodel->blendWeights ) * header->num_vertexes * SKM_MAX_WEIGHTS; if( vblendweights_byte ) { memcpy( poutmodel->blendWeights, vblendweights_byte, sizeof( qbyte ) * header->num_vertexes * SKM_MAX_WEIGHTS ); } else if( vblendweights_float ) { for( j = 0; j < header->num_vertexes * SKM_MAX_WEIGHTS; j++ ) { poutmodel->blendWeights[j] = LittleFloat( vblendweights_float[j] ) * 255.0f; } } // blends memsize = 0; memsize += poutmodel->numverts * ( sizeof( mskblend_t ) + sizeof( unsigned int ) ); pmem = Mod_Malloc( mod, memsize ); poutmodel->numblends = 0; poutmodel->blends = ( mskblend_t * )pmem; pmem += sizeof( *poutmodel->blends ) * poutmodel->numverts; poutmodel->vertexBlends = ( unsigned int * )pmem; vblendindices_byte = poutmodel->blendIndices; vblendweights_byte = poutmodel->blendWeights; for( i = 0; i < poutmodel->numverts; i++ ) { mskblend_t blend; for( j = 0; j < SKM_MAX_WEIGHTS; j++ ) { blend.indices[j] = vblendindices_byte[j]; blend.weights[j] = vblendweights_byte[j]; } poutmodel->vertexBlends[i] = Mod_SkeletalModel_AddBlend( poutmodel, &blend ); vblendindices_byte += SKM_MAX_WEIGHTS; vblendweights_byte += SKM_MAX_WEIGHTS; } // meshes memsize = 0; memsize += sizeof( mskmesh_t ) * header->num_meshes; memsize += sizeof( drawSurfaceSkeletal_t ) * header->num_meshes; pmem = Mod_Malloc( mod, memsize ); poutmodel->nummeshes = header->num_meshes; poutmodel->meshes = ( mskmesh_t * )pmem; pmem += sizeof( *poutmodel->meshes ) * header->num_meshes; inmesh = ( iqmmesh_t * )(pbase + header->ofs_meshes); for( i = 0; i < header->num_meshes; i++ ) { inmesh[i].name = LittleLong( inmesh[i].name ); inmesh[i].material = LittleLong( inmesh[i].material ); inmesh[i].first_vertex = LittleLong( inmesh[i].first_vertex ); inmesh[i].num_vertexes = LittleLong( inmesh[i].num_vertexes ); inmesh[i].first_triangle = LittleLong( inmesh[i].first_triangle ); inmesh[i].num_triangles = LittleLong( inmesh[i].num_triangles ); poutmodel->meshes[i].name = texts + inmesh[i].name; Mod_StripLODSuffix( poutmodel->meshes[i].name ); poutmodel->meshes[i].skin.name = texts + inmesh[i].material; poutmodel->meshes[i].skin.shader = R_RegisterSkin( poutmodel->meshes[i].skin.name ); poutmodel->meshes[i].elems = poutmodel->elems + inmesh[i].first_triangle * 3; poutmodel->meshes[i].numtris = inmesh[i].num_triangles; poutmodel->meshes[i].numverts = inmesh[i].num_vertexes; poutmodel->meshes[i].xyzArray = poutmodel->xyzArray + inmesh[i].first_vertex; poutmodel->meshes[i].normalsArray = poutmodel->normalsArray + inmesh[i].first_vertex; poutmodel->meshes[i].stArray = poutmodel->stArray + inmesh[i].first_vertex; poutmodel->meshes[i].sVectorsArray = poutmodel->sVectorsArray + inmesh[i].first_vertex; poutmodel->meshes[i].blendIndices = poutmodel->blendIndices + inmesh[i].first_vertex * SKM_MAX_WEIGHTS; poutmodel->meshes[i].blendWeights = poutmodel->blendWeights + inmesh[i].first_vertex * SKM_MAX_WEIGHTS; poutmodel->meshes[i].vertexBlends = poutmodel->vertexBlends + inmesh[i].first_vertex; // elements are always offset to start vertex 0 for each mesh outelems = poutmodel->meshes[i].elems; for( j = 0; j < poutmodel->meshes[i].numtris; j++ ) { outelems[0] -= inmesh[i].first_vertex; outelems[1] -= inmesh[i].first_vertex; outelems[2] -= inmesh[i].first_vertex; outelems += 3; } poutmodel->meshes[i].maxWeights = 1; vblendweights_byte = poutmodel->meshes[i].blendWeights; for( j = 0; j < poutmodel->meshes[i].numverts; j++ ) { for( k = 1; k < SKM_MAX_WEIGHTS && vblendweights_byte[k]; k++ ); if( k > poutmodel->meshes[i].maxWeights ) { poutmodel->meshes[i].maxWeights = k; if( k == SKM_MAX_WEIGHTS ) { break; } } vblendweights_byte += SKM_MAX_WEIGHTS; } // creating a VBO only makes sense if GLSL is present and the number of bones // we can handle on the GPU is sufficient if( glConfig.ext.vertex_buffer_object && poutmodel->numbones <= glConfig.maxGLSLBones ) { // build a static vertex buffer object for this mesh Mod_SkeletalBuildStaticVBOForMesh( &poutmodel->meshes[i] ); } } poutmodel->drawSurfs = ( drawSurfaceSkeletal_t * )pmem; pmem += sizeof( *poutmodel->drawSurfs ) * header->num_meshes; for( i = 0; i < header->num_meshes; i++ ) { poutmodel->drawSurfs[i].type = ST_SKELETAL; poutmodel->drawSurfs[i].model = mod; poutmodel->drawSurfs[i].mesh = poutmodel->meshes + i; } // bounds ClearBounds( mod->mins, mod->maxs ); inbounds = ( iqmbounds_t * )(pbase + header->ofs_bounds); for( i = 0; i < header->num_frames; i++ ) { for( j = 0; j < 3; j++ ) { inbounds[i].bbmin[j] = LittleFloat( inbounds[i].bbmin[j] ); inbounds[i].bbmax[j] = LittleFloat( inbounds[i].bbmax[j] ); } inbounds[i].radius = LittleFloat( inbounds[i].radius ); inbounds[i].xyradius = LittleFloat( inbounds[i].xyradius ); VectorCopy( inbounds[i].bbmin, poutmodel->frames[i].mins ); VectorCopy( inbounds[i].bbmax, poutmodel->frames[i].maxs ); poutmodel->frames[i].radius = inbounds[i].radius; AddPointToBounds( poutmodel->frames[i].mins, mod->mins, mod->maxs ); AddPointToBounds( poutmodel->frames[i].maxs, mod->mins, mod->maxs ); } mod->radius = RadiusFromBounds( mod->mins, mod->maxs ); mod->type = mod_skeletal; mod->registrationSequence = rsh.registrationSequence; mod->touch = &Mod_TouchSkeletalModel; R_Free( baseposes ); return; error: if( baseposes ) { R_Free( baseposes ); } mod->type = mod_bad; }
/* * Mod_LoadAliasMD3Model */ void Mod_LoadAliasMD3Model( model_t *mod, model_t *parent, void *buffer, bspFormatDesc_t *unused ) { int version, i, j, l; int bufsize, numverts; qbyte *buf; dmd3header_t *pinmodel; dmd3frame_t *pinframe; dmd3tag_t *pintag; dmd3mesh_t *pinmesh; dmd3skin_t *pinskin; dmd3coord_t *pincoord; dmd3vertex_t *pinvert; elem_t *pinelem, *poutelem; maliasvertex_t *poutvert; vec2_t *poutcoord; maliasskin_t *poutskin; maliasmesh_t *poutmesh; maliastag_t *pouttag; maliasframe_t *poutframe; maliasmodel_t *poutmodel; drawSurfaceAlias_t *drawSurf; pinmodel = ( dmd3header_t * )buffer; version = LittleLong( pinmodel->version ); if( version != MD3_ALIAS_VERSION ) ri.Com_Error( ERR_DROP, "%s has wrong version number (%i should be %i)", mod->name, version, MD3_ALIAS_VERSION ); mod->type = mod_alias; mod->extradata = poutmodel = Mod_Malloc( mod, sizeof( maliasmodel_t ) ); mod->radius = 0; mod->registrationSequence = rf.registrationSequence; mod->touch = &Mod_TouchAliasModel; ClearBounds( mod->mins, mod->maxs ); // byte swap the header fields and sanity check poutmodel->numframes = LittleLong( pinmodel->num_frames ); poutmodel->numtags = LittleLong( pinmodel->num_tags ); poutmodel->nummeshes = LittleLong( pinmodel->num_meshes ); poutmodel->numskins = 0; if( poutmodel->numframes <= 0 ) ri.Com_Error( ERR_DROP, "model %s has no frames", mod->name ); // else if( poutmodel->numframes > MD3_MAX_FRAMES ) // ri.Com_Error( ERR_DROP, "model %s has too many frames", mod->name ); if( poutmodel->numtags > MD3_MAX_TAGS ) ri.Com_Error( ERR_DROP, "model %s has too many tags", mod->name ); else if( poutmodel->numtags < 0 ) ri.Com_Error( ERR_DROP, "model %s has invalid number of tags", mod->name ); if( poutmodel->nummeshes < 0 ) ri.Com_Error( ERR_DROP, "model %s has invalid number of meshes", mod->name ); else if( !poutmodel->nummeshes && !poutmodel->numtags ) ri.Com_Error( ERR_DROP, "model %s has no meshes and no tags", mod->name ); // else if( poutmodel->nummeshes > MD3_MAX_MESHES ) // ri.Com_Error( ERR_DROP, "model %s has too many meshes", mod->name ); bufsize = poutmodel->numframes * ( sizeof( maliasframe_t ) + sizeof( maliastag_t ) * poutmodel->numtags ) + poutmodel->nummeshes * sizeof( maliasmesh_t ) + poutmodel->nummeshes * sizeof( drawSurfaceAlias_t ); buf = Mod_Malloc( mod, bufsize ); // // load the frames // pinframe = ( dmd3frame_t * )( ( qbyte * )pinmodel + LittleLong( pinmodel->ofs_frames ) ); poutframe = poutmodel->frames = ( maliasframe_t * )buf; buf += sizeof( maliasframe_t ) * poutmodel->numframes; for( i = 0; i < poutmodel->numframes; i++, pinframe++, poutframe++ ) { for( j = 0; j < 3; j++ ) { poutframe->scale[j] = MD3_XYZ_SCALE; poutframe->translate[j] = LittleFloat( pinframe->translate[j] ); } // never trust the modeler utility and recalculate bbox and radius ClearBounds( poutframe->mins, poutframe->maxs ); } // // load the tags // pintag = ( dmd3tag_t * )( ( qbyte * )pinmodel + LittleLong( pinmodel->ofs_tags ) ); pouttag = poutmodel->tags = ( maliastag_t * )buf; buf += sizeof( maliastag_t ) * poutmodel->numframes * poutmodel->numtags; for( i = 0; i < poutmodel->numframes; i++ ) { for( l = 0; l < poutmodel->numtags; l++, pintag++, pouttag++ ) { mat3_t axis; for( j = 0; j < 3; j++ ) { axis[AXIS_FORWARD+j] = LittleFloat( pintag->axis[0][j] ); axis[AXIS_RIGHT+j] = LittleFloat( pintag->axis[1][j] ); axis[AXIS_UP+j] = LittleFloat( pintag->axis[2][j] ); pouttag->origin[j] = LittleFloat( pintag->origin[j] ); } Quat_FromMatrix3( axis, pouttag->quat ); Quat_Normalize( pouttag->quat ); Q_strncpyz( pouttag->name, pintag->name, MD3_MAX_PATH ); } } // // allocate drawSurfs // drawSurf = poutmodel->drawSurfs = ( drawSurfaceAlias_t * )buf; buf += sizeof( drawSurfaceAlias_t ) * poutmodel->nummeshes; for( i = 0; i < poutmodel->nummeshes; i++, drawSurf++ ) { drawSurf->type = ST_ALIAS; drawSurf->model = mod; drawSurf->mesh = poutmodel->meshes + i; } // // load meshes // pinmesh = ( dmd3mesh_t * )( ( qbyte * )pinmodel + LittleLong( pinmodel->ofs_meshes ) ); poutmesh = poutmodel->meshes = ( maliasmesh_t * )buf; buf += sizeof( maliasmesh_t ) * poutmodel->nummeshes; for( i = 0; i < poutmodel->nummeshes; i++, poutmesh++ ) { if( strncmp( (const char *)pinmesh->id, IDMD3HEADER, 4 ) ) ri.Com_Error( ERR_DROP, "mesh %s in model %s has wrong id (%s should be %s)", pinmesh->name, mod->name, pinmesh->id, IDMD3HEADER ); Q_strncpyz( poutmesh->name, pinmesh->name, MD3_MAX_PATH ); Mod_StripLODSuffix( poutmesh->name ); poutmesh->numtris = LittleLong( pinmesh->num_tris ); poutmesh->numskins = LittleLong( pinmesh->num_skins ); poutmesh->numverts = numverts = LittleLong( pinmesh->num_verts ); /* if( poutmesh->numskins <= 0 ) ri.Com_Error( ERR_DROP, "mesh %i in model %s has no skins", i, mod->name ); else*/ if( poutmesh->numskins > MD3_MAX_SHADERS ) ri.Com_Error( ERR_DROP, "mesh %i in model %s has too many skins", i, mod->name ); if( poutmesh->numtris <= 0 ) ri.Com_Error( ERR_DROP, "mesh %i in model %s has no elements", i, mod->name ); else if( poutmesh->numtris > MD3_MAX_TRIANGLES ) ri.Com_Error( ERR_DROP, "mesh %i in model %s has too many triangles", i, mod->name ); if( poutmesh->numverts <= 0 ) ri.Com_Error( ERR_DROP, "mesh %i in model %s has no vertices", i, mod->name ); else if( poutmesh->numverts > MD3_MAX_VERTS ) ri.Com_Error( ERR_DROP, "mesh %i in model %s has too many vertices", i, mod->name ); bufsize = sizeof( maliasskin_t ) * poutmesh->numskins + poutmesh->numtris * sizeof( elem_t ) * 3 + numverts * ( sizeof( vec2_t ) + sizeof( maliasvertex_t ) * poutmodel->numframes ); buf = Mod_Malloc( mod, bufsize ); // // load the skins // pinskin = ( dmd3skin_t * )( ( qbyte * )pinmesh + LittleLong( pinmesh->ofs_skins ) ); poutskin = poutmesh->skins = ( maliasskin_t * )buf; buf += sizeof( maliasskin_t ) * poutmesh->numskins; for( j = 0; j < poutmesh->numskins; j++, pinskin++, poutskin++ ) { Q_strncpyz( poutskin->name, pinskin->name, sizeof( poutskin->name ) ); poutskin->shader = R_RegisterSkin( poutskin->name ); } // // load the elems // pinelem = ( elem_t * )( ( qbyte * )pinmesh + LittleLong( pinmesh->ofs_elems ) ); poutelem = poutmesh->elems = ( elem_t * )buf; buf += poutmesh->numtris * sizeof( elem_t ) * 3; for( j = 0; j < poutmesh->numtris; j++, pinelem += 3, poutelem += 3 ) { poutelem[0] = (elem_t)LittleLong( pinelem[0] ); poutelem[1] = (elem_t)LittleLong( pinelem[1] ); poutelem[2] = (elem_t)LittleLong( pinelem[2] ); } // // load the texture coordinates // pincoord = ( dmd3coord_t * )( ( qbyte * )pinmesh + LittleLong( pinmesh->ofs_tcs ) ); poutcoord = poutmesh->stArray = ( vec2_t * )buf; buf += poutmesh->numverts * sizeof( vec2_t ); for( j = 0; j < poutmesh->numverts; j++, pincoord++ ) { poutcoord[j][0] = LittleFloat( pincoord->st[0] ); poutcoord[j][1] = LittleFloat( pincoord->st[1] ); } // // load the vertexes and normals // pinvert = ( dmd3vertex_t * )( ( qbyte * )pinmesh + LittleLong( pinmesh->ofs_verts ) ); poutvert = poutmesh->vertexes = ( maliasvertex_t * )buf; for( l = 0, poutframe = poutmodel->frames; l < poutmodel->numframes; l++, poutframe++, pinvert += poutmesh->numverts, poutvert += poutmesh->numverts ) { vec3_t v; for( j = 0; j < poutmesh->numverts; j++ ) { poutvert[j].point[0] = LittleShort( pinvert[j].point[0] ); poutvert[j].point[1] = LittleShort( pinvert[j].point[1] ); poutvert[j].point[2] = LittleShort( pinvert[j].point[2] ); poutvert[j].latlong[0] = pinvert[j].norm[0]; poutvert[j].latlong[1] = pinvert[j].norm[1]; VectorCopy( poutvert[j].point, v ); AddPointToBounds( v, poutframe->mins, poutframe->maxs ); } } pinmesh = ( dmd3mesh_t * )( ( qbyte * )pinmesh + LittleLong( pinmesh->meshsize ) ); } // // setup drawSurfs // for( i = 0; i < poutmodel->nummeshes; i++ ) { drawSurf = poutmodel->drawSurfs + i; drawSurf->type = ST_ALIAS; drawSurf->model = mod; drawSurf->mesh = poutmodel->meshes + i; } // // build S and T vectors for frame 0 // Mod_AliasBuildMeshesForFrame0( mod ); // // calculate model bounds // poutframe = poutmodel->frames; for( i = 0; i < poutmodel->numframes; i++, poutframe++ ) { VectorMA( poutframe->translate, MD3_XYZ_SCALE, poutframe->mins, poutframe->mins ); VectorMA( poutframe->translate, MD3_XYZ_SCALE, poutframe->maxs, poutframe->maxs ); poutframe->radius = RadiusFromBounds( poutframe->mins, poutframe->maxs ); AddPointToBounds( poutframe->mins, mod->mins, mod->maxs ); AddPointToBounds( poutframe->maxs, mod->mins, mod->maxs ); mod->radius = max( mod->radius, poutframe->radius ); } }
qboolean PlayerConfig_MenuInit (void) { extern cvar_t *name; extern cvar_t *team; extern cvar_t *skin; char currentdirectory[1024]; char currentskin[1024]; char scratch[MAX_QPATH]; int i = 0; int y = 0; int currentdirectoryindex = 0; int currentskinindex = 0; cvar_t *hand = Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE ); static const char *handedness[] = { "right", "left", "center", 0 }; PlayerConfig_ScanDirectories (); if (s_numplayermodels == 0) return false; if ( hand->value < 0 || hand->value > 2 ) Cvar_SetValue( "hand", 0 ); // strncpy( currentdirectory, skin->string ); Q_strncpyz( currentdirectory, skin->string, sizeof(currentdirectory) ); if ( strchr( currentdirectory, '/' ) ) { // strncpy( currentskin, strchr( currentdirectory, '/' ) + 1 ); Q_strncpyz( currentskin, strchr( currentdirectory, '/' ) + 1, sizeof(currentskin) ); *strchr( currentdirectory, '/' ) = 0; } else if ( strchr( currentdirectory, '\\' ) ) { // strncpy( currentskin, strchr( currentdirectory, '\\' ) + 1 ); Q_strncpyz( currentskin, strchr( currentdirectory, '\\' ) + 1, sizeof(currentskin) ); *strchr( currentdirectory, '\\' ) = 0; } else { // strncpy( currentdirectory, "male" ); // strncpy( currentskin, "grunt" ); Q_strncpyz( currentdirectory, "male", sizeof(currentdirectory) ); Q_strncpyz( currentskin, "grunt", sizeof(currentskin) ); } qsort( s_pmi, s_numplayermodels, sizeof( s_pmi[0] ), pmicmpfnc ); memset( s_pmnames, 0, sizeof( s_pmnames ) ); for ( i = 0; i < s_numplayermodels; i++ ) { s_pmnames[i] = s_pmi[i].displayname; if ( Q_stricmp( s_pmi[i].directory, currentdirectory ) == 0 ) { int j; currentdirectoryindex = i; for ( j = 0; j < s_pmi[i].nskins; j++ ) { if ( Q_stricmp( s_pmi[i].skindisplaynames[j], currentskin ) == 0 ) { currentskinindex = j; break; } } } } s_player_config_menu.x = SCREEN_WIDTH*0.5 - 210; s_player_config_menu.y = SCREEN_HEIGHT*0.5 - 70; s_player_config_menu.nitems = 0; s_player_name_field.generic.type = MTYPE_FIELD; s_player_name_field.generic.flags = QMF_LEFT_JUSTIFY; s_player_name_field.generic.name = "name"; s_player_name_field.generic.callback = 0; s_player_name_field.generic.x = -MENU_FONT_SIZE; s_player_name_field.generic.y = y; s_player_name_field.length = 20; s_player_name_field.visible_length = 20; Q_strncpyz( s_player_name_field.buffer, name->string, sizeof(s_player_name_field.buffer) ); s_player_name_field.cursor = strlen( name->string ); s_player_model_title.generic.type = MTYPE_SEPARATOR; s_player_model_title.generic.flags = QMF_LEFT_JUSTIFY; s_player_model_title.generic.name = "model"; s_player_model_title.generic.x = -MENU_FONT_SIZE; s_player_model_title.generic.y = y += 3*MENU_LINE_SIZE; s_player_model_box.generic.type = MTYPE_SPINCONTROL; s_player_model_box.generic.x = -7*MENU_FONT_SIZE; s_player_model_box.generic.y = y += MENU_LINE_SIZE; s_player_model_box.generic.callback = ModelCallback; s_player_model_box.generic.cursor_offset = -6*MENU_FONT_SIZE; s_player_model_box.curvalue = currentdirectoryindex; s_player_model_box.itemnames = s_pmnames; s_player_skin_title.generic.type = MTYPE_SEPARATOR; s_player_skin_title.generic.flags = QMF_LEFT_JUSTIFY; s_player_skin_title.generic.name = "skin"; s_player_skin_title.generic.x = -2*MENU_FONT_SIZE; s_player_skin_title.generic.y = y += 2*MENU_LINE_SIZE; s_player_skin_box.generic.type = MTYPE_SPINCONTROL; s_player_skin_box.generic.x = -7*MENU_FONT_SIZE; s_player_skin_box.generic.y = y += MENU_LINE_SIZE; s_player_skin_box.generic.name = 0; s_player_skin_box.generic.callback = SkinCallback; // Knightmare added, was 0 s_player_skin_box.generic.cursor_offset = -6*MENU_FONT_SIZE; s_player_skin_box.curvalue = currentskinindex; s_player_skin_box.itemnames = s_pmi[currentdirectoryindex].skindisplaynames; s_player_skin_box.generic.flags |= QMF_SKINLIST; s_player_hand_title.generic.type = MTYPE_SEPARATOR; s_player_hand_title.generic.flags = QMF_LEFT_JUSTIFY; s_player_hand_title.generic.name = "handedness"; s_player_hand_title.generic.x = 4*MENU_FONT_SIZE; s_player_hand_title.generic.y = y += 2*MENU_LINE_SIZE; s_player_handedness_box.generic.type = MTYPE_SPINCONTROL; s_player_handedness_box.generic.x = -7*MENU_FONT_SIZE; s_player_handedness_box.generic.y = y += MENU_LINE_SIZE; s_player_handedness_box.generic.name = 0; s_player_handedness_box.generic.cursor_offset = -6*MENU_FONT_SIZE; s_player_handedness_box.generic.callback = HandednessCallback; s_player_handedness_box.curvalue = Cvar_VariableValue( "hand" ); s_player_handedness_box.itemnames = handedness; for (i = 0; i < sizeof(rate_tbl) / sizeof(*rate_tbl) - 1; i++) if (Cvar_VariableValue("rate") == rate_tbl[i]) break; s_player_rate_title.generic.type = MTYPE_SEPARATOR; s_player_rate_title.generic.flags = QMF_LEFT_JUSTIFY; s_player_rate_title.generic.name = "connect speed"; s_player_rate_title.generic.x = 7*MENU_FONT_SIZE; s_player_rate_title.generic.y = y += 2*MENU_LINE_SIZE; s_player_rate_box.generic.type = MTYPE_SPINCONTROL; s_player_rate_box.generic.x = -7*MENU_FONT_SIZE; s_player_rate_box.generic.y = y += MENU_LINE_SIZE; s_player_rate_box.generic.name = 0; s_player_rate_box.generic.cursor_offset = -6*MENU_FONT_SIZE; s_player_rate_box.generic.callback = RateCallback; s_player_rate_box.curvalue = i; s_player_rate_box.itemnames = rate_names; s_player_back_action.generic.type = MTYPE_ACTION; s_player_back_action.generic.name = "back to multiplayer"; s_player_back_action.generic.flags = QMF_LEFT_JUSTIFY; s_player_back_action.generic.x = -5*MENU_FONT_SIZE; s_player_back_action.generic.y = y += 2*MENU_LINE_SIZE; s_player_back_action.generic.statusbar = NULL; s_player_back_action.generic.callback = UI_BackMenu; // only register model and skin on starup or when changed Com_sprintf( scratch, sizeof( scratch ), "players/%s/tris.md2", s_pmi[s_player_model_box.curvalue].directory ); playermodel = R_RegisterModel( scratch ); Com_sprintf( scratch, sizeof( scratch ), "players/%s/%s.pcx", s_pmi[s_player_model_box.curvalue].directory, s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue] ); playerskin = R_RegisterSkin( scratch ); // show current weapon model (if any) if (currentweaponmodel && strlen(currentweaponmodel)) { Com_sprintf( scratch, sizeof( scratch ), "players/%s/%s", s_pmi[s_player_model_box.curvalue].directory, currentweaponmodel ); weaponmodel = R_RegisterModel( scratch ); if (!weaponmodel) { Com_sprintf( scratch, sizeof( scratch ), "players/%s/weapon.md2", s_pmi[s_player_model_box.curvalue].directory ); weaponmodel = R_RegisterModel( scratch ); } } else { Com_sprintf( scratch, sizeof( scratch ), "players/%s/weapon.md2", s_pmi[s_player_model_box.curvalue].directory ); weaponmodel = R_RegisterModel( scratch ); } Menu_AddItem( &s_player_config_menu, &s_player_name_field ); Menu_AddItem( &s_player_config_menu, &s_player_model_title ); Menu_AddItem( &s_player_config_menu, &s_player_model_box ); if ( s_player_skin_box.itemnames ) { Menu_AddItem( &s_player_config_menu, &s_player_skin_title ); Menu_AddItem( &s_player_config_menu, &s_player_skin_box ); } Menu_AddItem( &s_player_config_menu, &s_player_hand_title ); Menu_AddItem( &s_player_config_menu, &s_player_handedness_box ); Menu_AddItem( &s_player_config_menu, &s_player_rate_title ); Menu_AddItem( &s_player_config_menu, &s_player_rate_box ); Menu_AddItem( &s_player_config_menu, &s_player_back_action ); return true; }
/* ================ CL_LoadClientinfo ================ */ void CL_LoadClientinfo (clientinfo_t *ci, char *s) { int i = 0; char *t; char model_name[MAX_QPATH]; char skin_name[MAX_QPATH]; char model_filename[MAX_QPATH]; char skin_filename[MAX_QPATH]; char weapon_filename[MAX_QPATH]; Q_strncpyz (ci->cinfo, s, sizeof(ci->cinfo)); // isolate the player's name Q_strncpyz (ci->name, s, sizeof(ci->name)); t = strchr(s, '\\'); if (t) { if (t - s >= sizeof(ci->name)-1) { i = -1; } else { ci->name[t-s] = 0; s = t+1; } } t = s; while (*t) { if (*t <= 32) { i = -1; break; } t++; } if (cl_noskins->integer || *s == 0 || i == -1) { strcpy (model_filename, "players/male/tris.md2"); strcpy (weapon_filename, "players/male/weapon.md2"); strcpy (skin_filename, "players/male/grunt.pcx"); strcpy (ci->iconname, "/players/male/grunt_i.pcx"); ci->model = R_RegisterModel (model_filename); memset(ci->weaponmodel, 0, sizeof(ci->weaponmodel)); ci->weaponmodel[0] = R_RegisterModel (weapon_filename); ci->skin = R_RegisterSkin (skin_filename); ci->icon = Draw_FindPic (ci->iconname); } else { // isolate the model name Q_strncpyz (model_name, s, sizeof(model_name)); t = strchr(model_name, '/'); if (!t) t = strchr(model_name, '\\'); if (!t) { memcpy (model_name, "male\0grunt\0\0\0\0\0\0", 16); s = "male\\grunt\0"; } else { *t = 0; } // isolate the skin name Q_strncpyz(skin_name, s + strlen(model_name) + 1, sizeof(skin_name)); // model file Com_sprintf (model_filename, sizeof(model_filename), "players/%s/tris.md2", model_name); ci->model = R_RegisterModel (model_filename); if (!ci->model) { strcpy(model_name, "male"); strcpy(model_filename, "players/male/tris.md2"); ci->model = R_RegisterModel (model_filename); } // skin file Com_sprintf (skin_filename, sizeof(skin_filename), "players/%s/%s.pcx", model_name, skin_name); ci->skin = R_RegisterSkin (skin_filename); // if we don't have the skin and the model wasn't male, // see if the male has it (this is for CTF's skins) if (!ci->skin && Q_stricmp(model_name, "male")) { // change model to male strcpy(model_name, "male"); strcpy(model_filename, "players/male/tris.md2"); ci->model = R_RegisterModel (model_filename); // see if the skin exists for the male model Com_sprintf (skin_filename, sizeof(skin_filename), "players/%s/%s.pcx", model_name, skin_name); ci->skin = R_RegisterSkin (skin_filename); } // if we still don't have a skin, it means that the male model didn't have // it, so default to grunt if (!ci->skin) { // see if the skin exists for the male model Com_sprintf (skin_filename, sizeof(skin_filename), "players/%s/grunt.pcx", model_name); ci->skin = R_RegisterSkin (skin_filename); } // weapon file for (i = 0; i < num_cl_weaponmodels; i++) { Com_sprintf (weapon_filename, sizeof(weapon_filename), "players/%s/%s", model_name, cl_weaponmodels[i]); ci->weaponmodel[i] = R_RegisterModel(weapon_filename); if (!ci->weaponmodel[i] && strcmp(model_name, "cyborg") == 0) { // try male Com_sprintf (weapon_filename, sizeof(weapon_filename), "players/male/%s", cl_weaponmodels[i]); ci->weaponmodel[i] = R_RegisterModel(weapon_filename); } if (!cl_vwep->integer) break; // only one when vwep is off } // icon file Com_sprintf (ci->iconname, sizeof(ci->iconname), "/players/%s/%s_i.pcx", model_name, skin_name); ci->icon = Draw_FindPic (ci->iconname); } // must have loaded all data types to be valud if (!ci->skin || !ci->icon || !ci->model || !ci->weaponmodel[0]) { ci->skin = NULL; ci->icon = NULL; ci->model = NULL; ci->weaponmodel[0] = NULL; return; } }