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 "../road/Road.h"
10 #include "CGame.h"
11 #include "CHud.h"
12 #include "CGui.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 ///
BackFromChs()22 void CGui::BackFromChs()
23 {
24 pSet->gui.champ_num = -1;
25 pSet->gui.chall_num = -1;
26 //pChall = 0;
27 //CarListUpd(); // off filtering
28 }
29
isChallGui()30 bool CGui::isChallGui()
31 {
32 //return imgChall && imgChall->getVisible();
33 return pSet->inMenu == MNU_Challenge;
34 }
35
tabChallType(Tab wp,size_t id)36 void CGui::tabChallType(Tab wp, size_t id)
37 {
38 pSet->chall_type = id;
39 ChallsListUpdate();
40 }
41
42
43 /// Challenges list fill
44 //----------------------------------------------------------------------------------------------------------------------
ChallsListUpdate()45 void CGui::ChallsListUpdate()
46 {
47 const char clrCh[8][8] = {
48 // 0 Rally 1 Scenery 2 Endurance 3 Chase 4 Stunts 5 Extreme 6 Special 7 Test
49 "#A0D0FF","#80FF80","#C0FF60","#FFC060","#FF8080","#C0A0E0", "#60B0FF","#909090" };
50
51 liChalls->removeAllItems(); int n=1; size_t sel = ITEM_NONE;
52 int p = pSet->gui.champ_rev ? 1 : 0;
53 for (int i=0; i < data->chall->all.size(); ++i,++n)
54 {
55 const Chall& chl = data->chall->all[i];
56 if (chl.type == pSet->chall_type)
57 {
58 const ProgressChall& pc = progressL[p].chs[i];
59 int ntrks = pc.trks.size(), ct = pc.curTrack;
60 const String& clr = clrCh[chl.type];
61 //String cars = data->carsXml.colormap[chl.ci->type]; if (cars.length() != 7) clr = "#C0D0E0";
62
63 liChalls->addItem(""/*clr+ toStr(n/10)+toStr(n%10)*/, n); int l = liChalls->getItemCount()-1;
64 liChalls->setSubItemNameAt(1,l, clr+ chl.name.c_str());
65 liChalls->setSubItemNameAt(2,l, gcom->clrsDiff[chl.diff]+ TR("#{Diff"+toStr(chl.diff)+"}"));
66 liChalls->setSubItemNameAt(3,l, StrChallCars(chl));
67
68 liChalls->setSubItemNameAt(4,l, gcom->clrsDiff[std::min(8,ntrks*2/3+1)]+ iToStr(ntrks,3));
69 liChalls->setSubItemNameAt(5,l, gcom->clrsDiff[std::min(8,int(chl.time/3.f/60.f))]+ StrTime2(chl.time));
70 liChalls->setSubItemNameAt(6,l, ct == 0 || ct == ntrks ? "" :
71 clr+ fToStr(100.f * ct / ntrks,0,3)+" %");
72
73 liChalls->setSubItemNameAt(7,l, " "+ StrPrize(pc.fin+1));
74 liChalls->setSubItemNameAt(8,l, clr+ (pc.fin >= 0 ? fToStr(pc.avgPoints,1,5) : ""));
75 if (n-1 == pSet->gui.chall_num) sel = l;
76 } }
77 liChalls->setIndexSelected(sel);
78 }
79
80
81 /// Challenges list sel changed, fill Stages list
82 //----------------------------------------------------------------------------------------------------------------------
listChallChng(MyGUI::MultiList2 * chlist,size_t id)83 void CGui::listChallChng(MyGUI::MultiList2* chlist, size_t id)
84 {
85 if (id==ITEM_NONE || liChalls->getItemCount() == 0) return;
86
87 int nch = *liChalls->getItemDataAt<int>(id)-1;
88 if (nch < 0 || nch >= data->chall->all.size()) { LogO("Error chall sel > size."); return; }
89
90 CarListUpd(); // filter car list
91
92 // fill stages
93 liStages->removeAllItems();
94
95 int n = 1, p = pSet->gui.champ_rev ? 1 : 0;
96 const Chall& ch = data->chall->all[nch];
97 int ntrks = ch.trks.size();
98 for (int i=0; i < ntrks; ++i,++n)
99 {
100 const ChallTrack& trk = ch.trks[i];
101 float po = progressL[p].chs[nch].trks[i].points;
102 StageListAdd(n, trk.name, trk.laps, po > 0.f ? "#E0F0FF"+fToStr(po,1,3) : "");
103 }
104 if (edChDesc) edChDesc->setCaption(ch.descr);
105
106 UpdChallDetail(nch);
107 }
108
109
110 // list allowed cars types and cars
StrChallCars(const Chall & ch)111 String CGui::StrChallCars(const Chall& ch)
112 {
113 String str;
114 int i,s;
115
116 s = ch.carTypes.size();
117 for (i=0; i < s; ++i)
118 {
119 const String& ct = ch.carTypes[i];
120 str += data->cars->colormap[ct]; // car type color
121 str += ct;
122 if (i+1 < s) str += ",";
123 }
124 //int id = data->carsXml.carmap[*i];
125 //data->carsXml.cars[id-1];
126 if (!str.empty())
127 str += " ";
128
129 s = ch.cars.size();
130 for (i=0; i < s; ++i)
131 {
132 const String& c = ch.cars[i];
133 int id = data->cars->carmap[c]-1; // get car color from type
134 if (id >= 0) str += data->cars->colormap[ data->cars->cars[id].type ];
135 str += c;
136 if (i+1 < s) str += ",";
137 }
138 return str;
139 }
140
141 // test if car is in challenge allowed cars or types
IsChallCar(String name)142 bool CGui::IsChallCar(String name)
143 {
144 if (!liChalls || liChalls->getIndexSelected()==ITEM_NONE) return true;
145
146 int chId = *liChalls->getItemDataAt<int>(liChalls->getIndexSelected())-1;
147 const Chall& ch = data->chall->all[chId];
148
149 int i,s;
150 if (!ch.carTypes.empty())
151 { s = ch.carTypes.size();
152
153 int id = data->cars->carmap[name]-1;
154 if (id >= 0)
155 {
156 String type = data->cars->cars[id].type;
157
158 for (i=0; i < s; ++i)
159 if (type == ch.carTypes[i]) return true;
160 } }
161 if (!ch.cars.empty())
162 { s = ch.cars.size();
163
164 for (i=0; i < s; ++i)
165 if (name == ch.cars[i]) return true;
166 }
167 return false;
168 }
169
170
171 /// chall start
172 //---------------------------------------------------------------------
btnChallStart(WP)173 void CGui::btnChallStart(WP)
174 {
175 if (liChalls->getIndexSelected()==ITEM_NONE) return;
176 pSet->gui.champ_num = -1;
177 pSet->gui.chall_num = *liChalls->getItemDataAt<int>(liChalls->getIndexSelected())-1;
178
179 // if already finished, restart - will loose progress and scores ..
180 int chId = pSet->gui.chall_num, p = pSet->game.champ_rev ? 1 : 0;
181 LogO("|] Starting chall: "+toStr(chId)+(p?" rev":""));
182 ProgressChall& pc = progressL[p].chs[chId];
183 if (pc.curTrack == pc.trks.size())
184 {
185 LogO("|] Was at 100%, restarting progress.");
186 pc.curTrack = 0; //pc.score = 0.f;
187 }
188 // change btn caption to start/continue/restart ?..
189
190 btnNewGame(0);
191 }
192
193 /// stage start / end
194 //----------------------------------------------------------------------------------------------------------------------
btnChallStageStart(WP)195 void CGui::btnChallStageStart(WP)
196 {
197 // check if chall ended
198 int chId = pSet->game.chall_num, p = pSet->game.champ_rev ? 1 : 0;
199 ProgressChall& pc = progressL[p].chs[chId];
200 const Chall& ch = data->chall->all[chId];
201 bool last = pc.curTrack == ch.trks.size();
202
203 LogO("|] This was stage " + toStr(pc.curTrack) + "/" + toStr(ch.trks.size()) + " btn");
204 if (last)
205 { // show end window, todo: start particles..
206 app->mWndChallStage->setVisible(false);
207 // tutorial, tutorial hard, normal, hard, very hard, scenery, test
208 const int ui[8] = {0,1,2,3,4,5,0,0};
209 //if (imgChallEnd)
210 // imgChallEnd->setImageCoord(IntCoord(ui[std::min(7, std::max(0, ch.type))]*128,0,128,256));
211 app->mWndChallEnd->setVisible(true);
212
213 /// sounds //)
214 if (iChSnd < 0)
215 pGame->snd_fail->start();
216 else
217 pGame->snd_win[iChSnd]->start(); //)
218 return;
219 }
220
221 bool finished = pGame->timer.GetLastLap(0) > 0.f; //?-
222 if (finished)
223 {
224 LogO("|] Loading next stage.");
225 app->mWndChallStage->setVisible(false);
226 btnNewGame(0);
227 }else
228 {
229 LogO("|] Starting stage.");
230 app->mWndChallStage->setVisible(false);
231 pGame->pause = false;
232 pGame->timer.waiting = false;
233 pGame->timer.end_sim = false;
234 }
235 }
236
237 // stage back
btnChallStageBack(WP)238 void CGui::btnChallStageBack(WP)
239 {
240 app->mWndChallStage->setVisible(false);
241 app->isFocGui = true; // show back gui
242 toggleGui(false);
243 }
244
245 // chall end
btnChallEndClose(WP)246 void CGui::btnChallEndClose(WP)
247 {
248 app->mWndChallEnd->setVisible(false);
249 }
250
251
252 /// save progressL and update it on gui
ProgressLSave(bool upgGui)253 void CGui::ProgressLSave(bool upgGui)
254 {
255 progressL[0].SaveXml(PATHMANAGER::UserConfigDir() + "/progressL.xml");
256 progressL[1].SaveXml(PATHMANAGER::UserConfigDir() + "/progressL_rev.xml");
257 if (!upgGui)
258 return;
259 ChallsListUpdate();
260 listChallChng(liChalls, liChalls->getIndexSelected());
261 }
262
263
264 /// challenge advance logic
265 // caution: called from GAME, 2nd thread, no Ogre stuff here
266 //----------------------------------------------------------------------------------------------------------------------
ChallengeAdvance(float timeCur)267 void CGui::ChallengeAdvance(float timeCur/*total*/)
268 {
269 int chId = pSet->game.chall_num, p = pSet->game.champ_rev ? 1 : 0;
270 ProgressChall& pc = progressL[p].chs[chId];
271 ProgressTrackL& pt = pc.trks[pc.curTrack];
272 const Chall& ch = data->chall->all[chId];
273 const ChallTrack& trk = ch.trks[pc.curTrack];
274 LogO("|] --- Chall end: " + ch.name);
275
276 /// compute track poins --------------
277 float timeTrk = data->tracks->times[trk.name];
278 if (timeTrk < 1.f)
279 { LogO("|] Error: Track has no best time !"); timeTrk = 10.f; }
280 timeTrk *= trk.laps;
281
282 LogO("|] Track: " + trk.name);
283 LogO("|] Your time: " + toStr(timeCur));
284 LogO("|] Best time: " + toStr(timeTrk));
285
286 float carMul = app->GetCarTimeMul(pSet->game.car[0], pSet->game.sim_mode);
287 float points = 0.f; int pos = 0;
288
289 #if 1 // test score +- sec diff
290 for (int i=-2; i <= 2; ++i)
291 {
292 pos = app->GetRacePos(timeCur + i*2.f, timeTrk, carMul, true, &points);
293 LogO("|] var, add time: "+toStr(i*2)+" sec, points: "+fToStr(points,2));
294 }
295 #endif
296 pos = app->GetRacePos(timeCur, timeTrk, carMul, true, &points);
297
298 pt.time = timeCur; pt.points = points; pt.pos = pos;
299
300
301 /// Pass Stage --------------
302 bool passed = true, pa;
303 if (trk.timeNeeded > 0.f)
304 {
305 pa = pt.time <= trk.timeNeeded;
306 LogO("]] TotTime: " + StrTime(pt.time) + " Needed: " + StrTime(trk.timeNeeded) + " Passed: " + (pa ? "yes":"no"));
307 passed &= pa;
308 }
309 if (trk.passPoints > 0.f)
310 {
311 pa = pt.points >= trk.passPoints;
312 LogO("]] Points: " + fToStr(pt.points,1) + " Needed: " + fToStr(trk.passPoints,1) + " Passed: " + (pa ? "yes":"no"));
313 passed &= pa;
314 }
315 if (trk.passPos > 0)
316 {
317 pa = pt.pos <= trk.passPos;
318 LogO("]] Pos: " + toStr(pt.pos) + " Needed: " + toStr(trk.passPos) + " Passed: " + (pa ? "yes":"no"));
319 passed &= pa;
320 }
321 LogO(String("]] Passed total: ") + (passed ? "yes":"no"));
322
323
324 // -------------- advance --------------
325 bool last = pc.curTrack+1 == ch.trks.size();
326 LogO("|] This was stage " + toStr(pc.curTrack+1) + "/" + toStr(ch.trks.size()));
327
328 pGame->pause = true;
329 pGame->timer.waiting = true;
330 pGame->timer.end_sim = true;
331
332 // show stage end [window]
333 ChallFillStageInfo(true); // cur track
334 app->mWndChallStage->setVisible(true);
335
336 // sound //)
337 if (passed)
338 pGame->snd_stage->start();
339 else
340 pGame->snd_fail->start(); //)
341
342
343 if (!last || (last && !passed))
344 {
345 if (pc.curTrack == 0) // save picked car
346 pc.car = pSet->game.car[0];
347
348 if (passed)
349 pc.curTrack++; // next stage
350
351 ProgressLSave();
352 return;
353 }
354
355
356 // challenge end
357 //-----------------------------------------------------------------------------------------------
358
359 // compute avg
360 float avgPos = 0.f, avgPoints = 0.f, totalTime = 0.f;
361 int ntrks = pc.trks.size();
362 for (int t=0; t < ntrks; ++t)
363 {
364 const ProgressTrackL& pt = pc.trks[t];
365 totalTime += pt.time; avgPoints += pt.points; avgPos += pt.pos;
366 }
367 avgPoints /= ntrks; avgPos /= ntrks;
368
369 // save
370 pc.curTrack++;
371 pc.totalTime = totalTime; pc.avgPoints = avgPoints; pc.avgPos = avgPos;
372
373 LogO("|] Chall finished");
374 String s = "\n\n"+
375 TR("#C0D0F0#{Challenge}") + ": #C0D0FF" + ch.name +"\n";
376 #define sPass(pa) (pa ? TR(" #00FF00#{Passed}") : TR(" #FF8000#{DidntPass}"))
377
378
379 /// Pass Challenge --------------
380 String ss;
381 passed = true;
382 int prize = -1, pp = ch.prizes;
383
384 // time 1:00 ---------------
385 if (ch.totalTime > 0.f)
386 {
387 pa = pc.totalTime <= ch.totalTime;
388 // for p <= pp ..
389
390 LogO("]] TotalTime: "+StrTime(pc.totalTime)+" Needed: "+StrTime(ch.totalTime)+" Passed: "+(pa ? "yes":"no"));
391 ss += TR("#D8C0FF#{TBTime}")+": "+StrTime(pc.totalTime)+" / "+StrTime(ch.totalTime) + sPass(pa) +"\n";
392 passed &= pa;
393 }
394
395 // position 1st ---------------
396 if (ch.avgPos > 0.f)
397 {
398 ss += TR("#D8C0FF#{TBPosition}")+": "+fToStr(pc.avgPos,2,5)+" /";
399 String sp; bool pa0;
400 for (p=0; p <= pp; ++p)
401 {
402 float pass = ch.avgPos + ciAddPos[p] * ch.factor;
403 pa = pc.avgPos <= pass;
404 if (pa && p > prize) prize = p;
405
406 LogO("]] AvgPos: "+fToStr(pc.avgPos,1)+" Needed: "+fToStr(pass,1)+" Prize: "+toStr(p)+" Passed: "+(pa ? "yes":"no"));
407 sp += " "+clrPrize[2-pp+ p+1]+ fToStr(pass,1,3);
408 if (p == 0)
409 { passed &= pa; pa0 = pa; }
410 }
411 ss += sp +" "+ sPass(pa0) +"\n";
412 }
413
414 // points 10.0 ---------------
415 if (ch.avgPoints > 0.f)
416 {
417 ss += TR("#D8C0FF#{TBPoints}")+": "+fToStr(pc.avgPoints,2,5)+" /";
418 String sp; bool pa0;
419 for (p=0; p <= pp; ++p)
420 {
421 float pass = ch.avgPoints - cfSubPoints[p] * ch.factor;
422 pa = pc.avgPoints >= pass;
423 if (pa && p > prize) prize = p;
424
425 LogO("]] AvgPoints: "+fToStr(pc.avgPoints,1)+" Needed: "+fToStr(pass,1)+" Prize: "+toStr(p)+" Passed: "+(pa ? "yes":"no"));
426 sp = " "+clrPrize[2-pp+ p+1]+ fToStr(pass,1,3) + sp;
427 if (p == 0)
428 { passed &= pa; pa0 = pa; } // lost if didn't pass worst prize
429 }
430 ss += sp +" "+ sPass(pa0) +"\n";
431 }else //if (passed) // write points always on end
432 ss += TR("#C0E0FF#{TBPoints}")+": "+fToStr(pc.avgPoints,2,5) /*+ sPass(pa)*/ +"\n";
433
434 LogO(String("]] Passed total: ") + (passed ? "yes":"no") +" Prize: "+toStr(prize));
435
436
437 // end
438 pc.fin = passed ? prize : -1;
439 if (passed)
440 s += TR("\n#E0F0F8#{Prize}: ") + StrPrize(pc.fin+1)+"\n";
441 s += "\n"+ss;
442
443 ProgressLSave();
444
445 // save which sound to play //)
446 if (!passed)
447 iChSnd = -1;
448 else
449 iChSnd = std::min(2, std::max(0, prize-1)); // ch.diff ?
450
451
452 // upd chall end [window]
453 imgChallFail->setVisible(!passed);
454 imgChallCup->setVisible( passed); const int ui[8] = {2,3,4};
455 imgChallCup->setImageCoord(IntCoord(ui[std::min(2, std::max(0, pc.fin))]*128,0,128,256));
456
457 txChallEndC->setCaption(passed ? TR("#{ChampEndCongrats}") : "");
458 txChallEndF->setCaption(passed ? TR("#{ChallEndFinished}") : TR("#{Finished}"));
459
460 edChallEnd->setCaption(s);
461 //ap->mWndChallEnd->setVisible(true); // show after stage end
462
463 LogO("|]");
464 }
465
466
467 // Prize const * * *
468 const String
469 CGui::clrPrize[4] = {"","#D0B050","#D8D8D8","#E8E050"},
470 CGui::strPrize[4] = {"","#{Bronze}","#{Silver}","#{Gold}"};
471
472 // lowering pass req
473 const int CGui::ciAddPos[3] = {4,2,0};
474 const float CGui::cfSubPoints[3] = {2.f,1.f,0.f};
475
StrPrize(int i)476 const String CGui::StrPrize(int i) //0..3
477 {
478 return clrPrize[i] + TR(strPrize[i]);
479 }
480
481
482 // stage wnd text
483 //----------------------------------------------------------------------------------------------------------------------
ChallFillStageInfo(bool finished)484 void CGui::ChallFillStageInfo(bool finished)
485 {
486 int chId = pSet->game.chall_num, p = pSet->game.champ_rev ? 1 : 0;
487 const ProgressChall& pc = progressL[p].chs[chId];
488 const ProgressTrackL& pt = pc.trks[pc.curTrack];
489 const Chall& ch = data->chall->all[chId];
490 const ChallTrack& trk = ch.trks[pc.curTrack];
491 bool last = pc.curTrack+1 == ch.trks.size();
492
493 String s =
494 "#80FFE0"+ TR("#{Challenge}") + ": " + ch.name + "\n\n" +
495 "#80FFC0"+ TR("#{Stage}") + ": " + toStr(pc.curTrack+1) + " / " + toStr(ch.trks.size()) + "\n" +
496 "#80FF80"+ TR("#{Track}") + ": " + trk.name + "\n\n";
497
498 if (!finished) // track info at start
499 {
500 int id = data->tracks->trkmap[trk.name];
501 if (id > 0)
502 {
503 const TrackInfo* ti = &data->tracks->trks[id-1];
504 s += "#A0D0FF"+ TR("#{Difficulty}: ") + gcom->clrsDiff[ti->diff] + TR("#{Diff"+toStr(ti->diff)+"}") + "\n";
505 if (app->scn->road)
506 { Real len = app->scn->road->st.Length*0.001f * (pSet->show_mph ? 0.621371f : 1.f);
507 s += "#A0D0FF"+ TR("#{Distance}: ") + "#B0E0FF" +
508 fToStr(len, 1,4) + (pSet->show_mph ? TR(" #{UnitMi}") : TR(" #{UnitKm}")) + "\n\n";
509 } }
510 }
511
512 if (finished) // stage
513 {
514 s += "#80C0FF"+TR("#{Finished}.") + "\n\n";
515
516 /// Pass Stage --------------
517 bool passed = true, pa;
518 if (trk.timeNeeded > 0.f)
519 {
520 pa = pt.time <= trk.timeNeeded;
521 s += TR("#D8C0FF#{TBTime}: ") + StrTime(pt.time) + " / " + StrTime(trk.timeNeeded) + sPass(pa) +"\n";
522 passed &= pa;
523 }
524 if (trk.passPoints > 0.f)
525 {
526 pa = pt.points >= trk.passPoints;
527 s += TR("#D8C0FF#{TBPoints}: ") + fToStr(pt.points,1) + " / " + fToStr(trk.passPoints,1) + sPass(pa) +"\n";
528 passed &= pa;
529 }
530 if (trk.passPos > 0)
531 {
532 pa = pt.pos <= trk.passPos;
533 s += TR("#D8C0FF#{TBPosition}: ") + toStr(pt.pos) + " / " + toStr(trk.passPos) + sPass(pa) +"\n";
534 passed &= pa;
535 }
536
537 if (passed) s += "\n\n"+TR(last ? "#00FF00#{Continue}." : "#00FF00#{NextStage}.");
538 else s += "\n\n"+TR("#FF6000#{RepeatStage}.");
539 }
540 else
541 { /// Pass needed --------------
542 s += "#F0F060"+TR("#{Needed}") +"\n";
543 if (trk.timeNeeded > 0.f) s += TR(" #D8C0FF#{TBTime}: ") + StrTime(trk.timeNeeded) +"\n";
544 if (trk.passPoints > 0.f) s += TR(" #D8C0FF#{TBPoints}: ") + fToStr(trk.passPoints,1) +"\n";
545 if (trk.passPos > 0) s += TR(" #D8C0FF#{TBPosition}: ") + toStr(trk.passPos) +"\n";
546 if (app->scn->road) s += "\n#A8B8C8"+ app->scn->road->sTxtDesc;
547 }
548
549 edChallStage->setCaption(s);
550 btChallStage->setCaption(finished ? TR("#{Continue}") : TR("#{Start}"));
551
552 // preview image at start
553 if (!finished)
554 {
555 String path = gcom->PathListTrkPrv(0, trk.name);
556 app->prvStCh.Load(path+"view.jpg");
557 }
558 }
559
560
561 // chall details (gui tab Stages)
562 //----------------------------------------------------------------------------------------------------------------------
UpdChallDetail(int id)563 void CGui::UpdChallDetail(int id)
564 {
565 const Chall& ch = data->chall->all[id];
566 int ntrks = ch.trks.size();
567 int p = pSet->gui.champ_rev ? 1 : 0;
568
569 String s1,s2,clr;
570 //s1 += "\n"; s2 += "\n";
571
572 // track --------
573 clr = gcom->clrsDiff[ch.diff];
574 s1 += clr+ TR("#{Difficulty}\n"); s2 += clr+ TR("#{Diff"+toStr(ch.diff)+"}")+"\n";
575
576 clr = gcom->clrsDiff[std::min(8,ntrks*2/3+1)];
577 s1 += clr+ TR("#{Tracks}\n"); s2 += clr+ toStr(ntrks)+"\n";
578
579 //s1 += "\n"; s2 += "\n";
580 clr = gcom->clrsDiff[std::min(8,int(ch.time/3.f/60.f))];
581 s1 += TR("#80F0E0#{Time} [#{TimeMS}.]\n"); s2 += "#C0FFE0"+clr+ StrTime2(ch.time)+"\n";
582
583 // cars --------
584 s1 += "\n"; s2 += "\n";
585 s1 += TR("#F08080#{Vehicles}\n"); s2 += "#FFA0A0" + StrChallCars(ch)+"\n";
586 if (ch.carChng)
587 { s1 += TR("#C0B0B0#{CarChange}\n"); s2 += TR("#A0B8A0#{Allowed}")+"\n"; }
588
589
590 // game --------
591 s1 += "\n"; s2 += "\n";
592 s1 += TR("#D090E0#{Game}")+"\n"; s2 += "\n";
593 #define cmbs(cmb, i) (i>=0 ? cmb->getItemNameAt(i) : TR("#{Any}"))
594 s1 += TR("#A0B0C0 #{Simulation}\n"); s2 += "#B0C0D0"+ ch.sim_mode +"\n";
595 s1 += TR("#A090E0 #{Damage}\n"); s2 += "#B090FF"+ cmbs(cmbDamage, ch.damage_type) +"\n";
596 s1 += TR("#B080C0 #{InputMapRewind}\n"); s2 += "#C090D0"+ cmbs(cmbRewind, ch.rewind_type) +"\n";
597 //s1 += "\n"; s2 += "\n";
598 s1 += TR("#80C0FF #{Boost}\n"); s2 += "#90D0FF"+ cmbs(cmbBoost, ch.boost_type) +"\n";
599 s1 += TR("#6098A0 #{Flip}\n"); s2 += "#7098A0"+ cmbs(cmbFlip, ch.flip_type) +"\n";
600
601 // hud --------
602 //s1 += "\n"; s2 += "\n";
603 //bool minimap, chk_arr, chk_beam, trk_ghost; // deny using it if false
604
605 txtCh->setCaption(s1); valCh->setCaption(s2);
606
607
608 // pass challenge --------
609 s1 = ""; s2 = "";
610 if (ch.totalTime > 0.f || ch.avgPoints > 0.f || ch.avgPos > 0.f)
611 {
612 s1 += "\n"; s2 += "\n"; int p, pp = ch.prizes;
613 s1 += TR("#F0F060#{Needed} - #{Challenge}")+"\n"; s2 += "\n";
614 s1 += "#D8C0FF"; s2 += "#F0D8FF";
615 if (ch.avgPoints > 0.f){ s1 += TR(" #{TBPoints}\n");
616 for (p=0; p <= pp; ++p) s2 += clrPrize[2-pp+ p+1]+
617 fToStr(ch.avgPoints - cfSubPoints[p] * ch.factor ,1,3)+" ";
618 s2 += "\n"; }
619 if (ch.avgPos > 0.f) { s1 += TR(" #{TBPosition}\n");
620 for (p=0; p <= pp; ++p) s2 += clrPrize[2-pp+ p+1]+
621 fToStr(ch.avgPos + ciAddPos[p] * ch.factor ,1,3)+" ";
622 s2 += "\n"; }
623 if (ch.totalTime > 0.f){ s1 += TR(" #{TBTime}\n");
624 s2 += StrTime(ch.totalTime)+"\n"; }
625 }
626 txtChP[1]->setCaption(s1); valChP[1]->setCaption(s2);
627
628 // pass stage --------
629 s1 = ""; s2 = "";
630 size_t t = liStages->getIndexSelected();
631 if (t != ITEM_NONE)
632 {
633 const ChallTrack& trk = ch.trks[t];
634 if (trk.timeNeeded > 0.f || trk.passPoints > 0.f || trk.passPos > 0)
635 {
636 s1 += "\n"; s2 += "\n";
637 s1 += TR("#FFC060#{Needed} - #{Stage}")+"\n"; s2 += "\n";
638 s1 += "#D8C0FF"; s2 += "#F0D8FF";
639 if (trk.passPoints > 0.f){ s1 += TR(" #{TBPoints}\n"); s2 += fToStr(trk.passPoints,2,5)+"\n"; }
640 if (trk.passPos > 0.f) { s1 += TR(" #{TBPosition}\n"); s2 += fToStr(trk.passPos,2,5)+"\n"; }
641 if (trk.timeNeeded > 0.f){ s1 += TR(" #{TBTime}\n"); s2 += StrTime(trk.timeNeeded)+"\n"; }
642 } }
643 txtChP[0]->setCaption(s1); valChP[0]->setCaption(s2);
644
645
646 // progress --------
647 s1 = ""; s2 = "";
648 const ProgressChall& pc = progressL[p].chs[id];
649 int cur = pc.curTrack, all = data->chall->all[id].trks.size();
650 if (cur > 0)
651 {
652 s1 += TR("#B0FFFF#{Progress}\n"); s2 += "#D0FFFF"+(cur == all ? TR("#{Finished}").asUTF8() : fToStr(100.f * cur / all,0,3)+" %")+"\n";
653 s1 += TR("#F8FCFF#{Prize}\n"); s2 += StrPrize(pc.fin+1)+"\n";
654 #define clrP(b) if (b) { s1 += "#C8D0F0"; s2 += "#E0F0FF"; }else{ s1 += "#80A0C0"; s2 += "#90B0D0"; }
655 s1 += "\n"; s2 += "\n"; clrP(ch.avgPoints > 0.f);
656 s1 += TR(" #{TBPoints}\n"); s2 += fToStr(pc.avgPoints,2,5)+"\n"; clrP(ch.avgPos > 0.f);
657 s1 += TR(" #{TBPosition}\n"); s2 += fToStr(pc.avgPos,2,5)+"\n"; clrP(ch.totalTime > 0.f);
658 s1 += TR(" #{TBTime}\n"); s2 += StrTime(pc.totalTime)+"\n";
659 }
660 txtChP[2]->setCaption(s1); valChP[2]->setCaption(s2);
661
662
663 // btn start
664 s1 = cur == all ? TR("#{Restart}") : (cur == 0 ? TR("#{Start}") : TR("#{Continue}"));
665 btStChall->setCaption(s1);
666 btChRestart->setVisible(cur > 0);
667 }
668