1474 lines
29 KiB
C++
1474 lines
29 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* Additional copyright for this file:
|
|
* Copyright (C) 1995-1997 Presto Studios, Inc.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "pegasus/gamestate.h"
|
|
#include "pegasus/pegasus.h"
|
|
#include "pegasus/items/biochips/arthurchip.h"
|
|
#include "pegasus/neighborhood/caldoria/caldoria.h"
|
|
#include "pegasus/neighborhood/caldoria/caldoriabomb.h"
|
|
|
|
namespace Pegasus {
|
|
|
|
// Bomb game PICTs:
|
|
|
|
static const uint16 kYellowBombPICTBaseID = 700;
|
|
static const uint16 kRedBombPICTBaseID = 709;
|
|
static const uint16 kTimerLeftPICTID = 718;
|
|
static const uint16 kTimerRightPICTID = 719;
|
|
|
|
static const uint32 kFlashOnTime = 20;
|
|
static const uint32 kFlashOffTime = 10;
|
|
|
|
static const uint32 kOnTime1 = kFlashOnTime;
|
|
static const uint32 kOffTime1 = kOnTime1 + kFlashOffTime;
|
|
static const uint32 kOnTime2 = kOffTime1 + kFlashOnTime;
|
|
static const uint32 kOffTime2 = kOnTime2 + kFlashOffTime;
|
|
static const uint32 kOnTime3 = kOffTime2 + kFlashOnTime;
|
|
static const uint32 kOffTime3 = kOnTime3 + kFlashOffTime;
|
|
static const uint32 kOnTime4 = kOffTime3 + kFlashOnTime;
|
|
|
|
// Bomb hotspots start at 20000 since the extra Caldoria hotspots start at 10000.
|
|
// Assigning these vice versa causes a hotspot in level 4 to never activate for some reason.
|
|
static const HotSpotID kVertextHotSpotBaseID = 20000;
|
|
|
|
static const CoordType kVertextHotSpotWidth = 24;
|
|
static const CoordType kVertextHotSpotHeight = 24;
|
|
|
|
static const NotificationFlags kBombTimerExpiredFlag = 1;
|
|
|
|
static const VertexType kBombLevelOne[] = {
|
|
0, 1, 0, 1, 0, // hot vertices first.
|
|
1, 1, 0, 1, 1,
|
|
1, 1, 0, 1, 0,
|
|
1, 1, 0, 1, 1,
|
|
0, 1, 0, 1, 0,
|
|
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
|
|
9, // 9 edges in this level
|
|
|
|
kEdgeOneFourth,
|
|
3,
|
|
1, 2, 3,
|
|
0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
5,
|
|
5, 6, 7, 8, 9,
|
|
0, 0, 0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
4,
|
|
10, 11, 12, 13,
|
|
0, 0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
5,
|
|
15, 16, 17, 18, 19,
|
|
0, 0, 0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
3,
|
|
21, 22, 23,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
3,
|
|
5, 10, 15,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
5,
|
|
1, 6, 11, 16, 21,
|
|
0, 0, 0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
5,
|
|
3, 8, 13, 18, 23,
|
|
0, 0, 0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
3,
|
|
9, 14, 19,
|
|
0, 0
|
|
};
|
|
|
|
static const VertexType kBombLevelTwo[] = {
|
|
0, 1, 0, 1, 0,
|
|
1, 1, 1, 0, 1,
|
|
0, 0, 0, 1, 0,
|
|
1, 1, 1, 0, 1,
|
|
0, 1, 0, 1, 0,
|
|
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
|
|
15,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
5, 1,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
3,
|
|
17, 13, 9,
|
|
0, 0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
23, 19,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
3, 9,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
3,
|
|
7, 13, 19,
|
|
0, 0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
15, 21,
|
|
0,
|
|
|
|
kEdgeOneFourth,
|
|
3,
|
|
1, 2, 3,
|
|
0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
4,
|
|
6, 7, 8, 9,
|
|
0, 0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
4,
|
|
16, 17, 18, 19,
|
|
0, 0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
3,
|
|
21, 22, 23,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
3,
|
|
5, 10, 15,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
2,
|
|
1, 6,
|
|
0,
|
|
|
|
kEdgeOneHalf,
|
|
3,
|
|
7, 12, 17,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
3,
|
|
9, 14, 19,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
2,
|
|
16, 21,
|
|
0
|
|
};
|
|
|
|
static const VertexType kBombLevelThree[] = {
|
|
0, 1, 0, 1, 0,
|
|
1, 1, 1, 1, 1,
|
|
0, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 1,
|
|
0, 1, 0, 1, 0,
|
|
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
|
|
22,
|
|
|
|
kEdgeThreeSixteenths,
|
|
3,
|
|
15, 12, 9,
|
|
0, 0,
|
|
|
|
kEdgeFiveSixteenths,
|
|
3,
|
|
5, 12, 19,
|
|
0, 0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
5, 1,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
7, 3,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
15, 11,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
21, 17,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
23, 19,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
1, 7,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
3, 9,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
5, 11,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
15, 21,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
17, 23,
|
|
0,
|
|
|
|
kEdgeOneFourth,
|
|
3,
|
|
1, 2, 3,
|
|
0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
2,
|
|
5, 6,
|
|
0,
|
|
|
|
kEdgeOneFourth,
|
|
2,
|
|
8, 9,
|
|
0,
|
|
|
|
kEdgeOneFourth,
|
|
2,
|
|
15, 16,
|
|
0,
|
|
|
|
kEdgeOneFourth,
|
|
2,
|
|
18, 19,
|
|
0,
|
|
|
|
kEdgeOneFourth,
|
|
3,
|
|
21, 22, 23,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
2,
|
|
1, 6,
|
|
0,
|
|
|
|
kEdgeOneHalf,
|
|
2,
|
|
3, 8,
|
|
0,
|
|
|
|
kEdgeOneHalf,
|
|
2,
|
|
16, 21,
|
|
0,
|
|
|
|
kEdgeOneHalf,
|
|
2,
|
|
18, 23,
|
|
0
|
|
};
|
|
|
|
static const VertexType kBombLevelFour[] = {
|
|
1, 1, 1, 1, 0,
|
|
1, 1, 0, 1, 1,
|
|
1, 0, 1, 0, 1,
|
|
1, 1, 0, 1, 1,
|
|
0, 1, 1, 1, 1,
|
|
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
|
|
19,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
5, 1,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
3,
|
|
10, 6, 2,
|
|
0, 0,
|
|
|
|
kEdgeOneEighth,
|
|
3,
|
|
16, 12, 8,
|
|
0, 0,
|
|
|
|
kEdgeOneEighth,
|
|
3,
|
|
22, 18, 14,
|
|
0, 0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
23, 19,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
3,
|
|
2, 8, 14,
|
|
0, 0,
|
|
|
|
kEdgeThreeEighths,
|
|
3,
|
|
10, 16, 22,
|
|
0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
4,
|
|
0, 1, 2, 3,
|
|
0, 0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
2,
|
|
5, 6,
|
|
0,
|
|
|
|
kEdgeOneFourth,
|
|
2,
|
|
8, 9,
|
|
0,
|
|
|
|
kEdgeOneFourth,
|
|
2,
|
|
15, 16,
|
|
0,
|
|
|
|
kEdgeOneFourth,
|
|
2,
|
|
18, 19,
|
|
0,
|
|
|
|
kEdgeOneFourth,
|
|
4,
|
|
21, 22, 23, 24,
|
|
0, 0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
4,
|
|
0, 5, 10, 15,
|
|
0, 0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
2,
|
|
1, 6,
|
|
0,
|
|
|
|
kEdgeOneHalf,
|
|
2,
|
|
3, 8,
|
|
0,
|
|
|
|
kEdgeOneHalf,
|
|
4,
|
|
9, 14, 19, 24,
|
|
0, 0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
2,
|
|
16, 21,
|
|
0,
|
|
|
|
kEdgeOneHalf,
|
|
2,
|
|
18, 23,
|
|
0
|
|
};
|
|
|
|
static const VertexType kBombLevelFive[] = {
|
|
0, 1, 0, 1, 0,
|
|
1, 1, 1, 1, 1,
|
|
0, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1,
|
|
0, 1, 0, 1, 0,
|
|
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
|
|
19,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
5, 1,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
7, 3,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
13, 9,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
15, 11,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
21, 17,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
23, 19,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
1, 7,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
4,
|
|
5, 11, 17, 23,
|
|
0, 0, 0,
|
|
|
|
kEdgeThreeEighths,
|
|
3,
|
|
6, 12, 18,
|
|
0, 0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
13, 19,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
15, 21,
|
|
0,
|
|
|
|
kEdgeOneFourth,
|
|
5,
|
|
5, 6, 7, 8, 9,
|
|
0, 0, 0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
3,
|
|
15, 16, 17,
|
|
0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
2,
|
|
18, 19,
|
|
0,
|
|
|
|
kEdgeOneFourth,
|
|
3,
|
|
21, 22, 23,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
3,
|
|
5, 10, 15,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
2,
|
|
1, 6,
|
|
0,
|
|
|
|
kEdgeOneHalf,
|
|
3,
|
|
11, 16, 21,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
5,
|
|
3, 8, 13, 18, 23,
|
|
0, 0, 0, 0
|
|
};
|
|
|
|
static const VertexType kBombLevelSix[] = {
|
|
0, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1,
|
|
1, 0, 0, 0, 1,
|
|
1, 1, 1, 1, 1,
|
|
0, 1, 1, 1, 0,
|
|
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
|
|
25,
|
|
|
|
kEdgeOneSixteenth,
|
|
2,
|
|
10, 1,
|
|
0,
|
|
|
|
kEdgeOneSixteenth,
|
|
2,
|
|
23, 14,
|
|
0,
|
|
|
|
kEdgeSevenSixteenths,
|
|
2,
|
|
3, 14,
|
|
0,
|
|
|
|
kEdgeSevenSixteenths,
|
|
2,
|
|
10, 21,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
5, 1,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
3,
|
|
10, 6, 2,
|
|
0, 0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
7, 3,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
21, 17,
|
|
0,
|
|
|
|
kEdgeOneEighth,
|
|
3,
|
|
22, 18, 14,
|
|
0, 0,
|
|
|
|
kEdgeOneEighth,
|
|
2,
|
|
23, 19,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
1, 7,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
3,
|
|
2, 8, 14,
|
|
0, 0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
3, 9,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
3,
|
|
10, 16, 22,
|
|
0, 0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
15, 21,
|
|
0,
|
|
|
|
kEdgeThreeEighths,
|
|
2,
|
|
17, 23,
|
|
0,
|
|
|
|
kEdgeOneFourth,
|
|
3,
|
|
1, 2, 3,
|
|
0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
3,
|
|
6, 7, 8,
|
|
0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
3,
|
|
16, 17, 18,
|
|
0, 0,
|
|
|
|
kEdgeOneFourth,
|
|
3,
|
|
21, 22, 23,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
3,
|
|
5, 10, 15,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
3,
|
|
6, 11, 16,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
5,
|
|
2, 7, 12, 17, 22,
|
|
0, 0, 0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
3,
|
|
8, 13, 18,
|
|
0, 0,
|
|
|
|
kEdgeOneHalf,
|
|
3,
|
|
9, 14, 19,
|
|
0, 0
|
|
};
|
|
|
|
static const CoordType kBombGridWidth = 140;
|
|
static const CoordType kBombGridHeight = 140;
|
|
|
|
static const CoordType kDotOriginX = 0;
|
|
static const CoordType kDotOriginY = 0;
|
|
|
|
static const CoordType kVertOriginX = 2;
|
|
static const CoordType kVertOriginY = 6;
|
|
|
|
static const CoordType kHorizOriginX = 6;
|
|
static const CoordType kHorizOriginY = 2;
|
|
|
|
static const CoordType kDiagOriginX = 6;
|
|
static const CoordType kDiagOriginY = 6;
|
|
|
|
static const int g_originsX[] = {
|
|
kDiagOriginX,
|
|
kDiagOriginX,
|
|
kDiagOriginX,
|
|
kHorizOriginX,
|
|
kDiagOriginX,
|
|
kDiagOriginX,
|
|
kDiagOriginX,
|
|
kVertOriginX
|
|
};
|
|
|
|
static const int g_originsY[] = {
|
|
kDiagOriginY - 64,
|
|
kDiagOriginY - 32,
|
|
kDiagOriginY - 32,
|
|
kHorizOriginY,
|
|
kDiagOriginY,
|
|
kDiagOriginY,
|
|
kDiagOriginY,
|
|
kVertOriginY
|
|
};
|
|
|
|
struct HotVerticesList {
|
|
int numHotVerts;
|
|
VertexType hotVerts[25];
|
|
};
|
|
|
|
CoordType vertToX(VertexType vertex) {
|
|
return (vertex % 5) * 32;
|
|
}
|
|
|
|
CoordType vertToY(VertexType vertex) {
|
|
return (vertex / 5) * 32;
|
|
}
|
|
|
|
// This function returns the number of edges in the bomb edge list.
|
|
VertexType getNumEdges(BombEdgeList edges) {
|
|
return edges[50];
|
|
}
|
|
|
|
// These four functions return pointers into the given edge list.
|
|
|
|
// getFirstEdge and getNextEdge can be used to iterate across all edges
|
|
// in an edge list. These functions can be used to walk all the edges
|
|
// in a bomb edge list for drawing.
|
|
VertexType *getFirstEdge(BombEdgeList edges) {
|
|
return &edges[51];
|
|
}
|
|
|
|
VertexType *getNextEdge(VertexType *anEdge) {
|
|
return anEdge + *(anEdge + 1) * 2 + 1;
|
|
}
|
|
|
|
// getVertices returns a pointer to all of the vertices that should are
|
|
// hot. These vertices indicate all the vertices that should be drawn in
|
|
// the game.
|
|
VertexType *getVertices(BombEdgeList edges) {
|
|
return &edges[0];
|
|
}
|
|
|
|
// getUsedVertices returns a pointer to the "used" vertices area: the
|
|
// area that keeps track of which vertices have been set by the
|
|
// setVertexUsed used function.
|
|
VertexType *getUsedVertices(BombEdgeList edges) {
|
|
return &edges[25];
|
|
}
|
|
|
|
// Useful for saving. Saving the state of the bomb game is as simple as writing
|
|
// out the edge list.
|
|
int getEdgeListSize(BombEdgeList edges) {
|
|
VertexType numEdges = getNumEdges(edges);
|
|
VertexType *anEdge = getFirstEdge(edges);
|
|
|
|
while (numEdges--)
|
|
anEdge = getNextEdge(anEdge);
|
|
|
|
return anEdge - edges + 4;
|
|
}
|
|
|
|
// Returns true if the given vertex lies on the given edge.
|
|
bool vertexOnEdge(VertexType *anEdge, VertexType whichVertex) {
|
|
VertexType numVerts = *++anEdge;
|
|
|
|
while (numVerts--)
|
|
if (*++anEdge == whichVertex)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
// Given an edge list and a from vertex, this function constructs a list
|
|
// of all vertices that may be clicked on.
|
|
// if fromVertex == -1, all vertices are eligible.
|
|
// otherwise, only vertices on a line from fromVertex are eligible.
|
|
void makeHotVertexList(BombEdgeList edges, VertexType fromVertex, HotVerticesList &hotVertices) {
|
|
hotVertices.numHotVerts = 0;
|
|
|
|
if (fromVertex == -1) {
|
|
for (VertexType i = 0; i < 25; i++)
|
|
if (edges[i])
|
|
hotVertices.hotVerts[hotVertices.numHotVerts++] = i;
|
|
} else {
|
|
VertexType numEdges = getNumEdges(edges);
|
|
VertexType *anEdge = getFirstEdge(edges);
|
|
hotVertices.hotVerts[hotVertices.numHotVerts++] = fromVertex;
|
|
|
|
while (numEdges--) {
|
|
if (vertexOnEdge(anEdge, fromVertex)) {
|
|
VertexType *p = anEdge + 1;
|
|
VertexType numVerts = *p;
|
|
|
|
while (numVerts--)
|
|
if (*++p != fromVertex)
|
|
hotVertices.hotVerts[hotVertices.numHotVerts++] = *p;
|
|
}
|
|
|
|
anEdge = getNextEdge(anEdge);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set all edges in the edge list to the value passed in "edgeVal".
|
|
// For drawing purposes, 0 can mean don't draw, and 1 and higher can
|
|
// represent different colors.
|
|
void setAllEdgesUsed(BombEdgeList edges, VertexType used) {
|
|
VertexType numEdges = getNumEdges(edges);
|
|
VertexType *anEdge = getFirstEdge(edges);
|
|
|
|
while (numEdges--) {
|
|
VertexType *p1 = anEdge + 1;
|
|
VertexType numVerts = *p1;
|
|
p1 += numVerts + 1;
|
|
|
|
while (--numVerts)
|
|
*p1++ = used;
|
|
|
|
anEdge = getNextEdge(anEdge);
|
|
}
|
|
|
|
VertexType *p1 = edges;
|
|
VertexType *p2 = getUsedVertices(edges);
|
|
|
|
for (VertexType i = 0; i < 25; i++, p1++, p2++)
|
|
if (*p1)
|
|
*p2 = used;
|
|
}
|
|
|
|
// Same as setAllEdgesUsed, but only affects edges that are already set
|
|
// to a non-zero value.
|
|
void setAllUsedEdgesUsed(BombEdgeList edges, VertexType used) {
|
|
VertexType numEdges = getNumEdges(edges);
|
|
VertexType *anEdge = getFirstEdge(edges);
|
|
|
|
while (numEdges--) {
|
|
VertexType *p = anEdge + 1;
|
|
VertexType numVerts = *p;
|
|
p += numVerts + 1;
|
|
|
|
while (--numVerts) {
|
|
if (*p)
|
|
*p = used;
|
|
++p;
|
|
}
|
|
|
|
anEdge = getNextEdge(anEdge);
|
|
}
|
|
|
|
VertexType *p = getUsedVertices(edges);
|
|
for (VertexType i = 0; i < 25; i++, p++)
|
|
if (*p)
|
|
*p = used;
|
|
}
|
|
|
|
// Replace all edges with value "value" with the new value "used".
|
|
void replaceUsedEdges(BombEdgeList edges, VertexType value, VertexType used) {
|
|
VertexType numEdges = getNumEdges(edges);
|
|
VertexType *anEdge = getFirstEdge(edges);
|
|
|
|
while (numEdges--) {
|
|
VertexType *p = anEdge + 1;
|
|
VertexType numVerts = *p;
|
|
p += numVerts + 1;
|
|
|
|
while (--numVerts) {
|
|
if (*p == value)
|
|
*p = used;
|
|
|
|
p++;
|
|
}
|
|
|
|
anEdge = getNextEdge(anEdge);
|
|
}
|
|
|
|
VertexType *p = getUsedVertices(edges);
|
|
for (VertexType i = 0; i < 25; i++, p++)
|
|
if (*p == value)
|
|
*p = used;
|
|
}
|
|
|
|
// Set a vertex's value to "used".
|
|
void setVertexUsed(BombEdgeList edges, VertexType whichVertex, VertexType value) {
|
|
*(getUsedVertices(edges) + whichVertex) = value;
|
|
}
|
|
|
|
// Mark an edge in the given list between the two vertices as "used". This marks
|
|
// all inbetween vertices as well, even if the vertex is not marked as a "hot"
|
|
// vertex in the hot vertex section. Returns true if doing this operation
|
|
// crosses an already marked edge.
|
|
bool setEdgeUsed(BombEdgeList edges, VertexType fromVertex, VertexType toVertex) {
|
|
VertexType numEdges = getNumEdges(edges);
|
|
VertexType *anEdge = getFirstEdge(edges);
|
|
bool crossed = false;
|
|
|
|
while (numEdges--) {
|
|
VertexType *p = anEdge;
|
|
VertexType numVerts = *++p;
|
|
VertexType *fromPtr = nullptr;
|
|
VertexType *toPtr = nullptr;
|
|
VertexType i = numVerts;
|
|
p++;
|
|
|
|
while (i--) {
|
|
if (*p == fromVertex)
|
|
fromPtr = p;
|
|
else if (*p == toVertex)
|
|
toPtr = p;
|
|
|
|
if (fromPtr && toPtr) {
|
|
// Found the edge...
|
|
if (fromPtr > toPtr) {
|
|
p = fromPtr;
|
|
fromPtr = toPtr;
|
|
toPtr = p;
|
|
}
|
|
|
|
p = fromPtr + numVerts;
|
|
|
|
for (i = toPtr - fromPtr; i > 0; i--, p++) {
|
|
++(*p);
|
|
|
|
if (*p == 2)
|
|
crossed = true;
|
|
}
|
|
|
|
VertexType *verts = getVertices(edges);
|
|
VertexType *usedVerts = getUsedVertices(edges);
|
|
*(usedVerts + *fromPtr) = 1;
|
|
|
|
for (p = fromPtr + 1; p != toPtr; p++)
|
|
if (*(verts + *p))
|
|
*(usedVerts + *p) = 1;
|
|
|
|
*(usedVerts + *toPtr) = 1;
|
|
return crossed;
|
|
}
|
|
|
|
p++;
|
|
}
|
|
|
|
anEdge = getNextEdge(anEdge);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Return true if all edges are used. Can be used to determine when the bomb
|
|
// game is over.
|
|
bool allEdgesUsed(BombEdgeList edges) {
|
|
VertexType numEdges = getNumEdges(edges);
|
|
VertexType *anEdge = getFirstEdge(edges);
|
|
|
|
while (numEdges--) {
|
|
VertexType *p = anEdge + 1;
|
|
VertexType numVerts = *p;
|
|
p += numVerts + 1;
|
|
|
|
while (--numVerts) {
|
|
if (!*p)
|
|
return false;
|
|
|
|
++p;
|
|
}
|
|
|
|
anEdge = getNextEdge(anEdge);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
BombGrid::BombGrid(const DisplayElementID id) : Picture(id) {
|
|
Common::Rect bounds(0, 0, kBombGridWidth, kBombGridHeight);
|
|
|
|
allocateSurface(bounds);
|
|
setBounds(bounds);
|
|
_surface->fillRect(bounds, g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff));
|
|
|
|
_transparent = true;
|
|
|
|
_yellowDot.initFromPICTResource(g_vm->_resFork, kYellowBombPICTBaseID, true);
|
|
_yellowOneSixteenth.initFromPICTResource(g_vm->_resFork, kYellowBombPICTBaseID + 1, true);
|
|
_yellowOneEighth.initFromPICTResource(g_vm->_resFork, kYellowBombPICTBaseID + 2, true);
|
|
_yellowThreeSixteenths.initFromPICTResource(g_vm->_resFork, kYellowBombPICTBaseID + 3, true);
|
|
_yellowOneFourth.initFromPICTResource(g_vm->_resFork, kYellowBombPICTBaseID + 4, true);
|
|
_yellowFiveSixteenths.initFromPICTResource(g_vm->_resFork, kYellowBombPICTBaseID + 5, true);
|
|
_yellowThreeEighths.initFromPICTResource(g_vm->_resFork, kYellowBombPICTBaseID + 6, true);
|
|
_yellowSevenSixteenths.initFromPICTResource(g_vm->_resFork, kYellowBombPICTBaseID + 7, true);
|
|
_yellowOneHalf.initFromPICTResource(g_vm->_resFork, kYellowBombPICTBaseID + 8, true);
|
|
|
|
_redDot.initFromPICTResource(g_vm->_resFork, kRedBombPICTBaseID, true);
|
|
_redOneSixteenth.initFromPICTResource(g_vm->_resFork, kRedBombPICTBaseID + 1, true);
|
|
_redOneEighth.initFromPICTResource(g_vm->_resFork, kRedBombPICTBaseID + 2, true);
|
|
_redThreeSixteenths.initFromPICTResource(g_vm->_resFork, kRedBombPICTBaseID + 3, true);
|
|
_redOneFourth.initFromPICTResource(g_vm->_resFork, kRedBombPICTBaseID + 4, true);
|
|
_redFiveSixteenths.initFromPICTResource(g_vm->_resFork, kRedBombPICTBaseID + 5, true);
|
|
_redThreeEighths.initFromPICTResource(g_vm->_resFork, kRedBombPICTBaseID + 6, true);
|
|
_redSevenSixteenths.initFromPICTResource(g_vm->_resFork, kRedBombPICTBaseID + 7, true);
|
|
_redOneHalf.initFromPICTResource(g_vm->_resFork, kRedBombPICTBaseID + 8, true);
|
|
}
|
|
|
|
void BombGrid::drawEdges(BombEdgeList edges) {
|
|
GraphicsManager *gfx = g_vm->_gfx;
|
|
gfx->setCurSurface(_surface);
|
|
|
|
_surface->fillRect(Common::Rect(0, 0, kBombGridWidth, kBombGridHeight), g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff));
|
|
|
|
Frame *yellowStuff = &_yellowDot;
|
|
Frame *redStuff = &_redDot;
|
|
VertexType numEdges = getNumEdges(edges);
|
|
VertexType *anEdge = getFirstEdge(edges);
|
|
VertexType i, *p;
|
|
|
|
Common::Rect bounds;
|
|
getSurfaceBounds(bounds);
|
|
|
|
while (numEdges--) {
|
|
p = anEdge;
|
|
VertexType edgeDirection = *p++;
|
|
VertexType numVerts = *p++;
|
|
VertexType numSegs = numVerts - 1;
|
|
|
|
for (i = 0; i < numSegs; i++, p++) {
|
|
if (*(p + numVerts) > 0 && *(p + numVerts) < 4) {
|
|
Frame *drawStuff;
|
|
|
|
if (*(p + numVerts) == 2)
|
|
drawStuff = redStuff;
|
|
else
|
|
drawStuff = yellowStuff;
|
|
|
|
int x = vertToX(*p) + g_originsX[edgeDirection];
|
|
int y = vertToY(*p) + g_originsY[edgeDirection];
|
|
|
|
Common::Rect r1;
|
|
drawStuff[edgeDirection + 1].getSurfaceBounds(r1);
|
|
Common::Rect r2 = r1;
|
|
r2.moveTo(x, y);
|
|
drawStuff[edgeDirection + 1].drawImage(r1, r2);
|
|
}
|
|
}
|
|
|
|
anEdge = getNextEdge(anEdge);
|
|
}
|
|
|
|
for (i = 0, p = getUsedVertices(edges); i < 25; i++, p++) {
|
|
if (*p > 0 && *p < 4) {
|
|
Frame *drawStuff;
|
|
|
|
if (*p == 2)
|
|
drawStuff = redStuff;
|
|
else
|
|
drawStuff = yellowStuff;
|
|
|
|
int x = vertToX(i) + kDotOriginX;
|
|
int y = vertToY(i) + kDotOriginY;
|
|
|
|
Common::Rect r1;
|
|
drawStuff->getSurfaceBounds(r1);
|
|
Common::Rect r2 = r1;
|
|
r2.moveTo(x, y);
|
|
drawStuff->drawImage(r1, r2);
|
|
}
|
|
}
|
|
|
|
triggerRedraw();
|
|
gfx->setCurSurface(gfx->getWorkArea());
|
|
}
|
|
|
|
BombTimer::BombTimer(const DisplayElementID id) : IdlerAnimation(id) {
|
|
_middle = -1;
|
|
_leftImage.getImageFromPICTResource(g_vm->_resFork, kTimerLeftPICTID);
|
|
_rightImage.getImageFromPICTResource(g_vm->_resFork, kTimerRightPICTID);
|
|
|
|
Common::Rect r;
|
|
_leftImage.getSurfaceBounds(r);
|
|
setBounds(r);
|
|
}
|
|
|
|
void BombTimer::draw(const Common::Rect &updateRect) {
|
|
Common::Rect bounds;
|
|
getBounds(bounds);
|
|
|
|
Common::Rect r1 = bounds;
|
|
r1.right = _middle;
|
|
r1 = r1.findIntersectingRect(updateRect);
|
|
|
|
if (!r1.isEmpty()) {
|
|
Common::Rect r2 = r1;
|
|
r2.moveTo(r1.left - bounds.left, r1.top - bounds.top);
|
|
_leftImage.copyToCurrentPort(r2, r1);
|
|
}
|
|
|
|
r1 = bounds;
|
|
r1.left = _middle;
|
|
r1 = r1.findIntersectingRect(updateRect);
|
|
|
|
if (!r1.isEmpty()) {
|
|
Common::Rect r2 = r1;
|
|
r2.moveTo(r1.left - bounds.left, r1.top - bounds.top);
|
|
_rightImage.copyToCurrentPort(r2, r1);
|
|
}
|
|
}
|
|
|
|
void BombTimer::timeChanged(const TimeValue newTime) {
|
|
Common::Rect bounds;
|
|
getBounds(bounds);
|
|
|
|
int newMiddle = bounds.right - bounds.width() * newTime / getDuration();
|
|
if (newMiddle != _middle) {
|
|
_middle = newMiddle;
|
|
triggerRedraw();
|
|
}
|
|
}
|
|
|
|
#define CREATE_BOMB_LEVEL(num, data) \
|
|
_bombLevel[num] = new VertexType[sizeof(data)]; \
|
|
memcpy(_bombLevel[num], data, sizeof(data))
|
|
|
|
CaldoriaBomb::CaldoriaBomb(Neighborhood *owner, NotificationManager *manager) :
|
|
GameInteraction(kCaldoriaBombInteractionID, owner), _grid(kCaldoriaBombGridID),
|
|
_timer(kCaldoriaBombTimerID), _timerNotification(kCaldoriaBombTimerNotificationID, manager) {
|
|
CREATE_BOMB_LEVEL(0, kBombLevelOne);
|
|
CREATE_BOMB_LEVEL(1, kBombLevelTwo);
|
|
CREATE_BOMB_LEVEL(2, kBombLevelThree);
|
|
CREATE_BOMB_LEVEL(3, kBombLevelFour);
|
|
CREATE_BOMB_LEVEL(4, kBombLevelFive);
|
|
CREATE_BOMB_LEVEL(5, kBombLevelSix);
|
|
_currentLevel = 0;
|
|
}
|
|
|
|
#undef CREATE_BOMB_LEVEL
|
|
|
|
CaldoriaBomb::~CaldoriaBomb() {
|
|
for (int i = 0; i < 6; i++)
|
|
delete[] _bombLevel[i];
|
|
}
|
|
|
|
void CaldoriaBomb::setSoundFXLevel(const uint16) {
|
|
// The transition sounds between levels are ambience, so overwrite what
|
|
// Neighborhood::setSoundFXLevel does and keep using the ambience volume level
|
|
if (_timer.isRunning())
|
|
_owner->_navMovie.setVolume(g_vm->getAmbienceLevel());
|
|
}
|
|
|
|
void CaldoriaBomb::setAmbienceLevel(const uint16 level) {
|
|
if (_timer.isRunning())
|
|
_owner->_navMovie.setVolume(level);
|
|
}
|
|
|
|
void CaldoriaBomb::openInteraction() {
|
|
_grid.moveElementTo(kCaldoriaBombGridLeft, kCaldoriaBombGridTop);
|
|
_grid.setDisplayOrder(kCaldoriaBombGridOrder);
|
|
_grid.startDisplaying();
|
|
|
|
_timer.moveElementTo(kCaldoriaBombTimerLeft, kCaldoriaBombTimerTop);
|
|
_timer.setDisplayOrder(kCaldoriaBombTimerOrder);
|
|
_timer.startDisplaying();
|
|
_timer.setSegment(0, kTenMinutesPerFifteenTicks, kFifteenTicksPerSecond);
|
|
_timer.setTime(0);
|
|
|
|
_timerNotification.notifyMe(this, kBombTimerExpiredFlag, kBombTimerExpiredFlag);
|
|
_timerCallBack.setNotification(&_timerNotification);
|
|
_timerCallBack.initCallBack(&_timer, kCallBackAtExtremes);
|
|
_timerCallBack.setCallBackFlag(kBombTimerExpiredFlag);
|
|
|
|
Common::Rect r(0, 0, kVertextHotSpotWidth, kVertextHotSpotHeight);
|
|
|
|
for (VertexType i = 0; i < 25; i++) {
|
|
_vertexHotspot[i] = new Hotspot(i + kVertextHotSpotBaseID);
|
|
r.moveTo(vertToX(i) + kCaldoriaBombGridLeft - kVertextHotSpotWidth / 2 + 6,
|
|
vertToY(i) + kCaldoriaBombGridTop - kVertextHotSpotHeight / 2 + 6);
|
|
_vertexHotspot[i]->setArea(r);
|
|
_vertexHotspot[i]->setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
|
|
g_allHotspots.push_back(_vertexHotspot[i]);
|
|
}
|
|
|
|
_neighborhoodNotification = _owner->getNeighborhoodNotification();
|
|
_neighborhoodNotification->notifyMe(this, kExtraCompletedFlag, kExtraCompletedFlag);
|
|
}
|
|
|
|
void CaldoriaBomb::initInteraction() {
|
|
_owner->loadLoopSound1("");
|
|
_owner->startExtraSequence(kCaldoria56BombStage1, kExtraCompletedFlag, kFilterNoInput);
|
|
}
|
|
|
|
void CaldoriaBomb::closeInteraction() {
|
|
_timer.stop();
|
|
_timer.hide();
|
|
_timer.stopDisplaying();
|
|
_grid.hide();
|
|
_grid.stopDisplaying();
|
|
|
|
// The original did not do this, but we need it here
|
|
// Not sure why the original worked without this; probably
|
|
// related to the way the List code worked in CodeWarrior.
|
|
// If this is not here, the notifications will later attempt
|
|
// to remove itself from this receiver causing a very nasty
|
|
// crash.
|
|
_timerNotification.cancelNotification(this);
|
|
_neighborhoodNotification->cancelNotification(this);
|
|
}
|
|
|
|
void CaldoriaBomb::startBombAmbient(const Common::Path &ambient) {
|
|
_owner->loadLoopSound1(ambient);
|
|
}
|
|
|
|
void CaldoriaBomb::receiveNotification(Notification *notification, const NotificationFlags) {
|
|
if (notification == _neighborhoodNotification) {
|
|
switch (_owner->getLastExtra()) {
|
|
case kCaldoria56BombStage1:
|
|
_grid.show();
|
|
_timer.show();
|
|
_timerCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
|
|
_timer.start();
|
|
_currentLevel = 0;
|
|
_lastVertex = -1;
|
|
_owner->_navMovie.setVolume(g_vm->getAmbienceLevel());
|
|
startBombAmbient("Sounds/Caldoria/BmbLoop1.22K.AIFF");
|
|
if (g_arthurChip) {
|
|
if (g_vm->getRandomBit())
|
|
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA14", kArthurCaldoriaSeeRoofBomb);
|
|
else
|
|
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBB28", kArthurCaldoriaSeeRoofBomb);
|
|
}
|
|
break;
|
|
case kCaldoria56BombStage2:
|
|
case kCaldoria56BombStage3:
|
|
case kCaldoria56BombStage4:
|
|
case kCaldoria56BombStage5:
|
|
case kCaldoria56BombStage6:
|
|
_grid.show();
|
|
_currentLevel++;
|
|
_grid.drawEdges(_bombLevel[_currentLevel]);
|
|
_lastVertex = -1;
|
|
startBombAmbient(Common::Path(Common::String::format("Sounds/Caldoria/BmbLoop%d.22K.AIFF", _owner->getLastExtra() - kCaldoria56BombStage1 + 1)));
|
|
break;
|
|
case kCaldoria56BombStage7:
|
|
_owner->requestDeleteCurrentInteraction();
|
|
GameState.setCaldoriaBombDisarmed(true);
|
|
GameState.setScoringDisarmedNuke(true);
|
|
_owner->loadAmbientLoops();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else if (notification == &_timerNotification) {
|
|
_grid.hide();
|
|
_timer.stop();
|
|
_timer.hide();
|
|
_owner->_navMovie.setVolume(g_vm->getSoundFXLevel());
|
|
_owner->loadLoopSound1("");
|
|
_owner->playDeathExtra(kCaldoria56BombExplodes, kDeathNuclearExplosion);
|
|
}
|
|
}
|
|
|
|
void CaldoriaBomb::activateHotspots() {
|
|
GameInteraction::activateHotspots();
|
|
|
|
if (_currentLevel != -1 && _lastVertex >= -1) {
|
|
HotVerticesList hotVertices;
|
|
makeHotVertexList(_bombLevel[_currentLevel], _lastVertex, hotVertices);
|
|
|
|
for (VertexType i = 0; i < hotVertices.numHotVerts; i++)
|
|
g_allHotspots.activateOneHotspot(hotVertices.hotVerts[i] + kVertextHotSpotBaseID);
|
|
}
|
|
}
|
|
|
|
void CaldoriaBomb::clickInHotspot(const Input &input, const Hotspot *hotspot) {
|
|
int clickedVertex = (int)hotspot->getObjectID() - (int)kVertextHotSpotBaseID;
|
|
|
|
if (clickedVertex >= 0 && clickedVertex < 25) {
|
|
if (_lastVertex != -1 && setEdgeUsed(_bombLevel[_currentLevel], _lastVertex, clickedVertex)) {
|
|
clickedVertex = -2;
|
|
_flashTime = tickCount();
|
|
} else if (allEdgesUsed(_bombLevel[_currentLevel])) {
|
|
setVertexUsed(_bombLevel[_currentLevel], clickedVertex, 1);
|
|
clickedVertex = -20;
|
|
_flashTime = tickCount();
|
|
} else {
|
|
setVertexUsed(_bombLevel[_currentLevel], clickedVertex, 2);
|
|
}
|
|
|
|
_grid.drawEdges(_bombLevel[_currentLevel]);
|
|
_lastVertex = clickedVertex;
|
|
} else {
|
|
GameInteraction::clickInHotspot(input, hotspot);
|
|
}
|
|
}
|
|
|
|
InputBits CaldoriaBomb::getInputFilter() {
|
|
// Disallow arrow buttons.
|
|
return GameInteraction::getInputFilter() & kFilterAllButtons;
|
|
}
|
|
|
|
void CaldoriaBomb::handleInput(const Input &input, const Hotspot *hotspot) {
|
|
GameInteraction::handleInput(input, hotspot);
|
|
|
|
switch (_lastVertex) {
|
|
case -2: // Flash back to yellow.
|
|
if (tickCount() > _flashTime + kOnTime1) {
|
|
replaceUsedEdges(_bombLevel[_currentLevel], 2, 3);
|
|
_grid.drawEdges(_bombLevel[_currentLevel]);
|
|
_lastVertex = -3;
|
|
}
|
|
break;
|
|
case -3: // Flash back to red.
|
|
if (tickCount() > _flashTime + kOffTime1) {
|
|
replaceUsedEdges(_bombLevel[_currentLevel], 3, 2);
|
|
_grid.drawEdges(_bombLevel[_currentLevel]);
|
|
_lastVertex = -4;
|
|
}
|
|
break;
|
|
case -4: // Flash all to yellow.
|
|
if (tickCount() > _flashTime + kOnTime2) {
|
|
setAllUsedEdgesUsed(_bombLevel[_currentLevel], 1);
|
|
_grid.drawEdges(_bombLevel[_currentLevel]);
|
|
_lastVertex = -5;
|
|
}
|
|
break;
|
|
case -5: // Flash all to red.
|
|
if (tickCount() > _flashTime + kOffTime2) {
|
|
setAllUsedEdgesUsed(_bombLevel[_currentLevel], 2);
|
|
_grid.drawEdges(_bombLevel[_currentLevel]);
|
|
_lastVertex = -6;
|
|
}
|
|
break;
|
|
case -6: // Flash all to yellow.
|
|
if (tickCount() > _flashTime + kOnTime3) {
|
|
setAllUsedEdgesUsed(_bombLevel[_currentLevel], 1);
|
|
_grid.drawEdges(_bombLevel[_currentLevel]);
|
|
_lastVertex = -7;
|
|
}
|
|
break;
|
|
case -7: // Flash all to red.
|
|
if (tickCount() > _flashTime + kOffTime3) {
|
|
setAllUsedEdgesUsed(_bombLevel[_currentLevel], 2);
|
|
_grid.drawEdges(_bombLevel[_currentLevel]);
|
|
_lastVertex = -8;
|
|
}
|
|
break;
|
|
case -8: // Restore to normal.
|
|
if (tickCount() > _flashTime + kOnTime4) {
|
|
setAllEdgesUsed(_bombLevel[_currentLevel], 0);
|
|
_grid.drawEdges(_bombLevel[_currentLevel]);
|
|
_lastVertex = -1;
|
|
}
|
|
break;
|
|
|
|
// Flash grid after success.
|
|
case -20: // Flash off.
|
|
if (tickCount() > _flashTime + kOnTime1) {
|
|
setAllEdgesUsed(_bombLevel[_currentLevel], 4);
|
|
_grid.drawEdges(_bombLevel[_currentLevel]);
|
|
_lastVertex = -21;
|
|
}
|
|
break;
|
|
case -21: // Flash on.
|
|
if (tickCount() > _flashTime + kOffTime1) {
|
|
setAllEdgesUsed(_bombLevel[_currentLevel], 1);
|
|
_grid.drawEdges(_bombLevel[_currentLevel]);
|
|
_lastVertex = -22;
|
|
}
|
|
break;
|
|
case -22: // Flash off.
|
|
if (tickCount() > _flashTime + kOnTime2) {
|
|
setAllEdgesUsed(_bombLevel[_currentLevel], 4);
|
|
_grid.drawEdges(_bombLevel[_currentLevel]);
|
|
_lastVertex = -23;
|
|
}
|
|
break;
|
|
case -23: // Flash on.
|
|
if (tickCount() > _flashTime + kOffTime2) {
|
|
setAllEdgesUsed(_bombLevel[_currentLevel], 1);
|
|
_grid.drawEdges(_bombLevel[_currentLevel]);
|
|
_lastVertex = -24;
|
|
}
|
|
break;
|
|
case -24:
|
|
if (tickCount() > _flashTime + kOnTime3) {
|
|
_grid.hide();
|
|
_lastVertex = -1;
|
|
_owner->loadLoopSound1("");
|
|
|
|
switch (_currentLevel) {
|
|
case 0:
|
|
_owner->startExtraSequence(kCaldoria56BombStage2, kExtraCompletedFlag, kFilterNoInput);
|
|
break;
|
|
case 1:
|
|
_owner->startExtraSequence(kCaldoria56BombStage3, kExtraCompletedFlag, kFilterNoInput);
|
|
break;
|
|
case 2:
|
|
_owner->startExtraSequence(kCaldoria56BombStage4, kExtraCompletedFlag, kFilterNoInput);
|
|
break;
|
|
case 3:
|
|
_owner->startExtraSequence(kCaldoria56BombStage5, kExtraCompletedFlag, kFilterNoInput);
|
|
break;
|
|
case 4:
|
|
_owner->startExtraSequence(kCaldoria56BombStage6, kExtraCompletedFlag, kFilterNoInput);
|
|
break;
|
|
case 5:
|
|
_timer.stop();
|
|
_grid.hide();
|
|
_timer.hide();
|
|
_owner->_navMovie.setVolume(g_vm->getSoundFXLevel());
|
|
_owner->startExtraSequence(kCaldoria56BombStage7, kExtraCompletedFlag, kFilterNoInput);
|
|
if (g_arthurChip)
|
|
g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA02", kArthurCaldoriaDisarmedNuke);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
long CaldoriaBomb::getNumHints() {
|
|
return 2;
|
|
}
|
|
|
|
Common::Path CaldoriaBomb::getHintMovie(uint hintNum) {
|
|
return (hintNum == 1) ? "Images/AI/Caldoria/X56EH2" : "Images/AI/Caldoria/X56EH3";
|
|
}
|
|
|
|
bool CaldoriaBomb::canSolve() {
|
|
return true;
|
|
}
|
|
|
|
void CaldoriaBomb::doSolve() {
|
|
_timer.stop();
|
|
_grid.hide();
|
|
_timer.hide();
|
|
_owner->loadLoopSound1("");
|
|
_owner->startExtraSequence(kCaldoria56BombStage7, kExtraCompletedFlag, kFilterNoInput);
|
|
}
|
|
|
|
} // End of namespace Pegasus
|