mirror of
https://github.com/UberGames/RPG-X2.git
synced 2024-11-22 04:21:43 +00:00
2154 lines
64 KiB
C
2154 lines
64 KiB
C
|
// Copyright (C) 1999-2000 Id Software, Inc.
|
||
|
//
|
||
|
//=================================================
|
||
|
//
|
||
|
// TiM: Just a reference for my whacky jargon in here
|
||
|
// Character = the player model as a whole group (ie kulhane )
|
||
|
// Model = the .model file used to build the character ( ie admiral, cadet etc)
|
||
|
// Skin = the skinset field in the .model file, dictating which .skins to use (ie red/teal/gold... )
|
||
|
// ADDENDUM: Skin = the .skinset file linked to the .model file
|
||
|
//
|
||
|
//=================================================
|
||
|
#include "ui_local.h"
|
||
|
|
||
|
#define PIC_ARROW_UP "menu/common/arrow_up_16.tga"
|
||
|
#define PIC_ARROW_DOWN "menu/common/arrow_dn_16.tga"
|
||
|
|
||
|
#define LOW_MEMORY (5 * 1024 * 1024)
|
||
|
|
||
|
#define MAX_PLAYERNAMELENGTH 21
|
||
|
|
||
|
#define MAX_RACES 64
|
||
|
#define MAX_GENDERS 64
|
||
|
|
||
|
static void PlayerModel_BuildList( void );
|
||
|
static void PlayerModel_SetMenuItems( void );
|
||
|
static void PlayerModel_MenuInit(int menuFrom);
|
||
|
|
||
|
//yes... a lot
|
||
|
#define MAX_PLAYERCHARS 256
|
||
|
#define MAX_PLAYERMODELS 64
|
||
|
#define MAX_PLAYERSKINS 32
|
||
|
|
||
|
#define MAX_MENULISTITEMS 12
|
||
|
|
||
|
#define MIN_SCROLLHEIGHT 8
|
||
|
#define MAX_SCROLLRANGE 236
|
||
|
#define MAX_SCROLLTOP 108
|
||
|
|
||
|
#define ID_MENUCHAR0 0
|
||
|
#define ID_MENUCHAR1 1
|
||
|
#define ID_MENUCHAR2 2
|
||
|
#define ID_MENUCHAR3 3
|
||
|
#define ID_MENUCHAR4 4
|
||
|
#define ID_MENUCHAR5 5
|
||
|
#define ID_MENUCHAR6 6
|
||
|
#define ID_MENUCHAR7 7
|
||
|
#define ID_MENUCHAR8 8
|
||
|
#define ID_MENUCHAR9 9
|
||
|
#define ID_MENUCHAR10 10
|
||
|
#define ID_MENUCHAR11 11
|
||
|
|
||
|
#define ID_UPARROW 100
|
||
|
#define ID_DNARROW 101
|
||
|
#define ID_BACK 102
|
||
|
#define ID_MAINMENU 103
|
||
|
#define ID_INGAMEMENU 104
|
||
|
|
||
|
#define ID_APPLY 105
|
||
|
|
||
|
#define ID_MODELSET 106
|
||
|
#define ID_SKINSET 107
|
||
|
|
||
|
#define ID_RACEFILTER 108
|
||
|
#define ID_GENDERFILTER 109
|
||
|
|
||
|
#define ID_SCROLLBAR 110
|
||
|
|
||
|
#define ID_SETTINGS 20
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
int orgChar;
|
||
|
int orgModel;
|
||
|
int orgSkin;
|
||
|
} storedData_t;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
char charName[36];
|
||
|
int race;
|
||
|
int gender;
|
||
|
int index;
|
||
|
} charData_t;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
qboolean mouseDown;
|
||
|
qboolean doubleStep;
|
||
|
|
||
|
int yStart;
|
||
|
} scrollData_t;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
char filterName[32];
|
||
|
int filterIndex;
|
||
|
} filterData_t;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
menuframework_s menu;
|
||
|
int prevMenu;
|
||
|
menubitmap_s mainmenu;
|
||
|
menubitmap_s back;
|
||
|
menubitmap_s player;
|
||
|
|
||
|
menubitmap_s charMenu[MAX_MENULISTITEMS];
|
||
|
|
||
|
menubitmap_s upArrow;
|
||
|
menubitmap_s dnArrow;
|
||
|
|
||
|
menulist_s charModel;
|
||
|
menulist_s charSkin;
|
||
|
|
||
|
menulist_s raceFilter;
|
||
|
menulist_s genderFilter;
|
||
|
|
||
|
menubitmap_s apply;
|
||
|
|
||
|
menubitmap_s data;
|
||
|
menubitmap_s model;
|
||
|
|
||
|
menuaction_s scrollBar;
|
||
|
|
||
|
qhandle_t corner_ll_4_4;
|
||
|
qhandle_t corner_ll_4_18;
|
||
|
qhandle_t corner_lr_4_18;
|
||
|
qhandle_t corner_lr_18_4;
|
||
|
qhandle_t corner_ur_18_18;
|
||
|
|
||
|
qhandle_t playerIcon;
|
||
|
|
||
|
//menutext_s modelname;
|
||
|
//menutext_s skinname;
|
||
|
//menutext_s skinnameviewed;
|
||
|
menutext_s playername;
|
||
|
playerInfo_t playerinfo;
|
||
|
|
||
|
int numChars;
|
||
|
charData_t charNames[MAX_PLAYERCHARS]/*[128]*/;
|
||
|
char modelNames[MAX_PLAYERMODELS][32];
|
||
|
char skinNames[MAX_PLAYERMODELS][MAX_PLAYERSKINS][32];
|
||
|
//To save loading time, and the fact that loading data from txt files on the fly per spin cycle,
|
||
|
//can sometimes overload EF if the user gets button happy, We'll make it all data is loaded and consolidated on character choosing
|
||
|
|
||
|
//TiM - I think this is wasteful as all heck, but it can't be helped
|
||
|
//The model functions need the data stored as uniform char arrays,
|
||
|
//and the spin controls need them stored as char pointers. O_o
|
||
|
//But not only that, but since these are memory pointers, applying strUpr
|
||
|
//To them destroys the case in the arrays above.
|
||
|
//Hacky this may be, but there's no way around it without some totally Carmack-coding
|
||
|
//Raven had to do this too, so it's an inherent flaw in Q3 coding
|
||
|
char charNamesUpr[MAX_PLAYERCHARS][64];
|
||
|
char modelNamesUpr[MAX_PLAYERMODELS][64];
|
||
|
char skinNamesUpr[MAX_PLAYERMODELS][MAX_PLAYERSKINS][64];
|
||
|
|
||
|
char* modelList[MAX_PLAYERMODELS];
|
||
|
char* skinList[MAX_PLAYERSKINS];
|
||
|
|
||
|
char modelData[64];
|
||
|
char modelName[32];
|
||
|
|
||
|
//char raceNames[MAX_RACES][32];
|
||
|
filterData_t raceList[MAX_RACES];
|
||
|
char* raceNames[MAX_RACES];
|
||
|
int numRaces;
|
||
|
|
||
|
filterData_t genderList[MAX_GENDERS];
|
||
|
char* genderNames[MAX_GENDERS];
|
||
|
int numGenders;
|
||
|
|
||
|
int selectedChar;
|
||
|
int scrollOffset;
|
||
|
|
||
|
storedData_t storedData; //Original Skin Data
|
||
|
|
||
|
scrollData_t scrollData;
|
||
|
} playermodel_t;
|
||
|
|
||
|
static playermodel_t s_playermodel;
|
||
|
|
||
|
static int QDECL FilterList_Compare( const void *ptr1, const void *ptr2 );
|
||
|
static int QDECL CharMediaList_Compare( const void *ptr1, const void *ptr2 );
|
||
|
static void PlayerModel_DrawLoading( void );
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_CheckInArray
|
||
|
TiM: When building an array of races etc,
|
||
|
run it through this list to prevent multiple redundancy
|
||
|
Mental Note: Study Pointer Arithmetic more....
|
||
|
=================
|
||
|
*/
|
||
|
|
||
|
static int PlayerModel_CheckInFilter( char* string, filterData_t *filter, int width, int *num ) {
|
||
|
int i=0;
|
||
|
|
||
|
while( filter[i].filterName[0] && i < width ) {
|
||
|
if ( !Q_stricmp( filter[i].filterName, string ) ) {
|
||
|
//Com_Printf( S_COLOR_RED "String %s already in cell %i\n", array[i], i );
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
if ( !filter[i].filterName[0] && i < width )
|
||
|
{
|
||
|
Q_strncpyz( filter[i].filterName, string, 32 );
|
||
|
filter[i].filterIndex = i;
|
||
|
|
||
|
*num = *num + 1; //aah I see. You can't call *num++ since that increments the address, not the value XD
|
||
|
}
|
||
|
|
||
|
//Com_Printf( S_COLOR_RED "Added %s to cell %i", array[i], i );
|
||
|
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
//static int PlayerModel_CheckInArray( char* string, void *array, size_t length ) {
|
||
|
// int i=0;
|
||
|
// char *str=NULL;
|
||
|
//
|
||
|
// for (i = 0; i < length; i++ ) {
|
||
|
// str = ((char **)array)[i]; //funky, yet awesome use of the void type lol
|
||
|
//
|
||
|
// Com_Printf( S_COLOR_RED ": %s\n", str );
|
||
|
//
|
||
|
// if ( !str )
|
||
|
// break;
|
||
|
//
|
||
|
// if ( !Q_stricmp( str, string ) ) {
|
||
|
// return i;
|
||
|
// }
|
||
|
// }
|
||
|
//
|
||
|
// if ( i < length )
|
||
|
// {
|
||
|
// Q_strncpyz( ((char **)array)[i], string, length );
|
||
|
// }
|
||
|
//
|
||
|
// return i;
|
||
|
//}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_LoadAvailableModels
|
||
|
TiM: Loads a list of all the .model
|
||
|
files there are in a character's directory.
|
||
|
|
||
|
NB: In Spin Control menu types, the number
|
||
|
of elements is calced on init only. Each
|
||
|
time we refresh this, we'll need to update ourselves.
|
||
|
=================
|
||
|
*/
|
||
|
static int PlayerModel_LoadAvailableModels( void ) {
|
||
|
int i;
|
||
|
int j;
|
||
|
int numFiles;
|
||
|
char fileList[4096]; //Hopefully, this will never be exceeded ROFL
|
||
|
char* filePtr;
|
||
|
int fileLen;
|
||
|
int strLen;
|
||
|
char* temp;
|
||
|
char fileRoute[MAX_QPATH];
|
||
|
|
||
|
if ( s_playermodel.selectedChar == -1 )
|
||
|
return -1;
|
||
|
|
||
|
Com_sprintf( fileRoute, MAX_QPATH,
|
||
|
"models/players_rpgx/%s",
|
||
|
s_playermodel.charNames[s_playermodel.selectedChar].charName );
|
||
|
|
||
|
//Get our num files
|
||
|
memset( &fileList, 0, sizeof ( fileList ) );
|
||
|
numFiles = trap_FS_GetFileList( fileRoute, ".model", fileList, sizeof(fileList) );
|
||
|
|
||
|
if ( numFiles <=0 )
|
||
|
return -1;
|
||
|
|
||
|
//Convert to ptr for easier manip
|
||
|
filePtr = fileList;
|
||
|
|
||
|
memset( &s_playermodel.modelNames, 0, sizeof( s_playermodel.modelNames ) );
|
||
|
memset( &s_playermodel.modelNamesUpr, 0, sizeof( s_playermodel.modelNamesUpr ) );
|
||
|
memset( s_playermodel.modelList, 0, sizeof( s_playermodel.modelList ) );
|
||
|
|
||
|
//iterate thru all the null terminations in this thing
|
||
|
/**
|
||
|
* RPG-X | Phenix | 27/03/2007
|
||
|
* Made for loop in reverse to correctly order the models. (Task#39)
|
||
|
*/
|
||
|
j = 0;
|
||
|
for ( i = 0; j < MAX_PLAYERMODELS && i < numFiles; i++, filePtr += fileLen+1 ) {
|
||
|
fileLen = strlen( filePtr );
|
||
|
|
||
|
if ( !fileLen || !filePtr )
|
||
|
break;
|
||
|
|
||
|
//TiM - this shouldn't be possible
|
||
|
if ( strchr(filePtr,'/') || strchr(filePtr,'\\') )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
temp = filePtr;
|
||
|
|
||
|
//TiM: Strip extension
|
||
|
strLen = strlen( temp );
|
||
|
if ( strLen > 6 && !Q_stricmp( temp + strLen - 6, ".model" ) ) {
|
||
|
temp[strLen-6] = '\0';
|
||
|
}
|
||
|
|
||
|
Q_strncpyz( s_playermodel.modelNames[j], temp, sizeof ( s_playermodel.modelNames[j] ) );
|
||
|
j++;
|
||
|
}
|
||
|
|
||
|
//sort the models, then feed them to the rest of the variables
|
||
|
qsort( s_playermodel.modelNames, j, sizeof( s_playermodel.modelNames[0] ), CharMediaList_Compare );
|
||
|
|
||
|
for ( i = 0; i < j; i++ )
|
||
|
{
|
||
|
//TiM: A bit of a hacky ovveride here.
|
||
|
//Make it so 'main' is set by default
|
||
|
if ( !Q_stricmp( s_playermodel.modelNames[i], DEFAULT_MODEL ) ) {
|
||
|
s_playermodel.charModel.curvalue = i;
|
||
|
}
|
||
|
|
||
|
Q_strncpyz( s_playermodel.modelNamesUpr[i], s_playermodel.modelNames[i], sizeof( s_playermodel.modelNamesUpr[i] ) );
|
||
|
s_playermodel.modelList[i] = Q_strupr( s_playermodel.modelNamesUpr[i] );
|
||
|
}
|
||
|
|
||
|
return j;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
PlayerModel_LoadAvailableSkins
|
||
|
TiM: Access our selected .model file, get the skin name framework and
|
||
|
fill the skin array with all the skins we found.
|
||
|
|
||
|
Hoi... this could get complicated... O_o
|
||
|
================
|
||
|
*/
|
||
|
static void PlayerModel_LoadAvailableSkins( void ) {
|
||
|
int j=0;
|
||
|
int i=0;
|
||
|
int fileLen;
|
||
|
char fileBuffer[20000];
|
||
|
int numFiles;
|
||
|
char fileListBuffer[10000];
|
||
|
char* filePtr;
|
||
|
fileHandle_t f;
|
||
|
char filePath[MAX_QPATH];
|
||
|
char* token;
|
||
|
char skinSetFrame[MAX_QPATH];
|
||
|
int strLen;
|
||
|
char* star;
|
||
|
int numSkins=0;
|
||
|
int starFlags;
|
||
|
char skins[MAX_PLAYERSKINS][64];
|
||
|
|
||
|
if ( s_playermodel.selectedChar == -1 )
|
||
|
return;
|
||
|
|
||
|
/*memset( s_playermodel.skinNames, 0, sizeof( s_playermodel.skinNames ) );
|
||
|
memset( s_playermodel.skinNamesUpr, 0, sizeof( s_playermodel.skinNamesUpr ) );
|
||
|
*/
|
||
|
|
||
|
//TiM: Ugh, this is the only way to ensure completely flushing out the skins list on each model
|
||
|
for ( i = 0; i < MAX_PLAYERMODELS; i++ )
|
||
|
{
|
||
|
for( j = 0; j < MAX_PLAYERSKINS; j++ )
|
||
|
{
|
||
|
s_playermodel.skinNames[i][j][0] = '\0';
|
||
|
s_playermodel.skinNamesUpr[i][j][0] = '\0';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < MAX_PLAYERSKINS; i++ )
|
||
|
{
|
||
|
s_playermodel.skinList[i] = NULL;
|
||
|
skins[i][0] = '\0';
|
||
|
}
|
||
|
|
||
|
Com_sprintf( filePath, MAX_QPATH, "models/players_rpgx/%s", s_playermodel.charNames[s_playermodel.selectedChar].charName );
|
||
|
|
||
|
//first load the list of .skinset files we have
|
||
|
numFiles = trap_FS_GetFileList( filePath,
|
||
|
".skinset", fileListBuffer, sizeof(fileListBuffer) );
|
||
|
|
||
|
if ( numFiles <= 0 )
|
||
|
{
|
||
|
Com_Printf( S_COLOR_RED "ERROR: No Skinset files found!\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
filePtr = fileListBuffer;
|
||
|
|
||
|
j=0;
|
||
|
for ( i = 0; i < MAX_PLAYERSKINS && i < numFiles; i++, filePtr += strLen + 1 )
|
||
|
{
|
||
|
strLen = strlen( filePtr );
|
||
|
|
||
|
if ( !strLen )
|
||
|
break;
|
||
|
|
||
|
//TiM - this shouldn't be possible
|
||
|
if ( strchr(filePtr,'/') || strchr(filePtr,'\\') )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
token = filePtr;
|
||
|
|
||
|
if ( strLen > 8 && !Q_stricmp( token + (strLen - 8), ".skinset" ) )
|
||
|
{
|
||
|
token[strLen - 8] = '\0';
|
||
|
}
|
||
|
|
||
|
Q_strncpyz( skins[j], token, sizeof( skins[j] ) );
|
||
|
|
||
|
//Com_Printf( S_COLOR_RED "%s\n", skins[j] );
|
||
|
j++;
|
||
|
}
|
||
|
//Com_Printf( "Model Break\n", skins[j] );
|
||
|
|
||
|
//Com_Printf( "%s\n", s_playermodel.modelNames[2] );
|
||
|
j = 0;
|
||
|
while ( j < MAX_PLAYERMODELS )
|
||
|
{
|
||
|
if ( !s_playermodel.modelNames[j][0] )
|
||
|
break;
|
||
|
|
||
|
Com_sprintf( filePath, sizeof( filePath ),
|
||
|
"models/players_rpgx/%s/%s.model",
|
||
|
s_playermodel.charNames[s_playermodel.selectedChar].charName,
|
||
|
s_playermodel.modelNames[j] );
|
||
|
|
||
|
//load the .model data into our active buffer
|
||
|
fileLen = trap_FS_FOpenFile( filePath, &f, FS_READ);
|
||
|
|
||
|
if ( fileLen <= 0 ) {
|
||
|
Com_Printf( S_COLOR_RED "File not found: %s\n", filePath );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( fileLen > 20000 ) {
|
||
|
Com_Printf( S_COLOR_RED "File exceeded maximum size: %s\n", filePath );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
memset( &fileBuffer, 0, sizeof( fileBuffer ) );
|
||
|
trap_FS_Read( fileBuffer, sizeof( fileBuffer ), f );
|
||
|
|
||
|
trap_FS_FCloseFile( f );
|
||
|
|
||
|
if ( !fileBuffer[0] )
|
||
|
return;
|
||
|
|
||
|
filePtr = fileBuffer;
|
||
|
|
||
|
COM_BeginParseSession();
|
||
|
|
||
|
memset( skinSetFrame, 0, sizeof( skinSetFrame ) );
|
||
|
while ( 1 ) {
|
||
|
|
||
|
token = COM_Parse( &filePtr );
|
||
|
if ( !token || !filePtr )
|
||
|
break;
|
||
|
|
||
|
if ( !Q_stricmp( token, "skinSet" ) ) {
|
||
|
if ( COM_ParseString( &filePtr, &token ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
Q_strncpyz( skinSetFrame, token, sizeof( skinSetFrame ) );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//set a default one if nothing found
|
||
|
if ( !skinSetFrame[0] )
|
||
|
{
|
||
|
Com_sprintf( skinSetFrame, sizeof( skinSetFrame ), "%s_*", s_playermodel.modelNames[j]);
|
||
|
}
|
||
|
|
||
|
if ( !strchr( skinSetFrame, '*' ) )
|
||
|
{
|
||
|
Com_Printf( S_COLOR_RED "ERROR: No '*' in skinset define for character: %s/%s\n", s_playermodel.charNames[s_playermodel.selectedChar].charName, s_playermodel.modelNames[j] );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//okay... this is tricky.
|
||
|
//basically, we're starting off with a possible
|
||
|
//"main_*, "*_main", or "ma_*_in" set up, where we have to see
|
||
|
//if a file name like "red_main" is valid, and if it is, isolate the "red" from it
|
||
|
star = strstr( skinSetFrame, "*" );
|
||
|
|
||
|
////star is at the end
|
||
|
if ( (int)(star - skinSetFrame) + 1 == (int)strlen(skinSetFrame) )
|
||
|
{
|
||
|
Q_strncpyz( filePath, skinSetFrame, sizeof( filePath ) );
|
||
|
filePath[strlen(filePath)-1] = '\0';
|
||
|
|
||
|
starFlags = 1;
|
||
|
}
|
||
|
//star is at the front
|
||
|
else if ( (int)(star - skinSetFrame) == 0 )
|
||
|
{
|
||
|
star++; //QVMNOTE
|
||
|
Q_strncpyz( filePath, star, sizeof( filePath ) );
|
||
|
starFlags = 2;
|
||
|
}
|
||
|
else
|
||
|
starFlags = 0;
|
||
|
|
||
|
for ( i = 0; i < MAX_PLAYERSKINS; i++ )
|
||
|
{
|
||
|
if ( !skins[i] || !skins[i][0] )
|
||
|
break;
|
||
|
|
||
|
////star is at the end
|
||
|
if ( starFlags == 1 )
|
||
|
{
|
||
|
if ( strstr( skins[i], filePath ) != NULL )
|
||
|
{
|
||
|
Q_strncpyz( s_playermodel.skinNames[j][numSkins], skins[i] + strlen(filePath), sizeof( s_playermodel.skinNames[j][numSkins] ) );
|
||
|
//Q_strncpyz( s_playermodel.skinNamesUpr[j][numSkins], skins[i] + strlen(filePath), sizeof( s_playermodel.skinNamesUpr[j][numSkins] ) );
|
||
|
numSkins++;
|
||
|
}
|
||
|
}
|
||
|
//star is at the front
|
||
|
else if ( starFlags == 2 )
|
||
|
{
|
||
|
if ( (token = strstr( skins[i], filePath ) ) != NULL )
|
||
|
{
|
||
|
Q_strncpyz( s_playermodel.skinNames[j][numSkins], skins[i], (int)(strlen(skins[i]) - strlen(token))+1 );
|
||
|
//Q_strncpyz( s_playermodel.skinNamesUpr[j][numSkins], skins[i], (int)(strlen(skins[i]) - strlen(token))+1 );
|
||
|
numSkins++;
|
||
|
}
|
||
|
}
|
||
|
//else
|
||
|
//TiM | Come back to this later...
|
||
|
//For now, document it as the star must be at the front or back
|
||
|
}
|
||
|
|
||
|
qsort( s_playermodel.skinNames[j], numSkins, sizeof( s_playermodel.skinNames[j][0] ), CharMediaList_Compare );
|
||
|
|
||
|
for ( i = 0; i < numSkins; i++ )
|
||
|
{
|
||
|
Q_strncpyz( s_playermodel.skinNamesUpr[j][i], s_playermodel.skinNames[j][i], sizeof( s_playermodel.skinNamesUpr[j][i] ) );
|
||
|
//Com_Printf( S_COLOR_BLUE "%s\n", s_playermodel.skinNamesUpr[j][i] );
|
||
|
}
|
||
|
|
||
|
numSkins=0;
|
||
|
j++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int QDECL CharMediaList_Compare( const void *ptr1, const void *ptr2 )
|
||
|
{
|
||
|
const char *str1, *str2;
|
||
|
char chr1, chr2;
|
||
|
|
||
|
str1 = (const char *)ptr1;
|
||
|
str2 = (const char *)ptr2;
|
||
|
|
||
|
//Com_Printf( "STR1: %s STR2: %s\n", str1, str2 );
|
||
|
|
||
|
//default data always comes first
|
||
|
//Actually... we came this far, let's just make it all alphabetic
|
||
|
/*if ( !Q_stricmp( str1, DEFAULT_SKIN ) || !Q_stricmp( str1, DEFAULT_MODEL ) )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
else if ( !Q_stricmp( str2, DEFAULT_SKIN ) || !Q_stricmp( str2, DEFAULT_MODEL ) )
|
||
|
{
|
||
|
return 1;
|
||
|
}*/
|
||
|
|
||
|
chr1 = *str1;
|
||
|
chr2 = *str2;
|
||
|
|
||
|
//double check they're lower-case. case matters
|
||
|
if ( chr1 >= 'A' && chr1 <= 'Z' ) chr1 += 32;
|
||
|
if ( chr2 >= 'A' && chr2 <= 'Z' ) chr2 += 32;
|
||
|
|
||
|
//cascade the alphabetical list
|
||
|
while( chr1 == chr2 && chr1 && chr2)
|
||
|
{
|
||
|
chr1 = *(str1++);
|
||
|
chr2 = *(str2++);
|
||
|
}
|
||
|
|
||
|
//based off of their ASCII order.
|
||
|
return ((int)chr1 - (int)chr2);
|
||
|
}
|
||
|
|
||
|
static int QDECL FilterList_Compare( const void *ptr1, const void *ptr2 )
|
||
|
{
|
||
|
const char *str1, *str2;
|
||
|
char chr1, chr2;
|
||
|
|
||
|
str1 = ((filterData_t *)ptr1)->filterName;
|
||
|
str2 = ((filterData_t *)ptr2)->filterName;
|
||
|
|
||
|
//hacky override. Make sure 'All' comes first.
|
||
|
if ( !Q_stricmp( str1, "ALL" ) )
|
||
|
return -1;
|
||
|
|
||
|
chr1 = *str1;
|
||
|
chr2 = *str2;
|
||
|
|
||
|
//double check they're lower-case. case matters
|
||
|
if ( chr1 >= 'A' && chr1 <= 'Z' ) chr1 += 32;
|
||
|
if ( chr2 >= 'A' && chr2 <= 'Z' ) chr2 += 32;
|
||
|
|
||
|
//cascade the alphabetical list
|
||
|
while( chr1 == chr2 && chr1 && chr2)
|
||
|
{
|
||
|
if ( *(str1+1) == '\0' || *(str2+1) == '\0' )
|
||
|
break;
|
||
|
|
||
|
chr1 = *(str1++);
|
||
|
chr2 = *(str2++);
|
||
|
}
|
||
|
|
||
|
//based off of their ASCII order.
|
||
|
return ((int)chr1 - (int)chr2);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_PopulateSkinsList
|
||
|
=================
|
||
|
*/
|
||
|
static int PlayerModel_PopulateSkinsList ( void ) {
|
||
|
int i;
|
||
|
int j;
|
||
|
|
||
|
if ( !s_playermodel.skinNames[s_playermodel.charModel.curvalue][0][0] ) {
|
||
|
Com_Printf( S_COLOR_RED "ERROR: No valid skins found.\n" );
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
//just to ensure complete erasure of previous entries
|
||
|
for( i = 0; i < MAX_PLAYERSKINS; i++ )
|
||
|
s_playermodel.skinList[i] = NULL;
|
||
|
|
||
|
/**
|
||
|
* RPG-X | Phenix | 27/03/2007
|
||
|
* For loop reversed to output list in alphabetical order. (Task #39)
|
||
|
* RPG-X | TiM | 30/4/2007
|
||
|
* Reverted as it was causing an error with skin names not matching
|
||
|
*/
|
||
|
j = 0;
|
||
|
//for ( i = (MAX_PLAYERSKINS - 1); i >= 0; i-- )
|
||
|
for ( i = 0; i < MAX_PLAYERSKINS; i++ )
|
||
|
{
|
||
|
if ( s_playermodel.skinNames[s_playermodel.charModel.curvalue][i][0] ) //!
|
||
|
{
|
||
|
if ( !Q_stricmp( s_playermodel.skinNames[s_playermodel.charModel.curvalue][i], DEFAULT_SKIN ) )
|
||
|
s_playermodel.charSkin.curvalue = j; //j;
|
||
|
|
||
|
s_playermodel.skinList[j] = s_playermodel.skinNamesUpr[s_playermodel.charModel.curvalue][i];
|
||
|
|
||
|
Q_strupr( s_playermodel.skinList[j] );
|
||
|
|
||
|
j++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return j;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_OffsetCharList
|
||
|
|
||
|
TiM: Called whenever we scroll the model list.
|
||
|
So it'll cycle the value of each one up and down.
|
||
|
The parameter is a pointer so the updated
|
||
|
value will be passed through the scope to the calling
|
||
|
code area. :)
|
||
|
==================
|
||
|
*/
|
||
|
|
||
|
static void PlayerModel_OffsetCharList( int* offset ) {
|
||
|
char* buffer; //intermediate value so performing strupr won't pwn our case sensitive data
|
||
|
int i;
|
||
|
|
||
|
if ( *offset < 0 ) {
|
||
|
*offset = 0;
|
||
|
}
|
||
|
|
||
|
if ( ( s_playermodel.numChars > MAX_MENULISTITEMS) && (*offset > (s_playermodel.numChars - MAX_MENULISTITEMS ) ) ) {
|
||
|
*offset = (s_playermodel.numChars - MAX_MENULISTITEMS );
|
||
|
}
|
||
|
|
||
|
for ( i = 0; i < MAX_MENULISTITEMS; i++ ) {
|
||
|
buffer = s_playermodel.charNamesUpr[i + *offset];
|
||
|
//Q_strncpyz( buffer, s_playermodel.charNames[i + *offset], sizeof ( buffer ) );
|
||
|
|
||
|
//Com_Printf( "Buffer - %s, %s\n", buffer, s_playermodel.charNames[1] );
|
||
|
|
||
|
if ( !buffer[0] ) {
|
||
|
if ( s_playermodel.charMenu[i].generic.flags & ( QMF_INACTIVE | QMF_HIDDEN ) ) {
|
||
|
break;
|
||
|
}
|
||
|
else {
|
||
|
s_playermodel.charMenu[i].generic.flags = ( QMF_INACTIVE | QMF_HIDDEN );
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
s_playermodel.charMenu[i].generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
s_playermodel.charMenu[i].textPtr = buffer;
|
||
|
|
||
|
Q_strupr( s_playermodel.charMenu[i].textPtr );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_RebuildCharMenu
|
||
|
|
||
|
TiM: Called when we scroll the races/gender button.
|
||
|
Rebuild the main list based on the new parameters
|
||
|
=================
|
||
|
*/
|
||
|
static void PlayerModel_RebuildCharMenu( void ) {
|
||
|
int i;
|
||
|
qboolean raceValid=qfalse;
|
||
|
qboolean genderValid=qfalse;
|
||
|
|
||
|
s_playermodel.numChars = 0;
|
||
|
memset( &s_playermodel.charNamesUpr, 0, sizeof( s_playermodel.charNamesUpr ) );
|
||
|
|
||
|
i = 0;
|
||
|
while ( i < MAX_PLAYERCHARS ) {
|
||
|
if ( !s_playermodel.charNames[i].charName[0] )
|
||
|
break;
|
||
|
|
||
|
raceValid = s_playermodel.raceFilter.curvalue == 0 ||
|
||
|
( s_playermodel.raceList[s_playermodel.raceFilter.curvalue].filterIndex == s_playermodel.charNames[i].race );
|
||
|
|
||
|
genderValid = s_playermodel.genderFilter.curvalue == 0 ||
|
||
|
( s_playermodel.genderList[s_playermodel.genderFilter.curvalue].filterIndex == s_playermodel.charNames[i].gender );
|
||
|
|
||
|
//Com_Printf( "Char %s valid: %i %i\n", s_playermodel.charNames[i].charName, raceValid, genderValid );
|
||
|
|
||
|
if ( raceValid && genderValid )
|
||
|
{
|
||
|
Q_strncpyz( s_playermodel.charNamesUpr[s_playermodel.numChars], s_playermodel.charNames[i].charName, sizeof( s_playermodel.charNamesUpr[s_playermodel.numChars] ) );
|
||
|
|
||
|
if ( s_playermodel.raceFilter.curvalue == 0 && s_playermodel.genderFilter.curvalue == 0 )
|
||
|
s_playermodel.charNames[s_playermodel.numChars].index = -1;
|
||
|
else
|
||
|
s_playermodel.charNames[s_playermodel.numChars].index = i;
|
||
|
|
||
|
s_playermodel.numChars++;
|
||
|
|
||
|
}
|
||
|
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
if ( s_playermodel.numChars < MAX_MENULISTITEMS ) {
|
||
|
s_playermodel.upArrow.generic.flags = ( QMF_INACTIVE | QMF_GRAYED );
|
||
|
s_playermodel.dnArrow.generic.flags = ( QMF_INACTIVE | QMF_GRAYED );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s_playermodel.upArrow.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
s_playermodel.dnArrow.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
}
|
||
|
|
||
|
s_playermodel.scrollOffset = 0;
|
||
|
PlayerModel_OffsetCharList( &s_playermodel.scrollOffset );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_SpinPlayer
|
||
|
=================
|
||
|
*/
|
||
|
static void PlayerModel_SpinPlayer( void* ptr, int event)
|
||
|
{
|
||
|
if ( event == QM_ACTIVATED )
|
||
|
{
|
||
|
uis.spinView = qtrue;
|
||
|
uis.cursorpx = uis.cursorx;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_UpdateModel
|
||
|
=================
|
||
|
*/
|
||
|
static void PlayerModel_UpdateModel( void )
|
||
|
{
|
||
|
vec3_t viewangles;
|
||
|
vec3_t moveangles;
|
||
|
|
||
|
memset( &s_playermodel.playerinfo, 0, sizeof(playerInfo_t) );
|
||
|
|
||
|
viewangles[YAW] = uis.lastYaw;
|
||
|
viewangles[PITCH] = 0;
|
||
|
viewangles[ROLL] = 0;
|
||
|
VectorClear( moveangles );
|
||
|
|
||
|
UI_PlayerInfo_SetModel( &s_playermodel.playerinfo, s_playermodel.modelData );
|
||
|
UI_PlayerInfo_SetInfo( &s_playermodel.playerinfo, BOTH_WALK1, BOTH_WALK1, viewangles, moveangles, WP_NONE, trap_Cvar_VariableValue( "height" ), trap_Cvar_VariableValue( "weight" ), qfalse );
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_SaveChanges
|
||
|
=================
|
||
|
*/
|
||
|
static void PlayerModel_SaveChanges( void )
|
||
|
{
|
||
|
trap_Cvar_Set( "model", va("%s/%s/%s",
|
||
|
s_playermodel.charNames[s_playermodel.selectedChar].charName,
|
||
|
s_playermodel.modelNames[s_playermodel.charModel.curvalue],
|
||
|
s_playermodel.skinNames[s_playermodel.charModel.curvalue][s_playermodel.charSkin.curvalue] ) );
|
||
|
|
||
|
//Set backup data
|
||
|
s_playermodel.storedData.orgChar = s_playermodel.selectedChar;
|
||
|
s_playermodel.storedData.orgModel = s_playermodel.charModel.curvalue;
|
||
|
s_playermodel.storedData.orgSkin = s_playermodel.charSkin.curvalue;
|
||
|
|
||
|
Q_strncpyz( s_playermodel.modelData, UI_Cvar_VariableString( "model" ), sizeof ( s_playermodel.modelData ) );
|
||
|
PlayerModel_UpdateModel( );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
PlayerModel_CheckForChange
|
||
|
==================
|
||
|
*/
|
||
|
static void PlayerModel_CheckForChange( void ) {
|
||
|
qboolean enableSaveButton=qfalse;
|
||
|
|
||
|
if ( s_playermodel.storedData.orgChar != s_playermodel.selectedChar )
|
||
|
enableSaveButton = qtrue;
|
||
|
|
||
|
if ( s_playermodel.storedData.orgModel != s_playermodel.charModel.curvalue )
|
||
|
enableSaveButton = qtrue;
|
||
|
|
||
|
if ( s_playermodel.storedData.orgSkin != s_playermodel.charSkin.curvalue )
|
||
|
enableSaveButton = qtrue;
|
||
|
|
||
|
if ( s_playermodel.charSkin.numitems == 0 )
|
||
|
enableSaveButton = qfalse;
|
||
|
|
||
|
if ( s_playermodel.charModel.numitems == 0 )
|
||
|
enableSaveButton = qfalse;
|
||
|
|
||
|
if ( enableSaveButton ) {
|
||
|
s_playermodel.apply.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
}
|
||
|
else {
|
||
|
s_playermodel.apply.generic.flags = QMF_INACTIVE | QMF_GRAYED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_SetupScrollBar
|
||
|
=================
|
||
|
*/
|
||
|
static void PlayerModel_SetupScrollBar( menuaction_s *bar )
|
||
|
{
|
||
|
int height;
|
||
|
|
||
|
//first make sure it's worth enabling this at all
|
||
|
if ( s_playermodel.numChars <= MAX_MENULISTITEMS )
|
||
|
{
|
||
|
bar->generic.flags = QMF_INACTIVE | QMF_HIDDEN;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//show the bar
|
||
|
bar->generic.flags &= ~(QMF_INACTIVE | QMF_HIDDEN);
|
||
|
|
||
|
//calculate the necessary height of the bar
|
||
|
//by default, assume 1 pixel per offset
|
||
|
height = ( MAX_SCROLLRANGE) - ( s_playermodel.numChars - MAX_MENULISTITEMS );
|
||
|
|
||
|
//ensure box doesn't get too small
|
||
|
if ( height < MIN_SCROLLHEIGHT )
|
||
|
{
|
||
|
//double the step in that case
|
||
|
//a bit hacky, but no need for 3 since the limit isn't that high
|
||
|
height = ( MAX_SCROLLRANGE ) - ( s_playermodel.numChars * 0.5 - MAX_MENULISTITEMS );
|
||
|
s_playermodel.scrollData.doubleStep = qtrue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s_playermodel.scrollData.doubleStep = qfalse;
|
||
|
}
|
||
|
|
||
|
//reset to top
|
||
|
bar->generic.y = bar->generic.top = MAX_SCROLLTOP;
|
||
|
|
||
|
bar->height = height;
|
||
|
bar->generic.bottom = bar->generic.y + height;
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_UpdateScrollBar
|
||
|
=================
|
||
|
*/
|
||
|
static void PlayerModel_UpdateScrollBar( menuaction_s *bar )
|
||
|
{
|
||
|
bar->generic.y = MAX_SCROLLTOP + s_playermodel.scrollOffset*(s_playermodel.scrollData.doubleStep ? 0.5 : 1);
|
||
|
bar->generic.top = bar->generic.y;
|
||
|
bar->generic.bottom = bar->generic.top + bar->height;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_MenuEvent
|
||
|
=================
|
||
|
*/
|
||
|
static void PlayerModel_MenuEvent( void* ptr, int event )
|
||
|
{
|
||
|
|
||
|
if (event != QM_ACTIVATED)
|
||
|
return;
|
||
|
|
||
|
switch (((menucommon_s*)ptr)->id)
|
||
|
{
|
||
|
case ID_BACK:
|
||
|
//PlayerModel_SaveChanges();
|
||
|
UI_PopMenu();
|
||
|
break;
|
||
|
|
||
|
case ID_MAINMENU:
|
||
|
//PlayerModel_SaveChanges();
|
||
|
UI_MainMenu();
|
||
|
break;
|
||
|
|
||
|
case ID_INGAMEMENU:
|
||
|
//PlayerModel_SaveChanges();
|
||
|
UI_InGameMenu();
|
||
|
break;
|
||
|
|
||
|
case ID_SETTINGS:
|
||
|
UI_PopMenu();
|
||
|
//PlayerModel_SaveChanges();
|
||
|
UI_PlayerSettingsMenu(s_playermodel.prevMenu);
|
||
|
break;
|
||
|
|
||
|
case ID_DNARROW:
|
||
|
s_playermodel.scrollOffset++;
|
||
|
PlayerModel_OffsetCharList( &s_playermodel.scrollOffset );
|
||
|
|
||
|
if ( !(s_playermodel.scrollBar.generic.flags & QMF_INACTIVE ) )
|
||
|
PlayerModel_UpdateScrollBar( &s_playermodel.scrollBar );
|
||
|
break;
|
||
|
|
||
|
case ID_UPARROW:
|
||
|
s_playermodel.scrollOffset--;
|
||
|
PlayerModel_OffsetCharList( &s_playermodel.scrollOffset );
|
||
|
|
||
|
if ( !(s_playermodel.scrollBar.generic.flags & QMF_INACTIVE ) )
|
||
|
PlayerModel_UpdateScrollBar( &s_playermodel.scrollBar );
|
||
|
break;
|
||
|
|
||
|
case ID_MODELSET:
|
||
|
s_playermodel.charSkin.numitems = PlayerModel_PopulateSkinsList();
|
||
|
|
||
|
if ( s_playermodel.charSkin.numitems != -1 )
|
||
|
{
|
||
|
s_playermodel.charSkin.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s_playermodel.skinList[0] = "NONE";
|
||
|
s_playermodel.charSkin.generic.flags = QMF_INACTIVE | QMF_GRAYED;
|
||
|
s_playermodel.charSkin.numitems = 0;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ID_APPLY:
|
||
|
PlayerModel_SaveChanges();
|
||
|
break;
|
||
|
|
||
|
case ID_GENDERFILTER:
|
||
|
PlayerModel_RebuildCharMenu();
|
||
|
PlayerModel_SetupScrollBar( &s_playermodel.scrollBar );
|
||
|
break;
|
||
|
|
||
|
case ID_RACEFILTER:
|
||
|
PlayerModel_RebuildCharMenu();
|
||
|
PlayerModel_SetupScrollBar( &s_playermodel.scrollBar );
|
||
|
break;
|
||
|
|
||
|
case ID_MENUCHAR0:
|
||
|
case ID_MENUCHAR1:
|
||
|
case ID_MENUCHAR2:
|
||
|
case ID_MENUCHAR3:
|
||
|
case ID_MENUCHAR4:
|
||
|
case ID_MENUCHAR5:
|
||
|
case ID_MENUCHAR6:
|
||
|
case ID_MENUCHAR7:
|
||
|
case ID_MENUCHAR8:
|
||
|
case ID_MENUCHAR9:
|
||
|
case ID_MENUCHAR10:
|
||
|
case ID_MENUCHAR11:
|
||
|
{
|
||
|
int temp;
|
||
|
int oldChar = s_playermodel.selectedChar;
|
||
|
|
||
|
s_playermodel.selectedChar = ( ((menucommon_s*)ptr)->id - ID_MENUCHAR0 ) + s_playermodel.scrollOffset;
|
||
|
temp = s_playermodel.selectedChar;
|
||
|
|
||
|
if ( s_playermodel.charNames[ s_playermodel.selectedChar ].index >= 0 ) {
|
||
|
s_playermodel.selectedChar = s_playermodel.charNames[ s_playermodel.selectedChar ].index;
|
||
|
}
|
||
|
|
||
|
//Com_Printf( S_COLOR_RED "%i %i\n", s_playermodel.selectedChar, s_playermodel.charNames[ s_playermodel.selectedChar ].index );
|
||
|
|
||
|
//safety net. Without this, if a player held down 'enter', the game would overflow trying to load the same file over and over really fast. bad, really bad lol
|
||
|
if ( oldChar == s_playermodel.selectedChar && s_playermodel.selectedChar != -1 )
|
||
|
break;
|
||
|
|
||
|
//Reset the spin controls to 0.
|
||
|
//Without this, if we load a char with less models+skins than our last one, the game would crash
|
||
|
//since it'd be trying to parse NULL string data
|
||
|
s_playermodel.charModel.curvalue = 0;
|
||
|
s_playermodel.charSkin.curvalue = 0;
|
||
|
|
||
|
s_playermodel.playerIcon = trap_R_RegisterShaderNoMip( va( "models/players_rpgx/%s/model_icon.jpg", s_playermodel.charNames[s_playermodel.selectedChar].charName ) );
|
||
|
|
||
|
Q_strncpyz( s_playermodel.modelName, s_playermodel.charNamesUpr[ temp ], sizeof( s_playermodel.modelName ) );
|
||
|
|
||
|
s_playermodel.charModel.numitems = PlayerModel_LoadAvailableModels();
|
||
|
if ( s_playermodel.charModel.numitems != -1 )
|
||
|
{
|
||
|
s_playermodel.charModel.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
|
||
|
PlayerModel_LoadAvailableSkins();
|
||
|
s_playermodel.charSkin.numitems = PlayerModel_PopulateSkinsList();
|
||
|
|
||
|
if ( s_playermodel.charSkin.numitems != -1 )
|
||
|
{
|
||
|
s_playermodel.charSkin.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s_playermodel.skinList[0] = "NONE";
|
||
|
s_playermodel.charSkin.generic.flags = QMF_INACTIVE | QMF_GRAYED;
|
||
|
s_playermodel.charSkin.numitems = 0;
|
||
|
}
|
||
|
}
|
||
|
//reset the spin control
|
||
|
else
|
||
|
{
|
||
|
s_playermodel.modelList[0] = "NONE";
|
||
|
s_playermodel.charModel.generic.flags = QMF_INACTIVE | QMF_GRAYED;
|
||
|
s_playermodel.charModel.numitems = 0;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
PlayerModel_CheckForChange();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_MenuKey
|
||
|
=================
|
||
|
*/
|
||
|
static sfxHandle_t PlayerModel_MenuKey( int key )
|
||
|
{
|
||
|
switch( key )
|
||
|
{
|
||
|
case K_MOUSE1:
|
||
|
if ( Menu_ItemAtCursor( &s_playermodel.menu ) == &s_playermodel.scrollBar )
|
||
|
{
|
||
|
uis.activemenu->noNewSelecting = qtrue;
|
||
|
s_playermodel.scrollData.mouseDown = qtrue;
|
||
|
s_playermodel.scrollData.yStart = uis.cursory;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ( Menu_DefaultKey( &s_playermodel.menu, key ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_DrawPlayer
|
||
|
=================
|
||
|
*/
|
||
|
static void PlayerModel_DrawPlayer( void *self )
|
||
|
{
|
||
|
menubitmap_s* b;
|
||
|
vec3_t origin = {-40, 2.5, -4 }; //-3.8
|
||
|
|
||
|
b = (menubitmap_s*) self;
|
||
|
|
||
|
if( trap_MemoryRemaining() <= LOW_MEMORY ) {
|
||
|
UI_DrawProportionalString( b->generic.x, b->generic.y + b->height / 2, "LOW MEMORY", UI_LEFT, color_red );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
UI_DrawPlayer( (float)b->generic.x, (float)b->generic.y, (float)b->width, (float)b->height, origin, &s_playermodel.playerinfo, (int)(uis.realtime/1.5) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_BuildList
|
||
|
|
||
|
Heavily modifed by TiM
|
||
|
All we'll take into account now
|
||
|
is a valid directory name,
|
||
|
and that it contains a .model file
|
||
|
We'll work the rest out later
|
||
|
=================
|
||
|
*/
|
||
|
|
||
|
static int QDECL PlayerListOrder_Compare( const void *ptr1, const void *ptr2 );
|
||
|
|
||
|
static void PlayerModel_BuildList( void )
|
||
|
{
|
||
|
int numdirs;
|
||
|
int numfiles;
|
||
|
char dirlist[8192];
|
||
|
char filelist[128]; //2048
|
||
|
char* dirptr;
|
||
|
int i, j;
|
||
|
int dirlen;
|
||
|
charData_t *tempBuff;
|
||
|
//int offset;
|
||
|
int temp;
|
||
|
|
||
|
s_playermodel.selectedChar = -1;
|
||
|
s_playermodel.numChars = 0;
|
||
|
|
||
|
// iterate directory of all player models
|
||
|
numdirs = trap_FS_GetFileList("models/players_rpgx", "/", dirlist, sizeof(dirlist) );
|
||
|
dirptr = dirlist;
|
||
|
|
||
|
///Com_Printf("%i folders found\n", numdirs );
|
||
|
|
||
|
for (i=0; i<numdirs && s_playermodel.numChars < MAX_PLAYERCHARS; i++,dirptr+=dirlen+1)
|
||
|
{
|
||
|
dirlen = strlen(dirptr);
|
||
|
|
||
|
if ( !dirptr ) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (dirlen && dirptr[dirlen-1]=='/')
|
||
|
dirptr[dirlen-1]='\0';
|
||
|
|
||
|
//I'm guessing this is for non-PK3'd files
|
||
|
if (!strcmp(dirptr,".") || !strcmp(dirptr,".."))
|
||
|
continue;
|
||
|
|
||
|
// TiM : Check for .model files. That's all we need
|
||
|
numfiles = 0; //Just to be sure
|
||
|
numfiles = trap_FS_GetFileList( va("models/players_rpgx/%s",dirptr), ".model", filelist, 128 );
|
||
|
|
||
|
temp = qfalse;
|
||
|
if ( numfiles > 0 && dirptr[0] )
|
||
|
{
|
||
|
//TiM - Don't do duplicate chars (Since it caches PK3 and non PK3 ones as separate instances )
|
||
|
for ( j = 0; j < s_playermodel.numChars; j++ )
|
||
|
{
|
||
|
tempBuff = &s_playermodel.charNames[j];
|
||
|
|
||
|
if ( !Q_stricmp( tempBuff->charName, dirptr ) ){
|
||
|
temp = qtrue;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( temp )
|
||
|
continue;
|
||
|
|
||
|
tempBuff = &s_playermodel.charNames[s_playermodel.numChars];
|
||
|
Q_strncpyz( tempBuff->charName, dirptr, sizeof( tempBuff[s_playermodel.numChars].charName ) );
|
||
|
tempBuff->index = -1;
|
||
|
|
||
|
//TiM - Load data on the races if at all possible
|
||
|
if ( trap_FS_GetFileList( va("models/players_rpgx/%s",dirptr), "race.cfg", filelist, 128 ) > 0 )
|
||
|
{
|
||
|
fileHandle_t f;
|
||
|
char buffer[1024];
|
||
|
char* filePtr;
|
||
|
int fileLength;
|
||
|
char* token;
|
||
|
char filePath[MAX_QPATH];
|
||
|
|
||
|
Com_sprintf( filePath, sizeof(filePath), "models/players_rpgx/%s/race.cfg", dirptr );
|
||
|
fileLength = trap_FS_FOpenFile( filePath, &f, FS_READ );
|
||
|
|
||
|
//Com_Printf( S_COLOR_RED "File %s loaded.\n", dirptr );
|
||
|
|
||
|
if ( !fileLength ) {
|
||
|
continue;
|
||
|
}
|
||
|
//Com_Printf( S_COLOR_RED "We have length.\n" );
|
||
|
|
||
|
if ( fileLength > sizeof( buffer ) - 1 ) {
|
||
|
continue;
|
||
|
}
|
||
|
//Com_Printf( S_COLOR_RED "Good size.\n" );
|
||
|
|
||
|
memset( &buffer, 0, sizeof( buffer ) );
|
||
|
trap_FS_Read( buffer, fileLength, f );
|
||
|
//Com_Printf( S_COLOR_RED "Loaded data...\n" );
|
||
|
|
||
|
trap_FS_FCloseFile( f );
|
||
|
|
||
|
if ( !buffer[0] ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//Format is 'Race Gender'. Race must precede Gender
|
||
|
filePtr = buffer;
|
||
|
|
||
|
COM_BeginParseSession();
|
||
|
|
||
|
token = COM_Parse( &filePtr );
|
||
|
if ( !token )
|
||
|
continue;
|
||
|
|
||
|
//Com_Printf( S_COLOR_RED "Race %s Loaded\n", token );
|
||
|
|
||
|
//tempBuff->race = PlayerModel_CheckInArray( token, s_playermodel.raceNames, MAX_RACES );
|
||
|
|
||
|
//big dirty hack
|
||
|
/*for( k=0; k < MAX_RACES; k++ )
|
||
|
{
|
||
|
if ( !s_playermodel.raceNames[k].raceName[0] )
|
||
|
{
|
||
|
Q_strncpyz( s_playermodel.raceNames[k].raceName, token, sizeof( s_playermodel.raceNames[k].raceName ) );
|
||
|
tempBuff->race = s_playermodel.raceNames[k].raceIndex = k;
|
||
|
s_playermodel.numRaces++;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ( !Q_stricmp( s_playermodel.raceNames[k].raceName, token ) )
|
||
|
{
|
||
|
tempBuff->race = s_playermodel.raceNames[k].raceIndex = k;
|
||
|
break;
|
||
|
}
|
||
|
}*/
|
||
|
|
||
|
tempBuff->race = PlayerModel_CheckInFilter( token, s_playermodel.raceList, MAX_RACES, &s_playermodel.numRaces );
|
||
|
//Com_Printf( S_COLOR_RED "Number of races now: %i\n", s_playermodel.numRaces );
|
||
|
|
||
|
token = COM_Parse( &filePtr );
|
||
|
if ( !token )
|
||
|
continue;
|
||
|
//Com_Printf( S_COLOR_RED "Gender %s loaded\n", token );
|
||
|
|
||
|
//tempBuff->gender = PlayerModel_CheckInArray( token, s_playermodel.genderNames, MAX_GENDERS );
|
||
|
tempBuff->gender = PlayerModel_CheckInFilter( token, s_playermodel.genderList, MAX_GENDERS, &s_playermodel.numGenders );
|
||
|
|
||
|
//Com_Printf( S_COLOR_RED "%i\n", tempBuff[i].gender );
|
||
|
}
|
||
|
|
||
|
s_playermodel.numChars++;
|
||
|
tempBuff = &s_playermodel.charNames[ s_playermodel.numChars ];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//TiM - Flip the array so it's the right order
|
||
|
/*
|
||
|
* RPG-X | Phenix | 27/03/2007
|
||
|
* Removed code for Task#39 (List was fliped to be Z-A!!!!)*/
|
||
|
//for ( i = 0; i < s_playermodel.numChars; i++ ) {
|
||
|
// offset = ( ( s_playermodel.numChars - i ) - 1);
|
||
|
|
||
|
// Q_strncpyz( s_playermodel.charNames[i].charName,
|
||
|
// tempBuff[offset].charName,
|
||
|
// sizeof( s_playermodel.charNames[i].charName ) );
|
||
|
|
||
|
// s_playermodel.charNames[i].race = tempBuff[offset].race;
|
||
|
// s_playermodel.charNames[i].gender = tempBuff[offset].gender;
|
||
|
// s_playermodel.charNames[i].index = tempBuff[offset].index;
|
||
|
|
||
|
// Q_strncpyz( s_playermodel.charNamesUpr[i], s_playermodel.charNames[i].charName, sizeof( s_playermodel.charNamesUpr[i] ) );
|
||
|
//}
|
||
|
|
||
|
//RPG-X | TiM | 30-4-2007
|
||
|
//This loop obviously isn't working well enough.
|
||
|
//Bringing out the big guns. Using the Windows/Q3
|
||
|
//Binary data sorting function, qsort.
|
||
|
|
||
|
//sorting function located below
|
||
|
qsort( s_playermodel.charNames, s_playermodel.numChars, sizeof( charData_t ), PlayerListOrder_Compare );
|
||
|
|
||
|
//copy to the upper case list for rendering to the menu
|
||
|
for ( i = 0; i < s_playermodel.numChars; i++ )
|
||
|
Q_strncpyz( s_playermodel.charNamesUpr[i], s_playermodel.charNames[i].charName, sizeof( s_playermodel.charNamesUpr[i] ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerListOrder_Compare
|
||
|
|
||
|
TiM - 30-4-2007
|
||
|
Called in the above
|
||
|
qsort function.
|
||
|
Re-orders the player
|
||
|
list based on alphabetical
|
||
|
name.
|
||
|
=================
|
||
|
*/
|
||
|
static int QDECL PlayerListOrder_Compare( const void *ptr1, const void *ptr2 )
|
||
|
{
|
||
|
char *chr1, *chr2;
|
||
|
int delta;
|
||
|
|
||
|
//extract the first characters of the name from each entry
|
||
|
chr1 = ((charData_t *)ptr1)->charName;
|
||
|
chr2 = ((charData_t *)ptr2)->charName;
|
||
|
|
||
|
//double check they're lower-case. case matters
|
||
|
if ( *chr1 >= 'A' && *chr1 <= 'Z' ) *chr1 += 32;
|
||
|
if ( *chr2 >= 'A' && *chr2 <= 'Z' ) *chr2 += 32;
|
||
|
|
||
|
//based off of their ASCII order.
|
||
|
delta = (int)*chr1 - (int)*chr2;
|
||
|
|
||
|
//if characters weren't the same
|
||
|
if ( delta != 0 )
|
||
|
return delta;
|
||
|
|
||
|
//else loop through the rest
|
||
|
while ( chr1 && chr2 && delta == 0 )
|
||
|
{
|
||
|
delta = (int)*chr1 - (int)*chr2;
|
||
|
|
||
|
chr1++;
|
||
|
chr2++;
|
||
|
}
|
||
|
|
||
|
return delta;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_SetMenuItems
|
||
|
=================
|
||
|
*/
|
||
|
static void PlayerModel_SetMenuItems( void )
|
||
|
{
|
||
|
int i;
|
||
|
char* temp;
|
||
|
//char model[64];
|
||
|
char model[32];
|
||
|
char skin[32];
|
||
|
|
||
|
// name
|
||
|
trap_Cvar_VariableStringBuffer( "name", s_playermodel.playername.string, MAX_PLAYERNAMELENGTH );
|
||
|
|
||
|
// model
|
||
|
trap_Cvar_VariableStringBuffer( "model", s_playermodel.modelData, 64 );
|
||
|
|
||
|
if ( ( temp = strchr( s_playermodel.modelData, '/' ) ) == NULL )
|
||
|
{
|
||
|
Q_strncpyz( s_playermodel.modelName, s_playermodel.modelData, sizeof( s_playermodel.modelName ) );
|
||
|
Q_strncpyz( model, DEFAULT_MODEL, 32 );
|
||
|
Q_strncpyz( skin, DEFAULT_SKIN, 32);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int len;
|
||
|
char* tempSkin;
|
||
|
//
|
||
|
len = strlen( temp );
|
||
|
Q_strncpyz( s_playermodel.modelName, s_playermodel.modelData, (strlen(s_playermodel.modelData) - strlen(temp)) + 1 );
|
||
|
|
||
|
//*temp++;
|
||
|
temp++;
|
||
|
if ( ( tempSkin = strchr( temp, '/' ) ) == NULL ) {
|
||
|
if ( !temp || !temp[1] )
|
||
|
Q_strncpyz( model, DEFAULT_MODEL, 32 );
|
||
|
else
|
||
|
Q_strncpyz( model, temp, 32 );
|
||
|
|
||
|
Q_strncpyz( skin, DEFAULT_SKIN, 32 );
|
||
|
}
|
||
|
else {
|
||
|
len = strlen( tempSkin );
|
||
|
//*tempSkin++;
|
||
|
tempSkin++;
|
||
|
|
||
|
Q_strncpyz( model, temp, (strlen( temp ) - len) + 1 );
|
||
|
|
||
|
if ( !tempSkin || !tempSkin[1] )
|
||
|
Q_strncpyz( skin, DEFAULT_SKIN, 32 );
|
||
|
else
|
||
|
Q_strncpyz( skin, tempSkin, 32 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Com_Printf( S_COLOR_RED "Load model is %s %s %s\n", s_playermodel.modelName, model, skin );
|
||
|
|
||
|
// find model in our list
|
||
|
for (i=0; i<s_playermodel.numChars; i++)
|
||
|
{
|
||
|
if ( !Q_stricmp( s_playermodel.modelName, s_playermodel.charNames[i].charName ) ) {
|
||
|
s_playermodel.selectedChar = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//try to register the current shader icon
|
||
|
if ( s_playermodel.selectedChar != -1 ) {
|
||
|
s_playermodel.playerIcon = trap_R_RegisterShaderNoMip( va( "models/players_rpgx/%s/model_icon", s_playermodel.modelName ) );
|
||
|
|
||
|
//If we're exceeded the list, update it so we're at the top
|
||
|
if ( s_playermodel.selectedChar > MAX_MENULISTITEMS ) {
|
||
|
s_playermodel.scrollOffset = (s_playermodel.selectedChar - MAX_MENULISTITEMS)+1;
|
||
|
PlayerModel_OffsetCharList( &s_playermodel.scrollOffset );
|
||
|
}
|
||
|
|
||
|
s_playermodel.charModel.numitems = PlayerModel_LoadAvailableModels( );
|
||
|
|
||
|
if ( s_playermodel.charModel.numitems != -1 )
|
||
|
{
|
||
|
s_playermodel.charModel.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s_playermodel.charModel.numitems = 0;
|
||
|
s_playermodel.charModel.generic.flags = QMF_GRAYED | QMF_INACTIVE;
|
||
|
s_playermodel.modelList[0] = "NONE";
|
||
|
}
|
||
|
|
||
|
//TiM - Switch the spin controls to the right value;
|
||
|
for ( i=0; i < s_playermodel.charModel.numitems; i++ ) {
|
||
|
if ( !Q_stricmp( s_playermodel.modelList[i], model ) ) {
|
||
|
s_playermodel.charModel.curvalue = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PlayerModel_LoadAvailableSkins( );
|
||
|
s_playermodel.charSkin.numitems = PlayerModel_PopulateSkinsList();
|
||
|
|
||
|
if ( s_playermodel.charSkin.numitems != -1 )
|
||
|
{
|
||
|
s_playermodel.charSkin.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s_playermodel.charSkin.numitems = 0;
|
||
|
s_playermodel.charSkin.generic.flags = QMF_GRAYED | QMF_INACTIVE;
|
||
|
s_playermodel.skinList[0] = "NONE";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
for ( i=0; i < s_playermodel.charSkin.numitems; i++ ) {
|
||
|
if ( !Q_stricmp( s_playermodel.skinList[i], skin ) ) {
|
||
|
s_playermodel.charSkin.curvalue = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Set backup data
|
||
|
s_playermodel.storedData.orgChar = s_playermodel.selectedChar;
|
||
|
s_playermodel.storedData.orgModel = s_playermodel.charModel.curvalue;
|
||
|
s_playermodel.storedData.orgSkin = s_playermodel.charSkin.curvalue;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_DrawScrollBar
|
||
|
=================
|
||
|
*/
|
||
|
static void PlayerModel_DrawScrollBar( void *self )
|
||
|
{
|
||
|
qboolean focus;
|
||
|
menuaction_s *bar;
|
||
|
int *y;
|
||
|
int color;
|
||
|
int newY;
|
||
|
int dif;
|
||
|
|
||
|
bar = (menuaction_s *)self;
|
||
|
|
||
|
focus = ( Menu_ItemAtCursor( bar->generic.parent ) == bar );
|
||
|
|
||
|
if ( focus )
|
||
|
color = bar->color2;
|
||
|
else
|
||
|
color = bar->color;
|
||
|
|
||
|
trap_R_SetColor( colorTable[ color ] );
|
||
|
UI_DrawHandlePic( bar->generic.x, bar->generic.y, bar->width, bar->height, uis.whiteShader);
|
||
|
trap_R_SetColor( NULL );
|
||
|
|
||
|
if ( !s_playermodel.scrollData.mouseDown )
|
||
|
return;
|
||
|
|
||
|
if ( !trap_Key_IsDown( K_MOUSE1 ) )
|
||
|
{
|
||
|
s_playermodel.scrollData.mouseDown = qfalse;
|
||
|
uis.activemenu->noNewSelecting = qfalse;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( uis.cursory == s_playermodel.scrollData.yStart )
|
||
|
return;
|
||
|
|
||
|
y = &bar->generic.y;
|
||
|
|
||
|
newY = *y + (uis.cursory - s_playermodel.scrollData.yStart);
|
||
|
|
||
|
if ( newY+bar->height > MAX_SCROLLTOP + MAX_SCROLLRANGE )
|
||
|
newY = (MAX_SCROLLTOP + MAX_SCROLLRANGE) - bar->height;
|
||
|
|
||
|
if ( newY < MAX_SCROLLTOP )
|
||
|
newY = MAX_SCROLLTOP;
|
||
|
|
||
|
dif = newY - *y;
|
||
|
|
||
|
s_playermodel.scrollOffset += dif * (s_playermodel.scrollData.doubleStep ? 2 : 1);
|
||
|
PlayerModel_OffsetCharList( &s_playermodel.scrollOffset );
|
||
|
|
||
|
*y = newY;
|
||
|
bar->generic.top = *y;
|
||
|
bar->generic.bottom = *y + bar->height;
|
||
|
|
||
|
s_playermodel.scrollData.yStart = uis.cursory;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerSettingsMenu_Graphics
|
||
|
=================
|
||
|
*/
|
||
|
void PlayerModelMenu_Graphics (void)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
// Draw the basic screen layout
|
||
|
UI_MenuFrame2(&s_playermodel.menu);
|
||
|
|
||
|
trap_R_SetColor( colorTable[CT_LTBROWN1]);
|
||
|
UI_DrawHandlePic(30,203, 47, 186, uis.whiteShader); // Middle left line
|
||
|
|
||
|
trap_R_SetColor( colorTable[CT_LTORANGE]);
|
||
|
|
||
|
//TiM - Frame around the models selection list
|
||
|
UI_DrawHandlePic( 96, 50, 8, -32, s_playermodel.corner_ll_4_18); // UL Corner
|
||
|
UI_DrawHandlePic( 96, 369, 8, 8, s_playermodel.corner_ll_4_4); // LL Corner
|
||
|
UI_DrawHandlePic( 238, 62, 32, 32, s_playermodel.corner_ur_18_18); // UR Corner
|
||
|
UI_DrawHandlePic( 240, 368, 32, 8, s_playermodel.corner_lr_18_4); // LR Corner
|
||
|
UI_DrawHandlePic( 96, 81, 4, 290, uis.whiteShader); // Left side
|
||
|
UI_DrawHandlePic( 242, 87, 18, 18, uis.whiteShader ); //Right Side Up Arrow Button
|
||
|
if ( s_playermodel.scrollBar.generic.flags & QMF_HIDDEN )
|
||
|
{
|
||
|
UI_DrawHandlePic( 242, 108, 18, 236, uis.whiteShader); // Right side
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( s_playermodel.scrollBar.generic.y > MAX_SCROLLTOP + 4 )
|
||
|
UI_DrawHandlePic( 242, 108, 18, s_playermodel.scrollBar.generic.y - 108 - 3, uis.whiteShader);
|
||
|
if ( s_playermodel.scrollBar.generic.bottom + 3 < 343 )
|
||
|
UI_DrawHandlePic( 242, s_playermodel.scrollBar.generic.bottom + 3, 18, 343 - 3 - s_playermodel.scrollBar.generic.bottom, uis.whiteShader);
|
||
|
}
|
||
|
UI_DrawHandlePic( 242, 347, 18, 18, uis.whiteShader ); //Right Side Down Button
|
||
|
UI_DrawHandlePic( 100, 62, 141, 18, uis.whiteShader); // Top
|
||
|
UI_DrawHandlePic( 101, 371, 140, 4, uis.whiteShader); // Bottom
|
||
|
|
||
|
//TiM - Frame around the model specific data window
|
||
|
UI_DrawHandlePic( 265, 50, 8, -32, s_playermodel.corner_ll_4_18); // UL Corner
|
||
|
UI_DrawHandlePic( 265, 369, 8, 8, s_playermodel.corner_ll_4_4); // LL Corner
|
||
|
UI_DrawHandlePic( 422, 50, -8, -32, s_playermodel.corner_ll_4_18); // UR Corner
|
||
|
UI_DrawHandlePic( 422, 369, -8, 8, s_playermodel.corner_ll_4_4); // LR Corner
|
||
|
UI_DrawHandlePic( 265, 81, 4, 290, uis.whiteShader); // Left side
|
||
|
UI_DrawHandlePic( 426, 81, 4, 290, uis.whiteShader); // Right side
|
||
|
UI_DrawHandlePic( 269, 62, 157, 18, uis.whiteShader); // Top
|
||
|
UI_DrawHandlePic( 269, 371, 157, 4, uis.whiteShader); // Bottom
|
||
|
|
||
|
//TiM - Draw the stunningly awesome icon of the character
|
||
|
UI_DrawHandlePic( 306, 114, 82, 82, uis.whiteShader);
|
||
|
if ( !s_playermodel.playerIcon ) {
|
||
|
trap_R_SetColor( colorTable[CT_BLACK] );
|
||
|
UI_DrawHandlePic( 307, 115, 80, 80, uis.whiteShader );
|
||
|
UI_DrawProportionalString( 347, 145, "?", UI_BIGFONT|UI_CENTER, colorTable[CT_LTORANGE] );
|
||
|
}
|
||
|
else {
|
||
|
trap_R_SetColor( colorTable[CT_WHITE]);
|
||
|
UI_DrawHandlePic( 307, 115, 80, 80, s_playermodel.playerIcon );
|
||
|
}
|
||
|
|
||
|
//UI_DrawProportionalString( 220, 362, va("%s %d %s %d",menu_normal_text[MNT_SCREEN],(s_playermodel.modelpage + 1),menu_normal_text[MNT_OF],s_playermodel.numpages),UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
|
||
|
|
||
|
UI_DrawProportionalString( 108, 64, menu_normal_text[MNT_CHARS],UI_SMALLFONT,colorTable[CT_BLACK]); // Top
|
||
|
|
||
|
UI_DrawProportionalString( 275, 64, menu_normal_text[MNT_CHARDATA], UI_SMALLFONT, colorTable[CT_BLACK] );
|
||
|
|
||
|
trap_R_SetColor( colorTable[CT_DKGREY2]);
|
||
|
UI_DrawHandlePic( 439, 79, 151, 295, uis.whiteShader); // Background
|
||
|
|
||
|
// Frame around player model
|
||
|
trap_R_SetColor( colorTable[CT_LTORANGE]);
|
||
|
UI_DrawHandlePic( 435, 50, 8, -32, s_playermodel.corner_ll_4_18); // UL Corner
|
||
|
UI_DrawHandlePic( 435, 369, 8, 8, s_playermodel.corner_ll_4_4); // LL Corner
|
||
|
UI_DrawHandlePic( 440, 62, 150, 18, uis.whiteShader); // Top
|
||
|
UI_DrawHandlePic( 435, 79, 4, 295, uis.whiteShader); // Left side
|
||
|
UI_DrawHandlePic( 440, 371, 150, 4, uis.whiteShader); // Bottom
|
||
|
|
||
|
// Left rounded ends for buttons
|
||
|
trap_R_SetColor( colorTable[s_playermodel.mainmenu.color]);
|
||
|
UI_DrawHandlePic(s_playermodel.mainmenu.generic.x - 14, s_playermodel.mainmenu.generic.y,
|
||
|
MENU_BUTTON_MED_HEIGHT, MENU_BUTTON_MED_HEIGHT, uis.graphicButtonLeftEnd);
|
||
|
|
||
|
trap_R_SetColor( colorTable[s_playermodel.back.color]);
|
||
|
UI_DrawHandlePic(s_playermodel.back.generic.x - 14, s_playermodel.back.generic.y,
|
||
|
MENU_BUTTON_MED_HEIGHT, MENU_BUTTON_MED_HEIGHT, uis.graphicButtonLeftEnd);
|
||
|
|
||
|
trap_R_SetColor( colorTable[s_playermodel.data.color]);
|
||
|
UI_DrawHandlePic(s_playermodel.data.generic.x - 14, s_playermodel.data.generic.y,
|
||
|
MENU_BUTTON_MED_HEIGHT, MENU_BUTTON_MED_HEIGHT, uis.graphicButtonLeftEnd);
|
||
|
|
||
|
trap_R_SetColor( colorTable[s_playermodel.model.color]);
|
||
|
UI_DrawHandlePic(s_playermodel.model.generic.x - 14, s_playermodel.model.generic.y,
|
||
|
MENU_BUTTON_MED_HEIGHT, MENU_BUTTON_MED_HEIGHT, uis.graphicButtonLeftEnd);
|
||
|
|
||
|
//Model Name along the top
|
||
|
if ( s_playermodel.modelName[0] )
|
||
|
{
|
||
|
char* buf = s_playermodel.modelName;
|
||
|
|
||
|
UI_DrawProportionalString( 347, 89, Q_strupr( buf ), UI_SMALLFONT|UI_CENTER,colorTable[CT_DKPURPLE1]);
|
||
|
}
|
||
|
|
||
|
UI_DrawProportionalString( 74, 28, "881",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
|
||
|
UI_DrawProportionalString( 74, 150, "2445",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
|
||
|
UI_DrawProportionalString( 74, 206, "600",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
|
||
|
UI_DrawProportionalString( 74, 395, "3-44",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
|
||
|
|
||
|
//paint the selected model white
|
||
|
{
|
||
|
for ( i = 0; i < MAX_MENULISTITEMS; i++ )
|
||
|
{
|
||
|
if ( s_playermodel.charMenu[i].textcolor == CT_WHITE && s_playermodel.charMenu[i].textcolor2 == CT_WHITE )
|
||
|
{
|
||
|
s_playermodel.charMenu[i].textcolor = CT_DKGOLD1;
|
||
|
s_playermodel.charMenu[i].textcolor2 = CT_LTGOLD1;
|
||
|
}
|
||
|
|
||
|
//override between straight list, and filters
|
||
|
if ( ( s_playermodel.charNames[i + s_playermodel.scrollOffset].index == -1 && i + s_playermodel.scrollOffset == s_playermodel.selectedChar)
|
||
|
||
|
||
|
( s_playermodel.charNames[i + s_playermodel.scrollOffset].index >= 0 && s_playermodel.charNames[i + s_playermodel.scrollOffset].index == s_playermodel.selectedChar )
|
||
|
)
|
||
|
{
|
||
|
//Com_Printf( S_COLOR_GREEN "%i %i %i\n", i, s_playermodel.selectedChar, s_playermodel.charNames[i + s_playermodel.scrollOffset].index );
|
||
|
s_playermodel.charMenu[i].textcolor = CT_WHITE;
|
||
|
s_playermodel.charMenu[i].textcolor2 = CT_WHITE;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerSettings_MenuDraw
|
||
|
=================
|
||
|
*/
|
||
|
static void PlayerModel_MenuDraw (void)
|
||
|
{
|
||
|
PlayerModelMenu_Graphics();
|
||
|
|
||
|
Menu_Draw( &s_playermodel.menu );
|
||
|
}
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_MenuInit
|
||
|
=================
|
||
|
*/
|
||
|
static void PlayerModel_MenuInit(int menuFrom)
|
||
|
{
|
||
|
int i;
|
||
|
//int j;
|
||
|
//int k;
|
||
|
int x;
|
||
|
int y;
|
||
|
static char playername[32];
|
||
|
static char modelname[32];
|
||
|
static char skinname[32];
|
||
|
static char skinnameviewed[32];
|
||
|
qboolean races=qfalse;
|
||
|
qboolean genders=qfalse;
|
||
|
|
||
|
// zero set all our globals
|
||
|
memset( &s_playermodel, 0 ,sizeof(playermodel_t) );
|
||
|
|
||
|
s_playermodel.prevMenu = menuFrom;
|
||
|
|
||
|
//TiM : Model Spin view
|
||
|
uis.spinView = qfalse;
|
||
|
uis.lastYaw = 150;
|
||
|
|
||
|
PlayerModel_Cache();
|
||
|
|
||
|
//Set up some false data to feed our spin controls for the time being
|
||
|
//Spin controls NEED data passed to them on init, eitherwise they immediately terminate. which sucks lol
|
||
|
s_playermodel.modelList[0] = "NONE";
|
||
|
s_playermodel.skinList[0] = "NONE";
|
||
|
|
||
|
Q_strncpyz( s_playermodel.genderList[0].filterName , "All", 32 );
|
||
|
Q_strncpyz( s_playermodel.raceList[0].filterName, "All", 32 );
|
||
|
|
||
|
// set initial states
|
||
|
PlayerModel_BuildList();
|
||
|
|
||
|
//sort the race list alphabetically
|
||
|
//+1 for number to account for the 'All' value
|
||
|
qsort( (void *)s_playermodel.raceList, s_playermodel.numRaces+1, sizeof( filterData_t ), FilterList_Compare );
|
||
|
qsort( (void *)s_playermodel.genderList, s_playermodel.numGenders+1, sizeof( filterData_t ), FilterList_Compare );
|
||
|
|
||
|
//Populate the spin control pointers
|
||
|
for ( i = 0; i < 128; i++ ) {
|
||
|
if ( !s_playermodel.genderList[i].filterName[0] && !s_playermodel.raceList[i].filterName[0] )
|
||
|
break;
|
||
|
|
||
|
if ( s_playermodel.genderList[i].filterName[0] ) {
|
||
|
s_playermodel.genderNames[i] = s_playermodel.genderList[i].filterName;
|
||
|
genders = qtrue;
|
||
|
}
|
||
|
|
||
|
if ( s_playermodel.raceList[i].filterName[0] ) {
|
||
|
s_playermodel.raceNames[i] = s_playermodel.raceList[i].filterName;
|
||
|
races = qtrue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
s_playermodel.menu.key = PlayerModel_MenuKey;
|
||
|
s_playermodel.menu.wrapAround = qtrue;
|
||
|
s_playermodel.menu.fullscreen = qtrue;
|
||
|
s_playermodel.menu.draw = PlayerModel_MenuDraw;
|
||
|
s_playermodel.menu.descX = MENU_DESC_X;
|
||
|
s_playermodel.menu.descY = MENU_DESC_Y;
|
||
|
s_playermodel.menu.titleX = MENU_TITLE_X;
|
||
|
s_playermodel.menu.titleY = MENU_TITLE_Y;
|
||
|
s_playermodel.menu.titleI = MNT_CHANGEPLAYER_TITLE;
|
||
|
s_playermodel.menu.footNoteEnum = MNT_CHANGEPLAYER;
|
||
|
|
||
|
s_playermodel.mainmenu.generic.type = MTYPE_BITMAP;
|
||
|
s_playermodel.mainmenu.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
s_playermodel.mainmenu.generic.x = 110;
|
||
|
s_playermodel.mainmenu.generic.y = 391;
|
||
|
s_playermodel.mainmenu.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
|
||
|
s_playermodel.mainmenu.generic.callback = PlayerModel_MenuEvent;
|
||
|
s_playermodel.mainmenu.width = MENU_BUTTON_MED_WIDTH;
|
||
|
s_playermodel.mainmenu.height = MENU_BUTTON_MED_HEIGHT;
|
||
|
s_playermodel.mainmenu.color = CT_DKPURPLE1;
|
||
|
s_playermodel.mainmenu.color2 = CT_LTPURPLE1;
|
||
|
|
||
|
if (!ingameFlag)
|
||
|
{
|
||
|
s_playermodel.mainmenu.textEnum = MBT_MAINMENU;
|
||
|
s_playermodel.mainmenu.generic.id = ID_MAINMENU;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s_playermodel.mainmenu.textEnum = MBT_INGAMEMENU;
|
||
|
s_playermodel.mainmenu.generic.id = ID_INGAMEMENU;
|
||
|
}
|
||
|
|
||
|
s_playermodel.mainmenu.textX = MENU_BUTTON_TEXT_X;
|
||
|
s_playermodel.mainmenu.textY = MENU_BUTTON_TEXT_Y;
|
||
|
s_playermodel.mainmenu.textcolor = CT_BLACK;
|
||
|
s_playermodel.mainmenu.textcolor2 = CT_WHITE;
|
||
|
|
||
|
s_playermodel.back.generic.type = MTYPE_BITMAP;
|
||
|
s_playermodel.back.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
|
||
|
s_playermodel.back.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
s_playermodel.back.generic.callback = PlayerModel_MenuEvent;
|
||
|
s_playermodel.back.generic.id = ID_BACK;
|
||
|
s_playermodel.back.generic.x = 110;
|
||
|
s_playermodel.back.generic.y = 415;
|
||
|
s_playermodel.back.width = MENU_BUTTON_MED_WIDTH;
|
||
|
s_playermodel.back.height = MENU_BUTTON_MED_HEIGHT;
|
||
|
s_playermodel.back.color = CT_DKPURPLE1;
|
||
|
s_playermodel.back.color2 = CT_LTPURPLE1;
|
||
|
s_playermodel.back.textX = MENU_BUTTON_TEXT_X;
|
||
|
s_playermodel.back.textY = MENU_BUTTON_TEXT_Y;
|
||
|
s_playermodel.back.textEnum = MBT_BACK;
|
||
|
s_playermodel.back.generic.id = ID_BACK;
|
||
|
s_playermodel.back.textcolor = CT_BLACK;
|
||
|
s_playermodel.back.textcolor2 = CT_WHITE;
|
||
|
|
||
|
s_playermodel.data.generic.type = MTYPE_BITMAP;
|
||
|
s_playermodel.data.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
|
||
|
s_playermodel.data.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
s_playermodel.data.generic.id = ID_SETTINGS;
|
||
|
s_playermodel.data.generic.callback = PlayerModel_MenuEvent;
|
||
|
s_playermodel.data.generic.x = 482;
|
||
|
s_playermodel.data.generic.y = 391;
|
||
|
s_playermodel.data.width = MENU_BUTTON_MED_WIDTH;
|
||
|
s_playermodel.data.height = MENU_BUTTON_MED_HEIGHT;
|
||
|
s_playermodel.data.color = CT_DKPURPLE1;
|
||
|
s_playermodel.data.color2 = CT_LTPURPLE1;
|
||
|
s_playermodel.data.textX = 5;
|
||
|
s_playermodel.data.textY = 2;
|
||
|
s_playermodel.data.textEnum = MBT_PLAYERDATA;
|
||
|
s_playermodel.data.textcolor = CT_BLACK;
|
||
|
s_playermodel.data.textcolor2 = CT_WHITE;
|
||
|
|
||
|
s_playermodel.model.generic.type = MTYPE_BITMAP;
|
||
|
s_playermodel.model.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
|
||
|
s_playermodel.model.generic.flags = QMF_GRAYED;
|
||
|
s_playermodel.model.generic.x = 482;
|
||
|
s_playermodel.model.generic.y = 415;
|
||
|
s_playermodel.model.width = MENU_BUTTON_MED_WIDTH;
|
||
|
s_playermodel.model.height = MENU_BUTTON_MED_HEIGHT;
|
||
|
s_playermodel.model.color = CT_DKPURPLE1;
|
||
|
s_playermodel.model.color2 = CT_LTPURPLE1;
|
||
|
s_playermodel.model.textX = 5;
|
||
|
s_playermodel.model.textY = 2;
|
||
|
s_playermodel.model.textEnum = MBT_CHANGEMODEL;
|
||
|
s_playermodel.model.textcolor = CT_BLACK;
|
||
|
s_playermodel.model.textcolor2 = CT_WHITE;
|
||
|
|
||
|
//y = 88;
|
||
|
x = 107;
|
||
|
y = 85;
|
||
|
|
||
|
for (i=0; i < MAX_MENULISTITEMS; i++ ) {
|
||
|
s_playermodel.charMenu[i].generic.type = MTYPE_BITMAP;
|
||
|
s_playermodel.charMenu[i].generic.flags = QMF_INACTIVE | QMF_HIDDEN;
|
||
|
s_playermodel.charMenu[i].generic.x = x;
|
||
|
s_playermodel.charMenu[i].generic.y = y;
|
||
|
s_playermodel.charMenu[i].generic.callback = PlayerModel_MenuEvent;
|
||
|
s_playermodel.charMenu[i].generic.id = ID_MENUCHAR0+i;
|
||
|
s_playermodel.charMenu[i].width = 129;
|
||
|
s_playermodel.charMenu[i].height = 16;
|
||
|
s_playermodel.charMenu[i].color = CT_DKPURPLE1;
|
||
|
s_playermodel.charMenu[i].color2 = CT_LTPURPLE1;
|
||
|
s_playermodel.charMenu[i].textPtr = NULL;
|
||
|
s_playermodel.charMenu[i].textX = 4;
|
||
|
s_playermodel.charMenu[i].textY = 1;
|
||
|
s_playermodel.charMenu[i].textcolor = CT_DKGOLD1;
|
||
|
s_playermodel.charMenu[i].textcolor2 = CT_LTGOLD1;
|
||
|
s_playermodel.charMenu[i].textStyle = UI_SMALLFONT;
|
||
|
|
||
|
y += 24;
|
||
|
}
|
||
|
|
||
|
s_playermodel.playername.generic.type = MTYPE_PTEXT;
|
||
|
s_playermodel.playername.generic.flags = QMF_INACTIVE;
|
||
|
s_playermodel.playername.generic.x = 444;
|
||
|
s_playermodel.playername.generic.y = 63;
|
||
|
s_playermodel.playername.string = playername;
|
||
|
s_playermodel.playername.style = UI_SMALLFONT;
|
||
|
s_playermodel.playername.color = colorTable[CT_BLACK];
|
||
|
|
||
|
/*s_playermodel.modelname.generic.type = MTYPE_PTEXT;
|
||
|
s_playermodel.modelname.generic.flags = QMF_INACTIVE;
|
||
|
s_playermodel.modelname.generic.x = 121;
|
||
|
s_playermodel.modelname.generic.y = 338;
|
||
|
s_playermodel.modelname.string = modelname;
|
||
|
s_playermodel.modelname.style = UI_LEFT;
|
||
|
s_playermodel.modelname.color = colorTable[CT_LTBLUE1];*/
|
||
|
|
||
|
/*s_playermodel.skinname.generic.type = MTYPE_PTEXT;
|
||
|
s_playermodel.skinname.generic.flags = QMF_INACTIVE;
|
||
|
s_playermodel.skinname.generic.x = 323;
|
||
|
s_playermodel.skinname.generic.y = 338;
|
||
|
s_playermodel.skinname.string = skinname;
|
||
|
s_playermodel.skinname.style = UI_RIGHT;
|
||
|
s_playermodel.skinname.color = colorTable[CT_LTBLUE1];*/
|
||
|
|
||
|
s_playermodel.player.generic.type = MTYPE_BITMAP;
|
||
|
s_playermodel.player.generic.flags = QMF_SILENT;
|
||
|
s_playermodel.player.generic.ownerdraw = PlayerModel_DrawPlayer;
|
||
|
s_playermodel.player.generic.callback = PlayerModel_SpinPlayer;
|
||
|
s_playermodel.player.generic.x = 439; //400
|
||
|
s_playermodel.player.generic.y = 80; //20
|
||
|
s_playermodel.player.width = 151; //32*7.3
|
||
|
s_playermodel.player.height = 291; //56*7.3
|
||
|
|
||
|
s_playermodel.upArrow.generic.type = MTYPE_BITMAP;
|
||
|
s_playermodel.upArrow.generic.name = PIC_ARROW_UP;
|
||
|
s_playermodel.upArrow.generic.flags = QMF_GRAYED | QMF_INACTIVE;
|
||
|
s_playermodel.upArrow.generic.callback = PlayerModel_MenuEvent;
|
||
|
s_playermodel.upArrow.generic.id = ID_UPARROW;
|
||
|
s_playermodel.upArrow.generic.x = 243;
|
||
|
s_playermodel.upArrow.generic.y = 89;
|
||
|
s_playermodel.upArrow.width = 16;
|
||
|
s_playermodel.upArrow.height = 16;
|
||
|
s_playermodel.upArrow.color = CT_DKPURPLE1;
|
||
|
s_playermodel.upArrow.color2 = CT_LTPURPLE1;
|
||
|
s_playermodel.upArrow.textX = MENU_BUTTON_TEXT_X;
|
||
|
s_playermodel.upArrow.textY = MENU_BUTTON_TEXT_Y;
|
||
|
//s_playermodel.upArrow.textEnum = MBT_PREVPAGE;
|
||
|
s_playermodel.upArrow.textcolor = CT_BLACK;
|
||
|
s_playermodel.upArrow.textcolor2 = CT_WHITE;
|
||
|
|
||
|
s_playermodel.dnArrow.generic.type = MTYPE_BITMAP;
|
||
|
s_playermodel.dnArrow.generic.name = PIC_ARROW_DOWN;
|
||
|
s_playermodel.dnArrow.generic.flags = QMF_GRAYED | QMF_INACTIVE;
|
||
|
s_playermodel.dnArrow.generic.callback = PlayerModel_MenuEvent;
|
||
|
s_playermodel.dnArrow.generic.id = ID_DNARROW;
|
||
|
s_playermodel.dnArrow.generic.x = 243;
|
||
|
s_playermodel.dnArrow.generic.y = 349;
|
||
|
s_playermodel.dnArrow.width = 16;
|
||
|
s_playermodel.dnArrow.height = 16;
|
||
|
s_playermodel.dnArrow.color = CT_DKPURPLE1;
|
||
|
s_playermodel.dnArrow.color2 = CT_LTPURPLE1;
|
||
|
s_playermodel.dnArrow.textX = MENU_BUTTON_TEXT_X;
|
||
|
s_playermodel.dnArrow.textY = MENU_BUTTON_TEXT_Y;
|
||
|
//s_playermodel.dnArrow.textEnum = MBT_NEXTPAGE;
|
||
|
s_playermodel.dnArrow.textcolor = CT_BLACK;
|
||
|
s_playermodel.dnArrow.textcolor2 = CT_WHITE;
|
||
|
|
||
|
s_playermodel.charModel.generic.type = MTYPE_SPINCONTROL;
|
||
|
s_playermodel.charModel.generic.flags = QMF_INACTIVE | QMF_GRAYED; //QMF_HIGHLIGHT_IF_FOCUS
|
||
|
s_playermodel.charModel.generic.id = ID_MODELSET;
|
||
|
s_playermodel.charModel.generic.callback = PlayerModel_MenuEvent;
|
||
|
s_playermodel.charModel.generic.x = 291;//134;
|
||
|
s_playermodel.charModel.generic.y = 209;//207;
|
||
|
s_playermodel.charModel.textEnum = MBT_CHARMODEL;
|
||
|
s_playermodel.charModel.textcolor = CT_BLACK;
|
||
|
s_playermodel.charModel.textcolor2 = CT_WHITE;
|
||
|
s_playermodel.charModel.color = CT_DKPURPLE1;
|
||
|
s_playermodel.charModel.color2 = CT_LTPURPLE1;
|
||
|
s_playermodel.charModel.width = 92;//80;
|
||
|
s_playermodel.charModel.textX = 56;
|
||
|
s_playermodel.charModel.textY = 2;
|
||
|
s_playermodel.charModel.textFlags = UI_CENTER;
|
||
|
s_playermodel.charModel.listX = 56;
|
||
|
s_playermodel.charModel.listY = 24;
|
||
|
s_playermodel.charModel.listFlags = UI_CENTER;
|
||
|
s_playermodel.charModel.focusWidth = 110;
|
||
|
s_playermodel.charModel.focusHeight = 40;
|
||
|
s_playermodel.charModel.itemnames = (const char **)s_playermodel.modelList;
|
||
|
|
||
|
s_playermodel.charSkin.generic.type = MTYPE_SPINCONTROL;
|
||
|
s_playermodel.charSkin.generic.flags = QMF_INACTIVE | QMF_GRAYED;
|
||
|
s_playermodel.charSkin.generic.id = ID_SKINSET;
|
||
|
s_playermodel.charSkin.generic.callback = PlayerModel_MenuEvent;
|
||
|
s_playermodel.charSkin.generic.x = 291;//134;
|
||
|
s_playermodel.charSkin.generic.y = 266;//207;
|
||
|
s_playermodel.charSkin.textEnum = MBT_CHARSKIN;
|
||
|
s_playermodel.charSkin.textcolor = CT_BLACK;
|
||
|
s_playermodel.charSkin.textcolor2 = CT_WHITE;
|
||
|
s_playermodel.charSkin.color = CT_DKPURPLE1;
|
||
|
s_playermodel.charSkin.color2 = CT_LTPURPLE1;
|
||
|
s_playermodel.charSkin.width = 90;//80;
|
||
|
s_playermodel.charSkin.textX = 56;
|
||
|
s_playermodel.charSkin.textY = 2;
|
||
|
s_playermodel.charSkin.textFlags = UI_CENTER;
|
||
|
s_playermodel.charSkin.listX = 56;
|
||
|
s_playermodel.charSkin.listY = 24;
|
||
|
s_playermodel.charSkin.listFlags = UI_CENTER;
|
||
|
s_playermodel.charSkin.focusWidth = 110;
|
||
|
s_playermodel.charSkin.focusHeight = 40;
|
||
|
s_playermodel.charSkin.itemnames = (const char**)s_playermodel.skinList;
|
||
|
|
||
|
s_playermodel.raceFilter.generic.type = MTYPE_SPINCONTROL;
|
||
|
if ( !races ) {
|
||
|
s_playermodel.raceFilter.generic.flags = QMF_INACTIVE | QMF_GRAYED;
|
||
|
}
|
||
|
else {
|
||
|
s_playermodel.raceFilter.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
}
|
||
|
s_playermodel.raceFilter.generic.id = ID_RACEFILTER;
|
||
|
s_playermodel.raceFilter.generic.callback = PlayerModel_MenuEvent;
|
||
|
s_playermodel.raceFilter.generic.x = 270;
|
||
|
s_playermodel.raceFilter.generic.y = 391;
|
||
|
s_playermodel.raceFilter.textEnum = MBT_RACEFILTER;
|
||
|
s_playermodel.raceFilter.textcolor = CT_BLACK;
|
||
|
s_playermodel.raceFilter.textcolor2 = CT_WHITE;
|
||
|
s_playermodel.raceFilter.color = CT_DKPURPLE1;
|
||
|
s_playermodel.raceFilter.color2 = CT_LTPURPLE1;
|
||
|
s_playermodel.raceFilter.textX = 10;
|
||
|
s_playermodel.raceFilter.textY = 1;
|
||
|
s_playermodel.raceFilter.width = 65;
|
||
|
s_playermodel.raceFilter.itemnames = (const char**)s_playermodel.raceNames;
|
||
|
|
||
|
s_playermodel.genderFilter.generic.type = MTYPE_SPINCONTROL;
|
||
|
if ( !genders ) {
|
||
|
s_playermodel.genderFilter.generic.flags = QMF_INACTIVE | QMF_GRAYED;
|
||
|
}
|
||
|
else {
|
||
|
s_playermodel.genderFilter.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
}
|
||
|
s_playermodel.genderFilter.generic.id = ID_GENDERFILTER;
|
||
|
s_playermodel.genderFilter.generic.callback = PlayerModel_MenuEvent;
|
||
|
s_playermodel.genderFilter.generic.x = 270;
|
||
|
s_playermodel.genderFilter.generic.y = 414;
|
||
|
s_playermodel.genderFilter.textEnum = MBT_GENDERFILTER;
|
||
|
s_playermodel.genderFilter.textcolor = CT_BLACK;
|
||
|
s_playermodel.genderFilter.textcolor2 = CT_WHITE;
|
||
|
s_playermodel.genderFilter.color = CT_DKPURPLE1;
|
||
|
s_playermodel.genderFilter.color2 = CT_LTPURPLE1;
|
||
|
s_playermodel.genderFilter.textX = 10;
|
||
|
s_playermodel.genderFilter.textY = 1;
|
||
|
s_playermodel.genderFilter.width = 65;
|
||
|
s_playermodel.genderFilter.itemnames = (const char**)s_playermodel.genderNames;
|
||
|
|
||
|
s_playermodel.apply.generic.type = MTYPE_BITMAP;
|
||
|
s_playermodel.apply.generic.name = GRAPHIC_SQUARE;
|
||
|
s_playermodel.apply.generic.flags = QMF_GRAYED | QMF_INACTIVE;
|
||
|
s_playermodel.apply.generic.callback = PlayerModel_MenuEvent;
|
||
|
s_playermodel.apply.generic.id = ID_APPLY;
|
||
|
s_playermodel.apply.generic.x = 281;
|
||
|
s_playermodel.apply.generic.y = 321;
|
||
|
s_playermodel.apply.width = 132;
|
||
|
s_playermodel.apply.height = 39;
|
||
|
s_playermodel.apply.color = CT_DKPURPLE1;
|
||
|
s_playermodel.apply.color2 = CT_LTPURPLE1;
|
||
|
s_playermodel.apply.textX = MENU_BUTTON_TEXT_X;
|
||
|
s_playermodel.apply.textY = MENU_BUTTON_TEXT_Y;
|
||
|
s_playermodel.apply.textEnum = MBT_VIDEOAPPLYCHANGES;
|
||
|
s_playermodel.apply.textcolor = CT_BLACK;
|
||
|
s_playermodel.apply.textcolor2 = CT_WHITE;
|
||
|
|
||
|
s_playermodel.scrollBar.generic.type = MTYPE_ACTION;
|
||
|
s_playermodel.scrollBar.generic.flags = QMF_INACTIVE | QMF_HIDDEN;
|
||
|
s_playermodel.scrollBar.generic.x = 242;
|
||
|
s_playermodel.scrollBar.generic.y = 108;
|
||
|
s_playermodel.scrollBar.generic.id = ID_SCROLLBAR;
|
||
|
s_playermodel.scrollBar.generic.ownerdraw = PlayerModel_DrawScrollBar;
|
||
|
s_playermodel.scrollBar.width = 18;
|
||
|
s_playermodel.scrollBar.height = MIN_SCROLLHEIGHT;
|
||
|
s_playermodel.scrollBar.color = CT_DKPURPLE1;
|
||
|
s_playermodel.scrollBar.color2 = CT_LTPURPLE1;
|
||
|
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.model );
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.data );
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.player );
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.playername );
|
||
|
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.upArrow );
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.scrollBar );
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.dnArrow );
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.charModel );
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.charSkin );
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.apply );
|
||
|
|
||
|
for (i=0; i < MAX_MENULISTITEMS; i++ ) {
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.charMenu[i] );
|
||
|
}
|
||
|
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.raceFilter );
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.genderFilter );
|
||
|
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.back );
|
||
|
Menu_AddItem( &s_playermodel.menu, &s_playermodel.mainmenu );
|
||
|
|
||
|
if ( s_playermodel.numChars >= MAX_MENULISTITEMS ) {
|
||
|
s_playermodel.upArrow.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
s_playermodel.dnArrow.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
|
||
|
}
|
||
|
|
||
|
PlayerModel_SetMenuItems();
|
||
|
|
||
|
PlayerModel_OffsetCharList( &s_playermodel.scrollOffset );
|
||
|
|
||
|
PlayerModel_SetupScrollBar( &s_playermodel.scrollBar );
|
||
|
PlayerModel_UpdateScrollBar( &s_playermodel.scrollBar );
|
||
|
|
||
|
// update user interface
|
||
|
PlayerModel_UpdateModel();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_Cache
|
||
|
=================
|
||
|
*/
|
||
|
void PlayerModel_Cache( void )
|
||
|
{
|
||
|
//int i;
|
||
|
|
||
|
s_playermodel.corner_ll_4_18 = trap_R_RegisterShaderNoMip("menu/common/corner_ll_4_18");
|
||
|
s_playermodel.corner_ll_4_4 = trap_R_RegisterShaderNoMip("menu/common/corner_ll_4_4");
|
||
|
s_playermodel.corner_lr_4_18 = trap_R_RegisterShaderNoMip("menu/common/corner_lr_4_18");
|
||
|
s_playermodel.corner_lr_18_4 = trap_R_RegisterShaderNoMip("menu/common/corner_lr_18_4");
|
||
|
s_playermodel.corner_ur_18_18 = trap_R_RegisterShaderNoMip("menu/common/corner_ur_18_18");
|
||
|
|
||
|
trap_R_RegisterShaderNoMip(PIC_ARROW_UP);
|
||
|
trap_R_RegisterShaderNoMip(PIC_ARROW_DOWN);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_DrawLoading
|
||
|
=================
|
||
|
*/
|
||
|
static void PlayerModel_DrawLoading( void )
|
||
|
{
|
||
|
//register the corners now
|
||
|
qhandle_t cornerPic = trap_R_RegisterShaderNoMip("menu/common/corner_ll_47_18.tga");
|
||
|
int y = 50;
|
||
|
|
||
|
trap_R_SetColor( colorTable[CT_DKPURPLE2]);
|
||
|
|
||
|
UI_DrawHandlePic( 132, y+ 42, 128, -64, cornerPic); // Top Left corner
|
||
|
UI_DrawHandlePic( 132, y+252, 128, 64, cornerPic); // Bottom Left corner
|
||
|
|
||
|
UI_DrawHandlePic( 429, y+ 42, -128, -64, cornerPic); // Top Right corner
|
||
|
UI_DrawHandlePic( 429, y+252, -128, 64, cornerPic); // Bottom Right corner
|
||
|
|
||
|
UI_DrawHandlePic(145, y+75, 395, 18, uis.whiteShader); // Top
|
||
|
UI_DrawHandlePic(132, y+93, 47, 175, uis.whiteShader); // Left side
|
||
|
UI_DrawHandlePic(510, y+93, 47, 175, uis.whiteShader); // Right side
|
||
|
UI_DrawHandlePic(147,y+265, 65, 18, uis.whiteShader); // Bottom Left
|
||
|
UI_DrawHandlePic(477,y+265, 65, 18, uis.whiteShader); // Bottom Right
|
||
|
UI_DrawHandlePic(214,y+265, 261, 18, uis.whiteShader); // Bottom
|
||
|
|
||
|
UI_DrawProportionalString(345,y+159,menu_normal_text[MNT_LOADING],UI_SMALLFONT | UI_CENTER,colorTable[CT_LTGOLD1]);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=================
|
||
|
PlayerModel_Cache
|
||
|
=================
|
||
|
*/
|
||
|
void UI_PlayerModelMenu(int menuFrom)
|
||
|
{
|
||
|
//TiM - Spawn a quick "loading" box
|
||
|
//Sometimes this gives me the eerie creeps the game froze
|
||
|
PlayerModel_DrawLoading();
|
||
|
|
||
|
PlayerModel_MenuInit(menuFrom);
|
||
|
|
||
|
UI_PushMenu( &s_playermodel.menu );
|
||
|
|
||
|
//Menu_SetCursorToItem( &s_playermodel.menu, &s_playermodel.pics[s_playermodel.selectedmodel % MAX_MODELSPERPAGE] );
|
||
|
}
|
||
|
|
||
|
|