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 "hdb/hdb.h"
24 #include "hdb/ai.h"
25 #include "hdb/gfx.h"
26 #include "hdb/lua-script.h"
27 #include "hdb/map.h"
28 #include "hdb/sound.h"
29 #include "hdb/window.h"
30 
31 namespace HDB {
32 
33 static const char *cineTypeStr[] = {
34 	"C_NO_COMMAND",
35 	"C_STOPCINE",
36 	"C_LOCKPLAYER",
37 	"C_UNLOCKPLAYER",
38 	"C_SETCAMERA",
39 	"C_MOVECAMERA",
40 	"C_WAIT",
41 	"C_WAITUNTILDONE",
42 	"C_MOVEENTITY",
43 	"C_DIALOG",
44 	"C_ANIMENTITY",
45 	"C_RESETCAMERA",
46 	"C_SETENTITY",
47 	"C_STARTMAP",
48 	"C_MOVEPIC",
49 	"C_MOVEMASKEDPIC",
50 	"C_DRAWPIC",
51 	"C_DRAWMASKEDPIC",
52 	"C_FADEIN",
53 	"C_FADEOUT",
54 	"C_SPAWNENTITY",
55 	"C_PLAYSOUND",
56 	"C_CLEAR_FG",
57 	"C_SET_FG",
58 	"C_SET_BG",
59 	"C_FUNCTION",
60 	"C_ENTITYFACE",
61 	"C_USEENTITY",
62 	"C_REMOVEENTITY",
63 	"C_SETANIMFRAME",
64 	"C_TEXTOUT",
65 	"C_CENTERTEXTOUT",
66 	"C_PLAYVOICE",
67 
68 	"C_ENDLIST"
69 };
70 
processCines()71 void AI::processCines() {
72 	if (!_cineActive)
73 		return;
74 
75 	// Make sure Dialogs are timing out
76 	g_hdb->_window->checkDialogClose(0, 0);
77 
78 	// Make sure Cine Pics are drawing
79 	for (int i = 0; i < _numCineBlitList; i++) {
80 		if (_cineBlitList[i]->masked == false)
81 			_cineBlitList[i]->pic->draw(_cineBlitList[i]->x, _cineBlitList[i]->y);
82 		else
83 			_cineBlitList[i]->pic->drawMasked(_cineBlitList[i]->x, _cineBlitList[i]->y);
84 	}
85 
86 	// Check for Game Pause
87 	if (g_hdb->getPause())
88 		return;
89 
90 	bool bailOut = false;
91 	bool complete = false;
92 
93 	for (uint i = 0; i < _cine.size(); i++) {
94 		debug(3, "processCines: [%d] %s now: %d  start: %d delay: %d", i, cineTypeStr[_cine[i]->cmdType],
95 				g_system->getMillis(), _cine[i]->start, _cine[i]->delay);
96 
97 		switch (_cine[i]->cmdType) {
98 		case C_STOPCINE:
99 			{
100 				char func[64];
101 				memset(func, 0, 64);
102 
103 				if (_cine[i]->title)
104 					Common::strlcpy(func, _cine[i]->title, 64);
105 
106 				cineCleanup();
107 				if (func[0])
108 					g_hdb->_lua->callFunction(func, 0);
109 			}
110 			break;
111 		case C_STARTMAP:
112 			{
113 				const char *title = _cine[i]->title;
114 				// free all gfx alloc'ed during cine
115 				cineFreeGfx();
116 				_cineActive = false;
117 				_playerLock = false;
118 				_cameraLock = false;
119 				g_hdb->_window->setInfobarDark(0);
120 				g_hdb->_gfx->setPointerState(1);
121 				_cine.resize(0);
122 				_numCineFreeList = 0;
123 				_numCineBlitList = 0;
124 				// if cine is aborted and an abort function was specified, call it
125 				if (_cineAborted && _cineAbortFunc)
126 					g_hdb->_lua->callFunction(_cineAbortFunc, 0);
127 				g_hdb->changeMap(title);
128 				return;
129 			}
130 			break;
131 		case C_LOCKPLAYER:
132 			_playerLock = true;
133 			complete = true;
134 			if (_player)
135 				stopEntity(_player);
136 			clearWaypoints();
137 			break;
138 		case C_UNLOCKPLAYER:
139 			_playerLock = false;
140 			complete = true;
141 			break;
142 		case C_SETCAMERA:
143 			_cameraX = _cine[i]->x;
144 			_cameraY = _cine[i]->y;
145 			g_hdb->_map->centerMapXY((int)_cameraX + 16, (int)_cameraY + 16);
146 			_cameraLock = true;
147 			complete = true;
148 			break;
149 		case C_RESETCAMERA:
150 			{
151 				_cameraLock = false;
152 				int px, py;
153 				g_hdb->_ai->getPlayerXY(&px, &py);
154 				g_hdb->_map->centerMapXY(px + 16, py + 16);
155 				complete = true;
156 			}
157 			break;
158 		case C_MOVECAMERA:
159 			_cameraLock = true;
160 			if (!(_cine[i]->start)) {
161 				debug(3, "C_MOVECAMERA: [%d] now: x: %f, y: %f, speed: %d", i, _cine[i]->x, _cine[i]->y, _cine[i]->speed);
162 				_cine[i]->xv = (((double)_cine[i]->x) - _cameraX) / (double)_cine[i]->speed;
163 				_cine[i]->yv = (((double)_cine[i]->y) - _cameraY) / (double)_cine[i]->speed;
164 				_cine[i]->start = 1;
165 			}
166 			_cameraX += _cine[i]->xv;
167 			_cameraY += _cine[i]->yv;
168 			debug(3, "C_MOVECAMERA: _cine[%d]->xv: %f, _cine[%d]->yv: %f", i, _cine[i]->xv, i, _cine[i]->yv);
169 			debug(3, "C_MOVECAMERA: abs(_cameraX - _cine[i]->x): %f, abs(_cameraY - _cine[i]->y): %f", fabs(_cameraX - _cine[i]->x), fabs(_cameraY - _cine[i]->y));
170 			if (fabs(_cameraX - _cine[i]->x) <= 1 && fabs(_cameraY - _cine[i]->y) <= 1) {
171 				_cameraX = _cine[i]->x;
172 				_cameraY = _cine[i]->y;
173 				complete = true;
174 			}
175 			g_hdb->_map->centerMapXY((int)_cameraX + 16, (int)_cameraY + 16);
176 			break;
177 		case C_WAIT:
178 			if (!(_cine[i]->start)) {
179 				_cine[i]->start = 1;
180 				_cine[i]->delay = g_system->getMillis() + _cine[i]->delay * 1000;
181 			} else if (_cine[i]->delay < g_system->getMillis())
182 				complete = true;
183 			else
184 				bailOut = true;
185 			break;
186 		case C_WAITUNTILDONE:
187 			if (!i)
188 				complete = true;
189 			else
190 				bailOut = true;
191 
192 			break;
193 		case C_SETENTITY:
194 			_cine[i]->e = locateEntity(_cine[i]->string);
195 			if (_cine[i]->e) {
196 				_cine[i]->e->tileX = (int)_cine[i]->x / kTileWidth;
197 				_cine[i]->e->x = (int)_cine[i]->x;
198 				_cine[i]->e->tileY = (int)_cine[i]->y / kTileHeight;
199 				_cine[i]->e->y = (int)_cine[i]->y;
200 				_cine[i]->e->level = (int)_cine[i]->x2;
201 				debug(2, "Found '%s' in setEntity", _cine[i]->string);
202 			} else
203 				warning("Can't locate '%s' in setEntity", _cine[i]->string);
204 
205 			complete = true;
206 			break;
207 		case C_MOVEENTITY:
208 			if (!_cine[i]->start) {
209 				AIEntity *e = locateEntity(_cine[i]->title);
210 				if (e) {
211 					_cine[i]->e = e;
212 					_cine[i]->e->moveSpeed = _cine[i]->speed;
213 					_cine[i]->e->level = (int)_cine[i]->x2;
214 					setEntityGoal(_cine[i]->e, (int)_cine[i]->x, (int)_cine[i]->y);
215 					_cine[i]->start = 1;
216 				} else
217 					warning("Can't locate '%s' in moveEntity", _cine[i]->title);
218 			} else {
219 				debug(3, "C_MOVEENTITY: %d, %s tileX: %d, goalX: %d tileY %d, goalY: %d", i, AIType2Str(_cine[i]->e->type), _cine[i]->e->tileX, _cine[i]->e->goalX, _cine[i]->e->tileY, _cine[i]->e->goalY);
220 				if (!_cine[i]->e->goalX)
221 					complete = true;
222 			}
223 			break;
224 		case C_ANIMENTITY:
225 			if (!_cine[i]->start) {
226 				AIEntity *e = locateEntity(_cine[i]->title);
227 				if (e) {
228 					_cine[i]->e = e;
229 					e->state = (AIState)_cine[i]->speed;
230 					_cine[i]->start = 1;
231 					if (_cine[i]->end) // Loop ?
232 						complete = true;
233 					e->animFrame = 0;
234 					e->animDelay = e->animCycle;
235 					animEntFrames(e);
236 				} else {
237 					warning("Can't locate '%s' in animEntity", _cine[i]->title);
238 					complete = true;
239 				}
240 			} else {
241 				AIEntity *e = _cine[i]->e;
242 				if (!e->animFrame && e->animDelay == e->animCycle) {
243 					e->state = STATE_STANDDOWN;
244 					e->animFrame = 0;
245 					e->animDelay = e->animCycle;
246 					complete = true;
247 				}
248 			}
249 			break;
250 		case C_SETANIMFRAME:
251 			{
252 				AIEntity *e = locateEntity(_cine[i]->title);
253 				if (e) {
254 					e->state = (AIState)_cine[i]->start;
255 					e->animFrame = _cine[i]->end;
256 					e->animDelay = e->animCycle;
257 					animEntFrames(e);
258 					e->state = STATE_NONE;
259 					complete = true;
260 				}
261 			}
262 			break;
263 		case C_ENTITYFACE:
264 			{
265 				AIEntity *e = locateEntity(_cine[i]->title);
266 
267 				if (e) {
268 					int d = (int)_cine[i]->x;
269 					e->dir = (AIDir)d;
270 					switch (e->dir) {
271 					case DIR_UP:
272 						e->state = STATE_STANDUP;
273 						break;
274 					case DIR_DOWN:
275 						e->state = STATE_STANDDOWN;
276 						break;
277 					case DIR_LEFT:
278 						e->state = STATE_STANDLEFT;
279 						break;
280 					case DIR_RIGHT:
281 						e->state = STATE_STANDRIGHT;
282 						break;
283 					default:
284 						break;
285 					}
286 				} else
287 					warning("Can't find %s to ENTITYFACE", _cine[i]->title);
288 
289 				complete = true;
290 			}
291 			break;
292 		case C_DIALOG:
293 			if (_cine[i]->start) {
294 				g_hdb->_window->openDialog(_cine[i]->title, -1, _cine[i]->string, 0, nullptr);
295 				g_hdb->_window->setDialogDelay(_cine[i]->delay);
296 				_cine[i]->start = 0;
297 			} else if (g_hdb->_window->getDialogDelay() < g_hdb->getTimeSlice())
298 				complete = true;
299 			break;
300 		case C_TEXTOUT:
301 			if (!_cine[i]->start) {
302 				g_hdb->_window->textOut(_cine[i]->title, _cine[i]->x, _cine[i]->y, _cine[i]->end);
303 				_cine[i]->start = 1;
304 			} else if (!g_hdb->_window->textOutActive())
305 				complete = true;
306 			break;
307 		case C_CENTERTEXTOUT:
308 			if (!_cine[i]->start) {
309 				g_hdb->_window->centerTextOut(_cine[i]->title, _cine[i]->y, _cine[i]->end);
310 				_cine[i]->start = 1;
311 			} else if (!g_hdb->_window->textOutActive())
312 				complete = true;
313 			break;
314 		case C_DRAWPIC:
315 			{
316 				Picture *p = cineFindInBlitList(_cine[i]->id);
317 				if (p == nullptr) {
318 					p = g_hdb->_gfx->loadPic(_cine[i]->string);
319 					cineAddToFreeList(p);
320 					cineAddToBlitList(_cine[i]->id, p, (int)_cine[i]->x, (int)_cine[i]->y, false);
321 				}
322 				_cine[i]->pic = p;
323 				_cine[i]->pic->draw((int)_cine[i]->x, (int)_cine[i]->y);
324 				complete = true;
325 			}
326 			break;
327 		case C_DRAWMASKEDPIC:
328 			{
329 				Picture *p = cineFindInBlitList(_cine[i]->id);
330 				if (p == nullptr) {
331 					p = g_hdb->_gfx->loadPic(_cine[i]->string);
332 					cineAddToFreeList(p);
333 					cineAddToBlitList(_cine[i]->id, p, (int)_cine[i]->x, (int)_cine[i]->y, true);
334 				}
335 				_cine[i]->pic = p;
336 				_cine[i]->pic->drawMasked((int)_cine[i]->x, (int)_cine[i]->y);
337 				complete = true;
338 			}
339 			break;
340 
341 		case C_MOVEPIC:
342 			if (!_cine[i]->start) {
343 				Picture *pic = cineFindInBlitList(_cine[i]->id);
344 				if (!pic) {
345 					pic = g_hdb->_gfx->loadPic(_cine[i]->string);
346 					cineAddToFreeList(pic);
347 				} else
348 					cineRemoveFromBlitList(_cine[i]->id);
349 				_cine[i]->pic = pic;
350 				_cine[i]->start = 1;
351 			}
352 
353 			cineRemoveFromBlitList(_cine[i]->id);
354 			_cine[i]->x += _cine[i]->xv;
355 			_cine[i]->y += _cine[i]->yv;
356 			cineAddToBlitList(_cine[i]->id, _cine[i]->pic, (int)_cine[i]->x, (int)_cine[i]->y, false);
357 			if (abs((int)(_cine[i]->x - _cine[i]->x2)) <= 1 && abs((int)(_cine[i]->y - _cine[i]->y2)) <= 1)
358 				complete = true;
359 			break;
360 
361 		case C_MOVEMASKEDPIC:
362 			if (!_cine[i]->start) {
363 				Picture *pic = cineFindInBlitList(_cine[i]->id);
364 				if (!pic) {
365 					pic = g_hdb->_gfx->loadPic(_cine[i]->string);
366 					cineAddToFreeList(pic);
367 				} else
368 					cineRemoveFromBlitList(_cine[i]->id);
369 				_cine[i]->pic = pic;
370 				_cine[i]->start = 1;
371 			}
372 
373 			cineRemoveFromBlitList(_cine[i]->id);
374 			_cine[i]->x += _cine[i]->xv;
375 			_cine[i]->y += _cine[i]->yv;
376 			cineAddToBlitList(_cine[i]->id, _cine[i]->pic, (int)_cine[i]->x, (int)_cine[i]->y, true);
377 			if (abs((int)(_cine[i]->x - _cine[i]->x2)) <= 1 && abs((int)(_cine[i]->y - _cine[i]->y2)) <= 1)
378 				complete = true;
379 			break;
380 
381 		case C_USEENTITY:
382 			for (Common::Array<AIEntity *>::iterator it = _ents->begin(); it != _ents->end(); ++it) {
383 				if (Common::matchString((*it)->entityName, _cine[i]->string, true))
384 					g_hdb->useEntity((*it));
385 			}
386 			for (int k = 0; k < kMaxActions; k++) {
387 				if (Common::matchString(_actions[k].entityName, _cine[i]->string, true)) {
388 					checkActionList(&_dummyPlayer, _actions[k].x1, _actions[k].y1, false);
389 					checkActionList(&_dummyPlayer, _actions[k].x2, _actions[k].y2, false);
390 				}
391 			}
392 			for (int j = 0; j < kMaxAutoActions; j++) {
393 				if (Common::matchString(_autoActions[j].entityName, _cine[i]->string, true) && !_autoActions[j].activated)
394 					checkAutoList(&_dummyPlayer, _autoActions[j].x, _autoActions[j].y);
395 			}
396 			complete = true;
397 			break;
398 		case C_PLAYSOUND:
399 			g_hdb->_sound->playSound((int)_cine[i]->start);
400 			complete = true;
401 			break;
402 		case C_PLAYVOICE:
403 			g_hdb->_sound->playVoice((int)_cine[i]->x, (int)_cine[i]->y);
404 			complete = true;
405 			break;
406 		case C_FADEIN:
407 			if (!_cine[i]->start) {
408 				g_hdb->_gfx->setFade(true, (bool)_cine[i]->end, _cine[i]->speed);
409 				_cine[i]->start = 1;
410 			} else if (!g_hdb->_gfx->isFadeActive())
411 				complete = true;
412 			break;
413 		case C_FADEOUT:
414 			if (!_cine[i]->start) {
415 				g_hdb->_gfx->setFade(false, (bool)_cine[i]->end, _cine[i]->speed);
416 				_cine[i]->start = 1;
417 			} else if (!g_hdb->_gfx->isFadeActive())
418 				complete = true;
419 			break;
420 		case C_SPAWNENTITY:
421 			{
422 				int x2 = (int)_cine[i]->x2;
423 				int y2 = (int)_cine[i]->y2;
424 				spawn((AIType)x2, (AIDir)y2, (int)_cine[i]->x, (int)_cine[i]->y, _cine[i]->title, _cine[i]->string,
425 					_cine[i]->id, (AIDir)_cine[i]->start, (int)_cine[i]->end, (int)_cine[i]->delay, (int)_cine[i]->speed, 1);
426 				complete = true;
427 			}
428 			break;
429 		case C_REMOVEENTITY:
430 			{
431 				AIEntity *e = locateEntity(_cine[i]->string);
432 				if (e)
433 					removeEntity(e);
434 				complete = true;
435 			}
436 			break;
437 		case C_CLEAR_FG:
438 			g_hdb->_map->setMapFGTileIndex((int)_cine[i]->x, (int)_cine[i]->y, -1);
439 			g_hdb->_map->removeFGTileAnimation((int)_cine[i]->x, (int)_cine[i]->y);
440 			complete = true;
441 			break;
442 		case C_SET_BG:
443 			g_hdb->_map->setMapBGTileIndex((int)_cine[i]->x, (int)_cine[i]->y, (int)_cine[i]->start);
444 			g_hdb->_map->addBGTileAnimation((int)_cine[i]->x, (int)_cine[i]->y);
445 			complete = true;
446 			break;
447 		case C_SET_FG:
448 			g_hdb->_map->setMapFGTileIndex((int)_cine[i]->x, (int)_cine[i]->y, (int)_cine[i]->start);
449 			g_hdb->_map->addFGTileAnimation((int)_cine[i]->x, (int)_cine[i]->y);
450 			complete = true;
451 			break;
452 		case C_FUNCTION:
453 			g_hdb->_lua->callFunction(_cine[i]->title, 0);
454 			complete = true;
455 			break;
456 		default:
457 			break;
458 		}
459 
460 		if (bailOut)
461 			return;
462 
463 		if (complete && _cine.size()) {
464 			delete _cine[i];
465 			_cine.remove_at(i);
466 			i--;
467 			complete = false;
468 		}
469 	}
470 }
471 
cineCleanup()472 void AI::cineCleanup() {
473 	cineFreeGfx();
474 	_cineActive = false;
475 	// If aborted and abort function specified, call it
476 	if (_cineAborted && _cineAbortFunc)
477 		g_hdb->_lua->callFunction(_cineAbortFunc, 0);
478 
479 	_cameraLock = false;
480 	_playerLock = false;
481 	g_hdb->_window->setInfobarDark(0);
482 	g_hdb->_gfx->setPointerState(1);
483 
484 	int px, py;
485 	getPlayerXY(&px, &py);
486 	g_hdb->_map->centerMapXY(px + 16, py + 16);
487 }
488 
cineAbort()489 void AI::cineAbort() {
490 	for (uint i = 0; i < _cine.size(); i++) {
491 		if (_cine[i]->cmdType == C_STARTMAP || _cine[i]->cmdType == C_STOPCINE)
492 			_cine[0] = _cine[i];
493 	}
494 
495 	_cine.resize(1);
496 
497 	g_hdb->_window->closeAll();
498 
499 	if (_player)
500 		stopEntity(_player);
501 	_cineAborted = true;
502 }
503 
cineAddToBlitList(const char * id,Picture * pic,int x,int y,bool masked)504 void AI::cineAddToBlitList(const char *id, Picture *pic, int x, int y, bool masked) {
505 	_cineBlitList[_numCineBlitList] = new CineBlit;
506 	_cineBlitList[_numCineBlitList]->id = id;
507 	_cineBlitList[_numCineBlitList]->pic = pic;
508 	_cineBlitList[_numCineBlitList]->x = x;
509 	_cineBlitList[_numCineBlitList]->y = y;
510 	_cineBlitList[_numCineBlitList]->masked = masked;
511 	_numCineBlitList++;
512 }
513 
cineFindInBlitList(const char * name)514 Picture *AI::cineFindInBlitList(const char *name) {
515 	for (int i = 0; i < _numCineBlitList; i++) {
516 		if (Common::matchString(_cineBlitList[i]->id, name, true))
517 			return _cineBlitList[i]->pic;
518 	}
519 	return nullptr;
520 }
521 
cineRemoveFromBlitList(const char * name)522 void AI::cineRemoveFromBlitList(const char *name) {
523 	for (int i = 0; i < _numCineBlitList; i++) {
524 		if (Common::matchString(_cineBlitList[i]->id, name, true)) {
525 			delete _cineBlitList[i];
526 			for (; i < _numCineBlitList - 1; i++)
527 				_cineBlitList[i] = _cineBlitList[i + 1];
528 			_numCineBlitList--;
529 			_cineBlitList[_numCineBlitList] = nullptr;
530 			return;
531 		}
532 	}
533 }
534 
cineAddToFreeList(Picture * pic)535 void AI::cineAddToFreeList(Picture *pic) {
536 	if (_numCineFreeList >= kMaxCineGfx) {
537 		warning("cineAddToFreeList: Too many gfx in Cinematic!");
538 		return;
539 	}
540 	_cineFreeList[_numCineFreeList] = pic;
541 	_numCineFreeList++;
542 }
543 
cineFreeGfx()544 void AI::cineFreeGfx() {
545 	for (int i = 0; i < _numCineFreeList; i++)
546 		delete _cineFreeList[i];
547 
548 	_numCineFreeList = 0;
549 }
550 
cineStart(bool abortable,const char * abortFunc)551 void AI::cineStart(bool abortable, const char *abortFunc) {
552 	_cineAbortable = abortable;
553 	_cineAborted = false;
554 	_cineAbortFunc = abortFunc;
555 	_numCineBlitList = 0;
556 	_numCineFreeList = 0;
557 	_cineActive = true;
558 	_playerLock = false;
559 	_cameraLock = false;
560 
561 	_cine.clear();
562 }
563 
cineStop(const char * funcNext)564 void AI::cineStop(const char *funcNext) {
565 	CineCommand *cmd = new CineCommand;
566 	cmd->cmdType = C_STOPCINE;
567 	cmd->title = funcNext;
568 	_cine.push_back(cmd);
569 }
570 
cineStartMap(const char * mapName)571 void AI::cineStartMap(const char *mapName) {
572 	CineCommand *cmd = new CineCommand;
573 	cmd->cmdType = C_STARTMAP;
574 	cmd->title = mapName;
575 	_cine.push_back(cmd);
576 }
577 
cineLockPlayer()578 void AI::cineLockPlayer() {
579 	CineCommand *cmd = new CineCommand;
580 	cmd->cmdType = C_LOCKPLAYER;
581 	_cine.push_back(cmd);
582 }
583 
cineUnlockPlayer()584 void AI::cineUnlockPlayer() {
585 	CineCommand *cmd = new CineCommand;
586 	cmd->cmdType = C_UNLOCKPLAYER;
587 	_cine.push_back(cmd);
588 }
589 
cineSetCamera(int x,int y)590 void AI::cineSetCamera(int x, int y) {
591 	CineCommand *cmd = new CineCommand;
592 	cmd->x = x * kTileWidth;
593 	cmd->y = y * kTileHeight;
594 	cmd->cmdType = C_SETCAMERA;
595 	_cine.push_back(cmd);
596 }
597 
cineResetCamera()598 void AI::cineResetCamera() {
599 	CineCommand *cmd = new CineCommand;
600 	cmd->cmdType = C_RESETCAMERA;
601 	_cine.push_back(cmd);
602 }
603 
cineMoveCamera(int x,int y,int speed)604 void AI::cineMoveCamera(int x, int y, int speed) {
605 	CineCommand *cmd = new CineCommand;
606 	cmd->start = 0;
607 	cmd->x = x * kTileWidth;
608 	cmd->y = y * kTileHeight;
609 	cmd->speed = speed;
610 	debug(2, "Setting up C_MOVECAMERA: x: %f, y: %f", cmd->x, cmd->y);
611 	cmd->cmdType = C_MOVECAMERA;
612 	_cine.push_back(cmd);
613 }
614 
cineWait(int seconds)615 void AI::cineWait(int seconds) {
616 	CineCommand *cmd = new CineCommand;
617 	cmd->start = 0;
618 	cmd->cmdType = C_WAIT;
619 	cmd->delay = seconds;
620 	_cine.push_back(cmd);
621 }
622 
cineWaitUntilDone()623 void AI::cineWaitUntilDone() {
624 	CineCommand *cmd = new CineCommand;
625 	cmd->cmdType = C_WAITUNTILDONE;
626 	_cine.push_back(cmd);
627 }
628 
cineSetEntity(const char * entName,int x,int y,int level)629 void AI::cineSetEntity(const char *entName, int x, int y, int level) {
630 	CineCommand *cmd = new CineCommand;
631 	cmd->string = entName;
632 	cmd->x = x * kTileWidth;
633 	cmd->y = y * kTileHeight;
634 	cmd->x2 = level;
635 	cmd->cmdType = C_SETENTITY;
636 	_cine.push_back(cmd);
637 }
638 
cineMoveEntity(const char * entName,int x,int y,int level,int speed)639 void AI::cineMoveEntity(const char *entName, int x, int y, int level, int speed) {
640 	CineCommand *cmd = new CineCommand;
641 	cmd->x = x;
642 	cmd->y = y;
643 	cmd->x2 = level;
644 	cmd->start = 0;
645 	cmd->speed = speed;
646 	cmd->title = entName;
647 	cmd->cmdType = C_MOVEENTITY;
648 	_cine.push_back(cmd);
649 }
650 
cineAnimEntity(const char * entName,AIState state,int loop)651 void AI::cineAnimEntity(const char *entName, AIState state, int loop) {
652 	CineCommand *cmd = new CineCommand;
653 	cmd->start = 0;
654 	cmd->title = entName;
655 	cmd->speed = state;
656 	cmd->end = loop;
657 	cmd->cmdType = C_ANIMENTITY;
658 	_cine.push_back(cmd);
659 }
660 
cineSetAnimFrame(const char * entName,AIState state,int frame)661 void AI::cineSetAnimFrame(const char *entName, AIState state, int frame) {
662 	CineCommand *cmd = new CineCommand;
663 	cmd->start = state;
664 	cmd->title = entName;
665 	cmd->end = frame;
666 	cmd->cmdType = C_SETANIMFRAME;
667 	_cine.push_back(cmd);
668 }
669 
cineEntityFace(const char * luaName,double dir)670 void AI::cineEntityFace(const char *luaName, double dir) {
671 	CineCommand *cmd = new CineCommand;
672 	cmd->title = luaName;
673 	cmd->x = dir;
674 	cmd->cmdType = C_ENTITYFACE;
675 	_cine.push_back(cmd);
676 }
677 
cineSpawnEntity(AIType t,AIDir d,int x,int y,const char * func_init,const char * func_action,const char * func_use,AIDir d2,int level,int value1,int value2)678 void AI::cineSpawnEntity(AIType t, AIDir d, int x, int y, const char *func_init, const char *func_action,
679 				const char *func_use, AIDir d2, int level, int value1, int value2) {
680 	CineCommand *cmd = new CineCommand;
681 	cmd->cmdType = C_SPAWNENTITY;
682 	cmd->x2 = (double)t;
683 	cmd->y2 = (double)d;
684 	cmd->x = (double)x;
685 	cmd->y = (double)y;
686 	cmd->title = func_init;
687 	cmd->string = func_action;
688 	cmd->id = func_use;
689 	cmd->start = (int)d2;
690 	cmd->end = level;
691 	cmd->delay = value1;
692 	cmd->speed = value2;
693 
694 	_cine.push_back(cmd);
695 }
696 
cineRemoveEntity(const char * entName)697 void AI::cineRemoveEntity(const char *entName) {
698 	CineCommand *cmd = new CineCommand;
699 	cmd->string = entName;
700 	cmd->cmdType = C_REMOVEENTITY;
701 	_cine.push_back(cmd);
702 }
703 
cineDialog(const char * title,const char * string,int seconds)704 void AI::cineDialog(const char *title, const char *string, int seconds) {
705 	CineCommand *cmd = new CineCommand;
706 	cmd->title = title;
707 	cmd->string = string;
708 	cmd->delay = seconds;
709 	cmd->start = 1;
710 	if (!title || !string)
711 		warning("cineDialog: Missing Title or Text");
712 	cmd->cmdType = C_DIALOG;
713 	debug(6, "In cineDialog: C_DIALOG created. cmd->start: %d, cmd->title: %s", cmd->start, cmd->title);
714 	_cine.push_back(cmd);
715 }
716 
cineTextOut(const char * text,int x,int y,int timer)717 void AI::cineTextOut(const char *text, int x, int y, int timer) {
718 	CineCommand *cmd = new CineCommand;
719 	cmd->title = text;
720 	cmd->x = x;
721 	cmd->y = y;
722 	cmd->end = timer;
723 	cmd->start = 0;
724 	cmd->cmdType = C_TEXTOUT;
725 	_cine.push_back(cmd);
726 }
727 
cineCenterTextOut(const char * text,int y,int timer)728 void AI::cineCenterTextOut(const char *text, int y, int timer) {
729 	CineCommand *cmd = new CineCommand;
730 	cmd->title = text;
731 	cmd->y = y;
732 	cmd->end = timer;
733 	cmd->start = 0;
734 	cmd->cmdType = C_CENTERTEXTOUT;
735 	_cine.push_back(cmd);
736 }
737 
cineDrawPic(const char * id,const char * pic,int x,int y)738 void AI::cineDrawPic(const char *id, const char *pic, int x, int y) {
739 	if (!pic || !id) {
740 		warning("cineDrawPic: Missing ID or PIC");
741 		return;
742 	}
743 
744 	CineCommand *cmd = new CineCommand;
745 	cmd->x = x;
746 	cmd->y = y;
747 	cmd->string = pic;
748 	cmd->id = id;
749 	cmd->cmdType = C_DRAWPIC;
750 	_cine.push_back(cmd);
751 }
752 
cineDrawMaskedPic(const char * id,const char * pic,int x,int y)753 void AI::cineDrawMaskedPic(const char *id, const char *pic, int x, int y) {
754 	if (!pic || !id) {
755 		warning("cineDrawMaskedPic: Missing ID or PIC");
756 		return;
757 	}
758 
759 	CineCommand *cmd = new CineCommand;
760 	cmd->x = x;
761 	cmd->y = y;
762 	cmd->string = pic;
763 	cmd->id = id;
764 	cmd->cmdType = C_DRAWMASKEDPIC;
765 	_cine.push_back(cmd);
766 }
767 
cineMovePic(const char * id,const char * pic,int x1,int y1,int x2,int y2,int speed)768 void AI::cineMovePic(const char *id, const char *pic, int x1, int y1, int x2, int y2, int speed) {
769 	if (!pic || !id) {
770 		warning("cineMovePic: Missing ID or PIC");
771 		return;
772 	}
773 
774 	CineCommand *cmd = new CineCommand;
775 	cmd->x = x1;
776 	cmd->y = y1;
777 	cmd->x2 = x2;
778 	cmd->y2 = y2;
779 	cmd->speed = speed;
780 	cmd->xv = ((double)(x2-x1)) / (double)speed;
781 	cmd->yv = ((double)(y2-y1)) / (double)speed;
782 	cmd->start = 0;
783 	cmd->string = pic;
784 	cmd->id = id;
785 	cmd->cmdType = C_MOVEPIC;
786 	_cine.push_back(cmd);
787 }
788 
cineMoveMaskedPic(const char * id,const char * pic,int x1,int y1,int x2,int y2,int speed)789 void AI::cineMoveMaskedPic(const char *id, const char *pic, int x1, int y1, int x2, int y2, int speed) {
790 	if (!pic || !id) {
791 		warning("cineMoveMaskedPic: Missing ID or PIC");
792 		return;
793 	}
794 
795 	CineCommand *cmd = new CineCommand;
796 	cmd->x = x1;
797 	cmd->y = y1;
798 	cmd->x2 = x2;
799 	cmd->y2 = y2;
800 	cmd->speed = speed;
801 	cmd->xv = ((double)(x2-x1)) / (double)speed;
802 	cmd->yv = ((double)(y2-y1)) / (double)speed;
803 	cmd->start = 0;
804 	cmd->string = pic;
805 	cmd->id = id;
806 	cmd->cmdType = C_MOVEMASKEDPIC;
807 	_cine.push_back(cmd);
808 }
809 
cineUse(const char * entName)810 void AI::cineUse(const char *entName) {
811 	CineCommand *cmd = new CineCommand;
812 	cmd->string = entName;
813 	cmd->cmdType = C_USEENTITY;
814 	_cine.push_back(cmd);
815 }
816 
cinePlaySound(int index)817 void AI::cinePlaySound(int index) {
818 	CineCommand *cmd = new CineCommand;
819 	cmd->start = index;
820 	cmd->cmdType = C_PLAYSOUND;
821 	_cine.push_back(cmd);
822 }
823 
cinePlayVoice(int index,int actor)824 void AI::cinePlayVoice(int index, int actor) {
825 	CineCommand *cmd = new CineCommand;
826 	cmd->x = index;
827 	cmd->y = actor;
828 	cmd->cmdType = C_PLAYVOICE;
829 	_cine.push_back(cmd);
830 }
831 
cineFadeIn(bool isBlack,int steps)832 void AI::cineFadeIn(bool isBlack, int steps) {
833 	CineCommand *cmd = new CineCommand;
834 	cmd->speed = steps;
835 	cmd->end = (int)isBlack;
836 	cmd->start = 0;
837 	cmd->cmdType = C_FADEIN;
838 	_cine.push_back(cmd);
839 }
840 
cineFadeOut(bool isBlack,int steps)841 void AI::cineFadeOut(bool isBlack, int steps) {
842 	CineCommand *cmd = new CineCommand;
843 	cmd->speed = steps;
844 	cmd->end = (int)isBlack;
845 	cmd->start = 0;
846 	cmd->cmdType = C_FADEOUT;
847 	_cine.push_back(cmd);
848 }
849 
cineClearForeground(int x,int y)850 void AI::cineClearForeground(int x, int y) {
851 	CineCommand *cmd = new CineCommand;
852 	cmd->x = x;
853 	cmd->y = y;
854 	cmd->cmdType = C_CLEAR_FG;
855 	_cine.push_back(cmd);
856 }
857 
cineSetBackground(int x,int y,int index)858 void AI::cineSetBackground(int x, int y, int index) {
859 	CineCommand *cmd = new CineCommand;
860 	cmd->x = x;
861 	cmd->y = y;
862 	cmd->start = index;
863 	cmd->cmdType = C_SET_BG;
864 	_cine.push_back(cmd);
865 }
866 
cineSetForeground(int x,int y,int index)867 void AI::cineSetForeground(int x, int y, int index) {
868 	CineCommand *cmd = new CineCommand;
869 	cmd->x = x;
870 	cmd->y = y;
871 	cmd->start = index;
872 	cmd->cmdType = C_SET_FG;
873 	_cine.push_back(cmd);
874 }
875 
cineFunction(const char * func)876 void AI::cineFunction(const char *func) {
877 	CineCommand *cmd = new CineCommand;
878 	cmd->title = func;
879 	cmd->cmdType = C_FUNCTION;
880 	_cine.push_back(cmd);
881 }
882 
883 } // End of Namespace
884