KYRA: (LoK/Floppy) - fix minor animator glitch

(in the first cave, when trying to cross the broken bridge and falling into the river, a "cut off" Herman's head could appear on screen beside the death dialog)

The animator code is a bit different here between versions. Our code was apparently based only on DOS CD (Talkie).
This commit is contained in:
athrxx 2022-06-22 01:07:51 +02:00
parent a7fae9ff4e
commit a99055617b
4 changed files with 74 additions and 77 deletions

View File

@ -254,7 +254,7 @@ Common::Error KyraEngine_LoK::init() {
memset(_flagsTable, 0, sizeof(_flagsTable));
_talkingCharNum = -1;
_charSayUnk3 = -1;
_talkHeadAnimCharNum = -1;
_disabledTalkAnimObject = _enabledTalkAnimObject = 0;
memset(_currSentenceColor, 0, 3);
_startSentencePalIndex = -1;

View File

@ -468,7 +468,7 @@ protected:
int8 _talkingCharNum;
int8 _charSayUnk2;
int8 _charSayUnk3;
int8 _talkHeadAnimCharNum;
int8 _currHeadShape;
int _currentHeadFrameTableIndex;
int8 _disabledTalkAnimObject;

View File

@ -201,13 +201,13 @@ void Animator_LoK::preserveOrRestoreBackground(AnimObject *obj, bool restore) {
void Animator_LoK::prepDrawAllObjects() {
AnimObject *curObject = _objectQueue;
int drawPage = 2;
int flagUnk1 = 0, flagUnk2 = 0, flagUnk3 = 0;
int invisibilityDrawFlag = 0, blurDrawFlag = 0, fadeDrawFlag = 0;
if (_noDrawShapesFlag)
return;
if (_vm->_brandonStatusBit & 0x20)
flagUnk1 = 0x200;
invisibilityDrawFlag = Screen::kDRAWSHP_PREDATOR;
if (_vm->_brandonStatusBit & 0x40)
flagUnk2 = 0x4000;
blurDrawFlag = Screen::kDRAWSHP_MORPH;
while (curObject) {
if (curObject->active) {
@ -215,90 +215,85 @@ void Animator_LoK::prepDrawAllObjects() {
int ypos = curObject->y1;
int drawLayer = 0;
if (!(curObject->flags & 0x800))
if (!(curObject->flags & Screen::kDRAWSHP_PRIORITY))
drawLayer = 7;
else if (curObject->disable)
drawLayer = 0;
else
drawLayer = _vm->_sprites->getDrawLayer(curObject->drawY);
// talking head functionallity
if (_vm->_talkingCharNum != -1 && (_vm->_currentCharacter->currentAnimFrame != 88 || curObject->index != 0)) {
const int16 baseAnimFrameTable1[] = { 0x11, 0x35, 0x59, 0x00, 0x00, 0x00 };
const int16 baseAnimFrameTable2[] = { 0x15, 0x39, 0x5D, 0x00, 0x00, 0x00 };
const int8 xOffsetTable1[] = { 2, 4, 0, 5, 2, 0, 0, 0 };
const int8 xOffsetTable2[] = { 6, 4, 8, 3, 6, 0, 0, 0 };
const int8 yOffsetTable1[] = { 0, 8, 1, 1, 0, 0, 0, 0 };
const int8 yOffsetTable2[] = { 0, 8, 1, 1, 0, 0, 0, 0 };
if (curObject->index == 0 || curObject->index <= 4) {
// Talking head functionallity
// DOS Floppy, Amiga and Mac work differently than DOS Talkie. PC-98 and FM-Towns are similar to DOS Talkie, but also slightly different.
bool fmTownsOrPC98 = (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98);
if (_vm->_talkingCharNum != -1 && (fmTownsOrPC98 || (_vm->gameFlags().isTalkie ?
(_vm->_currentCharacter->currentAnimFrame != 88 || curObject->index != 0) : (_brandonScaleX == 0x100 || !_vm->_scaleMode)))) {
const int16 baseAnimFrameTable1[] = { 0x11, 0x35, 0x59, 0x00, 0x00 };
const int16 baseAnimFrameTable2[] = { 0x15, 0x39, 0x5D, 0x00, 0x00 };
const int8 xOffsetTable1[] = { 2, 4, 0, 5, 2, };
const int8 xOffsetTable2[] = { 6, 4, 8, 3, 6, };
const int8 yOffsetTable[] = { 0, 8, 1, 1, 0, };
if (curObject->index <= 4) {
int shapesIndex = 0;
if (curObject->index == _vm->_charSayUnk3) {
if (curObject->index == _vm->_talkHeadAnimCharNum)
shapesIndex = _vm->_currHeadShape + baseAnimFrameTable1[curObject->index];
} else {
else if (curObject->index != 2 || _vm->_characterList[2].sceneId == 77 || _vm->_characterList[2].sceneId == 86)
shapesIndex = baseAnimFrameTable2[curObject->index];
int temp2 = 0;
if (curObject->index == 2) {
if (_vm->_characterList[2].sceneId == 77 || _vm->_characterList[2].sceneId == 86)
temp2 = 1;
else
temp2 = 0;
} else {
temp2 = 1;
}
if (!temp2)
shapesIndex = -1;
}
else
shapesIndex = -1;
xpos = curObject->x1;
ypos = curObject->y1;
int tempX = 0, tempY = 0;
if (curObject->flags & 0x1) {
tempX = (xOffsetTable1[curObject->index] * _brandonScaleX) >> 8;
tempY = yOffsetTable1[curObject->index];
if (curObject->flags & Screen::kDRAWSHP_XFLIP) {
tempX = xOffsetTable1[curObject->index];
tempY = yOffsetTable[curObject->index];
} else {
tempX = (xOffsetTable2[curObject->index] * _brandonScaleX) >> 8;
tempY = yOffsetTable2[curObject->index];
tempX = xOffsetTable2[curObject->index];
tempY = yOffsetTable[curObject->index];
}
tempY = (tempY * _brandonScaleY) >> 8;
if (_vm->gameFlags().isTalkie || fmTownsOrPC98) {
tempX = (tempX * _brandonScaleX) >> 8;
tempY = (tempY * _brandonScaleY) >> 8;
if (_vm->_scaleMode && _brandonScaleX != 0x100)
++tempX;
}
xpos += tempX;
ypos += tempY;
if (_vm->_scaleMode && _brandonScaleX != 256)
++xpos;
if (curObject->index == 0 && shapesIndex != -1) {
if (!(_vm->_brandonStatusBit & 2)) {
flagUnk3 = 0x100;
if ((flagUnk1 & 0x200) || (flagUnk2 & 0x4000))
flagUnk3 = 0;
fadeDrawFlag = Screen::kDRAWSHP_FADE;
if ((invisibilityDrawFlag & Screen::kDRAWSHP_PREDATOR) || (blurDrawFlag & Screen::kDRAWSHP_MORPH))
fadeDrawFlag = 0;
int tempFlags = 0;
if (flagUnk3 & 0x100) {
tempFlags = curObject->flags & 1;
tempFlags |= 0x800 | flagUnk1 | 0x100;
if (fadeDrawFlag & Screen::kDRAWSHP_FADE) {
tempFlags = curObject->flags & Screen::kDRAWSHP_XFLIP;
tempFlags |= (Screen::kDRAWSHP_PRIORITY | invisibilityDrawFlag | Screen::kDRAWSHP_FADE);
}
if (!(flagUnk3 & 0x100) && (flagUnk2 & 0x4000)) {
tempFlags = curObject->flags & 1;
tempFlags |= 0x900 | flagUnk1 | 0x4000;
_screen->drawShape(drawPage, _vm->_shapes[shapesIndex], xpos, ypos, 2, tempFlags | 4, _vm->_brandonPoisonFlagsGFX, int(1), int(_vm->_brandonInvFlag), drawLayer, _brandonScaleX, _brandonScaleY);
if (!(fadeDrawFlag & Screen::kDRAWSHP_FADE) && (blurDrawFlag & Screen::kDRAWSHP_MORPH)) {
tempFlags = curObject->flags & Screen::kDRAWSHP_XFLIP;
tempFlags |= (Screen::kDRAWSHP_PRIORITY | Screen::kDRAWSHP_FADE | invisibilityDrawFlag | Screen::kDRAWSHP_MORPH);
_screen->drawShape(drawPage, _vm->_shapes[shapesIndex], xpos, ypos, 2, tempFlags | Screen::kDRAWSHP_SCALE, _vm->_brandonPoisonFlagsGFX, int(1), int(_vm->_brandonInvFlag), drawLayer, _brandonScaleX, _brandonScaleY);
} else {
if (!(flagUnk2 & 0x4000)) {
tempFlags = curObject->flags & 1;
tempFlags |= 0x900 | flagUnk1;
if (!(blurDrawFlag & Screen::kDRAWSHP_MORPH)) {
tempFlags = curObject->flags & Screen::kDRAWSHP_XFLIP;
tempFlags |= (Screen::kDRAWSHP_PRIORITY | Screen::kDRAWSHP_FADE | invisibilityDrawFlag);
}
_screen->drawShape(drawPage, _vm->_shapes[shapesIndex], xpos, ypos, 2, tempFlags | 4, _vm->_brandonPoisonFlagsGFX, int(1), drawLayer, _brandonScaleX, _brandonScaleY);
_screen->drawShape(drawPage, _vm->_shapes[shapesIndex], xpos, ypos, 2, tempFlags | Screen::kDRAWSHP_SCALE, _vm->_brandonPoisonFlagsGFX, int(1), drawLayer, _brandonScaleX, _brandonScaleY);
}
}
} else {
if (shapesIndex != -1) {
int tempFlags = 0;
if (curObject->flags & 1)
tempFlags = 1;
_screen->drawShape(drawPage, _vm->_shapes[shapesIndex], xpos, ypos, 2, tempFlags | 0x800, drawLayer);
if (curObject->flags & Screen::kDRAWSHP_XFLIP)
tempFlags = Screen::kDRAWSHP_XFLIP;
_screen->drawShape(drawPage, _vm->_shapes[shapesIndex], xpos, ypos, 2, tempFlags | Screen::kDRAWSHP_PRIORITY, drawLayer);
}
}
}
@ -307,34 +302,34 @@ void Animator_LoK::prepDrawAllObjects() {
xpos = curObject->x1;
ypos = curObject->y1;
curObject->flags |= 0x800;
curObject->flags |= Screen::kDRAWSHP_PRIORITY;
if (curObject->index == 0) {
flagUnk3 = 0x100;
fadeDrawFlag = Screen::kDRAWSHP_FADE;
if (flagUnk1 & 0x200 || flagUnk2 & 0x4000)
flagUnk3 = 0;
if (invisibilityDrawFlag & Screen::kDRAWSHP_PREDATOR || blurDrawFlag & Screen::kDRAWSHP_MORPH)
fadeDrawFlag = 0;
if (_vm->_brandonStatusBit & 2)
curObject->flags &= 0xFFFFFFFE;
curObject->flags &= ~Screen::kDRAWSHP_XFLIP;
if (!_vm->_scaleMode) {
if (flagUnk3 & 0x100)
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x100, (uint8 *)_vm->_brandonPoisonFlagsGFX, int(1), drawLayer);
else if (flagUnk2 & 0x4000)
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4000, int(_vm->_brandonInvFlag), drawLayer);
if (fadeDrawFlag & Screen::kDRAWSHP_FADE)
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | invisibilityDrawFlag | Screen::kDRAWSHP_FADE, (uint8 *)_vm->_brandonPoisonFlagsGFX, int(1), drawLayer);
else if (blurDrawFlag & Screen::kDRAWSHP_MORPH)
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | invisibilityDrawFlag | Screen::kDRAWSHP_MORPH, int(_vm->_brandonInvFlag), drawLayer);
else
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1, drawLayer);
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | invisibilityDrawFlag, drawLayer);
} else {
if (flagUnk3 & 0x100)
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x104, (uint8 *)_vm->_brandonPoisonFlagsGFX, int(1), drawLayer, _brandonScaleX, _brandonScaleY);
else if (flagUnk2 & 0x4000)
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4004, int(_vm->_brandonInvFlag), drawLayer, _brandonScaleX, _brandonScaleY);
if (fadeDrawFlag & Screen::kDRAWSHP_FADE)
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | invisibilityDrawFlag | Screen::kDRAWSHP_FADE | Screen::kDRAWSHP_SCALE, (uint8 *)_vm->_brandonPoisonFlagsGFX, int(1), drawLayer, _brandonScaleX, _brandonScaleY);
else if (blurDrawFlag & Screen::kDRAWSHP_MORPH)
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | invisibilityDrawFlag | Screen::kDRAWSHP_MORPH | Screen::kDRAWSHP_SCALE, int(_vm->_brandonInvFlag), drawLayer, _brandonScaleX, _brandonScaleY);
else
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4, drawLayer, _brandonScaleX, _brandonScaleY);
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | invisibilityDrawFlag | Screen::kDRAWSHP_SCALE, drawLayer, _brandonScaleX, _brandonScaleY);
}
} else {
if (curObject->index >= 16 && curObject->index <= 27)
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | 4, drawLayer, (int)_vm->_scaleTable[curObject->drawY], (int)_vm->_scaleTable[curObject->drawY]);
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | Screen::kDRAWSHP_SCALE, drawLayer, (int)_vm->_scaleTable[curObject->drawY], (int)_vm->_scaleTable[curObject->drawY]);
else
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags, drawLayer);
}

View File

@ -132,7 +132,7 @@ void KyraEngine_LoK::waitForChatToFinish(int vocFile, int chatDuration, const ch
}
void KyraEngine_LoK::endCharacterChat(int8 charNum, int16 convoInitialized) {
_charSayUnk3 = -1;
_talkHeadAnimCharNum = -1;
if (charNum > 4 && charNum < 11) {
_animator->sprites()[_disabledTalkAnimObject].active = 1;
@ -244,7 +244,7 @@ int KyraEngine_LoK::initCharacterChat(int8 charNum) {
_animator->flagAllObjectsForRefresh();
_animator->flagAllObjectsForBkgdChange();
_animator->preserveAnyChangedBackgrounds();
_charSayUnk3 = charNum;
_talkHeadAnimCharNum = charNum;
return returnValue;
}
@ -268,9 +268,11 @@ void KyraEngine_LoK::characterSays(int vocFile, const char *chatStr, int16 charN
backupChatPartnerAnimFrame(chatPartnerNum);
if (charNum < 5) {
_characterList[charNum].currentAnimFrame = startAnimFrames[charNum];
_charSayUnk3 = charNum;
_talkingCharNum = charNum;
if (_flags.isTalkie || _flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98 || _animator->_brandonScaleX == 0x100 || !_scaleMode) {
_characterList[charNum].currentAnimFrame = startAnimFrames[charNum];
_talkHeadAnimCharNum = charNum;
_talkingCharNum = charNum;
}
_animator->animRefreshNPC(charNum);
}