2011-06-01 12:20:56 +00:00
// 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 ] ;
2011-06-15 06:46:11 +00:00
//static char modelname[32];
//static char skinname[32];
//static char skinnameviewed[32];
2011-06-01 12:20:56 +00:00
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] );
}