mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-23 02:11:38 +00:00
9cedcd059b
svn-id: r31122
458 lines
11 KiB
C++
458 lines
11 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.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include "kyra/kyra_v2.h"
|
|
#include "kyra/wsamovie.h"
|
|
|
|
#include "common/endian.h"
|
|
|
|
namespace Kyra {
|
|
|
|
void KyraEngine_v2::clearAnimObjects() {
|
|
memset(_animObjects, 0, sizeof(_animObjects));
|
|
|
|
_animObjects[0].index = 0;
|
|
_animObjects[0].type = 0;
|
|
_animObjects[0].enabled = 1;
|
|
_animObjects[0].flags = 0x800;
|
|
_animObjects[0].width = 32;
|
|
_animObjects[0].height = 49;
|
|
_animObjects[0].width2 = 4;
|
|
_animObjects[0].height2 = 10;
|
|
|
|
for (int i = 1; i < 11; ++i) {
|
|
_animObjects[i].index = i;
|
|
_animObjects[i].type = 2;
|
|
}
|
|
|
|
for (int i = 11; i <= 40; ++i) {
|
|
_animObjects[i].index = i;
|
|
_animObjects[i].type = 1;
|
|
_animObjects[i].flags = 0x800;
|
|
_animObjects[i].width = 16;
|
|
_animObjects[i].height = 16;
|
|
}
|
|
}
|
|
|
|
KyraEngine_v2::AnimObj *KyraEngine_v2::initAnimList(AnimObj *list, AnimObj *entry) {
|
|
entry->nextObject = list;
|
|
return entry;
|
|
}
|
|
|
|
KyraEngine_v2::AnimObj *KyraEngine_v2::addToAnimListSorted(AnimObj *list, AnimObj *add) {
|
|
if (add->yPos1 <= list->yPos1) {
|
|
add->nextObject = list;
|
|
return add;
|
|
}
|
|
|
|
AnimObj *cur = list;
|
|
AnimObj *prev = list;
|
|
while (add->yPos1 > cur->yPos1) {
|
|
AnimObj *temp = cur->nextObject;
|
|
if (!temp)
|
|
break;
|
|
prev = cur;
|
|
cur = temp;
|
|
}
|
|
|
|
if (add->yPos1 <= cur->yPos1) {
|
|
prev->nextObject = add;
|
|
add->nextObject = cur;
|
|
} else {
|
|
cur->nextObject = add;
|
|
add->nextObject = 0;
|
|
}
|
|
return list;
|
|
}
|
|
|
|
KyraEngine_v2::AnimObj *KyraEngine_v2::deleteAnimListEntry(AnimObj *list, AnimObj *entry) {
|
|
if (!list)
|
|
return 0;
|
|
|
|
AnimObj *old = 0;
|
|
AnimObj *cur = list;
|
|
|
|
while (true) {
|
|
if (cur == entry)
|
|
break;
|
|
if (!cur->nextObject)
|
|
break;
|
|
old = cur;
|
|
cur = cur->nextObject;
|
|
}
|
|
|
|
if (cur == list) {
|
|
if (!cur->nextObject)
|
|
return 0;
|
|
cur = cur->nextObject;
|
|
return cur;
|
|
}
|
|
|
|
if (!cur->nextObject) {
|
|
if (!old)
|
|
return 0;
|
|
old->nextObject = 0;
|
|
return list;
|
|
}
|
|
|
|
if (cur != entry)
|
|
return list;
|
|
|
|
old->nextObject = entry->nextObject;
|
|
return list;
|
|
}
|
|
|
|
void KyraEngine_v2::drawAnimObjects() {
|
|
for (AnimObj *curObject = _animList; curObject; curObject = curObject->nextObject) {
|
|
if (!curObject->enabled)
|
|
continue;
|
|
|
|
int x = curObject->xPos2 - (_screen->getScreenDim(2)->sx << 3);
|
|
int y = curObject->yPos2 - _screen->getScreenDim(2)->sy;
|
|
int layer = 7;
|
|
|
|
if (curObject->flags & 0x800) {
|
|
if (curObject->animFlags)
|
|
layer = 0;
|
|
else
|
|
layer = getDrawLayer(curObject->xPos1, curObject->yPos1);
|
|
}
|
|
curObject->flags |= 0x800;
|
|
|
|
if (curObject->index)
|
|
drawSceneAnimObject(curObject, x, y, layer);
|
|
else
|
|
drawCharacterAnimObject(curObject, x, y, layer);
|
|
}
|
|
}
|
|
|
|
void KyraEngine_v2::refreshAnimObjects(int force) {
|
|
for (AnimObj *curObject = _animList; curObject; curObject = curObject->nextObject) {
|
|
if (!curObject->enabled)
|
|
continue;
|
|
if (!curObject->needRefresh && !force)
|
|
continue;
|
|
|
|
int x = curObject->xPos2 - curObject->width2;
|
|
if (x < 0)
|
|
x = 0;
|
|
if (x >= 320)
|
|
x = 319;
|
|
int y = curObject->yPos2 - curObject->height2;
|
|
if (y < 0)
|
|
y = 0;
|
|
if (y >= 143)
|
|
y = 142;
|
|
|
|
int width = curObject->width + curObject->width2 + 8;
|
|
int height = curObject->height + curObject->height2*2;
|
|
if (width + x > 320)
|
|
width -= width + x - 322;
|
|
if (height + y > 143)
|
|
height -= height + y - 144;
|
|
|
|
_screen->hideMouse();
|
|
_screen->copyRegion(x, y, x, y, width, height, 2, 0, Screen::CR_CLIPPED);
|
|
_screen->showMouse();
|
|
|
|
curObject->needRefresh = false;
|
|
}
|
|
}
|
|
|
|
void KyraEngine_v2::refreshAnimObjectsIfNeed() {
|
|
for (AnimObj *curEntry = _animList; curEntry; curEntry = curEntry->nextObject) {
|
|
if (curEntry->enabled && curEntry->needRefresh) {
|
|
restorePage3();
|
|
drawAnimObjects();
|
|
refreshAnimObjects(0);
|
|
_screen->updateScreen();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void KyraEngine_v2::updateItemAnimations() {
|
|
bool nextFrame = false;
|
|
|
|
if (_itemAnimData[0].itemIndex == -1 || _holdItemAnims)
|
|
return;
|
|
|
|
ItemAnimData *s = &_itemAnimData[_nextAnimItem++];
|
|
|
|
if (s->itemIndex == -1) {
|
|
_nextAnimItem = 0;
|
|
return;
|
|
}
|
|
|
|
uint32 ctime = _system->getMillis();
|
|
if (ctime < s->nextFrame)
|
|
return;
|
|
|
|
uint16 shpIdx = READ_LE_UINT16(s->frames + (s->curFrame << 2)) + 64;
|
|
if ((s->itemIndex == _handItemSet || s->itemIndex == _itemInHand) && (!_mouseState && _screen->isMouseVisible())) {
|
|
nextFrame = true;
|
|
_screen->setMouseCursor(8, 15, getShapePtr(shpIdx));
|
|
}
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
if (s->itemIndex == _mainCharacter.inventory[i]) {
|
|
nextFrame = true;
|
|
_screen->drawShape(2, _defaultShapeTable[240 + i], 304, 184, 0, 0);
|
|
_screen->drawShape(2, getShapePtr(shpIdx), 304, 184, 0, 0);
|
|
_screen->copyRegion(304, 184, _inventoryX[i], _inventoryY[i], 16, 16, 2, 0);
|
|
}
|
|
}
|
|
|
|
_screen->updateScreen();
|
|
|
|
for (int i = 11; i < 40; i++) {
|
|
AnimObj *animObject = &_animObjects[i];
|
|
if (animObject->shapeIndex2 == s->itemIndex + 64) {
|
|
if (s->itemIndex == 121) {
|
|
int f = findItem(_mainCharacter.sceneId, 121);
|
|
int nx = _itemList[f].x - 4;
|
|
if (nx > 12) {
|
|
if (lineIsPassable(nx, _itemList[f].y)) {
|
|
animObject->xPos2 -= 4;
|
|
_itemList[f].x -= 4;
|
|
}
|
|
}
|
|
}
|
|
animObject->shapePtr = _defaultShapeTable[shpIdx];
|
|
animObject->shapeIndex1 = shpIdx;
|
|
animObject->needRefresh = 1;
|
|
nextFrame = true;
|
|
}
|
|
}
|
|
|
|
if (nextFrame) {
|
|
s->nextFrame = _system->getMillis() + READ_LE_UINT16(s->frames + (s->curFrame << 2) + 2) * _tickLength;
|
|
s->curFrame = ++s->curFrame % s->numFrames;
|
|
}
|
|
}
|
|
|
|
void KyraEngine_v2::flagAnimObjsForRefresh() {
|
|
for (AnimObj *curEntry = _animList; curEntry; curEntry = curEntry->nextObject)
|
|
curEntry->needRefresh = 1;
|
|
}
|
|
|
|
void KyraEngine_v2::updateCharFacing() {
|
|
if (_mainCharacter.x1 > _mouseX)
|
|
_mainCharacter.facing = 5;
|
|
else
|
|
_mainCharacter.facing = 3;
|
|
|
|
_mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing];
|
|
updateCharacterAnim(0);
|
|
refreshAnimObjectsIfNeed();
|
|
}
|
|
|
|
void KyraEngine_v2::updateCharacterAnim(int) {
|
|
Character *c = &_mainCharacter;
|
|
AnimObj *animState = _animObjects;
|
|
|
|
animState->needRefresh = 1;
|
|
animState->unk8 = 1;
|
|
|
|
if (c->facing >= 1 && c->facing <= 3)
|
|
animState->flags |= 1;
|
|
else if (c->facing >= 5 && c->facing <= 7)
|
|
animState->flags &= ~1;
|
|
|
|
animState->xPos2 = animState->xPos1 = c->x1;
|
|
animState->yPos2 = animState->yPos1 = c->y1;
|
|
animState->shapePtr = _defaultShapeTable[c->animFrame];
|
|
animState->shapeIndex1 = animState->shapeIndex2 = c->animFrame;
|
|
|
|
int xAdd = _shapeDescTable[c->animFrame-9].xAdd;
|
|
int yAdd = _shapeDescTable[c->animFrame-9].yAdd;
|
|
|
|
_charScaleX = _charScaleY = getScale(c->x1, c->y1);
|
|
|
|
animState->xPos2 += (xAdd * _charScaleX) >> 8;
|
|
animState->yPos2 += (yAdd * _charScaleY) >> 8;
|
|
animState->width2 = 8;
|
|
animState->height2 = 10;
|
|
|
|
_animList = deleteAnimListEntry(_animList, animState);
|
|
if (_animList)
|
|
_animList = addToAnimListSorted(_animList, animState);
|
|
else
|
|
_animList = initAnimList(_animList, animState);
|
|
|
|
updateCharPal(1);
|
|
}
|
|
|
|
void KyraEngine_v2::updateSceneAnim(int anim, int newFrame) {
|
|
AnimObj *animObject = &_animObjects[1+anim];
|
|
if (!animObject->enabled)
|
|
return;
|
|
|
|
animObject->needRefresh = 1;
|
|
animObject->unk8 = 1;
|
|
animObject->flags = 0;
|
|
|
|
if (_sceneAnims[anim].flags & 2)
|
|
animObject->flags |= 0x800;
|
|
else
|
|
animObject->flags &= ~0x800;
|
|
|
|
if (_sceneAnims[anim].flags & 4)
|
|
animObject->flags |= 1;
|
|
else
|
|
animObject->flags &= ~1;
|
|
|
|
if (_sceneAnims[anim].flags & 0x20) {
|
|
animObject->shapePtr = _sceneShapeTable[newFrame];
|
|
animObject->shapeIndex2 = 0xFFFF;
|
|
animObject->shapeIndex3 = 0xFFFF;
|
|
animObject->animNum = 0xFFFF;
|
|
} else {
|
|
animObject->shapePtr = 0;
|
|
animObject->shapeIndex3 = newFrame;
|
|
animObject->animNum = anim;
|
|
}
|
|
|
|
animObject->xPos1 = _sceneAnims[anim].x;
|
|
animObject->yPos1 = _sceneAnims[anim].y;
|
|
animObject->xPos2 = _sceneAnims[anim].x2;
|
|
animObject->yPos2 = _sceneAnims[anim].y2;
|
|
|
|
if (_sceneAnims[anim].flags & 2) {
|
|
_animList = deleteAnimListEntry(_animList, animObject);
|
|
if (!_animList)
|
|
_animList = initAnimList(_animList, animObject);
|
|
else
|
|
_animList = addToAnimListSorted(_animList, animObject);
|
|
}
|
|
}
|
|
|
|
void KyraEngine_v2::drawSceneAnimObject(AnimObj *obj, int x, int y, int layer) {
|
|
if (obj->type == 1) {
|
|
if (obj->shapeIndex1 == 0xFFFF)
|
|
return;
|
|
int scale = getScale(obj->xPos1, obj->yPos1);
|
|
_screen->drawShape(2, getShapePtr(obj->shapeIndex1), x, y, 2, obj->flags | 4, layer, scale, scale);
|
|
return;
|
|
}
|
|
|
|
if (obj->shapePtr) {
|
|
_screen->drawShape(2, obj->shapePtr, x, y, 2, obj->flags, layer);
|
|
} else {
|
|
if (obj->shapeIndex3 == 0xFFFF || obj->animNum == 0xFFFF)
|
|
return;
|
|
|
|
int flags = 0x4000;
|
|
if (obj->flags & 0x800)
|
|
flags |= 0x8000;
|
|
|
|
if (_sceneAnims[obj->animNum].wsaFlag) {
|
|
x = y = 0;
|
|
} else {
|
|
x = obj->xPos2;
|
|
y = obj->yPos2;
|
|
}
|
|
|
|
_sceneAnimMovie[obj->animNum]->setX(x);
|
|
_sceneAnimMovie[obj->animNum]->setY(y);
|
|
_sceneAnimMovie[obj->animNum]->setDrawPage(2);
|
|
_sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, int(flags | layer), 0, 0);
|
|
}
|
|
}
|
|
|
|
void KyraEngine_v2::drawCharacterAnimObject(AnimObj *obj, int x, int y, int layer) {
|
|
if (_drawNoShapeFlag || obj->shapeIndex1 == 0xFFFF)
|
|
return;
|
|
_screen->drawShape(2, getShapePtr(obj->shapeIndex1), x, y, 2, obj->flags | 4, layer, _charScaleX, _charScaleY);
|
|
}
|
|
|
|
void KyraEngine_v2::addItemToAnimList(int item) {
|
|
restorePage3();
|
|
|
|
AnimObj *animObj = &_animObjects[11+item];
|
|
|
|
animObj->enabled = 1;
|
|
animObj->needRefresh = 1;
|
|
animObj->unk8 = 1;
|
|
|
|
int itemId = _itemList[item].id;
|
|
|
|
animObj->xPos2 = animObj->xPos1 = _itemList[item].x;
|
|
animObj->yPos2 = animObj->yPos1 = _itemList[item].y;
|
|
|
|
animObj->shapePtr = _defaultShapeTable[64+itemId];
|
|
animObj->shapeIndex2 = animObj->shapeIndex1 = 64+itemId;
|
|
|
|
int scaleY, scaleX;
|
|
scaleY = scaleX = getScale(animObj->xPos1, animObj->yPos1);
|
|
|
|
uint8 *shapePtr = getShapePtr(64+itemId);
|
|
animObj->xPos3 = (animObj->xPos2 -= (_screen->getShapeScaledWidth(shapePtr, scaleX) >> 1));
|
|
animObj->yPos3 = (animObj->yPos2 -= _screen->getShapeScaledHeight(shapePtr, scaleY));
|
|
|
|
animObj->width2 = animObj->height2 = 0;
|
|
|
|
_animList = addToAnimListSorted(_animList, animObj);
|
|
animObj->needRefresh = 1;
|
|
animObj->unk8 = 1;
|
|
}
|
|
|
|
void KyraEngine_v2::deleteItemAnimEntry(int item) {
|
|
AnimObj *animObj = &_animObjects[11+item];
|
|
|
|
restorePage3();
|
|
|
|
animObj->shapePtr = 0;
|
|
animObj->shapeIndex1 = 0xFFFF;
|
|
animObj->shapeIndex2 = 0xFFFF;
|
|
animObj->needRefresh = 1;
|
|
animObj->unk8 = 1;
|
|
|
|
refreshAnimObjectsIfNeed();
|
|
|
|
animObj->enabled = 0;
|
|
_animList = deleteAnimListEntry(_animList, animObj);
|
|
}
|
|
|
|
void KyraEngine_v2::setCharacterAnimDim(int w, int h) {
|
|
restorePage3();
|
|
|
|
_animObj0Width = _animObjects[0].width;
|
|
_animObj0Height = _animObjects[0].height;
|
|
|
|
_animObjects[0].width = w;
|
|
_animObjects[0].height = h;
|
|
}
|
|
|
|
void KyraEngine_v2::resetCharacterAnimDim() {
|
|
restorePage3();
|
|
|
|
_animObjects[0].width = _animObj0Width;
|
|
_animObjects[0].height = _animObj0Height;
|
|
}
|
|
|
|
} // end of namespace Kyra
|
|
|