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