1 #include "pch.h"
2 #include "common/Def_Str.h"
3 #include "common/data/CData.h"
4 #include "common/data/TracksXml.h"
5 #include "common/GuiCom.h"
6 #include "common/CScene.h"
7 #include "../vdrift/pathmanager.h"
8 #include "../vdrift/game.h"
9 #include "CGame.h"
10 #include "CHud.h"
11 #include "CGui.h"
12 #include "../road/Road.h"
13 #include "common/MultiList2.h"
14 #include "../sound/SoundMgr.h"
15 #include <OgreTextureManager.h>
16 using namespace std;
17 using namespace Ogre;
18 using namespace MyGUI;
19
20
21
chkChampRev(Ck *)22 void CGui::chkChampRev(Ck*)
23 {
24 ChampsListUpdate();
25 ChallsListUpdate();
26 }
27
tabTutType(Tab wp,size_t id)28 void CGui::tabTutType(Tab wp, size_t id)
29 {
30 pSet->tut_type = id;
31 ChampsListUpdate();
32 }
tabChampType(Tab wp,size_t id)33 void CGui::tabChampType(Tab wp, size_t id)
34 {
35 pSet->champ_type = id;
36 ChampsListUpdate();
37 }
38
39
40 /// Championships list fill
41 //----------------------------------------------------------------------------------------------------------------------
ChampsListUpdate()42 void CGui::ChampsListUpdate()
43 {
44 const char clrCh[8][8] = {
45 // 0 tutorial 1 tutorial hard // 2 normal 3 hard 4 very hard // 5 scenery 6 scenery2 7 test
46 "#FFFFA0", "#E0E000", "#A0F0FF", "#60C0FF", "#A0A0E0", "#80FF80", "#A0D080", "#909090" };
47
48 liChamps->removeAllItems(); int n=1; size_t sel = ITEM_NONE;
49 int p = pSet->gui.champ_rev ? 1 : 0;
50 for (int i=0; i < data->champs->all.size(); ++i,++n)
51 {
52 const Champ& ch = data->champs->all[i];
53 if (pSet->inMenu == MNU_Tutorial && ch.type == pSet->tut_type ||
54 pSet->inMenu == MNU_Champ && ch.type - 2 == pSet->champ_type)
55 {
56 const ProgressChamp& pc = progress[p].chs[i];
57 int ntrks = pc.trks.size(), ct = pc.curTrack;
58 const String& clr = clrCh[ch.type];
59
60 liChamps->addItem(""/*clr+ toStr(n/10)+toStr(n%10)*/, n); int l = liChamps->getItemCount()-1;
61 liChamps->setSubItemNameAt(1,l, clr+ ch.name.c_str());
62 liChamps->setSubItemNameAt(2,l, gcom->clrsDiff[ch.diff]+ TR("#{Diff"+toStr(ch.diff)+"}"));
63
64 liChamps->setSubItemNameAt(3,l, gcom->clrsDiff[std::min(8,ntrks*2/3+1)]+ iToStr(ntrks,3));
65 liChamps->setSubItemNameAt(4,l, gcom->clrsDiff[std::min(8,int(ch.time/3.f/60.f))]+" "+ StrTime2(ch.time));
66 liChamps->setSubItemNameAt(5,l, ct == 0 || ct == ntrks ? "" :
67 clr+ fToStr(100.f * ct / ntrks,0,3)+" %");
68
69 liChamps->setSubItemNameAt(6,l, pc.points > 0.f ? clr+ fToStr(pc.points,1,5) : "");
70 if (n-1 == pSet->gui.champ_num) sel = l;
71 } }
72 liChamps->setIndexSelected(sel);
73 }
74
75 /// upd dim champ,chall,stages lists ----------
updChampListDim()76 void CGui::updChampListDim()
77 {
78 const IntCoord& wi = app->mWndGame->getCoord();
79
80 // Champs -----
81 if (!liChamps) return;
82 int c,w;
83
84 int sum = 0, cnt = liChamps->getColumnCount(), sw = 0;
85 for (c=0; c < cnt; ++c) sum += colCh[c];
86 for (c=0; c < cnt; ++c)
87 {
88 w = c==cnt-1 ? 18 : float(colCh[c]) / sum * 0.76/*width*/ * wi.width * 0.97/*frame*/;
89 liChamps->setColumnWidthAt(c, w); sw += w;
90 }
91 int xt = 0.03*wi.width, yt = 0.10*wi.height; // pos
92 liChamps->setCoord(xt, yt, sw + 8/*frame*/, 0.40/*height*/*wi.height);
93 liChamps->setVisible(!isChallGui());
94
95 // Stages -----
96 if (!liStages) return;
97
98 sum = 0; cnt = liStages->getColumnCount(); sw = 0;
99 for (c=0; c < cnt; ++c) sum += colSt[c]; sum += 43;//-
100 for (c=0; c < cnt; ++c)
101 {
102 w = c==cnt-1 ? 18 : float(colSt[c]) / sum * 0.58/*width*/ * wi.width * 0.97/**/;
103 liStages->setColumnWidthAt(c, w); sw += w;
104 }
105 liStages->setCoord(xt, yt, sw + 8/**/, 0.50/*height*/*wi.height);
106 liStages->setVisible(true);
107
108 // Challs -----
109 if (!liChalls) return;
110
111 sum = 0; cnt = liChalls->getColumnCount(); sw = 0;
112 for (c=0; c < cnt; ++c) sum += colChL[c];
113 for (c=0; c < cnt; ++c)
114 {
115 w = c==cnt-1 ? 18 : float(colChL[c]) / sum * 0.76/*width*/ * wi.width * 0.97/**/;
116 liChalls->setColumnWidthAt(c, w); sw += w;
117 }
118 xt = 0.03*wi.width, yt = 0.10*wi.height; // pos
119 liChalls->setCoord(xt, yt, sw + 8/**/, 0.40/*height*/*wi.height);
120 liChalls->setVisible(isChallGui());
121 }
122
123
124 /// Championships list sel changed, fill Stages list
125 //----------------------------------------------------------------------------------------------------------------------
listChampChng(MyGUI::MultiList2 * chlist,size_t id)126 void CGui::listChampChng(MyGUI::MultiList2* chlist, size_t id)
127 {
128 if (id==ITEM_NONE || liChamps->getItemCount() == 0) return;
129
130 // fill stages
131 liStages->removeAllItems();
132
133 int pos = *liChamps->getItemDataAt<int>(id)-1;
134 if (pos < 0 || pos >= data->champs->all.size()) { LogO("Error champ sel > size."); return; }
135
136 int n = 1, p = pSet->gui.champ_rev ? 1 : 0;
137 const Champ& ch = data->champs->all[pos];
138 int ntrks = ch.trks.size();
139 for (int i=0; i < ntrks; ++i,++n)
140 {
141 const ChampTrack& trk = ch.trks[i];
142 float po = progress[p].chs[pos].trks[i].points;
143 StageListAdd(n, trk.name, trk.laps, po > 0.f ? "#E0F0FF"+fToStr(po,1,3) : "");
144 }
145 if (edChDesc) edChDesc->setCaption(ch.descr);
146
147
148 // champ details -----------------------------------
149 String s1,s2,clr; int i;
150 for (i=0; i<1; ++i) {
151 s1 += "\n"; s2 += "\n"; }
152
153 clr = gcom->clrsDiff[ch.diff];
154 s1 += clr+ TR("#{Difficulty}\n"); s2 += clr+ TR("#{Diff"+toStr(ch.diff)+"}")+"\n";
155
156 clr = gcom->clrsDiff[std::min(8,ntrks*2/3+1)];
157 s1 += clr+ TR("#{Tracks}\n"); s2 += clr+ toStr(ntrks)+"\n";
158
159 s1 += "\n"; s2 += "\n";
160 clr = gcom->clrsDiff[std::min(8,int(ch.time/3.f/60.f))];
161 s1 += TR("#80F0E0#{Time} [#{TimeMS}.]\n"); s2 += "#C0FFE0"+clr+ StrTime2(ch.time)+"\n";
162
163 s1 += "\n\n"; s2 += "\n\n";
164 int cur = progress[p].chs[pos].curTrack, all = data->champs->all[pos].trks.size();
165 s1 += TR("#B0C0E0#{Progress}\n"); s2 += "#B0D0F0"+(cur == all ? TR("#{Finished}").asUTF8() : fToStr(100.f * cur / all,0,3)+" %")+"\n";
166 s1 += TR("#D8C0FF#{Score}\n"); s2 += "#F0D8FF"+fToStr(progress[p].chs[pos].points,1,5)+"\n";
167
168 txtCh->setCaption(s1); valCh->setCaption(s2);
169 for (i=0; i<3; ++i) {
170 txtChP[i]->setCaption(""); valChP[i]->setCaption(""); }
171
172 // btn start
173 s1 = cur == all ? TR("#{Restart}") : (cur == 0 ? TR("#{Start}") : TR("#{Continue}"));
174 if (pSet->inMenu == MNU_Tutorial)
175 btStTut->setCaption(s1);
176 else btStChamp->setCaption(s1);
177 btChRestart->setVisible(cur > 0);
178 }
179
180
181 /// champ start
182 //---------------------------------------------------------------------
btnChampStart(WP)183 void CGui::btnChampStart(WP)
184 {
185 if (liChamps->getIndexSelected()==ITEM_NONE) return;
186 pSet->gui.chall_num = -1;
187 pSet->gui.champ_num = *liChamps->getItemDataAt<int>(liChamps->getIndexSelected())-1;
188
189 // if already finished, restart - will loose progress and scores ..
190 int chId = pSet->gui.champ_num, p = pSet->game.champ_rev ? 1 : 0;
191 LogO("|| Starting champ: "+toStr(chId)+(p?" rev":""));
192 ProgressChamp& pc = progress[p].chs[chId];
193 if (pc.curTrack == pc.trks.size())
194 {
195 LogO("|| Was at 100%, restarting progress.");
196 pc.curTrack = 0; //pc.score = 0.f;
197 }
198 // change btn caption to start/continue/restart ?..
199
200 btnNewGame(0);
201 }
202
203 /// stage start / end
204 //----------------------------------------------------------------------------------------------------------------------
btnChampStageStart(WP)205 void CGui::btnChampStageStart(WP)
206 {
207 // check if champ ended
208 int chId = pSet->game.champ_num, p = pSet->game.champ_rev ? 1 : 0;
209 ProgressChamp& pc = progress[p].chs[chId];
210 const Champ& ch = data->champs->all[chId];
211 bool last = pc.curTrack == ch.trks.size();
212
213 pGame->timer.end_sim = false;
214 LogO("|| This was stage " + toStr(pc.curTrack) + "/" + toStr(ch.trks.size()) + " btn");
215 if (last)
216 {
217 // show end window, todo: start particles..
218 app->mWndChampStage->setVisible(false);
219
220 // tutorial, tutorial hard, normal, hard, very hard, scenery, test
221 bool tut = ch.isTut();
222 const int ui[8] = {0,1,2,3,4,5,0,0};
223 if (imgChampEndCup)
224 imgChampEndCup->setImageCoord(IntCoord(ui[std::min(7, std::max(0, ch.type))]*128,0,128,256));
225
226 app->mWndChampEnd->setCaption(TR(tut ? "#{Tutorial}" : "#{Championship}"));
227 txChampEndF->setCaption(TR(tut ? "#{TutorEndFinished}" : "#{ChampEndFinished}"));
228
229 app->mWndChampEnd->setVisible(true);
230
231 /// sound //)
232 if (iChSnd < 0)
233 pGame->snd_fail->start();
234 else
235 pGame->snd_win[iChSnd]->start(); //)
236
237 return;
238 }
239
240 bool finished = pGame->timer.GetLastLap(0) > 0.f; //?-
241 if (finished)
242 {
243 LogO("|| Loading next stage.");
244 app->mWndChampStage->setVisible(false);
245 btnNewGame(0);
246 }else
247 {
248 LogO("|| Starting stage.");
249 app->mWndChampStage->setVisible(false);
250 pGame->pause = false;
251 pGame->timer.waiting = false;
252 }
253 }
254
255 // stage back
btnChampStageBack(WP)256 void CGui::btnChampStageBack(WP)
257 {
258 app->mWndChampStage->setVisible(false);
259 app->isFocGui = true; // show back gui
260 toggleGui(false);
261 }
262
263 // champ end
btnChampEndClose(WP)264 void CGui::btnChampEndClose(WP)
265 {
266 app->mWndChampEnd->setVisible(false);
267 }
268
269
270 /// save progress and update it on gui
ProgressSave(bool upgGui)271 void CGui::ProgressSave(bool upgGui)
272 {
273 progress[0].SaveXml(PATHMANAGER::UserConfigDir() + "/progress.xml");
274 progress[1].SaveXml(PATHMANAGER::UserConfigDir() + "/progress_rev.xml");
275 if (!upgGui)
276 return;
277 ChampsListUpdate();
278 listChampChng(liChamps, liChamps->getIndexSelected());
279 }
280
281
282 /// championship advance logic
283 // caution: called from GAME, 2nd thread, no Ogre stuff here
284 //----------------------------------------------------------------------------------------------------------------------
ChampionshipAdvance(float timeCur)285 void CGui::ChampionshipAdvance(float timeCur)
286 {
287 int chId = pSet->game.champ_num, p = pSet->game.champ_rev ? 1 : 0;
288 ProgressChamp& pc = progress[p].chs[chId];
289 const Champ& ch = data->champs->all[chId];
290 const ChampTrack& trk = ch.trks[pc.curTrack];
291 LogO("|| --- Champ end: " + ch.name);
292
293 /// compute track poins --------------
294 float timeTrk = data->tracks->times[trk.name];
295 if (timeTrk < 1.f)
296 { LogO("|| Error: Track has no best time !"); timeTrk = 10.f; }
297 timeTrk *= trk.laps;
298
299 LogO("|| Track: " + trk.name);
300 LogO("|| Your time: " + toStr(timeCur));
301 LogO("|| Best time: " + toStr(timeTrk));
302
303 float carMul = app->GetCarTimeMul(pSet->game.car[0], pSet->game.sim_mode);
304 float points = 0.f; int pos;
305
306 #if 1 // test score +- sec diff
307 for (int i=-2; i <= 4; ++i)
308 {
309 pos = app->GetRacePos(timeCur + i*2.f, timeTrk, carMul, true, &points);
310 LogO("|| var, add time: "+toStr(i*2)+" sec, points: "+fToStr(points,2));
311 }
312 #endif
313 pos = app->GetRacePos(timeCur, timeTrk, carMul, true, &points);
314
315 float pass = (pSet->game.sim_mode == "normal") ? 5.f : 2.f; ///..
316 bool passed = points >= pass; // didnt qualify, repeat current stage
317
318 LogO("|| Points: " + fToStr(points,1) + " pos: " + toStr(pos) + " Passed: " + (passed ? "yes":"no"));
319 pc.trks[pc.curTrack].points = points;
320
321 // -------------- advance --------------
322 bool last = pc.curTrack+1 == ch.trks.size();
323 LogO("|| This was stage " + toStr(pc.curTrack+1) + "/" + toStr(ch.trks.size()));
324
325 pGame->pause = true;
326 pGame->timer.waiting = true;
327 pGame->timer.end_sim = true;
328
329 // show stage end [window]
330 ChampFillStageInfo(true); // cur track
331 app->mWndChampStage->setVisible(true);
332
333 // sound //)
334 if (passed)
335 pGame->snd_stage->start();
336 else
337 pGame->snd_fail->start(); //)
338
339
340 if (!last || (last && !passed))
341 {
342 if (passed)
343 pc.curTrack++; // next stage
344
345 ProgressSave();
346 }else
347 { // champ ended
348 /// compute champ :score: --------------
349 int ntrk = pc.trks.size(); float sum = 0.f;
350 for (int t=0; t < ntrk; ++t)
351 sum += pc.trks[t].points;
352
353 pc.curTrack++; // end = 100 %
354 //float old = pc.score; // .. save only higher ?
355 pc.points = sum / ntrk; // average from all tracks
356
357 ProgressSave();
358
359 // save which sound to play //)
360 if (!passed)
361 iChSnd = -1;
362 else
363 iChSnd = std::min(2, std::max(0, ch.diff / 3));
364
365 LogO("|| Champ finished");
366 LogO("|| Total points: " + toStr(points));
367
368 // upd champ end [window]
369 String s =
370 TR(ch.isTut() ? /*"#{Tutorial}"*/"" : "#{Championship}: ") + ch.name + "\n" +
371 TR("#{TotalScore}") + ": " + fToStr(pc.points,1,5);
372 edChampEnd->setCaption(s);
373 //mWndChampEnd->setVisible(true); // show after stage end
374 }
375 }
376
377
378 // stage wnd text
379 //----------------------------------------------------------------------------------------------------------------------
ChampFillStageInfo(bool finished)380 void CGui::ChampFillStageInfo(bool finished)
381 {
382 int chId = pSet->game.champ_num, p = pSet->game.champ_rev ? 1 : 0;
383 ProgressChamp& pc = progress[p].chs[chId];
384 const Champ& ch = data->champs->all[chId];
385 const ChampTrack& trk = ch.trks[pc.curTrack];
386 bool last = pc.curTrack+1 == ch.trks.size();
387
388 String s;
389 s = "#80FFE0"+ ch.name + "\n\n" +
390 "#80FFC0"+ TR("#{Stage}") + ": " + toStr(pc.curTrack+1) + " / " + toStr(ch.trks.size()) + "\n" +
391 "#80FF80"+ TR("#{Track}") + ": " + trk.name + "\n\n";
392 app->mWndChampStage->setCaption(TR(ch.isTut() ? "#{Tutorial}" : "#{Championship}"));
393
394 if (!finished) // track info at start
395 {
396 int id = data->tracks->trkmap[trk.name];
397 if (id > 0)
398 {
399 const TrackInfo* ti = &data->tracks->trks[id-1];
400 s += "#A0D0FF"+ TR("#{Difficulty}: ") + gcom->clrsDiff[ti->diff] + TR("#{Diff"+toStr(ti->diff)+"}") + "\n";
401 if (app->scn->road)
402 { Real len = app->scn->road->st.Length*0.001f * (pSet->show_mph ? 0.621371f : 1.f);
403 s += "#A0D0FF"+ TR("#{Distance}: ") + "#B0E0FF" +
404 fToStr(len, 1,4) + (pSet->show_mph ? TR(" #{UnitMi}") : TR(" #{UnitKm}")) + "\n\n";
405 s += "#A8B8C8"+ app->scn->road->sTxtDesc;
406 } }
407 }
408
409 if (finished)
410 {
411 float points = pc.trks[pc.curTrack].points;
412 float pass = (pSet->game.sim_mode == "normal") ? 5.f : 2.f; ///..
413 s += "#80C0FF"+TR("#{Finished}") + ".\n" +
414 "#FFFF60"+TR("#{TBPoints}") + ": " + fToStr(points,1,5) + "\n";
415 s += "#80C0FF"+TR("#{Needed}") + ": " + fToStr(pass,1,5) + "\n\n";
416
417 bool passed = points >= pass;
418 if (passed)
419 s += "#00FF00"+TR("#{Passed}")+".\n"+TR(last ? "#{Continue}" : "#{NextStage}.");
420 else
421 s += "#FF8000"+TR("#{DidntPass}")+".\n"+TR("#{RepeatStage}.");
422 }
423 edChampStage->setCaption(s);
424 btChampStage->setCaption(finished ? TR("#{Continue}") : TR("#{Start}"));
425
426 // preview image at start
427 if (!finished)
428 {
429 String path = gcom->PathListTrkPrv(0, trk.name);
430 app->prvStCh.Load(path+"view.jpg");
431 }
432 }
433