mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-21 09:21:08 +00:00
371 lines
9.1 KiB
C++
371 lines
9.1 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 the original source code of Lord Avalot d'Argent version 1.3.
|
|
* Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
|
|
*/
|
|
|
|
/* Original name: CELER The unit for updating the screen pics. */
|
|
|
|
#include "avalanche/avalanche.h"
|
|
#include "avalanche/background.h"
|
|
|
|
namespace Avalanche {
|
|
|
|
const int16 Background::kOnDisk = -1;
|
|
|
|
Background::Background(AvalancheEngine *vm) {
|
|
_vm = vm;
|
|
_spriteNum = 0;
|
|
_nextBell = 0;
|
|
}
|
|
|
|
Background::~Background() {
|
|
release();
|
|
}
|
|
|
|
/**
|
|
* @remarks Originally called 'pics_link'
|
|
*/
|
|
void Background::update() {
|
|
if (_vm->_menu->isActive())
|
|
return; // No animation when the menus are up.
|
|
|
|
switch (_vm->_room) {
|
|
case kRoomOutsideArgentPub:
|
|
if ((_vm->_roomCycles % 12) == 0)
|
|
draw(-1, -1, (_vm->_roomCycles / 12) % 4);
|
|
break;
|
|
case kRoomBrummieRoad:
|
|
if ((_vm->_roomCycles % 2) == 0)
|
|
draw(-1, -1, (_vm->_roomCycles / 2) % 4);
|
|
break;
|
|
case kRoomBridge:
|
|
if ((_vm->_roomCycles % 2) == 0)
|
|
draw(-1, -1, 3 + (_vm->_roomCycles / 2) % 4);
|
|
break;
|
|
case kRoomYours:
|
|
if ((!_vm->_avvyIsAwake) && ((_vm->_roomCycles % 4) == 0))
|
|
draw(-1, -1, (_vm->_roomCycles / 12) % 2);
|
|
break;
|
|
case kRoomArgentPub:
|
|
if (((_vm->_roomCycles % 7) == 1) && (_vm->_malagauche != 177)) {
|
|
// Malagauche cycle.
|
|
_vm->_malagauche++;
|
|
switch (_vm->_malagauche) {
|
|
case 1:
|
|
case 11:
|
|
case 21:
|
|
draw(-1, -1, 11); // Looks forwards.
|
|
break;
|
|
case 8:
|
|
case 18:
|
|
case 28:
|
|
case 32:
|
|
draw(-1, -1, 10); // Looks at you.
|
|
break;
|
|
case 30:
|
|
draw(-1, -1, 12); // Winks.
|
|
break;
|
|
case 33:
|
|
_vm->_malagauche = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (_vm->_roomCycles % 200) {
|
|
case 179:
|
|
case 197:
|
|
draw(-1, -1, 4); // Dogfood's drinking cycle.
|
|
break;
|
|
case 182:
|
|
case 194:
|
|
draw(-1, -1, 5);
|
|
break;
|
|
case 185:
|
|
draw(-1, -1, 6);
|
|
break;
|
|
case 199:
|
|
_vm->_npcFacing = 177; // Impossible value for this.
|
|
break;
|
|
default:
|
|
if (_vm->_roomCycles % 200 <= 178) { // Normally.
|
|
byte direction = 1;
|
|
uint16 angle = _vm->bearing(1);
|
|
if (((angle >= 1) && (angle <= 90)) || ((angle >= 358) && (angle <= 360)))
|
|
direction = 3;
|
|
else if ((angle >= 293) && (angle <= 357))
|
|
direction = 2;
|
|
else if ((angle >= 270) && (angle <= 292))
|
|
direction = 4;
|
|
|
|
if (direction != _vm->_npcFacing) { // Dogfood.
|
|
draw(-1, -1, direction - 1);
|
|
_vm->_npcFacing = direction;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case kRoomWestHall:
|
|
if ((_vm->_roomCycles % 3) == 0) {
|
|
switch ((_vm->_roomCycles / 3) % 6) {
|
|
case 4:
|
|
draw(-1, -1, 0);
|
|
break;
|
|
case 1:
|
|
case 3:
|
|
case 5:
|
|
draw(-1, -1, 1);
|
|
break;
|
|
case 0:
|
|
case 2:
|
|
draw(-1, -1, 2);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case kRoomLustiesRoom:
|
|
if (!(_vm->_lustieIsAsleep)) {
|
|
byte direction = 0;
|
|
uint16 angle = _vm->bearing(1);
|
|
if ((_vm->_roomCycles % 45) > 42)
|
|
direction = 4; // du Lustie blinks.
|
|
// Bearing of Avvy from du Lustie.
|
|
else if ((angle <= 45) || ((angle >= 315) && (angle <= 360)))
|
|
direction = 1; // Middle.
|
|
else if ((angle >= 45) && (angle <= 180))
|
|
direction = 2; // Left.
|
|
else if ((angle >= 181) && (angle <= 314))
|
|
direction = 3; // Right.
|
|
|
|
if (direction != _vm->_npcFacing) { // du Lustie.
|
|
draw(-1, -1, direction - 1);
|
|
_vm->_npcFacing = direction;
|
|
}
|
|
}
|
|
break;
|
|
case kRoomAylesOffice:
|
|
if ((!_vm->_aylesIsAwake) && (_vm->_roomCycles % 14 == 0)) {
|
|
switch ((_vm->_roomCycles / 14) % 2) {
|
|
case 0:
|
|
draw(-1, -1, 0); // Frame 2: EGA.
|
|
break;
|
|
case 1:
|
|
draw(-1, -1, 2); // Frame 1: Natural.
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case kRoomRobins:
|
|
if (_vm->_tiedUp) {
|
|
switch (_vm->_roomCycles % 54) {
|
|
case 20:
|
|
draw(-1, -1, 3); // Frame 4: Avalot blinks.
|
|
break;
|
|
case 23:
|
|
draw(-1, -1, 1); // Frame 1: Back to normal.
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case kRoomNottsPub: {
|
|
// Bearing of Avvy from Port.
|
|
byte direction = 0;
|
|
uint16 angle = _vm->bearing(4);
|
|
if ((angle <= 45) || ((angle >= 315) && (angle <= 360)))
|
|
direction = 2; // Middle.
|
|
else if ((angle >= 45) && (angle <= 180))
|
|
direction = 6; // Left.
|
|
else if ((angle >= 181) && (angle <= 314))
|
|
direction = 8; // Right.
|
|
|
|
if ((_vm->_roomCycles % 60) > 57)
|
|
direction--; // Blinks.
|
|
|
|
if (direction != _vm->_npcFacing) { // Port.
|
|
draw(-1, -1, direction - 1);
|
|
_vm->_npcFacing = direction;
|
|
}
|
|
|
|
switch (_vm->_roomCycles % 50) {
|
|
case 45 :
|
|
draw(-1, -1, 8); // Spurge blinks.
|
|
break;
|
|
case 49 :
|
|
draw(-1, -1, 9);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case kRoomDucks: {
|
|
if ((_vm->_roomCycles % 3) == 0) // The fire flickers.
|
|
draw(-1, -1, (_vm->_roomCycles / 3) % 3);
|
|
|
|
// Bearing of Avvy from Duck.
|
|
byte direction = 0;
|
|
uint16 angle = _vm->bearing(1);
|
|
if ((angle <= 45) || ((angle >= 315) && (angle <= 360)))
|
|
direction = 4; // Middle.
|
|
else if ((angle >= 45) && (angle <= 180))
|
|
direction = 6; // Left.
|
|
else if ((angle >= 181) && (angle <= 314))
|
|
direction = 8; // Right.
|
|
|
|
if ((_vm->_roomCycles % 45) > 42)
|
|
direction++; // Duck blinks.
|
|
|
|
if (direction != _vm->_npcFacing) { // Duck.
|
|
draw(-1, -1, direction - 1);
|
|
_vm->_npcFacing = direction;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ((_vm->_bellsAreRinging) && (_vm->getFlag('B'))) {
|
|
// They're ringing the bells.
|
|
switch (_vm->_roomCycles % 4) {
|
|
case 1:
|
|
if (_nextBell < 5)
|
|
_nextBell = 12;
|
|
_nextBell--;
|
|
// CHECKME: 2 is a guess. No length in the original?
|
|
_vm->_sound->playNote(_vm->kNotes[_nextBell], 2);
|
|
break;
|
|
case 2:
|
|
_vm->_sound->stopSound();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Background::load(byte number) {
|
|
Common::File f;
|
|
_filename = _filename.format("chunk%d.avd", number);
|
|
if (!f.open(_filename))
|
|
return; // We skip because some rooms don't have sprites in the background.
|
|
|
|
f.seek(44);
|
|
_spriteNum = f.readByte();
|
|
for (int i = 0; i < _spriteNum; i++)
|
|
_offsets[i] = f.readSint32LE();
|
|
|
|
for (int i = 0; i < _spriteNum; i++) {
|
|
f.seek(_offsets[i]);
|
|
|
|
SpriteType sprite;
|
|
sprite._type = (PictureType)(f.readByte());
|
|
sprite._x = f.readSint16LE();
|
|
sprite._y = f.readSint16LE();
|
|
sprite._width = f.readSint16LE();
|
|
sprite._height = f.readSint16LE();
|
|
sprite._size = f.readSint32LE();
|
|
bool natural = f.readByte();
|
|
bool memorize = f.readByte();
|
|
|
|
if (memorize) {
|
|
_sprites[i]._x = sprite._x;
|
|
_sprites[i]._width = sprite._width;
|
|
_sprites[i]._y = sprite._y;
|
|
_sprites[i]._height = sprite._height;
|
|
_sprites[i]._type = sprite._type;
|
|
|
|
if (natural)
|
|
_vm->_graphics->getNaturalPicture(_sprites[i]);
|
|
else {
|
|
_sprites[i]._size = sprite._size;
|
|
_sprites[i]._picture = _vm->_graphics->loadPictureRaw(f, _sprites[i]._width * 8, _sprites[i]._height + 1);
|
|
}
|
|
} else
|
|
_sprites[i]._x = kOnDisk;
|
|
}
|
|
f.close();
|
|
}
|
|
|
|
void Background::release() {
|
|
for (int i = 0; i < _spriteNum; i++) {
|
|
if (_sprites[i]._x > kOnDisk)
|
|
_sprites[i]._picture.free();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Draw background animation
|
|
* @remarks Originally called 'show_one'
|
|
*/
|
|
void Background::draw(int16 destX, int16 destY, byte sprId) {
|
|
assert(sprId < 40);
|
|
|
|
if (_sprites[sprId]._x > kOnDisk) {
|
|
if (destX < 0) {
|
|
destX = _sprites[sprId]._x * 8;
|
|
destY = _sprites[sprId]._y;
|
|
}
|
|
drawSprite(destX, destY, _sprites[sprId]);
|
|
} else {
|
|
Common::File f;
|
|
if (!f.open(_filename)) // Filename was set in loadBackgroundSprites().
|
|
return; // We skip because some rooms don't have sprites in the background.
|
|
|
|
f.seek(_offsets[sprId]);
|
|
|
|
SpriteType sprite;
|
|
sprite._type = (PictureType)(f.readByte());
|
|
sprite._x = f.readSint16LE();
|
|
sprite._y = f.readSint16LE();
|
|
sprite._width = f.readSint16LE();
|
|
sprite._height = f.readSint16LE();
|
|
sprite._size = f.readSint32LE();
|
|
f.skip(2); // Natural and Memorize are used in Load()
|
|
sprite._picture = _vm->_graphics->loadPictureRaw(f, sprite._width * 8, sprite._height + 1);
|
|
|
|
if (destX < 0) {
|
|
destX = sprite._x * 8;
|
|
destY = sprite._y;
|
|
}
|
|
drawSprite(destX, destY, sprite);
|
|
|
|
sprite._picture.free();
|
|
f.close();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @remarks Originally called 'display_it'
|
|
*/
|
|
void Background::drawSprite(int16 x, int16 y, SpriteType &sprite) {
|
|
// These pictures are practically parts of the background. -10 is for the drop-down menu.
|
|
_vm->_graphics->drawBackgroundSprite(x, y - 10, sprite);
|
|
}
|
|
|
|
void Background::resetVariables() {
|
|
_nextBell = 0;
|
|
}
|
|
|
|
void Background::synchronize(Common::Serializer &sz) {
|
|
sz.syncAsByte(_nextBell);
|
|
}
|
|
} // End of namespace Avalanche.
|