]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/xonotic/playermodel.qc
Allow maps and player models to require beating a campaign or reaching a given level...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / xonotic / playermodel.qc
1 #include "playermodel.qh"
2
3 entity makeXonoticPlayerModelSelector()
4 {
5         entity me;
6         me = NEW(XonoticPlayerModelSelector);
7         me.configureXonoticPlayerModelSelector(me);
8         return me;
9 }
10
11 const float BUFMODELS_TITLE = 0;
12 const float BUFMODELS_IMAGE = 1;
13 const float BUFMODELS_MODEL = 2;
14 const float BUFMODELS_SKIN = 3;
15 const float BUFMODELS_DESC = 4;
16 const float BUFMODELS_COUNT = 5;
17
18 #define XONVOTE186 1 // (nyov) removal of model text description
19
20 void XonoticPlayerModelSelector_configureXonoticPlayerModelSelector(entity me)
21 {
22         me.configureXonoticImage(me, string_null, -1);
23 }
24
25 bool XonoticPlayerModelSelector_loadModels_isLocked()
26 {
27         bool hidden = false; // hide the player model based on campaign status
28         if(get_model_parameters_locked_name)
29         {
30                 if(get_model_parameters_locked_level > 0) // we need to have reached this level
31                         hidden = cvar(strcat("g_campaign_", get_model_parameters_locked_name, "_index")) < get_model_parameters_locked_level;
32                 else // we need to have won the campaign
33                         hidden = !cvar(strcat("g_campaign_", get_model_parameters_locked_name, "_won"));
34         }
35         return hidden;
36 }
37
38 void XonoticPlayerModelSelector_loadModels(entity me)
39 {
40         int i;
41         string fn;
42
43         float glob = search_begin(get_model_datafilename(string_null, -1, "txt"), true, true);
44         if (glob < 0)
45                 return;
46
47         float sortbuf = buf_create();
48         for(i = 0; i < search_getsize(glob); ++i)
49         {
50                 // select model #i!
51                 fn = search_getfilename(glob, i);
52                 if(!get_model_parameters(fn, -1))
53                         continue;
54                 if(get_model_parameters_hidden || XonoticPlayerModelSelector_loadModels_isLocked())
55                         continue;
56                 bufstr_add(sortbuf, sprintf("%-128s%s", get_model_parameters_name, fn), 1);
57         }
58         search_end(glob);
59         buf_sort(sortbuf, 128, 0);
60         me.numModels = buf_getsize(sortbuf);
61         me.bufModels = buf_create();
62         for(i = 0; i < me.numModels; ++i)
63         {
64                 fn = substring(bufstr_get(sortbuf, i), 128, -1);
65                 if(!get_model_parameters(fn, -1))
66                         error("But it JUST worked!");
67                 if(get_model_parameters_hidden || XonoticPlayerModelSelector_loadModels_isLocked())
68                         continue;
69                 bufstr_set(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_TITLE, get_model_parameters_name);
70                 bufstr_set(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_IMAGE, strcat("/", substring(get_model_datafilename(get_model_parameters_modelname, get_model_parameters_modelskin, "tga"), 0, -5)));
71                 bufstr_set(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_MODEL, get_model_parameters_modelname);
72                 bufstr_set(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_SKIN, ftos(get_model_parameters_modelskin));
73                 get_model_parameters_desc = strcat(get_model_parameters_desc, "\n");
74 #if XONVOTE186
75                 if(get_model_parameters_sex)
76                         get_model_parameters_desc = strcat(get_model_parameters_desc, sprintf("\n%s", get_model_parameters_sex));
77 #else
78                 if(get_model_parameters_description)
79                         get_model_parameters_desc = strcat(get_model_parameters_desc, sprintf("\n%s\n", get_model_parameters_description));
80                 if(get_model_parameters_sex)
81                         get_model_parameters_desc = strcat(get_model_parameters_desc, sprintf("\nSex: %s", get_model_parameters_sex));
82                 if(get_model_parameters_weight)
83                         get_model_parameters_desc = strcat(get_model_parameters_desc, sprintf("\nWeight: %g kg", get_model_parameters_weight));
84                 if(get_model_parameters_age)
85                         get_model_parameters_desc = strcat(get_model_parameters_desc, sprintf("\nAge: %g", get_model_parameters_age));
86 #endif
87                 while(substring(get_model_parameters_desc, -1, 1) == "\n")
88                         get_model_parameters_desc = substring(get_model_parameters_desc, 0, -2);
89                 bufstr_set(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_DESC, get_model_parameters_desc);
90         }
91         buf_del(sortbuf);
92         get_model_parameters(string_null, 0);
93         me.loadCvars(me); // this will select the initial model, depending on the current cvars
94         me.go(me, 0); // this will set the vars for the selected model
95 }
96
97 void XonoticPlayerModelSelector_destroy(entity me)
98 {
99         if(me.bufModels >= 0)
100         {
101                 buf_del(me.bufModels);
102                 me.bufModels = -1;
103         }
104 }
105
106 void XonoticPlayerModelSelector_loadCvars(entity me)
107 {
108         string skin, modelname;
109         float i;
110
111         skin = cvar_string("_cl_playerskin");
112         modelname = cvar_string("_cl_playermodel");
113
114         for(i = 0; i < me.numModels; ++i)
115         {
116                 if(bufstr_get(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_MODEL) == modelname)
117                 if(bufstr_get(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_SKIN) == skin)
118                         break;
119         }
120         if(i >= me.numModels) // fail
121                 i = 0;
122         me.idxModels = i;
123 }
124
125 void XonoticPlayerModelSelector_go(entity me, float d)
126 {
127         me.idxModels = mod(me.idxModels + d + me.numModels, me.numModels);
128
129         // select model #i!
130         strcpy(me.currentModelTitle, bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_TITLE));
131         strcpy(me.currentModelImage, bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_IMAGE));
132         me.currentSkin = stof(bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_SKIN));
133         strcpy(me.currentModel, bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_MODEL));
134         strcpy(me.currentModelDescription, bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_DESC));
135
136         // fix the image
137         if(draw_PictureSize(me.currentModelImage) == '0 0 0')
138                 me.src = "nopreview_player";
139         else
140                 me.src = me.currentModelImage;
141         me.updateAspect(me);
142 }
143
144 void PlayerModelSelector_Next_Click(entity btn, entity me)
145 {
146         if (me.numModels <= 0)
147                 return;
148         me.go(me, +1);
149         me.saveCvars(me);
150 }
151
152 void PlayerModelSelector_Prev_Click(entity btn, entity me)
153 {
154         if (me.numModels <= 0)
155                 return;
156         me.go(me, -1);
157         me.saveCvars(me);
158 }
159
160 void XonoticPlayerModelSelector_saveCvars(entity me)
161 {
162         // we can't immediately apply here because of flood control
163         cvar_set("_cl_playermodel", me.currentModel);
164         cvar_set("_cl_playerskin", ftos(me.currentSkin));
165 }
166
167 void XonoticPlayerModelSelector_draw(entity me)
168 {
169         float i, n;
170         vector o;
171
172         if (me.numModels <= 0)
173         {
174                 draw_CenterText('0.5 0.5 0', _("<no model found>"), me.realFontSize, SKINCOLOR_TEXT, 0.6, false);
175                 return;
176         }
177
178         SUPER(XonoticPlayerModelSelector).draw(me);
179         // draw text on the image, handle \n in the description
180
181         draw_beginBoldFont();
182
183 #if XONVOTE186 // (nyov) lower name display looks better when there is no description text
184         draw_CenterText('0.5 0.8 0', me.currentModelTitle, me.realFontSize * (me.titleFontSize / me.fontSize), SKINCOLOR_MODELTITLE, SKINALPHA_MODELTITLE, false);
185 #else
186         draw_CenterText('0.5 0 0', me.currentModelTitle, me.realFontSize * (me.titleFontSize / me.fontSize), SKINCOLOR_MODELTITLE, SKINALPHA_MODELTITLE, false);
187 #endif
188
189         draw_endBoldFont();
190
191         o = '0.5 1 0' - eY * me.realFontSize.y * ((n = tokenizebyseparator(me.currentModelDescription, "\n")) + 0.5);
192         for(i = 0; i < n; ++i)
193         {
194                 draw_CenterText(o, argv(i), me.realFontSize, SKINCOLOR_TEXT, 1, false);
195                 o += eY * me.realFontSize.y;
196         }
197 }
198
199 void XonoticPlayerModelSelector_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
200 {
201         SUPER(XonoticPlayerModelSelector).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
202         me.realFontSize_y = me.fontSize / absSize.y;
203         me.realFontSize_x = me.fontSize / absSize.x;
204 }
205
206 void XonoticPlayerModelSelector_showNotify(entity me)
207 {
208         // Reinitialize self.
209         me.destroy(me);
210         me.loadModels(me);
211 }