42 #include "ThemeModel.h" |
44 #include "ThemeModel.h" |
43 |
45 |
44 // last game info |
46 // last game info |
45 QList<QVariant> lastGameStartArgs = QList<QVariant>(); |
47 QList<QVariant> lastGameStartArgs = QList<QVariant>(); |
46 GameType lastGameType = gtNone; |
48 GameType lastGameType = gtNone; |
47 QString lastTrainingSubFolder = NULL; |
|
48 GameCFGWidget * lastGameCfg = NULL; |
49 GameCFGWidget * lastGameCfg = NULL; |
49 QString lastGameAmmo = NULL; |
50 QString lastGameAmmo = NULL; |
50 TeamSelWidget * lastGameTeamSel = NULL; |
51 TeamSelWidget * lastGameTeamSel = NULL; |
51 |
52 |
52 QString training, campaign, campaignScript, campaignTeam; // TODO: Cleaner solution? |
53 QString trainingName, trainingScript, trainingTeam, campaign, campaignScript, campaignTeam; // TODO: Cleaner solution? |
53 |
54 |
54 HWGame::HWGame(GameUIConfig * config, GameCFGWidget * gamecfg, QString ammo, TeamSelWidget* pTeamSelWidget) : |
55 HWGame::HWGame(GameUIConfig * config, GameCFGWidget * gamecfg, QString ammo, TeamSelWidget* pTeamSelWidget) : |
55 TCPBase(true, 0), |
56 TCPBase(true, !config->language().isEmpty(), 0), |
56 ammostr(ammo), |
57 ammostr(ammo), |
57 m_pTeamSelWidget(pTeamSelWidget) |
58 m_pTeamSelWidget(pTeamSelWidget) |
58 { |
59 { |
59 this->config = config; |
60 this->config = config; |
60 this->gamecfg = gamecfg; |
61 this->gamecfg = gamecfg; |
73 SetGameState(gsDestroyed); |
74 SetGameState(gsDestroyed); |
74 } |
75 } |
75 |
76 |
76 void HWGame::onClientDisconnect() |
77 void HWGame::onClientDisconnect() |
77 { |
78 { |
78 switch (gameType) |
79 if (demoIsPresent) |
79 { |
80 { |
80 case gtDemo: |
81 switch (gameType) |
81 // for video recording we need demo anyway |
82 { |
82 emit HaveRecord(rtNeither, demo); |
83 case gtDemo: |
83 break; |
84 // for video recording we need demo anyway |
84 case gtNet: |
85 emit HaveRecord(rtNeither, demo); |
85 emit HaveRecord(rtDemo, demo); |
86 break; |
86 break; |
87 case gtNet: |
87 default: |
|
88 if (gameState == gsInterrupted || gameState == gsHalted) |
|
89 emit HaveRecord(rtSave, demo); |
|
90 else if (gameState == gsFinished) |
|
91 emit HaveRecord(rtDemo, demo); |
88 emit HaveRecord(rtDemo, demo); |
92 else |
89 break; |
93 emit HaveRecord(rtNeither, demo); |
90 default: |
|
91 if (gameState == gsInterrupted || gameState == gsHalted) |
|
92 emit HaveRecord(rtSave, demo); |
|
93 else if (gameState == gsFinished) |
|
94 emit HaveRecord(rtDemo, demo); |
|
95 else |
|
96 emit HaveRecord(rtNeither, demo); |
|
97 } |
|
98 } |
|
99 else |
|
100 { |
|
101 emit HaveRecord(rtNeither, demo); |
94 } |
102 } |
95 SetGameState(gsStopped); |
103 SetGameState(gsStopped); |
96 } |
104 } |
97 |
105 |
98 void HWGame::commonConfig() |
106 void HWGame::commonConfig() |
137 commonConfig(); |
145 commonConfig(); |
138 } |
146 } |
139 |
147 |
140 void HWGame::SendQuickConfig() |
148 void HWGame::SendQuickConfig() |
141 { |
149 { |
|
150 /* Load and increase Quick Game experience level. |
|
151 Experience increases by 1 for each started game and maxes out |
|
152 at 20. Low experience levels will introduce a "beginner's bias" to make |
|
153 the first quick games easier and simpler. The max. possible difficulty |
|
154 increases progressively the longer you play. |
|
155 If experience is maxed out, the beginner's bias is gone and quick games |
|
156 are completely random. */ |
|
157 int exp = config->quickGameExperience(); |
|
158 if(exp < 20) |
|
159 { |
|
160 config->setQuickGameExperience(exp + 1); |
|
161 } |
|
162 qDebug("Starting quick game ..."); |
|
163 qDebug("Quick Game experience level: %d", exp); |
|
164 |
|
165 // Init stuff |
142 QByteArray teamscfg; |
166 QByteArray teamscfg; |
143 QAbstractItemModel * themeModel = DataManager::instance().themeModel()->withoutHidden(); |
167 QAbstractItemModel * themeModel = DataManager::instance().themeModel()->withoutHidden(); |
144 |
168 |
145 HWProto::addStringToBuffer(teamscfg, "TL"); |
169 HWProto::addStringToBuffer(teamscfg, "TL"); |
|
170 |
|
171 // Random seed |
|
172 HWProto::addStringToBuffer(teamscfg, "eseed " + QUuid::createUuid().toString()); |
|
173 |
|
174 int r, minhogs, maxhogs; |
|
175 |
|
176 // Random map type |
|
177 r = rand() % 10000; |
|
178 if(r < 3000) { // 30% |
|
179 // Random |
|
180 r = 0; |
|
181 } else if(r < 5250) { // 22.5% |
|
182 // Maze |
|
183 if(exp <= 3) |
|
184 r = 0; |
|
185 else |
|
186 r = 1; |
|
187 } else if(r < 7490) { // 22.4% |
|
188 // Perlin |
|
189 if(exp <= 7) |
|
190 r = 1; |
|
191 else |
|
192 r = 2; |
|
193 } else if(r < 7500 && exp >= 5) { // 0.1% |
|
194 // Floating Flowers (just for fun) |
|
195 r = 5; |
|
196 } else if(r < 8750) { // 12.5% |
|
197 // Image map |
|
198 r = 3; |
|
199 } else { // 12.5% |
|
200 // Forts |
|
201 r = 4; |
|
202 } |
|
203 switch(r) |
|
204 { |
|
205 // Random map |
|
206 default: |
|
207 case 0: { |
|
208 r = rand() % 3; |
|
209 if(r == 0) |
|
210 { |
|
211 // small island |
|
212 HWProto::addStringToBuffer(teamscfg, "e$template_filter 1"); |
|
213 minhogs = 3; |
|
214 maxhogs = 4; |
|
215 } |
|
216 else if(r == 1 || exp <= 6) |
|
217 { |
|
218 // medium island |
|
219 HWProto::addStringToBuffer(teamscfg, "e$template_filter 2"); |
|
220 minhogs = 4; |
|
221 maxhogs = 5; |
|
222 } |
|
223 else |
|
224 { |
|
225 // cave (locked at low experience because these maps can be huge) |
|
226 HWProto::addStringToBuffer(teamscfg, "e$template_filter 4"); |
|
227 minhogs = 4; |
|
228 maxhogs = 6; |
|
229 } |
|
230 HWProto::addStringToBuffer(teamscfg, "e$feature_size "+QString::number(rand()%18+4)); |
|
231 break; |
|
232 } |
|
233 // Maze |
|
234 case 1: { |
|
235 minhogs = 4; |
|
236 maxhogs = 6; |
|
237 HWProto::addStringToBuffer(teamscfg, "e$mapgen 1"); |
|
238 HWProto::addStringToBuffer(teamscfg, "e$template_filter "+QString::number(rand()%6)); |
|
239 HWProto::addStringToBuffer(teamscfg, "e$feature_size "+QString::number(rand()%16+6)); |
|
240 break; |
|
241 } |
|
242 // Perlin |
|
243 case 2: { |
|
244 minhogs = 4; |
|
245 maxhogs = 6; |
|
246 HWProto::addStringToBuffer(teamscfg, "e$mapgen 2"); |
|
247 HWProto::addStringToBuffer(teamscfg, "e$template_filter "+QString::number(rand()%6)); |
|
248 HWProto::addStringToBuffer(teamscfg, "e$feature_size "+QString::number(rand()%18+4)); |
|
249 break; |
|
250 } |
|
251 // Image map |
|
252 case 3: { |
|
253 minhogs = 4; |
|
254 maxhogs = 6; |
|
255 HWProto::addStringToBuffer(teamscfg, "e$mapgen 3"); |
|
256 // Select map from hardcoded list. |
|
257 // TODO: find a more dynamic solution. |
|
258 r = rand() % cQuickGameMaps.count(); |
|
259 HWProto::addStringToBuffer(teamscfg, "e$map " + cQuickGameMaps[r]); |
|
260 break; |
|
261 } |
|
262 // Forts |
|
263 case 4: { |
|
264 minhogs = 4; |
|
265 maxhogs = 6; |
|
266 HWProto::addStringToBuffer(teamscfg, "e$mapgen 4"); |
|
267 HWProto::addStringToBuffer(teamscfg, "e$feature_size "+QString::number(rand()%20+1)); |
|
268 break; |
|
269 } |
|
270 // Floating Flowers |
|
271 // (actually empty map; this forces the engine to generate fallback structures to have |
|
272 // something for hogs to stand on) |
|
273 case 5: { |
|
274 minhogs = 4; |
|
275 maxhogs = 8; |
|
276 HWProto::addStringToBuffer(teamscfg, "e$mapgen 3"); |
|
277 HWProto::addStringToBuffer(teamscfg, "e$feature_size "+QString::number(rand()%4+3)); |
|
278 break; |
|
279 } |
|
280 } |
|
281 |
|
282 // Theme |
146 HWProto::addStringToBuffer(teamscfg, QString("etheme %1") |
283 HWProto::addStringToBuffer(teamscfg, QString("etheme %1") |
147 .arg((themeModel->rowCount() > 0) ? themeModel->index(rand() % themeModel->rowCount(), 0).data(ThemeModel::ActualNameRole).toString() : "Nature")); |
284 .arg((themeModel->rowCount() > 0) ? themeModel->index(rand() % themeModel->rowCount(), 0).data(ThemeModel::ActualNameRole).toString() : "Nature")); |
148 HWProto::addStringToBuffer(teamscfg, "eseed " + QUuid::createUuid().toString()); |
285 |
149 |
286 int hogs = minhogs + rand() % (maxhogs-minhogs+1); |
150 HWProto::addStringToBuffer(teamscfg, "e$template_filter 2"); |
287 // Cap hog count at low experience |
151 HWProto::addStringToBuffer(teamscfg, "e$feature_size "+QString::number(rand()%18+4)); |
288 if((exp <= 8) && (hogs > 5)) |
152 |
289 hogs = 5; |
|
290 else if((exp <= 5) && (hogs > 4)) |
|
291 hogs = 4; |
|
292 |
|
293 // Teams |
|
294 // Player team |
153 HWTeam team1; |
295 HWTeam team1; |
154 team1.setDifficulty(0); |
296 team1.setDifficulty(0); |
155 team1.setColor(0); |
297 team1.setColor(0); |
156 team1.setNumHedgehogs(4); |
298 team1.setNumHedgehogs(hogs); |
157 HWNamegen::teamRandomEverything(team1); |
299 HWNamegen::teamRandomEverything(team1); |
158 team1.setVoicepack("Default"); |
300 team1.setVoicepack("Default_qau"); |
159 HWProto::addStringListToBuffer(teamscfg, |
301 |
160 team1.teamGameConfig(100)); |
302 // Computer team |
161 |
|
162 HWTeam team2; |
303 HWTeam team2; |
163 team2.setDifficulty(4); |
304 // Random difficulty. |
|
305 // Max. possible difficulty is capped at low experience levels. |
|
306 if(exp >= 15) // very easy to very hard (full range) |
|
307 r = 5 - rand() % 5; |
|
308 else if(exp >= 9) // very easy to hard |
|
309 r = 5 - rand() % 4; |
|
310 else if(exp >= 6) // very easy to medium |
|
311 r = 5 - rand() % 3; |
|
312 else if(exp >= 2) // very easy to easy |
|
313 r = 5 - rand() % 2; |
|
314 else // very easy |
|
315 r = 5; |
|
316 team2.setDifficulty(r); |
164 team2.setColor(1); |
317 team2.setColor(1); |
165 team2.setNumHedgehogs(4); |
318 team2.setNumHedgehogs(hogs); |
|
319 // Make sure the team names are not equal |
166 do |
320 do |
167 HWNamegen::teamRandomEverything(team2); |
321 HWNamegen::teamRandomEverything(team2); |
168 while(!team2.name().compare(team1.name()) || !team2.hedgehog(0).Hat.compare(team1.hedgehog(0).Hat)); |
322 while(!team2.name().compare(team1.name()) || !team2.hedgehog(0).Hat.compare(team1.hedgehog(0).Hat)); |
169 team2.setVoicepack("Default"); |
323 team2.setVoicepack("Default_qau"); |
170 HWProto::addStringListToBuffer(teamscfg, |
324 |
171 team2.teamGameConfig(100)); |
325 // Team play order |
172 |
326 r = rand() % 2; |
|
327 if(r == 0 || exp <= 4) // player plays first |
|
328 { |
|
329 HWProto::addStringListToBuffer(teamscfg, team1.teamGameConfig(100)); |
|
330 HWProto::addStringListToBuffer(teamscfg, team2.teamGameConfig(100)); |
|
331 } |
|
332 else // computer plays first |
|
333 { |
|
334 HWProto::addStringListToBuffer(teamscfg, team2.teamGameConfig(100)); |
|
335 HWProto::addStringListToBuffer(teamscfg, team1.teamGameConfig(100)); |
|
336 } |
|
337 |
|
338 // Ammo scheme "Default" |
|
339 // TODO: Random schemes |
173 HWProto::addStringToBuffer(teamscfg, QString("eammloadt %1").arg(cDefaultAmmoStore->mid(0, cAmmoNumber))); |
340 HWProto::addStringToBuffer(teamscfg, QString("eammloadt %1").arg(cDefaultAmmoStore->mid(0, cAmmoNumber))); |
174 HWProto::addStringToBuffer(teamscfg, QString("eammprob %1").arg(cDefaultAmmoStore->mid(cAmmoNumber, cAmmoNumber))); |
341 HWProto::addStringToBuffer(teamscfg, QString("eammprob %1").arg(cDefaultAmmoStore->mid(cAmmoNumber, cAmmoNumber))); |
175 HWProto::addStringToBuffer(teamscfg, QString("eammdelay %1").arg(cDefaultAmmoStore->mid(2 * cAmmoNumber, cAmmoNumber))); |
342 HWProto::addStringToBuffer(teamscfg, QString("eammdelay %1").arg(cDefaultAmmoStore->mid(2 * cAmmoNumber, cAmmoNumber))); |
176 HWProto::addStringToBuffer(teamscfg, QString("eammreinf %1").arg(cDefaultAmmoStore->mid(3 * cAmmoNumber, cAmmoNumber))); |
343 HWProto::addStringToBuffer(teamscfg, QString("eammreinf %1").arg(cDefaultAmmoStore->mid(3 * cAmmoNumber, cAmmoNumber))); |
177 HWProto::addStringToBuffer(teamscfg, QString("eammstore")); |
344 HWProto::addStringToBuffer(teamscfg, QString("eammstore")); |
182 |
349 |
183 void HWGame::SendTrainingConfig() |
350 void HWGame::SendTrainingConfig() |
184 { |
351 { |
185 QByteArray traincfg; |
352 QByteArray traincfg; |
186 HWProto::addStringToBuffer(traincfg, "TL"); |
353 HWProto::addStringToBuffer(traincfg, "TL"); |
|
354 |
|
355 HWTeam missionTeam = HWTeam(); |
|
356 missionTeam.setName(config->Form->ui.pageTraining->CBTeam->currentText()); |
|
357 missionTeam.loadFromFile(); |
|
358 missionTeam.setNumHedgehogs(HEDGEHOGS_PER_TEAM); |
|
359 missionTeam.setMissionTeam(true); |
|
360 HWProto::addStringListToBuffer(traincfg, missionTeam.teamGameConfig(100)); |
|
361 |
187 HWProto::addStringToBuffer(traincfg, "eseed " + QUuid::createUuid().toString()); |
362 HWProto::addStringToBuffer(traincfg, "eseed " + QUuid::createUuid().toString()); |
188 HWProto::addStringToBuffer(traincfg, "escript " + training); |
363 HWProto::addStringToBuffer(traincfg, "escript " + trainingScript); |
189 |
364 |
190 RawSendIPC(traincfg); |
365 RawSendIPC(traincfg); |
191 } |
366 } |
192 |
367 |
193 void HWGame::SendCampaignConfig() |
368 void HWGame::SendCampaignConfig() |
194 { |
369 { |
195 QByteArray campaigncfg; |
370 QByteArray campaigncfg; |
196 HWProto::addStringToBuffer(campaigncfg, "TL"); |
371 HWProto::addStringToBuffer(campaigncfg, "TL"); |
|
372 |
|
373 HWTeam missionTeam = HWTeam(); |
|
374 missionTeam.setName(config->Form->ui.pageCampaign->CBTeam->currentText()); |
|
375 missionTeam.loadFromFile(); |
|
376 missionTeam.setNumHedgehogs(HEDGEHOGS_PER_TEAM); |
|
377 missionTeam.setMissionTeam(true); |
|
378 HWProto::addStringListToBuffer(campaigncfg, missionTeam.teamGameConfig(100)); |
|
379 |
197 HWProto::addStringToBuffer(campaigncfg, "eseed " + QUuid::createUuid().toString()); |
380 HWProto::addStringToBuffer(campaigncfg, "eseed " + QUuid::createUuid().toString()); |
198 |
|
199 HWProto::addStringToBuffer(campaigncfg, "escript " + campaignScript); |
381 HWProto::addStringToBuffer(campaigncfg, "escript " + campaignScript); |
200 |
382 |
201 RawSendIPC(campaigncfg); |
383 RawSendIPC(campaigncfg); |
202 } |
384 } |
203 |
385 |