1 #include <QApplication>
2 
3 #include "gametools.h"
4 
5 #include "scene_if.h"
6 #include "gamewidget.h"
7 #include "gamestock.h"
8 #include "gamebonus.h"
9 #include "gameprofile.h"
10 #include "gamesound.h"
11 
12 #include "hammertool.h"
13 //#include "bighammertool.h"
14 //#include "smallhammertool.h"
15 #include "bombtool.h"
16 #include "thundertool.h"
17 #include "clocktool.h"
18 #include "randomkilltool.h"
19 #include "mixertool.h"
20 //#include "unblocktool.h"
21 #include "twintool.h"
22 
23 #include "consttools.h"
24 
25 #include "progressbar.h"
26 
27 #include "particlecontrol.h"
28 #include "gamehintcontrol.h"
29 
30 ToolSet * toolset = nullptr;
31 
32 ////////////////////////////////////////////////////////////////////////////////
33 
34 #define TOOL_STAGES 20
35 
36 int GameTool::stage;
37 
GameTool(int x,int y,int score)38 GameTool::GameTool(int x, int y, int score) :
39     myPos(x,y),
40     myScore(score),
41     myToolset(0),
42     myProgress(0),
43     myActive(false)
44 {
45 }
46 
GameTool(int x,int y,int score,const QString & resource)47 GameTool::GameTool(int x, int y, int score, const QString &resource) :
48     myPos(x,y),
49     myScore(score),
50     myToolset(0),
51     myProgress(0),
52     myActive(false)
53 {
54   myPixmap = QPixmap(GameWidget::getResourcePath() + "/tools/" + resource + ".png")
55              .scaled(DX(48),DY(48), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
56 }
57 
~GameTool()58 GameTool::~GameTool()
59 {
60 }
61 
setCurrent()62 void GameTool::setCurrent()
63 {
64   stage = TOOL_STAGES;
65 }
66 
advanceAndPaint(QPainter & p,int currentScore)67 void GameTool::advanceAndPaint(QPainter &p, int currentScore)
68 {
69   if (!myActive)
70   {
71 //    if (currentScore >= myScore && !myToolset->isPuzzle())
72 //    {
73 //      setActive(true);
74 //      animateActivation();
75 //      myToolset->nextToolActivated();
76 //    }
77     return;
78   }
79 
80   p.setOpacity(currentScore >= myScore ? 1 : 0.5);
81 
82 //  p.setPen(QPen(Qt::white));
83 //
84 //  p.drawText(QRect(myPos.x(), myPos.y()-DY(12), DX(48), DY(20)),
85 //             Qt::AlignHCenter | Qt::AlignTop, QString::number(myScore));
86 
87   if (myToolset->current() == this)
88   {
89     p.setOpacity((1.0/TOOL_STAGES) * stage);
90     if (!--stage) stage = TOOL_STAGES;
91   }
92 
93   p.drawPixmap(myPos, myPixmap);
94 }
95 
animateActivation()96 void GameTool::animateActivation()
97 {
98   scene->createPixmapPopup(myPos.x(), myPos.y(), -1, -1, myPixmap, 20);
99   scene->createPixmapPopup(myPos.x(), myPos.y(), 1, 1, myPixmap, 20);
100   scene->createPixmapPopup(myPos.x(), myPos.y(), -1, 1, myPixmap, 20);
101   scene->createPixmapPopup(myPos.x(), myPos.y(), 1, -1, myPixmap, 20);
102 }
103 
hint() const104 QString GameTool::hint() const
105 {
106   return QString("%1: %2").arg(bonusInfo->name, bonusInfo->comment);
107 }
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 
111 #define MAX_TOOL_SCORE  100
112 
113 struct ToolSetPrivate
114 {
ToolSetPrivateToolSetPrivate115   ToolSetPrivate() : myActiveToolIndex(0), maxCount(MAX_TOOL_SCORE)
116   {
117     QLinearGradient gr2(0,0,40,0);
118     gr2.setColorAt(0, QColor(0x034912));
119     gr2.setColorAt(0.5, QColor(0x00ff07));
120     gr2.setColorAt(1, QColor(0x034912));
121 
122     countBar = new ProgressBar(QRect(30,60, 40,630));
123     countBar->setUpSpeed(10);
124     countBar->setBrush(gr2);
125 
126     countBar->setMax(maxCount);
127   }
128 
~ToolSetPrivateToolSetPrivate129   ~ToolSetPrivate()
130   {
131     delete countBar;
132   }
133 
134   int myActiveToolIndex;
135   int maxCount;
136 
137   ProgressBar *countBar;
138 
139   HammerTool *hammerTool;
140   BombTool *bombTool;
141   ThunderTool *thunderTool;
142   ClockTool *clockTool;
143   RandomKillTool *randomKillTool;
144   MixerTool *mixerTool;
145   TwinTool *twinTool;
146   //class MagBonus *magBonus;
147   //class TimerBonus *timerBonus;
148   //class ScoreBonus *scoreBonus;
149   //class ClockBonus *clockBonus;
150 };
151 
152 ////////////////////////////////////////////////////////////////////////////////
153 
ToolSet()154 ToolSet::ToolSet() : toolScore(0), currentTool(0)
155 {
156   priv = new ToolSetPrivate();
157 
158   initGraphics();
159 
160   // active by default
161 //  smallHammerTool->setActive();
162 //  unblockTool->setActive();
163 }
164 
~ToolSet()165 ToolSet::~ToolSet()
166 {
167   qDeleteAll(tools);
168 }
169 
170 //int ToolSet::bonusClock() const { return clockBonus->value(); }
171 //int ToolSet::bonusScore() const { return scoreBonus->value(); }
172 //int ToolSet::bonusTimer() const { return timerBonus->value(); }
173 //int ToolSet::bonusMag() const { return magBonus->value(); }
174 
initGraphics()175 void ToolSet::initGraphics()
176 {
177 //  int magBonusVal = 0;
178 //  int timerBonusVal = 0;
179 //  int clockBonusVal = 0;
180 //  int scoreBonusVal = 0;
181 
182   //QList<bool> activ;
183 
184   if (tools.count())
185   {
186 //    magBonusVal = magBonus->value();
187 //    timerBonusVal = timerBonus->value();
188 //    clockBonusVal = clockBonus->value();
189 //    scoreBonusVal = scoreBonus->value();
190 
191 //    for (int i = 0; i < tools.count(); i++)
192 //      activ.append(tools.at(i)->isActive());
193 
194     qDeleteAll(tools);
195     tools.clear();
196   }
197 
198   int x1 = DX(26);
199   int y1 = DY(6);
200 
201   priv->clockTool = new ClockTool(x1, y1, MAX_TOOL_SCORE);
202   priv->mixerTool = new MixerTool(x1, y1, MAX_TOOL_SCORE);
203   priv->hammerTool = new HammerTool(x1, y1, MAX_TOOL_SCORE);
204   priv->bombTool = new BombTool(x1, y1, MAX_TOOL_SCORE);
205   priv->randomKillTool = new RandomKillTool(x1, y1, MAX_TOOL_SCORE);
206   priv->thunderTool = new ThunderTool(x1, y1, MAX_TOOL_SCORE);
207   priv->twinTool = new TwinTool(x1, y1, MAX_TOOL_SCORE);
208 
209 
210   // permanent tools
211 //  y += DY(100);
212 //  magBonus = new MagBonus(x1,y, 10000);
213 //  timerBonus = new TimerBonus(x2,y, 12000);
214 //  y += dy;
215 //  clockBonus = new ClockBonus(x1,y, 15000);
216 //  scoreBonus = new ScoreBonus(x2,y, 20000);
217 
218   // order in which the tools are given
219   tools.append(priv->clockTool);
220   tools.append(priv->hammerTool);
221   tools.append(priv->bombTool);
222   tools.append(priv->mixerTool);
223   tools.append(priv->randomKillTool);
224   tools.append(priv->thunderTool);
225   tools.append(priv->twinTool);
226 
227 //  tools.append(magBonus);
228 //  tools.append(timerBonus);
229 //  tools.append(clockBonus);
230 //  tools.append(scoreBonus);
231 
232   // update bonus values
233 //  magBonus->setValue(magBonusVal);
234 //  timerBonus->setValue(timerBonusVal);
235 //  clockBonus->setValue(clockBonusVal);
236 //  scoreBonus->setValue(scoreBonusVal);
237 
238   for (int i = 0; i < tools.count(); i++)
239   {
240     GameTool *tool = tools.at(i);
241     tool->setBase(this);
242     tool->setActive(priv->myActiveToolIndex == i);
243   }
244 }
245 
readProfile(LevelPackInfo * lpi)246 void ToolSet::readProfile(LevelPackInfo *lpi)
247 {
248   // this is to enable animation
249   setScore(0);
250   setScore(lpi->toolScore);
251 
252   currentTool = 0;
253 
254   priv->myActiveToolIndex = lpi->activeToolIndex;
255   if (priv->myActiveToolIndex < 0 && priv->myActiveToolIndex >= tools.count())
256     priv->myActiveToolIndex = 0;
257 
258   for (int i = 0; i < tools.count(); i++)
259   {
260     tools.at(i)->setActive(priv->myActiveToolIndex == i);
261   }
262 
263 //  scoreBonus->setValue(lpi->score_bonus);
264 //  clockBonus->setValue(lpi->time_bonus);
265 //  timerBonus->setValue(lpi->speed_bonus);
266 //  magBonus->setValue(lpi->speed_mag_bonus);
267 }
268 
writeProfile(LevelPackInfo * lpi)269 void ToolSet::writeProfile(LevelPackInfo *lpi)
270 {
271   lpi->toolScore = toolScore;
272   lpi->activeToolIndex = priv->myActiveToolIndex;
273 
274 //  lpi->score_bonus = scoreBonus->value();
275 //  lpi->time_bonus = clockBonus->value();
276 //  lpi->speed_bonus = timerBonus->value();
277 //  lpi->speed_mag_bonus = magBonus->value();
278 }
279 
activateRandomTool()280 void ToolSet::activateRandomTool()
281 {
282   priv->myActiveToolIndex = qrand() % tools.count();
283 
284   for (int i = 0; i < tools.count(); i++)
285   {
286     tools.at(i)->setActive(priv->myActiveToolIndex == i);
287   }
288 }
289 
updateScore()290 void ToolSet::updateScore()
291 {
292   static bool activated = false;
293 
294   toolScore = (int)priv->countBar->value();
295 
296   if (priv->countBar->isFull())
297   {
298     if (!activated)
299     {
300       activated = true;
301       tools.at(priv->myActiveToolIndex)->animateActivation();
302 
303       sndEngine->playSound(GameSound::sndTool);
304 
305       //hintControl->scheduleHint(hintControl->ToolsHint);
306       hintControl->scheduleHint(hintControl->ToolHint[priv->myActiveToolIndex]);
307     }
308   } else
309     activated = false;
310 }
311 
addScore(int score)312 void ToolSet::addScore(int score)
313 {
314   priv->countBar->addValue(score);
315   updateScore();
316 }
317 
setScore(int score)318 void ToolSet::setScore(int score)
319 {
320   priv->countBar->setValue(score);
321   updateScore();
322 }
323 
setLongestChain(int value)324 void ToolSet::setLongestChain(int value)
325 {
326   priv->maxCount = MAX_TOOL_SCORE - (value-3)*2;
327   priv->countBar->setMax(priv->maxCount);
328 
329   for (int i = 0; i < tools.count(); i++)
330   {
331     GameTool *tool = tools.at(i);
332     tool->setScore(priv->maxCount);
333   }
334 
335   updateScore();
336 }
337 
338 //void ToolSet::nextToolActivated()
339 //{
340 //  if (puzzle || next_tool == ALL_TOOLS)
341 //    return;
342 //
343 //  if (next_tool < tools.count())
344 //  {
345 //    GameTool *tool = tools.at(next_tool);
346 //    tool->setActive(true);
347 //    tool->animateActivation();
348 //    sndEngine->playSound(GameSound::sndTool);
349 //
350 //    next_tool++;
351 //  }
352 //  else
353 //    next_tool = ALL_TOOLS;
354 //}
355 
356 //int ToolSet::activeToolIndex(int score)
357 //{
358 //  int idx = 2;
359 //  if (puzzle) return idx;
360 //
361 //  while (idx < tools.count() && tools.at(idx)->score() <= score)
362 //    idx++;
363 //  if (idx == tools.count())
364 //    idx = 0;
365 //  return idx;
366 //}
367 
updateTools(QPainter & p)368 void ToolSet::updateTools(QPainter &p)
369 {
370   // countBar
371   priv->countBar->paint(p);
372 
373   // tool
374   p.setFont(gameStock->Font8);
375 
376   tools.at(priv->myActiveToolIndex)->advanceAndPaint(p, toolScore);
377 
378 //  for (int i = 0; i < tools.count(); i++)
379 //  {
380 //    GameTool *tool = tools.at(i);
381 //    tool->advanceAndPaint(p, toolScore);
382 //  }
383 }
384 
checkMouseActions(const QPoint & pos)385 bool ToolSet::checkMouseActions(const QPoint &pos)
386 {
387   for (int i = 0; i < tools.count(); i++)
388   {
389     GameTool *tool = tools.at(i);
390     if (!tool->isActive())
391       continue;
392 
393     if (QRect(tool->pos(), QSize(DX(48),DY(48))).contains(pos))
394     {
395       if (tool == currentTool)
396         break;
397 
398       if (tool->score() <= toolScore)
399       {
400         currentTool = tool;
401         currentTool->setCurrent();
402         QApplication::setOverrideCursor(currentTool->pixmap());
403 
404         if (tool->type() != GameTool::ManualTool)
405         {
406           if (tool->checkToolClick())
407           {
408             toolAboutExecute();
409 
410             if (!tool->inProgress())
411             {
412               toolExecuted();
413             }
414             return true;
415           }
416         }
417         else  // manual tool
418         {
419 
420         }
421 
422         myOverRow = myOverCol = -1;
423         return true;
424       }
425 
426       break;
427     }
428   }
429 
430   currentTool = 0;
431   scene->setDefaultGameCursor();
432   return false;
433 }
434 
progressCurrent()435 void ToolSet::progressCurrent()
436 {
437   if (!(currentTool->checkToolClick()))
438   {
439     toolExecuted();
440   }
441 }
442 
toolAboutExecute()443 void ToolSet::toolAboutExecute()
444 {
445   setScore(0);
446 
447   // emit particles
448   ParticleEmitter *pe = new ParticleEmitter(DX(40), DY(350));
449   pe->setDuration(80);
450   pe->setCount(40);
451   pe->setEmitRadius(DX(20), DY(350));
452   pe->setOpacityShift(0.3);
453   pe->setCreator(new UniformParticleCreator(3));  // green
454   partControl->addEmitter(pe);
455 }
456 
toolExecuted()457 void ToolSet::toolExecuted()
458 {
459   myOverRow = myOverCol = -1;
460   currentTool = 0;
461   setScore(0);
462   activateRandomTool();
463   scene->setDefaultGameCursor();
464 }
465 
checkItemClick(int row,int col)466 bool ToolSet::checkItemClick(int row, int col)
467 {
468   if (!currentTool->checkItemClick(row, col))
469     return false;
470 
471   toolAboutExecute();
472 
473   if (!currentTool->inProgress())
474     toolExecuted();
475 
476   return true;
477 }
478 
checkItemState(int row,int col)479 GameTool::ToolAction ToolSet::checkItemState(int row, int col)
480 {
481   if (!currentTool || myOverCol == -1 || myOverRow == -1)
482     return GameTool::ToolOutOfRange;
483 
484   if (currentTool->inProgress())
485     return GameTool::ToolOutOfRange;
486 
487   return currentTool->checkItemState(row, col);
488 }
489 
checkMouseMoved(int row,int col)490 void ToolSet::checkMouseMoved(int row, int col)
491 {
492   if (col >= 0 && col < scene->numCols() && row >= 0 && row < scene->numRows())
493   {
494     myOverRow = row;
495     myOverCol = col;
496   }
497   else
498     myOverRow = myOverCol = -1;
499 }
500 
checkMouseHover(const QPoint & pos)501 bool ToolSet::checkMouseHover(const QPoint &pos)
502 {
503   for (int i = 0; i < tools.count(); i++)
504   {
505     GameTool *tool = tools.at(i);
506 
507     if (!tool->isActive())
508       continue;
509 
510     if (QRect(tool->pos(), QSize(DX(48),DY(48))).contains(pos))
511     {
512       scene->showHint(tool->hint());
513       return true;
514     }
515   }
516 
517   return false;
518 }
519