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 /*
24  * This code is based on original Tony Tough source code
25  *
26  * Copyright (c) 1997-2003 Nayma Software
27  */
28 
29 #include "tony/mpal/memory.h"
30 #include "tony/mpal/mpalutils.h"
31 #include "tony/game.h"
32 #include "tony/tonychar.h"
33 #include "tony/tony.h"
34 
35 namespace Tony {
36 
37 bool RMTony::_bAction = false;
38 
initStatics()39 void RMTony::initStatics() {
40 	_bAction = false;
41 }
42 
RMTony()43 RMTony::RMTony() {
44 	_bShow = false;
45 	_bShowShadow = false;
46 	_bBodyFront = false;
47 	_bActionPending = false;
48 	_actionItem = NULL;
49 	_action = 0;
50 	_actionParm = 0;
51 	_bShepherdess = false;
52 	_bIsStaticTalk = false;
53 	_bIsTalking = false;
54 	_nPatB4Talking = 0;
55 	_nTalkType = TALK_NORMAL;
56 	_talkDirection = UP;
57 	_nTimeLastStep = 0;
58 	_hActionThread = CORO_INVALID_PID_VALUE;
59 }
60 
waitEndOfAction(CORO_PARAM,const void * param)61 void RMTony::waitEndOfAction(CORO_PARAM, const void *param) {
62 	CORO_BEGIN_CONTEXT;
63 	CORO_END_CONTEXT(_ctx);
64 
65 	uint32 pid = *(const uint32 *)param;
66 
67 	CORO_BEGIN_CODE(_ctx);
68 
69 	CORO_INVOKE_2(CoroScheduler.waitForSingleObject, pid, CORO_INFINITE);
70 
71 	_bAction = false;
72 
73 	CORO_END_CODE;
74 }
75 
newItemSpriteBuffer(int dimx,int dimy,bool bPreRLE)76 RMGfxSourceBuffer *RMTony::newItemSpriteBuffer(int dimx, int dimy, bool bPreRLE) {
77 	RMGfxSourceBuffer8RLE *spr;
78 
79 	assert(_cm == CM_256);
80 	spr = new RMGfxSourceBuffer8RLEByteAA;
81 	spr->setAlphaBlendColor(1);
82 	if (bPreRLE)
83 		spr->setAlreadyCompressed();
84 	return spr;
85 }
86 
init()87 void RMTony::init() {
88 	RMRes tony(0);
89 	RMRes body(9999);
90 
91 	// Tony is shown by default
92 	_bShow = _bShowShadow = true;
93 
94 	// No action pending
95 	_bActionPending = false;
96 	_bAction = false;
97 
98 	_bShepherdess = false;
99 	_bIsTalking = false;
100 	_bIsStaticTalk = false;
101 
102 	// Opens the buffer
103 	Common::SeekableReadStream *ds = tony.getReadStream();
104 
105 	// Reads his details from the stream
106 	readFromStream(*ds, true);
107 
108 	// Closes the buffer
109 	delete ds;
110 
111 	// Reads Tony's body
112 	ds = body.getReadStream();
113 	_body.readFromStream(*ds, true);
114 	delete ds;
115 	_body.setPattern(0);
116 
117 	_nTimeLastStep = g_vm->getTime();
118 }
119 
120 
close()121 void RMTony::close() {
122 	// Deallocation of missing item
123 	//_shadow.destroy();
124 }
125 
doFrame(CORO_PARAM,RMGfxTargetBuffer * bigBuf,int curLoc)126 void RMTony::doFrame(CORO_PARAM, RMGfxTargetBuffer *bigBuf, int curLoc) {
127 	CORO_BEGIN_CONTEXT;
128 	int time;
129 	CORO_END_CONTEXT(_ctx);
130 
131 	CORO_BEGIN_CODE(_ctx);
132 
133 	if (!_nInList && _bShow)
134 		bigBuf->addPrim(new RMGfxPrimitive(this));
135 
136 	setSpeed(GLOBALS._nCfgTonySpeed);
137 
138 	// Runs the normal character movement
139 	_ctx->time = g_vm->getTime();
140 
141 	do {
142 		_nTimeLastStep += (1000 / 40);
143 		CORO_INVOKE_2(RMCharacter::doFrame, bigBuf, curLoc);
144 	} while (_ctx->time > _nTimeLastStep + (1000 / 40));
145 
146 	// Check if we are at the end of a path
147 	if (endOfPath() && _bActionPending) {
148 		// Must perform the action on which we clicked
149 		_bActionPending = false;
150 	}
151 
152 	if (_bIsTalking || _bIsStaticTalk)
153 		_body.doFrame(bigBuf, false);
154 
155 	CORO_END_CODE;
156 }
157 
show()158 void RMTony::show() {
159 	_bShow = true;
160 	_bShowShadow = true;
161 }
162 
hide(bool bShowShadow)163 void RMTony::hide(bool bShowShadow) {
164 	_bShow = false;
165 	_bShowShadow = bShowShadow;
166 }
167 
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)168 void RMTony::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
169 	CORO_BEGIN_CONTEXT;
170 	CORO_END_CONTEXT(_ctx);
171 
172 	CORO_BEGIN_CODE(_ctx);
173 
174 	// Call the Draw() of the parent class if Tony is visible
175 	if (_bShow && _bDrawNow) {
176 		if (_bBodyFront) {
177 			prim->getDst().setEmpty();
178 			prim->getDst().offset(-44, -134);
179 			if (_bShepherdess)
180 				prim->getDst().offset(1, 4);
181 			CORO_INVOKE_2(RMCharacter::draw, bigBuf, prim);
182 		}
183 
184 		if (_bIsTalking || _bIsStaticTalk) {
185 			// Offest direction from scrolling
186 			prim->getDst().setEmpty();
187 			prim->getDst().offset(-_curScroll);
188 			prim->getDst().offset(_pos);
189 			prim->getDst().offset(-44, -134);
190 			prim->getDst() += _nBodyOffset;
191 			CORO_INVOKE_2(_body.draw, bigBuf, prim);
192 		}
193 
194 		if (!_bBodyFront) {
195 			prim->getDst().setEmpty();
196 			prim->getDst().offset(-44, -134);
197 			if (_bShepherdess)
198 				prim->getDst().offset(0, 3);
199 			CORO_INVOKE_2(RMCharacter::draw, bigBuf, prim);
200 		}
201 	}
202 
203 	CORO_END_CODE;
204 }
205 
moveAndDoAction(CORO_PARAM,RMPoint dst,RMItem * item,int nAction,int nActionParm)206 void RMTony::moveAndDoAction(CORO_PARAM, RMPoint dst, RMItem *item, int nAction, int nActionParm) {
207 	CORO_BEGIN_CONTEXT;
208 	bool result;
209 	CORO_END_CONTEXT(_ctx);
210 
211 	CORO_BEGIN_CODE(_ctx);
212 
213 	// Makes normal movement, but remember if you must then perform an action
214 	if (item == NULL) {
215 		_bActionPending = false;
216 		_actionItem = NULL;
217 	} else {
218 		_actionItem = item;
219 		_action = nAction;
220 		_actionParm = nActionParm;
221 		_bActionPending = true;
222 	}
223 
224 	CORO_INVOKE_2(RMCharacter::move, dst, &_ctx->result);
225 	if (!_ctx->result) {
226 		_bActionPending = false;
227 		_actionItem = NULL;
228 	}
229 
230 	CORO_END_CODE;
231 }
232 
executeAction(int nAction,int nActionItem,int nParm)233 void RMTony::executeAction(int nAction, int nActionItem, int nParm) {
234 	uint32 pid;
235 
236 	if (nAction == TA_COMBINE) {
237 		pid = mpalQueryDoAction(TA_COMBINE, nParm, nActionItem);
238 
239 		// If you failed the combine, we have RECEIVECOMBINE as a fallback
240 		if (pid == CORO_INVALID_PID_VALUE) {
241 			pid = mpalQueryDoAction(TA_RECEIVECOMBINE, nActionItem, nParm);
242 
243 			// If you failed with that, go with the generic
244 			// @@@ CombineGive!
245 			if (pid == CORO_INVALID_PID_VALUE) {
246 				pid = mpalQueryDoAction(TA_COMBINE, nParm, 0);
247 
248 				if (pid == CORO_INVALID_PID_VALUE) {
249 					pid = mpalQueryDoAction(TA_RECEIVECOMBINE, nActionItem, 0);
250 				}
251 			}
252 		}
253 	} else {
254 		// Perform the action
255 		pid = mpalQueryDoAction(nAction, nActionItem, 0);
256 	}
257 
258 	if (pid != CORO_INVALID_PID_VALUE) {
259 		_bAction = true;
260 		CoroScheduler.createProcess(waitEndOfAction, &pid, sizeof(uint32));
261 		_hActionThread = pid;
262 	} else if (nAction != TA_GOTO) {
263 		if (nAction == TA_TALK) {
264 			pid = mpalQueryDoAction(6, 1, 0);
265 			_bAction = true;
266 			CoroScheduler.createProcess(waitEndOfAction, &pid, sizeof(uint32));
267 			_hActionThread = pid;
268 		} else if (nAction == TA_PERORATE) {
269 			pid = mpalQueryDoAction(7, 1, 0);
270 			_bAction = true;
271 			CoroScheduler.createProcess(waitEndOfAction, &pid, sizeof(uint32));
272 			_hActionThread = pid;
273 		} else {
274 			pid = mpalQueryDoAction(5, 1, 0);
275 			_bAction = true;
276 			CoroScheduler.createProcess(waitEndOfAction, &pid, sizeof(uint32));
277 			_hActionThread = pid;
278 		}
279 	}
280 }
281 
stopNoAction(CORO_PARAM)282 void RMTony::stopNoAction(CORO_PARAM) {
283 	CORO_BEGIN_CONTEXT;
284 	CORO_END_CONTEXT(_ctx);
285 
286 	CORO_BEGIN_CODE(_ctx);
287 
288 	if (_bAction)
289 		CORO_INVOKE_2(CoroScheduler.waitForSingleObject, _hActionThread, CORO_INFINITE);
290 
291 	_bActionPending = false;
292 	_actionItem = NULL;
293 	CORO_INVOKE_0(stop);
294 
295 	CORO_END_CODE;
296 }
297 
stop(CORO_PARAM)298 void RMTony::stop(CORO_PARAM) {
299 	CORO_BEGIN_CONTEXT;
300 	uint32 pid;
301 	CORO_END_CONTEXT(_ctx);
302 
303 	CORO_BEGIN_CODE(_ctx);
304 
305 	if (_actionItem != NULL) {
306 		// Call MPAL to choose the direction
307 		_ctx->pid = mpalQueryDoAction(21, _actionItem->mpalCode(), 0);
308 
309 		if (_ctx->pid == CORO_INVALID_PID_VALUE)
310 			CORO_INVOKE_0(RMCharacter::stop);
311 		else {
312 			_bNeedToStop = false;    // If we make the OnWhichDirection, we don't need at least after the Stop().
313 			_bMoving = false;
314 			CORO_INVOKE_2(CoroScheduler.waitForSingleObject, _ctx->pid, CORO_INFINITE); // @@@ Put an assert after 10 seconds
315 		}
316 	} else {
317 		CORO_INVOKE_0(RMCharacter::stop);
318 	}
319 
320 	if (!_bActionPending)
321 		return;
322 
323 	_bActionPending = false;
324 
325 	executeAction(_action, _actionItem->mpalCode(), _actionParm);
326 
327 	_actionItem = NULL;
328 
329 	CORO_END_CODE;
330 }
331 
getCurPattern()332 int RMTony::getCurPattern() {
333 	int nPatt = RMCharacter::getCurPattern();
334 
335 	if (!_bShepherdess)
336 		return nPatt;
337 
338 	switch (nPatt) {
339 	case PAT_PAST_STANDUP:
340 		return PAT_STANDUP;
341 	case PAT_PAST_STANDDOWN:
342 		return PAT_STANDDOWN;
343 	case PAT_PAST_STANDLEFT:
344 		return PAT_STANDLEFT;
345 	case PAT_PAST_STANDRIGHT:
346 		return PAT_STANDRIGHT;
347 	case PAT_PAST_WALKUP:
348 		return PAT_WALKUP;
349 	case PAT_PAST_WALKDOWN:
350 		return PAT_WALKDOWN;
351 	case PAT_PAST_WALKLEFT:
352 		return PAT_WALKLEFT;
353 	case PAT_PAST_WALKRIGHT:
354 		return PAT_WALKRIGHT;
355 	default:
356 		break;
357 	}
358 
359 	return nPatt;
360 }
361 
setPattern(int nPatt,bool bPlayP0)362 void RMTony::setPattern(int nPatt, bool bPlayP0) {
363 	if (_bShepherdess) {
364 		switch (nPatt) {
365 		case PAT_STANDUP:
366 			nPatt = PAT_PAST_STANDUP;
367 			break;
368 		case PAT_STANDDOWN:
369 			nPatt = PAT_PAST_STANDDOWN;
370 			break;
371 		case PAT_STANDLEFT:
372 			nPatt = PAT_PAST_STANDLEFT;
373 			break;
374 		case PAT_STANDRIGHT:
375 			nPatt = PAT_PAST_STANDRIGHT;
376 			break;
377 		case PAT_WALKUP:
378 			nPatt = PAT_PAST_WALKUP;
379 			break;
380 		case PAT_WALKDOWN:
381 			nPatt = PAT_PAST_WALKDOWN;
382 			break;
383 		case PAT_WALKLEFT:
384 			nPatt = PAT_PAST_WALKLEFT;
385 			break;
386 		case PAT_WALKRIGHT:
387 			nPatt = PAT_PAST_WALKRIGHT;
388 			break;
389 		default:
390 			break;
391 		}
392 	}
393 
394 	RMCharacter::setPattern(nPatt, bPlayP0);
395 }
396 
take(int nWhere,int nPart)397 void RMTony::take(int nWhere, int nPart) {
398 	if (nPart == 0) {
399 		switch (getCurPattern()) {
400 		case PAT_STANDDOWN:
401 			assert(0);  // Not while you're doing a StandDown
402 			break;
403 
404 		case PAT_STANDUP:
405 			switch (nWhere) {
406 			case 0:
407 				setPattern(PAT_TAKEUP_UP1);
408 				break;
409 			case 1:
410 				setPattern(PAT_TAKEUP_MID1);
411 				break;
412 			case 2:
413 				setPattern(PAT_TAKEUP_DOWN1);
414 				break;
415 			default:
416 				break;
417 			}
418 			break;
419 
420 		case PAT_STANDRIGHT:
421 			switch (nWhere) {
422 			case 0:
423 				setPattern(PAT_TAKERIGHT_UP1);
424 				break;
425 			case 1:
426 				setPattern(PAT_TAKERIGHT_MID1);
427 				break;
428 			case 2:
429 				setPattern(PAT_TAKERIGHT_DOWN1);
430 				break;
431 			default:
432 				break;
433 			}
434 			break;
435 
436 		case PAT_STANDLEFT:
437 			switch (nWhere) {
438 			case 0:
439 				setPattern(PAT_TAKELEFT_UP1);
440 				break;
441 			case 1:
442 				setPattern(PAT_TAKELEFT_MID1);
443 				break;
444 			case 2:
445 				setPattern(PAT_TAKELEFT_DOWN1);
446 				break;
447 			default:
448 				break;
449 			}
450 			break;
451 
452 		default:
453 			break;
454 		}
455 	} else if (nPart == 1) {
456 		setPattern(getCurPattern() + 1);
457 	} else if (nPart == 2) {
458 		switch (getCurPattern()) {
459 		case PAT_TAKEUP_UP2:
460 		case PAT_TAKEUP_MID2:
461 		case PAT_TAKEUP_DOWN2:
462 			setPattern(PAT_STANDUP);
463 			break;
464 
465 		case PAT_TAKELEFT_UP2:
466 		case PAT_TAKELEFT_MID2:
467 		case PAT_TAKELEFT_DOWN2:
468 			setPattern(PAT_STANDLEFT);
469 			break;
470 
471 		case PAT_TAKERIGHT_UP2:
472 		case PAT_TAKERIGHT_MID2:
473 		case PAT_TAKERIGHT_DOWN2:
474 			setPattern(PAT_STANDRIGHT);
475 			break;
476 
477 		default:
478 			break;
479 		}
480 	}
481 }
482 
put(int nWhere,int nPart)483 void RMTony::put(int nWhere, int nPart) {
484 	if (nPart == 0) {
485 		switch (getCurPattern()) {
486 		case PAT_STANDDOWN:
487 			break;
488 
489 		case PAT_STANDUP:
490 			switch (nWhere) {
491 			case 0:
492 				setPattern(PAT_PUTUP_UP1);
493 				break;
494 			case 1:
495 				setPattern(PAT_PUTUP_MID1);
496 				break;
497 			case 2:
498 				setPattern(PAT_PUTUP_DOWN1);
499 				break;
500 			default:
501 				break;
502 			}
503 			break;
504 
505 		case PAT_STANDRIGHT:
506 			switch (nWhere) {
507 			case 0:
508 				setPattern(PAT_PUTRIGHT_UP1);
509 				break;
510 			case 1:
511 				setPattern(PAT_PUTRIGHT_MID1);
512 				break;
513 			case 2:
514 				setPattern(PAT_PUTRIGHT_DOWN1);
515 				break;
516 			default:
517 				break;
518 			}
519 			break;
520 
521 		case PAT_STANDLEFT:
522 			switch (nWhere) {
523 			case 0:
524 				setPattern(PAT_PUTLEFT_UP1);
525 				break;
526 			case 1:
527 				setPattern(PAT_PUTLEFT_MID1);
528 				break;
529 			case 2:
530 				setPattern(PAT_PUTLEFT_DOWN1);
531 				break;
532 			default:
533 				break;
534 			}
535 			break;
536 
537 		default:
538 			break;
539 		}
540 	} else if (nPart == 1) {
541 		setPattern(getCurPattern() + 1);
542 	} else if (nPart == 2) {
543 		switch (getCurPattern()) {
544 		case PAT_PUTUP_UP2:
545 		case PAT_PUTUP_MID2:
546 		case PAT_PUTUP_DOWN2:
547 			setPattern(PAT_STANDUP);
548 			break;
549 
550 		case PAT_PUTLEFT_UP2:
551 		case PAT_PUTLEFT_MID2:
552 		case PAT_PUTLEFT_DOWN2:
553 			setPattern(PAT_STANDLEFT);
554 			break;
555 
556 		case PAT_PUTRIGHT_UP2:
557 		case PAT_PUTRIGHT_MID2:
558 		case PAT_PUTRIGHT_DOWN2:
559 			setPattern(PAT_STANDRIGHT);
560 			break;
561 
562 		default:
563 			break;
564 		}
565 	}
566 }
567 
startTalkCalculate(CharacterTalkType nTalkType,int & headStartPat,int & bodyStartPat,int & headLoopPat,int & bodyLoopPat)568 bool RMTony::startTalkCalculate(CharacterTalkType nTalkType, int &headStartPat, int &bodyStartPat,
569 								int &headLoopPat, int &bodyLoopPat) {
570 	assert(!_bIsTalking);
571 
572 	_bIsTalking = true;
573 	_nPatB4Talking = getCurPattern();
574 	_nTalkType = nTalkType;
575 
576 	// Set the direction of speech ONLY if we are not in a static animation (since it would have already been done)
577 	if (!_bIsStaticTalk) {
578 		switch (_nPatB4Talking) {
579 		case PAT_STANDDOWN:
580 			_talkDirection = DOWN;
581 			break;
582 
583 		case PAT_TAKELEFT_UP2:
584 		case PAT_TAKELEFT_MID2:
585 		case PAT_TAKELEFT_DOWN2:
586 		case PAT_GETUPLEFT:
587 		case PAT_STANDLEFT:
588 			_talkDirection = LEFT;
589 			break;
590 
591 		case PAT_TAKERIGHT_UP2:
592 		case PAT_TAKERIGHT_MID2:
593 		case PAT_TAKERIGHT_DOWN2:
594 		case PAT_GETUPRIGHT:
595 		case PAT_STANDRIGHT:
596 			_talkDirection = RIGHT;
597 			break;
598 
599 		case PAT_TAKEUP_UP2:
600 		case PAT_TAKEUP_MID2:
601 		case PAT_TAKEUP_DOWN2:
602 		case PAT_STANDUP:
603 			_talkDirection = UP;
604 			break;
605 
606 		default:
607 			break;
608 		}
609 
610 		// Puts the body in front by default
611 		_bBodyFront = true;
612 	}
613 
614 	if (_bShepherdess) {
615 		// Talking whilst a shepherdess
616 		switch (_talkDirection) {
617 		case UP:
618 			setPattern(PAT_PAST_TALKUP);
619 			break;
620 
621 		case DOWN:
622 			setPattern(PAT_PAST_TALKDOWN);
623 			break;
624 
625 		case LEFT:
626 			setPattern(PAT_PAST_TALKLEFT);
627 			break;
628 
629 		case RIGHT:
630 			setPattern(PAT_PAST_TALKRIGHT);
631 			break;
632 
633 		default:
634 			break;
635 		}
636 		return false;
637 	}
638 
639 	headStartPat = bodyStartPat = 0;
640 	bodyLoopPat = 0;
641 
642 	switch (nTalkType) {
643 	case TALK_NORMAL:
644 		_bBodyFront = false;
645 		headStartPat = 0;
646 		bodyStartPat = 0;
647 
648 		switch (_talkDirection) {
649 		case DOWN:
650 			headLoopPat = PAT_TALK_DOWN;
651 			bodyLoopPat = BPAT_STANDDOWN;
652 			_nBodyOffset.set(4, 53);
653 			break;
654 
655 		case LEFT:
656 			headLoopPat = PAT_TALK_LEFT;
657 			bodyLoopPat = BPAT_STANDLEFT;
658 			_nBodyOffset.set(6, 56);
659 			break;
660 
661 		case RIGHT:
662 			headLoopPat = PAT_TALK_RIGHT;
663 			bodyLoopPat = BPAT_STANDRIGHT;
664 			_nBodyOffset.set(6, 56);
665 			break;
666 
667 		case UP:
668 			headLoopPat = PAT_TALK_UP;
669 			bodyLoopPat = BPAT_STANDUP;
670 			_nBodyOffset.set(6, 53);
671 			break;
672 
673 		default:
674 			break;
675 		}
676 		break;
677 
678 	case TALK_HIPS:
679 		_bBodyFront = false;
680 		switch (_talkDirection) {
681 		case UP:
682 			_nBodyOffset.set(2, 42);
683 			headStartPat = PAT_HEAD_UP;
684 			bodyStartPat = BPAT_HIPSUP_START;
685 			headLoopPat = PAT_TALK_UP;
686 			bodyLoopPat = BPAT_HIPSUP_LOOP;
687 			break;
688 
689 		case DOWN:
690 			_nBodyOffset.set(2, 48);
691 			headStartPat = PAT_HEAD_DOWN;
692 			bodyStartPat = BPAT_HIPSDOWN_START;
693 			headLoopPat = PAT_TALK_DOWN;
694 			bodyLoopPat = BPAT_HIPSDOWN_LOOP;
695 			break;
696 
697 		case LEFT:
698 			_nBodyOffset.set(-3, 53);
699 			headStartPat = PAT_HEAD_LEFT;
700 			bodyStartPat = BPAT_HIPSLEFT_START;
701 			headLoopPat = PAT_TALK_LEFT;
702 			bodyLoopPat = BPAT_HIPSLEFT_LOOP;
703 			break;
704 
705 		case RIGHT:
706 			_nBodyOffset.set(2, 53);
707 			headStartPat = PAT_HEAD_RIGHT;
708 			bodyStartPat = BPAT_HIPSRIGHT_START;
709 			headLoopPat = PAT_TALK_RIGHT;
710 			bodyLoopPat = BPAT_HIPSRIGHT_LOOP;
711 			break;
712 
713 		default:
714 			break;
715 		}
716 		break;
717 
718 	case TALK_SING:
719 		_nBodyOffset.set(-10, 25);
720 		headStartPat = PAT_HEAD_LEFT;
721 		bodyStartPat = BPAT_SINGLEFT_START;
722 		headLoopPat = PAT_TALK_LEFT;
723 		bodyLoopPat = BPAT_SINGLEFT_LOOP;
724 		break;
725 
726 	case TALK_LAUGH:
727 		_bBodyFront = false;
728 		switch (_talkDirection) {
729 		case UP:
730 		case DOWN:
731 		case LEFT:
732 			_nBodyOffset.set(6, 56);
733 			headStartPat = PAT_LAUGHLEFT_START;
734 			bodyStartPat = BPAT_STANDLEFT;
735 			headLoopPat = PAT_LAUGHLEFT_LOOP;
736 			bodyLoopPat = BPAT_LAUGHLEFT;
737 			break;
738 
739 		case RIGHT:
740 			_nBodyOffset.set(6, 56);
741 			headStartPat = PAT_LAUGHRIGHT_START;
742 			bodyStartPat = BPAT_STANDRIGHT;
743 			headLoopPat = PAT_LAUGHRIGHT_LOOP;
744 			bodyLoopPat = BPAT_LAUGHRIGHT;
745 			break;
746 
747 		default:
748 			break;
749 		}
750 		break;
751 
752 	case TALK_LAUGH2:
753 		_bBodyFront = false;
754 		switch (_talkDirection) {
755 		case UP:
756 		case DOWN:
757 		case LEFT:
758 			_nBodyOffset.set(6, 56);
759 			headStartPat = PAT_LAUGHLEFT_START;
760 			bodyStartPat = BPAT_STANDLEFT;
761 			headLoopPat = PAT_LAUGHLEFT_LOOP;
762 			break;
763 
764 		case RIGHT:
765 			_nBodyOffset.set(6, 56);
766 			headStartPat = PAT_LAUGHRIGHT_START;
767 			bodyStartPat = BPAT_STANDRIGHT;
768 			headLoopPat = PAT_LAUGHRIGHT_LOOP;
769 			bodyLoopPat = BPAT_LAUGHRIGHT;
770 			break;
771 
772 		default:
773 			break;
774 		}
775 		break;
776 
777 	case TALK_INDICATE:
778 		switch (_talkDirection) {
779 		case UP:
780 		case DOWN:
781 		case LEFT:
782 			_nBodyOffset.set(-4, 40);
783 			headLoopPat = PAT_TALK_LEFT;
784 			bodyLoopPat = BPAT_INDICATELEFT;
785 			break;
786 
787 		case RIGHT:
788 			_nBodyOffset.set(5, 40);
789 			headLoopPat = PAT_TALK_RIGHT;
790 			bodyLoopPat = BPAT_INDICATERIGHT;
791 			break;
792 
793 		default:
794 			break;
795 		}
796 		break;
797 
798 	case TALK_SCARED:
799 		switch (_talkDirection) {
800 		case UP:
801 			_nBodyOffset.set(-4, -11);
802 			headStartPat = PAT_HEAD_UP;
803 			bodyStartPat = BPAT_SCAREDUP_START;
804 			headLoopPat = PAT_TALK_UP;
805 			bodyLoopPat = BPAT_SCAREDUP_LOOP;
806 			break;
807 
808 		case DOWN:
809 			_nBodyOffset.set(-5, 45);
810 			headStartPat = PAT_SCAREDDOWN_START;
811 			bodyStartPat = BPAT_SCAREDDOWN_START;
812 			headLoopPat = PAT_SCAREDDOWN_LOOP;
813 			bodyLoopPat = BPAT_SCAREDDOWN_LOOP;
814 			break;
815 
816 		case RIGHT:
817 			_nBodyOffset.set(-4, 41);
818 			headStartPat = PAT_SCAREDRIGHT_START;
819 			bodyStartPat = BPAT_SCAREDRIGHT_START;
820 			headLoopPat = PAT_SCAREDRIGHT_LOOP;
821 			bodyLoopPat = BPAT_SCAREDRIGHT_LOOP;
822 			break;
823 
824 		case LEFT:
825 			_nBodyOffset.set(-10, 41);
826 			headStartPat = PAT_SCAREDLEFT_START;
827 			bodyStartPat = BPAT_SCAREDLEFT_START;
828 			headLoopPat = PAT_SCAREDLEFT_LOOP;
829 			bodyLoopPat = BPAT_SCAREDLEFT_LOOP;
830 			break;
831 
832 		default:
833 			break;
834 		}
835 		break;
836 
837 	case TALK_SCARED2:
838 		_bBodyFront = false;
839 		switch (_talkDirection) {
840 		case UP:
841 			bodyStartPat = BPAT_STANDUP;
842 			bodyLoopPat = BPAT_STANDUP;
843 			_nBodyOffset.set(6, 53);
844 
845 			headStartPat = PAT_HEAD_UP;
846 			headLoopPat = PAT_TALK_UP;
847 			break;
848 
849 		case DOWN:
850 			bodyStartPat = BPAT_STANDDOWN;
851 			bodyLoopPat = BPAT_STANDDOWN;
852 			_nBodyOffset.set(4, 53);
853 
854 			headStartPat = PAT_SCAREDDOWN_START;
855 			headLoopPat = PAT_SCAREDDOWN_LOOP;
856 			break;
857 
858 		case RIGHT:
859 			bodyStartPat = BPAT_STANDRIGHT;
860 			bodyLoopPat = BPAT_STANDRIGHT;
861 			_nBodyOffset.set(6, 56);
862 
863 			headStartPat = PAT_SCAREDRIGHT_START;
864 			headLoopPat = PAT_SCAREDRIGHT_LOOP;
865 			break;
866 
867 		case LEFT:
868 			bodyStartPat = BPAT_STANDLEFT;
869 			bodyLoopPat = BPAT_STANDLEFT;
870 			_nBodyOffset.set(6, 56);
871 
872 			headStartPat = PAT_SCAREDLEFT_START;
873 			headLoopPat = PAT_SCAREDLEFT_LOOP;
874 			break;
875 
876 		default:
877 			break;
878 		}
879 		break;
880 
881 	case TALK_WITHGLASSES:
882 		_nBodyOffset.set(4, 53);
883 		headLoopPat = PAT_TALK_DOWN;
884 		bodyLoopPat = BPAT_GLASS;
885 		break;
886 	case TALK_WITHWORM:
887 		_nBodyOffset.set(9, 56);
888 		headLoopPat = PAT_TALK_RIGHT;
889 		bodyLoopPat = BPAT_WORM;
890 		break;
891 	case TALK_WITHHAMMER:
892 		_nBodyOffset.set(6, 56);
893 		headLoopPat = PAT_TALK_LEFT;
894 		bodyLoopPat = BPAT_HAMMER;
895 		break;
896 	case TALK_WITHROPE:
897 		_nBodyOffset.set(-3, 38);
898 		headLoopPat = PAT_TALK_RIGHT;
899 		bodyLoopPat = BPAT_ROPE;
900 		break;
901 	case TALK_WITHSECRETARY:
902 		_nBodyOffset.set(-17, 12);
903 		headLoopPat = PAT_TALK_RIGHT;
904 		bodyLoopPat = BPAT_WITHSECRETARY;
905 		break;
906 
907 	case TALK_WITHRABBIT:
908 		switch (_talkDirection) {
909 		case LEFT:
910 		case UP:
911 			_nBodyOffset.set(-21, -5);
912 			bodyStartPat = BPAT_WITHRABBITLEFT_START;
913 			headLoopPat = PAT_TALK_LEFT;
914 			bodyLoopPat = BPAT_WITHRABBITLEFT_LOOP;
915 			break;
916 
917 		case DOWN:
918 		case RIGHT:
919 			_nBodyOffset.set(-4, -5);
920 			bodyStartPat = BPAT_WITHRABBITRIGHT_START;
921 			headLoopPat = PAT_TALK_RIGHT;
922 			bodyLoopPat = BPAT_WITHRABBITRIGHT_LOOP;
923 			break;
924 
925 		default:
926 			break;
927 		}
928 		break;
929 
930 	case TALK_WITHRECIPE:
931 		switch (_talkDirection) {
932 		case LEFT:
933 		case UP:
934 			_nBodyOffset.set(-61, -7);
935 			bodyStartPat = BPAT_WITHRECIPELEFT_START;
936 			headLoopPat = PAT_TALK_LEFT;
937 			bodyLoopPat = BPAT_WITHRECIPELEFT_LOOP;
938 			break;
939 
940 		case DOWN:
941 		case RIGHT:
942 			_nBodyOffset.set(-5, -7);
943 			bodyStartPat = BPAT_WITHRECIPERIGHT_START;
944 			headLoopPat = PAT_TALK_RIGHT;
945 			bodyLoopPat = BPAT_WITHRECIPERIGHT_LOOP;
946 			break;
947 
948 		default:
949 			break;
950 		}
951 		break;
952 
953 	case TALK_WITHCARDS:
954 		switch (_talkDirection) {
955 		case LEFT:
956 		case UP:
957 			_nBodyOffset.set(-34, -2);
958 			bodyStartPat = BPAT_WITHCARDSLEFT_START;
959 			headLoopPat = PAT_TALK_LEFT;
960 			bodyLoopPat = BPAT_WITHCARDSLEFT_LOOP;
961 			break;
962 
963 		case DOWN:
964 		case RIGHT:
965 			_nBodyOffset.set(-4, -2);
966 			bodyStartPat = BPAT_WITHCARDSRIGHT_START;
967 			headLoopPat = PAT_TALK_RIGHT;
968 			bodyLoopPat = BPAT_WITHCARDSRIGHT_LOOP;
969 			break;
970 
971 		default:
972 			break;
973 		}
974 		break;
975 
976 	case TALK_WITHSNOWMAN:
977 		switch (_talkDirection) {
978 		case LEFT:
979 		case UP:
980 			_nBodyOffset.set(-35, 2);
981 			bodyStartPat = BPAT_WITHSNOWMANLEFT_START;
982 			headLoopPat = PAT_TALK_LEFT;
983 			bodyLoopPat = BPAT_WITHSNOWMANLEFT_LOOP;
984 			break;
985 
986 		case DOWN:
987 		case RIGHT:
988 			_nBodyOffset.set(-14, 2);
989 			bodyStartPat = BPAT_WITHSNOWMANRIGHT_START;
990 			headLoopPat = PAT_TALK_RIGHT;
991 			bodyLoopPat = BPAT_WITHSNOWMANRIGHT_LOOP;
992 			break;
993 
994 		default:
995 			break;
996 		}
997 		break;
998 
999 	case TALK_WITHSNOWMANSTATIC:
1000 	case TALK_WITHRECIPESTATIC:
1001 	case TALK_WITHRABBITSTATIC:
1002 	case TALK_WITHCARDSSTATIC:
1003 	case TALK_WITH_NOTEBOOK:
1004 	case TALK_WITHMEGAPHONESTATIC:
1005 		switch (_talkDirection) {
1006 		case LEFT:
1007 		case UP:
1008 			headLoopPat = PAT_TALK_LEFT;
1009 			break;
1010 
1011 		case DOWN:
1012 		case RIGHT:
1013 			headLoopPat = PAT_TALK_RIGHT;
1014 			break;
1015 
1016 		default:
1017 			break;
1018 		}
1019 		break;
1020 
1021 		// The beard is the only case in which the head is animated separately while the body is the standard
1022 	case TALK_WITHBEARDSTATIC:
1023 		switch (_talkDirection) {
1024 		case LEFT:
1025 		case UP:
1026 			headLoopPat = PAT_TALKBEARD_LEFT;
1027 			bodyLoopPat = BPAT_STANDLEFT;
1028 			_nBodyOffset.set(6, 56);
1029 			break;
1030 
1031 		case DOWN:
1032 		case RIGHT:
1033 			headLoopPat = PAT_TALKBEARD_RIGHT;
1034 			bodyLoopPat = BPAT_STANDRIGHT;
1035 			_nBodyOffset.set(6, 56);
1036 			break;
1037 
1038 		default:
1039 			break;
1040 		}
1041 		break;
1042 
1043 	case TALK_DISGUSTED:
1044 		switch (_talkDirection) {
1045 		case LEFT:
1046 		case UP:
1047 			_nBodyOffset.set(6, 56);
1048 			headStartPat = PAT_DISGUSTEDLEFT_START;
1049 			bodyStartPat = BPAT_STANDLEFT;
1050 			headLoopPat = PAT_DISGUSTEDLEFT_LOOP;
1051 			break;
1052 
1053 		case DOWN:
1054 		case RIGHT:
1055 			_nBodyOffset.set(6, 56);
1056 			headStartPat = PAT_DISGUSTEDRIGHT_START;
1057 			bodyStartPat = BPAT_STANDRIGHT;
1058 			headLoopPat = PAT_DISGUSTEDRIGHT_LOOP;
1059 			break;
1060 
1061 		default:
1062 			break;
1063 		}
1064 		break;
1065 
1066 	case TALK_SARCASTIC:
1067 		switch (_talkDirection) {
1068 		case LEFT:
1069 		case UP:
1070 			_nBodyOffset.set(6, 56);
1071 			headStartPat = PAT_SARCASTICLEFT_START;
1072 			bodyStartPat = BPAT_STANDLEFT;
1073 			headLoopPat = PAT_SARCASTICLEFT_LOOP;
1074 			break;
1075 
1076 		case DOWN:
1077 		case RIGHT:
1078 			_nBodyOffset.set(6, 56);
1079 			headStartPat = PAT_SARCASTICRIGHT_START;
1080 			bodyStartPat = BPAT_STANDRIGHT;
1081 			headLoopPat = PAT_SARCASTICRIGHT_LOOP;
1082 			break;
1083 
1084 		default:
1085 			break;
1086 		}
1087 		break;
1088 
1089 	case TALK_MACBETH1:
1090 		_nBodyOffset.set(-33, -1);
1091 		headLoopPat = PAT_TALK_LEFT;
1092 		bodyLoopPat = BPAT_MACBETH1;
1093 		break;
1094 	case TALK_MACBETH2:
1095 		_nBodyOffset.set(-33, -1);
1096 		headLoopPat = PAT_TALK_LEFT;
1097 		bodyLoopPat = BPAT_MACBETH2;
1098 		break;
1099 	case TALK_MACBETH3:
1100 		_nBodyOffset.set(-33, -1);
1101 		headLoopPat = PAT_TALK_LEFT;
1102 		bodyLoopPat = BPAT_MACBETH3;
1103 		break;
1104 	case TALK_MACBETH4:
1105 		_nBodyOffset.set(-33, -1);
1106 		headLoopPat = PAT_TALK_LEFT;
1107 		bodyLoopPat = BPAT_MACBETH4;
1108 		break;
1109 	case TALK_MACBETH5:
1110 		_nBodyOffset.set(-33, -1);
1111 		headLoopPat = PAT_TALK_LEFT;
1112 		bodyLoopPat = BPAT_MACBETH5;
1113 		break;
1114 	case TALK_MACBETH6:
1115 		_nBodyOffset.set(-33, -1);
1116 		headLoopPat = PAT_TALK_LEFT;
1117 		bodyLoopPat = BPAT_MACBETH6;
1118 		break;
1119 	case TALK_MACBETH7:
1120 		_nBodyOffset.set(-33, -1);
1121 		headLoopPat = PAT_TALK_LEFT;
1122 		bodyLoopPat = BPAT_MACBETH7;
1123 		break;
1124 	case TALK_MACBETH8:
1125 		_nBodyOffset.set(-33, -1);
1126 		headLoopPat = PAT_TALK_LEFT;
1127 		bodyLoopPat = BPAT_MACBETH8;
1128 		break;
1129 	case TALK_MACBETH9:
1130 		_nBodyOffset.set(-33, -1);
1131 		headLoopPat = PAT_TALK_LEFT;
1132 		bodyLoopPat = BPAT_MACBETH9;
1133 		break;
1134 
1135 	case TALK_SCAREDSTATIC:
1136 		_bBodyFront = false;
1137 		switch (_talkDirection) {
1138 		case DOWN:
1139 			bodyStartPat = BPAT_STANDDOWN;
1140 			bodyLoopPat = BPAT_STANDDOWN;
1141 			_nBodyOffset.set(4, 53);
1142 
1143 			headStartPat = PAT_SCAREDDOWN_STAND;
1144 			headLoopPat = PAT_SCAREDDOWN_LOOP;
1145 			break;
1146 
1147 		case RIGHT:
1148 			bodyStartPat = BPAT_STANDRIGHT;
1149 			bodyLoopPat = BPAT_STANDRIGHT;
1150 			_nBodyOffset.set(6, 56);
1151 
1152 			headStartPat = PAT_SCAREDRIGHT_STAND;
1153 			headLoopPat = PAT_SCAREDRIGHT_LOOP;
1154 			break;
1155 
1156 		case LEFT:
1157 			bodyStartPat = BPAT_STANDLEFT;
1158 			bodyLoopPat = BPAT_STANDLEFT;
1159 			_nBodyOffset.set(6, 56);
1160 
1161 			headStartPat = PAT_SCAREDLEFT_STAND;
1162 			headLoopPat = PAT_SCAREDLEFT_LOOP;
1163 			break;
1164 
1165 		default:
1166 			break;
1167 		}
1168 		break;
1169 
1170 	default:
1171 		break;
1172 	}
1173 
1174 	return true;
1175 }
1176 
startTalk(CORO_PARAM,CharacterTalkType nTalkType)1177 void RMTony::startTalk(CORO_PARAM, CharacterTalkType nTalkType) {
1178 	CORO_BEGIN_CONTEXT;
1179 	int headStartPat, bodyStartPat;
1180 	int headLoopPat, bodyLoopPat;
1181 	CORO_END_CONTEXT(_ctx);
1182 
1183 	CORO_BEGIN_CODE(_ctx);
1184 
1185 	_ctx->headStartPat = _ctx->bodyStartPat = 0;
1186 	_ctx->headLoopPat = _ctx->bodyLoopPat = 0;
1187 
1188 	if (!startTalkCalculate(nTalkType, _ctx->headStartPat, _ctx->bodyStartPat,
1189 	                        _ctx->headLoopPat, _ctx->bodyLoopPat))
1190 		return;
1191 
1192 	// Perform the set pattern
1193 	if (_ctx->headStartPat != 0 || _ctx->bodyStartPat != 0) {
1194 		setPattern(_ctx->headStartPat);
1195 		_body.setPattern(_ctx->bodyStartPat);
1196 
1197 		if (_ctx->bodyStartPat != 0)
1198 			CORO_INVOKE_0(_body.waitForEndPattern);
1199 		if (_ctx->headStartPat != 0)
1200 			CORO_INVOKE_0(waitForEndPattern);
1201 	}
1202 
1203 	setPattern(_ctx->headLoopPat);
1204 	if (_ctx->bodyLoopPat)
1205 		_body.setPattern(_ctx->bodyLoopPat);
1206 
1207 	CORO_END_CODE;
1208 }
1209 
endTalkCalculate(int & headStandPat,int & headEndPat,int & bodyEndPat,int & finalPat,bool & bStatic)1210 bool RMTony::endTalkCalculate(int &headStandPat, int &headEndPat, int &bodyEndPat, int &finalPat, bool &bStatic) {
1211 	bodyEndPat = 0;
1212 	headEndPat = 0;
1213 
1214 	switch (_talkDirection) {
1215 	case UP:
1216 		finalPat = PAT_STANDUP;
1217 		headStandPat = PAT_HEAD_UP;
1218 		break;
1219 
1220 	case DOWN:
1221 		finalPat = PAT_STANDDOWN;
1222 		headStandPat = PAT_HEAD_DOWN;
1223 		break;
1224 
1225 	case LEFT:
1226 		finalPat = PAT_STANDLEFT;
1227 		headStandPat = PAT_HEAD_LEFT;
1228 		break;
1229 
1230 	case RIGHT:
1231 		finalPat = PAT_STANDRIGHT;
1232 		headStandPat = PAT_HEAD_RIGHT;
1233 		break;
1234 
1235 	default:
1236 		break;
1237 	}
1238 
1239 	if (_bShepherdess) {
1240 		setPattern(finalPat);
1241 		_bIsTalking = false;
1242 		return false;
1243 	}
1244 
1245 	bStatic = false;
1246 	switch (_nTalkType) {
1247 	case TALK_NORMAL:
1248 		bodyEndPat = 0;
1249 		break;
1250 
1251 	case TALK_HIPS:
1252 		switch (_talkDirection) {
1253 		case UP:
1254 			bodyEndPat = BPAT_HIPSUP_END;
1255 			break;
1256 
1257 		case DOWN:
1258 			bodyEndPat = BPAT_HIPSDOWN_END;
1259 			break;
1260 
1261 		case LEFT:
1262 			bodyEndPat = BPAT_HIPSLEFT_END;
1263 			break;
1264 
1265 		case RIGHT:
1266 			bodyEndPat = BPAT_HIPSRIGHT_END;
1267 			break;
1268 
1269 		default:
1270 			break;
1271 		}
1272 		break;
1273 
1274 	case TALK_SING:
1275 		bodyEndPat = BPAT_SINGLEFT_END;
1276 		break;
1277 
1278 	case TALK_LAUGH:
1279 	case TALK_LAUGH2:
1280 		if (_talkDirection == LEFT)
1281 			headEndPat = PAT_LAUGHLEFT_END;
1282 		else if (_talkDirection == RIGHT)
1283 			headEndPat = PAT_LAUGHRIGHT_END;
1284 
1285 		bodyEndPat = 0;
1286 		break;
1287 
1288 	case TALK_DISGUSTED:
1289 		switch (_talkDirection) {
1290 		case UP:
1291 		case LEFT:
1292 			headEndPat = PAT_DISGUSTEDLEFT_END;
1293 			break;
1294 
1295 		case DOWN:
1296 		case RIGHT:
1297 			headEndPat = PAT_DISGUSTEDRIGHT_END;
1298 			break;
1299 
1300 		default:
1301 			break;
1302 		}
1303 
1304 		bodyEndPat = 0;
1305 		break;
1306 
1307 	case TALK_SARCASTIC:
1308 		switch (_talkDirection) {
1309 		case UP:
1310 		case LEFT:
1311 			headEndPat = PAT_SARCASTICLEFT_END;
1312 			break;
1313 
1314 		case DOWN:
1315 		case RIGHT:
1316 			headEndPat = PAT_SARCASTICRIGHT_END;
1317 			break;
1318 
1319 		default:
1320 			break;
1321 		}
1322 
1323 		bodyEndPat = 0;
1324 		break;
1325 
1326 	case TALK_INDICATE:
1327 		break;
1328 
1329 	case TALK_SCARED:
1330 		switch (_talkDirection) {
1331 		case UP:
1332 			bodyEndPat = BPAT_SCAREDUP_END;
1333 			break;
1334 
1335 		case DOWN:
1336 			headEndPat = PAT_SCAREDDOWN_END;
1337 			bodyEndPat = BPAT_SCAREDDOWN_END;
1338 			break;
1339 
1340 		case RIGHT:
1341 			headEndPat = PAT_SCAREDRIGHT_END;
1342 			bodyEndPat = BPAT_SCAREDRIGHT_END;
1343 			break;
1344 
1345 		case LEFT:
1346 			headEndPat = PAT_SCAREDLEFT_END;
1347 			bodyEndPat = BPAT_SCAREDLEFT_END;
1348 			break;
1349 
1350 		default:
1351 			break;
1352 		}
1353 		break;
1354 
1355 	case TALK_SCARED2:
1356 		switch (_talkDirection) {
1357 		case UP:
1358 			bodyEndPat = 0;
1359 			break;
1360 
1361 		case DOWN:
1362 			headEndPat = PAT_SCAREDDOWN_END;
1363 			bodyEndPat = 0;
1364 			break;
1365 
1366 		case RIGHT:
1367 			headEndPat = PAT_SCAREDRIGHT_END;
1368 			bodyEndPat = 0;
1369 			break;
1370 
1371 		case LEFT:
1372 			headEndPat = PAT_SCAREDLEFT_END;
1373 			bodyEndPat = 0;
1374 			break;
1375 
1376 		default:
1377 			break;
1378 		}
1379 		break;
1380 
1381 	case TALK_WITHRABBIT:
1382 		switch (_talkDirection) {
1383 		case UP:
1384 		case LEFT:
1385 			finalPat = PAT_STANDLEFT;
1386 			bodyEndPat = BPAT_WITHRABBITLEFT_END;
1387 			break;
1388 
1389 		case RIGHT:
1390 		case DOWN:
1391 			finalPat = PAT_STANDRIGHT;
1392 			bodyEndPat = BPAT_WITHRABBITRIGHT_END;
1393 			break;
1394 
1395 		default:
1396 			break;
1397 		}
1398 		break;
1399 
1400 	case TALK_WITHRECIPE:
1401 		switch (_talkDirection) {
1402 		case UP:
1403 		case LEFT:
1404 			finalPat = PAT_STANDLEFT;
1405 			bodyEndPat = BPAT_WITHRECIPELEFT_END;
1406 			break;
1407 
1408 		case RIGHT:
1409 		case DOWN:
1410 			finalPat = PAT_STANDRIGHT;
1411 			bodyEndPat = BPAT_WITHRECIPERIGHT_END;
1412 			break;
1413 
1414 		default:
1415 			break;
1416 		}
1417 		break;
1418 
1419 	case TALK_WITHCARDS:
1420 		switch (_talkDirection) {
1421 		case UP:
1422 		case LEFT:
1423 			finalPat = PAT_STANDLEFT;
1424 			bodyEndPat = BPAT_WITHCARDSLEFT_END;
1425 			break;
1426 
1427 		case RIGHT:
1428 		case DOWN:
1429 			finalPat = PAT_STANDRIGHT;
1430 			bodyEndPat = BPAT_WITHCARDSRIGHT_END;
1431 			break;
1432 
1433 		default:
1434 			break;
1435 		}
1436 		break;
1437 
1438 	case TALK_WITHSNOWMAN:
1439 		switch (_talkDirection) {
1440 		case UP:
1441 		case LEFT:
1442 			finalPat = PAT_STANDLEFT;
1443 			bodyEndPat = BPAT_WITHSNOWMANLEFT_END;
1444 			break;
1445 
1446 		case RIGHT:
1447 		case DOWN:
1448 			finalPat = PAT_STANDRIGHT;
1449 			bodyEndPat = BPAT_WITHSNOWMANRIGHT_END;
1450 			break;
1451 
1452 		default:
1453 			break;
1454 		}
1455 		break;
1456 
1457 	case TALK_WITHWORM:
1458 		finalPat = PAT_WITHWORM;
1459 		break;
1460 	case TALK_WITHROPE:
1461 		finalPat = PAT_WITHROPE;
1462 		break;
1463 	case TALK_WITHSECRETARY:
1464 		finalPat = PAT_WITHSECRETARY;
1465 		break;
1466 	case TALK_WITHHAMMER:
1467 		finalPat = PAT_WITHHAMMER;
1468 		break;
1469 	case TALK_WITHGLASSES:
1470 		finalPat = PAT_WITHGLASSES;
1471 		break;
1472 
1473 	case TALK_MACBETH1:
1474 	case TALK_MACBETH2:
1475 	case TALK_MACBETH3:
1476 	case TALK_MACBETH4:
1477 	case TALK_MACBETH5:
1478 	case TALK_MACBETH6:
1479 	case TALK_MACBETH7:
1480 	case TALK_MACBETH8:
1481 		finalPat = 0;
1482 		break;
1483 
1484 	case TALK_SCAREDSTATIC:
1485 		switch (_talkDirection) {
1486 		case DOWN:
1487 			headStandPat = PAT_SCAREDDOWN_STAND;
1488 			bodyEndPat = 0;
1489 			break;
1490 
1491 		case RIGHT:
1492 			headStandPat = PAT_SCAREDRIGHT_STAND;
1493 			bodyEndPat = 0;
1494 			break;
1495 
1496 		case LEFT:
1497 			headStandPat = PAT_SCAREDLEFT_STAND;
1498 			bodyEndPat = 0;
1499 			break;
1500 
1501 
1502 		default:
1503 			break;
1504 		}
1505 		break;
1506 
1507 	default:
1508 		break;
1509 	}
1510 
1511 	return true;
1512 }
1513 
endTalk(CORO_PARAM)1514 void RMTony::endTalk(CORO_PARAM) {
1515 	CORO_BEGIN_CONTEXT;
1516 	int headStandPat, headEndPat;
1517 	int bodyEndPat, finalPat;
1518 	bool bStatic;
1519 	CORO_END_CONTEXT(_ctx);
1520 
1521 	CORO_BEGIN_CODE(_ctx);
1522 
1523 	_ctx->headStandPat = _ctx->headEndPat = 0;
1524 	_ctx->bodyEndPat = _ctx->finalPat = 0;
1525 	_ctx->bStatic = false;
1526 
1527 	_ctx->bodyEndPat = 0;
1528 	_ctx->headEndPat = 0;
1529 
1530 	if (!endTalkCalculate(_ctx->headStandPat, _ctx->headEndPat, _ctx->bodyEndPat, _ctx->finalPat, _ctx->bStatic))
1531 		return;
1532 
1533 	// Handles the end of an animated and static, leaving everything unchanged
1534 	if (_bIsStaticTalk) {
1535 		if (_nTalkType == TALK_WITHBEARDSTATIC) {
1536 			setPattern(0);
1537 			if (_talkDirection == UP || _talkDirection == LEFT) {
1538 				_body.setPattern(BPAT_WITHBEARDLEFT_STATIC);
1539 				_nBodyOffset.set(-41, -14);
1540 			} else if (_talkDirection == DOWN || _talkDirection == RIGHT) {
1541 				_body.setPattern(BPAT_WITHBEARDRIGHT_STATIC);
1542 				_nBodyOffset.set(-26, -14);
1543 			}
1544 		} else {
1545 			setPattern(_ctx->headStandPat);
1546 
1547 			CORO_INVOKE_0(_body.waitForEndPattern);
1548 		}
1549 
1550 		_bIsTalking = false;
1551 		return;
1552 	}
1553 
1554 	// Set the pattern
1555 	if (_ctx->headEndPat != 0 && _ctx->bodyEndPat != 0) {
1556 		setPattern(_ctx->headEndPat);
1557 
1558 		CORO_INVOKE_0(_body.waitForEndPattern);
1559 
1560 		_body.setPattern(_ctx->bodyEndPat);
1561 
1562 		CORO_INVOKE_0(waitForEndPattern);
1563 		CORO_INVOKE_0(_body.waitForEndPattern);
1564 	} else if (_ctx->bodyEndPat != 0) {
1565 		setPattern(_ctx->headStandPat);
1566 
1567 		CORO_INVOKE_0(_body.waitForEndPattern);
1568 
1569 		_body.setPattern(_ctx->bodyEndPat);
1570 
1571 		CORO_INVOKE_0(_body.waitForEndPattern);
1572 	} else if (_ctx->headEndPat != 0) {
1573 		CORO_INVOKE_0(_body.waitForEndPattern);
1574 
1575 		setPattern(_ctx->headEndPat);
1576 
1577 		CORO_INVOKE_0(waitForEndPattern);
1578 	} else {
1579 		CORO_INVOKE_0(_body.waitForEndPattern);
1580 	}
1581 
1582 	if (_ctx->finalPat != 0) {
1583 		_body.setPattern(0);
1584 		setPattern(_ctx->finalPat);
1585 	}
1586 
1587 	_bIsTalking = false;
1588 
1589 	CORO_END_CODE;
1590 }
1591 
startStaticCalculate(CharacterTalkType nTalk,int & headPat,int & headLoopPat,int & bodyStartPat,int & bodyLoopPat)1592 void RMTony::startStaticCalculate(CharacterTalkType nTalk, int &headPat, int &headLoopPat,
1593 								  int &bodyStartPat, int &bodyLoopPat) {
1594 	int nPat = getCurPattern();
1595 
1596 	headLoopPat = -1;
1597 
1598 	switch (nPat) {
1599 	case PAT_STANDDOWN:
1600 		_talkDirection = DOWN;
1601 		headPat = PAT_HEAD_RIGHT;
1602 		break;
1603 
1604 	case PAT_TAKELEFT_UP2:
1605 	case PAT_TAKELEFT_MID2:
1606 	case PAT_TAKELEFT_DOWN2:
1607 	case PAT_GETUPLEFT:
1608 	case PAT_STANDLEFT:
1609 		_talkDirection = LEFT;
1610 		headPat = PAT_HEAD_LEFT;
1611 		break;
1612 
1613 	case PAT_TAKERIGHT_UP2:
1614 	case PAT_TAKERIGHT_MID2:
1615 	case PAT_TAKERIGHT_DOWN2:
1616 	case PAT_GETUPRIGHT:
1617 	case PAT_STANDRIGHT:
1618 		_talkDirection = RIGHT;
1619 		headPat = PAT_HEAD_RIGHT;
1620 		break;
1621 
1622 	case PAT_TAKEUP_UP2:
1623 	case PAT_TAKEUP_MID2:
1624 	case PAT_TAKEUP_DOWN2:
1625 	case PAT_STANDUP:
1626 		_talkDirection = UP;
1627 		headPat = PAT_HEAD_LEFT;
1628 		break;
1629 
1630 	default:
1631 		break;
1632 	}
1633 
1634 	_bBodyFront = true;
1635 
1636 	switch (nTalk) {
1637 	case TALK_WITHRABBITSTATIC:
1638 		switch (_talkDirection) {
1639 		case UP:
1640 		case LEFT:
1641 			_nBodyOffset.set(-21, -5);
1642 			bodyStartPat = BPAT_WITHRABBITLEFT_START;
1643 			bodyLoopPat = BPAT_WITHRABBITLEFT_LOOP;
1644 			break;
1645 
1646 		case DOWN:
1647 		case RIGHT:
1648 			_nBodyOffset.set(-4, -5);
1649 			bodyStartPat = BPAT_WITHRABBITRIGHT_START;
1650 			bodyLoopPat = BPAT_WITHRABBITRIGHT_LOOP;
1651 			break;
1652 
1653 		default:
1654 			break;
1655 		}
1656 		break;
1657 
1658 	case TALK_WITHCARDSSTATIC:
1659 		switch (_talkDirection) {
1660 		case UP:
1661 		case LEFT:
1662 			_nBodyOffset.set(-34, -2);
1663 			bodyStartPat = BPAT_WITHCARDSLEFT_START;
1664 			bodyLoopPat = BPAT_WITHCARDSLEFT_LOOP;
1665 			break;
1666 
1667 		case DOWN:
1668 		case RIGHT:
1669 			_nBodyOffset.set(-4, -2);
1670 			bodyStartPat = BPAT_WITHCARDSRIGHT_START;
1671 			bodyLoopPat = BPAT_WITHCARDSRIGHT_LOOP;
1672 			break;
1673 
1674 		default:
1675 			break;
1676 		}
1677 		break;
1678 
1679 	case TALK_WITHRECIPESTATIC:
1680 		switch (_talkDirection) {
1681 		case UP:
1682 		case LEFT:
1683 			_nBodyOffset.set(-61, -7);
1684 			bodyStartPat = BPAT_WITHRECIPELEFT_START;
1685 			bodyLoopPat = BPAT_WITHRECIPELEFT_LOOP;
1686 			break;
1687 
1688 		case DOWN:
1689 		case RIGHT:
1690 			_nBodyOffset.set(-5, -7);
1691 			bodyStartPat = BPAT_WITHRECIPERIGHT_START;
1692 			bodyLoopPat = BPAT_WITHRECIPERIGHT_LOOP;
1693 			break;
1694 
1695 		default:
1696 			break;
1697 		}
1698 		break;
1699 
1700 	case TALK_WITHSNOWMANSTATIC:
1701 		switch (_talkDirection) {
1702 		case UP:
1703 		case LEFT:
1704 			_nBodyOffset.set(-35, 2);
1705 			bodyStartPat = BPAT_WITHSNOWMANLEFT_START;
1706 			bodyLoopPat = BPAT_WITHSNOWMANLEFT_LOOP;
1707 			break;
1708 
1709 		case DOWN:
1710 		case RIGHT:
1711 			_nBodyOffset.set(-14, 2);
1712 			bodyStartPat = BPAT_WITHSNOWMANRIGHT_START;
1713 			bodyLoopPat = BPAT_WITHSNOWMANRIGHT_LOOP;
1714 			break;
1715 
1716 		default:
1717 			break;
1718 		}
1719 		break;
1720 
1721 	case TALK_WITH_NOTEBOOK:
1722 		switch (_talkDirection) {
1723 		case UP:
1724 		case LEFT:
1725 			_nBodyOffset.set(-16, -9);
1726 			bodyStartPat = BPAT_WITHNOTEBOOKLEFT_START;
1727 			bodyLoopPat = BPAT_WITHNOTEBOOKLEFT_LOOP;
1728 			break;
1729 
1730 		case DOWN:
1731 		case RIGHT:
1732 			_nBodyOffset.set(-6, -9);
1733 			bodyStartPat = BPAT_WITHNOTEBOOKRIGHT_START;
1734 			bodyLoopPat = BPAT_WITHNOTEBOOKRIGHT_LOOP;
1735 			break;
1736 
1737 		default:
1738 			break;
1739 		}
1740 		break;
1741 
1742 	case TALK_WITHMEGAPHONESTATIC:
1743 		switch (_talkDirection) {
1744 		case UP:
1745 		case LEFT:
1746 			_nBodyOffset.set(-41, -8);
1747 			bodyStartPat = BPAT_WITHMEGAPHONELEFT_START;
1748 			bodyLoopPat = BPAT_WITHMEGAPHONELEFT_LOOP;
1749 			break;
1750 
1751 		case DOWN:
1752 		case RIGHT:
1753 			_nBodyOffset.set(-14, -8);
1754 			bodyStartPat = BPAT_WITHMEGAPHONERIGHT_START;
1755 			bodyLoopPat = BPAT_WITHMEGAPHONERIGHT_LOOP;
1756 			break;
1757 
1758 		default:
1759 			break;
1760 		}
1761 		break;
1762 
1763 	case TALK_WITHBEARDSTATIC:
1764 		switch (_talkDirection) {
1765 		case UP:
1766 		case LEFT:
1767 			_nBodyOffset.set(-41, -14);
1768 			bodyStartPat = BPAT_WITHBEARDLEFT_START;
1769 			bodyLoopPat = BPAT_STANDLEFT;
1770 			headLoopPat = PAT_TALKBEARD_LEFT;
1771 			headPat = 0;
1772 			break;
1773 
1774 		case DOWN:
1775 		case RIGHT:
1776 			_nBodyOffset.set(-26, -14);
1777 			bodyStartPat = BPAT_WITHBEARDRIGHT_START;
1778 			bodyLoopPat = BPAT_STANDRIGHT;
1779 			headLoopPat = PAT_TALKBEARD_RIGHT;
1780 			headPat = 0;
1781 			break;
1782 
1783 		default:
1784 			break;
1785 		}
1786 		break;
1787 
1788 	case TALK_SCAREDSTATIC:
1789 		switch (_talkDirection) {
1790 		case DOWN:
1791 			headPat = PAT_SCAREDDOWN_START;
1792 			bodyLoopPat = BPAT_STANDDOWN;
1793 			bodyStartPat = BPAT_STANDDOWN;
1794 			headLoopPat = PAT_SCAREDDOWN_STAND;
1795 			_nBodyOffset.set(4, 53);
1796 			break;
1797 
1798 		case LEFT:
1799 			headPat = PAT_SCAREDLEFT_START;
1800 			bodyLoopPat = BPAT_STANDLEFT;
1801 			bodyStartPat = BPAT_STANDLEFT;
1802 			headLoopPat = PAT_SCAREDLEFT_STAND;
1803 			_nBodyOffset.set(6, 56);
1804 			break;
1805 
1806 		case RIGHT:
1807 			headPat = PAT_SCAREDRIGHT_START;
1808 			bodyLoopPat = BPAT_STANDRIGHT;
1809 			bodyStartPat = BPAT_STANDRIGHT;
1810 			headLoopPat = PAT_SCAREDRIGHT_STAND;
1811 			_nBodyOffset.set(6, 56);
1812 			break;
1813 
1814 		case UP:
1815 		default:
1816 			break;
1817 		}
1818 
1819 	default:
1820 		break;
1821 	}
1822 }
1823 
startStatic(CORO_PARAM,CharacterTalkType nTalk)1824 void RMTony::startStatic(CORO_PARAM, CharacterTalkType nTalk) {
1825 	CORO_BEGIN_CONTEXT;
1826 	int headPat, headLoopPat;
1827 	int bodyStartPat, bodyLoopPat;
1828 	CORO_END_CONTEXT(_ctx);
1829 
1830 	CORO_BEGIN_CODE(_ctx);
1831 
1832 	_ctx->headPat = _ctx->headLoopPat = 0;
1833 	_ctx->bodyStartPat = _ctx->bodyLoopPat = 0;
1834 
1835 	startStaticCalculate(nTalk, _ctx->headPat, _ctx->headLoopPat,
1836 		_ctx->bodyStartPat, _ctx->bodyLoopPat);
1837 
1838 	// e vai con i pattern
1839 	_bIsStaticTalk = true;
1840 
1841 	setPattern(_ctx->headPat);
1842 	_body.setPattern(_ctx->bodyStartPat);
1843 
1844 	CORO_INVOKE_0(_body.waitForEndPattern);
1845 	CORO_INVOKE_0(waitForEndPattern);
1846 
1847 	if (_ctx->headLoopPat != -1)
1848 		setPattern(_ctx->headLoopPat);
1849 	_body.setPattern(_ctx->bodyLoopPat);
1850 
1851 	CORO_END_CODE;
1852 }
1853 
endStaticCalculate(CharacterTalkType nTalk,int & bodyEndPat,int & finalPat,int & headEndPat)1854 void RMTony::endStaticCalculate(CharacterTalkType nTalk, int &bodyEndPat, int &finalPat, int &headEndPat) {
1855 	switch (_talkDirection) {
1856 	case UP:
1857 	case LEFT:
1858 		finalPat = PAT_STANDLEFT;
1859 		break;
1860 
1861 	case RIGHT:
1862 	case DOWN:
1863 		finalPat = PAT_STANDRIGHT;
1864 		break;
1865 
1866 	default:
1867 		break;
1868 	}
1869 
1870 	switch (nTalk) {
1871 	case TALK_WITHSNOWMANSTATIC:
1872 		switch (_talkDirection) {
1873 		case UP:
1874 		case LEFT:
1875 			bodyEndPat = BPAT_WITHSNOWMANLEFT_END;
1876 			break;
1877 
1878 		case DOWN:
1879 		case RIGHT:
1880 			bodyEndPat = BPAT_WITHSNOWMANRIGHT_END;
1881 			break;
1882 
1883 		default:
1884 			break;
1885 		}
1886 		break;
1887 
1888 	case TALK_WITHRECIPESTATIC:
1889 		switch (_talkDirection) {
1890 		case UP:
1891 		case LEFT:
1892 			bodyEndPat = BPAT_WITHRECIPELEFT_END;
1893 			break;
1894 
1895 		case DOWN:
1896 		case RIGHT:
1897 			bodyEndPat = BPAT_WITHRECIPERIGHT_END;
1898 			break;
1899 
1900 		default:
1901 			break;
1902 		}
1903 		break;
1904 
1905 	case TALK_WITHRABBITSTATIC:
1906 		switch (_talkDirection) {
1907 		case UP:
1908 		case LEFT:
1909 			bodyEndPat = BPAT_WITHRABBITLEFT_END;
1910 			break;
1911 
1912 		case DOWN:
1913 		case RIGHT:
1914 			bodyEndPat = BPAT_WITHRABBITRIGHT_END;
1915 			break;
1916 
1917 		default:
1918 			break;
1919 		}
1920 		break;
1921 
1922 	case TALK_WITHCARDSSTATIC:
1923 		switch (_talkDirection) {
1924 		case UP:
1925 		case LEFT:
1926 			bodyEndPat = BPAT_WITHCARDSLEFT_END;
1927 			break;
1928 
1929 		case DOWN:
1930 		case RIGHT:
1931 			bodyEndPat = BPAT_WITHCARDSRIGHT_END;
1932 			break;
1933 
1934 		default:
1935 			break;
1936 		}
1937 		break;
1938 
1939 	case TALK_WITH_NOTEBOOK:
1940 		switch (_talkDirection) {
1941 		case UP:
1942 		case LEFT:
1943 			bodyEndPat = BPAT_WITHNOTEBOOKLEFT_END;
1944 			break;
1945 
1946 		case DOWN:
1947 		case RIGHT:
1948 			bodyEndPat = BPAT_WITHNOTEBOOKRIGHT_END;
1949 			break;
1950 
1951 		default:
1952 			break;
1953 		}
1954 		break;
1955 
1956 	case TALK_WITHMEGAPHONESTATIC:
1957 		switch (_talkDirection) {
1958 		case UP:
1959 		case LEFT:
1960 			bodyEndPat = BPAT_WITHMEGAPHONELEFT_END;
1961 			break;
1962 
1963 		case DOWN:
1964 		case RIGHT:
1965 			bodyEndPat = BPAT_WITHMEGAPHONERIGHT_END;
1966 			break;
1967 
1968 		default:
1969 			break;
1970 		}
1971 		break;
1972 
1973 	case TALK_WITHBEARDSTATIC:
1974 		switch (_talkDirection) {
1975 		case UP:
1976 		case LEFT:
1977 			bodyEndPat = BPAT_WITHBEARDLEFT_END;
1978 			break;
1979 
1980 		case DOWN:
1981 		case RIGHT:
1982 			bodyEndPat = BPAT_WITHBEARDRIGHT_END;
1983 			break;
1984 
1985 		default:
1986 			break;
1987 		}
1988 		break;
1989 
1990 	case TALK_SCAREDSTATIC:
1991 		switch (_talkDirection) {
1992 		case LEFT:
1993 			headEndPat = PAT_SCAREDLEFT_END;
1994 			break;
1995 
1996 		case DOWN:
1997 			headEndPat = PAT_SCAREDDOWN_END;
1998 			break;
1999 
2000 		case RIGHT:
2001 			headEndPat = PAT_SCAREDRIGHT_END;
2002 			break;
2003 
2004 		case UP:
2005 		default:
2006 			break;
2007 		}
2008 		break;
2009 
2010 	default:
2011 		break;
2012 	}
2013 }
2014 
endStatic(CORO_PARAM,CharacterTalkType nTalk)2015 void RMTony::endStatic(CORO_PARAM, CharacterTalkType nTalk) {
2016 	CORO_BEGIN_CONTEXT;
2017 	int bodyEndPat;
2018 	int finalPat;
2019 	int headEndPat;
2020 	CORO_END_CONTEXT(_ctx);
2021 
2022 	CORO_BEGIN_CODE(_ctx);
2023 
2024 	_ctx->bodyEndPat = 0;
2025 	_ctx->finalPat = 0;
2026 	_ctx->headEndPat = 0;
2027 
2028 	endStaticCalculate(nTalk, _ctx->bodyEndPat, _ctx->finalPat, _ctx->headEndPat);
2029 
2030 	if (_ctx->headEndPat != 0) {
2031 		setPattern(_ctx->headEndPat);
2032 
2033 		CORO_INVOKE_0(waitForEndPattern);
2034 	} else {
2035 		// Play please
2036 		_body.setPattern(_ctx->bodyEndPat);
2037 
2038 		CORO_INVOKE_0(_body.waitForEndPattern);
2039 	}
2040 
2041 	setPattern(_ctx->finalPat);
2042 	_body.setPattern(0);
2043 
2044 	_bIsStaticTalk = false;
2045 
2046 	CORO_END_CODE;
2047 }
2048 
2049 /**
2050  * Waits until the end of a pattern
2051  */
waitForEndPattern(CORO_PARAM,uint32 hCustomSkip)2052 void RMTony::waitForEndPattern(CORO_PARAM, uint32 hCustomSkip) {
2053 	RMCharacter::waitForEndPattern(coroParam, hCustomSkip);
2054 }
2055 
2056 /**
2057  * Check if currently in an action
2058  */
inAction()2059 bool RMTony::inAction() {
2060 	return (_bActionPending && _action != 0) | _bAction;
2061 }
2062 
2063 /**
2064  * Check if there needs to be an update for scrolling movement
2065  */
mustUpdateScrolling()2066 bool RMTony::mustUpdateScrolling() {
2067 	return ((!inAction()) || (isMoving()));
2068 }
2069 
2070 /**
2071  * Returns Tony's position
2072  */
position()2073 RMPoint RMTony::position() {
2074 	return _pos;
2075 }
2076 
2077 /**
2078  * Set the scrolling position
2079  */
setScrollPosition(const RMPoint & pt)2080 void RMTony::setScrollPosition(const RMPoint &pt) {
2081 	RMCharacter::setScrollPosition(pt);
2082 }
2083 
2084 /**
2085  * Tony disguises himself!
2086  */
setShepherdess(bool bIsPast)2087 void RMTony::setShepherdess(bool bIsPast) {
2088 	_bShepherdess = bIsPast;
2089 }
2090 
getShepherdess()2091 int RMTony::getShepherdess() {
2092 	return _bShepherdess;
2093 }
2094 
playSfx(int nSfx)2095 void RMTony::playSfx(int nSfx) {
2096 	RMItem::playSfx(nSfx);
2097 }
2098 
2099 } // End of namespace Tony
2100