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
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (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, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "sherlock/scalpel/scalpel_inventory.h"
24 #include "sherlock/scalpel/scalpel_fixed_text.h"
25 #include "sherlock/scalpel/scalpel_screen.h"
26 #include "sherlock/scalpel/scalpel_user_interface.h"
27 #include "sherlock/scalpel/scalpel.h"
28
29 namespace Sherlock {
30
31 namespace Scalpel {
32
ScalpelInventory(SherlockEngine * vm)33 ScalpelInventory::ScalpelInventory(SherlockEngine *vm) : Inventory(vm) {
34 _invShapes.resize(6);
35
36 _fixedTextExit = FIXED(Inventory_Exit);
37 _fixedTextLook = FIXED(Inventory_Look);
38 _fixedTextUse = FIXED(Inventory_Use);
39 _fixedTextGive = FIXED(Inventory_Give);
40
41 _hotkeyExit = toupper(_fixedTextExit[0]);
42 _hotkeyLook = toupper(_fixedTextLook[0]);
43 _hotkeyUse = toupper(_fixedTextUse[0]);
44 _hotkeyGive = toupper(_fixedTextGive[0]);
45
46 _hotkeysIndexed[0] = _hotkeyExit;
47 _hotkeysIndexed[1] = _hotkeyLook;
48 _hotkeysIndexed[2] = _hotkeyUse;
49 _hotkeysIndexed[3] = _hotkeyGive;
50 _hotkeysIndexed[4] = '-';
51 _hotkeysIndexed[5] = '+';
52 _hotkeysIndexed[6] = ',';
53 _hotkeysIndexed[7] = '.';
54 }
55
~ScalpelInventory()56 ScalpelInventory::~ScalpelInventory() {
57 }
58
identifyUserButton(int key)59 int ScalpelInventory::identifyUserButton(int key) {
60 for (uint16 hotkeyNr = 0; hotkeyNr < sizeof(_hotkeysIndexed); hotkeyNr++) {
61 if (key == _hotkeysIndexed[hotkeyNr])
62 return hotkeyNr;
63 }
64 return -1;
65 }
66
drawInventory(InvNewMode mode)67 void ScalpelInventory::drawInventory(InvNewMode mode) {
68 ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen;
69 UserInterface &ui = *_vm->_ui;
70 InvNewMode tempMode = mode;
71
72 loadInv();
73
74 if (mode == INVENTORY_DONT_DISPLAY) {
75 screen.activateBackBuffer2();
76 }
77
78 // Draw the window background
79 Surface &bb = *screen.getBackBuffer();
80 bb.fillRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 10), BORDER_COLOR);
81 bb.fillRect(Common::Rect(0, CONTROLS_Y1 + 10, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR);
82 bb.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y1 + 10,
83 SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR);
84 bb.fillRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH,
85 SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR);
86 bb.fillRect(Common::Rect(2, CONTROLS_Y1 + 10, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT - 1),
87 INV_BACKGROUND);
88
89 // Draw the buttons
90 screen.makeButton(Common::Rect(INVENTORY_POINTS[0][0], CONTROLS_Y1, INVENTORY_POINTS[0][1],
91 CONTROLS_Y1 + 10), INVENTORY_POINTS[0][2], _fixedTextExit);
92 screen.makeButton(Common::Rect(INVENTORY_POINTS[1][0], CONTROLS_Y1, INVENTORY_POINTS[1][1],
93 CONTROLS_Y1 + 10), INVENTORY_POINTS[1][2], _fixedTextLook);
94 screen.makeButton(Common::Rect(INVENTORY_POINTS[2][0], CONTROLS_Y1, INVENTORY_POINTS[2][1],
95 CONTROLS_Y1 + 10), INVENTORY_POINTS[2][2], _fixedTextUse);
96 screen.makeButton(Common::Rect(INVENTORY_POINTS[3][0], CONTROLS_Y1, INVENTORY_POINTS[3][1],
97 CONTROLS_Y1 + 10), INVENTORY_POINTS[3][2], _fixedTextGive);
98 screen.makeButton(Common::Rect(INVENTORY_POINTS[4][0], CONTROLS_Y1, INVENTORY_POINTS[4][1],
99 CONTROLS_Y1 + 10), INVENTORY_POINTS[4][2] + 8, "^^", false); // 2 arrows pointing to the left
100 screen.makeButton(Common::Rect(INVENTORY_POINTS[5][0], CONTROLS_Y1, INVENTORY_POINTS[5][1],
101 CONTROLS_Y1 + 10), INVENTORY_POINTS[5][2] + 4, "^", false); // 1 arrow pointing to the left
102 screen.makeButton(Common::Rect(INVENTORY_POINTS[6][0], CONTROLS_Y1, INVENTORY_POINTS[6][1],
103 CONTROLS_Y1 + 10), INVENTORY_POINTS[6][2] + 4, "_", false); // 1 arrow pointing to the right
104 screen.makeButton(Common::Rect(INVENTORY_POINTS[7][0], CONTROLS_Y1, INVENTORY_POINTS[7][1],
105 CONTROLS_Y1 + 10), INVENTORY_POINTS[7][2] + 8, "__", false); // 2 arrows pointing to the right
106
107 if (tempMode == INVENTORY_DONT_DISPLAY)
108 mode = LOOK_INVENTORY_MODE;
109 _invMode = (InvMode)((int)mode);
110
111 if (mode != PLAIN_INVENTORY) {
112 assert((uint)mode < sizeof(_hotkeysIndexed));
113 ui._oldKey = _hotkeysIndexed[mode];
114 } else {
115 ui._oldKey = -1;
116 }
117
118 invCommands(0);
119 putInv(SLAM_DONT_DISPLAY);
120
121 if (tempMode != INVENTORY_DONT_DISPLAY) {
122 if (!ui._slideWindows) {
123 screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
124 } else {
125 ui.summonWindow(false, CONTROLS_Y1);
126 }
127
128 ui._windowOpen = true;
129 } else {
130 // Reset the screen back buffer to the first buffer now that drawing is done
131 screen.activateBackBuffer1();
132 }
133
134 assert(IS_SERRATED_SCALPEL);
135 ((ScalpelUserInterface *)_vm->_ui)->_oldUse = -1;
136 }
137
invCommands(bool slamIt)138 void ScalpelInventory::invCommands(bool slamIt) {
139 ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen;
140 UserInterface &ui = *_vm->_ui;
141
142 if (slamIt) {
143 screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1),
144 _invMode == INVMODE_EXIT ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND,
145 true, _fixedTextExit);
146 screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1),
147 _invMode == INVMODE_LOOK ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND,
148 true, _fixedTextLook);
149 screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1),
150 _invMode == INVMODE_USE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
151 true, _fixedTextUse);
152 screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1),
153 _invMode == INVMODE_GIVE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
154 true, _fixedTextGive);
155 screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1),
156 _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND,
157 "^^"); // 2 arrows pointing to the left
158 screen.print(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1 + 1),
159 _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND,
160 "^"); // 2 arrows pointing to the left
161 screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1),
162 (_holdings - _invIndex <= 6) ? COMMAND_NULL : COMMAND_FOREGROUND,
163 "_"); // 1 arrow pointing to the right
164 screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1),
165 (_holdings - _invIndex <= 6) ? COMMAND_NULL : COMMAND_FOREGROUND,
166 "__"); // 2 arrows pointing to the right
167 if (_invMode != INVMODE_LOOK)
168 ui.clearInfo();
169 } else {
170 screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1),
171 _invMode == INVMODE_EXIT ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
172 false, _fixedTextExit);
173 screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1),
174 _invMode == INVMODE_LOOK ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
175 false, _fixedTextLook);
176 screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1),
177 _invMode == INVMODE_USE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
178 false, _fixedTextUse);
179 screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1),
180 _invMode == INVMODE_GIVE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
181 false, _fixedTextGive);
182 screen.gPrint(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1),
183 _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND,
184 "^^"); // 2 arrows pointing to the left
185 screen.gPrint(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1),
186 _invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND,
187 "^"); // 1 arrow pointing to the left
188 screen.gPrint(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1),
189 (_holdings - _invIndex < 7) ? COMMAND_NULL : COMMAND_FOREGROUND,
190 "_"); // 1 arrow pointing to the right
191 screen.gPrint(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1),
192 (_holdings - _invIndex < 7) ? COMMAND_NULL : COMMAND_FOREGROUND,
193 "__"); // 2 arrows pointing to the right
194 }
195 }
196
highlight(int index,byte color)197 void ScalpelInventory::highlight(int index, byte color) {
198 Screen &screen = *_vm->_screen;
199 Surface &bb = *screen.getBackBuffer();
200 int slot = index - _invIndex;
201 ImageFrame &frame = (*_invShapes[slot])[0];
202
203 bb.fillRect(Common::Rect(8 + slot * 52, 165, (slot + 1) * 52, 194), color);
204 bb.SHtransBlitFrom(frame, Common::Point(6 + slot * 52 + ((47 - frame._width) / 2),
205 163 + ((33 - frame._height) / 2)));
206 screen.slamArea(8 + slot * 52, 165, 44, 30);
207 }
208
refreshInv()209 void ScalpelInventory::refreshInv() {
210 Screen &screen = *_vm->_screen;
211 Talk &talk = *_vm->_talk;
212 ScalpelUserInterface &ui = *(ScalpelUserInterface *)_vm->_ui;
213
214 ui._invLookFlag = true;
215 freeInv();
216
217 ui._infoFlag = true;
218 ui.clearInfo();
219
220 screen._backBuffer2.SHblitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y),
221 Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
222 ui.examine();
223
224 if (!talk._talkToAbort) {
225 screen._backBuffer2.SHblitFrom((*ui._controlPanel)[0], Common::Point(0, CONTROLS_Y));
226 loadInv();
227 }
228 }
229
putInv(InvSlamMode slamIt)230 void ScalpelInventory::putInv(InvSlamMode slamIt) {
231 ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen;
232 UserInterface &ui = *_vm->_ui;
233
234 // If an inventory item has disappeared (due to using it or giving it),
235 // a blank space slot may have appeared. If so, adjust the inventory
236 if (_invIndex > 0 && _invIndex > (_holdings - (int)_invShapes.size())) {
237 --_invIndex;
238 freeGraphics();
239 loadGraphics();
240 }
241
242 if (slamIt != SLAM_SECONDARY_BUFFER) {
243 screen.makePanel(Common::Rect(6, 163, 54, 197));
244 screen.makePanel(Common::Rect(58, 163, 106, 197));
245 screen.makePanel(Common::Rect(110, 163, 158, 197));
246 screen.makePanel(Common::Rect(162, 163, 210, 197));
247 screen.makePanel(Common::Rect(214, 163, 262, 197));
248 screen.makePanel(Common::Rect(266, 163, 314, 197));
249 }
250
251 // Iterate through displaying up to 6 objects at a time
252 for (int idx = _invIndex; idx < _holdings && (idx - _invIndex) < (int)_invShapes.size(); ++idx) {
253 int itemNum = idx - _invIndex;
254 Surface &bb = (slamIt == SLAM_SECONDARY_BUFFER) ? screen._backBuffer2 : *screen.getBackBuffer();
255 Common::Rect r(8 + itemNum * 52, 165, 51 + itemNum * 52, 194);
256
257 // Draw the background
258 if (idx == ui._selector) {
259 bb.fillRect(r, BUTTON_BACKGROUND);
260 }
261 else if (slamIt == SLAM_SECONDARY_BUFFER) {
262 bb.fillRect(r, BUTTON_MIDDLE);
263 }
264
265 // Draw the item image
266 ImageFrame &frame = (*_invShapes[itemNum])[0];
267 bb.SHtransBlitFrom(frame, Common::Point(6 + itemNum * 52 + ((47 - frame._width) / 2),
268 163 + ((33 - frame._height) / 2)));
269 }
270
271 if (slamIt == SLAM_DISPLAY)
272 screen.slamArea(6, 163, 308, 34);
273
274 if (slamIt != SLAM_SECONDARY_BUFFER)
275 ui.clearInfo();
276
277 if (slamIt == 0) {
278 invCommands(0);
279 }
280 else if (slamIt == SLAM_SECONDARY_BUFFER) {
281 screen.activateBackBuffer2();
282 invCommands(0);
283 screen.activateBackBuffer1();
284 }
285 }
286
loadInv()287 void ScalpelInventory::loadInv() {
288 // Exit if the inventory names are already loaded
289 if (_names.size() > 0)
290 return;
291
292 // Load the inventory names
293 Common::SeekableReadStream *stream = _vm->_res->load("invent.txt");
294
295 int streamSize = stream->size();
296 while (stream->pos() < streamSize) {
297 Common::String name;
298 char c;
299 while ((c = stream->readByte()) != 0)
300 name += c;
301
302 _names.push_back(name);
303 }
304
305 delete stream;
306
307 loadGraphics();
308 }
309
310 } // End of namespace Scalpel
311
312 } // End of namespace Sherlock
313