summaryrefslogtreecommitdiff
path: root/src/game/g_playermodel.c
blob: 7f79b38a01f3b1535989e39d3ba58bd46d5d01d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//
// Author: blowFish <blowfish@badsec.org>
//

#include "g_local.h"

//-------------------------------------------------------------------------
// Player models
//-------------------------------------------------------------------------
//
static qboolean
_is_playermodel_uniq(const char *model)
{
    int i;
    for ( i = 0; i < level.playerModelCount; i++ )
    {
        if ( !strcmp( model, level.playerModel[i] ) )
            return qfalse;
    }

    return qtrue;
}

static void
G_AddPlayerModel(const char *model)
{
    if (!_is_playermodel_uniq(model))
        return;

    // HACK!
    if (!strcmp(model, "human_bsuit"))
        return;

    level.playerModel[ level.playerModelCount ] = G_CopyString(model);
    level.playerModelCount++;
}

void G_InitPlayerModel(void)
{
    char fileList[ 16*1024 ] = {""};
    char *filePtr;
    int  numFiles;
    int  fileLen = 0;
    int  i;

    // TODO: Add an FS trap which is does correct file globbing
    numFiles = trap_FS_GetFilteredFiles( "/models/players", "",
            "models*players*head_*.skin",
            fileList, sizeof(fileList) );
    filePtr = fileList;

    for( i = 0; i < numFiles && level.playerModelCount < MAX_PLAYER_MODEL;
            i++, filePtr += fileLen + 1 )
    {
        char *start, *c;

        fileLen = strlen( filePtr );

        // skip leading '/'
        start = filePtr + 15;

        // Only want directory names at the current depth.
        for ( c = start; c != '\0'; c++ )
        {
            if ( *c == '/' || *c == '\\' )
            {
                *c = '\0';
                break;
            }
        }

        G_AddPlayerModel(start);
    }
}

qboolean G_IsValidPlayerModel(const char *model)
{
    return !_is_playermodel_uniq(model);
}

void G_FreePlayerModel(void)
{
    int i;
    for ( i = 0; i < level.playerModelCount; i++ )
        BG_Free( level.playerModel[i] );
}

//-------------------------------------------------------------------------
// Skins
//-------------------------------------------------------------------------

void G_GetPlayerModelSkins( const char *modelname, char skins[][ 64 ],
 int maxskins, int *numskins )
{
    char fileList[ 16*1024 ] = {""};
    int nFiles;
    char *filePtr;
    int fileLen = 0;
    int i;

    *numskins = 0;
    nFiles = trap_FS_GetFilteredFiles("models/players", ".skin",
            va("models*players*%s*skin", modelname),
            fileList, sizeof(fileList));
    filePtr = fileList;
    for (i = 0; i < nFiles && i < maxskins; i++ )
    {
        char *start, *end;

        fileLen = strlen( filePtr );

        start = filePtr;
        start += strlen(va("models/players/%s/", modelname));

        end = filePtr + fileLen;
        end -= 5;
        *end = '\0';
        filePtr += fileLen + 1;

        // dumb way to filter out the unique skins of segmented and
        // nonsegmented models.
        // TODO: Stop writing code at 4am.
        if ( start[0] == 'h'
          && start[1] == 'e'
          && start[2] == 'a'
          && start[3] == 'd'
          && start[4] == '_' )
            start += 5;

        else if ( start[0] == 'n'
               && start[1] == 'o'
               && start[2] == 'n'
               && start[3] == 's'
               && start[4] == 'e'
               && start[5] == 'g'
               && start[6] == '_' )
            start += 7;

        else
            continue;

        strncpy(skins[*numskins], start, 64 );
        (*numskins)++;
    }
}

/*
======================
GetSkin

Probably should be called GetSkin[or]Default. Tries to recreate what
appears to be an undocumented set of conventions that must be allowed
in other q3 derives.

This algorithm is not really good enough for Tremulous considering
armour + upgrade/advanced in gameplay

XXX Move this into bg_
======================
*/
char *GetSkin( char *modelname, char *wish )
{
    char skins[ MAX_PLAYER_MODEL ][ 64 ];
    int numskins;
    int i;
    qboolean foundDefault = qfalse;
    qboolean foundSelfNamed = qfalse;
    static char lastpick[ 64 ] = {""};
    lastpick[0] = '\0'; // reset static buf

    G_GetPlayerModelSkins(modelname, skins, MAX_PLAYER_MODEL, &numskins);

    for (i = 0; i < numskins; i++)
    {
        if ( i == 0 )
            strncpy(lastpick, skins[0], 64 );

        if ( !strcmp(wish, skins[i]) )
            return wish;
        else if ( !strcmp("default", skins[i]))
            foundDefault = qtrue;
        else if ( !strcmp(modelname, skins[i]))
            foundSelfNamed = qtrue;
    }

    if (foundDefault)
        return "default";
    else if (foundSelfNamed)
        return modelname;

    return lastpick;
}