scummvm/engines/tony/custom.cpp
2014-02-18 02:39:39 +01:00

2505 lines
68 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on original Tony Tough source code
*
* Copyright (c) 1997-2003 Nayma Software
*/
#include "common/system.h"
#include "common/savefile.h"
#include "tony/mpal/mpal.h"
#include "tony/mpal/memory.h"
#include "tony/custom.h"
#include "tony/font.h"
#include "tony/game.h"
#include "tony/gfxcore.h"
#include "tony/tony.h"
#include "tony/tonychar.h"
#include "tony/utils.h"
namespace Tony {
static const char *const kAmbianceFile[] = {
"None",
"1.ADP", // Grilli.WAV
"2.ADP", // Grilli-Ovattati.WAV
"3.ADP", // Grilli-Vento.WAV
"3.ADP", // Grilli-Vento1.WAV
"5.ADP", // Vento1.WAV
"4.ADP", // Mare1.WAV
"6.ADP" // Mare1.WAV half volume
};
static const MusicFileEntry kMusicFiles[] = {
{"00.ADP", 0}, {"01.ADP", 0}, {"02.ADP", 0}, {"03.ADP", 0},
{"04.ADP", 0}, {"05.ADP", 0}, {"06.ADP", 0}, {"07.ADP", 0},
{"08.ADP", 2450}, {"09.ADP", 0}, {"10.ADP", 0}, {"11.ADP", 0},
{"12.ADP", 0}, {"13.ADP", 0}, {"14.ADP", 0}, {"15.ADP", 0},
{"16.ADP", 0}, {"17.ADP", 0}, {"18.ADP", 0}, {"19.ADP", 0},
{"20.ADP", 0}, {"21.ADP", 0}, {"22.ADP", 0}, {"23.ADP", 0},
{"24.ADP", 0}, {"25.ADP", 0}, {"26.ADP", 0}, {"27.ADP", 0},
{"28.ADP", 1670}, {"29.ADP", 0}, {"30.ADP", 0}, {"31.ADP", 0},
{"32.ADP", 2900}, {"33.ADP", 0}, {"34.ADP", 0}, {"35.ADP", 0},
{"36.ADP", 0}, {"37.ADP", 0}, {"38.ADP", 0}, {"39.ADP", 0},
{"40.ADP", 0}, {"41.ADP", 1920}, {"42.ADP", 1560}, {"43.ADP", 1920},
{"44.ADP", 1920}, {"45.ADP", 1920}, {"46.ADP", 1920}, {"47.ADP", 1920},
{"48.ADP", 1920}, {"49.ADP", 1920}, {"50.ADP", 1920}, {"51.ADP", 1920},
{"52.ADP", 1920}, {"53.ADP", 0}, {"54.ADP", 0}, {"55.ADP", 0},
{"56.ADP", 0}, {"57.ADP", 0}, {"58.ADP", 0}, {"59.ADP", 0}
};
static const char *const kJingleFileNames[] = {
"S00.ADP", "S01.ADP", "S02.ADP", "S03.ADP", "S04.ADP",
"S05.ADP", "S06.ADP", "S07.ADP", "S08.ADP", "S09.ADP",
"S10.ADP", "S11.ADP", "S12.ADP", "S13.ADP", "S14.ADP",
"S15.ADP", "S16.ADP", "S17.ADP", "S18.ADP"
};
void reapplyChangedHotspot() {
for (int i = 0; i < GLOBALS._curChangedHotspot; i++)
GLOBALS._loc->getItemFromCode(GLOBALS._changedHotspot[i]._dwCode)->changeHotspot(RMPoint(GLOBALS._changedHotspot[i]._nX, GLOBALS._changedHotspot[i]._nY));
}
void saveChangedHotspot(Common::OutSaveFile *f) {
f->writeByte(GLOBALS._curChangedHotspot);
if (GLOBALS._curChangedHotspot > 0) {
for (int i = 0; i < GLOBALS._curChangedHotspot; ++i)
GLOBALS._changedHotspot[i].save(f);
}
}
void loadChangedHotspot(Common::InSaveFile *f) {
GLOBALS._curChangedHotspot = f->readByte();
if (GLOBALS._curChangedHotspot > 0) {
for (int i = 0; i < GLOBALS._curChangedHotspot; ++i)
GLOBALS._changedHotspot[i].load(f);
}
}
/**
* Classes required for custom functions
*
* Tony (To Move him) -> You can do MPAL through the animation? I really think so
*
* SendMessage -> I'd say just theEngine.SendMessage()
* ChangeLocation -> theEngine.ChangeLocation()
* AddInventory -> theEngine.AddInventory()
*/
void mCharResetCodes() {
for (int i = 0; i < 10; i++)
GLOBALS._mCharacter[i]._item = GLOBALS._loc->getItemFromCode(GLOBALS._mCharacter[i]._code);
for (int i = 0; i < 10; i++)
GLOBALS._character[i]._item = GLOBALS._loc->getItemFromCode(GLOBALS._character[i]._code);
}
void charsSaveAll(Common::OutSaveFile *f) {
for (int i = 0; i < 10; i++) {
f->writeByte(GLOBALS._isMChar[i]);
if (GLOBALS._isMChar[i]) {
GLOBALS._mCharacter[i].save(f);
} else {
GLOBALS._character[i].save(f);
}
}
}
void charsLoadAll(Common::InSaveFile *f) {
for (int i = 0; i < 10; i++) {
GLOBALS._isMChar[i] = f->readByte();
if (GLOBALS._isMChar[i])
GLOBALS._mCharacter[i].load(f);
else
GLOBALS._character[i].load(f);
}
}
void faceToMe(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_STANDDOWN);
}
void backToMe(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_STANDUP);
}
void leftToMe(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_STANDLEFT);
}
void rightToMe(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_STANDRIGHT);
}
void tonySetPerorate(CORO_PARAM, uint32 bStatus, uint32, uint32, uint32) {
g_vm->getEngine()->setPerorate(bStatus);
}
void mySleep(CORO_PARAM, uint32 dwTime, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
int i;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
if (!GLOBALS._bSkipIdle)
CORO_INVOKE_1(CoroScheduler.sleep, dwTime);
CORO_END_CODE;
}
void setAlwaysDisplay(CORO_PARAM, uint32 val, uint32, uint32, uint32) {
GLOBALS._bAlwaysDisplay = (val != 0);
}
void setPointer(CORO_PARAM, uint32 dwPointer, uint32, uint32, uint32) {
switch (dwPointer) {
case 1:
GLOBALS._pointer->setSpecialPointer(GLOBALS._pointer->PTR_ARROWUP);
break;
case 2:
GLOBALS._pointer->setSpecialPointer(GLOBALS._pointer->PTR_ARROWDOWN);
break;
case 3:
GLOBALS._pointer->setSpecialPointer(GLOBALS._pointer->PTR_ARROWLEFT);
break;
case 4:
GLOBALS._pointer->setSpecialPointer(GLOBALS._pointer->PTR_ARROWRIGHT);
break;
case 5:
GLOBALS._pointer->setSpecialPointer(GLOBALS._pointer->PTR_ARROWMAP);
break;
default:
GLOBALS._pointer->setSpecialPointer(GLOBALS._pointer->PTR_NONE);
break;
}
}
VoiceHeader *searchVoiceHeader(uint32 codehi, uint32 codelo) {
int code = (codehi << 16) | codelo;
if (g_vm->_voices.size() == 0)
return NULL;
for (uint i = 0; i < g_vm->_voices.size(); i++) {
if (g_vm->_voices[i]._code == code)
return &g_vm->_voices[i];
}
return NULL;
}
void sendTonyMessage(CORO_PARAM, uint32 dwMessage, uint32 nX, uint32 nY, uint32) {
CORO_BEGIN_CONTEXT;
RMMessage msg;
int i;
int curOffset;
VoiceHeader *curVoc;
FPSfx *voice;
RMTextDialog text;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
_ctx->curOffset = 0;
if (GLOBALS._bSkipIdle)
return;
_ctx->msg.load(dwMessage);
if (!_ctx->msg.isValid())
return;
_ctx->curVoc = searchVoiceHeader(0, dwMessage);
_ctx->voice = NULL;
if (_ctx->curVoc) {
// Is positioned within the database of entries beginning at the first
_ctx->curOffset = _ctx->curVoc->_offset;
// First time allocation
g_vm->_vdbFP.seek(_ctx->curOffset);
g_vm->_theSound.createSfx(&_ctx->voice);
_ctx->voice->loadVoiceFromVDB(g_vm->_vdbFP);
_ctx->curOffset = g_vm->_vdbFP.pos();
_ctx->voice->setLoop(false);
}
if (GLOBALS._nTonyNextTalkType != GLOBALS._tony->TALK_NORMAL) {
CORO_INVOKE_1(GLOBALS._tony->startTalk, GLOBALS._nTonyNextTalkType);
if (!GLOBALS._bStaticTalk)
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_NORMAL;
} else {
if (_ctx->msg.numPeriods() > 1)
CORO_INVOKE_1(GLOBALS._tony->startTalk, GLOBALS._tony->TALK_HIPS);
else
CORO_INVOKE_1(GLOBALS._tony->startTalk, GLOBALS._tony->TALK_NORMAL);
}
if (GLOBALS._curBackText)
CORO_INVOKE_0(GLOBALS._curBackText->hide);
GLOBALS._bTonyIsSpeaking = true;
for (_ctx->i = 0; _ctx->i < _ctx->msg.numPeriods() && !GLOBALS._bSkipIdle; _ctx->i++) {
_ctx->text.setInput(GLOBALS._input);
// Alignment
_ctx->text.setAlignType(RMText::HCENTER, RMText::VBOTTOM);
// Color
_ctx->text.setColor(0, 255, 0);
// Writes the text
_ctx->text.writeText(_ctx->msg[_ctx->i], 0);
// Set the position
if (nX == 0 && nY == 0)
_ctx->text.setPosition(GLOBALS._tony->position() - RMPoint(0, 130) - GLOBALS._loc->scrollPosition());
else
_ctx->text.setPosition(RMPoint(nX, nY) - GLOBALS._loc->scrollPosition());
// Handling for always display
if (GLOBALS._bAlwaysDisplay) {
_ctx->text.setAlwaysDisplay();
_ctx->text.forceTime();
}
// Record the text
g_vm->getEngine()->linkGraphicTask(&_ctx->text);
if (_ctx->curVoc) {
if (_ctx->i == 0) {
_ctx->voice->play();
_ctx->text.setCustomSkipHandle2(_ctx->voice->_hEndOfBuffer);
} else {
g_vm->_vdbFP.seek(_ctx->curOffset);
g_vm->_theSound.createSfx(&_ctx->voice);
_ctx->voice->loadVoiceFromVDB(g_vm->_vdbFP);
_ctx->curOffset = g_vm->_vdbFP.pos();
_ctx->voice->setLoop(false);
_ctx->voice->play();
_ctx->text.setCustomSkipHandle2(_ctx->voice->_hEndOfBuffer);
}
}
// Wait for the end of the display
_ctx->text.setCustomSkipHandle(GLOBALS._hSkipIdle);
CORO_INVOKE_0(_ctx->text.waitForEndDisplay);
if (_ctx->curVoc) {
_ctx->voice->stop();
_ctx->voice->release();
_ctx->voice = NULL;
}
}
GLOBALS._bTonyIsSpeaking = false;
if (GLOBALS._curBackText)
GLOBALS._curBackText->show();
CORO_INVOKE_0(GLOBALS._tony->endTalk);
CORO_END_CODE;
}
void changeBoxStatus(CORO_PARAM, uint32 nLoc, uint32 nBox, uint32 nStatus, uint32) {
GLOBALS._boxes->changeBoxStatus(nLoc, nBox, nStatus);
}
void custLoadLocation(CORO_PARAM, uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) {
CORO_BEGIN_CONTEXT;
uint32 h;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._curChangedHotspot = 0;
if (bUseStartPos != 0)
g_vm->getEngine()->loadLocation(nLoc, RMPoint(tX, tY), GLOBALS._startLocPos[nLoc]);
else
g_vm->getEngine()->loadLocation(nLoc, RMPoint(tX, tY), RMPoint(-1, -1));
_ctx->h = mpalQueryDoAction(0, nLoc, 0);
// On Enter?
if (_ctx->h != CORO_INVALID_PID_VALUE)
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, _ctx->h, CORO_INFINITE);
CORO_END_CODE;
}
void sendFullscreenMsgStart(CORO_PARAM, uint32 nMsg, uint32 nFont, uint32, uint32) {
CORO_BEGIN_CONTEXT;
RMMessage *msg;
RMGfxClearTask clear;
int i;
RMTextDialog text;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
_ctx->msg = new RMMessage(nMsg);
GLOBALS._fullScreenMessageLoc = GLOBALS._loc->TEMPGetNumLoc();
GLOBALS._fullScreenMessagePt = GLOBALS._tony->position();
if (GLOBALS._bSkipIdle)
return;
CORO_INVOKE_2(g_vm->getEngine()->unloadLocation, false, NULL);
GLOBALS._tony->hide();
for (_ctx->i = 0; _ctx->i < _ctx->msg->numPeriods() && !GLOBALS._bSkipIdle; _ctx->i++) {
_ctx->text.setInput(GLOBALS._input);
// Alignment
_ctx->text.setAlignType(RMText::HCENTER, RMText::VCENTER);
// Forces the text to disappear in time
_ctx->text.forceTime();
// Color
_ctx->text.setColor(255, 255, 255);
// Write the text
if (nFont == 0)
_ctx->text.writeText((*_ctx->msg)[_ctx->i], 1);
else if (nFont == 1)
_ctx->text.writeText((*_ctx->msg)[_ctx->i], 0);
// Set the position
_ctx->text.setPosition(RMPoint(320, 240));
_ctx->text.setAlwaysDisplay();
_ctx->text.forceTime();
// Record the text
g_vm->getEngine()->linkGraphicTask(&_ctx->clear);
g_vm->getEngine()->linkGraphicTask(&_ctx->text);
// Wait for the end of display
_ctx->text.setCustomSkipHandle(GLOBALS._hSkipIdle);
CORO_INVOKE_0(_ctx->text.waitForEndDisplay);
}
delete _ctx->msg;
CORO_END_CODE;
}
void clearScreen(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
char buf[256];
RMGfxClearTask clear;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
g_vm->getEngine()->linkGraphicTask(&_ctx->clear);
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, g_vm->_hEndOfFrame, CORO_INFINITE);
// WORKAROUND: This fixes a bug in the original source where the linked clear task
// didn't have time to be drawn and removed from the draw list before the method
// ended, thus remaining in the draw list and causing a later crash
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, g_vm->_hEndOfFrame, CORO_INFINITE);
CORO_END_CODE;
}
void sendFullscreenMsgEnd(CORO_PARAM, uint32 bNotEnableTony, uint32, uint32, uint32) {
g_vm->getEngine()->loadLocation(GLOBALS._fullScreenMessageLoc, RMPoint(GLOBALS._fullScreenMessagePt._x, GLOBALS._fullScreenMessagePt._y), RMPoint(-1, -1));
if (!bNotEnableTony)
GLOBALS._tony->show();
mCharResetCodes();
reapplyChangedHotspot();
}
void sendFullscreenMessage(CORO_PARAM, uint32 nMsg, uint32 nFont, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_4(sendFullscreenMsgStart, nMsg, nFont, 0, 0);
CORO_INVOKE_4(sendFullscreenMsgEnd, 0, 0, 0, 0);
CORO_END_CODE;
}
void noBullsEye(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._bNoBullsEye = true;
}
void closeLocation(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
if (!GLOBALS._bNoBullsEye) {
g_vm->getEngine()->initWipe(1);
CORO_INVOKE_0(g_vm->getEngine()->waitWipeEnd);
}
g_vm->stopMusic(4);
// On exit, unload
CORO_INVOKE_2(g_vm->getEngine()->unloadLocation, true, NULL);
CORO_END_CODE;
}
void changeLocation(CORO_PARAM, uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) {
CORO_BEGIN_CONTEXT;
uint32 h;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
if (!GLOBALS._bNoBullsEye) {
g_vm->getEngine()->initWipe(1);
CORO_INVOKE_0(g_vm->getEngine()->waitWipeEnd);
}
if (GLOBALS._lastTappeto != GLOBALS._ambiance[nLoc]) {
g_vm->stopMusic(4);
}
// On exit, unfreeze
CORO_INVOKE_2(g_vm->getEngine()->unloadLocation, true, NULL);
GLOBALS._curChangedHotspot = 0;
if (bUseStartPos != 0)
g_vm->getEngine()->loadLocation(nLoc, RMPoint(tX, tY), GLOBALS._startLocPos[nLoc]);
else
g_vm->getEngine()->loadLocation(nLoc, RMPoint(tX, tY), RMPoint(-1, -1));
if (GLOBALS._lastTappeto != GLOBALS._ambiance[nLoc]) {
GLOBALS._lastTappeto = GLOBALS._ambiance[nLoc];
if (GLOBALS._lastTappeto != 0)
g_vm->playMusic(4, kAmbianceFile[GLOBALS._lastTappeto], 0, true, 2000);
}
if (!GLOBALS._bNoBullsEye) {
g_vm->getEngine()->initWipe(2);
}
_ctx->h = mpalQueryDoAction(0, nLoc, 0);
if (!GLOBALS._bNoBullsEye) {
CORO_INVOKE_0(g_vm->getEngine()->waitWipeEnd);
g_vm->getEngine()->closeWipe();
}
GLOBALS._bNoBullsEye = false;
// On Enter?
if (_ctx->h != CORO_INVALID_PID_VALUE)
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, _ctx->h, CORO_INFINITE);
CORO_END_CODE;
}
void setLocStartPosition(CORO_PARAM, uint32 nLoc, uint32 lX, uint32 lY, uint32) {
GLOBALS._startLocPos[nLoc].set(lX, lY);
}
void saveTonyPosition(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._saveTonyPos = GLOBALS._tony->position();
GLOBALS._saveTonyLoc = GLOBALS._loc->TEMPGetNumLoc();
}
void restoreTonyPosition(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_4(changeLocation, GLOBALS._saveTonyLoc, GLOBALS._saveTonyPos._x, GLOBALS._saveTonyPos._y, 0);
mCharResetCodes();
CORO_END_CODE;
}
void disableInput(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->getEngine()->disableInput();
}
void enableInput(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->getEngine()->enableInput();
}
void stopTony(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._tony->stopNoAction(coroParam);
}
void custEnableGUI(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS.EnableGUI();
}
void custDisableGUI(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS.DisableGUI();
}
void tonyGenericTake1(CORO_PARAM, uint32 nDirection) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._tony->take(nDirection, 0);
if (!GLOBALS._bSkipIdle)
CORO_INVOKE_0(GLOBALS._tony->waitForEndPattern);
CORO_END_CODE;
}
void tonyGenericTake2(CORO_PARAM, uint32 nDirection) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._tony->take(nDirection, 1);
if (!GLOBALS._bSkipIdle)
CORO_INVOKE_0(GLOBALS._tony->waitForEndPattern);
GLOBALS._tony->take(nDirection, 2);
CORO_END_CODE;
}
void tonyGenericPut1(CORO_PARAM, uint32 nDirection) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._tony->put(nDirection, 0);
if (!GLOBALS._bSkipIdle)
CORO_INVOKE_0(GLOBALS._tony->waitForEndPattern);
CORO_END_CODE;
}
void tonyGenericPut2(CORO_PARAM, uint32 nDirection) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._tony->put(nDirection, 1);
if (!GLOBALS._bSkipIdle)
CORO_INVOKE_0(GLOBALS._tony->waitForEndPattern);
GLOBALS._tony->put(nDirection, 2);
CORO_END_CODE;
}
void tonyTakeUp1(CORO_PARAM, uint32, uint32, uint32, uint32) {
tonyGenericTake1(coroParam, 0);
}
void tonyTakeMid1(CORO_PARAM, uint32, uint32, uint32, uint32) {
tonyGenericTake1(coroParam, 1);
}
void tonyTakeDown1(CORO_PARAM, uint32, uint32, uint32, uint32) {
tonyGenericTake1(coroParam, 2);
}
void tonyTakeUp2(CORO_PARAM, uint32, uint32, uint32, uint32) {
tonyGenericTake2(coroParam, 0);
}
void tonyTakeMid2(CORO_PARAM, uint32, uint32, uint32, uint32) {
tonyGenericTake2(coroParam, 1);
}
void tonyTakeDown2(CORO_PARAM, uint32, uint32, uint32, uint32) {
tonyGenericTake2(coroParam, 2);
}
void tonyPutUp1(CORO_PARAM, uint32, uint32, uint32, uint32) {
tonyGenericPut1(coroParam, 0);
}
void tonyPutMid1(CORO_PARAM, uint32, uint32, uint32, uint32) {
tonyGenericPut1(coroParam, 1);
}
void tonyPutDown1(CORO_PARAM, uint32, uint32, uint32, uint32) {
tonyGenericPut1(coroParam, 2);
}
void tonyPutUp2(CORO_PARAM, uint32, uint32, uint32, uint32) {
tonyGenericPut2(coroParam, 0);
}
void tonyPutMid2(CORO_PARAM, uint32, uint32, uint32, uint32) {
tonyGenericPut2(coroParam, 1);
}
void tonyPutDown2(CORO_PARAM, uint32, uint32, uint32, uint32) {
tonyGenericPut2(coroParam, 2);
}
void tonyOnTheFloor(CORO_PARAM, uint32 dwParte, uint32, uint32, uint32) {
if (dwParte == 0)
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_ONTHEFLOORLEFT);
else
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_ONTHEFLOORRIGHT);
}
void tonyGetUp(CORO_PARAM, uint32 dwParte, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
if (dwParte == 0)
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_GETUPLEFT);
else
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_GETUPRIGHT);
if (!GLOBALS._bSkipIdle)
CORO_INVOKE_0(GLOBALS._tony->waitForEndPattern);
CORO_END_CODE;
}
void tonyShepherdess(CORO_PARAM, uint32 bIsPast, uint32, uint32, uint32) {
GLOBALS._tony->setShepherdess(bIsPast);
}
void tonyWhistle(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_WHISTLERIGHT);
if (!GLOBALS._bSkipIdle)
CORO_INVOKE_0(GLOBALS._tony->waitForEndPattern);
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_STANDRIGHT);
CORO_END_CODE;
}
void tonySetNumTexts(uint32 dwText) {
GLOBALS._dwTonyNumTexts = dwText;
GLOBALS._bTonyInTexts = false;
}
void tonyLaugh(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_LAUGH;
}
void tonyGiggle(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_LAUGH2;
}
void tonyHips(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_HIPS;
}
void tonySing(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_SING;
}
void tonyIndicate(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_INDICATE;
}
void tonyScaredWithHands(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_SCARED;
}
void tonyScaredWithoutHands(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_SCARED2;
}
void tonyWithHammer(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHHAMMER;
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_WITHHAMMER);
}
void tonyWithGlasses(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHGLASSES;
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_WITHGLASSES);
}
void tonyWithWorm(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHWORM;
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_WITHWORM);
}
void tonyWithRope(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHROPE;
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_WITHROPE);
}
void tonyWithSecretary(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHSECRETARY;
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_WITHSECRETARY);
}
void tonyWithRabbitANIM(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHRABBIT;
}
void tonyWithRecipeANIM(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHRECIPE;
}
void tonyWithCardsANIM(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHCARDS;
}
void tonyWithSnowmanANIM(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHSNOWMAN;
}
void tonyWithSnowmanStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHSNOWMANSTATIC;
GLOBALS._bStaticTalk = true;
CORO_INVOKE_1(GLOBALS._tony->startStatic, GLOBALS._tony->TALK_WITHSNOWMANSTATIC);
CORO_END_CODE;
}
void tonyWithSnowmanEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_1(GLOBALS._tony->endStatic, GLOBALS._tony->TALK_WITHSNOWMANSTATIC);
GLOBALS._bStaticTalk = false;
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_NORMAL;
CORO_END_CODE;
}
void tonyWithRabbitStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHRABBITSTATIC;
GLOBALS._bStaticTalk = true;
CORO_INVOKE_1(GLOBALS._tony->startStatic, GLOBALS._tony->TALK_WITHRABBITSTATIC);
CORO_END_CODE;
}
void tonyWithRabbitEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_1(GLOBALS._tony->endStatic, GLOBALS._tony->TALK_WITHRABBITSTATIC);
GLOBALS._bStaticTalk = false;
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_NORMAL;
CORO_END_CODE;
}
void tonyWithRecipeStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHRECIPESTATIC;
GLOBALS._bStaticTalk = true;
CORO_INVOKE_1(GLOBALS._tony->startStatic, GLOBALS._tony->TALK_WITHRECIPESTATIC);
CORO_END_CODE;
}
void tonyWithRecipeEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_1(GLOBALS._tony->endStatic, GLOBALS._tony->TALK_WITHRECIPESTATIC);
GLOBALS._bStaticTalk = false;
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_NORMAL;
CORO_END_CODE;
}
void tonyWithCardsStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHCARDSSTATIC;
GLOBALS._bStaticTalk = true;
CORO_INVOKE_1(GLOBALS._tony->startStatic, GLOBALS._tony->TALK_WITHCARDSSTATIC);
CORO_END_CODE;
}
void tonyWithCardsEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_1(GLOBALS._tony->endStatic, GLOBALS._tony->TALK_WITHCARDSSTATIC);
GLOBALS._bStaticTalk = false;
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_NORMAL;
CORO_END_CODE;
}
void tonyWithNotebookStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITH_NOTEBOOK;
GLOBALS._bStaticTalk = true;
CORO_INVOKE_1(GLOBALS._tony->startStatic, GLOBALS._tony->TALK_WITH_NOTEBOOK);
CORO_END_CODE;
}
void tonyWithNotebookEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_1(GLOBALS._tony->endStatic, GLOBALS._tony->TALK_WITH_NOTEBOOK);
GLOBALS._bStaticTalk = false;
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_NORMAL;
CORO_END_CODE;
}
void tonyWithMegaphoneStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHMEGAPHONESTATIC;
GLOBALS._bStaticTalk = true;
CORO_INVOKE_1(GLOBALS._tony->startStatic, GLOBALS._tony->TALK_WITHMEGAPHONESTATIC);
CORO_END_CODE;
}
void tonyWithMegaphoneEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_1(GLOBALS._tony->endStatic, GLOBALS._tony->TALK_WITHMEGAPHONESTATIC);
GLOBALS._bStaticTalk = false;
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_NORMAL;
CORO_END_CODE;
}
void tonyWithBeardStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHBEARDSTATIC;
GLOBALS._bStaticTalk = true;
CORO_INVOKE_1(GLOBALS._tony->startStatic, GLOBALS._tony->TALK_WITHBEARDSTATIC);
CORO_END_CODE;
}
void tonyWithBeardEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_1(GLOBALS._tony->endStatic, GLOBALS._tony->TALK_WITHBEARDSTATIC);
GLOBALS._bStaticTalk = false;
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_NORMAL;
CORO_END_CODE;
}
void tonyScaredStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_SCAREDSTATIC;
GLOBALS._bStaticTalk = true;
CORO_INVOKE_1(GLOBALS._tony->startStatic, GLOBALS._tony->TALK_SCAREDSTATIC);
CORO_END_CODE;
}
void tonyScaredEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_1(GLOBALS._tony->endStatic, GLOBALS._tony->TALK_SCAREDSTATIC);
GLOBALS._bStaticTalk = false;
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_NORMAL;
CORO_END_CODE;
}
void tonyDisgusted(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_DISGUSTED;
}
void tonySniffLeft(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_SNIFF_LEFT);
CORO_INVOKE_0(GLOBALS._tony->waitForEndPattern);
CORO_INVOKE_4(leftToMe, 0, 0, 0, 0);
CORO_END_CODE;
}
void tonySniffRight(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_SNIFF_RIGHT);
CORO_INVOKE_0(GLOBALS._tony->waitForEndPattern);
CORO_INVOKE_4(rightToMe, 0, 0, 0, 0);
CORO_END_CODE;
}
void tonySarcastic(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_SARCASTIC;
}
void tonyMacbeth(CORO_PARAM, uint32 nPos, uint32, uint32, uint32) {
switch (nPos) {
case 1:
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_MACBETH1;
break;
case 2:
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_MACBETH2;
break;
case 3:
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_MACBETH3;
break;
case 4:
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_MACBETH4;
break;
case 5:
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_MACBETH5;
break;
case 6:
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_MACBETH6;
break;
case 7:
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_MACBETH7;
break;
case 8:
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_MACBETH8;
break;
case 9:
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_MACBETH9;
break;
}
}
void enableTony(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._tony->show();
}
void disableTony(CORO_PARAM, uint32 bShowShadow, uint32, uint32, uint32) {
GLOBALS._tony->hide(bShowShadow);
}
void waitForPatternEnd(CORO_PARAM, uint32 nItem, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
RMItem *item;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
_ctx->item = GLOBALS._loc->getItemFromCode(nItem);
if (!GLOBALS._bSkipIdle && _ctx->item != NULL)
CORO_INVOKE_1(_ctx->item->waitForEndPattern, GLOBALS._hSkipIdle);
CORO_END_CODE;
}
void setTonyPosition(CORO_PARAM, uint32 nX, uint32 nY, uint32 nLoc, uint32) {
GLOBALS._tony->setPosition(RMPoint(nX, nY), nLoc);
}
void moveTonyAndWait(CORO_PARAM, uint32 nX, uint32 nY, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
// WORKAROUND: Delay for a frame before starting the move to give any previous move time to finish.
// This fixes a bug in the first scene where if you immediately 'Use Door', Tony moves to the door,
// and then floats to the right rather than properly walking.
CORO_SLEEP(1);
CORO_INVOKE_1(GLOBALS._tony->move, RMPoint(nX, nY));
if (!GLOBALS._bSkipIdle)
CORO_INVOKE_0(GLOBALS._tony->waitForEndMovement);
CORO_END_CODE;
}
void moveTony(CORO_PARAM, uint32 nX, uint32 nY, uint32, uint32) {
GLOBALS._tony->move(coroParam, RMPoint(nX, nY));
}
void scrollLocation(CORO_PARAM, uint32 nX, uint32 nY, uint32 sX, uint32 sY) {
CORO_BEGIN_CONTEXT;
int lx, ly;
RMPoint pt;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
// Take the scroll coordinates
_ctx->lx = (int32)nX;
_ctx->ly = (int32)nY;
_ctx->pt = GLOBALS._loc->scrollPosition();
while ((_ctx->lx != 0 || _ctx->ly != 0) && !GLOBALS._bSkipIdle) {
if (_ctx->lx > 0) {
_ctx->lx -= (int32)sX;
if (_ctx->lx < 0)
_ctx->lx = 0;
_ctx->pt.offset((int32)sX, 0);
} else if (_ctx->lx < 0) {
_ctx->lx += (int32)sX;
if (_ctx->lx > 0)
_ctx->lx = 0;
_ctx->pt.offset(-(int32)sX, 0);
}
if (_ctx->ly > 0) {
_ctx->ly -= sY;
if (_ctx->ly < 0)
_ctx->ly = 0;
_ctx->pt.offset(0, sY);
} else if (_ctx->ly < 0) {
_ctx->ly += sY;
if (_ctx->ly > 0)
_ctx->ly = 0;
_ctx->pt.offset(0, -(int32)sY);
}
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, g_vm->_hEndOfFrame, CORO_INFINITE);
GLOBALS._loc->setScrollPosition(_ctx->pt);
GLOBALS._tony->setScrollPosition(_ctx->pt);
}
CORO_END_CODE;
}
void syncScrollLocation(CORO_PARAM, uint32 nX, uint32 nY, uint32 sX, uint32 sY) {
CORO_BEGIN_CONTEXT;
int lx, ly;
RMPoint pt, startpt;
uint32 dwStartTime, dwCurTime, dwTotalTime;
uint32 stepX, stepY;
int dimx, dimy;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
// Take the scroll coordinates
_ctx->lx = (int32)nX;
_ctx->ly = (int32)nY;
_ctx->dimx = _ctx->lx;
_ctx->dimy = _ctx->ly;
if (_ctx->lx < 0)
_ctx->dimx = -_ctx->lx;
if (_ctx->ly < 0)
_ctx->dimy = -_ctx->ly;
_ctx->stepX = sX;
_ctx->stepY = sY;
_ctx->startpt = GLOBALS._loc->scrollPosition();
_ctx->dwStartTime = g_vm->getTime();
if (sX)
_ctx->dwTotalTime = _ctx->dimx * (1000 / 35) / sX;
else
_ctx->dwTotalTime = _ctx->dimy * (1000 / 35) / sY;
while ((_ctx->lx != 0 || _ctx->ly != 0) && !GLOBALS._bSkipIdle) {
_ctx->dwCurTime = g_vm->getTime() - _ctx->dwStartTime;
if (_ctx->dwCurTime > _ctx->dwTotalTime)
break;
_ctx->pt = _ctx->startpt;
if (sX) {
if (_ctx->lx > 0)
_ctx->pt._x += (_ctx->dimx * _ctx->dwCurTime) / _ctx->dwTotalTime;
else
_ctx->pt._x -= (_ctx->dimx * _ctx->dwCurTime) / _ctx->dwTotalTime;
} else {
if (_ctx->ly > 0)
_ctx->pt._y += (_ctx->dimy * _ctx->dwCurTime) / _ctx->dwTotalTime;
else
_ctx->pt._y -= (_ctx->dimy * _ctx->dwCurTime) / _ctx->dwTotalTime;
}
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, g_vm->_hEndOfFrame, CORO_INFINITE);
GLOBALS._loc->setScrollPosition(_ctx->pt);
GLOBALS._tony->setScrollPosition(_ctx->pt);
}
// Set the position finale
if (sX) {
if (_ctx->lx > 0)
_ctx->pt._x = _ctx->startpt._x + _ctx->dimx;
else
_ctx->pt._x = _ctx->startpt._x - _ctx->dimx;
} else {
if (_ctx->ly > 0)
_ctx->pt._y = _ctx->startpt._y + _ctx->dimy;
else
_ctx->pt._y = _ctx->startpt._y - _ctx->dimy;
}
GLOBALS._loc->setScrollPosition(_ctx->pt);
GLOBALS._tony->setScrollPosition(_ctx->pt);
CORO_END_CODE;
}
void changeHotspot(CORO_PARAM, uint32 dwCode, uint32 nX, uint32 nY, uint32) {
int i;
for (i = 0; i < GLOBALS._curChangedHotspot; i++) {
if (GLOBALS._changedHotspot[i]._dwCode == dwCode) {
GLOBALS._changedHotspot[i]._nX = nX;
GLOBALS._changedHotspot[i]._nY = nY;
break;
}
}
if (i == GLOBALS._curChangedHotspot) {
GLOBALS._changedHotspot[i]._dwCode = dwCode;
GLOBALS._changedHotspot[i]._nX = nX;
GLOBALS._changedHotspot[i]._nY = nY;
GLOBALS._curChangedHotspot++;
}
GLOBALS._loc->getItemFromCode(dwCode)->changeHotspot(RMPoint(nX, nY));
}
void autoSave(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->autoSave(coroParam);
}
void abortGame(CORO_PARAM, uint32, uint32, uint32, uint32) {
debug(1, "script called abortGame");
g_vm->quitGame();
}
void shakeScreen(CORO_PARAM, uint32 nScosse, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
uint32 i;
uint32 curTime;
int dirx, diry;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
_ctx->curTime = g_vm->getTime();
_ctx->dirx = 1;
_ctx->diry = 1;
while (g_vm->getTime() < _ctx->curTime + nScosse) {
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, g_vm->_hEndOfFrame, CORO_INFINITE);
GLOBALS._loc->setFixedScroll(RMPoint(1 * _ctx->dirx, 1 * _ctx->diry));
GLOBALS._tony->setFixedScroll(RMPoint(1 * _ctx->dirx, 1 * _ctx->diry));
_ctx->i = g_vm->_randomSource.getRandomNumber(2);
if (_ctx->i == 0 || _ctx->i == 2)
_ctx->dirx = -_ctx->dirx;
else if (_ctx->i == 1 || _ctx->i == 2)
_ctx->diry = -_ctx->diry;
}
GLOBALS._loc->setFixedScroll(RMPoint(0, 0));
GLOBALS._tony->setFixedScroll(RMPoint(0, 0));
CORO_END_CODE;
}
/*
* Characters
*/
void charSetCode(CORO_PARAM, uint32 nChar, uint32 nCode, uint32, uint32) {
assert(nChar < 16);
GLOBALS._character[nChar]._code = nCode;
GLOBALS._character[nChar]._item = GLOBALS._loc->getItemFromCode(nCode);
GLOBALS._character[nChar]._r = 255;
GLOBALS._character[nChar]._g = 255;
GLOBALS._character[nChar]._b = 255;
GLOBALS._character[nChar]._talkPattern = 0;
GLOBALS._character[nChar]._startTalkPattern = 0;
GLOBALS._character[nChar]._endTalkPattern = 0;
GLOBALS._character[nChar]._standPattern = 0;
GLOBALS._isMChar[nChar] = false;
}
void charSetColor(CORO_PARAM, uint32 nChar, uint32 r, uint32 g, uint32 b) {
assert(nChar < 16);
GLOBALS._character[nChar]._r = r;
GLOBALS._character[nChar]._g = g;
GLOBALS._character[nChar]._b = b;
}
void charSetTalkPattern(CORO_PARAM, uint32 nChar, uint32 tp, uint32 sp, uint32) {
assert(nChar < 16);
GLOBALS._character[nChar]._talkPattern = tp;
GLOBALS._character[nChar]._standPattern = sp;
}
void charSetStartEndTalkPattern(CORO_PARAM, uint32 nChar, uint32 sp, uint32 ep, uint32) {
assert(nChar < 16);
GLOBALS._character[nChar]._startTalkPattern = sp;
GLOBALS._character[nChar]._endTalkPattern = ep;
}
void charSendMessage(CORO_PARAM, uint32 nChar, uint32 dwMessage, uint32 bIsBack, uint32) {
CORO_BEGIN_CONTEXT;
RMMessage *msg;
int i;
RMPoint pt;
RMTextDialog *text;
int curOffset;
VoiceHeader *curVoc;
FPSfx *voice;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
_ctx->msg = new RMMessage(dwMessage);
_ctx->curOffset = 0;
assert(nChar < 16);
_ctx->pt = GLOBALS._character[nChar]._item->calculatePos() - RMPoint(-60, 20) - GLOBALS._loc->scrollPosition();
if (GLOBALS._character[nChar]._startTalkPattern != 0) {
GLOBALS._character[nChar]._item->setPattern(GLOBALS._character[nChar]._startTalkPattern);
CORO_INVOKE_0(GLOBALS._character[nChar]._item->waitForEndPattern);
}
GLOBALS._character[nChar]._item->setPattern(GLOBALS._character[nChar]._talkPattern);
_ctx->curVoc = searchVoiceHeader(0, dwMessage);
_ctx->voice = NULL;
if (_ctx->curVoc) {
// Position within the database of entries, beginning at the first
g_vm->_vdbFP.seek(_ctx->curVoc->_offset);
_ctx->curOffset = _ctx->curVoc->_offset;
}
for (_ctx->i = 0; _ctx->i < _ctx->msg->numPeriods() && !GLOBALS._bSkipIdle; _ctx->i++) {
if (bIsBack) {
GLOBALS._curBackText = _ctx->text = new RMTextDialogScrolling(GLOBALS._loc);
if (GLOBALS._bTonyIsSpeaking)
CORO_INVOKE_0(GLOBALS._curBackText->hide);
} else
_ctx->text = new RMTextDialog;
_ctx->text->setInput(GLOBALS._input);
// Skipping
_ctx->text->setSkipStatus(!bIsBack);
// Alignment
_ctx->text->setAlignType(RMText::HCENTER, RMText::VBOTTOM);
// Color
_ctx->text->setColor(GLOBALS._character[nChar]._r, GLOBALS._character[nChar]._g, GLOBALS._character[nChar]._b);
// Write the text
_ctx->text->writeText((*_ctx->msg)[_ctx->i], 0);
// Set the position
_ctx->text->setPosition(_ctx->pt);
// Set the always display
if (GLOBALS._bAlwaysDisplay) {
_ctx->text->setAlwaysDisplay();
_ctx->text->forceTime();
}
// Record the text
g_vm->getEngine()->linkGraphicTask(_ctx->text);
if (_ctx->curVoc) {
g_vm->_theSound.createSfx(&_ctx->voice);
g_vm->_vdbFP.seek(_ctx->curOffset);
_ctx->voice->loadVoiceFromVDB(g_vm->_vdbFP);
_ctx->voice->setLoop(false);
if (bIsBack)
_ctx->voice->setVolume(55);
_ctx->voice->play();
_ctx->text->setCustomSkipHandle2(_ctx->voice->_hEndOfBuffer);
_ctx->curOffset = g_vm->_vdbFP.pos();
}
// Wait for the end of display
_ctx->text->setCustomSkipHandle(GLOBALS._hSkipIdle);
CORO_INVOKE_0(_ctx->text->waitForEndDisplay);
if (_ctx->curVoc) {
_ctx->voice->stop();
_ctx->voice->release();
_ctx->voice = NULL;
}
GLOBALS._curBackText = NULL;
delete _ctx->text;
}
if (GLOBALS._character[nChar]._endTalkPattern != 0) {
GLOBALS._character[nChar]._item->setPattern(GLOBALS._character[nChar]._endTalkPattern);
CORO_INVOKE_0(GLOBALS._character[nChar]._item->waitForEndPattern);
}
GLOBALS._character[nChar]._item->setPattern(GLOBALS._character[nChar]._standPattern);
delete _ctx->msg;
CORO_END_CODE;
}
void addInventory(CORO_PARAM, uint32 dwCode, uint32, uint32, uint32) {
GLOBALS._inventory->addItem(dwCode);
}
void removeInventory(CORO_PARAM, uint32 dwCode, uint32, uint32, uint32) {
GLOBALS._inventory->removeItem(dwCode);
}
void changeInventoryStatus(CORO_PARAM, uint32 dwCode, uint32 dwStatus, uint32, uint32) {
GLOBALS._inventory->changeItemStatus(dwCode, dwStatus);
}
/*
* Master Characters
*/
void mCharSetCode(CORO_PARAM, uint32 nChar, uint32 nCode, uint32, uint32) {
assert(nChar < 10);
GLOBALS._mCharacter[nChar]._code = nCode;
if (nCode == 0)
GLOBALS._mCharacter[nChar]._item = NULL;
else
GLOBALS._mCharacter[nChar]._item = GLOBALS._loc->getItemFromCode(nCode);
GLOBALS._mCharacter[nChar]._r = 255;
GLOBALS._mCharacter[nChar]._g = 255;
GLOBALS._mCharacter[nChar]._b = 255;
GLOBALS._mCharacter[nChar]._x = -1;
GLOBALS._mCharacter[nChar]._y = -1;
GLOBALS._mCharacter[nChar]._bAlwaysBack = 0;
for (int i = 0; i < 10; i++)
GLOBALS._mCharacter[nChar]._numTalks[i] = 1;
GLOBALS._mCharacter[nChar]._curGroup = 0;
GLOBALS._isMChar[nChar] = true;
}
void mCharResetCode(CORO_PARAM, uint32 nChar, uint32, uint32, uint32) {
GLOBALS._mCharacter[nChar]._item = GLOBALS._loc->getItemFromCode(GLOBALS._mCharacter[nChar]._code);
}
void mCharSetPosition(CORO_PARAM, uint32 nChar, uint32 nX, uint32 nY, uint32) {
assert(nChar < 10);
GLOBALS._mCharacter[nChar]._x = nX;
GLOBALS._mCharacter[nChar]._y = nY;
}
void mCharSetColor(CORO_PARAM, uint32 nChar, uint32 r, uint32 g, uint32 b) {
assert(nChar < 10);
GLOBALS._mCharacter[nChar]._r = r;
GLOBALS._mCharacter[nChar]._g = g;
GLOBALS._mCharacter[nChar]._b = b;
}
void mCharSetNumTalksInGroup(CORO_PARAM, uint32 nChar, uint32 nGroup, uint32 nTalks, uint32) {
assert(nChar < 10);
assert(nGroup < 10);
GLOBALS._mCharacter[nChar]._numTalks[nGroup] = nTalks;
}
void mCharSetCurrentGroup(CORO_PARAM, uint32 nChar, uint32 nGroup, uint32, uint32) {
assert(nChar < 10);
assert(nGroup < 10);
GLOBALS._mCharacter[nChar]._curGroup = nGroup;
}
void mCharSetNumTexts(CORO_PARAM, uint32 nChar, uint32 nTexts, uint32, uint32) {
assert(nChar < 10);
GLOBALS._mCharacter[nChar]._numTexts = nTexts - 1;
GLOBALS._mCharacter[nChar]._bInTexts = false;
}
void mCharSetAlwaysBack(CORO_PARAM, uint32 nChar, uint32 bAlwaysBack, uint32, uint32) {
assert(nChar < 10);
GLOBALS._mCharacter[nChar]._bAlwaysBack = bAlwaysBack;
}
void mCharSendMessage(CORO_PARAM, uint32 nChar, uint32 dwMessage, uint32 bIsBack, uint32 nFont) {
CORO_BEGIN_CONTEXT;
RMMessage *msg;
int i;
int parm;
RMPoint pt;
uint32 h;
RMTextDialog *text;
int curOffset;
VoiceHeader *curVoc;
FPSfx *voice;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
_ctx->msg = new RMMessage(dwMessage);
_ctx->curOffset = 0;
assert(nChar < 10);
bIsBack |= GLOBALS._mCharacter[nChar]._bAlwaysBack ? 1 : 0;
// Calculates the position of the text according to the current frame
if (GLOBALS._mCharacter[nChar]._x == -1)
_ctx->pt = GLOBALS._mCharacter[nChar]._item->calculatePos() - RMPoint(-60, 20) - GLOBALS._loc->scrollPosition();
else
_ctx->pt = RMPoint(GLOBALS._mCharacter[nChar]._x, GLOBALS._mCharacter[nChar]._y);
// Parameter for special actions: random between the spoken
_ctx->parm = (GLOBALS._mCharacter[nChar]._curGroup * 10) + g_vm->_randomSource.getRandomNumber(
GLOBALS._mCharacter[nChar]._numTalks[GLOBALS._mCharacter[nChar]._curGroup] - 1) + 1;
// Try to run the custom function to initialize the speech
if (GLOBALS._mCharacter[nChar]._item) {
_ctx->h = mpalQueryDoAction(30, GLOBALS._mCharacter[nChar]._item->mpalCode(), _ctx->parm);
if (_ctx->h != CORO_INVALID_PID_VALUE) {
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, _ctx->h, CORO_INFINITE);
}
}
_ctx->curVoc = searchVoiceHeader(0, dwMessage);
_ctx->voice = NULL;
if (_ctx->curVoc) {
// Position within the database of entries, beginning at the first
g_vm->_vdbFP.seek(_ctx->curVoc->_offset);
_ctx->curOffset = _ctx->curVoc->_offset;
}
for (_ctx->i = 0; _ctx->i < _ctx->msg->numPeriods() && !GLOBALS._bSkipIdle; _ctx->i++) {
// Create a different object depending on whether it's background or not
if (bIsBack) {
GLOBALS._curBackText = _ctx->text = new RMTextDialogScrolling(GLOBALS._loc);
if (GLOBALS._bTonyIsSpeaking)
CORO_INVOKE_0(GLOBALS._curBackText->hide);
} else
_ctx->text = new RMTextDialog;
_ctx->text->setInput(GLOBALS._input);
// Skipping
_ctx->text->setSkipStatus(!bIsBack);
// Alignment
_ctx->text->setAlignType(RMText::HCENTER, RMText::VBOTTOM);
// Color
_ctx->text->setColor(GLOBALS._mCharacter[nChar]._r, GLOBALS._mCharacter[nChar]._g, GLOBALS._mCharacter[nChar]._b);
// Write the text
_ctx->text->writeText((*_ctx->msg)[_ctx->i], nFont);
// Set the position
_ctx->text->setPosition(_ctx->pt);
// Set the always display
if (GLOBALS._bAlwaysDisplay) {
_ctx->text->setAlwaysDisplay();
_ctx->text->forceTime();
}
// Record the text
g_vm->getEngine()->linkGraphicTask(_ctx->text);
if (_ctx->curVoc) {
g_vm->_theSound.createSfx(&_ctx->voice);
g_vm->_vdbFP.seek(_ctx->curOffset);
_ctx->voice->loadVoiceFromVDB(g_vm->_vdbFP);
_ctx->voice->setLoop(false);
if (bIsBack)
_ctx->voice->setVolume(55);
_ctx->voice->play();
_ctx->text->setCustomSkipHandle2(_ctx->voice->_hEndOfBuffer);
_ctx->curOffset = g_vm->_vdbFP.pos();
}
// Wait for the end of display
_ctx->text->setCustomSkipHandle(GLOBALS._hSkipIdle);
CORO_INVOKE_0(_ctx->text->waitForEndDisplay);
if (_ctx->curVoc) {
_ctx->voice->stop();
_ctx->voice->release();
_ctx->voice = NULL;
}
GLOBALS._curBackText = NULL;
delete _ctx->text;
}
delete _ctx->msg;
// Try to run the custom function to close the speech
if (GLOBALS._mCharacter[nChar]._item) {
_ctx->h = mpalQueryDoAction(31, GLOBALS._mCharacter[nChar]._item->mpalCode(), _ctx->parm);
if (_ctx->h != CORO_INVALID_PID_VALUE)
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, _ctx->h, CORO_INFINITE);
}
CORO_END_CODE;
}
/*
* Dialogs
*/
void sendDialogMessage(CORO_PARAM, uint32 nPers, uint32 nMsg, uint32, uint32) {
CORO_BEGIN_CONTEXT;
char *string;
RMTextDialog *text;
int parm;
uint32 h;
bool bIsBack;
VoiceHeader *curVoc;
FPSfx *voice;
RMPoint pt;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
_ctx->bIsBack = false;
// The SendDialogMessage can go in the background if it is a character
if (nPers != 0 && GLOBALS._isMChar[nPers] && GLOBALS._mCharacter[nPers]._bAlwaysBack)
_ctx->bIsBack = true;
_ctx->curVoc = searchVoiceHeader(GLOBALS._curDialog, nMsg);
_ctx->voice = NULL;
if (_ctx->curVoc) {
// Position within the database of entries, beginning at the first
g_vm->_vdbFP.seek(_ctx->curVoc->_offset);
g_vm->_theSound.createSfx(&_ctx->voice);
_ctx->voice->loadVoiceFromVDB(g_vm->_vdbFP);
_ctx->voice->setLoop(false);
if (_ctx->bIsBack)
_ctx->voice->setVolume(55);
}
_ctx->string = mpalQueryDialogPeriod(nMsg);
if (nPers == 0) {
_ctx->text = new RMTextDialog;
_ctx->text->setColor(0, 255, 0);
_ctx->text->setPosition(GLOBALS._tony->position() - RMPoint(0, 130) - GLOBALS._loc->scrollPosition());
_ctx->text->writeText(_ctx->string, 0);
if (GLOBALS._dwTonyNumTexts > 0) {
if (!GLOBALS._bTonyInTexts) {
if (GLOBALS._nTonyNextTalkType != GLOBALS._tony->TALK_NORMAL) {
CORO_INVOKE_1(GLOBALS._tony->startTalk, GLOBALS._nTonyNextTalkType);
if (!GLOBALS._bStaticTalk)
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_NORMAL;
} else
CORO_INVOKE_1(GLOBALS._tony->startTalk, GLOBALS._tony->TALK_NORMAL);
GLOBALS._bTonyInTexts = true;
}
GLOBALS._dwTonyNumTexts--;
} else {
CORO_INVOKE_1(GLOBALS._tony->startTalk, GLOBALS._nTonyNextTalkType);
if (!GLOBALS._bStaticTalk)
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_NORMAL;
}
} else if (!GLOBALS._isMChar[nPers]) {
_ctx->text = new RMTextDialog;
_ctx->pt = GLOBALS._character[nPers]._item->calculatePos() - RMPoint(-60, 20) - GLOBALS._loc->scrollPosition();
if (GLOBALS._character[nPers]._startTalkPattern != 0) {
GLOBALS._character[nPers]._item->setPattern(GLOBALS._character[nPers]._startTalkPattern);
CORO_INVOKE_0(GLOBALS._character[nPers]._item->waitForEndPattern);
}
GLOBALS._character[nPers]._item->setPattern(GLOBALS._character[nPers]._talkPattern);
_ctx->text->setColor(GLOBALS._character[nPers]._r, GLOBALS._character[nPers]._g, GLOBALS._character[nPers]._b);
_ctx->text->writeText(_ctx->string, 0);
_ctx->text->setPosition(_ctx->pt);
} else {
if (GLOBALS._mCharacter[nPers]._x == -1)
_ctx->pt = GLOBALS._mCharacter[nPers]._item->calculatePos() - RMPoint(-60, 20) - GLOBALS._loc->scrollPosition();
else
_ctx->pt = RMPoint(GLOBALS._mCharacter[nPers]._x, GLOBALS._mCharacter[nPers]._y);
// Parameter for special actions. Random between the spoken.
_ctx->parm = (GLOBALS._mCharacter[nPers]._curGroup * 10) + g_vm->_randomSource.getRandomNumber(
GLOBALS._mCharacter[nPers]._numTalks[GLOBALS._mCharacter[nPers]._curGroup] - 1) + 1;
if (GLOBALS._mCharacter[nPers]._numTexts != 0 && GLOBALS._mCharacter[nPers]._bInTexts) {
GLOBALS._mCharacter[nPers]._numTexts--;
} else {
// Try to run the custom function to initialize the speech
_ctx->h = mpalQueryDoAction(30, GLOBALS._mCharacter[nPers]._item->mpalCode(), _ctx->parm);
if (_ctx->h != CORO_INVALID_PID_VALUE)
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, _ctx->h, CORO_INFINITE);
GLOBALS._mCharacter[nPers]._curTalk = _ctx->parm;
if (GLOBALS._mCharacter[nPers]._numTexts != 0) {
GLOBALS._mCharacter[nPers]._bInTexts = true;
GLOBALS._mCharacter[nPers]._numTexts--;
}
}
if (GLOBALS._mCharacter[nPers]._bAlwaysBack) {
_ctx->text = GLOBALS._curBackText = new RMTextDialogScrolling(GLOBALS._loc);
if (GLOBALS._bTonyIsSpeaking)
CORO_INVOKE_0(GLOBALS._curBackText->hide);
_ctx->bIsBack = true;
} else
_ctx->text = new RMTextDialog;
_ctx->text->setSkipStatus(!GLOBALS._mCharacter[nPers]._bAlwaysBack);
_ctx->text->setColor(GLOBALS._mCharacter[nPers]._r, GLOBALS._mCharacter[nPers]._g, GLOBALS._mCharacter[nPers]._b);
_ctx->text->writeText(_ctx->string, 0);
_ctx->text->setPosition(_ctx->pt);
}
if (!GLOBALS._bSkipIdle) {
_ctx->text->setInput(GLOBALS._input);
if (GLOBALS._bAlwaysDisplay) {
_ctx->text->setAlwaysDisplay();
_ctx->text->forceTime();
}
_ctx->text->setAlignType(RMText::HCENTER, RMText::VBOTTOM);
g_vm->getEngine()->linkGraphicTask(_ctx->text);
if (_ctx->curVoc) {
_ctx->voice->play();
_ctx->text->setCustomSkipHandle2(_ctx->voice->_hEndOfBuffer);
}
// Wait for the end of display
_ctx->text->setCustomSkipHandle(GLOBALS._hSkipIdle);
CORO_INVOKE_0(_ctx->text->waitForEndDisplay);
}
if (_ctx->curVoc) {
_ctx->voice->stop();
_ctx->voice->release();
_ctx->voice = NULL;
}
if (nPers != 0) {
if (!GLOBALS._isMChar[nPers]) {
if (GLOBALS._character[nPers]._endTalkPattern != 0) {
GLOBALS._character[nPers]._item->setPattern(GLOBALS._character[nPers]._endTalkPattern);
CORO_INVOKE_0(GLOBALS._character[nPers]._item->waitForEndPattern);
}
GLOBALS._character[nPers]._item->setPattern(GLOBALS._character[nPers]._standPattern);
delete _ctx->text;
} else {
if ((GLOBALS._mCharacter[nPers]._bInTexts && GLOBALS._mCharacter[nPers]._numTexts == 0) || !GLOBALS._mCharacter[nPers]._bInTexts) {
// Try to run the custom function to close the speech
GLOBALS._mCharacter[nPers]._curTalk = (GLOBALS._mCharacter[nPers]._curTalk % 10) + GLOBALS._mCharacter[nPers]._curGroup * 10;
_ctx->h = mpalQueryDoAction(31, GLOBALS._mCharacter[nPers]._item->mpalCode(), GLOBALS._mCharacter[nPers]._curTalk);
if (_ctx->h != CORO_INVALID_PID_VALUE)
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, _ctx->h, CORO_INFINITE);
GLOBALS._mCharacter[nPers]._bInTexts = false;
GLOBALS._mCharacter[nPers]._numTexts = 0;
}
GLOBALS._curBackText = NULL;
delete _ctx->text;
}
} else {
if ((GLOBALS._dwTonyNumTexts == 0 && GLOBALS._bTonyInTexts) || !GLOBALS._bTonyInTexts) {
CORO_INVOKE_0(GLOBALS._tony->endTalk);
GLOBALS._dwTonyNumTexts = 0;
GLOBALS._bTonyInTexts = false;
}
delete _ctx->text;
}
globalDestroy(_ctx->string);
CORO_END_CODE;
}
// @@@@ This cannot be skipped!!!!!!!!!!!!!!!!!!!
void startDialog(CORO_PARAM, uint32 nDialog, uint32 nStartGroup, uint32, uint32) {
CORO_BEGIN_CONTEXT;
uint32 nChoice;
uint32 *sl;
uint32 i, num;
char *string;
RMDialogChoice dc;
int sel;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
GLOBALS._curDialog = nDialog;
// Call MPAL to start the dialog
mpalQueryDoDialog(nDialog, nStartGroup);
// Wait until a choice is selected
mpalQueryDialogWaitForChoice(&_ctx->nChoice);
while (_ctx->nChoice != (uint32) - 1) {
// Get the list of options
_ctx->sl = mpalQueryDialogSelectList(_ctx->nChoice);
for (_ctx->num = 0; _ctx->sl[_ctx->num] != 0; _ctx->num++)
;
// If there is only one option, do it automatically, and wait for the next choice
if (_ctx->num == 1) {
mpalQueryDialogSelectionDWORD(_ctx->nChoice, _ctx->sl[0]);
globalDestroy(_ctx->sl);
// Wait for the next choice to be made
mpalQueryDialogWaitForChoice(&_ctx->nChoice);
continue;
}
// Making a choice for dialog
_ctx->dc.init();
_ctx->dc.setNumChoices(_ctx->num);
// Writeall the possible options
for (_ctx->i = 0; _ctx->i < _ctx->num; _ctx->i++) {
_ctx->string = mpalQueryDialogPeriod(_ctx->sl[_ctx->i]);
assert(_ctx->string != NULL);
_ctx->dc.addChoice(_ctx->string);
globalDestroy(_ctx->string);
}
// Activate the object
g_vm->getEngine()->linkGraphicTask(&_ctx->dc);
CORO_INVOKE_0(_ctx->dc.show);
// Draw the pointer
GLOBALS._pointer->setSpecialPointer(GLOBALS._pointer->PTR_NONE);
g_vm->getEngine()->enableMouse();
while (!(GLOBALS._input->mouseLeftClicked() && ((_ctx->sel = _ctx->dc.getSelection()) != -1))) {
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, g_vm->_hEndOfFrame, CORO_INFINITE);
CORO_INVOKE_1(_ctx->dc.doFrame, GLOBALS._input->mousePos());
}
// Hide the pointer
g_vm->getEngine()->disableMouse();
CORO_INVOKE_0(_ctx->dc.hide);
mpalQueryDialogSelectionDWORD(_ctx->nChoice, _ctx->sl[_ctx->sel]);
// Closes the choice
_ctx->dc.close();
globalDestroy(_ctx->sl);
// Wait for the next choice to be made
mpalQueryDialogWaitForChoice(&_ctx->nChoice);
}
CORO_END_CODE;
}
/*
* Sync between idle and mpal
*/
void takeOwnership(CORO_PARAM, uint32 num, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
if (GLOBALS._mut[num]._ownerPid != (uint32)CoroScheduler.getCurrentPID()) {
// The mutex is currently owned by a different process.
// Wait for the event to be signalled, which means the mutex is free.
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, GLOBALS._mut[num]._eventId, CORO_INFINITE);
GLOBALS._mut[num]._ownerPid = (uint32)CoroScheduler.getCurrentPID();
}
GLOBALS._mut[num]._lockCount++;
CORO_END_CODE;
}
void releaseOwnership(CORO_PARAM, uint32 num, uint32, uint32, uint32) {
if (!GLOBALS._mut[num]._lockCount) {
warning("ReleaseOwnership tried to release mutex %d, which isn't held", num);
return;
}
if (GLOBALS._mut[num]._ownerPid != (uint32)CoroScheduler.getCurrentPID()) {
warning("ReleaseOwnership tried to release mutex %d, which is held by a different process", num);
return;
}
GLOBALS._mut[num]._lockCount--;
if (!GLOBALS._mut[num]._lockCount) {
GLOBALS._mut[num]._ownerPid = 0;
// Signal the event, to wake up processes waiting for the lock.
CoroScheduler.setEvent(GLOBALS._mut[num]._eventId);
}
}
/*
* Music
* -----
*
* Fadeout effects supposed:
*
* nFX = 0 - The new music replaces the old one
* nFX=1 - The new music interfades with the old one
* nFX=2 - The new music takes over in time from the old
*
*/
void threadFadeInMusic(CORO_PARAM, const void *nMusic) {
CORO_BEGIN_CONTEXT;
int i;
CORO_END_CONTEXT(_ctx);
int nChannel = *(const int *)nMusic;
CORO_BEGIN_CODE(_ctx);
debugC(DEBUG_INTERMEDIATE, kTonyDebugSound, "Start FadeIn Music");
for (_ctx->i = 0; _ctx->i < 16; _ctx->i++) {
g_vm->setMusicVolume(nChannel, _ctx->i * 4);
CORO_INVOKE_1(CoroScheduler.sleep, 100);
}
g_vm->setMusicVolume(nChannel, 64);
debugC(DEBUG_INTERMEDIATE, kTonyDebugSound, "End FadeIn Music");
CORO_KILL_SELF();
CORO_END_CODE;
}
void threadFadeOutMusic(CORO_PARAM, const void *nMusic) {
CORO_BEGIN_CONTEXT;
int i;
int startVolume;
CORO_END_CONTEXT(_ctx);
int nChannel = *(const int *)nMusic;
CORO_BEGIN_CODE(_ctx);
_ctx->startVolume = g_vm->getMusicVolume(nChannel);
for (_ctx->i = 16; _ctx->i > 0 && !GLOBALS._bFadeOutStop; _ctx->i--) {
if (_ctx->i * 4 < _ctx->startVolume)
g_vm->setMusicVolume(nChannel, _ctx->i * 4);
CORO_INVOKE_1(CoroScheduler.sleep, 100);
}
if (!GLOBALS._bFadeOutStop)
g_vm->setMusicVolume(nChannel, 0);
// If a jingle is played, stop it
if (nChannel == 2)
g_vm->stopMusic(2);
CORO_KILL_SELF();
CORO_END_CODE;
}
void fadeInSoundEffect(CORO_PARAM, uint32, uint32, uint32, uint32) {
CoroScheduler.createProcess(threadFadeInMusic, &GLOBALS._curSoundEffect, sizeof(int));
}
void fadeOutSoundEffect(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._bFadeOutStop = false;
CoroScheduler.createProcess(threadFadeOutMusic, &GLOBALS._curSoundEffect, sizeof(int));
}
void fadeOutJingle(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._bFadeOutStop = false;
int channel = 2;
CoroScheduler.createProcess(threadFadeOutMusic, &channel, sizeof(int));
}
void fadeInJingle(CORO_PARAM, uint32, uint32, uint32, uint32) {
int channel = 2;
CoroScheduler.createProcess(threadFadeInMusic, &channel, sizeof(int));
}
void stopSoundEffect(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->stopMusic(GLOBALS._curSoundEffect);
}
void stopJingle(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->stopMusic(2);
}
void muteSoundEffect(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->setMusicVolume(GLOBALS._curSoundEffect, 0);
}
void demuteSoundEffect(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._bFadeOutStop = true;
g_vm->setMusicVolume(GLOBALS._curSoundEffect, 64);
}
void muteJingle(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->setMusicVolume(2, 0);
}
void demuteJingle(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->setMusicVolume(2, 64);
}
void custPlayMusic(uint32 nChannel, const char *mFN, uint32 nFX, bool bLoop, int nSync = 0) {
if (nSync == 0)
nSync = 2000;
debugC(DEBUG_INTERMEDIATE, kTonyDebugMusic, "Start CustPlayMusic");
g_vm->playMusic(nChannel, mFN, nFX, bLoop, nSync);
debugC(DEBUG_INTERMEDIATE, kTonyDebugMusic, "End CustPlayMusic");
}
void playSoundEffect(CORO_PARAM, uint32 nMusic, uint32 nFX, uint32 bNoLoop, uint32) {
if (nFX == 0 || nFX == 1 || nFX == 2) {
debugC(DEBUG_INTERMEDIATE, kTonyDebugSound, "PlaySoundEffect stop fadeout");
GLOBALS._bFadeOutStop = true;
}
GLOBALS._lastMusic = nMusic;
custPlayMusic(GLOBALS._curSoundEffect, kMusicFiles[nMusic]._name, nFX, bNoLoop ? false : true, kMusicFiles[nMusic]._sync);
}
void playJingle(CORO_PARAM, uint32 nMusic, uint32 nFX, uint32 bLoop, uint32) {
custPlayMusic(2, kJingleFileNames[nMusic], nFX, bLoop);
}
void playItemSfx(CORO_PARAM, uint32 nItem, uint32 nSFX, uint32, uint32) {
if (nItem == 0) {
GLOBALS._tony->playSfx(nSFX);
} else {
RMItem *item = GLOBALS._loc->getItemFromCode(nItem);
if (item)
item->playSfx(nSFX);
}
}
void restoreMusic(CORO_PARAM) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_4(playSoundEffect, GLOBALS._lastMusic, 0, 0, 0);
if (GLOBALS._lastTappeto != 0)
custPlayMusic(4, kAmbianceFile[GLOBALS._lastTappeto], 0, true);
CORO_END_CODE;
}
void saveMusic(Common::OutSaveFile *f) {
f->writeByte(GLOBALS._lastMusic);
f->writeByte(GLOBALS._lastTappeto);
}
void loadMusic(Common::InSaveFile *f) {
GLOBALS._lastMusic = f->readByte();
GLOBALS._lastTappeto = f->readByte();
}
void jingleFadeStart(CORO_PARAM, uint32 nJingle, uint32 bLoop, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_4(fadeOutSoundEffect, 0, 0, 0, 0);
CORO_INVOKE_4(muteJingle, 0, 0, 0, 0);
CORO_INVOKE_4(playJingle, nJingle, 0, bLoop, 0);
CORO_INVOKE_4(fadeInJingle, 0, 0, 0, 0);
CORO_END_CODE;
}
void jingleFadeEnd(CORO_PARAM, uint32 nJingle, uint32 bLoop, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_4(fadeOutJingle, 0, 0, 0, 0);
CORO_INVOKE_4(fadeInSoundEffect, 0, 0, 0, 0);
CORO_END_CODE;
}
void mustSkipIdleStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._bSkipIdle = true;
CoroScheduler.setEvent(GLOBALS._hSkipIdle);
}
void mustSkipIdleEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._bSkipIdle = false;
CoroScheduler.resetEvent(GLOBALS._hSkipIdle);
}
void patIrqFreeze(CORO_PARAM, uint32 bStatus, uint32, uint32, uint32) {
// Unused in ScummVM.
}
void openInitLoadMenu(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_0(g_vm->openInitLoadMenu);
CORO_END_CODE;
}
void openInitOptions(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_0(g_vm->openInitOptions);
CORO_END_CODE;
}
void doCredits(CORO_PARAM, uint32 nMsg, uint32 dwTime, uint32, uint32) {
CORO_BEGIN_CONTEXT;
RMMessage *msg;
RMTextDialog *text;
uint32 hDisable;
int i;
uint32 startTime;
~CoroContextTag() {
delete msg;
delete[] text;
}
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
_ctx->msg = new RMMessage(nMsg);
_ctx->hDisable = CoroScheduler.createEvent(true, false);
_ctx->text = new RMTextDialog[_ctx->msg->numPeriods()];
for (_ctx->i = 0; _ctx->i < _ctx->msg->numPeriods(); _ctx->i++) {
_ctx->text[_ctx->i].setInput(GLOBALS._input);
// Alignment
if ((*_ctx->msg)[_ctx->i][0] == '@') {
_ctx->text[_ctx->i].setAlignType(RMText::HCENTER, RMText::VTOP);
_ctx->text[_ctx->i].writeText(&(*_ctx->msg)[_ctx->i][1], 3);
_ctx->text[_ctx->i].setPosition(RMPoint(414, 70 + _ctx->i * 26)); // 70
} else {
_ctx->text[_ctx->i].setAlignType(RMText::HLEFT, RMText::VTOP);
_ctx->text[_ctx->i].writeText((*_ctx->msg)[_ctx->i], 3);
_ctx->text[_ctx->i].setPosition(RMPoint(260, 70 + _ctx->i * 26));
}
// Set the position
_ctx->text[_ctx->i].setAlwaysDisplay();
_ctx->text[_ctx->i].setForcedTime(dwTime * 1000);
_ctx->text[_ctx->i].setNoTab();
// Wait for the end of display
_ctx->text[_ctx->i].setCustomSkipHandle(_ctx->hDisable);
// Record the text
g_vm->getEngine()->linkGraphicTask(&_ctx->text[_ctx->i]);
}
_ctx->startTime = g_vm->getTime();
while (_ctx->startTime + dwTime * 1000 > g_vm->getTime()) {
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, g_vm->_hEndOfFrame, CORO_INFINITE);
if (GLOBALS._input->mouseLeftClicked() || GLOBALS._input->mouseRightClicked())
break;
if (g_vm->getEngine()->getInput().getAsyncKeyState(Common::KEYCODE_TAB))
break;
}
CoroScheduler.setEvent(_ctx->hDisable);
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, g_vm->_hEndOfFrame, CORO_INFINITE);
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, g_vm->_hEndOfFrame, CORO_INFINITE);
delete[] _ctx->text;
delete _ctx->msg;
_ctx->text = NULL;
_ctx->msg = NULL;
CORO_END_CODE;
}
BEGIN_CUSTOM_FUNCTION_MAP()
ASSIGN(1, custLoadLocation)
ASSIGN(2, mySleep)
ASSIGN(3, setPointer)
ASSIGN(5, moveTony)
ASSIGN(6, faceToMe)
ASSIGN(7, backToMe)
ASSIGN(8, leftToMe)
ASSIGN(9, rightToMe)
ASSIGN(10, sendTonyMessage)
ASSIGN(11, changeBoxStatus)
ASSIGN(12, changeLocation)
ASSIGN(13, disableTony)
ASSIGN(14, enableTony)
ASSIGN(15, waitForPatternEnd)
ASSIGN(16, setLocStartPosition)
ASSIGN(17, scrollLocation)
ASSIGN(18, moveTonyAndWait)
ASSIGN(19, changeHotspot)
ASSIGN(20, addInventory)
ASSIGN(21, removeInventory)
ASSIGN(22, changeInventoryStatus)
ASSIGN(23, setTonyPosition)
ASSIGN(24, sendFullscreenMessage)
ASSIGN(25, saveTonyPosition)
ASSIGN(26, restoreTonyPosition)
ASSIGN(27, disableInput)
ASSIGN(28, enableInput)
ASSIGN(29, stopTony)
ASSIGN(30, tonyTakeUp1)
ASSIGN(31, tonyTakeMid1)
ASSIGN(32, tonyTakeDown1)
ASSIGN(33, tonyTakeUp2)
ASSIGN(34, tonyTakeMid2)
ASSIGN(35, tonyTakeDown2)
ASSIGN(72, tonyPutUp1)
ASSIGN(73, tonyPutMid1)
ASSIGN(74, tonyPutDown1)
ASSIGN(75, tonyPutUp2)
ASSIGN(76, tonyPutMid2)
ASSIGN(77, tonyPutDown2)
ASSIGN(36, tonyOnTheFloor)
ASSIGN(37, tonyGetUp)
ASSIGN(38, tonyShepherdess)
ASSIGN(39, tonyWhistle)
ASSIGN(40, tonyLaugh)
ASSIGN(41, tonyHips)
ASSIGN(42, tonySing)
ASSIGN(43, tonyIndicate)
ASSIGN(44, tonyScaredWithHands)
ASSIGN(49, tonyScaredWithoutHands)
ASSIGN(45, tonyWithGlasses)
ASSIGN(46, tonyWithWorm)
ASSIGN(47, tonyWithHammer)
ASSIGN(48, tonyWithRope)
ASSIGN(90, tonyWithRabbitANIM)
ASSIGN(91, tonyWithRecipeANIM)
ASSIGN(92, tonyWithCardsANIM)
ASSIGN(93, tonyWithSnowmanANIM)
ASSIGN(94, tonyWithSnowmanStart)
ASSIGN(95, tonyWithSnowmanEnd)
ASSIGN(96, tonyWithRabbitStart)
ASSIGN(97, tonyWithRabbitEnd)
ASSIGN(98, tonyWithRecipeStart)
ASSIGN(99, tonyWithRecipeEnd)
ASSIGN(100, tonyWithCardsStart)
ASSIGN(101, tonyWithCardsEnd)
ASSIGN(102, tonyWithNotebookStart)
ASSIGN(103, tonyWithNotebookEnd)
ASSIGN(104, tonyWithMegaphoneStart)
ASSIGN(105, tonyWithMegaphoneEnd)
ASSIGN(106, tonyWithBeardStart)
ASSIGN(107, tonyWithBeardEnd)
ASSIGN(108, tonyGiggle)
ASSIGN(109, tonyDisgusted)
ASSIGN(110, tonySarcastic)
ASSIGN(111, tonyMacbeth)
ASSIGN(112, tonySniffLeft)
ASSIGN(113, tonySniffRight)
ASSIGN(114, tonyScaredStart)
ASSIGN(115, tonyScaredEnd)
ASSIGN(116, tonyWithSecretary)
ASSIGN(50, charSetCode)
ASSIGN(51, charSetColor)
ASSIGN(52, charSetTalkPattern)
ASSIGN(53, charSendMessage)
ASSIGN(54, charSetStartEndTalkPattern)
ASSIGN(60, mCharSetCode)
ASSIGN(61, mCharSetColor)
ASSIGN(62, mCharSetCurrentGroup)
ASSIGN(63, mCharSetNumTalksInGroup)
ASSIGN(64, mCharSetNumTexts)
ASSIGN(65, mCharSendMessage)
ASSIGN(66, mCharSetPosition)
ASSIGN(67, mCharSetAlwaysBack)
ASSIGN(68, mCharResetCode)
ASSIGN(70, startDialog)
ASSIGN(71, sendDialogMessage)
ASSIGN(80, takeOwnership)
ASSIGN(81, releaseOwnership)
ASSIGN(86, playSoundEffect)
ASSIGN(87, playJingle)
ASSIGN(88, fadeInSoundEffect)
ASSIGN(89, fadeOutSoundEffect)
ASSIGN(123, fadeInJingle)
ASSIGN(124, fadeOutJingle)
ASSIGN(125, muteSoundEffect)
ASSIGN(126, demuteSoundEffect)
ASSIGN(127, muteJingle)
ASSIGN(128, demuteJingle)
ASSIGN(84, stopSoundEffect)
ASSIGN(85, stopJingle)
ASSIGN(83, playItemSfx)
ASSIGN(129, jingleFadeStart)
ASSIGN(130, jingleFadeEnd)
ASSIGN(120, shakeScreen)
ASSIGN(121, autoSave)
ASSIGN(122, abortGame)
ASSIGN(131, noBullsEye)
ASSIGN(132, sendFullscreenMsgStart)
ASSIGN(133, sendFullscreenMsgEnd)
ASSIGN(134, custEnableGUI)
ASSIGN(135, custDisableGUI)
ASSIGN(136, clearScreen)
ASSIGN(137, patIrqFreeze)
ASSIGN(138, tonySetPerorate)
ASSIGN(139, openInitLoadMenu)
ASSIGN(140, openInitOptions)
ASSIGN(141, syncScrollLocation)
ASSIGN(142, closeLocation)
ASSIGN(143, setAlwaysDisplay)
ASSIGN(144, doCredits)
ASSIGN(200, mustSkipIdleStart);
ASSIGN(201, mustSkipIdleEnd);
END_CUSTOM_FUNCTION_MAP()
void processKilledCallback(Common::PROCESS *p) {
for (uint i = 0; i < 10; i++) {
if (GLOBALS._mut[i]._ownerPid == p->pid) {
// Handle scripts which don't call ReleaseOwnership, such as
// the one in loc37's vEnter when Tony is chasing the mouse.
debug(DEBUG_BASIC, "Force-releasing mutex %d after process died", i);
GLOBALS._mut[i]._ownerPid = 0;
GLOBALS._mut[i]._lockCount = 0;
CoroScheduler.setEvent(GLOBALS._mut[i]._eventId);
}
}
}
void setupGlobalVars(RMTony *tony, RMPointer *ptr, RMGameBoxes *box, RMLocation *loc, RMInventory *inv, RMInput *input) {
GLOBALS._tony = tony;
GLOBALS._pointer = ptr;
GLOBALS._boxes = box;
GLOBALS._loc = loc;
GLOBALS._inventory = inv;
GLOBALS._input = input;
GLOBALS.DisableGUI = mainDisableGUI;
GLOBALS.EnableGUI = mainEnableGUI;
GLOBALS._bAlwaysDisplay = false;
CoroScheduler.setResourceCallback(processKilledCallback);
for (int i = 0; i < 10; i++)
GLOBALS._mut[i]._eventId = CoroScheduler.createEvent(false, true);
for (int i = 0; i < 200; i++)
GLOBALS._ambiance[i] = 0;
GLOBALS._ambiance[6] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[7] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[8] = AMBIANCE_CRICKETSMUFFLED;
GLOBALS._ambiance[10] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[12] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[13] = AMBIANCE_CRICKETSMUFFLED;
GLOBALS._ambiance[15] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[16] = AMBIANCE_CRICKETSWIND;
GLOBALS._ambiance[18] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[19] = AMBIANCE_CRICKETSWIND;
GLOBALS._ambiance[20] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[23] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[26] = AMBIANCE_SEAHALFVOLUME;
GLOBALS._ambiance[27] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[28] = AMBIANCE_CRICKETSWIND;
GLOBALS._ambiance[31] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[33] = AMBIANCE_SEA;
GLOBALS._ambiance[35] = AMBIANCE_SEA;
GLOBALS._ambiance[36] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[37] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[40] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[41] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[42] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[45] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[51] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[52] = AMBIANCE_CRICKETSWIND1;
GLOBALS._ambiance[53] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[54] = AMBIANCE_CRICKETS;
GLOBALS._ambiance[57] = AMBIANCE_WIND;
GLOBALS._ambiance[58] = AMBIANCE_WIND;
GLOBALS._ambiance[60] = AMBIANCE_WIND;
// Create an event for the idle skipping
GLOBALS._hSkipIdle = CoroScheduler.createEvent(true, false);
}
} // end of namespace Tony