/* 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. * */ #include "common/debug.h" #include "common/system.h" #include "toon/character.h" #include "toon/drew.h" #include "toon/flux.h" #include "toon/path.h" namespace Toon { Character::Character(ToonEngine *vm) : _vm(vm) { _animationInstance = NULL; _shadowAnimationInstance = NULL; _x = 0; _y = 0; _z = 0; _finalX = 0; _finalY = 0; _sceneAnimationId = -1; _walkAnim = NULL; _idleAnim = NULL; _talkAnim = NULL; _shadowAnim = NULL; _specialAnim = NULL; _facing = 0; _flags = 0; _animFlags = 0; _isTalking = false; _id = 0; _scale = 1024; _blockingWalk = false; _animScriptId = -1; _animSpecialId = -1; _animSpecialDefaultId = 0; _currentPathNode = 0; _currentWalkStamp = 0; _currentFacingStamp = 0; _visible = true; _speed = 150; // 150 = nominal drew speed _lastWalkTime = 0; _numPixelToWalk = 0; _nextIdleTime = _vm->_system->getMillis() + (_vm->randRange(0, 600) + 300) * _vm->getTickLength(); _lineToSayId = 0; _time = 0; } Character::~Character(void) { delete _animationInstance; delete _shadowAnimationInstance; delete _walkAnim; delete _idleAnim; delete _talkAnim; delete _shadowAnim; delete _specialAnim; } void Character::init() { } void Character::forceFacing(int32 facing) { debugC(4, kDebugCharacter, "forceFacing(%d)", facing); _facing = facing; } void Character::setFacing(int32 facing) { debugC(4, kDebugCharacter, "setFacing(%d)", facing); if (facing == _facing) return; if (!_visible) { _facing = facing; return; } if (_blockingWalk) { _flags |= 2; _currentFacingStamp++; int32 localFacingStamp = _currentFacingStamp; int32 dir = 0; _lastWalkTime = _vm->_system->getMillis(); if ((_facing - facing + 8) % 8 > (facing - _facing + 8) % 8) dir = 1; else dir = -1; while (_facing != facing) { int32 elapsedTime = _vm->getOldMilli() - _lastWalkTime; while (elapsedTime > _vm->getTickLength() * 3 && _facing != facing) { _facing += dir; while (_facing >= 8) _facing -= 8; while (_facing < 0) _facing += 8; elapsedTime -= _vm->getTickLength() * 3; _lastWalkTime = _vm->getOldMilli(); } if (_currentPathNode == 0) playStandingAnim(); else playWalkAnim(0, 0); _vm->doFrame(); if (_currentFacingStamp != localFacingStamp) { // another setFacing was started in doFrame, we need to cancel this one. return; } }; _flags &= ~2; } _facing = facing; } void Character::forcePosition(int16 x, int16 y) { debugC(5, kDebugCharacter, "forcePosition(%d, %d)", x, y); setPosition(x, y); _finalX = x; _finalY = y; } void Character::setPosition(int16 x, int16 y) { debugC(5, kDebugCharacter, "setPosition(%d, %d)", x, y); _x = x; _y = y; if (_animationInstance) _animationInstance->setPosition(_x, _y, _z); return; } bool Character::walkTo(int16 newPosX, int16 newPosY) { debugC(1, kDebugCharacter, "walkTo(%d, %d)", newPosX, newPosY); if (!_visible) return true; if (_x == newPosX && _y == newPosY) return true; _vm->getPathFinding()->resetBlockingRects(); // don't allow flux to go at the same position as drew if (_id == 1) { int16 sizeX = MAX(5, 30 * _vm->getDrew()->getScale() / 1024); int16 sizeY = MAX(2, 20 * _vm->getDrew()->getScale() / 1024); _vm->getPathFinding()->addBlockingEllipse(_vm->getDrew()->getFinalX(), _vm->getDrew()->getFinalY(), sizeX, sizeY); } _vm->getPathFinding()->findClosestWalkingPoint(newPosX, newPosY, &_finalX, &_finalY, _x, _y); if (_x == _finalX && _y == _finalY) return true; if (_vm->getPathFinding()->findPath(_x, _y, _finalX, _finalY)) { int16 localFinalX = _finalX; int16 localFinalY = _finalY; int32 smoothDx = 0; int32 smoothDy = 0; _currentPath.clear(); for (uint32 a = 0; a < _vm->getPathFinding()->getPathNodeCount(); a++) _currentPath.push_back(Common::Point(_vm->getPathFinding()->getPathNodeX(a), _vm->getPathFinding()->getPathNodeY(a))); _currentPathNode = 0; stopSpecialAnim(); _lastWalkTime = _vm->_system->getMillis(); _numPixelToWalk = 0; _flags |= 0x1; _currentWalkStamp++; int32 localWalkStamp = _currentWalkStamp; if (_blockingWalk) { while ((_x != newPosX || _y != newPosY) && _currentPathNode < _currentPath.size() && !_vm->shouldQuitGame()) { if (_currentPathNode < _currentPath.size() - 4) { int32 delta = MIN(4, _currentPath.size() - 1 - _currentPathNode); int16 dx = _currentPath[_currentPathNode+delta].x - _x; int16 dy = _currentPath[_currentPathNode+delta].y - _y; // smooth the facing computation. It prevents some ugly flickering from happening if (!smoothDx && !smoothDy) { smoothDx = dx; smoothDy = dy; } else { smoothDx = (dx + smoothDx * 3) / 4; smoothDy = (dy + smoothDy * 3) / 4; } setFacing(getFacingFromDirection(smoothDx, smoothDy)); if (_currentWalkStamp != localWalkStamp) { // another walkTo was started in setFacing, we need to cancel this one. return false; } playWalkAnim(0, 0); } // in 1/1000 pixels _numPixelToWalk += _speed * (_vm->_system->getMillis() - _lastWalkTime) * _scale / 1024; _lastWalkTime = _vm->_system->getMillis(); while (_numPixelToWalk >= 1000 && _currentPathNode < _currentPath.size()) { _x = _currentPath[_currentPathNode].x; _y = _currentPath[_currentPathNode].y; _currentPathNode += 1; _numPixelToWalk -= 1000; } setPosition(_x, _y); _vm->doFrame(); if (_currentWalkStamp != localWalkStamp) { // another walkTo was started in doFrame, we need to cancel this one. return false; } } playStandingAnim(); _flags &= ~0x1; _currentPathNode = 0; _currentPath.clear(); if (_x != localFinalX || _y != localFinalY) { return false; } } } return true; } void Character::setFlag(int flag) { _flags = flag; } int32 Character::getFlag() { return _flags; } int16 Character::getX() { return _x; } int16 Character::getY() { return _y; } bool Character::getVisible() { return _visible; } void Character::setVisible(bool visible) { debugC(1, kDebugCharacter, "setVisible(%d)", (visible) ? 1 : 0); _visible = visible; if (_animationInstance) _animationInstance->setVisible(visible); if (_shadowAnimationInstance) _shadowAnimationInstance->setVisible(visible); return; } int32 Character::getFacing() { return _facing; } bool Character::loadWalkAnimation(const Common::String &animName) { debugC(1, kDebugCharacter, "loadWalkAnimation(%s)", animName.c_str()); delete _walkAnim; _walkAnim = new Animation(_vm); return _walkAnim->loadAnimation(animName); } bool Character::loadIdleAnimation(const Common::String &animName) { debugC(1, kDebugCharacter, "loadIdleAnimation(%s)", animName.c_str()); delete _idleAnim; _idleAnim = new Animation(_vm); return _idleAnim->loadAnimation(animName); } bool Character::loadTalkAnimation(const Common::String &animName) { debugC(1, kDebugCharacter, "loadTalkAnimation(%s)", animName.c_str()); delete _talkAnim; _talkAnim = new Animation(_vm); return _talkAnim->loadAnimation(animName); } bool Character::setupPalette() { return false; // only for Drew } void Character::playStandingAnim() { } void Character::updateTimers(int32 relativeAdd) { _nextIdleTime += relativeAdd; _lastWalkTime += relativeAdd; } void Character::stopSpecialAnim() { debugC(4, kDebugCharacter, "stopSpecialAnim()"); if (_animScriptId != -1) _vm->getSceneAnimationScript(_animScriptId)->_frozenForConversation = false; //if (_sceneAnimationId != -1) // _animationInstance->setAnimation(_vm->getSceneAnimation(_sceneAnimationId)->_animation); bool needStandingAnim = (_animFlags & 0x40) != 0; _animSpecialId = -1; _time = 0; _animFlags = 0; _flags &= ~1; _flags &= ~4; if (needStandingAnim) { playStandingAnim(); } } void Character::update(int32 timeIncrement) { debugC(5, kDebugCharacter, "update(%d)", timeIncrement); if ((_flags & 0x1) && _currentPath.size() > 0) { if (_currentPathNode < _currentPath.size()) { if (_currentPathNode < _currentPath.size() - 10) { int32 delta = MIN(10, _currentPath.size() - 1 - _currentPathNode); int16 dx = _currentPath[_currentPathNode+delta].x - _x; int16 dy = _currentPath[_currentPathNode+delta].y - _y; setFacing(getFacingFromDirection(dx, dy)); playWalkAnim(0, 0); } // in 1/1000 pixels _numPixelToWalk += _speed * (_vm->_system->getMillis() - _lastWalkTime) * _scale / 1024; _lastWalkTime = _vm->_system->getMillis(); while (_numPixelToWalk > 1000 && _currentPathNode < _currentPath.size()) { _x = _currentPath[_currentPathNode].x; _y = _currentPath[_currentPathNode].y; _currentPathNode += 1; _numPixelToWalk -= 1000; } setPosition(_x, _y); } else { playStandingAnim(); _flags &= ~0x1; _currentPath.clear(); } } updateIdle(); #if 0 // handle special anims if ((_flags & 4) == 0) return; if (_animScriptId != -1) { _animationInstance = _vm->getSceneAnimation(this->) #endif int32 animId = _animSpecialId; if (animId >= 1000) animId = 0; if (_animSpecialId < 0) return; int32 currentFrame = _animationInstance->getFrame(); const SpecialCharacterAnimation *anim = getSpecialAnimation(_id, animId); if ((_animFlags & 0x10) == 0) { if (_animScriptId != -1 && currentFrame > 0 && !_vm->getSceneAnimationScript(_animScriptId)->_frozen) { if (_vm->getCurrentLineToSay() != _lineToSayId && (_animFlags & 8)) stopSpecialAnim(); return; } if (_id == 1 && (_animFlags & 4)) { if (_animFlags & 0x10) return; } else { if (_id == 1 && (_animFlags & 0x10) && _vm->getCurrentLineToSay() != -1) { return; } if ((_animFlags & 0x40) == 0 && _vm->getCurrentLineToSay() == -1) { stopSpecialAnim(); return; } if (_animScriptId != -1) _vm->getSceneAnimationScript(_animScriptId)->_frozenForConversation = true; // TODO setup backup // _animFlags |= 0x10; _animationInstance->setAnimation(_specialAnim); _animationInstance->setFrame(0); _time = _vm->getOldMilli() + 8 * _vm->getTickLength(); } } if ((_animFlags & 3) == 2) { if ((((_animFlags & 8) == 8) && _vm->getCurrentLineToSay() != _lineToSayId) || !_vm->getAudioManager()->voiceStillPlaying()) // || (_flags & 8)) && _vm->getAudioManager()->voiceStillPlaying()) _animFlags |= 1; } if (_time > _vm->getOldMilli()) return; int32 animFlag = anim->_unused; int32 nextFrame = currentFrame + 1; int32 nextTime = _time; int32 animDir = 1; if (!animFlag) { if (_animFlags & 1) { if (anim->_flags7 == 0xff) { if (currentFrame > anim->_flag1 / 2) animDir = 1; else animDir = -1; } else { if (currentFrame >= anim->_flags6) { if (currentFrame < anim->_flags7) currentFrame = anim->_flags7; } if (currentFrame > anim->_flags6) animDir = 1; else animDir = -1; } nextFrame = currentFrame + animDir; nextTime = _vm->getOldMilli() + 6 * _vm->getTickLength(); } else { if (_animFlags & 0x20) { nextFrame = currentFrame - 1; if (nextFrame == anim->_flags6 - 1) { if (anim->_flags8 != 1 && (_vm->randRange(0, 1) == 1 || anim->_flags8 == 2)) { _animFlags &= ~0x20; nextFrame += 2; if (nextFrame > anim->_flags7) nextFrame = anim->_flags7; } else { nextFrame = anim->_flags7; } } } else { nextFrame = currentFrame + 1; if (nextFrame == anim->_flags7 + 1 && (_animFlags & 0x40) == 0) { if (anim->_flags8 != 1 && (_vm->randRange(0, 1) || anim->_flags8 == 2)) { _animFlags |= 0x20; nextFrame -= 2; if (nextFrame < anim->_flags6) nextFrame = anim->_flags6; } else { nextFrame = anim->_flags6; } } } nextTime = _vm->getOldMilli() + 8 * _vm->getTickLength(); } // goto label78 } // skipped all this part. //label78 #if 0 if (_id == 0) debug(" drew animation name %s / flag %d / frame %d", _specialAnim->_name, _animFlags, nextFrame); if (_id == 1) debug(" flux animation flag %d / frame %d", _animFlags, nextFrame); if (_id == 7) debug(" footman animation flag %d / frame %d", _animFlags, nextFrame); #endif _time = nextTime; if (nextFrame < 0 || nextFrame >= anim->_flag1) { if ((_animFlags & 2) == 0 || _vm->getCurrentLineToSay() != _lineToSayId) { stopSpecialAnim(); return; } // lots skipped here _animFlags &= ~0x10; _animationInstance->forceFrame(0); return; } //if ((_flags & 8) == 0 || !_vm->getAudioManager()->voiceStillPlaying( ) || ) _animationInstance->forceFrame(nextFrame); } // adapted from Kyra int32 Character::getFacingFromDirection(int16 dx, int16 dy) { debugC(4, kDebugCharacter, "getFacingFromDirection(%d, %d)", dx, dy); static const int facingTable[] = { //1, 0, 1, 2, 3, 4, 3, 2, 7, 0, 7, 6, 5, 4, 5, 6 5, 6, 5, 4, 3, 2, 3, 4, 7, 6, 7, 0, 1, 2, 1, 0 }; dx = -dx; int32 facingEntry = 0; int16 ydiff = dy; if (ydiff < 0) { ++facingEntry; ydiff = -ydiff; } facingEntry *= 2; int16 xdiff = dx; if (xdiff < 0) { ++facingEntry; xdiff = -xdiff; } facingEntry *= 2; if (xdiff >= ydiff) { // Swap xdiff and ydiff int16 temp = ydiff; ydiff = xdiff; xdiff = temp; } else facingEntry++; facingEntry *= 2; if (xdiff < ((ydiff + 1) / 2)) facingEntry++; return facingTable[facingEntry]; } AnimationInstance *Character::getAnimationInstance() { return _animationInstance; } void Character::setAnimationInstance(AnimationInstance *instance) { _animationInstance = instance; } int32 Character::getScale() { return _scale; } void Character::playWalkAnim(int32 startFrame, int32 endFrame) { } void Character::setId(int32 id) { _id = id; } int32 Character::getId() { return _id; } void Character::save(Common::WriteStream *stream) { debugC(1, kDebugCharacter, "save(stream)"); // we have to save visibility too, put in flags to not invalidate old savegames. stream->writeSint32LE(_flags | ((_visible == false) ? 0x100 : 0)); stream->writeSint32LE(_x); stream->writeSint32LE(_y); stream->writeSint32LE(_z); stream->writeSint32LE(_finalX); stream->writeSint32LE(_finalY); stream->writeSint32LE(_scale); stream->writeSint32LE(_id); stream->writeSint32LE(_animScriptId); stream->writeSint32LE(_animFlags); stream->writeSint32LE(_animSpecialDefaultId); stream->writeSint32LE(_sceneAnimationId); } void Character::load(Common::ReadStream *stream) { debugC(1, kDebugCharacter, "read(stream)"); _flags = stream->readSint32LE(); _flags &= ~1; // characters are not walking when restoring. _x = stream->readSint32LE(); _y = stream->readSint32LE(); _z = stream->readSint32LE(); _finalX = stream->readSint32LE(); _finalY = stream->readSint32LE(); _scale = stream->readSint32LE(); _id = stream->readSint32LE(); _animScriptId = stream->readSint32LE(); _animFlags = stream->readSint32LE(); _animSpecialDefaultId = stream->readSint32LE(); _sceneAnimationId = stream->readSint32LE(); if (_sceneAnimationId > -1) { setAnimationInstance(_vm->getSceneAnimation(_sceneAnimationId)->_animInstance); } // "not visible" flag. if (_flags & 0x100) { _flags &= ~0x100; setVisible(false); } } void Character::setAnimScript(int32 animScriptId) { _animScriptId = animScriptId; } void Character::setSceneAnimationId(int32 sceneAnimationId) { _sceneAnimationId = sceneAnimationId; } int32 Character::getAnimScript() { return _animScriptId; } void Character::playTalkAnim() { } void Character::stopWalk() { debugC(1, kDebugCharacter, "stopWalk()"); _finalX = _x; _finalY = _y; _flags &= ~0x1; _currentPathNode = 0; _currentPath.clear(); } const SpecialCharacterAnimation *Character::getSpecialAnimation(int32 characterId, int32 animationId) { debugC(6, kDebugCharacter, "getSpecialAnimation(%d, %d)", characterId, animationId); // very nice animation list hardcoded in the executable... static const SpecialCharacterAnimation anims[] = { { "TLK547_?", 9, 0, 0, 0, 0, 0, 1, 5, 8, 1, 8, 0, 255 }, { "TLK555_?", 16, 0, 0, 0, 0, 6, 8, 10, 255, 6, 11, 2, 255 }, { "LST657_?", 14, 0, 0, 0, 0, 255, 255, 255, 255, 5, 11, 0, 255 }, { "TLK587_?", 18, 0, 0, 0, 0, 5, 7, 9, 11, 4, 13, 1, 255 }, { "LST659_?", 14, 0, 0, 0, 0, 255, 255, 255, 255, 6, 8, 0, 255 }, { "TLK595_?", 11, 0, 0, 0, 0, 3, 6, 255, 255, 1, 7, 0, 255 }, { "IDL165_?", 13, 0, 0, 0, 0, 255, 255, 255, 255, 6, 8, 0, 255 }, { "LST699_?", 10, 0, 0, 0, 0, 255, 255, 255, 255, 1, 9, 1, 255 }, { "LST713_?", 10, 0, 0, 0, 0, 255, 255, 255, 255, 4, 6, 0, 255 }, { "IDL169_?", 16, 0, 0, 0, 0, 255, 255, 255, 255, 5, 9, 2, 255 }, { "IDL173_?", 19, 0, 0, 0, 0, 255, 255, 255, 255, 4, 17, 1, 255 }, { "IDL187_?", 14, 0, 0, 0, 0, 255, 255, 255, 255, 4, 8, 0, 255 }, { "IDL185_?", 15, 0, 0, 0, 0, 255, 255, 255, 255, 6, 9, 1, 255 }, { "TLK635_?", 16, 0, 0, 0, 0, 5, 8, 10, 12, 4, 12, 0, 255 }, { "TLK637_?", 18, 0, 0, 0, 0, 5, 7, 9, 12, 4, 13, 0, 255 }, { "TLK551_?", 20, 0, 0, 0, 0, 5, 9, 11, 15, 4, 16, 0, 255 }, { "TLK553_?", 20, 0, 0, 0, 0, 7, 9, 11, 13, 6, 15, 0, 255 }, { "TLK619_?", 18, 0, 0, 0, 0, 5, 8, 11, 13, 5, 15, 0, 255 }, { "TLK601_?", 12, 0, 0, 0, 0, 2, 5, 6, 10, 2, 10, 1, 255 }, { "TLK559_?", 18, 0, 0, 0, 0, 4, 6, 10, 12, 4, 13, 0, 255 }, { "TLK557_?", 16, 0, 0, 0, 0, 6, 8, 10, 255, 6, 11, 0, 255 }, { "TLK561_?", 17, 0, 0, 0, 0, 6, 8, 10, 12, 5, 12, 0, 255 }, { "TLK623_?", 19, 0, 0, 0, 0, 6, 8, 10, 13, 6, 14, 0, 255 }, { "TLK591_?", 20, 0, 0, 0, 0, 10, 14, 255, 255, 7, 15, 0, 255 }, { "TLK567_?", 19, 0, 0, 0, 0, 6, 9, 11, 14, 5, 15, 0, 255 }, { "TLK629_?", 18, 0, 0, 0, 0, 6, 8, 10, 11, 6, 12, 0, 255 }, { "TLK627_?", 19, 0, 0, 0, 0, 7, 10, 12, 14, 4, 14, 0, 255 }, { "TLK631_?", 19, 0, 0, 0, 0, 8, 10, 255, 255, 8, 12, 0, 255 }, { "TLK565_?", 17, 0, 0, 0, 0, 4, 7, 9, 11, 3, 12, 0, 255 }, { "TLK603_?", 16, 0, 0, 0, 0, 5, 255, 255, 255, 3, 9, 0, 255 }, { "TLK573_?", 20, 0, 0, 0, 0, 6, 7, 10, 255, 6, 16, 2, 255 }, { "TLK615_?", 17, 0, 0, 0, 0, 6, 8, 10, 12, 5, 12, 0, 255 }, { "TLK609_?", 18, 0, 0, 0, 0, 6, 8, 10, 12, 5, 13, 0, 255 }, { "TLK611_?", 18, 0, 0, 0, 0, 8, 10, 12, 255, 7, 13, 0, 255 }, { "TLK607_?", 16, 0, 0, 0, 0, 4, 7, 9, 11, 4, 12, 0, 255 }, { "TLK581_?", 15, 0, 0, 0, 0, 7, 9, 11, 255, 6, 11, 0, 255 }, { "SHD107_?", 46, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "IHL106_?", 23, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 7 }, { "GLV106_?", 23, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 7 }, { "FXTKA_?", 11, 0, 0, 0, 0, 7, 255, 255, 255, 2, 9, 0, 255 }, { "FXTKF_?", 12, 0, 0, 0, 0, 6, 8, 255, 255, 5, 9, 0, 255 }, { "FXTKG_?", 9, 0, 0, 0, 0, 5, 255, 255, 255, 4, 7, 0, 255 }, { "FXTKI_?", 12, 0, 0, 0, 0, 6, 255, 255, 255, 5, 9, 0, 255 }, { "FXTKL_?", 14, 0, 0, 0, 0, 4, 6, 255, 255, 3, 10, 0, 255 }, { "FXTKO_?", 10, 0, 0, 0, 0, 4, 255, 255, 255, 4, 7, 0, 255 }, { "FXTKP_?", 9, 0, 0, 0, 0, 4, 6, 255, 255, 3, 7, 0, 255 }, { "FXTKQ_?", 10, 0, 0, 0, 0, 4, 6, 255, 255, 3, 7, 0, 255 }, { "FXLSA_?", 11, 0, 0, 0, 0, 255, 255, 255, 255, 4, 6, 0, 255 }, { "FXLSB_?", 9, 0, 0, 0, 0, 255, 255, 255, 255, 4, 5, 0, 255 }, { "FXLSK_?", 8, 0, 0, 0, 0, 255, 255, 255, 255, 5, 6, 0, 255 }, { "FXLSM_?", 7, 0, 0, 0, 0, 255, 255, 255, 255, 4, 4, 0, 255 }, { "FXLSP_?", 7, 0, 0, 0, 0, 255, 255, 255, 255, 3, 3, 0, 255 }, { "FXLSQ_?", 6, 0, 0, 0, 0, 255, 255, 255, 255, 3, 3, 0, 255 }, { "FXIDE_?", 10, 0, 0, 0, 0, 255, 255, 255, 255, 5, 7, 0, 255 }, { "FXIDI_?", 7, 0, 0, 0, 0, 255, 255, 255, 255, 1, 6, 1, 255 }, { "FXRCT1_?", 12, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "FXTKB_?", 11, 0, 0, 0, 0, 7, 255, 255, 255, 5, 9, 0, 255 }, { "FXTKC_?", 14, 0, 0, 0, 0, 2, 5, 8, 10, 1, 12, 2, 255 }, { "FXTKD_?", 14, 0, 0, 0, 0, 5, 7, 9, 255, 4, 11, 0, 255 }, { "FXTKE_?", 14, 0, 0, 0, 0, 2, 255, 255, 255, 1, 12, 1, 255 }, { "FXTKH_?", 11, 0, 0, 0, 0, 6, 8, 255, 255, 4, 9, 0, 255 }, { "FXTKJ_?", 8, 0, 0, 0, 0, 7, 255, 255, 255, 4, 7, 0, 255 }, { "FXTKK_?", 13, 0, 0, 0, 0, 6, 8, 255, 255, 5, 9, 0, 255 }, { "FXTKM_?", 11, 0, 0, 0, 0, 6, 255, 255, 255, 4, 7, 0, 255 }, { "FXTKN_?", 9, 0, 0, 0, 0, 5, 7, 255, 255, 4, 7, 0, 255 }, { "FXLSC_?", 9, 0, 0, 0, 0, 255, 255, 255, 255, 3, 6, 1, 255 }, { "FXLSD_?", 7, 0, 0, 0, 0, 255, 255, 255, 255, 4, 5, 0, 255 }, { "FXLSE_?", 9, 0, 0, 0, 0, 255, 255, 255, 255, 8, 8, 0, 255 }, { "FXLSG_?", 11, 0, 0, 0, 0, 255, 255, 255, 255, 6, 8, 2, 255 }, { "FXLSI_?", 8, 0, 0, 0, 0, 255, 255, 255, 255, 5, 6, 0, 255 }, { "FXLSJ_?", 5, 0, 0, 0, 0, 255, 255, 255, 255, 3, 4, 0, 255 }, { "FXLSO_?", 8, 0, 0, 0, 0, 255, 255, 255, 255, 4, 5, 0, 255 }, { "FXIDA_?", 15, 0, 0, 0, 0, 255, 255, 255, 255, 1, 12, 1, 255 }, { "FXIDB_?", 12, 0, 0, 0, 0, 255, 255, 255, 255, 4, 11, 1, 255 }, { "FXIDC_?", 11, 0, 0, 0, 0, 255, 255, 255, 255, 7, 7, 0, 255 }, { "FXIDD_?", 15, 0, 0, 0, 0, 255, 255, 255, 255, 6, 6, 0, 255 }, { "FXIDG_?", 6, 0, 0, 0, 0, 255, 255, 255, 255, 3, 4, 0, 255 }, { "FXVRA_?", 7, 0, 0, 0, 0, 255, 255, 255, 255, 2, 6, 2, 255 }, { "FXIDF_?", 15, 0, 0, 0, 0, 255, 255, 255, 255, 9, 11, 0, 255 }, { "FXEXA_?", 9, 0, 0, 0, 0, 255, 255, 255, 255, 5, 5, 0, 255 }, { "FXEXA_?", 9, 0, 0, 0, 0, 255, 255, 255, 255, 5, 5, 0, 255 }, { "FFNTK1", 8, 0, 0, 0, 0, 255, 255, 255, 255, 1, 7, 0, 255 }, { "FFTLK1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 1, 9, 0, 1 }, { "FFBLS1", 9, 0, 0, 0, 0, 255, 255, 255, 255, 3, 8, 0, 2 }, { "FFLOV2", 6, 0, 0, 0, 0, 255, 255, 255, 255, 3, 5, 0, 2 }, { "FFWOE1", 11, 0, 0, 0, 0, 255, 255, 255, 255, 3, 9, 0, 2 }, { "FFSNF1", 9, 0, 0, 0, 0, 255, 255, 255, 255, 4, 6, 0, 4 }, { "FFLAF1", 9, 0, 0, 0, 0, 255, 255, 255, 255, 2, 8, 0, 1 }, { "FFSKE1", 11, 0, 0, 0, 0, 255, 255, 255, 255, 3, 10, 0, 2 }, { "RGTLK2", 10, 0, 0, 0, 0, 4, 6, 255, 255, 2, 6, 0, 1 }, { "RGTLK1", 10, 0, 0, 0, 0, 4, 6, 255, 255, 2, 6, 0, 1 }, { "BRTLK1", 26, 0, 0, 0, 0, 255, 255, 255, 255, 2, 23, 0, 255 }, { "BREXT1", 14, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "BRLRT1", 19, 0, 0, 0, 0, 255, 255, 255, 255, 1, 15, 0, 255 }, { "BRBWV1", 12, 0, 0, 0, 0, 255, 255, 255, 255, 3, 8, 0, 255 }, { "BRPAT1", 11, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "BRBSP1", 7, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "BRBEX1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "BRBLK1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "BRBET1", 17, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "BRWEX1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "BBTLK2", 26, 0, 0, 0, 0, 255, 255, 255, 255, 2, 23, 1, 255 }, { "BBEXT2", 14, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 1, 255 }, { "BRLST1", 9, 0, 0, 0, 0, 255, 255, 255, 255, 2, 7, 0, 255 }, { "BRLSN1", 13, 0, 0, 0, 0, 255, 255, 255, 255, 1, 13, 2, 255 }, { "BRBNO1", 13, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "BRBND1", 8, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "BBLSN2", 13, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "CCTALK", 6, 0, 0, 0, 0, 2, 5, 255, 255, 1, 5, 0, 255 }, { "CCBIT1", 13, 0, 0, 0, 0, 3, 5, 9, 11, 2, 11, 2, 255 }, { "CCCMP1", 13, 0, 0, 0, 0, 6, 9, 255, 255, 5, 10, 1, 2 }, { "CCCOY1", 14, 0, 0, 0, 0, 6, 8, 255, 255, 4, 8, 0, 3 }, { "CCFNG1", 5, 0, 0, 0, 0, 255, 255, 255, 255, 4, 4, 0, 255 }, { "CCGRB1", 13, 0, 0, 0, 0, 6, 255, 255, 255, 6, 9, 0, 3 }, { "CCGST1", 9, 0, 0, 0, 0, 4, 255, 255, 255, 4, 7, 0, 2 }, { "CCHCN1", 10, 0, 0, 0, 0, 6, 9, 255, 255, 4, 9, 0, 0 }, { "CCHND1", 7, 0, 0, 0, 0, 6, 255, 255, 255, 2, 6, 0, 1 }, { "FTTLK2", 11, 0, 0, 0, 0, 1, 4, 6, 9, 1, 10, 0, 2 }, { "FTGNO2", 11, 0, 0, 0, 0, 4, 6, 8, 255, 4, 8, 1, 2 }, { "FTGST2", 6, 0, 0, 0, 0, 1, 2, 4, 5, 2, 5, 0, 1 }, { "FTHND2", 7, 0, 0, 0, 0, 2, 5, 255, 255, 1, 6, 1, 255 }, { "FTRNT2", 11, 0, 0, 0, 0, 3, 5, 7, 9, 2, 9, 1, 1 }, { "FTSRG2", 10, 0, 0, 0, 0, 4, 6, 8, 255, 3, 8, 1, 1 }, { "FTQOT2", 8, 0, 0, 0, 0, 1, 4, 8, 255, 1, 6, 1, 255 }, { "FMSTK1", 9, 0, 0, 0, 0, 255, 255, 255, 255, 1, 7, 0, 255 }, { "FMCRH1", 13, 0, 0, 0, 0, 255, 255, 255, 255, 3, 10, 0, 255 }, { "FMFGR1", 12, 0, 0, 0, 0, 255, 255, 255, 255, 1, 10, 0, 255 }, { "FMPRS1", 17, 0, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 255 }, { "FMAGR1", 12, 0, 0, 0, 0, 255, 255, 255, 255, 2, 9, 0, 255 }, { "FMWOE1", 11, 0, 0, 0, 0, 255, 255, 255, 255, 1, 9, 0, 255 }, { "FMTOE1", 17, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "FM1TK1", 12, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "FM2TK1", 6, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "FM3TK1", 8, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "FMTNB1", 4, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "FMLOK1", 6, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "FMCST1", 11, 0, 0, 0, 0, 255, 255, 255, 255, 3, 8, 0, 255 }, { "FMLUP3", 8, 0, 0, 0, 0, 255, 255, 255, 255, 2, 5, 0, 255 }, { "BDTLK1", 8, 0, 0, 0, 0, 255, 255, 255, 255, 1, 7, 0, 255 }, { "BDGLE1", 15, 0, 0, 0, 0, 255, 255, 255, 255, 6, 10, 0, 255 }, { "BDSHK1", 16, 0, 0, 0, 0, 255, 255, 255, 255, 5, 11, 0, 1 }, { "BDWOE1", 22, 0, 0, 0, 0, 255, 255, 255, 255, 9, 16, 0, 2 }, { "BDHIP1", 22, 0, 0, 0, 0, 255, 255, 255, 255, 8, 16, 0, 1 }, { "BDFLG1", 13, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "BDKLT1", 12, 0, 0, 0, 0, 255, 255, 255, 255, 5, 10, 0, 255 }, { "BDSWY1", 8, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "WPSNK1", 5, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "WPLAF1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 5, 9, 1, 1 }, { "DOTLK1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 1, 8, 0, 255 }, { "DOGST1", 15, 0, 0, 0, 0, 255, 255, 255, 255, 4, 11, 1, 255 }, { "DO2DF1", 14, 0, 0, 0, 0, 255, 255, 255, 255, 3, 11, 1, 255 }, { "DOSNG1", 11, 0, 0, 0, 0, 255, 255, 255, 255, 8, 9, 1, 255 }, { "DOWOE1", 12, 0, 0, 0, 0, 255, 255, 255, 255, 5, 10, 1, 255 }, { "DO2ME1", 18, 0, 0, 0, 0, 255, 255, 255, 255, 5, 13, 1, 255 }, { "DOGLP1", 9, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 1, 255 }, { "DOCRY1", 9, 0, 0, 0, 0, 255, 255, 255, 255, 3, 6, 1, 255 }, { "METLK1", 5, 0, 0, 0, 0, 255, 255, 255, 255, 1, 4, 0, 255 }, { "MECHT1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 2, 9, 1, 255 }, { "ME2DF1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 2, 9, 0, 255 }, { "MESNG1", 12, 0, 0, 0, 0, 255, 255, 255, 255, 5, 10, 2, 255 }, { "MEWOE1", 13, 0, 0, 0, 0, 255, 255, 255, 255, 3, 10, 1, 255 }, { "ME2DO1", 11, 0, 0, 0, 0, 255, 255, 255, 255, 2, 9, 1, 255 }, { "MEGLP1", 9, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 1, 255 }, { "MECRY1", 12, 0, 0, 0, 0, 255, 255, 255, 255, 6, 9, 1, 255 }, { "CSTLK1", 8, 0, 0, 0, 0, 255, 255, 255, 255, 1, 7, 0, 0 }, { "CSNUD1", 14, 0, 0, 0, 0, 255, 255, 255, 255, 5, 11, 0, 2 }, { "CSSPR1", 11, 0, 0, 0, 0, 255, 255, 255, 255, 4, 8, 0, 2 }, { "CSWVE1", 13, 0, 0, 0, 0, 255, 255, 255, 255, 4, 9, 0, 1 }, { "CSYEL1", 9, 0, 0, 0, 0, 255, 255, 255, 255, 2, 6, 0, 1 }, { "JMTLK1", 7, 0, 0, 0, 0, 1, 4, 255, 255, 1, 6, 0, 0 }, { "JMEGO1", 11, 0, 0, 0, 0, 6, 255, 255, 255, 3, 8, 0, 1 }, { "JMARS1", 7, 0, 0, 0, 0, 4, 6, 255, 255, 3, 6, 0, 2 }, { "JMHIP1", 8, 0, 0, 0, 0, 3, 5, 7, 255, 2, 7, 0, 1 }, { "JMBNK1", 2, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "MRTLK1", 9, 0, 0, 0, 0, 4, 7, 255, 255, 2, 7, 0, 1 }, { "MRHOF1", 8, 0, 0, 0, 0, 3, 5, 255, 255, 2, 5, 0, 255 }, { "MRMRN1", 11, 0, 0, 0, 0, 3, 7, 255, 255, 1, 8, 0, 0 }, { "MRDPR1", 11, 0, 0, 0, 0, 1, 5, 9, 255, 1, 8, 0, 255 }, { "MRGLE1", 13, 0, 0, 0, 0, 5, 9, 255, 255, 3, 10, 0, 2 }, { "MRTDF1", 11, 0, 0, 0, 0, 3, 7, 9, 255, 3, 9, 0, 1 }, { "MREDF1", 11, 0, 0, 0, 0, 4, 255, 255, 255, 1, 10, 1, 255 }, { "MREPL1", 12, 0, 0, 0, 0, 5, 6, 7, 9, 2, 9, 1, 1 }, { "MRAPL1", 12, 0, 0, 0, 0, 4, 8, 9, 255, 2, 9, 0, 1 }, { "MREVL1", 8, 0, 0, 0, 0, 5, 255, 255, 255, 1, 5, 1, 255 }, { "BWDMR1", 16, 0, 0, 0, 0, 4, 7, 9, 11, 3, 14, 0, 1 }, { "BWBUF1", 12, 0, 0, 0, 0, 5, 8, 255, 255, 3, 11, 0, 1 }, { "BWHIP1", 12, 0, 0, 0, 0, 3, 6, 255, 255, 1, 9, 2, 0 }, { "BWHWL1", 14, 0, 0, 0, 0, 255, 255, 255, 255, 1, 4, 2, 255 }, { "BWLEN1", 10, 0, 0, 0, 0, 3, 6, 255, 255, 2, 7, 0, 1 }, { "BWSRL1", 6, 0, 0, 0, 0, 255, 255, 255, 255, 2, 5, 0, 1 }, { "BWWAG1", 6, 0, 0, 0, 0, 4, 10, 14, 18, 1, 4, 0, 0 }, { "BWYEL1", 8, 0, 0, 0, 0, 4, 255, 255, 255, 2, 7, 0, 1 }, { "BWTLK1", 15, 0, 0, 0, 0, 5, 8, 255, 255, 5, 9, 0, 1 }, { "SLTLK1", 19, 0, 0, 0, 0, 255, 255, 255, 255, 1, 18, 0, 255 }, { "SLPND1", 12, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "SLPNT1", 8, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "SLPTR1", 14, 0, 0, 0, 0, 255, 255, 255, 255, 6, 13, 1, 255 }, { "SDTLK1", 7, 0, 0, 0, 0, 255, 255, 255, 255, 1, 5, 0, 255 }, { "SDPDF1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 3, 6, 0, 255 }, { "SDPNT1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 2, 7, 0, 255 }, { "SDSLF1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 2, 7, 0, 255 }, { "SDSTG1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "SDWVE1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 1, 8, 0, 255 }, { "SDSTK1", 9, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "SDSMK1", 22, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "SDGLN1", 5, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "SDLAF1", 8, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "RMHIP1", 12, 0, 0, 0, 0, 7, 255, 255, 255, 1, 10, 2, 255 }, { "RMGES1", 19, 0, 0, 0, 0, 11, 255, 255, 255, 8, 13, 2, 2 }, { "RMPCH1", 18, 0, 0, 0, 0, 12, 255, 255, 255, 6, 13, 0, 2 }, { "RMSTH1", 12, 0, 0, 0, 0, 5, 255, 255, 255, 3, 6, 0, 2 }, { "RMHND1", 7, 0, 0, 0, 0, 5, 255, 255, 255, 5, 5, 1, 255 }, { "RMSTH1", 12, 0, 0, 0, 0, 5, 255, 255, 255, 5, 6, 1, 2 }, { "SGHND1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 1, 9, 0, 0 }, { "SGSTF1", 13, 0, 0, 0, 0, 255, 255, 255, 255, 1, 12, 0, 255 }, { "SGSLP1", 16, 0, 0, 0, 0, 255, 255, 255, 255, 1, 15, 0, 255 }, { "SGPHC1", 12, 0, 0, 0, 0, 255, 255, 255, 255, 4, 9, 0, 255 }, { "SGHALT", 22, 0, 0, 0, 0, 255, 255, 255, 255, 7, 15, 0, 255 }, { "STTLK1", 13, 0, 0, 0, 0, 5, 9, 255, 255, 3, 10, 0, 2 }, { "STTNM1", 13, 0, 0, 0, 0, 5, 9, 255, 255, 3, 10, 0, 2 }, { "STFST1", 11, 0, 0, 0, 0, 3, 8, 255, 255, 1, 9, 0, 255 }, { "STLAF1", 20, 0, 0, 0, 0, 255, 255, 255, 255, 11, 15, 1, 2 }, { "STGES1", 13, 0, 0, 0, 0, 5, 7, 255, 255, 3, 7, 0, 2 }, { "STFNT1", 10, 0, 0, 0, 0, 4, 6, 255, 255, 255, 255, 0, 2 }, { "STSRK1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 1, 3, 2, 0 }, { "STRED1", 11, 0, 0, 0, 0, 255, 255, 255, 255, 2, 10, 0, 255 }, { "STLKU1", 6, 0, 0, 0, 0, 3, 255, 255, 255, 2, 5, 0, 0 }, { "STKEY1", 15, 0, 0, 0, 0, 9, 11, 255, 255, 9, 14, 0, 255 }, { "STMKTD1", 7, 0, 0, 0, 0, 3, 6, 255, 255, 1, 6, 0, 255 }, { "STTKM1", 21, 0, 0, 0, 0, 12, 13, 15, 16, 12, 17, 0, 1 }, { "STMSZ1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 1, 3, 2, 255 }, { "STPNV1", 14, 0, 0, 0, 0, 6, 11, 255, 255, 4, 11, 0, 1 }, { "STSOM1", 10, 0, 0, 0, 0, 255, 255, 255, 255, 1, 3, 2, 255 }, { "MYTLK1", 9, 0, 0, 0, 0, 2, 4, 255, 255, 1, 4, 0, 0 }, { "MYSQUAWK", 5, 0, 0, 0, 0, 255, 255, 255, 255, 3, 3, 1, 255 }, { "SPTLK", 12, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "SPARM", 16, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "SPHOP", 18, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "SPLNT", 16, 0, 0, 0, 0, 255, 255, 255, 255, 3, 13, 0, 255 }, { "SPLAF", 11, 0, 0, 0, 0, 255, 255, 255, 255, 5, 10, 2, 255 }, { "SPTFN", 10, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "SPPIN", 14, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "SPINH1", 21, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "SPSFTCOM", 10, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 255 }, { "MFTMZ1", 9, 0, 0, 0, 0, 255, 255, 255, 255, 1, 8, 1, 255 }, { "MFTLK1", 13, 0, 0, 0, 0, 2, 7, 255, 255, 1, 12, 1, 255 }, { "VGCIR1", 15, 0, 0, 0, 0, 5, 9, 255, 255, 2, 13, 1, 255 }, { "VGBIT1", 12, 0, 0, 0, 0, 6, 9, 255, 255, 2, 9, 1, 255 }, { "VGANG1", 10, 0, 0, 0, 0, 9, 255, 255, 255, 1, 9, 0, 255 }, { "VGCOM1", 13, 0, 0, 0, 0, 5, 11, 255, 255, 2, 11, 0, 255 }, { "VGCUR1", 8, 0, 0, 0, 0, 4, 8, 255, 255, 2, 7, 0, 255 }, { "VGTLK1", 11, 0, 0, 0, 0, 3, 6, 255, 255, 3, 10, 0, 255 }, { "VGEXP1", 10, 0, 0, 0, 0, 5, 9, 255, 255, 3, 9, 0, 255 }, { "WFTLK1", 8, 0, 0, 0, 0, 255, 255, 255, 255, 1, 7, 0, 1 }, { "WFPNT1", 20, 0, 0, 0, 0, 255, 255, 255, 255, 6, 16, 0, 1 }, { "WFFST1", 13, 0, 0, 0, 0, 255, 255, 255, 255, 2, 8, 0, 2 }, { "WFTNO1", 8, 0, 0, 0, 0, 255, 255, 255, 255, 2, 5, 0, 2 }, { "WFSRG1", 11, 0, 0, 0, 0, 255, 255, 255, 255, 3, 8, 0, 1 }, { "WFGTK1", 16, 0, 0, 0, 0, 255, 255, 255, 255, 1, 15, 0, 255 }, { "WFPAW1", 24, 0, 0, 0, 0, 255, 255, 255, 255, 4, 22, 0, 1 }, { "LGTLK", 20, 0, 0, 0, 0, 4, 8, 11, 15, 1, 17, 0, 255 }, { "LGSHOUT", 16, 0, 0, 0, 0, 12, 255, 255, 255, 6, 12, 0, 255 }, { "POMRN1", 12, 0, 0, 0, 0, 3, 5, 7, 255, 3, 9, 0, 2 }, { "POGLE1", 14, 0, 0, 0, 0, 7, 10, 255, 255, 5, 10, 0, 2 }, { "PLMRG1", 16, 0, 0, 0, 0, 9, 255, 255, 255, 8, 12, 0, 1 }, { "PLCMR1", 16, 0, 0, 0, 0, 8, 10, 255, 255, 8, 12, 0, 3 }, { "PLEVL1", 17, 0, 0, 0, 0, 9, 255, 255, 255, 7, 9, 0, 1 }, { "PLEDF1", 9, 0, 0, 0, 0, 4, 6, 255, 255, 5, 7, 0, 2 }, { "PLTLK1", 11, 0, 0, 0, 0, 5, 8, 255, 255, 5, 8, 0, 1 }, { "ELTLK1", 8, 0, 0, 0, 0, 3, 5, 7, 255, 2, 7, 0, 255 }, { "ELSNR1", 7, 0, 0, 0, 0, 3, 255, 255, 255, 1, 5, 0, 255 }, { "RG2TK1", 10, 0, 0, 0, 0, 4, 6, 255, 255, 2, 6, 0, 1 }, { "RG2TK1", 10, 0, 0, 0, 0, 4, 6, 255, 255, 2, 6, 0, 1 }, { "C2TALK", 6, 0, 0, 0, 0, 2, 5, 255, 255, 1, 5, 0, 255 }, { "C2BIT1", 13, 0, 0, 0, 0, 3, 5, 9, 11, 2, 11, 2, 255 }, { "C2CMP1", 13, 0, 0, 0, 0, 6, 9, 255, 255, 5, 10, 1, 2 }, { "C2COY1", 14, 0, 0, 0, 0, 6, 8, 255, 255, 4, 8, 0, 3 }, { "C2FNG1", 5, 0, 0, 0, 0, 255, 255, 255, 255, 4, 4, 0, 255 }, { "C2GRB1", 13, 0, 0, 0, 0, 6, 255, 255, 255, 6, 9, 0, 3 }, { "C2GST1", 9, 0, 0, 0, 0, 4, 255, 255, 255, 4, 7, 0, 2 }, { "C2HCN1", 10, 0, 0, 0, 0, 6, 9, 255, 255, 4, 9, 0, 0 }, { "C2HND1", 7, 0, 0, 0, 0, 6, 255, 255, 255, 2, 6, 0, 1 }, { "666TKBB3", 21, 0, 0, 0, 0, 9, 14, 255, 255, 6, 16, 0, 255 }, { "665TFLX3", 27, 0, 0, 0, 0, 10, 14, 17, 255, 10, 18, 0, 255 }, { "664FXTK3", 18, 0, 0, 0, 0, 5, 7, 11, 13, 3, 15, 0, 255 }, { "FDTALK", 15, 0, 0, 0, 0, 9, 255, 255, 255, 7, 9, 0, 255 }, { "FDYELL", 16, 0, 0, 0, 0, 10, 255, 255, 255, 8, 10, 0, 255 }, { "GLTLK", 20, 0, 0, 0, 0, 6, 12, 18, 255, 1, 19, 0, 255 }, { "GLTRN", 4, 0, 0, 0, 0, 3, 255, 255, 255, 1, 2, 0, 255 }, { "RAYTALK1", 10, 0, 0, 0, 0, 3, 5, 8, 255, 1, 9, 0, 255 }, { "BRTKB1", 17, 0, 0, 0, 0, 255, 255, 255, 255, 2, 14, 0, 255 } }; static const int32 characterAnims[] = { 0, 39, 81, 89, 91, 108, 117, 124, 138, 146, 148, 156, 164, 169, 174, 179, 184, 193, 197, 207, 213, 218, 233, 235, 244, 245, 246, 246, 246, 246, 253, 253, 253, 253, 260, 262, 264, 269, 271, 273, 282, 284, 285, 287, 289, 290, 291, 291, 291, 291, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289 }; return &anims[characterAnims[characterId] + animationId]; } bool Character::loadShadowAnimation(const Common::String &animName) { debugC(1, kDebugCharacter, "loadShadowAnimation(%s)", animName.c_str()); delete _shadowAnim; _shadowAnim = new Animation(_vm); if (!_shadowAnim->loadAnimation(animName)) return false; delete _shadowAnimationInstance; _shadowAnimationInstance = _vm->getAnimationManager()->createNewInstance(kAnimationCharacter); _vm->getAnimationManager()->addInstance(_shadowAnimationInstance); _shadowAnimationInstance->setAnimation(_shadowAnim); _shadowAnimationInstance->setVisible(true); _shadowAnimationInstance->setUseMask(true); return true; } void Character::plotPath(Graphics::Surface& surface) { for (uint32 i = 0; i < _currentPath.size(); i++) { *(byte *)surface.getBasePtr(_currentPath[i].x, _currentPath[i].y) = (i < _currentPathNode); } } void Character::playAnim(int32 animId, int32 unused, int32 flags) { debugC(3, kDebugCharacter, "playAnim(%d, unused, %d)", animId, flags); if (animId == 0) animId = _animSpecialDefaultId; // get the anim to load const SpecialCharacterAnimation *anim = getSpecialAnimation(_id, animId); char animName[20]; strcpy(animName, anim->_filename); int32 facing = _facing; if (_id == 1) { // flux special case... some animations are not for every facing facing = CharacterFlux::fixFacingForAnimation(facing, animId); } if (strchr(animName, '?')) *strchr(animName, '?') = '0' + facing; strcat(animName, ".CAF"); if (_animScriptId != -1 && (flags & 8) == 0) _vm->getSceneAnimationScript(_animScriptId)->_frozenForConversation = true; stopSpecialAnim(); if (flags & 8) { // talker _lineToSayId = _vm->getCurrentLineToSay(); // make the talker busy _flags |= 1; // old special anim was talking anim ? in this case we don't wait for the character to be ready bool wasTalkAnim = _specialAnim && strstr(_specialAnim->_name, "TLK"); // wait for the character to be ready while (_animScriptId != -1 && _animationInstance && _animationInstance->getFrame() > 0 && !wasTalkAnim && (_specialAnim && _animationInstance->getAnimation() != _specialAnim)) { _vm->simpleUpdate(false); } } if (_sceneAnimationId > -1) setAnimationInstance(_vm->getSceneAnimation(_sceneAnimationId)->_animInstance); _animFlags |= flags; delete _specialAnim; _specialAnim = new Animation(_vm); _specialAnim->loadAnimation(animName); _animSpecialId = animId; if (_animationInstance) { _animationInstance->setAnimation(_specialAnim); _animationInstance->setAnimationRange(0, _specialAnim->_numFrames - 1); _animationInstance->reset(); _animationInstance->stopAnimation(); _animationInstance->setLooping(false); } } int32 Character::getAnimFlag() { return _animFlags; } void Character::setAnimFlag(int32 flag) { _animFlags = flag; } int32 Character::getSceneAnimationId() { return _sceneAnimationId; } void Character::setDefaultSpecialAnimationId(int32 defaultAnimationId) { _animSpecialDefaultId = defaultAnimationId; } int16 Character::getFinalX() { return _finalX; } int16 Character::getFinalY() { return _finalY; } void Character::updateIdle() { debugC(5, kDebugCharacter, "updateIdle()"); // only flux and drew if (_id > 1) return; if (_vm->state()->_mouseHidden) _nextIdleTime = _vm->getOldMilli() + (300 + _vm->randRange(0, 600)) * _vm->getTickLength(); if (_vm->getOldMilli() > _nextIdleTime) { if (((_flags & 1) == 0) || ((_flags & 2) != 0)) { if (!_vm->state()->_inCloseUp && !_vm->state()->_inCutaway && _animSpecialId == -1) { if (!_vm->state()->_mouseHidden) { _nextIdleTime = _vm->getOldMilli() + (300 + _vm->randRange(0, 600)) * _vm->getTickLength(); playAnim(getRandomIdleAnim(), 0, 0x40); _flags |= 0x4; } } } } } } // End of namespace Toon