ScummVM API documentation
necklacepuzzle.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11 
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16 
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef NANCY_ACTION_NECKLACEPUZZLE_H
23 #define NANCY_ACTION_NECKLACEPUZZLE_H
24 
25 #include "engines/nancy/commontypes.h"
26 #include "engines/nancy/action/puzzlerecord.h"
27 #include "engines/nancy/action/mousefollow.h"
28 
29 namespace Nancy {
30 namespace Action {
31 
32 // Nancy15 rewrote AR 243 into a shell-stringing puzzle: a box of shells on one
33 // side, and a set of strands hanging from needles on the other. A shell is taken
34 // from the box onto the cursor and dropped on a needle, where it slides down the
35 // strand and stacks on the ones already there. Every strand has to end up holding
36 // the exact sequence the design calls for.
37 //
38 // How many of each shell are left is not kept in the record; it lives in the
39 // shared table values, so the box counts survive leaving and re-entering. Shells
40 // left on a strand are handed back when the puzzle is abandoned unsolved.
41 class NecklacePuzzle : public PuzzleRecord {
42 public:
44  virtual ~NecklacePuzzle();
45 
46  void init() override;
47  void registerGraphics() override;
48 
49  void readData(Common::SeekableReadStream &stream) override;
50  void execute() override;
51  void handleInput(NancyInput &input) override;
52 
53  bool isViewportRelative() const override { return true; }
54 
55 protected:
56  Common::String getRecordTypeName() const override { return "NecklacePuzzle"; }
57 
58  static const int16 kNoBead = -1;
59  static const int16 kNoTableIndex = 255;
60 
61  // A kind of shell. All shells of a kind share their three sprite sheets: one
62  // for the cursor, one for the strand, one for the box.
63  struct BeadType {
64  int32 key = 0;
65  bool overlaps = false; // this kind sits into the one below it
66  int cursorImage = -1; // indices into _images
67  int strandImage = -1;
68  int boxImage = -1;
69  };
70 
71  struct Bead {
72  byte type = 0; // BeadType::key
73  Common::Rect cursorSrc;
74  Common::Rect strandSrc;
75  Common::Rect boxSrc;
76  Common::Rect boxDest; // also the hotspot for taking one out of the box
77  int16 tableIndex = kNoTableIndex; // table value holding how many are left
78  };
79 
80  struct PlacedBead {
81  int16 bead = kNoBead;
82  Common::Rect rect;
83  };
84 
85  struct Strand {
86  bool grabByTopBead = false; // take the top shell back by clicking it, not the needle
87  bool allowSwap = false; // a full strand lets its top shell be replaced
88  Common::Array<byte> allowedTypes;
89  Common::Array<uint16> solution; // required table indices, top of the strand first
90  Common::Rect needleHotspot;
91  Common::Rect strandRect;
92  float dropSeconds = 0.0f; // time a shell takes to slide the strand's full length
93 
95  };
96 
97  // What the cursor is over. Only one of the two is ever set.
98  struct Hover {
99  int strand = -1;
100  int bead = -1;
101  bool swapTop = false; // dropping here replaces the strand's top shell
102  };
103 
104  int findBeadType(byte key) const;
105  bool strandAccepts(const Strand &strand, byte type) const;
106 
107  // Y the next shell dropped on `strand` comes to rest against, and the same one
108  // level further down (used to decide whether a full strand can still swap).
109  int stackTop(const Strand &strand) const;
110  int stackTopBelow(const Strand &strand) const;
111 
112  Hover hitTest(const Common::Point &mousePos) const;
113 
114  int16 beadCount(const Bead &bead) const;
115  void adjustBeadCount(const Bead &bead, int16 delta);
116 
117  void holdBead(int16 bead, NancyInput *input);
118  void releaseBead();
119  void dropBeadOn(int strand);
120  void checkSolved();
121  void refundBeads();
122 
123  void redraw();
124  void drawBeadCount(const Bead &bead);
125 
126  // -- File data --
127  bool _refundOnExit = false;
128  int32 _overlapPlaced = 0; // taken off an overlapping shell's width on a strand
129  int32 _overlapFalling = 0; // how far an overlapping shell sinks into the one below
130  FlagDescription _dropFlag; // set every time a shell is strung
131  uint16 _heldCursorType = 0;
132  uint16 _hoverCursorType = 0;
133  int32 _heldOffsetX = 0; // where the held shell sits relative to the cursor
134  int32 _heldOffsetY = 0;
135  uint16 _countFontID = 0;
136  uint16 _unknownA0 = 0;
137  uint16 _countTextExtraY = 0;
138  int32 _countTextX = 0; // offset from the box rect's top left
139  int32 _countTextY = 0;
140 
141  Common::Array<Common::Path> _imageNames;
142  Common::Array<BeadType> _beadTypes;
143  Common::Array<Bead> _beads;
144  Common::Array<Strand> _strands;
145 
146  RandomSoundBlock _pickUpSound;
147  RandomSoundBlock _putDownSound;
148  RandomSoundBlock _unknownSound; // no known trigger; "NO SOUND" in the shipped record
149 
150  RandomSoundBlock _solvedSound;
151 
152  // Played when the puzzle is left unfinished. Its scene is 9999 in the shipped
153  // record, so the exit hotspot's own scene is what the player ends up in.
154  SceneChangeDescription _unsolvedScene;
155  RandomSoundBlock _unsolvedSound;
156 
157  // -- Runtime state --
159 
160  int16 _heldBead = kNoBead;
161  MouseFollowObject _heldBeadObject;
162 
163  int _fallingStrand = -1;
164  int _fallingStartY = 0;
165  int _fallingEndY = 0;
166  uint32 _fallStartTime = 0;
167  uint32 _fallDuration = 0;
168 
169  bool _solved = false;
170  bool _exitRequested = false;
171 };
172 
173 } // End of namespace Action
174 } // End of namespace Nancy
175 
176 #endif // NANCY_ACTION_NECKLACEPUZZLE_H
Definition: str.h:59
Definition: commontypes.h:186
Definition: rect.h:536
Definition: necklacepuzzle.h:85
Definition: stream.h:745
Definition: input.h:41
Definition: necklacepuzzle.h:41
Definition: commontypes.h:324
Definition: necklacepuzzle.h:71
Definition: necklacepuzzle.h:80
Definition: rect.h:144
Definition: necklacepuzzle.h:98
Definition: puzzlerecord.h:37
Definition: necklacepuzzle.h:63
Definition: mousefollow.h:50
Definition: commontypes.h:201
Definition: actionmanager.h:32