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; _animationInstance->setAnimation(_specialAnim); _animationInstance->setAnimationRange(0, _specialAnim->_numFrames - 1); _animationInstance->reset(); _animationInstance->stopAnimation(); _animationInstance->setLooping(false); }
void CharacterDrew::playStandingAnim() { debugC(4, kDebugCharacter, "playStandingAnim()"); stopSpecialAnim(); _animationInstance->setAnimation(_walkAnim); _animationInstance->setFrame(_facing * 2); _shadowAnimationInstance->setFrame(_facing); _animationInstance->setAnimationRange(_facing * 2, _facing * 2); _animationInstance->stopAnimation(); _animationInstance->setLooping(true); //setVisible(true); }
void CharacterDrew::playWalkAnim(int32 start, int32 end) { debugC(4, kDebugCharacter, "playWalkAnim(%d, %d)", start, end); stopSpecialAnim(); _animationInstance->setAnimation(_walkAnim); _shadowAnimationInstance->setFrame(_facing); _animationInstance->setAnimationRange(16 + _facing * 14, 16 + _facing * 14 + 13); _animationInstance->playAnimation(); _animationInstance->setFps(16); _animationInstance->setLooping(true); //setVisible(true); }
void Character::update(int32 timeIncrement) { debugC(5, kDebugCharacter, "update(%d)", timeIncrement); if ((_flags & 0x1) && _currentPathNodeCount > 0) { if (_currentPathNode < _currentPathNodeCount) { if (_currentPathNode < _currentPathNodeCount - 10) { int32 delta = MIN<int32>(10, _currentPathNodeCount - _currentPathNode); int32 dx = _currentPathX[_currentPathNode+delta] - _x; int32 dy = _currentPathY[_currentPathNode+delta] - _y; setFacing(getFacingFromDirection(dx, dy)); playWalkAnim(0, 0); } // in 1/1000 pixels _numPixelToWalk += _speed * (_vm->getSystem()->getMillis() - _lastWalkTime) * _scale / 1024; _lastWalkTime = _vm->getSystem()->getMillis(); while (_numPixelToWalk > 1000 && _currentPathNode < _currentPathNodeCount) { _x = _currentPathX[_currentPathNode]; _y = _currentPathY[_currentPathNode]; _currentPathNode += 1; _numPixelToWalk -= 1000; } setPosition(_x, _y); } else { playStandingAnim(); _flags &= ~0x1; _currentPathNodeCount = 0; } } 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); }
bool Character::walkTo(int32 newPosX, int32 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 ) { int32 sizeX = MAX<int32>(5, 30 * _vm->getDrew()->getScale() / 1024); int32 sizeY = MAX<int32>(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)) { int32 localFinalX = _finalX; int32 localFinalY = _finalY; int32 smoothDx = 0; int32 smoothDy = 0; for (int32 a = 0; a < _vm->getPathFinding()->getPathNodeCount(); a++) { _currentPathX[a] = _vm->getPathFinding()->getPathNodeX(a); _currentPathY[a] = _vm->getPathFinding()->getPathNodeY(a); } _currentPathNodeCount = _vm->getPathFinding()->getPathNodeCount(); _currentPathNode = 0; stopSpecialAnim(); _lastWalkTime = _vm->getSystem()->getMillis(); _numPixelToWalk = 0; _flags |= 0x1; _currentWalkStamp++; int32 localWalkStamp = _currentWalkStamp; if (_blockingWalk) { while ((_x != newPosX || _y != newPosY) && _currentPathNode < _currentPathNodeCount && !_vm->shouldQuitGame()) { if (_currentPathNode < _currentPathNodeCount - 4) { int32 delta = MIN<int32>(4, _currentPathNodeCount - _currentPathNode); int32 dx = _currentPathX[_currentPathNode+delta] - _x; int32 dy = _currentPathY[_currentPathNode+delta] - _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)); playWalkAnim(0, 0); } // in 1/1000 pixels _numPixelToWalk += _speed * (_vm->getSystem()->getMillis() - _lastWalkTime) * _scale / 1024; _lastWalkTime = _vm->getSystem()->getMillis(); while (_numPixelToWalk >= 1000 && _currentPathNode < _currentPathNodeCount) { _x = _currentPathX[_currentPathNode]; _y = _currentPathY[_currentPathNode]; _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; _currentPathNodeCount = 0; if (_x != localFinalX || _y != localFinalY) { return false; } } } return true; }