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 "../vdrift/pathmanager.h"
7 #include "../vdrift/game.h"
8 #include "../road/Road.h"
9 #include "CGame.h"
10 #include "CHud.h"
11 #include "CGui.h"
12 #include "common/MultiList2.h"
13 using namespace std;
14 using namespace Ogre;
15 using namespace MyGUI;
16
17
18 ///______________________________________________________________________________________________
19 ///
20 /// load championship or challenge track
21 ///______________________________________________________________________________________________
Ch_NewGame()22 void App::Ch_NewGame()
23 {
24 if (pSet->game.champ_num >= (int)data->champs->all.size() ||
25 pSet->game.chall_num >= (int)data->chall->all.size()) // range
26 { pSet->game.champ_num = -1;
27 pSet->game.chall_num = -1; }
28
29 pGame->timer.end_sim = false;
30 int iChamp = pSet->game.champ_num;
31 int iChall = pSet->game.chall_num;
32 if (iChall >= 0)
33 {
34 /// challenge stage
35 int p = pSet->game.champ_rev ? 1 : 0;
36 ProgressChall& pc = gui->progressL[p].chs[iChall];
37 Chall& chl = data->chall->all[iChall];
38 if (pc.curTrack >= chl.trks.size()) pc.curTrack = 0; // restart
39 const ChallTrack& trk = chl.trks[pc.curTrack];
40 gui->pChall = &chl; // set
41
42 pSet->game.track = trk.name; pSet->game.track_user = 0;
43 pSet->game.trackreverse = pSet->game.champ_rev ? !trk.reversed : trk.reversed;
44 pSet->game.num_laps = trk.laps;
45
46 pSet->game.sim_mode = chl.sim_mode;
47 pSet->game.damage_type = chl.damage_type;
48 pSet->game.damage_dec = chl.dmg_lap;
49
50 pSet->game.boost_type = chl.boost_type;
51 pSet->game.flip_type = chl.flip_type;
52 pSet->game.rewind_type = chl.rewind_type;
53 pSet->game.BoostDefault(); //
54
55 // car not set, and not allowed in chall
56 if (!gui->IsChallCar(pSet->game.car[0])) // pick last
57 { int cnt = gui->carList->getItemCount();
58 if (cnt > 0)
59 pSet->game.car[0] = gui->carList->getItemNameAt(std::min(0,cnt-1)).substr(7);
60 else
61 { LogO("Error: Challenge cars empty!"); return; }
62 }
63 // set picked car when continuing
64 if (pc.curTrack > 0 && !pc.car.empty() && !chl.carChng)
65 pSet->game.car[0] = pc.car;
66
67 //TODO: ?challenge icons near denied combos,chkboxes
68
69 pSet->game.trees = 1.5f; //-
70 pSet->game.collis_veget = true;
71 pSet->game.dyn_objects = true; //-
72
73 pGame->pause = true; // wait for stage wnd close
74 pGame->timer.waiting = true;
75 }
76 else if (iChamp >= 0)
77 {
78 /// championship stage
79 int p = pSet->game.champ_rev ? 1 : 0;
80 ProgressChamp& pc = gui->progress[p].chs[iChamp];
81 const Champ& ch = data->champs->all[iChamp];
82 if (pc.curTrack >= ch.trks.size()) pc.curTrack = 0; // restart
83 const ChampTrack& trk = ch.trks[pc.curTrack];
84 pSet->game.track = trk.name; pSet->game.track_user = 0;
85 pSet->game.trackreverse = pSet->game.champ_rev ? !trk.reversed : trk.reversed;
86 pSet->game.num_laps = trk.laps;
87
88 pSet->game.boost_type = 1; // from trk.?
89 pSet->game.flip_type = 2;
90 pSet->game.rewind_type = 1;
91 pSet->game.BoostDefault(); //
92 //pSet->game.damage_dec = 40.f; //?
93 //pSet->game.trees = 1.f; // >=1 ?
94 //pSet->game.collis_veget = true;
95
96 pGame->pause = true; // wait for stage wnd close
97 pGame->timer.waiting = true;
98 }else
99 { pGame->pause = false; // single race
100 pGame->timer.waiting = false;
101 }
102 }
103
104
105 /// car time mul
106 //-----------------------------------------------------------------------------------------------
GetCarTimeMul(const string & car,const string & sim_mode)107 float App::GetCarTimeMul(const string& car, const string& sim_mode)
108 {
109 // car factor (time mul, for less power)
110 float carMul = 1.f;
111 int id = data->cars->carmap[car];
112 if (id > 0)
113 { const CarInfo& ci = data->cars->cars[id-1];
114 bool easy = sim_mode == "easy";
115 carMul = easy ? ci.easy : ci.norm;
116 }
117 return carMul;
118 }
119
120 /// compute race position, basing on car and track time
121 //-----------------------------------------------------------------------------------------------
122
GetRacePos(float timeCur,float timeTrk,float carTimeMul,bool coldStart,float * pPoints)123 int App::GetRacePos(float timeCur, float timeTrk, float carTimeMul, bool coldStart, float* pPoints)
124 {
125 // magic factor: seconds needed for 1 second of track time for 1 race place difference
126 // eg. if track time is 3min = 180 sec, then 180*magic = 2.16 sec
127 // and this is the difference between car race positions (1 and 2, 2 and 3 etc)
128 // 0.006 .. 0.0012 // par
129 //float time1pl = magic * timeTrk;
130
131 // if already driving at start, add 1 sec (times are for 1st lap)
132 float timeC = timeCur + (coldStart ? 0 : 1);
133 float time = timeC * carTimeMul;
134
135 float place = (time - timeTrk)/timeTrk / data->cars->magic;
136 // time = (place * magic * timeTrk + timeTrk) / carTimeMul; //todo: show this in lists and hud..
137 if (pPoints)
138 *pPoints = std::max(0.f, (20.f - place) * 0.5f);
139
140 int plc = place < 1.f ? 1 : std::min(30, (int)( floor(place +1.f) ));
141 return plc;
142 }
143
144
145 ///______________________________________________________________________________________________
146 /// Load championships.xml, progress.xml (once)
147 //-----------------------------------------------------------------------------------------------
Ch_XmlLoad()148 void CGui::Ch_XmlLoad()
149 {
150 /* stats */
151 float time = 0.f; int trks = 0;
152 for (std::map<std::string, float>::const_iterator it = data->tracks->times.begin();
153 it != data->tracks->times.end(); ++it)
154 {
155 const string& trk = (*it).first;
156 if (trk.substr(0,4) != "Test")
157 {
158 time += (*it).second;
159 ++trks;
160 } }
161 LogO("Total tracks: "+ toStr(trks) + ", total time: "+ StrTime2(time/60.f)+" h:m");
162
163
164 #if 0 /* test race pos,points */
165 float trk = 100.f;
166 LogO("Test Time "+StrTime(trk)+" Pos Points");
167 for (int i=-5; i <= 20; ++i)
168 {
169 float points = 0.f, t = trk + i*1.f;
170 int pos = GetRacePos(t, trk, 1.0f, true, &points);
171 LogO(" "+StrTime(t)+" "+iToStr(pos,2)+" "+fToStr(points,2,5));
172 }
173 #endif
174
175
176 /// Champs ---------------------------
177 ProgressXml oldprog[2];
178 oldprog[0].LoadXml(PATHMANAGER::UserConfigDir() + "/progress.xml");
179 oldprog[1].LoadXml(PATHMANAGER::UserConfigDir() + "/progress_rev.xml");
180
181 int chs = data->champs->all.size();
182
183 /// this is for old progress ver loading, from game with newer champs
184 /// it resets progress only for champs which ver has changed (or track count)
185 // fill progress
186 for (int pr=0; pr < 2; ++pr)
187 {
188 progress[pr].chs.clear();
189 for (int c=0; c < chs; ++c)
190 {
191 const Champ& ch = data->champs->all[c];
192
193 // find this champ in loaded progress
194 bool found = false; int p = 0;
195 ProgressChamp* opc = 0;
196 while (!found && p < oldprog[pr].chs.size())
197 {
198 opc = &oldprog[pr].chs[p];
199 // same name, ver and trks count
200 if (opc->name == ch.name && opc->ver == ch.ver &&
201 opc->trks.size() == ch.trks.size())
202 found = true;
203 ++p;
204 }
205 if (!found)
206 LogO("|| reset progress for champ: " + ch.name);
207
208 ProgressChamp pc;
209 pc.name = ch.name; pc.ver = ch.ver;
210
211 if (found) // found progress, points
212 { pc.curTrack = opc->curTrack;
213 pc.points = opc->points;
214 }
215
216 // fill tracks
217 for (int t=0; t < ch.trks.size(); ++t)
218 {
219 ProgressTrack pt;
220 if (found) // found track points
221 pt.points = opc->trks[t].points;
222 pc.trks.push_back(pt);
223 }
224
225 progress[pr].chs.push_back(pc);
226 } }
227 ProgressSave(false); //will be later in guiInit
228
229 if (progress[0].chs.size() != data->champs->all.size() ||
230 progress[1].chs.size() != data->champs->all.size())
231 LogO("|| ERROR: champs and progress sizes differ !");
232
233
234 /// Challenges ---------------------------
235 ProgressLXml oldpr[2];
236 oldpr[0].LoadXml(PATHMANAGER::UserConfigDir() + "/progressL.xml");
237 oldpr[1].LoadXml(PATHMANAGER::UserConfigDir() + "/progressL_rev.xml");
238
239 chs = data->chall->all.size();
240
241 /// this is for old progress ver loading, from game with newer challs
242 /// it resets progress only for challs which ver has changed (or track count)
243 // fill progress
244 for (int pr=0; pr < 2; ++pr)
245 {
246 progressL[pr].chs.clear();
247 for (int c=0; c < chs; ++c)
248 {
249 const Chall& ch = data->chall->all[c];
250
251 // find this chall in loaded progress
252 bool found = false; int p = 0;
253 ProgressChall* opc = 0;
254 while (!found && p < oldpr[pr].chs.size())
255 {
256 opc = &oldpr[pr].chs[p];
257 // same name, ver and trks count
258 if (opc->name == ch.name && opc->ver == ch.ver &&
259 opc->trks.size() == ch.trks.size())
260 found = true;
261 ++p;
262 }
263 if (!found)
264 LogO("|| reset progressL for chall: " + ch.name);
265
266 ProgressChall pc;
267 pc.name = ch.name; pc.ver = ch.ver;
268
269 if (found)
270 { // found progress, copy
271 pc.curTrack = opc->curTrack; pc.car = opc->car;
272 pc.avgPoints = opc->avgPoints; pc.totalTime = opc->totalTime;
273 pc.avgPos = opc->avgPos; pc.fin = opc->fin;
274 }
275
276 // fill tracks
277 for (int t=0; t < ch.trks.size(); ++t)
278 {
279 ProgressTrackL pt;
280 if (found)
281 { // found track points
282 const ProgressTrackL& opt = opc->trks[t]; //pt = opt;
283 pt.points = opt.points; pt.time = opt.time; pt.pos = opt.pos;
284 }
285 pc.trks.push_back(pt);
286 }
287
288 progressL[pr].chs.push_back(pc);
289 } }
290 ProgressLSave(false); //will be later in guiInit
291
292 if (progressL[0].chs.size() != data->chall->all.size() ||
293 progressL[1].chs.size() != data->chall->all.size())
294 LogO("|] ERROR: challs and progressL sizes differ !");
295 }
296
297
298 /// upd tutor,champ,chall gui vis
299 //-----------------------------------------------------------------------------------------------
UpdChampTabVis()300 void CGui::UpdChampTabVis()
301 {
302 if (!liChamps || !tabChamp || !btStChamp) return;
303 static int oldMenu = pSet->inMenu;
304 bool tutor = pSet->inMenu == MNU_Tutorial, champ = pSet->inMenu == MNU_Champ, chall = pSet->inMenu == MNU_Challenge;
305 bool any = tutor || champ || chall;
306
307 tabTut->setVisible(tutor); imgTut->setVisible(tutor); btStTut->setVisible(tutor);
308 tabChamp->setVisible(champ); imgChamp->setVisible(champ); btStChamp->setVisible(champ);
309 tabChall->setVisible(chall); imgChall->setVisible(chall); btStChall->setVisible(chall);
310 btNewGameCar->setVisible(!any);
311
312 liChamps->setVisible(!chall); liChamps->setColour(tutor ? Colour(0.85,0.8,0.75) : Colour(0.75,0.8,0.85));
313 liChalls->setVisible( chall); liChalls->setColour(Colour(0.74,0.7,0.82));
314 panCh->setColour(tutor ? Colour(0.9,0.8,0.7) : champ ? Colour(0.7,0.9,0.8) : Colour(0.77,0.75,0.92));
315
316 if (oldMenu != pSet->inMenu && any)
317 { oldMenu = pSet->inMenu;
318 if (chall) ChallsListUpdate();
319 else ChampsListUpdate();
320 }
321 //if (pSet->inMenu == MNU_Single)
322 // BackFromChs();
323
324 if (edChInfo->getVisible()) // info texts
325 edChInfo->setCaption(
326 chall ? TR("#{ChallInfo2}")+"\n"+TR("#{ChallInfo}") :
327 tutor ? TR("#{TutorInfo}")+"\n"+TR("#{ChampInfo}") :
328 TR("#{ChampInfo2}")+"\n"+TR("#{ChampInfo}"));
329
330 btChRestart->setVisible(false);
331 }
332
btnChampInfo(WP)333 void CGui::btnChampInfo(WP)
334 {
335 pSet->champ_info = !pSet->champ_info;
336 if (edChInfo) edChInfo->setVisible(pSet->champ_info);
337 }
338
339
340 /// add item in stages list
341 //-----------------------------------------------------------------------------------------------
StageListAdd(int n,String name,int laps,String progress)342 void CGui::StageListAdd(int n, String name, int laps, String progress)
343 {
344 String clr = gcom->GetSceneryColor(name);
345 liStages->addItem(clr+ toStr(n/10)+toStr(n%10), 0); int l = liStages->getItemCount()-1;
346 liStages->setSubItemNameAt(1,l, clr+ name.c_str());
347
348 int id = data->tracks->trkmap[name]-1; if (id < 0) return;
349 const TrackInfo& ti = data->tracks->trks[id];
350
351 float carMul = app->GetCarTimeMul(pSet->game.car[0], pSet->game.sim_mode);
352 float time = (data->tracks->times[name] * laps /*laps > 1 -1*/) / carMul;
353
354 liStages->setSubItemNameAt(2,l, clr+ ti.scenery);
355 liStages->setSubItemNameAt(3,l, gcom->clrsDiff[ti.diff]+ TR("#{Diff"+toStr(ti.diff)+"}"));
356 liStages->setSubItemNameAt(4,l, "#60C0A0 "+toStr(laps));
357 liStages->setSubItemNameAt(5,l, "#80C0F0 "+StrTime2(time));
358 liStages->setSubItemNameAt(6,l, progress);
359 }
360
361 /// Stages list sel changed, update Track info
362 //-----------------------------------------------------------------------------------------------
listStageChng(MyGUI::MultiList2 * li,size_t pos)363 void CGui::listStageChng(MyGUI::MultiList2* li, size_t pos)
364 {
365 if (valStageNum) valStageNum->setVisible(pos!=ITEM_NONE);
366 if (pos==ITEM_NONE) return;
367
368 string trk; bool rev=false; int all=1;
369 if (isChallGui())
370 { if (liChalls->getIndexSelected()==ITEM_NONE) return;
371 int nch = *liChalls->getItemDataAt<int>(liChalls->getIndexSelected())-1;
372 if (nch >= data->chall->all.size()) { LogO("Error chall sel > size."); return; }
373
374 const Chall& ch = data->chall->all[nch];
375 if (pos >= ch.trks.size()) { LogO("Error stage sel > tracks."); return; }
376 trk = ch.trks[pos].name; rev = ch.trks[pos].reversed; all = ch.trks.size();
377
378 UpdChallDetail(nch); // stage pass upd txt
379 }else
380 { if (liChamps->getIndexSelected()==ITEM_NONE) return;
381 int nch = *liChamps->getItemDataAt<int>(liChamps->getIndexSelected())-1;
382 if (nch >= data->champs->all.size()) { LogO("Error champ sel > size."); return; }
383
384 const Champ& ch = data->champs->all[nch];
385 if (pos >= ch.trks.size()) { LogO("Error stage sel > tracks."); return; }
386 trk = ch.trks[pos].name; rev = ch.trks[pos].reversed; all = ch.trks.size();
387 }
388 if (pSet->gui.champ_rev) rev = !rev;
389
390 if (valTrkNet) valTrkNet->setCaption(TR("#{Track}: ") + trk);
391 ReadTrkStatsChamp(trk, rev);
392 if (valStageNum) valStageNum->setCaption(toStr(pos+1) +" / "+ toStr(all));
393 }
394
395
396 // stage loaded
Ch_LoadEnd()397 void CGui::Ch_LoadEnd()
398 {
399 if (pSet->game.champ_num >= 0)
400 {
401 ChampFillStageInfo(false);
402 app->mWndChampStage->setVisible(true);
403 }
404 if (pSet->game.chall_num >= 0)
405 {
406 ChallFillStageInfo(false);
407 app->mWndChallStage->setVisible(true);
408 }
409 }
410
411 // Stages gui tab
btnStageNext(WP)412 void CGui::btnStageNext(WP)
413 {
414 size_t id = liStages->getIndexSelected(), all = liStages->getItemCount();
415 if (all == 0) return;
416 if (id == ITEM_NONE) id = 0;
417 else
418 id = (id +1) % all;
419 liStages->setIndexSelected(id);
420 listStageChng(liStages, id);
421 }
422
btnStagePrev(WP)423 void CGui::btnStagePrev(WP)
424 {
425 size_t id = liStages->getIndexSelected(), all = liStages->getItemCount();
426 if (all == 0) return;
427 if (id == ITEM_NONE) id = 0;
428 id = (id + all -1) % all;
429 liStages->setIndexSelected(id);
430 listStageChng(liStages, id);
431 }
432
433
434 // restart progress curtrack
btnChRestart(WP)435 void CGui::btnChRestart(WP)
436 {
437 int p = pSet->game.champ_rev ? 1 : 0;
438 if (pSet->inMenu == MNU_Tutorial || pSet->inMenu == MNU_Champ)
439 {
440 if (liChamps->getIndexSelected()==ITEM_NONE) return;
441 int chId = *liChamps->getItemDataAt<int>(liChamps->getIndexSelected())-1;
442 ProgressChamp& pc = progress[p].chs[chId];
443 pc.curTrack = 0; ChampsListUpdate();
444 }
445 else if (pSet->inMenu == MNU_Challenge)
446 {
447 if (liChalls->getIndexSelected()==ITEM_NONE) return;
448 int chId = *liChalls->getItemDataAt<int>(liChalls->getIndexSelected())-1;
449 ProgressChall& pc = progressL[p].chs[chId];
450 pc.curTrack = 0; ChallsListUpdate();
451 }
452 }
453