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 #include "dragons/cursor.h"
23 #include "dragons/actor.h"
24 #include "dragons/actorresource.h"
25 #include "dragons/dragons.h"
26 #include "dragons/dragonimg.h"
27 #include "dragons/dragonini.h"
28 #include "dragons/dragonobd.h"
29 #include "dragons/inventory.h"
30 #include "dragons/scene.h"
31 #include "dragons/scriptopcodes.h"
32 #include "dragons/screen.h"
33
34 namespace Dragons {
35
Cursor(DragonsEngine * vm)36 Cursor::Cursor(DragonsEngine *vm): _vm(vm), _actor(0), _x(0), _y(0) {
37 _sequenceID = 0;
38 _data_800728b0_cursor_seqID = 0;
39 _iniUnderCursor = 0;
40 _performActionTargetINI = 0;
41 _objectInHandSequenceID = 0;
42 _cursorActivationSeqOffset = 0;
43 _iniItemInHand = 0;
44 _handPointerSequenceID = _vm->getCursorHandPointerSequenceID();
45 }
46
init(ActorManager * actorManager,DragonINIResource * dragonINIResource)47 void Cursor::init(ActorManager *actorManager, DragonINIResource *dragonINIResource) {
48 _sequenceID = 0;
49 _actor = actorManager->loadActor(0, 0); //Load cursor
50 _actor->_x_pos = _x = 160;
51 _actor->_y_pos = _y = 100;
52 _actor->_priorityLayer = 6;
53 _actor->_flags = 0;
54 _actor->_scale = DRAGONS_ENGINE_SPRITE_100_PERCENT_SCALE;
55 _actor->updateSequence(_sequenceID);
56 _actor->_flags |= (ACTOR_FLAG_40 | Dragons::ACTOR_FLAG_80 | Dragons::ACTOR_FLAG_100 |
57 ACTOR_FLAG_200);
58
59 dragonINIResource->getFlickerRecord()->actor = _actor; //TODO is this correct?
60 dragonINIResource->getFlickerRecord()->flags |= INI_FLAG_1;
61 _iniUnderCursor = 0;
62 _iniItemInHand = 0;
63 _objectInHandSequenceID = 0;
64 _cursorActivationSeqOffset = 0;
65 _data_800728b0_cursor_seqID = 0;
66 _performActionTargetINI = 0;
67 }
68
69
update()70 void Cursor::update() {
71 if (!_vm->isFlagSet(ENGINE_FLAG_8) || _vm->isFlagSet(Dragons::ENGINE_FLAG_100)) {
72 return;
73 }
74 // TODO update cursor from inputs here.
75
76 // 0x800280b8
77 if (_sequenceID == 0 && _vm->_inventory->isOpen()) {
78 _sequenceID = 1;
79 }
80
81 _actor->_x_pos = _x;
82 _actor->_y_pos = _y;
83
84 // 0x80028104
85 if (_iniUnderCursor != 0
86 && ((_iniUnderCursor & 0x8000 && _vm->_inventory->isOpen())
87 ||(!(_iniUnderCursor & 0x8000) && _vm->getINI(_iniUnderCursor - 1)->flags & 0x80))) {
88 if (_actor->_sequenceID != _handPointerSequenceID) {
89 _actor->updateSequence(_handPointerSequenceID);
90 }
91 return;
92 }
93 int32 inventorySequenceID = _vm->_inventory->getSequenceId();
94 if ((_iniUnderCursor == 0x8001) && (inventorySequenceID == 1)) {
95 if (_actor->_sequenceID != _handPointerSequenceID) {
96 _actor->updateSequence(_handPointerSequenceID);
97 }
98 return;
99 }
100
101 if (_iniUnderCursor == 0x8002 && inventorySequenceID == 4) {//goto LAB_80028204;
102 if (_actor->_sequenceID != _handPointerSequenceID) {
103 _actor->updateSequence(_handPointerSequenceID);
104 }
105 return;
106 }
107
108 if (_iniUnderCursor != 0x8002 || (inventorySequenceID != 1 && inventorySequenceID != 3)) {
109 if ((_iniUnderCursor != 0x8001) || ((inventorySequenceID != 0 && (inventorySequenceID != 3)))) {
110 if (_sequenceID == 5) {
111 uint16 uVar1 = (uint) _objectInHandSequenceID;
112 if (_cursorActivationSeqOffset != 0) {
113 uVar1 = uVar1 + 1;
114 }
115 if (uVar1 == (uint) _actor->_sequenceID) {
116 return;
117 }
118 _actor->updateSequence((uint) _objectInHandSequenceID + (uint) (_cursorActivationSeqOffset != 0));
119 } else {
120 if (_sequenceID + (uint) _cursorActivationSeqOffset != (uint) _actor->_sequenceID) {
121 _actor->updateSequence(_sequenceID + (uint) _cursorActivationSeqOffset);
122 }
123 }
124 return;
125 }
126 }
127
128 if (_iniItemInHand == 0) {
129 if (_actor->_sequenceID != _handPointerSequenceID) {
130 _actor->updateSequence(_handPointerSequenceID);
131 }
132 return;
133 } else {
134 if ((uint)_actor->_sequenceID != (uint)_objectInHandSequenceID + 1) {
135 _actor->updateSequence((uint)_objectInHandSequenceID + 1);
136 }
137 }
138
139 // 0x_800281c0
140 }
141
updateVisibility()142 void Cursor::updateVisibility() {
143 if (_vm->isFlagSet(ENGINE_FLAG_8) && !_vm->isUnkFlagSet(Dragons::ENGINE_UNK1_FLAG_10)) {
144 _actor->_priorityLayer = 9;
145 } else {
146 _actor->_priorityLayer = 0;
147 }
148 }
149
updatePosition(int16 x,int16 y)150 void Cursor::updatePosition(int16 x, int16 y) {
151 _x = x;
152 _y = y;
153 }
154
updateINIUnderCursor()155 int16 Cursor::updateINIUnderCursor() {
156 if (_vm->isFlagSet(ENGINE_FLAG_10)) {
157 int16 xOffset = 0;
158 if (_vm->_inventory->getSequenceId() == 0 || _vm->_inventory->getSequenceId() == 2) {
159 if (_vm->_inventory->getPositionIndex() == 1 || _vm->_inventory->getPositionIndex() == 3) {
160 xOffset = 0x32;
161 }
162 }
163 Common::Point inventoryPosition = _vm->_inventory->getPosition();
164 if (_x >= inventoryPosition.x + 0xa + xOffset
165 && _x < inventoryPosition.x + 0x35 + xOffset
166 && _y >= inventoryPosition.y + 0xa
167 && _y < inventoryPosition.y + 0x25) {
168 _iniUnderCursor = 0x8001;
169 return _iniUnderCursor;
170 }
171
172 if (_x >= inventoryPosition.x + 0x36
173 && _x < inventoryPosition.x + 0x5f
174 && _y >= inventoryPosition.y + 0xa
175 && _y < inventoryPosition.y + 0x25
176 && _vm->_inventory->getPositionIndex() != 0
177 && _vm->_inventory->getPositionIndex() != 2) {
178 _iniUnderCursor = 0x8002;
179 return _iniUnderCursor;
180 }
181 }
182
183 // TODO 0x80028940
184 if (_vm->_inventory->getState() == InventoryOpen) {
185 _iniUnderCursor = _vm->_inventory->getIniAtPosition(_x, _y);
186 return _iniUnderCursor;
187 }
188
189 return updateIniFromScene();
190 }
191
updateIniFromScene()192 int16 Cursor::updateIniFromScene() {
193 int16 cursorX = _x + _vm->_scene->_camera.x;
194 int16 cursorY = _y + _vm->_scene->_camera.y;
195 int16 cursorTileX = cursorX / 32;
196 int16 cursorTileY = cursorY / 8;
197 int16 data_80072890_orig = _performActionTargetINI;
198 int16 data_800728b0_cursor_seqID_orig = _data_800728b0_cursor_seqID;
199
200 for (int i = 0; i <_vm->_dragonINIResource->totalRecords(); i++) {
201 DragonINI *ini = _vm->_dragonINIResource->getRecord(i);
202 if (ini->sceneId != _vm->_scene->getSceneId()) {
203 // 0x80028be4
204 } else if (!_vm->_dragonINIResource->isFlicker(ini) && !(ini->flags & 0x40)) {
205 int16 cursorOverIni = 0;
206 // 0x80028a10
207 if (ini->flags & 1) {
208 // 0x80028b18
209 if (ini->actor->isFlagSet(ACTOR_FLAG_40) && ini->actor->isFlagSet(ACTOR_FLAG_8)) {
210 int16 iniActorXPosition = ini->actor->_x_pos - ini->actor->_frame->xOffset;
211 int16 iniActorYPosition = ini->actor->_y_pos - ini->actor->_frame->yOffset;
212 if (cursorX >= iniActorXPosition && cursorX < iniActorXPosition + ini->actor->_frame->width
213 && cursorY >= iniActorYPosition && cursorY < iniActorYPosition + ini->actor->_frame->height) {
214 cursorOverIni = i + 1;
215 }
216 }
217 } else {
218 // 0x80028a24
219 if (ini->imgId != -1) {
220 Img *img = _vm->_dragonImg->getImg((uint32)ini->imgId);
221 if (img->field_e - 1 >= 1) { // TODO this is >= 2 in the original.
222 if (cursorTileX >= img->x && cursorTileX < img->x + img->w && cursorTileY >= img->y && cursorTileY < img->y + img->h) {
223 cursorOverIni = i + 1;
224 }
225 } else {
226 // 0x80028ac4
227 if (cursorX >= img->x && cursorX < img->x + img->w && cursorY >= img->y && cursorY < img->y + img->h) {
228 cursorOverIni = i + 1;
229 }
230 }
231 }
232 }
233 if (cursorOverIni != 0) {
234 // 0x80028bf0
235 // _iniUnderCursor = cursorOverIni;
236 _performActionTargetINI = _iniUnderCursor;
237 _data_800728b0_cursor_seqID = _sequenceID;
238
239 if (ini->flags & 0x800) {
240 _performActionTargetINI = cursorOverIni;
241 uint32 newSeqId = 1;
242 for (int idx = 0; idx < 5; idx++) {
243 _data_800728b0_cursor_seqID = idx;
244 byte *obd = _vm->_dragonOBD->getFromOpt(cursorOverIni - 1); //_dragonRMS->getAfterSceneLoadedScript(sceneId);
245 ScriptOpCall scriptOpCall(obd + 8, READ_LE_UINT32(obd));
246
247 // uVar17 = uVar15;
248 // local_58 = dragon_Obd_Offset + *(int *)(uVar16 * 8 + dragon_Opt_Offset + -8) + 8;
249 // data_800728b0 = idx;
250 // local_54 = read_int32();
251 // local_54 = local_54 + local_58;
252 // uVar6 = ;
253 if (executeScript(scriptOpCall, 0)) {
254 newSeqId = idx;
255 break;
256 }
257 }
258
259 _sequenceID = newSeqId;
260 _iniUnderCursor = cursorOverIni;
261 _performActionTargetINI = _iniUnderCursor;
262 _data_800728b0_cursor_seqID = _sequenceID;
263 return _iniUnderCursor;
264 }
265 if (_sequenceID != 0) {
266 _iniUnderCursor = cursorOverIni;
267 _performActionTargetINI = data_80072890_orig;
268 _data_800728b0_cursor_seqID = data_800728b0_cursor_seqID_orig;
269 return _iniUnderCursor;
270 }
271 byte *obd = _vm->_dragonOBD->getFromOpt(cursorOverIni - 1); //_dragonRMS->getAfterSceneLoadedScript(sceneId);
272 ScriptOpCall scriptOpCall(obd + 8, READ_LE_UINT32(obd));
273
274 // local_48 = dragon_Obd_Offset + *(int *)(uVar16 * 8 + dragon_Opt_Offset + -8) + 8;
275 // local_44 = read_int32();
276 // local_44 = local_44 + local_48;
277 if (executeScript(scriptOpCall, 0)) {
278 _iniUnderCursor = cursorOverIni;
279 _performActionTargetINI = data_80072890_orig;
280 _data_800728b0_cursor_seqID = data_800728b0_cursor_seqID_orig;
281 return _iniUnderCursor;
282 }
283 }
284 }
285 }
286 _iniUnderCursor = 0;
287 _performActionTargetINI = data_80072890_orig;
288 _data_800728b0_cursor_seqID = data_800728b0_cursor_seqID_orig;
289 return 0;
290 }
291
executeScript(ScriptOpCall & scriptOpCall,uint16 unkFlag)292 int16 Cursor::executeScript(ScriptOpCall &scriptOpCall, uint16 unkFlag) {
293 int16 temp = _vm->_scriptOpcodes->_scriptTargetINI;
294 byte *codeStart = scriptOpCall._code;
295
296 scriptOpCall._field8 = 1;
297 scriptOpCall._result = 0;
298 _vm->_scriptOpcodes->_numDialogStackFramesToPop = 0;
299 _vm->_scriptOpcodes->executeScriptLoop(scriptOpCall);
300
301 if (!(scriptOpCall._result & 1) && _data_800728b0_cursor_seqID == 5 && unkFlag != 0) {
302 _vm->_scriptOpcodes->_scriptTargetINI = -1;
303 scriptOpCall._code = codeStart;
304 scriptOpCall._field8 = 1;
305 scriptOpCall._result = 0;
306 _vm->_scriptOpcodes->_numDialogStackFramesToPop = 0;
307 _vm->_scriptOpcodes->executeScriptLoop(scriptOpCall);
308 _vm->_scriptOpcodes->_scriptTargetINI = temp;
309 if (scriptOpCall._result & 1) {
310 scriptOpCall._result |= 2;
311 }
312 }
313 return scriptOpCall._result & 3;
314 }
315
selectPreviousCursor()316 void Cursor::selectPreviousCursor() {
317 int16 newSequenceID = _sequenceID - 1;
318 InventoryState inventoryType = _vm->_inventory->getState();
319 if (newSequenceID == 0 && (inventoryType == InventoryOpen || inventoryType == InventionBookOpen)) {
320 newSequenceID = _sequenceID - 2;
321 }
322 _sequenceID = newSequenceID;
323 if (_sequenceID == 3 && inventoryType == InventoryOpen) {
324 _sequenceID = 1;
325 }
326 if (_sequenceID == 2) {
327 _sequenceID = 1;
328 }
329 if (_sequenceID == -1) {
330 _sequenceID = _iniItemInHand == 0 ? 4 : 5;
331 }
332 }
333
updateSequenceID(int16 sequenceID)334 void Cursor::updateSequenceID(int16 sequenceID) {
335 _sequenceID = sequenceID;
336 _actor->updateSequence(_sequenceID);
337 }
338
setActorFlag400()339 void Cursor::setActorFlag400() {
340 _actor->setFlag(ACTOR_FLAG_400);
341 }
342
clearActorFlag400()343 void Cursor::clearActorFlag400() {
344 _actor->clearFlag(ACTOR_FLAG_400);
345 }
346
getPalette()347 byte *Cursor::getPalette() {
348 return _actor->_actorResource->getPalette();
349 }
350
updateActorPosition(int16 x,int16 y)351 void Cursor::updateActorPosition(int16 x, int16 y) {
352 updatePosition(x, y);
353 _actor->_x_pos = _x;
354 _actor->_y_pos = _y;
355 }
356
357 } // End of namespace Dragons
358