Initial commit
This commit is contained in:
1
engines/avalanche/POTFILES
Normal file
1
engines/avalanche/POTFILES
Normal file
@@ -0,0 +1 @@
|
||||
engines/avalanche/parser.cpp
|
||||
1581
engines/avalanche/animation.cpp
Normal file
1581
engines/avalanche/animation.cpp
Normal file
File diff suppressed because it is too large
Load Diff
175
engines/avalanche/animation.h
Normal file
175
engines/avalanche/animation.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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: TRIP5 / Trippancy V - the sprite animation subsystem */
|
||||
|
||||
#ifndef AVALANCHE_ANIMATION_H
|
||||
#define AVALANCHE_ANIMATION_H
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
class Animation;
|
||||
|
||||
enum Direction {
|
||||
kDirUp = 0, kDirRight, kDirDown, kDirLeft,
|
||||
kDirUpRight, kDirDownRight, kDirDownLeft, kDirUpLeft,
|
||||
kDirStopped, kDirNone = 177
|
||||
};
|
||||
|
||||
class AnimationType {
|
||||
public:
|
||||
byte _id;
|
||||
|
||||
byte _xLength, _yLength;
|
||||
ManiType *_mani[24];
|
||||
SilType *_sil[24];
|
||||
byte _frameNum; // Number of pictures.
|
||||
byte _seq; // How many in one stride.
|
||||
byte _characterId; // The number according to Acci. (1=Avvy, etc.)
|
||||
byte _count; // Counts before changing step.
|
||||
|
||||
Direction _facingDir;
|
||||
byte _stepNum;
|
||||
int16 _x, _y; // Current xy coords.
|
||||
int8 _moveX, _moveY; // Amount to move sprite by, each step.
|
||||
bool _quick, _visible, _homing, _doCheck;
|
||||
int16 _homingX, _homingY; // Homing x & y coords.
|
||||
byte _speedX, _speedY;
|
||||
bool _vanishIfStill;
|
||||
bool _callEachStepFl;
|
||||
byte _eachStepProc;
|
||||
|
||||
AnimationType(Animation *anim);
|
||||
|
||||
void init(byte spritenum, bool doCheck);
|
||||
void reset();
|
||||
void draw();
|
||||
void turn(Direction whichway);
|
||||
void appear(int16 wx, int16 wy, Direction wf);
|
||||
void bounce();
|
||||
void walk();
|
||||
void walkTo(byte pednum);
|
||||
void stopHoming();
|
||||
void setSpeed(int8 xx, int8 yy);
|
||||
void stopWalk();
|
||||
void chatter();
|
||||
void remove();
|
||||
|
||||
private:
|
||||
Animation *_anim;
|
||||
|
||||
int16 _oldX[2], _oldY[2]; // Last xy coords.
|
||||
Color _fgBubbleCol, _bgBubbleCol; // Foreground & background bubble colors.
|
||||
|
||||
bool checkCollision();
|
||||
int8 getSign(int16 val);
|
||||
void homeStep();
|
||||
};
|
||||
|
||||
class Animation {
|
||||
public:
|
||||
friend class AnimationType;
|
||||
|
||||
static const byte kSpriteNumbMax = 5; // current max no. of sprites
|
||||
|
||||
enum Proc {
|
||||
kProcNone = 0,
|
||||
kProcFollowAvvyY,
|
||||
kProcBackAndForth,
|
||||
kProcFaceAvvy,
|
||||
kProcArrow,
|
||||
kProcGrabAvvy,
|
||||
kProcFollowAvvy
|
||||
};
|
||||
|
||||
AnimationType *_sprites[kSpriteNumbMax];
|
||||
|
||||
Animation(AvalancheEngine *vm);
|
||||
~Animation();
|
||||
|
||||
void animLink();
|
||||
void resetAnims();
|
||||
void callSpecial(uint16 which);
|
||||
void catacombMove(byte ped);
|
||||
void stopWalking();
|
||||
void setMoveSpeed(byte t, Direction dir);
|
||||
void appearPed(byte sprNum, byte pedNum);
|
||||
bool inField(byte which);
|
||||
bool nearDoor();
|
||||
void updateSpeed();
|
||||
void handleMoveKey(const Common::Event &event);
|
||||
void hideInCupboard();
|
||||
|
||||
// These 2 functions are responsible for playing the thunder animation when the player swears too much.
|
||||
void drawLightning(int16 x1, int16 y1, int16 x2, int16 y2);
|
||||
void thunder();
|
||||
|
||||
void wobble();
|
||||
|
||||
void setDirection(Direction dir);
|
||||
void setOldDirection(Direction dir);
|
||||
Direction getDirection();
|
||||
Direction getOldDirection();
|
||||
|
||||
void setAvvyClothes(int id);
|
||||
int getAvvyClothes();
|
||||
|
||||
void resetVariables();
|
||||
void synchronize(Common::Serializer &sz);
|
||||
private:
|
||||
Direction _direction; // The direction Avvy is currently facing.
|
||||
Direction _oldDirection;
|
||||
static const int32 kCatacombMap[8][8];
|
||||
bool _arrowTriggered; // And has the arrow been triggered?
|
||||
bool _mustExclaim;
|
||||
byte _geidaSpin, _geidaTime; // For the making "Geida dizzy" joke.
|
||||
uint16 _sayWhat;
|
||||
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
byte checkFeet(int16 x1, int16 x2, int16 oy, int16 y, byte yl);
|
||||
byte geidaPed(byte ped);
|
||||
void dawnDelay();
|
||||
|
||||
void grabAvvy(byte tripnum);
|
||||
void arrowProcs(byte tripnum);
|
||||
|
||||
// Different movements for NPCs:
|
||||
void followAvalotY(byte tripnum);
|
||||
void backAndForth(byte tripnum);
|
||||
void faceAvvy(byte tripnum);
|
||||
|
||||
// Movements for Homing NPCs: Spludwick and Geida.
|
||||
void spin(Direction dir, byte &tripnum);
|
||||
void takeAStep(byte &tripnum);
|
||||
void follow(byte tripnum);
|
||||
|
||||
void drawSprites();
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche.
|
||||
|
||||
#endif // AVALANCHE_ANIMATION_H
|
||||
523
engines/avalanche/avalanche.cpp
Normal file
523
engines/avalanche/avalanche.cpp
Normal file
@@ -0,0 +1,523 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "avalanche/avalanche.h"
|
||||
|
||||
#include "common/random.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "graphics/thumbnail.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
AvalancheEngine::AvalancheEngine(OSystem *syst, const AvalancheGameDescription *gd) : Engine(syst), _gameDescription(gd), _fxHidden(false), _interrogation(0) {
|
||||
setDebugger(new AvalancheConsole(this));
|
||||
|
||||
_rnd = new Common::RandomSource("avalanche");
|
||||
_showDebugLines = false;
|
||||
|
||||
_clock = nullptr;
|
||||
_graphics = nullptr;
|
||||
_parser = nullptr;
|
||||
_dialogs = nullptr;
|
||||
_background = nullptr;
|
||||
_sequence = nullptr;
|
||||
_timer = nullptr;
|
||||
_animation = nullptr;
|
||||
_dropdown = nullptr;
|
||||
_closing = nullptr;
|
||||
_sound = nullptr;
|
||||
_nim = nullptr;
|
||||
_ghostroom = nullptr;
|
||||
_help = nullptr;
|
||||
_highscore = nullptr;
|
||||
|
||||
initVariables();
|
||||
}
|
||||
|
||||
AvalancheEngine::~AvalancheEngine() {
|
||||
delete _rnd;
|
||||
|
||||
delete _graphics;
|
||||
delete _parser;
|
||||
|
||||
delete _clock;
|
||||
delete _dialogs;
|
||||
delete _background;
|
||||
delete _sequence;
|
||||
delete _timer;
|
||||
delete _animation;
|
||||
delete _dropdown;
|
||||
delete _closing;
|
||||
delete _sound;
|
||||
delete _nim;
|
||||
delete _ghostroom;
|
||||
delete _help;
|
||||
delete _highscore;
|
||||
|
||||
for (int i = 0; i < 31; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
if (_also[i][j] != nullptr) {
|
||||
delete _also[i][j];
|
||||
_also[i][j] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AvalancheEngine::initVariables() {
|
||||
for (int i = 0; i < 31; i++) {
|
||||
_also[i][0] = nullptr;
|
||||
_also[i][1] = nullptr;
|
||||
}
|
||||
|
||||
memset(_fxPal, 0, 16 * 16 * 3);
|
||||
|
||||
for (int i = 0; i < 15; i++) {
|
||||
_peds[i]._direction = kDirNone;
|
||||
_peds[i]._x = 0;
|
||||
_peds[i]._y = 0;
|
||||
_magics[i]._operation = kMagicNothing;
|
||||
_magics[i]._data = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
_portals[i]._operation = kMagicNothing;
|
||||
_portals[i]._data = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 30; i++) {
|
||||
_fields[i]._x1 = 0;
|
||||
_fields[i]._y1 = 0;
|
||||
_fields[i]._x2 = 0;
|
||||
_fields[i]._y2 = 0;
|
||||
}
|
||||
|
||||
_fieldNum = 0;
|
||||
_cp = 0;
|
||||
_ledStatus = 177;
|
||||
_alive = false;
|
||||
_subjectNum = 0;
|
||||
_him = kPeoplePardon;
|
||||
_her = kPeoplePardon;
|
||||
_it = Parser::kPardon;
|
||||
_roomCycles = 0;
|
||||
_doingSpriteRun = false;
|
||||
_isLoaded = false;
|
||||
_soundFx = true;
|
||||
_holdTheDawn = false;
|
||||
|
||||
_lineNum = 0;
|
||||
for (int i = 0; i < 50; i++)
|
||||
_lines[i]._color = kColorWhite;
|
||||
_dropsOk = false;
|
||||
_cheat = false;
|
||||
_letMeOut = false;
|
||||
_thinks = 2;
|
||||
_thinkThing = true;
|
||||
_animationsEnabled = true;
|
||||
_currentMouse = 177;
|
||||
_holdLeftMouse = false;
|
||||
|
||||
resetVariables();
|
||||
}
|
||||
|
||||
Common::ErrorCode AvalancheEngine::initialize() {
|
||||
_graphics = new GraphicManager(this);
|
||||
_parser = new Parser(this);
|
||||
|
||||
_clock = new Clock(this);
|
||||
_dialogs = new Dialogs(this);
|
||||
_background = new Background(this);
|
||||
_sequence = new Sequence(this);
|
||||
_timer = new Timer(this);
|
||||
_animation = new Animation(this);
|
||||
_dropdown = new DropDownMenu(this);
|
||||
_closing = new Closing(this);
|
||||
_sound = new SoundHandler(this);
|
||||
_nim = new Nim(this);
|
||||
_ghostroom = new GhostRoom(this);
|
||||
_help = new Help(this);
|
||||
_highscore = new HighScore(this);
|
||||
|
||||
_graphics->init();
|
||||
_dialogs->init();
|
||||
init();
|
||||
_parser->init();
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool AvalancheEngine::hasFeature(EngineFeature f) const {
|
||||
return (f == kSupportsSavingDuringRuntime) || (f == kSupportsLoadingDuringRuntime);
|
||||
}
|
||||
|
||||
const char *AvalancheEngine::getCopyrightString() const {
|
||||
return "Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.";
|
||||
}
|
||||
|
||||
void AvalancheEngine::synchronize(Common::Serializer &sz) {
|
||||
_animation->synchronize(sz);
|
||||
_parser->synchronize(sz);
|
||||
_nim->synchronize(sz);
|
||||
_sequence->synchronize(sz);
|
||||
_background->synchronize(sz);
|
||||
|
||||
sz.syncAsByte(_carryNum);
|
||||
for (int i = 0; i < kObjectNum; i++)
|
||||
sz.syncAsByte(_objects[i]);
|
||||
sz.syncAsSint16LE(_score);
|
||||
sz.syncAsSint32LE(_money);
|
||||
sz.syncAsByte(_room);
|
||||
if (sz.isSaving())
|
||||
_saveNum++;
|
||||
sz.syncAsByte(_saveNum);
|
||||
sz.syncBytes(_roomCount, 100);
|
||||
sz.syncAsByte(_wonNim);
|
||||
sz.syncAsByte(_wineState);
|
||||
sz.syncAsByte(_cwytalotGone);
|
||||
sz.syncAsByte(_passwordNum);
|
||||
sz.syncAsByte(_aylesIsAwake);
|
||||
sz.syncAsByte(_drawbridgeOpen);
|
||||
sz.syncAsByte(_avariciusTalk);
|
||||
sz.syncAsByte(_rottenOnion);
|
||||
sz.syncAsByte(_onionInVinegar);
|
||||
sz.syncAsByte(_givenToSpludwick);
|
||||
sz.syncAsByte(_brummieStairs);
|
||||
sz.syncAsByte(_cardiffQuestionNum);
|
||||
sz.syncAsByte(_passedCwytalotInHerts);
|
||||
sz.syncAsByte(_avvyIsAwake);
|
||||
sz.syncAsByte(_avvyInBed);
|
||||
sz.syncAsByte(_userMovesAvvy);
|
||||
sz.syncAsByte(_npcFacing);
|
||||
sz.syncAsByte(_givenBadgeToIby);
|
||||
sz.syncAsByte(_friarWillTieYouUp);
|
||||
sz.syncAsByte(_tiedUp);
|
||||
sz.syncAsByte(_boxContent);
|
||||
sz.syncAsByte(_talkedToCrapulus);
|
||||
sz.syncAsByte(_jacquesState);
|
||||
sz.syncAsByte(_bellsAreRinging);
|
||||
sz.syncAsByte(_standingOnDais);
|
||||
sz.syncAsByte(_takenPen);
|
||||
sz.syncAsByte(_arrowInTheDoor);
|
||||
|
||||
if (sz.isSaving()) {
|
||||
uint16 like2drinkSize = _favoriteDrink.size();
|
||||
sz.syncAsUint16LE(like2drinkSize);
|
||||
for (uint16 i = 0; i < like2drinkSize; i++) {
|
||||
char actChr = _favoriteDrink[i];
|
||||
sz.syncAsByte(actChr);
|
||||
}
|
||||
|
||||
uint16 favoriteSongSize = _favoriteSong.size();
|
||||
sz.syncAsUint16LE(favoriteSongSize);
|
||||
for (uint16 i = 0; i < favoriteSongSize; i++) {
|
||||
char actChr = _favoriteSong[i];
|
||||
sz.syncAsByte(actChr);
|
||||
}
|
||||
|
||||
uint16 worst_place_on_earthSize = _worstPlaceOnEarth.size();
|
||||
sz.syncAsUint16LE(worst_place_on_earthSize);
|
||||
for (uint16 i = 0; i < worst_place_on_earthSize; i++) {
|
||||
char actChr = _worstPlaceOnEarth[i];
|
||||
sz.syncAsByte(actChr);
|
||||
}
|
||||
|
||||
uint16 spare_eveningSize = _spareEvening.size();
|
||||
sz.syncAsUint16LE(spare_eveningSize);
|
||||
for (uint16 i = 0; i < spare_eveningSize; i++) {
|
||||
char actChr = _spareEvening[i];
|
||||
sz.syncAsByte(actChr);
|
||||
}
|
||||
} else {
|
||||
if (!_favoriteDrink.empty())
|
||||
_favoriteDrink.clear();
|
||||
uint16 like2drinkSize = 0;
|
||||
char actChr = ' ';
|
||||
sz.syncAsUint16LE(like2drinkSize);
|
||||
for (uint16 i = 0; i < like2drinkSize; i++) {
|
||||
sz.syncAsByte(actChr);
|
||||
_favoriteDrink += actChr;
|
||||
}
|
||||
|
||||
if (!_favoriteSong.empty())
|
||||
_favoriteSong.clear();
|
||||
uint16 favoriteSongSize = 0;
|
||||
sz.syncAsUint16LE(favoriteSongSize);
|
||||
for (uint16 i = 0; i < favoriteSongSize; i++) {
|
||||
sz.syncAsByte(actChr);
|
||||
_favoriteSong += actChr;
|
||||
}
|
||||
|
||||
if (!_worstPlaceOnEarth.empty())
|
||||
_worstPlaceOnEarth.clear();
|
||||
uint16 worst_place_on_earthSize = 0;
|
||||
sz.syncAsUint16LE(worst_place_on_earthSize);
|
||||
for (uint16 i = 0; i < worst_place_on_earthSize; i++) {
|
||||
sz.syncAsByte(actChr);
|
||||
_worstPlaceOnEarth += actChr;
|
||||
}
|
||||
|
||||
if (!_spareEvening.empty())
|
||||
_spareEvening.clear();
|
||||
uint16 spare_eveningSize = 0;
|
||||
sz.syncAsUint16LE(spare_eveningSize);
|
||||
for (uint16 i = 0; i < spare_eveningSize; i++) {
|
||||
sz.syncAsByte(actChr);
|
||||
_spareEvening += actChr;
|
||||
}
|
||||
}
|
||||
|
||||
sz.syncAsSint32LE(_totalTime);
|
||||
sz.syncAsByte(_jumpStatus);
|
||||
sz.syncAsByte(_mushroomGrowing);
|
||||
sz.syncAsByte(_spludwickAtHome);
|
||||
sz.syncAsByte(_lastRoom);
|
||||
sz.syncAsByte(_lastRoomNotMap);
|
||||
sz.syncAsByte(_crapulusWillTell);
|
||||
sz.syncAsByte(_enterCatacombsFromLustiesRoom);
|
||||
sz.syncAsByte(_teetotal);
|
||||
sz.syncAsByte(_malagauche);
|
||||
sz.syncAsByte(_drinking);
|
||||
sz.syncAsByte(_enteredLustiesRoomAsMonk);
|
||||
sz.syncAsByte(_catacombX);
|
||||
sz.syncAsByte(_catacombY);
|
||||
sz.syncAsByte(_avvysInTheCupboard);
|
||||
sz.syncAsByte(_geidaFollows);
|
||||
sz.syncAsByte(_givenPotionToGeida);
|
||||
sz.syncAsByte(_lustieIsAsleep);
|
||||
sz.syncAsByte(_beenTiedUp);
|
||||
sz.syncAsByte(_sittingInPub);
|
||||
sz.syncAsByte(_spurgeTalkCount);
|
||||
sz.syncAsByte(_metAvaroid);
|
||||
sz.syncAsByte(_takenMushroom);
|
||||
sz.syncAsByte(_givenPenToAyles);
|
||||
sz.syncAsByte(_askedDogfoodAboutNim);
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
sz.syncAsSint32LE(_timer->_times[i]._timeLeft);
|
||||
sz.syncAsByte(_timer->_times[i]._action);
|
||||
sz.syncAsByte(_timer->_times[i]._reason);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool AvalancheEngine::canSaveGameStateCurrently(Common::U32String *msg) {
|
||||
return (_animationsEnabled && _alive);
|
||||
}
|
||||
|
||||
Common::Error AvalancheEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
|
||||
return (saveGame(slot, desc) ? Common::kNoError : Common::kWritingFailed);
|
||||
}
|
||||
|
||||
bool AvalancheEngine::saveGame(const int16 slot, const Common::String &desc) {
|
||||
Common::String fileName = getSaveStateName(slot);
|
||||
Common::OutSaveFile *f = g_system->getSavefileManager()->openForSaving(fileName);
|
||||
if (!f) {
|
||||
warning("Can't create file '%s', game not saved.", fileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
f->writeUint32LE(MKTAG('A', 'V', 'A', 'L'));
|
||||
|
||||
// Write version. We can't restore from obsolete versions.
|
||||
f->writeByte(kSavegameVersion);
|
||||
|
||||
f->writeUint32LE(desc.size());
|
||||
f->write(desc.c_str(), desc.size());
|
||||
Graphics::saveThumbnail(*f);
|
||||
|
||||
TimeDate t;
|
||||
_system->getTimeAndDate(t);
|
||||
f->writeSint16LE(t.tm_mday);
|
||||
f->writeSint16LE(t.tm_mon);
|
||||
f->writeSint16LE(t.tm_year);
|
||||
|
||||
_totalTime += getTimeInSeconds() - _startTime;
|
||||
|
||||
Common::Serializer sz(nullptr, f);
|
||||
synchronize(sz);
|
||||
f->finalize();
|
||||
delete f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AvalancheEngine::canLoadGameStateCurrently(Common::U32String *msg) {
|
||||
return (_animationsEnabled);
|
||||
}
|
||||
|
||||
Common::Error AvalancheEngine::loadGameState(int slot) {
|
||||
return (loadGame(slot) ? Common::kNoError : Common::kReadingFailed);
|
||||
}
|
||||
|
||||
bool AvalancheEngine::loadGame(const int16 slot) {
|
||||
Common::String fileName = getSaveStateName(slot);
|
||||
Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(fileName);
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
uint32 signature = f->readUint32LE();
|
||||
if (signature != MKTAG('A', 'V', 'A', 'L'))
|
||||
return false;
|
||||
|
||||
// Check version. We can't restore from obsolete versions.
|
||||
byte saveVersion = f->readByte();
|
||||
if (saveVersion > kSavegameVersion) {
|
||||
warning("Savegame of incompatible version!");
|
||||
delete f;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the description.
|
||||
uint32 descSize = f->readUint32LE();
|
||||
Common::String description;
|
||||
for (uint32 i = 0; i < descSize; i++) {
|
||||
char actChar = f->readByte();
|
||||
description += actChar;
|
||||
}
|
||||
|
||||
description.toUppercase();
|
||||
Graphics::skipThumbnail(*f);
|
||||
|
||||
// Read the time the game was saved.
|
||||
TimeDate t;
|
||||
t.tm_mday = f->readSint16LE();
|
||||
t.tm_mon = f->readSint16LE();
|
||||
t.tm_year = f->readSint16LE();
|
||||
|
||||
resetAllVariables();
|
||||
|
||||
Common::Serializer sz(f, nullptr);
|
||||
synchronize(sz);
|
||||
delete f;
|
||||
|
||||
_isLoaded = true;
|
||||
|
||||
_animationsEnabled = false;
|
||||
|
||||
if (_holdTheDawn) {
|
||||
_holdTheDawn = false;
|
||||
fadeIn();
|
||||
}
|
||||
|
||||
_background->release();
|
||||
minorRedraw();
|
||||
_dropdown->setup();
|
||||
setRoom(kPeopleAvalot, _room);
|
||||
_alive = true;
|
||||
refreshObjectList();
|
||||
_animation->updateSpeed();
|
||||
drawDirection();
|
||||
_animation->animLink();
|
||||
_background->update();
|
||||
|
||||
Common::String tmpStr = Common::String::format("%cLoaded: %c%s.ASG%c%c%c%s%c%csaved on %s.",
|
||||
kControlItalic, kControlRoman, description.c_str(), kControlCenter, kControlNewLine,
|
||||
kControlNewLine, _roomnName.c_str(), kControlNewLine, kControlNewLine,
|
||||
expandDate(t.tm_mday, t.tm_mon, t.tm_year).c_str());
|
||||
_dialogs->displayText(tmpStr);
|
||||
|
||||
AnimationType *avvy = _animation->_sprites[0];
|
||||
if (avvy->_quick && avvy->_visible)
|
||||
_animation->setMoveSpeed(0, _animation->getDirection()); // We push Avvy in the right direction is he was moving.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Common::String AvalancheEngine::expandDate(int d, int m, int y) {
|
||||
static const char months[12][10] = {
|
||||
"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
|
||||
};
|
||||
|
||||
Common::String month = Common::String(months[m]);
|
||||
Common::String day = intToStr(d);
|
||||
|
||||
if (((1 <= d) && (d <= 9)) || ((21 <= d) && (d <= 31)))
|
||||
switch (d % 10) {
|
||||
case 1:
|
||||
day += "st";
|
||||
break;
|
||||
case 2:
|
||||
day += "nd";
|
||||
break;
|
||||
case 3:
|
||||
day += "rd";
|
||||
break;
|
||||
default:
|
||||
day += "th";
|
||||
}
|
||||
|
||||
return day + ' ' + month + ' ' + intToStr(y + 1900);
|
||||
}
|
||||
|
||||
uint32 AvalancheEngine::getTimeInSeconds() {
|
||||
TimeDate time;
|
||||
_system->getTimeAndDate(time);
|
||||
return time.tm_hour * 3600 + time.tm_min * 60 + time.tm_sec;
|
||||
}
|
||||
|
||||
void AvalancheEngine::updateEvents() {
|
||||
Common::Event event;
|
||||
|
||||
while (_eventMan->pollEvent(event)) {
|
||||
switch (event.type) {
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
_holdLeftMouse = true; // Used in checkclick() and Menu::menu_link().
|
||||
break;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
_holdLeftMouse = false; // Same as above.
|
||||
break;
|
||||
case Common::EVENT_KEYDOWN:
|
||||
handleKeyDown(event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AvalancheEngine::getEvent(Common::Event &event) {
|
||||
return _eventMan->pollEvent(event);
|
||||
}
|
||||
|
||||
Common::Point AvalancheEngine::getMousePos() {
|
||||
return _eventMan->getMousePos();
|
||||
}
|
||||
|
||||
Common::Error AvalancheEngine::run() {
|
||||
Common::ErrorCode err = initialize();
|
||||
if (err != Common::kNoError)
|
||||
return err;
|
||||
|
||||
do {
|
||||
runAvalot();
|
||||
} while (!_letMeOut && !shouldQuit());
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche
|
||||
308
engines/avalanche/avalanche.h
Normal file
308
engines/avalanche/avalanche.h
Normal file
@@ -0,0 +1,308 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AVALANCHE_AVALANCHE_H
|
||||
#define AVALANCHE_AVALANCHE_H
|
||||
|
||||
#include "avalanche/console.h"
|
||||
#include "avalanche/graphics.h"
|
||||
#include "avalanche/parser.h"
|
||||
#include "avalanche/avalot.h"
|
||||
#include "avalanche/dialogs.h"
|
||||
#include "avalanche/background.h"
|
||||
#include "avalanche/sequence.h"
|
||||
#include "avalanche/timer.h"
|
||||
#include "avalanche/animation.h"
|
||||
#include "avalanche/dropdown.h"
|
||||
#include "avalanche/closing.h"
|
||||
#include "avalanche/sound.h"
|
||||
#include "avalanche/nim.h"
|
||||
#include "avalanche/clock.h"
|
||||
#include "avalanche/ghostroom.h"
|
||||
#include "avalanche/help.h"
|
||||
#include "avalanche/shootemup.h"
|
||||
#include "avalanche/mainmenu.h"
|
||||
#include "avalanche/highscore.h"
|
||||
|
||||
#include "common/error.h"
|
||||
#include "common/serializer.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
|
||||
#include "graphics/cursorman.h"
|
||||
|
||||
namespace Common {
|
||||
class RandomSource;
|
||||
}
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
struct AvalancheGameDescription;
|
||||
|
||||
static const int kSavegameVersion = 2;
|
||||
|
||||
enum Pitch {
|
||||
kPitchInvalid,
|
||||
kPitchLower,
|
||||
kPitchSame,
|
||||
kPitchHigher
|
||||
};
|
||||
|
||||
class AvalancheEngine : public Engine {
|
||||
public:
|
||||
byte _saveNum; // number of times this game has been saved
|
||||
|
||||
Clock *_clock;
|
||||
GraphicManager *_graphics;
|
||||
Parser *_parser;
|
||||
Dialogs *_dialogs;
|
||||
Background *_background;
|
||||
Sequence *_sequence;
|
||||
Timer *_timer;
|
||||
Animation *_animation;
|
||||
DropDownMenu *_dropdown;
|
||||
Closing *_closing;
|
||||
SoundHandler *_sound;
|
||||
Nim *_nim;
|
||||
GhostRoom *_ghostroom;
|
||||
Help *_help;
|
||||
HighScore *_highscore;
|
||||
|
||||
AvalancheEngine(OSystem *syst, const AvalancheGameDescription *gd);
|
||||
~AvalancheEngine() override;
|
||||
|
||||
Common::ErrorCode initialize();
|
||||
|
||||
Common::RandomSource *_rnd;
|
||||
|
||||
const AvalancheGameDescription *_gameDescription;
|
||||
uint32 getFeatures() const;
|
||||
const char *getGameId() const;
|
||||
Common::Platform getPlatform() const;
|
||||
bool hasFeature(EngineFeature f) const override;
|
||||
const char *getCopyrightString() const;
|
||||
|
||||
void synchronize(Common::Serializer &sz);
|
||||
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
|
||||
bool saveGame(const int16 slot, const Common::String &desc);
|
||||
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
Common::Error loadGameState(int slot) override;
|
||||
bool loadGame(const int16 slot);
|
||||
Common::String expandDate(int d, int m, int y);
|
||||
uint32 getTimeInSeconds();
|
||||
|
||||
void updateEvents();
|
||||
bool getEvent(Common::Event &event); // A wrapper around _eventMan->pollEvent(), so we can use it in Scrolls::normscroll() for example.
|
||||
Common::Point getMousePos();
|
||||
|
||||
protected:
|
||||
// Engine APIs
|
||||
Common::Error run() override;
|
||||
|
||||
public:
|
||||
// For Thinkabout:
|
||||
static const bool kThing = true;
|
||||
static const bool kPerson = false;
|
||||
|
||||
static const char kSpludwicksOrder[3];
|
||||
|
||||
static const uint16 kNotes[12];
|
||||
|
||||
bool _holdLeftMouse;
|
||||
|
||||
// If this is greater than zero, the next line you type is stored in the DNA in a position dictated by the value.
|
||||
// If a scroll comes up, or you leave the room, it's automatically set to zero.
|
||||
byte _interrogation;
|
||||
|
||||
// Former DNA structure
|
||||
byte _carryNum; // How many objects you're carrying...
|
||||
bool _objects[kObjectNum]; // ...and which ones they are.
|
||||
int16 _score; // your score, of course
|
||||
int32 _money; // your current amount of dosh
|
||||
Room _room; // your current room
|
||||
bool _wonNim; // Have you *won* Nim? (That's harder.)
|
||||
byte _wineState; // 0=good (Notts), 1=passable(Argent) ... 3=vinegar.
|
||||
bool _cwytalotGone; // Has Cwytalot rushed off to Jerusalem yet?
|
||||
byte _passwordNum; // Number of the passw for this game.
|
||||
bool _aylesIsAwake; // pretty obvious!
|
||||
byte _drawbridgeOpen; // Between 0 (shut) and 4 (open).
|
||||
byte _avariciusTalk; // How much Avaricius has said to you.
|
||||
bool _rottenOnion; // And has it rotted?
|
||||
bool _onionInVinegar; // Is the onion in the vinegar?
|
||||
byte _givenToSpludwick; // 0 = nothing given, 1 = onion...
|
||||
byte _brummieStairs; // Progression through the stairs trick.
|
||||
byte _cardiffQuestionNum; // Things you get asked in Cardiff.
|
||||
bool _avvyIsAwake; // Well? Is Avvy awake? (Screen 1 only.)
|
||||
bool _avvyInBed; // True if Avvy's in bed, but awake.
|
||||
bool _userMovesAvvy; // If this is false, the user has no control over Avvy's movements.
|
||||
byte _npcFacing; // If there's an NPC in the current room which turns it's head according to Avvy's movement (keep looking at him), this variable tells which way it's facing at the moment.
|
||||
bool _givenBadgeToIby; // Have you given the badge to Iby yet?
|
||||
bool _friarWillTieYouUp; // If you're going to get tied up.
|
||||
bool _tiedUp; // You ARE tied up!
|
||||
byte _boxContent; // 0 = money (sixpence), 254 = empty, any other number implies the contents of the box.
|
||||
bool _talkedToCrapulus; // Pretty self-explanatory.
|
||||
byte _jacquesState; // 0=asleep, 1=awake, 2=gets up, 3=gone.
|
||||
bool _bellsAreRinging; // Is Jacques ringing the bells?
|
||||
bool _standingOnDais; // In room 71, inside Cardiff Castle.
|
||||
bool _takenPen; // Have you taken the pen (in Cardiff?)
|
||||
bool _arrowInTheDoor; // Did the arrow hit the wall?
|
||||
Common::String _favoriteDrink, _favoriteSong, _worstPlaceOnEarth, _spareEvening; // Personalisation str's
|
||||
uint32 _startTime; // When did you start playing this session?
|
||||
uint32 _totalTime; // Your total time playing this game, in seconds. Updated only at saving and loading.
|
||||
byte _jumpStatus; // Fixes how high you're jumping.
|
||||
bool _mushroomGrowing; // Is the mushroom growing in 42?
|
||||
bool _crapulusWillTell; // Will Crapulus tell you about Spludwick being away?
|
||||
bool _enterCatacombsFromLustiesRoom;
|
||||
bool _teetotal; // Are we touching any more drinks?
|
||||
byte _malagauche; // Position of Malagauche. See Celer for more info.
|
||||
char _drinking; // What's he getting you?
|
||||
bool _enteredLustiesRoomAsMonk;
|
||||
byte _catacombX, _catacombY; // XY coords in the catacombs.
|
||||
bool _avvysInTheCupboard; // On screen 22.
|
||||
bool _geidaFollows; // Is Geida following you?
|
||||
bool _givenPotionToGeida; // Does Geida have the potion?
|
||||
bool _lustieIsAsleep; // Is BDL asleep?
|
||||
bool _beenTiedUp; // In r__Robins.
|
||||
bool _sittingInPub; // Are you sitting down in the pub?
|
||||
byte _spurgeTalkCount; // Count for talking to Spurge.
|
||||
bool _metAvaroid;
|
||||
bool _takenMushroom, _givenPenToAyles, _askedDogfoodAboutNim;
|
||||
// End of former DNA Structure
|
||||
|
||||
bool _showDebugLines;
|
||||
byte _lineNum; // Number of lines.
|
||||
LineType _lines[50]; // For Also.
|
||||
bool _dropsOk;
|
||||
bool _cheat; // CHECKME: Currently unused
|
||||
bool _letMeOut;
|
||||
byte _thinks;
|
||||
bool _thinkThing;
|
||||
bool _animationsEnabled; // If set to TRUE, it stops the animation system working. This prevents display of the new sprites before the new picture is loaded or during the display of a scroll. Original name: seescroll.
|
||||
char _objectList[10];
|
||||
// Called .free() for them in ~Gyro().
|
||||
|
||||
byte _currentMouse; // current mouse-void
|
||||
Common::String *_also[31][2];
|
||||
PedType _peds[15];
|
||||
MagicType _magics[15];
|
||||
MagicType _portals[7];
|
||||
FieldType _fields[30];
|
||||
byte _fieldNum;
|
||||
Common::String _listen;
|
||||
byte _cp, _ledStatus;
|
||||
FontType _font;
|
||||
bool _alive;
|
||||
byte _subjectNum; // The same thing.
|
||||
People _him, _her;
|
||||
byte _it;
|
||||
uint32 _roomCycles; // Set to 0 when you enter a room, added to in every loop. Cycles since you've been in this room.
|
||||
|
||||
bool _doingSpriteRun; // Only set to True if we're doing a sprite_run at this moment. This stops the trippancy system from moving any of the sprites.
|
||||
bool _soundFx;
|
||||
|
||||
bool _isLoaded; // Is it a loaded gamestate?
|
||||
|
||||
void callVerb(VerbCode id);
|
||||
void loadBackground(byte num);
|
||||
void loadRoom(byte num);
|
||||
void thinkAbout(byte object, bool type); // Hey!!! Get it and put it!!!
|
||||
void incScore(byte num); // Add on no. of points
|
||||
void fxToggle();
|
||||
void refreshObjectList();
|
||||
void errorLed();
|
||||
void fadeOut();
|
||||
void fadeIn();
|
||||
void drawDirection(); // Draws the little icon at the left end of the text input field.
|
||||
void gameOver();
|
||||
uint16 bearing(byte whichPed); // Returns the bearing from ped 'whichped' to Avvy, in degrees.
|
||||
|
||||
// There are two kinds of redraw: Major and Minor. Minor is what happens when you load a game, etc.
|
||||
// Major was replaced with GraphicManager::refreshScreen(), it redraws EVERYTHING.
|
||||
void minorRedraw();
|
||||
|
||||
void spriteRun();
|
||||
|
||||
Common::String intToStr(int32 num);
|
||||
void newGame(); // This sets up the DNA for a completely new game.
|
||||
bool getFlag(char x);
|
||||
bool decreaseMoney(uint16 amount); // Called pennycheck in the original.
|
||||
|
||||
Common::String getName(People whose);
|
||||
Common::String getItem(byte which); // Called get_better in the original.
|
||||
Common::String f5Does(); // This procedure determines what f5 does.
|
||||
|
||||
void openDoor(Room whither, byte ped, byte magicnum); // Handles slidey-open doors.
|
||||
void flipRoom(Room room, byte ped);
|
||||
|
||||
void setRoom(People persId, Room roomId);
|
||||
Room getRoom(People persId);
|
||||
private:
|
||||
static const int16 kMaxSprites = 2; // Current max no. of sprites.
|
||||
static Room _whereIs[29];
|
||||
|
||||
// Will be used in dusk() and dawn().
|
||||
bool _fxHidden;
|
||||
byte _fxPal[16][16][3];
|
||||
|
||||
bool _spludwickAtHome; // Is Spludwick at home?
|
||||
bool _passedCwytalotInHerts; // Have you passed Cwytalot in Herts?
|
||||
bool _holdTheDawn; // If this is true, calling Dawn will do nothing. It's used, for example, at the start, to stop Load from dawning.
|
||||
byte _lastRoom;
|
||||
byte _lastRoomNotMap;
|
||||
byte _roomCount[100]; // Add one to each every time you enter a room
|
||||
Common::String _mouseText;
|
||||
Common::String _flags;
|
||||
Common::String _roomnName; // Name of actual room
|
||||
int8 _scoreToDisplay[3];
|
||||
|
||||
Common::String readAlsoStringFromFile(Common::File &file);
|
||||
void runAvalot();
|
||||
void init();
|
||||
void initVariables();
|
||||
void setup();
|
||||
void scram(Common::String &str);
|
||||
void unScramble();
|
||||
void handleKeyDown(Common::Event &event); // To replace Basher::keyboard_link() and Basher::typein().
|
||||
void enterNewTown();
|
||||
void findPeople(byte room);
|
||||
void putGeidaAt(byte whichPed, byte ped);
|
||||
void guideAvvy(Common::Point cursorPos);
|
||||
void enterRoom(Room room, byte ped);
|
||||
void exitRoom(byte x);
|
||||
void drawToolbar();
|
||||
void drawScore();
|
||||
void useCompass(const Common::Point &cursorPos); // Click on the compass on the toolbar to control Avvy's movement.
|
||||
void checkClick();
|
||||
void fixFlashers();
|
||||
void loadAlso(byte num);
|
||||
void resetAllVariables();
|
||||
void resetVariables();
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_AVALANCHE_H
|
||||
1690
engines/avalanche/avalot.cpp
Normal file
1690
engines/avalanche/avalot.cpp
Normal file
File diff suppressed because it is too large
Load Diff
68
engines/avalanche/avalot.h
Normal file
68
engines/avalanche/avalot.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* AVALOT The kernel of the program. */
|
||||
|
||||
#ifndef AVALANCHE_AVALOT_H
|
||||
#define AVALANCHE_AVALOT_H
|
||||
|
||||
#include "avalanche/animation.h"
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
static const byte kObjectNum = 18; // always preface with a #
|
||||
static const int16 kCarryLimit = 12; // carry limit
|
||||
|
||||
struct PedType {
|
||||
int16 _x, _y;
|
||||
Direction _direction;
|
||||
};
|
||||
|
||||
struct MagicType {
|
||||
byte _operation; // one of the operations
|
||||
uint16 _data; // data for them
|
||||
};
|
||||
|
||||
struct FieldType {
|
||||
int16 _x1, _y1, _x2, _y2;
|
||||
};
|
||||
|
||||
struct LineType : public FieldType {
|
||||
Color _color;
|
||||
};
|
||||
|
||||
struct QuasipedType {
|
||||
byte _whichPed;
|
||||
Color _textColor;
|
||||
Room _room;
|
||||
Color _backgroundColor;
|
||||
People _who;
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_AVALOT_H
|
||||
384
engines/avalanche/background.cpp
Normal file
384
engines/avalanche/background.cpp
Normal file
@@ -0,0 +1,384 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
for (int i = 0; i < 40; ++i)
|
||||
_offsets[i] = 0;
|
||||
}
|
||||
|
||||
Background::~Background() {
|
||||
release();
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks Originally called 'pics_link'
|
||||
*/
|
||||
void Background::update() {
|
||||
if (_vm->_dropdown->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;
|
||||
default:
|
||||
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;
|
||||
default:
|
||||
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 <= 180)
|
||||
direction = 2; // Left.
|
||||
else if (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;
|
||||
default:
|
||||
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;
|
||||
default:
|
||||
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 <= 180)
|
||||
direction = 6; // Left.
|
||||
else if (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;
|
||||
default:
|
||||
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 <= 180)
|
||||
direction = 6; // Left.
|
||||
else if (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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Background::loadSprites(byte number) {
|
||||
Common::File f;
|
||||
_filename = Common::Path(Common::String::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.
|
||||
78
engines/avalanche/background.h
Normal file
78
engines/avalanche/background.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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. */
|
||||
|
||||
#ifndef AVALANCHE_BACKGROUND_H
|
||||
#define AVALANCHE_BACKGROUND_H
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
enum PictureType {kEga, kBgi, kNaturalImage};
|
||||
|
||||
struct SpriteType {
|
||||
PictureType _type;
|
||||
int16 _x, _y;
|
||||
int16 _width, _height;
|
||||
int32 _size;
|
||||
Graphics::Surface _picture;
|
||||
};
|
||||
|
||||
class Background {
|
||||
public:
|
||||
Background(AvalancheEngine *vm);
|
||||
~Background();
|
||||
|
||||
void update();
|
||||
void loadSprites(byte number);
|
||||
void release();
|
||||
|
||||
// Setting the destination to negative coordinates means the picture should be drawn to it's original position.
|
||||
// If you give it positive values, the picture will be plotted to the desired coordinates on the screen.
|
||||
// By that we get rid of show_one_at(), which would be almost identical and cause a lot of code duplication.
|
||||
void draw(int16 destX, int16 destY, byte sprId);
|
||||
void resetVariables();
|
||||
void synchronize(Common::Serializer &sz);
|
||||
|
||||
private:
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
byte _nextBell; // For the ringing.
|
||||
int32 _offsets[40];
|
||||
byte _spriteNum;
|
||||
SpriteType _sprites[40];
|
||||
Common::Path _filename;
|
||||
static const int16 kOnDisk; // Value of _sprites[fv]._x when it's not in memory.
|
||||
|
||||
void drawSprite(int16 x, int16 y, SpriteType &sprite);
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche.
|
||||
|
||||
#endif // AVALANCHE_BACKGROUND_H
|
||||
117
engines/avalanche/clock.cpp
Normal file
117
engines/avalanche/clock.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "avalanche/clock.h"
|
||||
#include "avalanche/avalanche.h"
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
Clock::Clock(AvalancheEngine *vm) {
|
||||
_vm = vm;
|
||||
// Magic value to determine if we just created the instance
|
||||
_oldHour = _oldHourAngle = _oldMinute = 17717;
|
||||
_hour = _minute = _second = 0;
|
||||
_hourAngle = 0;
|
||||
}
|
||||
|
||||
void Clock::update() {
|
||||
TimeDate t;
|
||||
_vm->_system->getTimeAndDate(t);
|
||||
_hour = t.tm_hour;
|
||||
_minute = t.tm_min;
|
||||
_second = t.tm_sec;
|
||||
|
||||
_hourAngle = (_hour % 12) * 30 + _minute / 2;
|
||||
|
||||
if (_oldHour != _hour) {
|
||||
plotHands();
|
||||
chime();
|
||||
}
|
||||
|
||||
if (_oldMinute != _minute)
|
||||
plotHands();
|
||||
|
||||
if ((_hour == 0) && (_oldHour != 0) && (_oldHour != 17717)) {
|
||||
Common::String tmpStr = Common::String::format("Good morning!%c%cYes, it's just past " \
|
||||
"midnight. Are you having an all-night Avvy session? Glad you like the game that much!",
|
||||
kControlNewLine, kControlNewLine);
|
||||
_vm->_dialogs->displayText(tmpStr);
|
||||
}
|
||||
_oldHour = _hour;
|
||||
_oldHourAngle = _hourAngle;
|
||||
_oldMinute = _minute;
|
||||
}
|
||||
|
||||
Common::Point Clock::calcHand(uint16 angle, uint16 length, Color color) {
|
||||
if (angle > 900) {
|
||||
return(Common::Point(177, 177));
|
||||
}
|
||||
|
||||
return(_vm->_graphics->drawScreenArc(kCenterX, kCenterY, 449 - angle, 450 - angle, length, color));
|
||||
}
|
||||
|
||||
void Clock::drawHand(const Common::Point &endPoint, Color color) {
|
||||
if (endPoint.x == 177)
|
||||
return;
|
||||
|
||||
_vm->_graphics->drawScreenLine(kCenterX, kCenterY, endPoint.x, endPoint.y, color);
|
||||
}
|
||||
|
||||
void Clock::plotHands() {
|
||||
_clockHandHour = calcHand(_oldHourAngle, 14, kColorYellow);
|
||||
_clockHandMinute = calcHand(_oldMinute * 6, 17, kColorYellow);
|
||||
drawHand(_clockHandHour, kColorBrown);
|
||||
drawHand(_clockHandMinute, kColorBrown);
|
||||
|
||||
_clockHandHour = calcHand(_hourAngle, 14, kColorBrown);
|
||||
_clockHandMinute = calcHand(_minute * 6, 17, kColorBrown);
|
||||
drawHand(_clockHandHour, kColorYellow);
|
||||
drawHand(_clockHandMinute, kColorYellow);
|
||||
}
|
||||
|
||||
void Clock::chime() {
|
||||
// Too high - must be first time around
|
||||
// Mute - skip the sound generation
|
||||
if ((_oldHour == 17717) || (!_vm->_soundFx))
|
||||
return;
|
||||
|
||||
byte hour = _hour % 12;
|
||||
if (hour == 0)
|
||||
hour = 12;
|
||||
|
||||
_vm->_graphics->loadMouse(kCurWait);
|
||||
|
||||
for (int i = 1; i <= hour; i++) {
|
||||
for (int j = 1; j <= 3; j++)
|
||||
_vm->_sound->playNote((i % 3) * 64 + 140 - j * 30, 50 - j * 12);
|
||||
if (i != hour)
|
||||
_vm->_system->delayMillis(100);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche
|
||||
59
engines/avalanche/clock.h
Normal file
59
engines/avalanche/clock.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AVALANCHE_CLOCK_H
|
||||
#define AVALANCHE_CLOCK_H
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "avalanche/enums.h"
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
class Clock {
|
||||
public:
|
||||
Clock(AvalancheEngine *vm);
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
static const int kCenterX = 510;
|
||||
static const int kCenterY = 183;
|
||||
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
uint16 _hour, _minute, _second, _hourAngle, _oldHour, _oldMinute, _oldHourAngle;
|
||||
Common::Point _clockHandHour, _clockHandMinute;
|
||||
|
||||
Common::Point calcHand(uint16 angle, uint16 length, Color color);
|
||||
void drawHand(const Common::Point &endPoint, Color color);
|
||||
void plotHands();
|
||||
void chime();
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_CLOCK_H
|
||||
74
engines/avalanche/closing.cpp
Normal file
74
engines/avalanche/closing.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* CLOSING The closing screen and error handler. */
|
||||
|
||||
#include "avalanche/avalanche.h"
|
||||
#include "avalanche/closing.h"
|
||||
|
||||
#include "common/random.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
Closing::Closing(AvalancheEngine *vm) {
|
||||
_vm = vm;
|
||||
warning("STUB: Closing::Closing()");
|
||||
}
|
||||
|
||||
void Closing::getScreen(ScreenType which) {
|
||||
warning("STUB: Closing::getScreen()");
|
||||
}
|
||||
|
||||
void Closing::showScreen() {
|
||||
warning("STUB: Closing::showScreen()");
|
||||
}
|
||||
|
||||
void Closing::putIn(Common::String str, uint16 where) {
|
||||
warning("STUB: Closing::putIn()");
|
||||
}
|
||||
|
||||
void Closing::exitGame() {
|
||||
static const char nouns[12][14] = {
|
||||
"sackbut", "harpsichord", "camel", "conscience", "ice-cream", "serf",
|
||||
"abacus", "castle", "carrots", "megaphone", "manticore", "drawbridge"
|
||||
};
|
||||
|
||||
static const char verbs[12][12] = {
|
||||
"haunt", "daunt", "tickle", "gobble", "erase", "provoke",
|
||||
"surprise", "ignore", "stare at", "shriek at", "frighten", "quieten"
|
||||
};
|
||||
|
||||
_vm->_sound->stopSound();
|
||||
|
||||
getScreen(kScreenNagScreen);
|
||||
byte nounId = _vm->_rnd->getRandomNumber(11);
|
||||
byte verbId = _vm->_rnd->getRandomNumber(11);
|
||||
Common::String result = Common::String::format("%s will %s you", nouns[nounId], verbs[verbId]);
|
||||
putIn(result, 1628);
|
||||
showScreen(); // No halt- it's already set up.
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche.
|
||||
61
engines/avalanche/closing.h
Normal file
61
engines/avalanche/closing.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* CLOSING The closing screen and error handler. */
|
||||
|
||||
#ifndef AVALANCHE_CLOSING_H
|
||||
#define AVALANCHE_CLOSING_H
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
class Closing {
|
||||
public:
|
||||
Closing(AvalancheEngine *vm);
|
||||
void exitGame();
|
||||
|
||||
private:
|
||||
// Will be needed during implementation of Closing.
|
||||
enum ScreenType {
|
||||
kScreenBugAlert = 1,
|
||||
kScreenRamCram = 2,
|
||||
kScreenNagScreen = 3,
|
||||
kScreenTwoCopies = 5
|
||||
};
|
||||
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
void getScreen(ScreenType which);
|
||||
void showScreen();
|
||||
void putIn(Common::String str, uint16 where);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche.
|
||||
|
||||
#endif // AVALANCHE_CLOSING_H
|
||||
3
engines/avalanche/configure.engine
Normal file
3
engines/avalanche/configure.engine
Normal file
@@ -0,0 +1,3 @@
|
||||
# This file is included from the main "configure" script
|
||||
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
|
||||
add_engine avalanche "Lord Avalot d'Argent" no "" "" "highres"
|
||||
52
engines/avalanche/console.cpp
Normal file
52
engines/avalanche/console.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "avalanche/console.h"
|
||||
#include "avalanche/avalanche.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
AvalancheConsole::AvalancheConsole(AvalancheEngine *vm) : GUI::Debugger(), _vm(vm) {
|
||||
registerCmd("magic_lines", WRAP_METHOD(AvalancheConsole, Cmd_MagicLines));
|
||||
}
|
||||
|
||||
AvalancheConsole::~AvalancheConsole() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This command loads up the specified new scene number
|
||||
*/
|
||||
bool AvalancheConsole::Cmd_MagicLines(int argc, const char **argv) {
|
||||
if (argc != 1) {
|
||||
debugPrintf("Usage: %s\n", argv[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
_vm->_showDebugLines = !_vm->_showDebugLines;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche
|
||||
50
engines/avalanche/console.h
Normal file
50
engines/avalanche/console.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AVALANCHE_CONSOLE_H
|
||||
#define AVALANCHE_CONSOLE_H
|
||||
|
||||
#include "gui/debugger.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
class AvalancheEngine;
|
||||
|
||||
class AvalancheConsole : public GUI::Debugger {
|
||||
public:
|
||||
AvalancheConsole(AvalancheEngine *vm);
|
||||
~AvalancheConsole(void) override;
|
||||
|
||||
protected:
|
||||
bool Cmd_MagicLines(int argc, const char **argv);
|
||||
|
||||
private:
|
||||
AvalancheEngine *_vm;
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_CONSOLE_H
|
||||
4
engines/avalanche/credits.pl
Normal file
4
engines/avalanche/credits.pl
Normal file
@@ -0,0 +1,4 @@
|
||||
begin_section("Avalanche");
|
||||
add_person("Peter Bozsó", "uruk", "");
|
||||
add_person("Arnaud Boutonné", "Strangerke", "");
|
||||
end_section();
|
||||
75
engines/avalanche/detection.cpp
Normal file
75
engines/avalanche/detection.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "base/plugins.h"
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "avalanche/detection.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
static const PlainGameDescriptor avalancheGames[] = {
|
||||
{"avalanche", "Lord Avalot d'Argent"},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
static const AvalancheGameDescription gameDescriptions[] = {
|
||||
{{
|
||||
"avalanche", nullptr,
|
||||
AD_ENTRY2s("avalot.sez", "de10eb353228013da3d3297784f81ff9", 48763,
|
||||
"mainmenu.avd", "89f31211af579a872045b175cc264298", 18880),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO1(GUIO_NOMIDI)
|
||||
}},
|
||||
|
||||
{AD_TABLE_END_MARKER}
|
||||
};
|
||||
|
||||
class AvalancheMetaEngineDetection : public AdvancedMetaEngineDetection<AvalancheGameDescription> {
|
||||
public:
|
||||
AvalancheMetaEngineDetection() : AdvancedMetaEngineDetection(gameDescriptions, avalancheGames) {
|
||||
}
|
||||
|
||||
const char *getName() const override {
|
||||
return "avalanche";
|
||||
}
|
||||
|
||||
const char *getEngineName() const override {
|
||||
return "Avalanche";
|
||||
}
|
||||
|
||||
const char *getOriginalCopyright() const override {
|
||||
return "Avalanche (C) 1994-1995 Mike, Mark and Thomas Thurman.";
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
REGISTER_PLUGIN_STATIC(AVALANCHE_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, Avalanche::AvalancheMetaEngineDetection);
|
||||
40
engines/avalanche/detection.h
Normal file
40
engines/avalanche/detection.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AVALANCHE_DETECTION_H
|
||||
#define AVALANCHE_DETECTION_H
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
struct AvalancheGameDescription {
|
||||
AD_GAME_DESCRIPTION_HELPERS(desc);
|
||||
|
||||
ADGameDescription desc;
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_DETECTION_H
|
||||
1227
engines/avalanche/dialogs.cpp
Normal file
1227
engines/avalanche/dialogs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
118
engines/avalanche/dialogs.h
Normal file
118
engines/avalanche/dialogs.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* SCROLLS The scroll driver. */
|
||||
|
||||
#ifndef AVALANCHE_DIALOGS_H
|
||||
#define AVALANCHE_DIALOGS_H
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
class Dialogs;
|
||||
|
||||
typedef void (Dialogs::*DialogFunctionType)();
|
||||
|
||||
class Dialogs {
|
||||
public:
|
||||
bool _aboutBox; // Is this the about box? - Used in scrollModeNormal(), not yet fully implemented
|
||||
FontType _fonts[2];
|
||||
|
||||
Dialogs(AvalancheEngine *vm);
|
||||
|
||||
void init();
|
||||
void reset();
|
||||
void setReadyLight(byte state);
|
||||
void displayText(Common::String text);
|
||||
bool displayQuestion(Common::String question);
|
||||
void setTalkPos(int16 x, int16 y);
|
||||
int16 getTalkPosX();
|
||||
void setBubbleStateNatural();
|
||||
void displayMusicalScroll();
|
||||
void displayScrollChain(char block, byte point, bool report = true, bool bubbling = false);
|
||||
void talkTo(byte whom);
|
||||
void sayIt(Common::String str);
|
||||
Common::String personSpeaks();
|
||||
void sayThanks(byte thing);
|
||||
void sayHello();
|
||||
void sayOK();
|
||||
void saySilly();
|
||||
private:
|
||||
AvalancheEngine *_vm;
|
||||
int16 _talkX, _talkY;
|
||||
|
||||
enum FontStyle {
|
||||
kFontStyleRoman,
|
||||
kFontStyleItalic
|
||||
};
|
||||
|
||||
typedef int8 TuneType[31];
|
||||
|
||||
static const TuneType kTune;
|
||||
static const int16 kHalfIconWidth = 19;
|
||||
static const QuasipedType kQuasipeds[16];
|
||||
|
||||
Common::String _scroll[15];
|
||||
Common::Point _dodgeCoord;
|
||||
byte _maxLineNum;
|
||||
bool _scReturn;
|
||||
bool _noError;
|
||||
byte _currentFont;
|
||||
byte _param; // For using arguments code
|
||||
byte _useIcon;
|
||||
byte _scrollBells; // no. of times to ring the bell
|
||||
int16 _underScroll; // Y-coord of just under the scroll text.
|
||||
int16 _shadowBoxX, _shadowBoxY;
|
||||
|
||||
void drawBubble(DialogFunctionType modeFunc);
|
||||
void drawScroll(DialogFunctionType modeFunc);
|
||||
void scrollModeNormal();
|
||||
void scrollModeDialogue();
|
||||
void scrollModeMusic();
|
||||
|
||||
// These 2 are used only in musicalScroll().
|
||||
void store(byte what, TuneType &played);
|
||||
bool theyMatch(TuneType &played);
|
||||
void stripTrailingSpaces(Common::String &str);
|
||||
void solidify(byte n);
|
||||
void dodgem();
|
||||
void unDodgem();
|
||||
|
||||
Common::String displayMoney();
|
||||
void easterEgg();
|
||||
void say(int16 x, int16 y, Common::String text);
|
||||
void resetScrollDriver();
|
||||
void ringBell();
|
||||
void loadFont();
|
||||
|
||||
void unSkrimble(Common::String &text);
|
||||
void doTheBubble(Common::String &text);
|
||||
void speak(byte who, byte subject);
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_DIALOGS_H
|
||||
849
engines/avalanche/dropdown.cpp
Normal file
849
engines/avalanche/dropdown.cpp
Normal file
@@ -0,0 +1,849 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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: DROPDOWN A customized version of Oopmenu (qv). */
|
||||
|
||||
#include "avalanche/avalanche.h"
|
||||
#include "avalanche/dropdown.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
void HeadType::init(char trig, char altTrig, Common::String title, byte pos, MenuFunc setupFunc, MenuFunc chooseFunc, DropDownMenu *menu) {
|
||||
_trigger = trig;
|
||||
_altTrigger = altTrig;
|
||||
_title = title;
|
||||
_position = pos;
|
||||
_xpos = _position * _dropdown->kSpacing + _dropdown->kIndent;
|
||||
_xright = (_position + 1) * _dropdown->kSpacing + _dropdown->kIndent;
|
||||
_setupFunc = setupFunc;
|
||||
_chooseFunc = chooseFunc;
|
||||
|
||||
_dropdown = menu;
|
||||
}
|
||||
|
||||
void HeadType::draw() {
|
||||
CursorMan.showMouse(false);
|
||||
_dropdown->drawMenuText(_xpos, 1, _trigger, _title, true, false);
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
|
||||
void HeadType::highlight() {
|
||||
CursorMan.showMouse(false);
|
||||
|
||||
_dropdown->_vm->_sound->stopSound();
|
||||
_dropdown->drawMenuText(_xpos, 1, _trigger, _title, true, true);
|
||||
|
||||
_dropdown->_activeMenuItem._left = _xpos;
|
||||
_dropdown->_activeMenuItem._activeNow = true;
|
||||
_dropdown->_activeMenuItem._activeNum = _position;
|
||||
_dropdown->_menuActive = true;
|
||||
|
||||
// Force reload and redraw of cursor.
|
||||
_dropdown->_vm->_currentMouse = 177;
|
||||
|
||||
}
|
||||
|
||||
bool HeadType::parseAltTrigger(char key) {
|
||||
if (key != _altTrigger)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void MenuItem::init(DropDownMenu *menu) {
|
||||
_dropdown = menu;
|
||||
|
||||
_activeNow = false;
|
||||
_activeNum = 1;
|
||||
_dropdown->_menuActive = false;
|
||||
}
|
||||
|
||||
void MenuItem::reset() {
|
||||
_optionNum = 0;
|
||||
_width = 0;
|
||||
_firstlix = false;
|
||||
_oldY = 0;
|
||||
_highlightNum = 0;
|
||||
}
|
||||
|
||||
void MenuItem::setupOption(Common::String title, char trigger, Common::String shortcut, bool valid) {
|
||||
uint16 width = (title + shortcut).size() + 3;
|
||||
if (_width < width)
|
||||
_width = width;
|
||||
|
||||
_options[_optionNum]._title = title;
|
||||
_options[_optionNum]._trigger = trigger;
|
||||
_options[_optionNum]._shortcut = shortcut;
|
||||
_options[_optionNum]._valid = valid;
|
||||
_optionNum++;
|
||||
}
|
||||
|
||||
void MenuItem::displayOption(byte y, bool highlit) {
|
||||
Common::String text = _options[y]._title;
|
||||
while (text.size() + _options[y]._shortcut.size() < _width)
|
||||
text += ' '; // Pad _options[y] with spaces.
|
||||
text += _options[y]._shortcut;
|
||||
|
||||
Color backgroundColor;
|
||||
if (highlit)
|
||||
backgroundColor = kColorBlack;
|
||||
else
|
||||
backgroundColor = kColorLightgray;
|
||||
|
||||
_dropdown->_vm->_graphics->drawMenuBlock((_flx1 + 1) * 8, 3 + (y + 1) * 10, (_flx2 + 1) * 8, 13 + (y + 1) * 10, backgroundColor);
|
||||
_dropdown->drawMenuText(_left, 4 + (y + 1) * 10, _options[y]._trigger, text, _options[y]._valid, highlit);
|
||||
}
|
||||
|
||||
void MenuItem::display() {
|
||||
CursorMan.showMouse(false);
|
||||
|
||||
_firstlix = true;
|
||||
_flx1 = _left - 2;
|
||||
_flx2 = _left + _width;
|
||||
_fly = 15 + _optionNum * 10;
|
||||
_activeNow = true;
|
||||
_dropdown->_menuActive = true;
|
||||
|
||||
_dropdown->_vm->_graphics->drawMenuItem((_flx1 + 1) * 8, 12, (_flx2 + 1) * 8, _fly);
|
||||
|
||||
displayOption(0, true);
|
||||
for (int y = 1; y < _optionNum; y++)
|
||||
displayOption(y, false);
|
||||
|
||||
_dropdown->_vm->_currentMouse = 177;
|
||||
|
||||
CursorMan.showMouse(true); // 4 = fletch
|
||||
}
|
||||
|
||||
void MenuItem::wipe() {
|
||||
CursorMan.showMouse(false);
|
||||
|
||||
_dropdown->drawMenuText(_dropdown->_menuBar._menuItems[_dropdown->_activeMenuItem._activeNum]._xpos, 1,
|
||||
_dropdown->_menuBar._menuItems[_dropdown->_activeMenuItem._activeNum]._trigger,
|
||||
_dropdown->_menuBar._menuItems[_dropdown->_activeMenuItem._activeNum]._title, true, false);
|
||||
|
||||
_activeNow = false;
|
||||
_dropdown->_menuActive = false;
|
||||
_firstlix = false;
|
||||
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
|
||||
void MenuItem::moveHighlight(int8 inc) {
|
||||
if (inc != 0) {
|
||||
int8 highlightNum = _highlightNum + inc;
|
||||
if ((highlightNum < 0) || (highlightNum >= _optionNum))
|
||||
return;
|
||||
_highlightNum = highlightNum;
|
||||
}
|
||||
CursorMan.showMouse(false);
|
||||
displayOption(_oldY, false);
|
||||
displayOption(_highlightNum, true);
|
||||
_oldY = _highlightNum;
|
||||
CursorMan.showMouse(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This makes the menu highlight follow the mouse.
|
||||
* @remarks Originally called 'lightup'
|
||||
*/
|
||||
void MenuItem::lightUp(Common::Point cursorPos) {
|
||||
if ((cursorPos.x < _flx1 * 8) || (cursorPos.x > _flx2 * 8) || (cursorPos.y <= 25) || (cursorPos.y > ((_fly - 3) * 2 + 1)))
|
||||
return;
|
||||
_highlightNum = (cursorPos.y - 26) / 20;
|
||||
if (_highlightNum == _oldY)
|
||||
return;
|
||||
moveHighlight(0);
|
||||
}
|
||||
|
||||
void MenuItem::select(byte which) {
|
||||
if (!_options[which]._valid)
|
||||
return;
|
||||
|
||||
_choiceNum = which;
|
||||
wipe();
|
||||
|
||||
if (_choiceNum == _optionNum)
|
||||
_choiceNum--; // Off the bottom.
|
||||
if (_choiceNum > _optionNum)
|
||||
_choiceNum = 0; // Off the top, I suppose.
|
||||
|
||||
(_dropdown->*_dropdown->_menuBar._menuItems[_activeNum]._chooseFunc)();
|
||||
}
|
||||
|
||||
void MenuItem::parseKey(char c) {
|
||||
c = toupper(c);
|
||||
bool found = false;
|
||||
for (int i = 0; i < _optionNum; i++) {
|
||||
if ((toupper(_options[i]._trigger) == c) && _options[i]._valid) {
|
||||
select(i);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
_dropdown->_vm->_sound->blip();
|
||||
}
|
||||
|
||||
MenuBar::MenuBar() {
|
||||
_menuNum = 0;
|
||||
_dropdown = nullptr;
|
||||
}
|
||||
|
||||
void MenuBar::init(DropDownMenu *menu) {
|
||||
_dropdown = menu;
|
||||
_menuNum = 0;
|
||||
}
|
||||
|
||||
void MenuBar::createMenuItem(char trig, Common::String title, char altTrig, MenuFunc setupFunc, MenuFunc chooseFunc) {
|
||||
_menuItems[_menuNum].init(trig, altTrig, title, _menuNum, setupFunc, chooseFunc, _dropdown);
|
||||
_menuNum++;
|
||||
}
|
||||
|
||||
void MenuBar::draw() {
|
||||
_dropdown->_vm->_graphics->drawMenuBar(kMenuBackgroundColor);
|
||||
|
||||
byte savecp = _dropdown->_vm->_cp;
|
||||
_dropdown->_vm->_cp = 3;
|
||||
|
||||
for (int i = 0; i < _menuNum; i++)
|
||||
_menuItems[i].draw();
|
||||
|
||||
_dropdown->_vm->_cp = savecp;
|
||||
}
|
||||
|
||||
void MenuBar::parseAltTrigger(char c) {
|
||||
byte i = 0;
|
||||
while ((i < _menuNum) && (_menuItems[i].parseAltTrigger(c)))
|
||||
i++;
|
||||
if (i == _menuNum)
|
||||
return;
|
||||
setupMenuItem(i);
|
||||
}
|
||||
|
||||
void MenuBar::setupMenuItem(byte which) {
|
||||
if (_dropdown->_activeMenuItem._activeNow) {
|
||||
_dropdown->_activeMenuItem.wipe(); // Get rid of menu.
|
||||
if (_dropdown->_activeMenuItem._activeNum == _menuItems[which]._position)
|
||||
return; // Clicked on own highlight.
|
||||
}
|
||||
_menuItems[which].highlight();
|
||||
(_dropdown->*_menuItems[which]._setupFunc)();
|
||||
}
|
||||
|
||||
void MenuBar::chooseMenuItem(int16 x) {
|
||||
for (int i = 0; i < _menuNum; i++) {
|
||||
if ((x > _menuItems[i]._xpos * 8) && (x < _menuItems[i]._xright * 8)) {
|
||||
setupMenuItem(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DropDownMenu::DropDownMenu(AvalancheEngine *vm) {
|
||||
_vm = vm;
|
||||
_activeMenuItem.init(this);
|
||||
_menuBar.init(this);
|
||||
|
||||
_menuActive = false;
|
||||
_lastPerson = kPeopleNone;
|
||||
}
|
||||
|
||||
void DropDownMenu::findWhatYouCanDoWithIt() {
|
||||
switch (_vm->_thinks) {
|
||||
case kObjectWine:
|
||||
case kObjectPotion:
|
||||
case kObjectInk:
|
||||
_verbStr = Common::String(kVerbCodeExam) + kVerbCodeDrink;
|
||||
break;
|
||||
case kObjectBell:
|
||||
_verbStr = Common::String(kVerbCodeExam) + kVerbCodeRing;
|
||||
break;
|
||||
case kObjectClothes:
|
||||
case kObjectChastity:
|
||||
_verbStr = Common::String(kVerbCodeExam) + kVerbCodeWear;
|
||||
break;
|
||||
case kObjectLute:
|
||||
_verbStr = Common::String(kVerbCodeExam) + kVerbCodePlay;
|
||||
break;
|
||||
case kObjectMushroom:
|
||||
case kObjectOnion:
|
||||
_verbStr = Common::String(kVerbCodeExam) + kVerbCodeEat;
|
||||
break;
|
||||
default:
|
||||
_verbStr = kVerbCodeExam; // Anything else.
|
||||
}
|
||||
}
|
||||
|
||||
void DropDownMenu::drawMenuText(int16 x, int16 y, char trigger, Common::String text, bool valid, bool highlighted) {
|
||||
Color fontColor;
|
||||
Color backgroundColor;
|
||||
if (highlighted) {
|
||||
fontColor = kColorWhite;
|
||||
backgroundColor = kColorBlack;
|
||||
} else {
|
||||
fontColor = kColorBlack;
|
||||
backgroundColor = kColorLightgray;
|
||||
}
|
||||
|
||||
byte ander = valid ? 255 : 170;
|
||||
|
||||
FontType font;
|
||||
for (uint i = 0; i < text.size(); i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
byte idx = text[i];
|
||||
font[idx][j] = _vm->_font[idx][j] & ander; // Set the font.
|
||||
// And set the background of the text to the desired color.
|
||||
_vm->_graphics->wipeChar(x * 8 + i * 8, y + j, backgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_graphics->drawNormalText(text, font, 8, x * 8, y, fontColor);
|
||||
|
||||
// Underline the selected character.
|
||||
if ((trigger == 0) || !text.contains(trigger) )
|
||||
return;
|
||||
else {
|
||||
byte i;
|
||||
for (i = 0; text[i] != trigger; i++)
|
||||
; // Search for the character in the string.
|
||||
|
||||
_vm->_graphics->drawChar(ander, x * 8 + i * 8, y + 8, fontColor);
|
||||
}
|
||||
|
||||
_vm->_graphics->refreshScreen();
|
||||
}
|
||||
|
||||
void DropDownMenu::bleep() {
|
||||
_vm->_sound->playNote(177, 7);
|
||||
}
|
||||
|
||||
void DropDownMenu::parseKey(char r, char re) {
|
||||
#if 0
|
||||
switch (r) {
|
||||
case 0:
|
||||
case 224: {
|
||||
switch (re) {
|
||||
case 'K':
|
||||
if (_activeMenuItem._activeNum > 1) {
|
||||
_activeMenuItem.wipe();
|
||||
_menuBar.setupMenuItem(_activeMenuItem._activeNum - 1);
|
||||
} else {
|
||||
// Get menu on the left-hand side.
|
||||
_activeMenuItem.wipe();
|
||||
_menuBar.chooseMenuItem((_menuBar._menuNum - 1) * kSpacing + kIndent);
|
||||
}
|
||||
break;
|
||||
case 'M':
|
||||
if (_activeMenuItem._activeNum < _menuBar._menuNum) {
|
||||
_activeMenuItem.wipe();
|
||||
_menuBar.setupMenuItem(_activeMenuItem._activeNum + 1);
|
||||
} else {
|
||||
// Get menu on the far right-hand side.
|
||||
_activeMenuItem.wipe();
|
||||
_menuBar.chooseMenuItem(kIndent);
|
||||
}
|
||||
break;
|
||||
case 'H':
|
||||
_activeMenuItem.moveHighlight(-1);
|
||||
break;
|
||||
case 'P':
|
||||
_activeMenuItem.moveHighlight(1);
|
||||
break;
|
||||
default:
|
||||
_menuBar.parseAltTrigger(re);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
_activeMenuItem.select(_activeMenuItem._highlightNum);
|
||||
break;
|
||||
default:
|
||||
if (_activeMenuItem._activeNow)
|
||||
_activeMenuItem.parseKey(r);
|
||||
}
|
||||
#endif
|
||||
|
||||
warning("STUB: Dropdown::parseKey()"); // To be implemented properly later! Don't remove the comment above!
|
||||
}
|
||||
|
||||
Common::String DropDownMenu::selectGender(byte x) {
|
||||
if (x < 175)
|
||||
return "im";
|
||||
else
|
||||
return "er";
|
||||
}
|
||||
|
||||
void DropDownMenu::setupMenuGame() {
|
||||
_activeMenuItem.reset();
|
||||
_activeMenuItem.setupOption("Help...", 'H', "f1", true);
|
||||
_activeMenuItem.setupOption("Boss Key", 'B', "alt-B", true);
|
||||
_activeMenuItem.setupOption("Untrash screen", 'U', "ctrl-f7", false);
|
||||
_activeMenuItem.setupOption("Score and rank", 'S', "f9", true);
|
||||
_activeMenuItem.setupOption("About Avvy...", 'A', "shift-f10", true);
|
||||
_activeMenuItem.display();
|
||||
}
|
||||
|
||||
void DropDownMenu::setupMenuFile() {
|
||||
_activeMenuItem.reset();
|
||||
_activeMenuItem.setupOption("New game", 'N', "f4", true);
|
||||
_activeMenuItem.setupOption("Load...", 'L', "^f3", true);
|
||||
_activeMenuItem.setupOption("Save", 'S', "^f2", _vm->_alive);
|
||||
_activeMenuItem.setupOption("Save As...", 'v', "", _vm->_alive);
|
||||
_activeMenuItem.setupOption("DOS Shell", 'D', "alt-1", false);
|
||||
_activeMenuItem.setupOption("Quit", 'Q', "alt-X", true);
|
||||
_activeMenuItem.display();
|
||||
}
|
||||
|
||||
void DropDownMenu::setupMenuAction() {
|
||||
_activeMenuItem.reset();
|
||||
|
||||
Common::String f5Does = _vm->f5Does();
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (!f5Does.empty())
|
||||
f5Does.deleteChar(0);
|
||||
if (f5Does.empty())
|
||||
_activeMenuItem.setupOption("Do something", 'D', "f5", false);
|
||||
else
|
||||
_activeMenuItem.setupOption(f5Does, f5Does[0], "f5", true);
|
||||
_activeMenuItem.setupOption("Pause game", 'P', "f6", true);
|
||||
if (_vm->_room == kRoomMap)
|
||||
_activeMenuItem.setupOption("Journey thither", 'J', "f7", _vm->_animation->nearDoor());
|
||||
else
|
||||
_activeMenuItem.setupOption("Open the door", 'O', "f7", _vm->_animation->nearDoor());
|
||||
_activeMenuItem.setupOption("Look around", 'L', "f8", true);
|
||||
_activeMenuItem.setupOption("Inventory", 'I', "Tab", true);
|
||||
if (_vm->_animation->_sprites[0]->_speedX == kWalk)
|
||||
_activeMenuItem.setupOption("Run fast", 'R', "^R", true);
|
||||
else
|
||||
_activeMenuItem.setupOption("Walk slowly", 'W', "^W", true);
|
||||
|
||||
_activeMenuItem.display();
|
||||
}
|
||||
|
||||
void DropDownMenu::setupMenuPeople() {
|
||||
if (!people.empty())
|
||||
people.clear();
|
||||
|
||||
_activeMenuItem.reset();
|
||||
|
||||
for (int i = kPeopleAvalot; i <= kPeopleWisewoman; i++) {
|
||||
if (_vm->getRoom((People)i) == _vm->_room) {
|
||||
_activeMenuItem.setupOption(_vm->getName((People)i), getNameChar((People)i), "", true);
|
||||
people += i;
|
||||
}
|
||||
}
|
||||
|
||||
_activeMenuItem.display();
|
||||
}
|
||||
|
||||
void DropDownMenu::setupMenuObjects() {
|
||||
_activeMenuItem.reset();
|
||||
for (int i = 0; i < kObjectNum; i++) {
|
||||
if (_vm->_objects[i])
|
||||
_activeMenuItem.setupOption(getThing(i + 1), getThingChar(i + 1), "", true);
|
||||
}
|
||||
_activeMenuItem.display();
|
||||
}
|
||||
|
||||
void DropDownMenu::setupMenuWith() {
|
||||
_activeMenuItem.reset();
|
||||
|
||||
if (_vm->_thinkThing) {
|
||||
findWhatYouCanDoWithIt();
|
||||
|
||||
for (uint i = 0; i < _verbStr.size(); i++) {
|
||||
char vbchar;
|
||||
Common::String verb;
|
||||
|
||||
_vm->_parser->verbOpt(_verbStr[i], verb, vbchar);
|
||||
_activeMenuItem.setupOption(verb, vbchar, "", true);
|
||||
}
|
||||
|
||||
// We disable the "give" option if: (a), you haven't selected anybody, (b), the _person you've selected isn't in the room,
|
||||
// or (c), the _person you've selected is YOU!
|
||||
|
||||
if ((_lastPerson == kPeopleAvalot) || (_lastPerson == _vm->_parser->kNothing)
|
||||
|| (_vm->getRoom(_lastPerson) != _vm->_room))
|
||||
_activeMenuItem.setupOption("Give to...", 'G', "", false); // Not here.
|
||||
else {
|
||||
_activeMenuItem.setupOption(Common::String("Give to ") + _vm->getName(_lastPerson), 'G', "", true);
|
||||
_verbStr = _verbStr + kVerbCodeGive;
|
||||
}
|
||||
} else {
|
||||
_activeMenuItem.setupOption("Examine", 'x', "", true);
|
||||
_activeMenuItem.setupOption(Common::String("Talk to h") + selectGender(_vm->_thinks), 'T', "", true);
|
||||
_verbStr = Common::String(kVerbCodeExam) + kVerbCodeTalk;
|
||||
switch (_vm->_thinks) {
|
||||
case kPeopleGeida:
|
||||
case kPeopleArkata:
|
||||
_activeMenuItem.setupOption("Kiss her", 'K', "", true);
|
||||
_verbStr = _verbStr + kVerbCodeKiss;
|
||||
break;
|
||||
case kPeopleDogfood:
|
||||
_activeMenuItem.setupOption("Play his game", 'P', "", !_vm->_wonNim); // True if you HAVEN'T won.
|
||||
_verbStr = _verbStr + kVerbCodePlay;
|
||||
break;
|
||||
case kPeopleMalagauche: {
|
||||
bool isSober = !_vm->_teetotal;
|
||||
_activeMenuItem.setupOption("Buy some wine", 'w', "", !_vm->_objects[kObjectWine - 1]);
|
||||
_activeMenuItem.setupOption("Buy some beer", 'b', "", isSober);
|
||||
_activeMenuItem.setupOption("Buy some whisky", 'h', "", isSober);
|
||||
_activeMenuItem.setupOption("Buy some cider", 'c', "", isSober);
|
||||
_activeMenuItem.setupOption("Buy some mead", 'm', "", isSober);
|
||||
_verbStr = _verbStr + 101 + 100 + 102 + 103 + 104;
|
||||
}
|
||||
break;
|
||||
case kPeopleTrader:
|
||||
_activeMenuItem.setupOption("Buy an onion", 'o', "", !_vm->_objects[kObjectOnion - 1]);
|
||||
_verbStr = _verbStr + 105;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
_activeMenuItem.display();
|
||||
}
|
||||
|
||||
void DropDownMenu::runMenuGame() {
|
||||
// Help, boss, untrash screen.
|
||||
switch (_activeMenuItem._choiceNum) {
|
||||
case 0:
|
||||
_vm->callVerb(kVerbCodeHelp);
|
||||
break;
|
||||
case 1:
|
||||
_vm->callVerb(kVerbCodeBoss);
|
||||
break;
|
||||
case 2:
|
||||
_vm->_graphics->refreshScreen();
|
||||
break;
|
||||
case 3:
|
||||
_vm->callVerb(kVerbCodeScore);
|
||||
break;
|
||||
case 4:
|
||||
_vm->callVerb(kVerbCodeInfo);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DropDownMenu::runMenuFile() {
|
||||
// New game, load, save, save as, DOS shell, about, quit.
|
||||
switch (_activeMenuItem._choiceNum) {
|
||||
case 0:
|
||||
_vm->callVerb(kVerbCodeRestart);
|
||||
break;
|
||||
case 1:
|
||||
if (!_vm->_parser->_realWords[1].empty())
|
||||
_vm->_parser->_realWords[1].clear();
|
||||
_vm->callVerb(kVerbCodeLoad);
|
||||
break;
|
||||
// Case 2 is 'Save', Case 3 is 'Save As'. Both triggers ScummVM save screen.
|
||||
case 2:
|
||||
case 3:
|
||||
if (!_vm->_parser->_realWords[1].empty())
|
||||
_vm->_parser->_realWords[1].clear();
|
||||
_vm->callVerb(kVerbCodeSave);
|
||||
break;
|
||||
case 4:
|
||||
// Command Prompt, disabled
|
||||
break;
|
||||
case 5:
|
||||
_vm->callVerb(kVerbCodeQuit);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DropDownMenu::runMenuAction() {
|
||||
// Get up, pause game, open door, look, inventory, walk/run.
|
||||
switch (_activeMenuItem._choiceNum) {
|
||||
case 0: {
|
||||
_vm->_parser->_person = kPeoplePardon;
|
||||
_vm->_parser->_thing = _vm->_parser->kPardon;
|
||||
Common::String f5Does = _vm->f5Does();
|
||||
VerbCode verb = (VerbCode)(byte)f5Does[0];
|
||||
_vm->callVerb(verb);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
_vm->_parser->_thing = _vm->_parser->kPardon;
|
||||
_vm->callVerb(kVerbCodePause);
|
||||
break;
|
||||
case 2:
|
||||
_vm->callVerb(kVerbCodeOpen);
|
||||
break;
|
||||
case 3:
|
||||
_vm->_parser->_thing = _vm->_parser->kPardon;
|
||||
_vm->callVerb(kVerbCodeLook);
|
||||
break;
|
||||
case 4:
|
||||
_vm->callVerb(kVerbCodeInv);
|
||||
break;
|
||||
case 5: {
|
||||
AnimationType *avvy = _vm->_animation->_sprites[0];
|
||||
if (avvy->_speedX == kWalk)
|
||||
avvy->_speedX = kRun;
|
||||
else
|
||||
avvy->_speedX = kWalk;
|
||||
_vm->_animation->updateSpeed();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DropDownMenu::runMenuObjects() {
|
||||
_vm->thinkAbout(_vm->_objectList[_activeMenuItem._choiceNum], AvalancheEngine::kThing);
|
||||
}
|
||||
|
||||
void DropDownMenu::runMenuPeople() {
|
||||
_vm->thinkAbout(people[_activeMenuItem._choiceNum], AvalancheEngine::kPerson);
|
||||
_lastPerson = (People)people[_activeMenuItem._choiceNum];
|
||||
}
|
||||
|
||||
void DropDownMenu::runMenuWith() {
|
||||
_vm->_parser->_thing = _vm->_thinks;
|
||||
|
||||
if (_vm->_thinkThing) {
|
||||
_vm->_parser->_thing += 49;
|
||||
|
||||
if (_verbStr[_activeMenuItem._choiceNum] == kVerbCodeGive)
|
||||
_vm->_parser->_person = _lastPerson;
|
||||
else
|
||||
_vm->_parser->_person = kPeoplePardon;
|
||||
} else {
|
||||
switch (_verbStr[_activeMenuItem._choiceNum]) {
|
||||
case 100: // Beer
|
||||
case 102: // Whisky
|
||||
case 103: // Cider
|
||||
_vm->_parser->_thing = _verbStr[_activeMenuItem._choiceNum];
|
||||
_vm->callVerb(kVerbCodeBuy);
|
||||
return;
|
||||
case 101: // Wine
|
||||
_vm->_parser->_thing = 50;
|
||||
_vm->callVerb(kVerbCodeBuy);
|
||||
return;
|
||||
case 104: // Mead
|
||||
_vm->_parser->_thing = 107;
|
||||
_vm->callVerb(kVerbCodeBuy);
|
||||
return;
|
||||
case 105: // Onion (trader)
|
||||
_vm->_parser->_thing = 67;
|
||||
_vm->callVerb(kVerbCodeBuy);
|
||||
return;
|
||||
default:
|
||||
_vm->_parser->_person = (People)_vm->_parser->_thing;
|
||||
_vm->_parser->_thing = Parser::kPardon;
|
||||
_vm->_subjectNum = 0;
|
||||
}
|
||||
}
|
||||
_vm->callVerb((VerbCode)(byte)_verbStr[_activeMenuItem._choiceNum]);
|
||||
}
|
||||
|
||||
void DropDownMenu::setup() {
|
||||
_menuBar.init(this);
|
||||
_activeMenuItem.init(this);
|
||||
|
||||
_menuBar.createMenuItem('F', "File", '!', &Avalanche::DropDownMenu::setupMenuFile, &Avalanche::DropDownMenu::runMenuFile);
|
||||
_menuBar.createMenuItem('G', "Game", 34, &Avalanche::DropDownMenu::setupMenuGame, &Avalanche::DropDownMenu::runMenuGame);
|
||||
_menuBar.createMenuItem('A', "Action", 30, &Avalanche::DropDownMenu::setupMenuAction, &Avalanche::DropDownMenu::runMenuAction);
|
||||
_menuBar.createMenuItem('O', "Objects", 24, &Avalanche::DropDownMenu::setupMenuObjects, &Avalanche::DropDownMenu::runMenuObjects);
|
||||
_menuBar.createMenuItem('P', "People", 25, &Avalanche::DropDownMenu::setupMenuPeople, &Avalanche::DropDownMenu::runMenuPeople);
|
||||
_menuBar.createMenuItem('W', "With", 17, &Avalanche::DropDownMenu::setupMenuWith, &Avalanche::DropDownMenu::runMenuWith);
|
||||
|
||||
_menuBar.draw();
|
||||
}
|
||||
|
||||
void DropDownMenu::update() {
|
||||
_vm->_graphics->saveScreen();
|
||||
|
||||
Common::Point cursorPos = _vm->getMousePos();
|
||||
while (!_activeMenuItem._activeNow && (cursorPos.y <= 21) && _vm->_holdLeftMouse) {
|
||||
_menuBar.chooseMenuItem(cursorPos.x);
|
||||
do {
|
||||
_vm->updateEvents();
|
||||
} while (_vm->_holdLeftMouse && !_vm->shouldQuit());
|
||||
|
||||
while (!_vm->shouldQuit()) {
|
||||
do {
|
||||
_vm->updateEvents();
|
||||
|
||||
// We update the cursor's picture.
|
||||
cursorPos = _vm->getMousePos();
|
||||
// Change arrow...
|
||||
if ((0 <= cursorPos.y) && (cursorPos.y <= 21))
|
||||
_vm->_graphics->loadMouse(kCurUpArrow); // Up arrow
|
||||
else if ((22 <= cursorPos.y) && (cursorPos.y <= 339)) {
|
||||
if ((cursorPos.x >= _activeMenuItem._flx1 * 8) && (cursorPos.x <= _activeMenuItem._flx2 * 8) && (cursorPos.y <= _activeMenuItem._fly * 2 + 1))
|
||||
_vm->_graphics->loadMouse(kCurRightArrow); // Right-arrow
|
||||
else
|
||||
_vm->_graphics->loadMouse(kCurFletch); // Fletch
|
||||
} else if ((340 <= cursorPos.y) && (cursorPos.y <= 399))
|
||||
_vm->_graphics->loadMouse(kCurScrewDriver); // Screwdriver
|
||||
|
||||
_activeMenuItem.lightUp(cursorPos);
|
||||
|
||||
_vm->_graphics->refreshScreen();
|
||||
} while (!_vm->_holdLeftMouse && !_vm->shouldQuit());
|
||||
|
||||
if (_vm->_holdLeftMouse) {
|
||||
if (cursorPos.y > 21) {
|
||||
if (!((_activeMenuItem._firstlix) && ((cursorPos.x >= _activeMenuItem._flx1 * 8) && (cursorPos.x <= _activeMenuItem._flx2 * 8)
|
||||
&& (cursorPos.y >= 24) && (cursorPos.y <= (_activeMenuItem._fly * 2 + 1))))) {
|
||||
// Clicked OUTSIDE the menu.
|
||||
if (_activeMenuItem._activeNow) {
|
||||
_activeMenuItem.wipe();
|
||||
_vm->_holdLeftMouse = false;
|
||||
_vm->_graphics->removeBackup();
|
||||
return;
|
||||
} // No "else"- clicking on menu has no effect (only releasing).
|
||||
}
|
||||
} else {
|
||||
// Clicked on menu bar.
|
||||
if (_activeMenuItem._activeNow) {
|
||||
_activeMenuItem.wipe();
|
||||
_vm->_graphics->restoreScreen();
|
||||
|
||||
if (((_activeMenuItem._left * 8) <= cursorPos.x) && (cursorPos.x <= (_activeMenuItem._left * 8 + 80))) { // 80: the width of one menu item on the bar in pixels.
|
||||
// If we clicked on the same menu item (the one that is already active) on the bar...
|
||||
_vm->_holdLeftMouse = false;
|
||||
_vm->_graphics->removeBackup();
|
||||
return;
|
||||
} else {
|
||||
_vm->_holdLeftMouse = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOT clicked button...
|
||||
if ((_activeMenuItem._firstlix) && ((cursorPos.x >= _activeMenuItem._flx1 * 8) && (cursorPos.x <= _activeMenuItem._flx2 * 8)
|
||||
&& (cursorPos.y >= 12) && (cursorPos.y <= (_activeMenuItem._fly * 2 + 1)))) {
|
||||
|
||||
// We act only if the button is released over a menu item.
|
||||
while (!_vm->shouldQuit()) {
|
||||
cursorPos = _vm->getMousePos();
|
||||
_activeMenuItem.lightUp(cursorPos);
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
_vm->updateEvents();
|
||||
if (!_vm->_holdLeftMouse)
|
||||
break;
|
||||
}
|
||||
|
||||
uint16 which = (cursorPos.y - 26) / 20;
|
||||
_activeMenuItem.select(which);
|
||||
if (_activeMenuItem._options[which]._valid) { // If the menu item wasn't active, we do nothing.
|
||||
_vm->_graphics->removeBackup();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_graphics->removeBackup();
|
||||
}
|
||||
|
||||
char DropDownMenu::getThingChar(byte which) {
|
||||
static const char thingsChar[] = "WMBParCLguKeSnIohn"; // V=Vinegar
|
||||
|
||||
char result;
|
||||
switch (which) {
|
||||
case kObjectWine:
|
||||
if (_vm->_wineState == 3)
|
||||
result = 'V'; // Vinegar
|
||||
else
|
||||
result = thingsChar[which - 1];
|
||||
break;
|
||||
default:
|
||||
result = thingsChar[which - 1];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
byte DropDownMenu::getNameChar(People whose) {
|
||||
static const char ladChar[] = "ASCDMTRwLfgeIyPu";
|
||||
static const char lassChar[] = "kG\xB1o";
|
||||
|
||||
if (whose <= kPeopleJacques)
|
||||
return ladChar[whose - kPeopleAvalot];
|
||||
else if ((whose >= kPeopleArkata) && (whose <= kPeopleWisewoman))
|
||||
return lassChar[whose - kPeopleArkata];
|
||||
else
|
||||
error("getName() - Unexpected character id %d", (byte) whose);
|
||||
}
|
||||
|
||||
Common::String DropDownMenu::getThing(byte which) {
|
||||
static const char things[kObjectNum][20] = {
|
||||
"Wine", "Money-bag", "Bodkin", "Potion", "Chastity belt",
|
||||
"Crossbow bolt", "Crossbow", "Lute", "Pilgrim's badge", "Mushroom", "Key",
|
||||
"Bell", "Scroll", "Pen", "Ink", "Clothes", "Habit", "Onion"
|
||||
};
|
||||
|
||||
Common::String result;
|
||||
switch (which) {
|
||||
case kObjectWine:
|
||||
switch (_vm->_wineState) {
|
||||
case 1:
|
||||
case 4:
|
||||
result = Common::String(things[which - 1]);
|
||||
break;
|
||||
case 3:
|
||||
result = "Vinegar";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case kObjectOnion:
|
||||
if (_vm->_rottenOnion) {
|
||||
result = Common::String("rotten onion");
|
||||
} else {
|
||||
result = Common::String(things[which - 1]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = Common::String(things[which - 1]);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DropDownMenu::isActive() {
|
||||
return _menuActive;
|
||||
}
|
||||
|
||||
void DropDownMenu::init() {
|
||||
_menuActive = false;
|
||||
}
|
||||
|
||||
void DropDownMenu::resetVariables() {
|
||||
_lastPerson = kPeoplePardon;
|
||||
}
|
||||
} // End of namespace Avalanche.
|
||||
181
engines/avalanche/dropdown.h
Normal file
181
engines/avalanche/dropdown.h
Normal file
@@ -0,0 +1,181 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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: DROPDOWN A customized version of Oopmenu (qv). */
|
||||
|
||||
#ifndef AVALANCHE_DROPDOWN_H
|
||||
#define AVALANCHE_DROPDOWN_H
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
class DropDownMenu;
|
||||
|
||||
typedef void (DropDownMenu::*MenuFunc)();
|
||||
static const Color kMenuBackgroundColor = kColorLightgray;
|
||||
static const Color kMenuBorderColor = kColorBlack;
|
||||
|
||||
class HeadType {
|
||||
public:
|
||||
Common::String _title;
|
||||
char _trigger, _altTrigger;
|
||||
byte _position;
|
||||
int16 _xpos, _xright;
|
||||
MenuFunc _setupFunc, _chooseFunc;
|
||||
|
||||
void init(char trig, char alTtrig, Common::String title, byte pos, MenuFunc setupFunc, MenuFunc chooseFunc, DropDownMenu *menu);
|
||||
void draw();
|
||||
void highlight();
|
||||
bool parseAltTrigger(char key);
|
||||
|
||||
private:
|
||||
DropDownMenu *_dropdown;
|
||||
};
|
||||
|
||||
struct OptionType {
|
||||
Common::String _title;
|
||||
byte _trigger;
|
||||
Common::String _shortcut;
|
||||
bool _valid;
|
||||
};
|
||||
|
||||
class MenuItem {
|
||||
public:
|
||||
OptionType _options[12];
|
||||
uint16 _width, _left;
|
||||
bool _firstlix;
|
||||
int16 _flx1, _flx2, _fly;
|
||||
bool _activeNow; // Is there an active option now?
|
||||
byte _activeNum; // And if so, which is it?
|
||||
byte _choiceNum; // Your choice?
|
||||
|
||||
void init(DropDownMenu *menu);
|
||||
void reset();
|
||||
void setupOption(Common::String title, char trigger, Common::String shortcut, bool valid);
|
||||
void display();
|
||||
void wipe();
|
||||
void lightUp(Common::Point cursorPos);
|
||||
void select(byte which);
|
||||
|
||||
private:
|
||||
byte _oldY; // used by lightUp
|
||||
byte _optionNum;
|
||||
byte _highlightNum;
|
||||
|
||||
DropDownMenu *_dropdown;
|
||||
|
||||
void displayOption(byte y, bool highlit);
|
||||
void moveHighlight(int8 inc);
|
||||
|
||||
// CHECKME: Useless function?
|
||||
void parseKey(char c);
|
||||
};
|
||||
|
||||
class MenuBar {
|
||||
public:
|
||||
HeadType _menuItems[8];
|
||||
byte _menuNum;
|
||||
|
||||
MenuBar();
|
||||
void init(DropDownMenu *menu);
|
||||
void createMenuItem(char trig, Common::String title, char altTrig, MenuFunc setupFunc, MenuFunc chooseFunc);
|
||||
void draw();
|
||||
void chooseMenuItem(int16 x);
|
||||
|
||||
private:
|
||||
DropDownMenu *_dropdown;
|
||||
|
||||
void setupMenuItem(byte which);
|
||||
// CHECKME: Useless function
|
||||
void parseAltTrigger(char c);
|
||||
};
|
||||
|
||||
class DropDownMenu {
|
||||
public:
|
||||
friend class HeadType;
|
||||
friend class MenuItem;
|
||||
friend class MenuBar;
|
||||
|
||||
MenuItem _activeMenuItem;
|
||||
MenuBar _menuBar;
|
||||
|
||||
DropDownMenu(AvalancheEngine *vm);
|
||||
|
||||
void update();
|
||||
void setup(); // Standard menu bar.
|
||||
bool isActive();
|
||||
void init();
|
||||
void resetVariables();
|
||||
|
||||
private:
|
||||
static const byte kIndent = 5;
|
||||
static const byte kSpacing = 10;
|
||||
|
||||
// Checkme: Useless constants?
|
||||
// static const Color kMenuFontColor = kColorBlack;
|
||||
// static const Color kHighlightBackgroundColor = kColorBlack;
|
||||
// static const Color kHighlightFontColor = kColorWhite;
|
||||
// static const Color kDisabledColor = kColorDarkgray;
|
||||
|
||||
Common::String people;
|
||||
Common::String _verbStr; // what you can do with your object. :-)
|
||||
bool _menuActive; // Kludge so we don't have to keep referring to the menu.
|
||||
People _lastPerson; // Last person to have been selected using the People menu.
|
||||
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
Common::String selectGender(byte x); // Returns "im" for boys, and "er" for girls.
|
||||
void findWhatYouCanDoWithIt();
|
||||
void drawMenuText(int16 x, int16 y, char trigger, Common::String text, bool valid, bool highlighted);
|
||||
void bleep();
|
||||
|
||||
char getThingChar(byte which);
|
||||
byte getNameChar(People whose);
|
||||
Common::String getThing(byte which);
|
||||
|
||||
void setupMenuGame();
|
||||
void setupMenuFile();
|
||||
void setupMenuAction();
|
||||
void setupMenuPeople();
|
||||
void setupMenuObjects();
|
||||
void setupMenuWith();
|
||||
|
||||
void runMenuGame();
|
||||
void runMenuFile();
|
||||
void runMenuAction();
|
||||
void runMenuObjects();
|
||||
void runMenuPeople();
|
||||
void runMenuWith();
|
||||
|
||||
// CHECKME: Useless function?
|
||||
void parseKey(char r, char re);
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche.
|
||||
|
||||
#endif // AVALANCHE_DROPDOWN_H
|
||||
136
engines/avalanche/enums.h
Normal file
136
engines/avalanche/enums.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AVALANCHE_ENUMS_H
|
||||
#define AVALANCHE_ENUMS_H
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
enum MonsterType { kMonsterTypeGhost, kMonsterTypeGlerk };
|
||||
|
||||
enum Flavour { kFlavourEga, kFlavourBgi, kFlavourNatural, kFlavourTwo, kFlavourOne };
|
||||
|
||||
enum Color {
|
||||
kColorBlack = 0, kColorBlue, kColorGreen, kColorCyan, kColorRed,
|
||||
kColorMagenta = 5, kColorBrown, kColorLightgray, kColorDarkgray, kColorLightblue,
|
||||
kColorLightgreen = 10, kColorLightcyan, kColorLightred, kColorLightmagenta, kColorYellow,
|
||||
kColorWhite = 15
|
||||
};
|
||||
|
||||
// CHECKME: kRoomBossKey is a guess
|
||||
enum Room {
|
||||
kRoomNowhere = 0, kRoomYours = 1, kRoomOutsideYours = 2, kRoomOutsideSpludwicks = 3,
|
||||
kRoomYourHall = 5, kRoomMusicRoom = 7, kRoomOutsideArgentPub = 9, kRoomArgentRoad = 10,
|
||||
kRoomWiseWomans = 11, kRoomSpludwicks = 12, kRoomInsideAbbey = 13, kRoomOutsideAbbey = 14,
|
||||
kRoomAvvysGarden = 15, kRoomAylesOffice = 16, kRoomArgentPub = 19, kRoomBrummieRoad = 20,
|
||||
kRoomBridge = 21, kRoomLusties = 22, kRoomLustiesRoom = 23, kRoomWestHall = 25,
|
||||
kRoomEastHall = 26, kRoomOubliette = 27, kRoomGeidas = 28, kRoomCatacombs = 29,
|
||||
kRoomEntranceHall = 40, kRoomRobins = 42, kRoomOutsideNottsPub = 46, kRoomNottsPub = 47,
|
||||
kRoomOutsideDucks = 50, kRoomDucks = 51, kRoomOutsideCardiffCastle = 70, kRoomInsideCardiffCastle = 71,
|
||||
kRoomBossKey = 98, kRoomMap = 99, kRoomDummy = 177 // Dummy room
|
||||
};
|
||||
|
||||
// Objects you can hold:
|
||||
enum Object {
|
||||
kObjectWine = 1, kObjectMoney, kObjectBodkin, kObjectPotion, kObjectChastity,
|
||||
kObjectBolt, kObjectCrossbow, kObjectLute, kObjectBadge, kObjectMushroom,
|
||||
kObjectKey, kObjectBell, kObjectPrescription, kObjectPen, kObjectInk,
|
||||
kObjectClothes, kObjectHabit, kObjectOnion, kObjectDummy = 177
|
||||
};
|
||||
|
||||
// People who hang around this game.
|
||||
enum People {
|
||||
// Boys:
|
||||
kPeopleAvalot = 150, kPeopleSpludwick = 151, kPeopleCrapulus = 152, kPeopleDrDuck = 153,
|
||||
kPeopleMalagauche = 154, kPeopleFriarTuck = 155, kPeopleRobinHood = 156, kPeopleCwytalot = 157,
|
||||
kPeopleDuLustie = 158, kPeopleDuke = 159, kPeopleDogfood = 160, kPeopleTrader = 161,
|
||||
kPeopleIbythneth = 162, kPeopleAyles = 163, kPeoplePort = 164, kPeopleSpurge = 165,
|
||||
kPeopleJacques = 166,
|
||||
// Girls:
|
||||
kPeopleArkata = 175, kPeopleGeida = 176, kPeopleInvisible = 177, kPeopleWisewoman = 178,
|
||||
//
|
||||
kPeoplePardon = 254, kPeopleNone = 0
|
||||
};
|
||||
|
||||
enum VerbCode {
|
||||
kVerbCodeExam = 1, kVerbCodeOpen = 2, kVerbCodePause = 3, kVerbCodeGet = 4, kVerbCodeDrop = 5,
|
||||
kVerbCodeInv = 6, kVerbCodeTalk = 7, kVerbCodeGive = 8, kVerbCodeDrink = 9, kVerbCodeLoad = 10,
|
||||
kVerbCodeSave = 11, kVerbCodePay = 12, kVerbCodeLook = 13, kVerbCodeBreak = 14, kVerbCodeQuit = 15,
|
||||
kVerbCodeSit = 16, kVerbCodeStand = 17, kVerbCodeGo = 18, kVerbCodeInfo = 19, kVerbCodeUndress = 20,
|
||||
kVerbCodeWear = 21, kVerbCodePlay = 22, kVerbCodeRing = 23, kVerbCodeHelp = 24, kVerbCodeLarrypass = 25,
|
||||
kVerbCodePhaon = 26, kVerbCodeBoss = 27, kVerbCodePee = 28, kVerbCodeCheat = 29, kVerbCodeMagic = 30,
|
||||
kVerbCodeRestart = 31, kVerbCodeEat = 32, kVerbCodeListen = 33, kVerbCodeBuy = 34, kVerbCodeAttack = 35,
|
||||
kVerbCodePasswd = 36, kVerbCodeDir = 37, kVerbCodeDie = 38, kVerbCodeScore = 39, kVerbCodePut = 40,
|
||||
kVerbCodeKiss = 41, kVerbCodeClimb = 42, kVerbCodeJump = 43, kVerbCodeHiscores = 44, kVerbCodeWake = 45,
|
||||
kVerbCodeHello = 46, kVerbCodeThanks = 47,
|
||||
kVerbCodeSmartAlec = 249, kVerbCodeExpletive = 253, kVerbCodePardon = 254
|
||||
};
|
||||
|
||||
enum MouseCursor {
|
||||
kCurUpArrow = 0, kCurScrewDriver = 1, kCurRightArrow = 2, kCurFletch = 3, kCurWait = 4, kCurHand = 5,
|
||||
kCurCrosshair = 6, kCurIBeam = 7, kCurHelp = 8
|
||||
};
|
||||
|
||||
// Magic/portal constants:
|
||||
enum Magics {
|
||||
kMagicNothing, // Ignore it if this line is touched.
|
||||
kMagicBounce, // Bounce off this line. Not valid for portals.
|
||||
kMagicExclaim, // Put up a chain of scrolls.
|
||||
kMagicTransport, // Enter new room.
|
||||
kMagicUnfinished, // Unfinished connection.
|
||||
kMagicSpecial, // Special function.
|
||||
kMagicOpenDoor // Opening door.
|
||||
};
|
||||
|
||||
// Constants to replace the command characters from Pascal.
|
||||
// For more information, see: https://github.com/marnanel/avalot/wiki/Scrolldrivers
|
||||
enum ControlCharacter {
|
||||
kControlSpeechBubble = 2, // ^B
|
||||
kControlCenter = 3, // ^C
|
||||
kControlToBuffer = 4, // ^D
|
||||
kControlItalic = 6, // ^F
|
||||
kControlBell = 7, // ^G
|
||||
kControlBackspace = 8, // ^H
|
||||
kControlInsertSpaces = 9, // ^I
|
||||
kControlLeftJustified = 12, // ^L
|
||||
kControlNewLine = 13, // ^M
|
||||
kControlParagraph = 16, // ^P
|
||||
kControlQuestion = 17, // ^Q
|
||||
kControlRoman = 18, // ^R
|
||||
kControlRegister = 19, // ^S
|
||||
kControlNegative = 21, // ^U
|
||||
kControlIcon = 22 // ^V
|
||||
};
|
||||
|
||||
static const int16 kScreenWidth = 640;
|
||||
static const int16 kScreenHeight = 200;
|
||||
|
||||
static const int16 kWalk = 3;
|
||||
static const int16 kRun = 5;
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_ENUMS_H
|
||||
398
engines/avalanche/ghostroom.cpp
Normal file
398
engines/avalanche/ghostroom.cpp
Normal file
@@ -0,0 +1,398 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "avalanche/avalanche.h"
|
||||
#include "avalanche/ghostroom.h"
|
||||
|
||||
#include "common/random.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
const int8 GhostRoom::kAdjustment[5] = { 7, 0, 7, 7, 7 };
|
||||
const byte GhostRoom::kWaveOrder[5] = { 4, 0, 1, 2, 3 };
|
||||
const byte GhostRoom::kGlerkFade[26] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 0 };
|
||||
const byte GhostRoom::kGreldetFade[18] = { 0, 1, 2, 3, 4, 5, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0, 0 };
|
||||
|
||||
GhostRoom::GhostRoom(AvalancheEngine *vm) {
|
||||
_vm = vm;
|
||||
|
||||
_glerkStage = 0;
|
||||
_batX = 0;
|
||||
_batY = 0;
|
||||
_batCount = 0;
|
||||
_aarghCount = 0;
|
||||
_greldetX = _greldetY = 0;
|
||||
_greldetCount = 0;
|
||||
_redGreldet = false;
|
||||
_wasLoaded = false;
|
||||
|
||||
_ghost = nullptr;
|
||||
_glerk = nullptr;
|
||||
}
|
||||
|
||||
GhostRoom::~GhostRoom() {
|
||||
for (int i = 0; i < 2; i++)
|
||||
_eyes[i].free();
|
||||
|
||||
_exclamation.free();
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
_bat[i].free();
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
_aargh[i].free();
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
_greenEyes[i].free();
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 6; j++)
|
||||
_greldet[j][i].free();
|
||||
}
|
||||
|
||||
if (_wasLoaded) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
for (int y = 0; y < 66; y++) {
|
||||
delete[] _ghost[i][j][y];
|
||||
}
|
||||
delete[] _ghost[i][j];
|
||||
}
|
||||
delete[] _ghost[i];
|
||||
}
|
||||
delete[] _ghost;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
for (int y = 0; y < 35; y++) {
|
||||
delete[] _glerk[i][j][y];
|
||||
}
|
||||
delete[] _glerk[i][j];
|
||||
}
|
||||
delete[] _glerk[i];
|
||||
}
|
||||
delete[] _glerk;
|
||||
}
|
||||
}
|
||||
|
||||
void GhostRoom::wait(uint16 howLong) {
|
||||
for (int i = 0; i < howLong; i++) {
|
||||
Common::Event event;
|
||||
_vm->getEvent(event);
|
||||
if (event.type == Common::EVENT_KEYDOWN)
|
||||
_vm->_sound->playNote(6177, 1);
|
||||
_vm->_system->delayMillis(1);
|
||||
}
|
||||
}
|
||||
|
||||
void GhostRoom::doBat() {
|
||||
_batCount++;
|
||||
|
||||
int8 dx = 0;
|
||||
int8 iy = 0;
|
||||
byte batImage = 0;
|
||||
if ((_batCount % 2) == 1) {
|
||||
if ((1 <= _batCount) && (_batCount <= 90)) {
|
||||
dx = 2;
|
||||
iy = 1;
|
||||
batImage = 0;
|
||||
} else if ((91 <= _batCount) && (_batCount <= 240)) {
|
||||
dx = 1;
|
||||
iy = 1;
|
||||
batImage = 1;
|
||||
} else if((241 <= _batCount) && (_batCount <= 260)) {
|
||||
dx = 1;
|
||||
iy = 4;
|
||||
batImage = 2;
|
||||
}
|
||||
|
||||
if (batImage && (_batCount == 91 || _batCount == 241)) // When the bat changes, blank out the old one.
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(_batX + _bat[batImage].w, _batY, _batX + _bat[batImage - 1].w, _batY + _bat[batImage - 1].h), kColorBlack);
|
||||
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(_batX, _batY, _batX + _bat[batImage].w, _batY + iy), kColorBlack);
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(_batX + _bat[batImage].w - dx, _batY, _batX + _bat[batImage].w, _batY + _bat[batImage].h), kColorBlack);
|
||||
|
||||
_batX -= dx;
|
||||
_batY++;
|
||||
_vm->_graphics->ghostDrawPicture(_bat[batImage], _batX, _batY);
|
||||
}
|
||||
}
|
||||
|
||||
void GhostRoom::bigGreenEyes(byte how) {
|
||||
_vm->_graphics->ghostDrawPicture(_greenEyes[how], 330, 103);
|
||||
_vm->_graphics->ghostDrawPicture(_greenEyes[how], 376, 103);
|
||||
_vm->_graphics->refreshScreen();
|
||||
}
|
||||
|
||||
ChunkBlock GhostRoom::readChunkBlock(Common::File &file) {
|
||||
ChunkBlock cb;
|
||||
cb._flavour = (Flavour)file.readByte();
|
||||
cb._x = file.readSint16LE();
|
||||
cb._y = file.readSint16LE();
|
||||
cb._width = file.readSint16LE();
|
||||
cb._height = file.readSint16LE();
|
||||
cb._size = file.readSint32LE();
|
||||
return cb;
|
||||
}
|
||||
|
||||
void GhostRoom::loadPictures() {
|
||||
Common::File file;
|
||||
|
||||
if (!file.open("spooky.avd"))
|
||||
error("AVALANCHE: GhostRoom: File not found: spooky.avd");
|
||||
|
||||
file.seek(44);
|
||||
|
||||
// Initializing ghost's array.
|
||||
_ghost = new byte***[5];
|
||||
for (int i = 0; i < 5; i++) {
|
||||
_ghost[i] = new byte**[2];
|
||||
for (int j = 0; j < 2; j++) {
|
||||
_ghost[i][j] = new byte*[66];
|
||||
for (int y = 0; y < 66; y++) {
|
||||
_ghost[i][j][y] = new byte[26];
|
||||
for (int x = 0; x < 26; x++)
|
||||
_ghost[i][j][y][x] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read in the pictures of the ghost.
|
||||
for (int i = 0; i < 5; i++) {
|
||||
ChunkBlock cb = readChunkBlock(file);
|
||||
for (int j = 0; j < 2; j++) {
|
||||
for (int y = 0; y <= cb._height; y++)
|
||||
file.read(_ghost[i][j][y], cb._width / 8);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
_eyes[i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord);
|
||||
|
||||
_exclamation = _vm->_graphics->ghostLoadPicture(file, dummyCoord);
|
||||
|
||||
// Actually this function not just loads, but also draws the images, but they are part of the background
|
||||
// and they are need to be drawn only once.
|
||||
_vm->_graphics->ghostDrawBackgroundItems(file);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
_bat[i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord);
|
||||
|
||||
// Initializing glerk's array.
|
||||
_glerk = new byte***[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
_glerk[i] = new byte**[4];
|
||||
for (int j = 0; j < 4; j++) {
|
||||
_glerk[i][j] = new byte*[35];
|
||||
for (int y = 0; y < 35; y++) {
|
||||
_glerk[i][j][y] = new byte[9];
|
||||
for (int x = 0; x < 9; x++)
|
||||
_glerk[i][j][y][x] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read in the pictures of the "glerk".
|
||||
for (int i = 0; i < 6; i++) {
|
||||
ChunkBlock cb = readChunkBlock(file);
|
||||
for (int j = 0; j < 4; j++) {
|
||||
for (int y = 0; y <= cb._height; y++)
|
||||
file.read(_glerk[i][j][y], cb._width / 8);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
_aargh[i] = _vm->_graphics->ghostLoadPicture(file, _aarghWhere[i]);
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
_greenEyes[i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 6; j++)
|
||||
_greldet[j][i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord);
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
void GhostRoom::run() {
|
||||
CursorMan.showMouse(false);
|
||||
_vm->_graphics->saveScreen();
|
||||
_vm->fadeOut();
|
||||
_vm->_graphics->blackOutScreen();
|
||||
_vm->fadeIn();
|
||||
|
||||
// Only load the pictures if it's our first time walking into the room.
|
||||
// After that we simply use the already loaded images.
|
||||
if (!_wasLoaded) {
|
||||
loadPictures();
|
||||
_wasLoaded = true;
|
||||
}
|
||||
|
||||
// Avvy walks over:
|
||||
_glerkStage = 0;
|
||||
_batX = 277;
|
||||
_batY = 40;
|
||||
_batCount = 0;
|
||||
|
||||
for (int x = 500; x >= 217; x--) {
|
||||
// The floating eyeballs:
|
||||
int xBound = x % 30;
|
||||
if ((22 <= xBound) && (xBound <= 27)) {
|
||||
if (xBound == 27)
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(x, 135, x + 17, 137), kColorBlack);
|
||||
_vm->_graphics->ghostDrawPicture(_eyes[0], x, 136);
|
||||
_vm->_graphics->drawDot(x + 16, 137, kColorBlack);
|
||||
} else {
|
||||
if (xBound == 21)
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(x, 137, x + 18, 139), kColorBlack);
|
||||
_vm->_graphics->ghostDrawPicture(_eyes[0], x, 135);
|
||||
_vm->_graphics->drawDot(x + 16, 136, kColorBlack); // Eyes would leave a trail 1 pixel high behind them.
|
||||
}
|
||||
|
||||
// Plot the Glerk:
|
||||
if ((x % 10) == 0) {
|
||||
if (_glerkStage > 25)
|
||||
break;
|
||||
|
||||
_vm->_graphics->ghostDrawMonster(_glerk[kGlerkFade[_glerkStage]], 456, 14, kMonsterTypeGlerk);
|
||||
_glerkStage++;
|
||||
}
|
||||
|
||||
doBat();
|
||||
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
wait(15);
|
||||
}
|
||||
|
||||
// Blank out the Glerk's space.
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(456, 14, 531, 51), kColorBlack);
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
|
||||
// Here comes the descending ghost:
|
||||
for (int y = -64; y <= 103; y++) {
|
||||
_vm->_graphics->ghostDrawMonster(_ghost[1 + (abs(y / 7) % 2) * 3], 0, y, kMonsterTypeGhost);
|
||||
if (y > 0)
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(0, y - 1, 26 * 8 + 1, y + 1), kColorBlack);
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
wait(27);
|
||||
}
|
||||
|
||||
// Then it waves:
|
||||
_aarghCount = -15;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 5; j++) {
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(0, 96, 26 * 8, 170), kColorBlack);
|
||||
_vm->_graphics->ghostDrawMonster(_ghost[kWaveOrder[j]], 0, 96 + kAdjustment[j], kMonsterTypeGhost);
|
||||
|
||||
_aarghCount++;
|
||||
|
||||
if (_aarghCount >= 0) {
|
||||
for (int k = 0; k <= _aarghCount; k++)
|
||||
_vm->_graphics->ghostDrawPicture(_aargh[k], _aarghWhere[k].x, _aarghWhere[k].y);
|
||||
}
|
||||
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
wait(177);
|
||||
}
|
||||
}
|
||||
|
||||
// The exclamation mark appears:
|
||||
_vm->_graphics->ghostDrawPicture(_exclamation, 246, 127);
|
||||
_vm->_graphics->refreshScreen();
|
||||
wait(777);
|
||||
|
||||
// Erase "aargh":
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(172, 78, 348, 112), kColorBlack);
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
for (int i = 4; i >= 0; i--) {
|
||||
wait(377);
|
||||
bigGreenEyes(i);
|
||||
}
|
||||
|
||||
// Erase the exclamation mark:
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(246, 127, 252, 134), kColorBlack);
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
// Avvy hurries back:
|
||||
_glerkStage = 0;
|
||||
_greldetCount = 18;
|
||||
_redGreldet = false;
|
||||
|
||||
for (int x = 217; x <= 479; x++) {
|
||||
// The floating eyeballs again:
|
||||
int xBound = x % 30;
|
||||
if ((22 <= xBound) && (xBound <= 27)) {
|
||||
if (xBound == 22)
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(x + 22, 134, x + 39, 138), kColorBlack);
|
||||
_vm->_graphics->ghostDrawPicture(_eyes[1], x + 23, 136);
|
||||
_vm->_graphics->drawDot(x + 22, 137, kColorBlack);
|
||||
} else {
|
||||
if (xBound == 28)
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(x + 22, 135, x + 39, 139), kColorBlack);
|
||||
_vm->_graphics->ghostDrawPicture(_eyes[1], x + 23, 135);
|
||||
_vm->_graphics->drawDot(x + 22, 136, kColorBlack); // Eyes would leave a trail 1 pixel high behind them.
|
||||
}
|
||||
|
||||
// Plot the Green Eyes:
|
||||
if ((x % 53) == 5) {
|
||||
bigGreenEyes(_glerkStage);
|
||||
_glerkStage++;
|
||||
}
|
||||
|
||||
// Plot the Greldet:
|
||||
if (_greldetCount == 18) {
|
||||
_greldetX = _vm->_rnd->getRandomNumber(599);
|
||||
_greldetY = _vm->_rnd->getRandomNumber(79);
|
||||
_greldetCount = 0;
|
||||
_redGreldet = !_redGreldet;
|
||||
}
|
||||
|
||||
_vm->_graphics->ghostDrawPicture(_greldet[kGreldetFade[_greldetCount]][_redGreldet], _greldetX, _greldetY);
|
||||
_greldetCount++;
|
||||
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
wait(10);
|
||||
}
|
||||
|
||||
CursorMan.showMouse(true);
|
||||
|
||||
_vm->fadeOut();
|
||||
_vm->_graphics->restoreScreen();
|
||||
_vm->_graphics->removeBackup();
|
||||
_vm->_animation->animLink();
|
||||
_vm->fadeIn();
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche
|
||||
87
engines/avalanche/ghostroom.h
Normal file
87
engines/avalanche/ghostroom.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AVALANCHE_GHOSTROOM_H
|
||||
#define AVALANCHE_GHOSTROOM_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
struct ChunkBlock {
|
||||
Flavour _flavour;
|
||||
int16 _x, _y;
|
||||
int16 _width, _height;
|
||||
int32 _size;
|
||||
};
|
||||
|
||||
class GhostRoom {
|
||||
public:
|
||||
GhostRoom(AvalancheEngine *vm);
|
||||
~GhostRoom();
|
||||
|
||||
void run();
|
||||
ChunkBlock readChunkBlock(Common::File &file);
|
||||
|
||||
private:
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
static const int8 kAdjustment[5];
|
||||
static const byte kWaveOrder[5];
|
||||
static const byte kGlerkFade[26];
|
||||
static const byte kGreldetFade[18];
|
||||
|
||||
Common::Point dummyCoord;
|
||||
byte ****_ghost;// [5][2][66][26]
|
||||
Graphics::Surface _eyes[2];
|
||||
Graphics::Surface _exclamation;
|
||||
Graphics::Surface _bat[3];
|
||||
byte ****_glerk; // [6][4][35][9]
|
||||
Graphics::Surface _aargh[6];
|
||||
Common::Point _aarghWhere[6];
|
||||
Graphics::Surface _greenEyes[5];
|
||||
Graphics::Surface _greldet[6][2];
|
||||
|
||||
int16 _batX, _batY;
|
||||
uint16 _batCount;
|
||||
byte _glerkStage;
|
||||
int8 _aarghCount;
|
||||
int16 _greldetX, _greldetY;
|
||||
byte _greldetCount;
|
||||
bool _redGreldet;
|
||||
bool _wasLoaded;
|
||||
|
||||
void loadPictures();
|
||||
void wait(uint16 howLong);
|
||||
void doBat();
|
||||
void bigGreenEyes(byte how);
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_GHOSTROOM_H
|
||||
1266
engines/avalanche/graphics.cpp
Normal file
1266
engines/avalanche/graphics.cpp
Normal file
File diff suppressed because it is too large
Load Diff
210
engines/avalanche/graphics.h
Normal file
210
engines/avalanche/graphics.h
Normal file
@@ -0,0 +1,210 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AVALANCHE_GRAPHICS_H
|
||||
#define AVALANCHE_GRAPHICS_H
|
||||
|
||||
#include "avalanche/enums.h"
|
||||
|
||||
#include "common/file.h"
|
||||
#include "common/rect.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
class AnimationType;
|
||||
struct SpriteType;
|
||||
struct ChunkBlock;
|
||||
|
||||
typedef byte FontType[256][16];
|
||||
typedef byte ManiType[2049];
|
||||
typedef byte SilType[51][11]; // 35, 4
|
||||
|
||||
struct MouseHotspotType {
|
||||
int16 _horizontal, _vertical;
|
||||
};
|
||||
|
||||
class GraphicManager {
|
||||
public:
|
||||
static const MouseHotspotType kMouseHotSpots[9];
|
||||
Color _talkBackgroundColor, _talkFontColor;
|
||||
|
||||
GraphicManager(AvalancheEngine *vm);
|
||||
~GraphicManager();
|
||||
void init();
|
||||
void loadDigits();
|
||||
void loadMouse(byte which);
|
||||
|
||||
void drawRectangle(Common::Rect rect, Color color);
|
||||
void drawFilledRectangle(Common::Rect rect, Color color);
|
||||
void blackOutScreen();
|
||||
void drawDot(int x, int y, Color color);
|
||||
void drawLine(int x1, int y1, int x2, int y2, int penX, int penY, Color color);
|
||||
Common::Point drawScreenArc(int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color);
|
||||
void drawPieSlice(int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color);
|
||||
void drawTriangle(Common::Point *p, Color color);
|
||||
void drawNormalText(const Common::String &text, FontType font, byte fontHeight, int16 x, int16 y, Color color);
|
||||
void drawScrollText(const Common::String &text, FontType font, byte fontHeight, int16 x, int16 y, Color color);
|
||||
void drawDigit(int index, int x, int y);
|
||||
void drawDirection(int index, int x, int y);
|
||||
void drawScrollShadow(int16 x1, int16 y1, int16 x2, int16 y2);
|
||||
void drawShadowBox(int16 x1, int16 y1, int16 x2, int16 y2, Common::String text);
|
||||
void drawScroll(int mx, int lx, int my, int ly);
|
||||
void drawMenuBar(Color color);
|
||||
void drawSpeedBar(int speed);
|
||||
void drawBackgroundSprite(int16 x, int16 y, SpriteType &sprite);
|
||||
void drawMenuBlock(int x1, int y1, int x2, int y2, Color color);
|
||||
void drawMenuItem(int x1, int y1, int x2, int y2);
|
||||
void wipeChar(int x, int y, Color color);
|
||||
void drawChar(byte ander, int x, int y, Color color);
|
||||
void drawDebugLines();
|
||||
|
||||
// For the mini-game "Nim".
|
||||
void nimLoad();
|
||||
void nimDrawStone(int x, int y);
|
||||
void nimDrawInitials();
|
||||
void nimDrawLogo();
|
||||
void nimFree();
|
||||
|
||||
// Used in wobble()
|
||||
void shiftScreen();
|
||||
|
||||
// Used in winning()
|
||||
void drawWinningPic();
|
||||
|
||||
// Ghostroom's functions:
|
||||
void ghostDrawMonster(byte ***picture, uint16 destX, int16 destY, MonsterType type);
|
||||
Graphics::Surface ghostLoadPicture(Common::File &file, Common::Point &coord);
|
||||
void ghostDrawPicture(const Graphics::Surface &picture, uint16 destX, uint16 destY);
|
||||
void ghostDrawBackgroundItems(Common::File &file);
|
||||
|
||||
// Help's function:
|
||||
void helpDrawButton(int y, byte which);
|
||||
void helpDrawHighlight(byte which, Color color);
|
||||
void helpDrawBigText(const Common::String &text, int16 x, int16 y, Color color);
|
||||
|
||||
// Shoot em' up's functions:
|
||||
void seuDrawTitle();
|
||||
void seuLoad();
|
||||
void seuFree();
|
||||
void seuDrawPicture(int x, int y, byte which);
|
||||
void seuDrawCameo(int destX, int destY, byte w1, byte w2);
|
||||
uint16 seuGetPicWidth(int which);
|
||||
uint16 seuGetPicHeight(int which);
|
||||
|
||||
// Main Menu's functions:
|
||||
// The main menu uses a different screen height (350) from the game itself (200 * 2)
|
||||
// so it needs it's own graphic functions on that matter.
|
||||
void menuRefreshScreen();
|
||||
void menuInitialize();
|
||||
void menuFree();
|
||||
void menuRestoreScreen();
|
||||
void menuLoadPictures();
|
||||
void menuDrawBigText(FontType font, uint16 x, uint16 y, Common::String text, Color color);
|
||||
void menuDrawIndicator(int x);
|
||||
|
||||
void clearAlso();
|
||||
void clearTextBar();
|
||||
void setAlsoLine(int x1, int y1, int x2, int y2, Color color);
|
||||
byte getAlsoColor(int x1, int y1, int x2, int y2);
|
||||
byte getScreenColor(Common::Point pos);
|
||||
|
||||
// Further information about this: https://moddingwiki.shikadi.net/wiki/Raw_EGA_data
|
||||
Graphics::Surface loadPictureRaw(Common::File &file, uint16 width, uint16 height);
|
||||
|
||||
void drawSprite(AnimationType *sprite, byte picnum, int16 x, int16 y);
|
||||
void drawThinkPic(const Common::Path &filename, int id);
|
||||
void drawToolbar();
|
||||
void drawCursor(byte pos);
|
||||
void drawReadyLight(Color color);
|
||||
void drawSoundLight(bool state);
|
||||
void drawErrorLight(bool state);
|
||||
void drawSign(Common::String name, int16 xl, int16 yl, int16 y);
|
||||
void drawIcon(int16 x, int16 y, byte which);
|
||||
void drawScreenLine(int16 x, int16 y, int16 x2, int16 y2, Color color);
|
||||
void prepareBubble(int xc, int xw, int my, Common::Point points[3]);
|
||||
void refreshScreen();
|
||||
void loadBackground(Common::File &file);
|
||||
void refreshBackground();
|
||||
void setBackgroundColor(Color newColor);
|
||||
void setDialogColor(Color bg, Color text);
|
||||
|
||||
void zoomOut(int16 x, int16 y);
|
||||
void showScroll();
|
||||
void getNaturalPicture(SpriteType &sprite);
|
||||
|
||||
void saveScreen();
|
||||
void restoreScreen();
|
||||
void removeBackup();
|
||||
|
||||
private:
|
||||
static const int16 kMouseSize = 134;
|
||||
static const uint16 kBackgroundWidth = kScreenWidth;
|
||||
static const byte kEgaPaletteIndex[16];
|
||||
static const byte kBackgroundHeight = 8 * 12080 / kScreenWidth; // With 640 width it's 151.
|
||||
// The 8 = number of bits in a byte, and 12080 comes from Lucerna::load().
|
||||
static const uint16 kMenuScreenHeight = 350;
|
||||
|
||||
Graphics::Surface _background;
|
||||
Graphics::Surface _backup;
|
||||
Graphics::Surface _digits[10]; // digitsize and rwlitesize are defined in loadDigits() !!!
|
||||
Graphics::Surface _directions[9]; // Maybe it will be needed to move them to the class itself instead.
|
||||
Graphics::Surface _magics; // Lucerna::draw_also_lines() draws the "magical" lines here. Further information: https://github.com/marnanel/avalot/wiki/Also
|
||||
Graphics::Surface _screen; // Only used in refreshScreen() to make it more optimized. (No recreation of it at every call of the function.)
|
||||
Graphics::Surface _scrolls;
|
||||
Graphics::Surface _surface;
|
||||
Graphics::Surface _menu;
|
||||
|
||||
// For the mini-game "Nim".
|
||||
Graphics::Surface _nimStone;
|
||||
Graphics::Surface _nimInitials[3];
|
||||
Graphics::Surface _nimLogo;
|
||||
|
||||
// For the mini-game "Shoot em' up".
|
||||
Graphics::Surface _seuPictures[99];
|
||||
|
||||
byte _egaPalette[64][3];
|
||||
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
void skipDifference(int size, const Graphics::Surface &picture, Common::File &file);
|
||||
|
||||
// Further information about these two: https://moddingwiki.shikadi.net/wiki/Raw_EGA_data
|
||||
Graphics::Surface loadPictureGraphic(Common::File &file); // Reads Graphic-planar EGA data.
|
||||
Graphics::Surface loadPictureSign(Common::File &file, uint16 width, uint16 height); // Reads a tricky type of picture used for the "game over"/"about" scrolls and in the mini-game Nim.
|
||||
|
||||
void drawText(Graphics::Surface &surface, const Common::String &text, FontType font, byte fontHeight, int16 x, int16 y, Color color);
|
||||
void drawBigText(Graphics::Surface &surface, const Common::String &text, FontType font, byte fontHeight, int16 x, int16 y, Color color);
|
||||
void drawPicture(Graphics::Surface &target, const Graphics::Surface &picture, uint16 destX, uint16 destY);
|
||||
|
||||
// Taken from Free Pascal's Procedure InternalEllipseDefault. Used to replace Pascal's procedure arc.
|
||||
// Returns the end point of the arc. (Needed in Clock.)
|
||||
Common::Point drawArc(Graphics::Surface &surface, int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color);
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_GRAPHICS_H
|
||||
269
engines/avalanche/help.cpp
Normal file
269
engines/avalanche/help.cpp
Normal file
@@ -0,0 +1,269 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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: HELPER The help system unit. */
|
||||
|
||||
#include "avalanche/avalanche.h"
|
||||
#include "avalanche/help.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
Help::Help(AvalancheEngine *vm) {
|
||||
_vm = vm;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
_buttons[i]._trigger = Common::KEYCODE_INVALID;
|
||||
_buttons[i]._whither = 0;
|
||||
}
|
||||
_highlightWas = 0;
|
||||
_buttonNum = 0;
|
||||
_holdLeft = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and draws the chosen page of the help.
|
||||
* @remarks Originally called 'getme'
|
||||
*/
|
||||
void Help::switchPage(byte which) {
|
||||
// Help icons are 80x20.
|
||||
|
||||
_highlightWas = 177; // Forget where the highlight was.
|
||||
|
||||
Common::File file;
|
||||
|
||||
if (!file.open("help.avd"))
|
||||
error("AVALANCHE: Help: File not found: help.avd");
|
||||
|
||||
file.seek(which * 2);
|
||||
uint16 offset = file.readUint16LE();
|
||||
file.seek(offset);
|
||||
|
||||
Common::String title = getLine(file);
|
||||
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(0, 0, 640, 200), kColorBlue);
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(8, 40, 450, 200), kColorWhite);
|
||||
|
||||
byte index = file.readByte();
|
||||
_vm->_graphics->helpDrawButton(-177, index);
|
||||
|
||||
// Plot the title:
|
||||
_vm->_graphics->drawNormalText(title, _vm->_font, 8, 629 - 8 * title.size(), 26, kColorBlack);
|
||||
_vm->_graphics->drawNormalText(title, _vm->_font, 8, 630 - 8 * title.size(), 25, kColorCyan);
|
||||
|
||||
_vm->_graphics->helpDrawBigText("help!", 549, 1, kColorBlack);
|
||||
_vm->_graphics->helpDrawBigText("help!", 550, 0, kColorCyan);
|
||||
|
||||
byte y = 0;
|
||||
do {
|
||||
Common::String line = getLine(file);
|
||||
if (!line.empty()) {
|
||||
if (line.compareTo(Common::String('!')) == 0) // End of the help text is signalled with a '!'.
|
||||
break;
|
||||
if (line[0] == '\\') {
|
||||
line.deleteChar(0);
|
||||
_vm->_graphics->drawNormalText(line, _vm->_font, 8, 16, 41 + y * 10, kColorRed);
|
||||
}
|
||||
else
|
||||
_vm->_graphics->drawNormalText(line, _vm->_font, 8, 16, 41 + y * 10, kColorBlack);
|
||||
}
|
||||
y++;
|
||||
} while (true);
|
||||
|
||||
// We are now at the end of the text. Next we must read the icons:
|
||||
y = 0;
|
||||
_buttonNum = 0;
|
||||
while (!file.eos()) {
|
||||
int trigger = file.readByte();
|
||||
|
||||
if (trigger == 177)
|
||||
break;
|
||||
switch (trigger) {
|
||||
case 254: // Escape
|
||||
trigger = 27;
|
||||
break;
|
||||
case 214: // PageUp
|
||||
trigger = 280;
|
||||
break;
|
||||
case 216: // PageDown
|
||||
trigger = 281;
|
||||
break;
|
||||
default: // A - Z
|
||||
// The characters are stored in the file in uppercase, but we need the lowercase versions for KeyCode:
|
||||
trigger = tolower(trigger);
|
||||
break;
|
||||
}
|
||||
|
||||
_buttons[y]._trigger = Common::KeyCode(trigger);
|
||||
index = file.readByte();
|
||||
if (_buttons[y]._trigger != Common::KEYCODE_INVALID)
|
||||
_vm->_graphics->helpDrawButton(13 + (y + 1) * 27, index);
|
||||
_buttons[y]._whither = file.readByte(); // This is the position to jump to.
|
||||
|
||||
Common::String text = "";
|
||||
switch (_buttons[y]._trigger) {
|
||||
case Common::KEYCODE_ESCAPE:
|
||||
text = Common::String("Esc");
|
||||
break;
|
||||
case Common::KEYCODE_PAGEUP:
|
||||
text = Common::String(24);
|
||||
break;
|
||||
case Common::KEYCODE_PAGEDOWN:
|
||||
text = Common::String(25);
|
||||
break;
|
||||
default:
|
||||
text = Common::String(toupper(_buttons[y]._trigger));
|
||||
break;
|
||||
}
|
||||
|
||||
_vm->_graphics->helpDrawBigText(text, 589 - (text.size() * 8), 18 + (y + 1) * 27, kColorBlack);
|
||||
_vm->_graphics->helpDrawBigText(text, 590 - (text.size() * 8), 17 + (y + 1) * 27, kColorCyan);
|
||||
|
||||
y++;
|
||||
_buttonNum++;
|
||||
}
|
||||
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
Common::String Help::getLine(Common::File &file) {
|
||||
Common::String line;
|
||||
byte length = file.readByte();
|
||||
for (int i = 0; i < length; i++) {
|
||||
char c = file.readByte();
|
||||
line += (c ^ 177);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
bool Help::handleMouse(const Common::Event &event) {
|
||||
Common::Point mousePos;
|
||||
mousePos.x = event.mouse.x;
|
||||
mousePos.y = event.mouse.y / 2;
|
||||
|
||||
int index;
|
||||
|
||||
if (event.type == Common::EVENT_LBUTTONUP) { // Clicked *somewhere*...
|
||||
_holdLeft = false;
|
||||
|
||||
if ((mousePos.x < 470) || (mousePos.x > 550) || (((mousePos.y - 13) % 27) > 20))
|
||||
index = -1;
|
||||
else // Clicked on a button.
|
||||
index = ((mousePos.y - 13) / 27) - 1;
|
||||
} else { // LBUTTONDOWN or MOUSEMOVE
|
||||
int highlightIs = 0;
|
||||
index = -1;
|
||||
|
||||
// Decide which button we are hovering the cursor over:
|
||||
if ((mousePos.x > 470) && (mousePos.x <= 550) && (((mousePos.y - 13) % 27) <= 20)) { // No click, so highlight.
|
||||
highlightIs = (mousePos.y - 13) / 27 - 1;
|
||||
if ((highlightIs < 0) || (5 < highlightIs))
|
||||
highlightIs = 177; // In case of silly values.
|
||||
} else
|
||||
highlightIs = 177;
|
||||
|
||||
Color highlightColor = kColorLightblue;
|
||||
// If we clicked on a button or we are holding down the button, we have to highlight it with cyan:
|
||||
if (((highlightIs != 177) && (event.type == Common::EVENT_LBUTTONDOWN)) || _holdLeft) {
|
||||
_holdLeft = true;
|
||||
highlightColor = kColorLightcyan;
|
||||
}
|
||||
|
||||
// Erase the previous highlight only if it's needed:
|
||||
if (_highlightWas != highlightIs)
|
||||
_vm->_graphics->helpDrawHighlight(_highlightWas, kColorBlue);
|
||||
|
||||
// Highlight the current one with the proper color:
|
||||
if ((highlightIs != 177) && (_buttons[highlightIs]._trigger != Common::KEYCODE_INVALID)) {
|
||||
_highlightWas = highlightIs;
|
||||
_vm->_graphics->helpDrawHighlight(highlightIs, highlightColor);
|
||||
}
|
||||
}
|
||||
|
||||
if ((index >= 0) && (_buttons[index]._trigger != Common::KEYCODE_INVALID)) {
|
||||
if (_buttons[index]._trigger == Common::KEYCODE_ESCAPE)
|
||||
return true;
|
||||
|
||||
_vm->fadeOut();
|
||||
switchPage(_buttons[index]._whither);
|
||||
_vm->fadeIn();
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Help::handleKeyboard(const Common::Event &event) {
|
||||
if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < _buttonNum; i++) {
|
||||
if (_buttons[i]._trigger == event.kbd.keycode) {
|
||||
_vm->fadeOut();
|
||||
switchPage(_buttons[i]._whither);
|
||||
_vm->fadeIn();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks Originally called 'boot_help'
|
||||
*/
|
||||
void Help::run() {
|
||||
_vm->_graphics->saveScreen();
|
||||
_vm->fadeOut();
|
||||
switchPage(0);
|
||||
_vm->fadeIn();
|
||||
|
||||
_vm->_graphics->loadMouse(kCurHelp);
|
||||
|
||||
// Originally it was the body of 'continue_help':
|
||||
bool close = false;
|
||||
while (!_vm->shouldQuit() && !close) {
|
||||
Common::Event event;
|
||||
_vm->getEvent(event);
|
||||
if (event.type == Common::EVENT_KEYDOWN)
|
||||
close = handleKeyboard(event);
|
||||
else if ((event.type == Common::EVENT_LBUTTONDOWN) || (event.type == Common::EVENT_LBUTTONUP) || (event.type == Common::EVENT_MOUSEMOVE))
|
||||
close = handleMouse(event);
|
||||
|
||||
_vm->_graphics->refreshScreen();
|
||||
}
|
||||
// End of 'continue_help'.
|
||||
|
||||
_vm->fadeOut();
|
||||
_vm->_graphics->restoreScreen();
|
||||
_vm->_graphics->removeBackup();
|
||||
_vm->fadeIn();
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche
|
||||
64
engines/avalanche/help.h
Normal file
64
engines/avalanche/help.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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: HELPER The help system unit. */
|
||||
|
||||
#ifndef AVALANCHE_HELP_H
|
||||
#define AVALANCHE_HELP_H
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
class Help {
|
||||
public:
|
||||
Help(AvalancheEngine *vm);
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
struct Button {
|
||||
Common::KeyCode _trigger;
|
||||
byte _whither;
|
||||
};
|
||||
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
Button _buttons[10];
|
||||
byte _highlightWas;
|
||||
byte _buttonNum; // How many buttons do we have on the screen at the moment?
|
||||
bool _holdLeft; // Is the left mouse button is still being held?
|
||||
|
||||
void switchPage(byte which);
|
||||
Common::String getLine(Common::File &file); // It was a nested function in getMe().
|
||||
|
||||
// These two return true if we have to leave the Help:
|
||||
bool handleMouse(const Common::Event &event);
|
||||
bool handleKeyboard(const Common::Event &event);
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_HELP_H
|
||||
116
engines/avalanche/highscore.cpp
Normal file
116
engines/avalanche/highscore.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "avalanche/avalanche.h"
|
||||
#include "avalanche/highscore.h"
|
||||
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
HighScore::HighScore(AvalancheEngine *vm) {
|
||||
_vm = vm;
|
||||
|
||||
for (int i = 0; i < 12; ++i) {
|
||||
_data[i]._name = "";
|
||||
_data[i]._rank = "";
|
||||
_data[i]._score = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void HighScore::displayHighScores() {
|
||||
warning("STUB: HighScore::displayHighScores(");
|
||||
}
|
||||
|
||||
void HighScore::saveHighScores() {
|
||||
int firstSmaller = 0;
|
||||
while ((firstSmaller < 12) && (_data[firstSmaller]._score >= _vm->_score))
|
||||
firstSmaller++;
|
||||
|
||||
if (firstSmaller < 12) {
|
||||
// Shift all the lower scores down a space:
|
||||
for (int i = firstSmaller; i < 11; i++)
|
||||
_data[i + 1] = _data[i];
|
||||
// Set the new high score:
|
||||
_data[firstSmaller]._name = "Player"; // TODO: Come up with something for that. In the original it wasn't implemented at all...
|
||||
_data[firstSmaller]._rank = _vm->_parser->rank();
|
||||
_data[firstSmaller]._score = _vm->_score;
|
||||
}
|
||||
|
||||
Common::OutSaveFile *f = g_system->getSavefileManager()->openForSaving("scores.avd");
|
||||
if (!f) {
|
||||
warning("Can't create file 'scores.avd', high scores are not saved.");
|
||||
return;
|
||||
}
|
||||
Common::Serializer sz(nullptr, f);
|
||||
syncHighScores(sz);
|
||||
f->finalize();
|
||||
delete f;
|
||||
}
|
||||
|
||||
void HighScore::loadHighScroes() {
|
||||
Common::File file;
|
||||
if (!file.exists("scores.avd")) {
|
||||
produceDefaultHighScores();
|
||||
} else {
|
||||
Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading("scores.avd");
|
||||
if (!f)
|
||||
return;
|
||||
Common::Serializer sz(f, nullptr);
|
||||
syncHighScores(sz);
|
||||
delete f;
|
||||
}
|
||||
}
|
||||
|
||||
void HighScore::produceDefaultHighScores() {
|
||||
for (int i = 0; i < 12; i++) {
|
||||
_data[i]._score = 32 - (i + 1) * 2;
|
||||
_data[i]._rank = "...";
|
||||
}
|
||||
_data[0]._name = "Mike";
|
||||
_data[1]._name = "Liz";
|
||||
_data[2]._name = "Thomas";
|
||||
_data[3]._name = "Mark";
|
||||
_data[4]._name = "Mandy";
|
||||
_data[5]._name = "Andrew";
|
||||
_data[6]._name = "Lucy Tryphena";
|
||||
_data[7]._name = "Tammy the dog";
|
||||
_data[8]._name = "Avaricius";
|
||||
_data[9]._name = "Spellchick";
|
||||
_data[10]._name = "Caddelli";
|
||||
_data[11]._name = "Spludwick";
|
||||
}
|
||||
|
||||
void HighScore::syncHighScores(Common::Serializer &sz) {
|
||||
for (int i = 0; i < 12; i++) {
|
||||
sz.syncString(_data[i]._name);
|
||||
sz.syncAsUint16LE(_data[i]._score);
|
||||
sz.syncString(_data[i]._rank);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche
|
||||
58
engines/avalanche/highscore.h
Normal file
58
engines/avalanche/highscore.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AVALANCHE_HIGHSCORE_H
|
||||
#define AVALANCHE_HIGHSCORE_H
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
struct HighScoreData {
|
||||
Common::String _name;
|
||||
uint16 _score;
|
||||
Common::String _rank;
|
||||
};
|
||||
|
||||
class HighScore {
|
||||
public:
|
||||
HighScore(AvalancheEngine *vm);
|
||||
|
||||
void displayHighScores();
|
||||
void saveHighScores();
|
||||
void loadHighScroes();
|
||||
|
||||
private:
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
HighScoreData _data[12];
|
||||
|
||||
void produceDefaultHighScores();
|
||||
void syncHighScores(Common::Serializer &sz);
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_HIGHSCORE_H
|
||||
117
engines/avalanche/mainmenu.cpp
Normal file
117
engines/avalanche/mainmenu.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "avalanche/avalanche.h"
|
||||
#include "avalanche/mainmenu.h"
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
MainMenu::MainMenu(AvalancheEngine *vm) {
|
||||
_vm = vm;
|
||||
|
||||
_registrant = Common::String("");
|
||||
}
|
||||
|
||||
void MainMenu::run() {
|
||||
CursorMan.showMouse(false);
|
||||
_vm->_graphics->menuInitialize();
|
||||
_vm->_graphics->menuLoadPictures();
|
||||
loadRegiInfo();
|
||||
loadFont();
|
||||
|
||||
option(1, "Play the game.");
|
||||
option(2, "Read the background.");
|
||||
option(3, "Preview... perhaps...");
|
||||
option(4, "View the documentation.");
|
||||
option(5, "Registration info.");
|
||||
option(6, "Exit back to DOS.");
|
||||
centre(274, _registrant);
|
||||
centre(301, "Make your choice, or wait for the demo.");
|
||||
|
||||
_vm->_graphics->menuRefreshScreen();
|
||||
|
||||
wait();
|
||||
}
|
||||
|
||||
void MainMenu::loadFont() {
|
||||
Common::File file;
|
||||
if (!file.open("avalot.fnt"))
|
||||
error("AVALANCHE: Scrolls: File not found: avalot.fnt");
|
||||
for (int16 i = 0; i < 256; i++)
|
||||
file.read(_font[i], 16);
|
||||
file.close();
|
||||
}
|
||||
|
||||
void MainMenu::loadRegiInfo() {
|
||||
_registrant = "(Unregistered evaluation copy.)";
|
||||
warning("STUB: MainMenu::loadRegiInfo()");
|
||||
}
|
||||
|
||||
void MainMenu::option(byte which, Common::String what) {
|
||||
_vm->_graphics->menuDrawBigText(_font, 127, 39 + which * 33, Common::String(which + 48) + ')', kColorBlack);
|
||||
_vm->_graphics->menuDrawBigText(_font, 191, 39 + which * 33, what, kColorBlack);
|
||||
}
|
||||
|
||||
void MainMenu::centre(int16 y, Common::String text) {
|
||||
_vm->_graphics->menuDrawBigText(_font, 320 - text.size() * 8, y, text, kColorLightgray);
|
||||
}
|
||||
|
||||
void MainMenu::wait() {
|
||||
int x = 0;
|
||||
while (!_vm->shouldQuit()) {
|
||||
_vm->_graphics->menuDrawIndicator(x);
|
||||
_vm->_system->delayMillis(40);
|
||||
x++;
|
||||
if (x == 641)
|
||||
x = 0;
|
||||
Common::Event event;
|
||||
_vm->getEvent(event);
|
||||
if (event.type == Common::EVENT_KEYDOWN) {
|
||||
switch (event.kbd.keycode) {
|
||||
case Common::KEYCODE_SPACE:
|
||||
case Common::KEYCODE_RETURN:
|
||||
case Common::KEYCODE_1: // Falltroughs are inteded.
|
||||
// Play the game
|
||||
_vm->_graphics->menuFree();
|
||||
_vm->_graphics->menuRestoreScreen();
|
||||
CursorMan.showMouse(true);
|
||||
return;
|
||||
case Common::KEYCODE_ESCAPE:
|
||||
case Common::KEYCODE_6: // Falltroughs are inteded.
|
||||
// Exit back to DOS
|
||||
_vm->_letMeOut = true;
|
||||
_vm->_graphics->menuFree();
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche
|
||||
54
engines/avalanche/mainmenu.h
Normal file
54
engines/avalanche/mainmenu.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AVALANCHE_MAINMENU_H
|
||||
#define AVALANCHE_MAINMENU_H
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
class MainMenu {
|
||||
public:
|
||||
MainMenu(AvalancheEngine *vm);
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
Common::String _registrant;
|
||||
FontType _font;
|
||||
|
||||
void loadFont();
|
||||
void loadRegiInfo();
|
||||
void option(byte which, Common::String what);
|
||||
void centre(int16 y, Common::String text);
|
||||
void wait();
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_MAINMENU_H
|
||||
195
engines/avalanche/metaengine.cpp
Normal file
195
engines/avalanche/metaengine.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "avalanche/avalanche.h"
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/savefile.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
#include "graphics/thumbnail.h"
|
||||
|
||||
#include "avalanche/detection.h"
|
||||
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
uint32 AvalancheEngine::getFeatures() const {
|
||||
return _gameDescription->desc.flags;
|
||||
}
|
||||
|
||||
const char *AvalancheEngine::getGameId() const {
|
||||
return _gameDescription->desc.gameId;
|
||||
}
|
||||
|
||||
Common::Platform AvalancheEngine::getPlatform() const {
|
||||
return _gameDescription->desc.platform;
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
class AvalancheMetaEngine : public AdvancedMetaEngine<AvalancheGameDescription> {
|
||||
public:
|
||||
const char *getName() const override {
|
||||
return "avalanche";
|
||||
}
|
||||
|
||||
Common::Error createInstance(OSystem *syst, Engine **engine, const AvalancheGameDescription *gd) const override;
|
||||
bool hasFeature(MetaEngineFeature f) const override;
|
||||
|
||||
int getMaximumSaveSlot() const override { return 99; }
|
||||
SaveStateList listSaves(const char *target) const override;
|
||||
bool removeSaveState(const char *target, int slot) const override;
|
||||
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
|
||||
};
|
||||
|
||||
Common::Error AvalancheMetaEngine::createInstance(OSystem *syst, Engine **engine, const AvalancheGameDescription *gd) const {
|
||||
*engine = new AvalancheEngine(syst,gd);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool AvalancheMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsListSaves) ||
|
||||
(f == kSupportsDeleteSave) ||
|
||||
(f == kSupportsLoadingDuringStartup) ||
|
||||
(f == kSavesSupportMetaInfo) ||
|
||||
(f == kSavesSupportThumbnail) ||
|
||||
(f == kSimpleSavesNames);
|
||||
}
|
||||
|
||||
SaveStateList AvalancheMetaEngine::listSaves(const char *target) const {
|
||||
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||
Common::StringArray filenames;
|
||||
Common::String pattern = target;
|
||||
pattern.toUppercase();
|
||||
pattern += ".###";
|
||||
|
||||
filenames = saveFileMan->listSavefiles(pattern);
|
||||
|
||||
SaveStateList saveList;
|
||||
for (const auto &filename : filenames) {
|
||||
int slotNum = atoi(filename.c_str() + filename.size() - 3);
|
||||
if (slotNum >= 0 && slotNum <= getMaximumSaveSlot()) {
|
||||
Common::InSaveFile *file = saveFileMan->openForLoading(filename);
|
||||
if (file) {
|
||||
// Check for our signature.
|
||||
uint32 signature = file->readUint32LE();
|
||||
if (signature != MKTAG('A', 'V', 'A', 'L')) {
|
||||
warning("Savegame of incompatible type!");
|
||||
delete file;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check version.
|
||||
byte saveVersion = file->readByte();
|
||||
if (saveVersion > kSavegameVersion) {
|
||||
warning("Savegame of incompatible version!");
|
||||
delete file;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Read name.
|
||||
uint32 nameSize = file->readUint32LE();
|
||||
if (nameSize >= 255) {
|
||||
delete file;
|
||||
continue;
|
||||
}
|
||||
char *name = new char[nameSize + 1];
|
||||
file->read(name, nameSize);
|
||||
name[nameSize] = 0;
|
||||
|
||||
saveList.push_back(SaveStateDescriptor(this, slotNum, name));
|
||||
delete[] name;
|
||||
delete file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort saves based on slot number.
|
||||
Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
|
||||
return saveList;
|
||||
}
|
||||
|
||||
bool AvalancheMetaEngine::removeSaveState(const char *target, int slot) const {
|
||||
Common::String fileName = Common::String::format("%s.%03d", target, slot);
|
||||
return g_system->getSavefileManager()->removeSavefile(fileName);
|
||||
}
|
||||
|
||||
SaveStateDescriptor AvalancheMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
|
||||
Common::String fileName = Common::String::format("%s.%03d", target, slot);
|
||||
Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(fileName);
|
||||
|
||||
if (f) {
|
||||
// Check for our signature.
|
||||
uint32 signature = f->readUint32LE();
|
||||
if (signature != MKTAG('A', 'V', 'A', 'L')) {
|
||||
warning("Savegame of incompatible type!");
|
||||
delete f;
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
// Check version.
|
||||
byte saveVersion = f->readByte();
|
||||
if (saveVersion > kSavegameVersion) {
|
||||
warning("Savegame of a too recent version!");
|
||||
delete f;
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
// Read the description.
|
||||
uint32 descSize = f->readUint32LE();
|
||||
Common::String description;
|
||||
for (uint32 i = 0; i < descSize; i++) {
|
||||
char actChar = f->readByte();
|
||||
description += actChar;
|
||||
}
|
||||
|
||||
SaveStateDescriptor desc(this, slot, description);
|
||||
|
||||
Graphics::Surface *thumbnail;
|
||||
if (!Graphics::loadThumbnail(*f, thumbnail)) {
|
||||
warning("Cannot read thumbnail data, possibly broken savegame");
|
||||
delete f;
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
desc.setThumbnail(thumbnail);
|
||||
|
||||
delete f;
|
||||
return desc;
|
||||
}
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(AVALANCHE)
|
||||
REGISTER_PLUGIN_DYNAMIC(AVALANCHE, PLUGIN_TYPE_ENGINE, Avalanche::AvalancheMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(AVALANCHE, PLUGIN_TYPE_ENGINE, Avalanche::AvalancheMetaEngine);
|
||||
#endif
|
||||
35
engines/avalanche/module.mk
Normal file
35
engines/avalanche/module.mk
Normal file
@@ -0,0 +1,35 @@
|
||||
MODULE := engines/avalanche
|
||||
|
||||
MODULE_OBJS = \
|
||||
animation.o \
|
||||
avalanche.o \
|
||||
avalot.o \
|
||||
background.o \
|
||||
closing.o \
|
||||
console.o \
|
||||
graphics.o \
|
||||
dropdown.o \
|
||||
parser.o \
|
||||
dialogs.o \
|
||||
sequence.o \
|
||||
sound.o \
|
||||
timer.o \
|
||||
metaengine.o \
|
||||
nim.o \
|
||||
clock.o \
|
||||
ghostroom.o \
|
||||
help.o \
|
||||
shootemup.o \
|
||||
mainmenu.o \
|
||||
highscore.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_AVALANCHE), DYNAMIC_PLUGIN)
|
||||
PLUGIN := 1
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
||||
# Detection objects
|
||||
DETECT_OBJS += $(MODULE)/detection.o
|
||||
574
engines/avalanche/nim.cpp
Normal file
574
engines/avalanche/nim.cpp
Normal file
@@ -0,0 +1,574 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "avalanche/avalanche.h"
|
||||
#include "avalanche/nim.h"
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
const char * const Nim::kNames[2] = {"Avalot", "Dogfood"};
|
||||
|
||||
Nim::Nim(AvalancheEngine *vm) {
|
||||
_vm = vm;
|
||||
|
||||
resetVariables();
|
||||
}
|
||||
|
||||
void Nim::resetVariables() {
|
||||
_playedNim = 0;
|
||||
_turns = 0;
|
||||
_dogfoodsTurn = false;
|
||||
_stonesLeft = 0;
|
||||
_clicked = false;
|
||||
_row = 0;
|
||||
_number = 0;
|
||||
_squeak = false;
|
||||
_lmo = false;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
_old[i] = 0;
|
||||
_stones[i] = 0;
|
||||
_inAp[i] = false;
|
||||
_r[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Nim::synchronize(Common::Serializer &sz) {
|
||||
if (sz.isLoading() && sz.getVersion() < 2)
|
||||
return;
|
||||
|
||||
sz.syncAsByte(_playedNim);
|
||||
}
|
||||
|
||||
void Nim::playNim() {
|
||||
if (_vm->_wonNim) { // Already won the game.
|
||||
_vm->_dialogs->displayScrollChain('Q', 6);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_vm->_askedDogfoodAboutNim) {
|
||||
_vm->_dialogs->displayScrollChain('Q', 84);
|
||||
return;
|
||||
}
|
||||
|
||||
_vm->_dialogs->displayScrollChain('Q', 3);
|
||||
_playedNim++;
|
||||
|
||||
_vm->_graphics->saveScreen();
|
||||
_vm->fadeOut();
|
||||
|
||||
CursorMan.showMouse(false);
|
||||
setup();
|
||||
board();
|
||||
//CursorMan.showMouse(true);
|
||||
|
||||
do {
|
||||
|
||||
startMove();
|
||||
if (_dogfoodsTurn)
|
||||
dogFood();
|
||||
else {
|
||||
CursorMan.showMouse(true);
|
||||
takeSome();
|
||||
CursorMan.showMouse(false);
|
||||
}
|
||||
_stones[_row] -= _number;
|
||||
showChanges();
|
||||
} while (_stonesLeft != 0);
|
||||
|
||||
endOfGame(); // Winning sequence is A1, B3, B1, C1, C1, btw.
|
||||
|
||||
_vm->fadeOut();
|
||||
_vm->_graphics->restoreScreen();
|
||||
_vm->_graphics->removeBackup();
|
||||
_vm->fadeIn();
|
||||
CursorMan.showMouse(true);
|
||||
|
||||
if (_dogfoodsTurn) {
|
||||
// Dogfood won - as usual.
|
||||
if (_playedNim == 1) // Your first game.
|
||||
_vm->_dialogs->displayScrollChain('Q', 4); // Goody! Play me again?
|
||||
else
|
||||
_vm->_dialogs->displayScrollChain('Q', 5); // Oh, look at that! I've won again!
|
||||
_vm->decreaseMoney(4); // And you've just lost 4d!
|
||||
} else {
|
||||
// You won - strange!
|
||||
_vm->_dialogs->displayScrollChain('Q', 7);
|
||||
_vm->_objects[kObjectLute - 1] = true;
|
||||
_vm->refreshObjectList();
|
||||
_vm->_wonNim = true;
|
||||
_vm->_background->draw(-1, -1, 0); // Show the settle with no lute on it.
|
||||
|
||||
// 7 points for winning!
|
||||
_vm->incScore(7);
|
||||
}
|
||||
|
||||
if (_playedNim == 1) {
|
||||
// 3 points for playing your 1st game.
|
||||
_vm->incScore(3);
|
||||
}
|
||||
}
|
||||
|
||||
void Nim::chalk(int x, int y, Common::String text) {
|
||||
const Color greys[] = { kColorBlack, kColorDarkgray, kColorLightgray, kColorWhite };
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_vm->_graphics->drawNormalText(text, _vm->_font, 8, x - i, y, greys[i]);
|
||||
_vm->_graphics->refreshScreen();
|
||||
int freq = i * 100 * text.size();
|
||||
if (freq == 0)
|
||||
_vm->_system->delayMillis(3);
|
||||
else
|
||||
_vm->_sound->playNote(freq, 3);
|
||||
_vm->_system->delayMillis(30);
|
||||
}
|
||||
}
|
||||
|
||||
void Nim::setup() {
|
||||
_vm->fadeIn();
|
||||
_vm->_graphics->nimLoad();
|
||||
|
||||
_vm->_graphics->blackOutScreen();
|
||||
// Upper left rectangle.
|
||||
_vm->_graphics->drawRectangle(Common::Rect(10, 5, 381, 71), kColorRed);
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(11, 6, 380, 70), kColorBrown);
|
||||
// Bottom right rectangle.
|
||||
_vm->_graphics->drawRectangle(Common::Rect(394, 50, 635, 198), kColorRed);
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(395, 51, 634, 197), kColorBrown);
|
||||
|
||||
_vm->_graphics->nimDrawLogo();
|
||||
_vm->_graphics->nimDrawInitials();
|
||||
|
||||
_vm->_graphics->drawNormalText("SCOREBOARD:", _vm->_font, 8, 475, 45, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("Turn:", _vm->_font, 8, 420, 55, kColorYellow);
|
||||
_vm->_graphics->drawNormalText("Player:", _vm->_font, 8, 490, 55, kColorYellow);
|
||||
_vm->_graphics->drawNormalText("Move:", _vm->_font, 8, 570, 55, kColorYellow);
|
||||
|
||||
chalk(27, 7, "Take pieces away with:");
|
||||
chalk(77, 17, "1) the mouse (click leftmost)");
|
||||
chalk(53, 27, "or 2) the keyboard:");
|
||||
chalk(220, 27, Common::String(24) + '/' + 25 + ": choose row,");
|
||||
chalk(164, 37, Common::String("+/- or ") + 27 + '/' + 26 + ": more/fewer,");
|
||||
chalk(204, 47, "Enter: take stones.");
|
||||
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
_stones[i] = i + 3;
|
||||
_stonesLeft = 12;
|
||||
|
||||
_turns = 0;
|
||||
_dogfoodsTurn = true;
|
||||
|
||||
_row = 0;
|
||||
_number = 1;
|
||||
for (int i = 0; i < 3; i++)
|
||||
_old[i] = 0;
|
||||
}
|
||||
|
||||
void Nim::board() {
|
||||
_vm->_graphics->drawFilledRectangle(Common::Rect(57, 72, 393, 200), kColorBlack);
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < _stones[i]; j++)
|
||||
_vm->_graphics->nimDrawStone(64 + j * 8 * 8, 75 + i * 35);
|
||||
// It's practically the body of the Pascal function "plotstone()", reimplemented.
|
||||
// It's the only place where we use it, so there's no reason to keep it separated as a function.
|
||||
_vm->_graphics->refreshScreen();
|
||||
}
|
||||
|
||||
void Nim::startMove() {
|
||||
_turns++;
|
||||
Common::String turnsStr = Common::String::format("%d", _turns);
|
||||
int y = 55 + _turns * 10;
|
||||
_dogfoodsTurn = !_dogfoodsTurn;
|
||||
chalk(433, y, turnsStr);
|
||||
chalk(493, y, kNames[_dogfoodsTurn]);
|
||||
for (int i = 0; i < 3; i++)
|
||||
_old[i] = _stones[i];
|
||||
}
|
||||
|
||||
void Nim::showChanges() {
|
||||
chalk(573, 55 + _turns * 10, Common::String('A' + _row) + Common::String('0' + _number));
|
||||
board();
|
||||
_stonesLeft -= _number;
|
||||
}
|
||||
|
||||
void Nim::blip() {
|
||||
_vm->_sound->playNote(1771, 3);
|
||||
}
|
||||
|
||||
void Nim::findNextUp() {
|
||||
while (_stones[_row] == 0) {
|
||||
_row--;
|
||||
if (_row < 0)
|
||||
_row = 2;
|
||||
}
|
||||
|
||||
if (_number > _stones[_row])
|
||||
_number = _stones[_row];
|
||||
}
|
||||
|
||||
void Nim::findNextDown() {
|
||||
while (_stones[_row] == 0) {
|
||||
_row++;
|
||||
if (_row > 2)
|
||||
_row = 0;
|
||||
}
|
||||
|
||||
if (_number > _stones[_row])
|
||||
_number = _stones[_row];
|
||||
}
|
||||
|
||||
bool Nim::checkInput() {
|
||||
while (!_vm->shouldQuit()) {
|
||||
_vm->_graphics->refreshScreen();
|
||||
Common::Event event;
|
||||
while (_vm->getEvent(event)) {
|
||||
if (event.type == Common::EVENT_LBUTTONUP) {
|
||||
Common::Point cursorPos = _vm->getMousePos();
|
||||
|
||||
int8 newRow = (cursorPos.y / 2 - 38) / 35 - 1;
|
||||
if ((newRow < 0) || (newRow > 2)) {
|
||||
blip();
|
||||
return false;
|
||||
}
|
||||
|
||||
int8 newNum = _stones[newRow] - ((cursorPos.x - 64) / 64);
|
||||
if ((newNum < 1) || (newNum > _stones[newRow])) {
|
||||
blip();
|
||||
return false;
|
||||
}
|
||||
|
||||
_number = newNum;
|
||||
_row = newRow;
|
||||
|
||||
return true;
|
||||
} else if (event.type == Common::EVENT_KEYDOWN) {
|
||||
switch (event.kbd.keycode) {
|
||||
case Common::KEYCODE_LEFT:
|
||||
case Common::KEYCODE_KP_PLUS:
|
||||
if (_stones[_row] > _number)
|
||||
_number++;
|
||||
return false;
|
||||
case Common::KEYCODE_RIGHT:
|
||||
case Common::KEYCODE_KP_MINUS:
|
||||
if (_number > 1)
|
||||
_number--;
|
||||
return false;
|
||||
case Common::KEYCODE_END:
|
||||
case Common::KEYCODE_1:
|
||||
_number = 1;
|
||||
return false;
|
||||
case Common::KEYCODE_2:
|
||||
if (_stones[_row] >= 2)
|
||||
_number = 2;
|
||||
return false;
|
||||
case Common::KEYCODE_3:
|
||||
if (_stones[_row] >= 3)
|
||||
_number = 3;
|
||||
else
|
||||
_number = _stones[_row];
|
||||
return false;
|
||||
case Common::KEYCODE_4:
|
||||
if (_stones[_row] >= 4)
|
||||
_number = 4;
|
||||
else
|
||||
_number = _stones[_row];
|
||||
return false;
|
||||
case Common::KEYCODE_5:
|
||||
if (_stones[_row] == 5)
|
||||
_number = 5;
|
||||
else
|
||||
_number = _stones[_row];
|
||||
return false;
|
||||
case Common::KEYCODE_HOME:
|
||||
_number = _stones[_row];
|
||||
return false;
|
||||
case Common::KEYCODE_UP:
|
||||
_row--;
|
||||
if (_row < 0)
|
||||
_row = 2;
|
||||
findNextUp();
|
||||
return false;
|
||||
case Common::KEYCODE_DOWN:
|
||||
_row++;
|
||||
if (_row > 2)
|
||||
_row = 0;
|
||||
findNextDown();
|
||||
return false;
|
||||
case Common::KEYCODE_a:
|
||||
if (_stones[0] != 0) {
|
||||
_row = 0;
|
||||
if (_number > _stones[_row])
|
||||
_number = _stones[_row];
|
||||
}
|
||||
return false;
|
||||
case Common::KEYCODE_b:
|
||||
if (_stones[1] != 0) {
|
||||
_row = 1;
|
||||
if (_number > _stones[_row])
|
||||
_number = _stones[_row];
|
||||
}
|
||||
return false;
|
||||
case Common::KEYCODE_c:
|
||||
if (_stones[2] != 0) {
|
||||
_row = 2;
|
||||
if (_number > _stones[_row])
|
||||
_number = _stones[_row];
|
||||
}
|
||||
return false;
|
||||
case Common::KEYCODE_PAGEUP:
|
||||
_row = 0;
|
||||
findNextDown();
|
||||
return false;
|
||||
case Common::KEYCODE_PAGEDOWN:
|
||||
_row = 2;
|
||||
findNextUp();
|
||||
return false;
|
||||
case Common::KEYCODE_RETURN:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Nim::takeSome() {
|
||||
_number = 1;
|
||||
|
||||
do {
|
||||
byte sr;
|
||||
do {
|
||||
sr = _stones[_row];
|
||||
if (sr == 0) {
|
||||
if (_row == 2)
|
||||
_row = 0;
|
||||
else
|
||||
_row++;
|
||||
_number = 1;
|
||||
}
|
||||
} while (sr == 0);
|
||||
|
||||
if (_number > sr)
|
||||
_number = sr;
|
||||
|
||||
int x1 = 63 + (_stones[_row] - _number) * 64;
|
||||
int y1 = 38 + 35 * (_row + 1);
|
||||
int x2 = 55 + _stones[_row] * 64;
|
||||
int y2 = 64 + 35 * (_row + 1);
|
||||
_vm->_graphics->drawRectangle(Common::Rect(x1, y1, x2, y2), kColorBlue); // Draw the selection rectangle.
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
bool confirm = false;
|
||||
do {
|
||||
confirm = checkInput();
|
||||
|
||||
if (!confirm) {
|
||||
_vm->_graphics->drawRectangle(Common::Rect(x1, y1, x2, y2), kColorBlack); // Erase the previous selection.
|
||||
x1 = 63 + (_stones[_row] - _number) * 64;
|
||||
y1 = 38 + 35 * (_row + 1);
|
||||
x2 = 55 + _stones[_row] * 64;
|
||||
y2 = 64 + 35 * (_row + 1);
|
||||
_vm->_graphics->drawRectangle(Common::Rect(x1, y1, x2, y2), kColorBlue); // Draw the new one.
|
||||
_vm->_graphics->refreshScreen();
|
||||
}
|
||||
} while (!confirm);
|
||||
|
||||
return;
|
||||
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void Nim::endOfGame() {
|
||||
chalk(595, 55 + _turns * 10, "Wins!");
|
||||
_vm->_graphics->drawNormalText("- - - Press any key... - - -", _vm->_font, 8, 100, 190, kColorWhite);
|
||||
|
||||
Common::Event event;
|
||||
bool escape = false;
|
||||
while (!_vm->shouldQuit() && !escape) {
|
||||
_vm->_graphics->refreshScreen();
|
||||
while (_vm->getEvent(event)) {
|
||||
if ((event.type == Common::EVENT_LBUTTONUP) || (event.type == Common::EVENT_KEYDOWN)) {
|
||||
escape = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_graphics->nimFree();
|
||||
}
|
||||
|
||||
bool Nim::find(byte x) {
|
||||
bool ret = false;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (_stones[i] == x) {
|
||||
ret = true;
|
||||
_inAp[i] = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Nim::findAp(byte start, byte stepSize) {
|
||||
byte thisOne = 0;
|
||||
byte matches = 0;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
_inAp[i] = 0; // Blank 'em all!
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (find(start + i * stepSize))
|
||||
matches++;
|
||||
else
|
||||
thisOne = i;
|
||||
}
|
||||
|
||||
// Now... Matches must be 0, 1, 2, or 3.
|
||||
// 0 / 1 mean there are no A.P.s here, so we'll keep looking,
|
||||
// 2 means there is a potential A.P.that we can create (ideal!), and
|
||||
// 3 means that we're already in an A.P. (Trouble!)
|
||||
|
||||
byte ooo = 0; // Odd one out.
|
||||
|
||||
switch (matches) {
|
||||
case 2:
|
||||
for (int i = 0; i < 3; i++) { // Find which one didn't fit the A.P.
|
||||
if (!_inAp[i])
|
||||
ooo = i;
|
||||
}
|
||||
|
||||
if (_stones[ooo] > (start + thisOne * stepSize)) { // Check if it's possible!
|
||||
// Create an A.P.
|
||||
_row = ooo; // Already calculated.
|
||||
// Start + thisone * stepsize will give the amount we SHOULD have here.
|
||||
_number = _stones[_row] - (start + thisOne * stepSize);
|
||||
_lmo = true;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 3: // We're actually IN an A.P! Trouble! Oooh dear.
|
||||
// Take 1 from the largest pile.
|
||||
_row = _r[2];
|
||||
_number = 1;
|
||||
_lmo = true;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Nim::dogFood() {
|
||||
_lmo = false;
|
||||
byte live = 0;
|
||||
byte sr[3];
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (_stones[i] > 0) {
|
||||
_r[live] = i;
|
||||
sr[live] = _stones[i];
|
||||
live++;
|
||||
}
|
||||
}
|
||||
|
||||
switch (live) {
|
||||
case 1: // Only one is free - so take 'em all!
|
||||
_row = _r[0];
|
||||
_number = _stones[_r[0]];
|
||||
return;
|
||||
case 2: // Two are free - make them equal!
|
||||
if (sr[0] > sr[1]) { // T > b
|
||||
_row = _r[0];
|
||||
_number = sr[0] - sr[1];
|
||||
}
|
||||
else if (sr[0] < sr[1]) { // B > t
|
||||
_row = _r[1];
|
||||
_number = sr[1] - sr[0];
|
||||
}
|
||||
else { // B = t... oh no, we've lost!
|
||||
_row = _r[0];
|
||||
_number = 1;
|
||||
}
|
||||
return;
|
||||
case 3: {
|
||||
// Ho hum... this'll be difficult!
|
||||
// There are three possible courses of action when we have 3 lines left:
|
||||
// 1) Look for 2 equal lines, then take the odd one out.
|
||||
// 2) Look for A.P.s, and capitalise on them.
|
||||
// 3) Go any old where.
|
||||
const byte other[3][2] = { { 1, 2 }, { 0, 2 }, { 0, 1 } };
|
||||
|
||||
for (int i = 0; i < 3; i++) { // Look for 2 equal lines.
|
||||
if (_stones[other[i][0]] == _stones[other[i][1]]) {
|
||||
_row = i; // This row.
|
||||
_number = _stones[i]; // All of 'em.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool sorted;
|
||||
do {
|
||||
sorted = true;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (sr[i] > sr[i + 1]) {
|
||||
byte temp = sr[i + 1];
|
||||
sr[i + 1] = sr[i];
|
||||
sr[i] = temp;
|
||||
|
||||
temp = _r[i + 1];
|
||||
_r[i + 1] = _r[i];
|
||||
_r[i] = temp;
|
||||
|
||||
sorted = false;
|
||||
}
|
||||
}
|
||||
} while (!sorted);
|
||||
|
||||
// Now we look for A.P.s...
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
findAp(i, 1); // There are 3 "1"s.
|
||||
if (_lmo)
|
||||
return; // Cut - out.
|
||||
}
|
||||
findAp(1, 2); // Only "2" possible.
|
||||
if (_lmo)
|
||||
return;
|
||||
|
||||
// A.P.search must have failed - use the default move.
|
||||
_row = _r[2];
|
||||
_number = 1;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche
|
||||
78
engines/avalanche/nim.h
Normal file
78
engines/avalanche/nim.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AVALANCHE_NIM_H
|
||||
#define AVALANCHE_NIM_H
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
class Nim {
|
||||
public:
|
||||
Nim(AvalancheEngine *vm);
|
||||
void resetVariables();
|
||||
void synchronize(Common::Serializer &sz);
|
||||
void playNim();
|
||||
|
||||
private:
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
static const char * const kNames[2];
|
||||
|
||||
byte _old[3];
|
||||
byte _stones[3];
|
||||
byte _turns;
|
||||
bool _dogfoodsTurn;
|
||||
byte _stonesLeft;
|
||||
bool _clicked;
|
||||
int8 _row;
|
||||
byte _number;
|
||||
bool _squeak;
|
||||
byte _playedNim; // How many times you've played Nim.
|
||||
|
||||
// Inner variables for dogFood(), find() and findAp().
|
||||
bool _inAp[3];
|
||||
bool _lmo; // Let Me Out!
|
||||
byte _r[3];
|
||||
|
||||
void chalk(int x, int y, Common::String text);
|
||||
void setup();
|
||||
void board();
|
||||
void startMove();
|
||||
void showChanges();
|
||||
void blip();
|
||||
void findNextUp(); // Inner function for checkInput().
|
||||
void findNextDown(); // Same as above.
|
||||
bool checkInput(); // It returns TRUE if the player confirmed his selection of stones either by pressing RETURN or by clicking on a stone.
|
||||
void takeSome();
|
||||
void endOfGame();
|
||||
bool find(byte x); // This gives TRUE if there's a pile with x stones in.
|
||||
void findAp(byte start, byte stepSize);
|
||||
void dogFood(); // AI procedure to play the game.
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_NIM_H
|
||||
2526
engines/avalanche/parser.cpp
Normal file
2526
engines/avalanche/parser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
148
engines/avalanche/parser.h
Normal file
148
engines/avalanche/parser.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AVALANCHE_PARSER_H
|
||||
#define AVALANCHE_PARSER_H
|
||||
|
||||
#include "avalanche/enums.h"
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/str.h"
|
||||
#include "common/serializer.h"
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
class Parser {
|
||||
public:
|
||||
static const int16 kParserWordsNum = 277; // How many words does the parser know?
|
||||
static const int16 kFirstPassword = 88; // words[kFirstPassword] should equal "TIROS".
|
||||
static const byte kPardon = 254; // Didn't understand / wasn't given.
|
||||
static const byte kNothing = 250;
|
||||
static const byte kMoved = 0; // This word was moved. (Usually because it was the subject of conversation.)
|
||||
|
||||
struct VocabEntry {
|
||||
byte _number;
|
||||
Common::String _word;
|
||||
|
||||
void init(byte number, Common::String word) {
|
||||
_number = number;
|
||||
_word = word;
|
||||
}
|
||||
};
|
||||
|
||||
VocabEntry _vocabulary[kParserWordsNum];
|
||||
|
||||
Common::String _realWords[11];
|
||||
VerbCode _verb;
|
||||
byte _thing;
|
||||
People _person;
|
||||
bool _polite;
|
||||
Common::String _inputText;
|
||||
Common::String _inputTextBackup;
|
||||
byte _inputTextPos;
|
||||
bool _quote;
|
||||
bool _cursorState;
|
||||
bool _weirdWord;
|
||||
|
||||
byte _wearing; // what you're wearing
|
||||
|
||||
Parser(AvalancheEngine *vm);
|
||||
void init();
|
||||
void parse();
|
||||
void doThat();
|
||||
void verbOpt(byte verb, Common::String &answer, char &ansKey);
|
||||
void drink();
|
||||
void handleInputText(const Common::Event &event);
|
||||
void handleBackspace();
|
||||
void handleReturn();
|
||||
void handleFunctionKey(const Common::Event &event);
|
||||
void plotText();
|
||||
void cursorOn();
|
||||
void cursorOff();
|
||||
void tryDropdown();
|
||||
int16 getPos(const Common::String &crit, const Common::String &src);
|
||||
void doVerb(VerbCode id);
|
||||
Common::String rank();
|
||||
void resetVariables();
|
||||
void synchronize(Common::Serializer &sz);
|
||||
|
||||
private:
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
struct RankType {
|
||||
uint16 _score;
|
||||
char _title[20];
|
||||
};
|
||||
|
||||
static const char *kCopyright;
|
||||
static const char *kVersionNum;
|
||||
|
||||
Common::String _thats;
|
||||
byte _thing2;
|
||||
byte _sworeNum; // number of times you've sworn
|
||||
byte _alcoholLevel; // Your blood alcohol level.
|
||||
bool _boughtOnion; // Have you bought an onion yet?
|
||||
|
||||
byte wordNum(Common::String word);
|
||||
void replace(Common::String oldChars, byte newChar);
|
||||
Common::String totalTime();
|
||||
void clearWords();
|
||||
void cheatParse(Common::String codes);
|
||||
void stripPunctuation(Common::String &word);
|
||||
void displayWhat(byte target, bool animate, bool &ambiguous);
|
||||
bool doPronouns();
|
||||
void properNouns();
|
||||
void lookAround();
|
||||
void openDoor();
|
||||
void storeInterrogation(byte interrogation);
|
||||
void examineObject();
|
||||
bool isPersonHere();
|
||||
void exampers();
|
||||
bool isHolding();
|
||||
void openBox(bool isOpening);
|
||||
void examine();
|
||||
void inventory();
|
||||
void swallow();
|
||||
void peopleInRoom();
|
||||
void putProc();
|
||||
void notInOrder();
|
||||
void goToCauldron();
|
||||
bool giveToSpludwick();
|
||||
void cardiffClimbing();
|
||||
void already();
|
||||
void standUp();
|
||||
void getProc(char thing);
|
||||
void giveGeidaTheLute();
|
||||
void playHarp();
|
||||
void winSequence();
|
||||
void wipeText();
|
||||
void bossKey();
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_PARSER_H
|
||||
231
engines/avalanche/sequence.cpp
Normal file
231
engines/avalanche/sequence.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* SEQUENCE The sequencer. */
|
||||
|
||||
#include "avalanche/avalanche.h"
|
||||
#include "avalanche/sequence.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
Sequence::Sequence(AvalancheEngine *vm) {
|
||||
_vm = vm;
|
||||
|
||||
resetVariables();
|
||||
}
|
||||
|
||||
void Sequence::resetVariables() {
|
||||
_flipToWhere = kRoomNowhere;
|
||||
_flipToPed = 0;
|
||||
}
|
||||
|
||||
void Sequence::init(byte what) {
|
||||
_seq[0] = what;
|
||||
|
||||
for (int i = 1; i < kSeqLength; i++)
|
||||
_seq[i] = 0;
|
||||
}
|
||||
|
||||
void Sequence::add(byte what) {
|
||||
for (int16 i = 0; i < kSeqLength; i++) {
|
||||
if (_seq[i] == 0) {
|
||||
_seq[i] = what;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::switchRoom(Room where, byte ped) {
|
||||
add(kNowFlip);
|
||||
|
||||
_flipToWhere = where;
|
||||
_flipToPed = ped;
|
||||
}
|
||||
|
||||
void Sequence::startTimer() {
|
||||
_vm->_timer->loseTimer(Timer::kReasonSequencer);
|
||||
_vm->_timer->addTimer(7, Timer::kProcSequence, Timer::kReasonSequencer);
|
||||
}
|
||||
|
||||
void Sequence::startTimerImmobilized() {
|
||||
// They can't move.
|
||||
_vm->_userMovesAvvy = false;
|
||||
// And they're not moving now.
|
||||
_vm->_animation->stopWalking();
|
||||
// Apart from that, it's the same thing.
|
||||
startTimer();
|
||||
}
|
||||
|
||||
void Sequence::shoveLeft() {
|
||||
for (uint i = 0; i < kSeqLength - 1; i++)
|
||||
_seq[i] = _seq[i + 1];
|
||||
_seq[kSeqLength - 1] = 0;
|
||||
}
|
||||
|
||||
void Sequence::callSequencer() {
|
||||
byte curSeq = _seq[0];
|
||||
|
||||
switch (curSeq) {
|
||||
case 0:
|
||||
// No more routines.
|
||||
return;
|
||||
break;
|
||||
case kNowFlip:
|
||||
// Flip room.
|
||||
_vm->_userMovesAvvy = true;
|
||||
_vm->flipRoom(_flipToWhere, _flipToPed);
|
||||
shoveLeft();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (curSeq <= 176) {
|
||||
// Show a frame.
|
||||
_vm->_background->draw(-1, -1, curSeq - 1);
|
||||
shoveLeft();
|
||||
}
|
||||
|
||||
// Make sure this PROC gets called again.
|
||||
startTimer();
|
||||
}
|
||||
|
||||
void Sequence::startHallSeq(Room whither, byte ped) {
|
||||
init(1);
|
||||
add(2);
|
||||
switchRoom(whither, ped);
|
||||
startTimerImmobilized();
|
||||
}
|
||||
|
||||
void Sequence::startOutsideSeq(Room whither, byte ped) {
|
||||
init(1);
|
||||
add(2);
|
||||
add(3);
|
||||
switchRoom(whither, ped);
|
||||
startTimerImmobilized();
|
||||
}
|
||||
|
||||
void Sequence::startCardiffSeq(Room whither, byte ped) {
|
||||
init(1);
|
||||
add(5);
|
||||
switchRoom(whither, ped);
|
||||
startTimerImmobilized();
|
||||
}
|
||||
|
||||
void Sequence::startNaughtyDukeSeq() {
|
||||
init(2);
|
||||
startTimer();
|
||||
}
|
||||
|
||||
void Sequence::startGardenSeq() {
|
||||
init(2);
|
||||
add(1);
|
||||
add(3);
|
||||
startTimer();
|
||||
}
|
||||
|
||||
void Sequence::startDuckSeq() {
|
||||
init(3);
|
||||
add(2);
|
||||
add(1);
|
||||
add(4);
|
||||
startTimer();
|
||||
}
|
||||
|
||||
void Sequence::startLustiesSeq3(Room whither, byte ped) {
|
||||
init(4);
|
||||
add(5);
|
||||
add(6);
|
||||
switchRoom(whither, ped);
|
||||
startTimerImmobilized();
|
||||
}
|
||||
|
||||
void Sequence::startMusicRoomSeq2(Room whither, byte ped) {
|
||||
init(5);
|
||||
add(6);
|
||||
switchRoom(whither, ped);
|
||||
startTimerImmobilized();
|
||||
}
|
||||
|
||||
void Sequence::startGeidaLuteSeq() {
|
||||
init(5);
|
||||
// He falls asleep...
|
||||
add(6);
|
||||
// Not really closing, but we're using the same procedure.
|
||||
startTimer();
|
||||
}
|
||||
|
||||
void Sequence::startMusicRoomSeq() {
|
||||
init(6);
|
||||
add(5);
|
||||
add(7);
|
||||
startTimer();
|
||||
}
|
||||
|
||||
void Sequence::startWinSeq() {
|
||||
init(7);
|
||||
add(8);
|
||||
add(9);
|
||||
startTimer();
|
||||
}
|
||||
|
||||
void Sequence::startCupboardSeq() {
|
||||
init(8);
|
||||
add(7);
|
||||
startTimer();
|
||||
}
|
||||
|
||||
void Sequence::startLustiesSeq2(Room whither, byte ped) {
|
||||
init(8);
|
||||
add(9);
|
||||
switchRoom(whither, ped);
|
||||
startTimerImmobilized();
|
||||
}
|
||||
|
||||
void Sequence::startCardiffSeq2() {
|
||||
init(1);
|
||||
if (_vm->_arrowInTheDoor)
|
||||
add(3);
|
||||
else
|
||||
add(2);
|
||||
|
||||
if (_vm->_takenPen)
|
||||
_vm->_background->draw(-1, -1, 3);
|
||||
|
||||
startTimer();
|
||||
}
|
||||
|
||||
void Sequence::startDummySeq(Room whither, byte ped) {
|
||||
switchRoom(whither, ped);
|
||||
startTimerImmobilized();
|
||||
}
|
||||
|
||||
void Sequence::synchronize(Common::Serializer &sz) {
|
||||
sz.syncBytes(_seq, kSeqLength);
|
||||
sz.syncAsByte(_flipToWhere);
|
||||
sz.syncAsByte(_flipToPed);
|
||||
}
|
||||
} // End of namespace Avalanche.
|
||||
79
engines/avalanche/sequence.h
Normal file
79
engines/avalanche/sequence.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* SEQUENCE The sequencer. */
|
||||
|
||||
#ifndef AVALANCHE_SEQUENCE_H
|
||||
#define AVALANCHE_SEQUENCE_H
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
class Sequence {
|
||||
private:
|
||||
static const int16 kNowFlip = 177;
|
||||
static const int16 kSeqLength = 10;
|
||||
|
||||
byte _seq[kSeqLength];
|
||||
|
||||
Room _flipToWhere;
|
||||
byte _flipToPed;
|
||||
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
void shoveLeft(); // This is called by Timer when it's time to do another frame. It shifts everything to the left.
|
||||
void init(byte what);
|
||||
void add(byte what);
|
||||
void switchRoom(Room where, byte ped);
|
||||
void startTimer();
|
||||
void startTimerImmobilized();
|
||||
|
||||
public:
|
||||
Sequence(AvalancheEngine *vm);
|
||||
void synchronize(Common::Serializer &sz);
|
||||
void resetVariables();
|
||||
void callSequencer();
|
||||
|
||||
void startCupboardSeq();
|
||||
void startMusicRoomSeq();
|
||||
void startMusicRoomSeq2(Room whither, byte ped);
|
||||
void startGardenSeq();
|
||||
void startGeidaLuteSeq();
|
||||
void startWinSeq();
|
||||
void startNaughtyDukeSeq();
|
||||
void startLustiesSeq2(Room whither, byte ped);
|
||||
void startLustiesSeq3(Room whither, byte ped);
|
||||
void startHallSeq(Room whither, byte ped);
|
||||
void startCardiffSeq(Room whither, byte ped);
|
||||
void startOutsideSeq(Room whither, byte ped);
|
||||
void startDuckSeq();
|
||||
void startCardiffSeq2();
|
||||
void startDummySeq(Room whither, byte ped);
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche.
|
||||
|
||||
#endif // AVALANCHE_SEQUENCE_H
|
||||
693
engines/avalanche/shootemup.cpp
Normal file
693
engines/avalanche/shootemup.cpp
Normal file
@@ -0,0 +1,693 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "avalanche/avalanche.h"
|
||||
#include "avalanche/shootemup.h"
|
||||
|
||||
#include "common/random.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
const byte ShootEmUp::kStocks = 27;
|
||||
const byte ShootEmUp::kAvvyShoots = 86;
|
||||
const byte ShootEmUp::kFacingRight = 87;
|
||||
const byte ShootEmUp::kFacingLeft = 93;
|
||||
const long int ShootEmUp::kFlag = -20047;
|
||||
const byte ShootEmUp::kFrameDelayMax = 2;
|
||||
const byte ShootEmUp::kAvvyY = 150;
|
||||
const byte ShootEmUp::kShooting[7] = { 86, 79, 80, 81, 80, 79, 86 };
|
||||
const byte ShootEmUp::kTimesASecond = 18;
|
||||
const byte ShootEmUp::kFlashTime = 20; // If flash_time is <= this, the word "time" will flash. Should be about 20.
|
||||
const byte ShootEmUp::kLeftMargin = 10;
|
||||
const int16 ShootEmUp::kRightMargin = 605;
|
||||
|
||||
ShootEmUp::ShootEmUp(AvalancheEngine *vm) {
|
||||
_vm = vm;
|
||||
|
||||
_time = 120;
|
||||
for (int i = 0; i < 7; i++)
|
||||
_stockStatus[i] = 0;
|
||||
for (int i = 0; i < 99; i++) {
|
||||
_sprites[i]._ix = 0;
|
||||
_sprites[i]._iy = 0;
|
||||
_sprites[i]._x = kFlag;
|
||||
_sprites[i]._y = 0;
|
||||
_sprites[i]._p = 0;
|
||||
_sprites[i]._timeout = 0;
|
||||
_sprites[i]._cameo = false;
|
||||
_sprites[i]._cameoFrame = 0;
|
||||
_sprites[i]._missile = false;
|
||||
_sprites[i]._wipe = false;
|
||||
}
|
||||
_rectNum = 0;
|
||||
_avvyWas = 320;
|
||||
_avvyPos = 320;
|
||||
_avvyAnim = 1;
|
||||
_avvyFacing = kFacingLeft;
|
||||
_altWasPressedBefore = false;
|
||||
_throwNext = 73;
|
||||
_firing = false;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_running[i]._x = kFlag;
|
||||
_running[i]._y = 0;
|
||||
_running[i]._frame = 0;
|
||||
_running[i]._tooHigh = 0;
|
||||
_running[i]._lowest = 0;
|
||||
_running[i]._ix = 0;
|
||||
_running[i]._iy = 0;
|
||||
_running[i]._frameDelay = 0;
|
||||
}
|
||||
for (int i = 0; i < 7; i++)
|
||||
_hasEscaped[i] = false;
|
||||
_count321 = 255; // Counting down.
|
||||
_howManyHaveEscaped = 0;
|
||||
_escapeCount = 0;
|
||||
_escaping = false;
|
||||
_timeThisSecond = 0;
|
||||
_cp = false;
|
||||
_wasFacing = 0;
|
||||
_score = 0;
|
||||
_escapeStock = 0;
|
||||
_gotOut = false;
|
||||
}
|
||||
|
||||
uint16 ShootEmUp::run() {
|
||||
CursorMan.showMouse(false);
|
||||
_vm->_graphics->saveScreen();
|
||||
_vm->fadeOut();
|
||||
_vm->_graphics->seuDrawTitle();
|
||||
_vm->fadeIn();
|
||||
|
||||
_vm->_graphics->seuLoad();
|
||||
|
||||
// Should we show the instructions?
|
||||
while (!_vm->shouldQuit()) {
|
||||
Common::Event event;
|
||||
_vm->getEvent(event);
|
||||
if (event.type == Common::EVENT_KEYDOWN) {
|
||||
if ((event.kbd.keycode == Common::KEYCODE_i) || (event.kbd.keycode == Common::KEYCODE_F1))
|
||||
instructions();
|
||||
break; // We don't show the instructions and simply go on with the minigame if not I or F1 was pressed.
|
||||
}
|
||||
}
|
||||
|
||||
setup();
|
||||
|
||||
while ((_time != 0) && (!_vm->shouldQuit())) {
|
||||
uint32 beginLoop = _vm->_system->getMillis();
|
||||
|
||||
blankIt();
|
||||
hitPeople();
|
||||
plotThem();
|
||||
moveThem();
|
||||
moveAvvy();
|
||||
bumpFolk();
|
||||
peopleRunning();
|
||||
animate();
|
||||
escapeCheck();
|
||||
collisionCheck();
|
||||
updateTime();
|
||||
check321();
|
||||
readKbd();
|
||||
|
||||
_cp = !_cp;
|
||||
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
uint32 delay = _vm->_system->getMillis() - beginLoop;
|
||||
if (delay <= 55)
|
||||
_vm->_system->delayMillis(55 - delay); // Replaces slowdown(); 55 comes from 18.2 Hz (B Flight).
|
||||
};
|
||||
|
||||
_vm->fadeOut();
|
||||
_vm->_graphics->restoreScreen();
|
||||
_vm->_graphics->removeBackup();
|
||||
_vm->fadeIn();
|
||||
CursorMan.showMouse(true);
|
||||
|
||||
return _score;
|
||||
}
|
||||
|
||||
bool ShootEmUp::overlap(uint16 a1x, uint16 a1y, uint16 a2x, uint16 a2y, uint16 b1x, uint16 b1y, uint16 b2x, uint16 b2y) {
|
||||
// By De Morgan's law:
|
||||
return (a2x >= b1x) && (b2x >= a1x) && (a2y >= b1y) && (b2y >= a1y);
|
||||
}
|
||||
|
||||
byte ShootEmUp::getStockNumber(byte index) {
|
||||
while (_hasEscaped[index]) {
|
||||
index++;
|
||||
if (index == 7)
|
||||
index = 0;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void ShootEmUp::blankIt() {
|
||||
for (int i = 0; i < _rectNum; i++)
|
||||
_vm->_graphics->drawFilledRectangle(_rectangles[i], kColorBlack);
|
||||
_rectNum = 0;
|
||||
}
|
||||
|
||||
void ShootEmUp::moveThem() {
|
||||
for (int i = 0; i < 99; i++) {
|
||||
if (_sprites[i]._x != kFlag) {
|
||||
_sprites[i]._x += _sprites[i]._ix;
|
||||
_sprites[i]._y += _sprites[i]._iy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::blank(Common::Rect rect) {
|
||||
_rectangles[_rectNum++] = rect;
|
||||
}
|
||||
|
||||
void ShootEmUp::plotThem() {
|
||||
for (int i = 0; i < 99; i++) {
|
||||
if (_sprites[i]._x != kFlag) {
|
||||
if (_sprites[i]._cameo) {
|
||||
_vm->_graphics->seuDrawCameo(_sprites[i]._x, _sprites[i]._y, _sprites[i]._p, _sprites[i]._cameoFrame);
|
||||
if (!_cp) {
|
||||
_sprites[i]._cameoFrame += 2;
|
||||
_sprites[i]._p += 2;
|
||||
}
|
||||
} else
|
||||
_vm->_graphics->seuDrawPicture(_sprites[i]._x, _sprites[i]._y, _sprites[i]._p);
|
||||
|
||||
if (_sprites[i]._wipe)
|
||||
blank(Common::Rect(_sprites[i]._x, _sprites[i]._y, _sprites[i]._x + _vm->_graphics->seuGetPicWidth(_sprites[i]._p), _sprites[i]._y + _vm->_graphics->seuGetPicHeight(_sprites[i]._p)));
|
||||
|
||||
if (_sprites[i]._timeout > 0) {
|
||||
_sprites[i]._timeout--;
|
||||
if (_sprites[i]._timeout == 0)
|
||||
_sprites[i]._x = kFlag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::define(int16 x, int16 y, int8 p, int8 ix, int8 iy, int16 time, bool isAMissile, bool doWeWipe) {
|
||||
for (int i = 0; i < 99; i++) {
|
||||
if (_sprites[i]._x == kFlag) {
|
||||
_sprites[i]._x = x;
|
||||
_sprites[i]._y = y;
|
||||
_sprites[i]._p = p;
|
||||
_sprites[i]._ix = ix;
|
||||
_sprites[i]._iy = iy;
|
||||
_sprites[i]._timeout = time;
|
||||
_sprites[i]._cameo = false;
|
||||
_sprites[i]._missile = isAMissile;
|
||||
_sprites[i]._wipe = doWeWipe;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::defineCameo(int16 x, int16 y, int8 p, int16 time) {
|
||||
for (int i = 0; i < 99; i++) {
|
||||
if (_sprites[i]._x == kFlag) {
|
||||
_sprites[i]._x = x;
|
||||
_sprites[i]._y = y;
|
||||
_sprites[i]._p = p;
|
||||
_sprites[i]._ix = 0;
|
||||
_sprites[i]._iy = 0;
|
||||
_sprites[i]._timeout = time;
|
||||
_sprites[i]._cameo = true;
|
||||
_sprites[i]._cameoFrame = p + 1;
|
||||
_sprites[i]._missile = false;
|
||||
_sprites[i]._wipe = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::showStock(byte index) {
|
||||
if (_escaping && (index == _escapeStock)) {
|
||||
_vm->_graphics->seuDrawPicture(index * 90 + 20, 30, kStocks + 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_stockStatus[index] > 5)
|
||||
return;
|
||||
|
||||
_vm->_graphics->seuDrawPicture(index * 90 + 20, 30, kStocks + _stockStatus[index]);
|
||||
_stockStatus[index] = 1 - _stockStatus[index];
|
||||
}
|
||||
|
||||
void ShootEmUp::drawNumber(int number, int size, int x) {
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
int divisor = 10;
|
||||
for (int j = 0; j < size - 2 - i; j++)
|
||||
divisor *= 10;
|
||||
char value = number / divisor;
|
||||
_vm->_graphics->seuDrawPicture(x + i * 10, 0, value);
|
||||
number -= value * divisor;
|
||||
}
|
||||
_vm->_graphics->seuDrawPicture(x + (size - 1) * 10, 0, number % 10);
|
||||
}
|
||||
|
||||
void ShootEmUp::showScore() {
|
||||
drawNumber(_score, 5, 40);
|
||||
}
|
||||
|
||||
void ShootEmUp::showTime() {
|
||||
drawNumber(_time, 3, 140);
|
||||
}
|
||||
|
||||
void ShootEmUp::gain(int8 howMuch) {
|
||||
if ((_score + howMuch) < 0) // howMuch can be negative!
|
||||
_score = 0;
|
||||
else
|
||||
_score += howMuch;
|
||||
|
||||
showScore();
|
||||
}
|
||||
|
||||
void ShootEmUp::newEscape() {
|
||||
_escapeCount = _vm->_rnd->getRandomNumber(17) * 20;
|
||||
_escaping = false;
|
||||
}
|
||||
|
||||
void ShootEmUp::nextPage() {
|
||||
_vm->_graphics->drawNormalText("Press a key for next page >", _vm->_font, 8, 400, 190, kColorWhite);
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
while (!_vm->shouldQuit()) {
|
||||
Common::Event event;
|
||||
_vm->getEvent(event);
|
||||
if (event.type == Common::EVENT_KEYDOWN) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_graphics->blackOutScreen();
|
||||
}
|
||||
|
||||
void ShootEmUp::instructions() {
|
||||
_vm->_graphics->blackOutScreen();
|
||||
_vm->_graphics->seuDrawPicture(25, 25, kFacingRight);
|
||||
_vm->_graphics->drawNormalText("< Avvy, our hero, needs your help - you must move him around.", _vm->_font, 8, 60, 35, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("(He''s too terrified to move himself!)", _vm->_font, 8, 80, 45, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("Your task is to prevent the people in the stocks from escaping", _vm->_font, 8, 0, 75, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("by pelting them with rotten fruit, eggs and bread. The keys are:", _vm->_font, 8, 0, 85, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("LEFT SHIFT", _vm->_font, 8, 80, 115, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("Move left.", _vm->_font, 8, 200, 115, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("RIGHT SHIFT", _vm->_font, 8, 72, 135, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("Move right.", _vm->_font, 8, 200, 135, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("ALT", _vm->_font, 8, 136, 155, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("Throw something.", _vm->_font, 8, 200, 155, kColorWhite);
|
||||
|
||||
nextPage();
|
||||
|
||||
_vm->_graphics->seuDrawPicture(25, 35, kStocks);
|
||||
_vm->_graphics->drawNormalText("This man is in the stocks. Your job is to stop him getting out.", _vm->_font, 8, 80, 35, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("UNFORTUNATELY... the locks on the stocks are loose, and every", _vm->_font, 8, 88, 45, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("so often, someone will discover this and try to get out.", _vm->_font, 8, 88, 55, kColorWhite);
|
||||
_vm->_graphics->seuDrawPicture(25, 85, kStocks + 2);
|
||||
_vm->_graphics->drawNormalText("< Someone who has found a way out!", _vm->_font, 8, 80, 85, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("You MUST IMMEDIATELY hit people smiling like this, or they", _vm->_font, 8, 88, 95, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("will disappear and lose you points.", _vm->_font, 8, 88, 105, kColorWhite);
|
||||
_vm->_graphics->seuDrawPicture(25, 125, kStocks + 5);
|
||||
_vm->_graphics->seuDrawPicture(25, 155, kStocks + 4);
|
||||
_vm->_graphics->drawNormalText("< Oh dear!", _vm->_font, 8, 80, 125, kColorWhite);
|
||||
|
||||
nextPage();
|
||||
|
||||
_vm->_graphics->drawNormalText("Your task is made harder by:", _vm->_font, 8, 0, 35, kColorWhite);
|
||||
_vm->_graphics->seuDrawPicture(25, 55, 48);
|
||||
_vm->_graphics->drawNormalText("< Yokels. These people will run in front of you. If you hit", _vm->_font, 8, 60, 55, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("them, you will lose MORE points than you get hitting people", _vm->_font, 8, 68, 65, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("in the stocks. So BEWARE!", _vm->_font, 8, 68, 75, kColorWhite);
|
||||
_vm->_graphics->drawNormalText("Good luck with the game!", _vm->_font, 8, 80, 125, kColorWhite);
|
||||
|
||||
nextPage();
|
||||
}
|
||||
|
||||
void ShootEmUp::setup() {
|
||||
_vm->_graphics->blackOutScreen();
|
||||
|
||||
newEscape();
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
_stockStatus[i] = _vm->_rnd->getRandomNumber(1);
|
||||
showStock(i);
|
||||
}
|
||||
|
||||
// Set up status line:
|
||||
_vm->_graphics->seuDrawPicture(0, 0, 16); // Score:
|
||||
showScore(); // Value of score (00000 here).
|
||||
_vm->_graphics->seuDrawPicture(110, 0, 19); // Time:
|
||||
showTime(); // Value of time.
|
||||
|
||||
_vm->_graphics->refreshScreen();
|
||||
|
||||
// From the original core cycle:
|
||||
initRunner(20, 70, 48, 54, _vm->_rnd->getRandomNumber(4) + 1, _vm->_rnd->getRandomNumber(3) - 2);
|
||||
initRunner(600, 70, 48, 54, _vm->_rnd->getRandomNumber(4) + 1, _vm->_rnd->getRandomNumber(3) - 2);
|
||||
initRunner(600, 100, 61, 67, (-(int8)_vm->_rnd->getRandomNumber(4)) + 1, _vm->_rnd->getRandomNumber(3) - 2);
|
||||
initRunner(20, 100, 61, 67, (-(int8)_vm->_rnd->getRandomNumber(4)) + 1, _vm->_rnd->getRandomNumber(3) - 2);
|
||||
}
|
||||
|
||||
void ShootEmUp::initRunner(int16 x, int16 y, byte f1, byte f2, int8 ix, int8 iy) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (_running[i]._x == kFlag) {
|
||||
_running[i]._x = x;
|
||||
_running[i]._y = y;
|
||||
_running[i]._frame = f1;
|
||||
_running[i]._tooHigh = f2;
|
||||
_running[i]._lowest = f1;
|
||||
_running[i]._ix = ix;
|
||||
_running[i]._iy = iy;
|
||||
if ((ix == 0) && (iy == 0))
|
||||
_running[i]._ix = 2; // To stop them running on the spot!
|
||||
_running[i]._frameDelay = kFrameDelayMax;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::moveAvvy() {
|
||||
if (_avvyWas < _avvyPos)
|
||||
_avvyFacing = kFacingRight;
|
||||
else if (_avvyWas > _avvyPos)
|
||||
_avvyFacing = kFacingLeft;
|
||||
|
||||
if (!_firing) {
|
||||
if (_avvyWas == _avvyPos)
|
||||
_avvyAnim = 1;
|
||||
else {
|
||||
_avvyAnim++;
|
||||
if (_avvyAnim == 6)
|
||||
_avvyAnim = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (_avvyFacing == kAvvyShoots)
|
||||
define(_avvyPos, kAvvyY, kShooting[_avvyAnim], 0, 0, 1, false, true);
|
||||
else
|
||||
define(_avvyPos, kAvvyY, _avvyAnim + _avvyFacing, 0, 0, 1, false, true);
|
||||
|
||||
_avvyWas = _avvyPos;
|
||||
|
||||
if (_avvyFacing == kAvvyShoots) {
|
||||
if (_avvyAnim == 6) {
|
||||
_avvyFacing = _wasFacing;
|
||||
_avvyAnim = 0;
|
||||
_firing = false;
|
||||
} else
|
||||
_avvyAnim++;
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::readKbd() {
|
||||
Common::Event event;
|
||||
_vm->getEvent(event);
|
||||
|
||||
if ((event.type == Common::EVENT_KEYUP) && ((event.kbd.keycode == Common::KEYCODE_LALT) || (event.kbd.keycode == Common::KEYCODE_RALT))) {
|
||||
// Don't let the player fire continuously by holding down one of the ALT keys.
|
||||
_altWasPressedBefore = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_firing) // So you can't stack up shots while the shooting animation plays.
|
||||
return;
|
||||
|
||||
if (event.type == Common::EVENT_KEYDOWN) {
|
||||
switch (event.kbd.keycode) {
|
||||
case Common::KEYCODE_LALT: // Alt was pressed - shoot!
|
||||
case Common::KEYCODE_RALT: // Falltrough is intended.
|
||||
if (_altWasPressedBefore || (_count321 != 0))
|
||||
return;
|
||||
|
||||
_altWasPressedBefore = true;
|
||||
_firing = true;
|
||||
define(_avvyPos + 27, kAvvyY + 5, _throwNext, 0, -2, 53, true, true);
|
||||
_throwNext++;
|
||||
if (_throwNext == 79)
|
||||
_throwNext = 73;
|
||||
_avvyAnim = 0;
|
||||
_wasFacing = _avvyFacing;
|
||||
_avvyFacing = kAvvyShoots;
|
||||
return;
|
||||
case Common::KEYCODE_RSHIFT: // Right shift: move right.
|
||||
_avvyPos += 5;
|
||||
if (_avvyPos > kRightMargin)
|
||||
_avvyPos = kRightMargin;
|
||||
return;
|
||||
case Common::KEYCODE_LSHIFT: // Left shift: move left.
|
||||
_avvyPos -= 5;
|
||||
if (_avvyPos < kLeftMargin)
|
||||
_avvyPos = kLeftMargin;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::animate() {
|
||||
if (_vm->_rnd->getRandomNumber(9) == 1)
|
||||
showStock(getStockNumber(_vm->_rnd->getRandomNumber(5)));
|
||||
for (int i = 0; i < 7; i++) {
|
||||
if (_stockStatus[i] > 5) {
|
||||
_stockStatus[i]--;
|
||||
if (_stockStatus[i] == 8) {
|
||||
_stockStatus[i] = 0;
|
||||
showStock(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::collisionCheck() {
|
||||
for (int i = 0; i < 99; i++) {
|
||||
if ((_sprites[i]._x != kFlag) && (_sprites[i]._missile) &&
|
||||
(_sprites[i]._y < 60) && (_sprites[i]._timeout == 1)) {
|
||||
int distFromSide = (_sprites[i]._x - 20) % 90;
|
||||
int thisStock = (_sprites[i]._x - 20) / 90;
|
||||
if ((!_hasEscaped[thisStock]) && (distFromSide > 17) && (distFromSide < 34)) {
|
||||
_vm->_sound->playNote(999, 3);
|
||||
_vm->_system->delayMillis(3);
|
||||
define(_sprites[i]._x + 20, _sprites[i]._y, 25 + _vm->_rnd->getRandomNumber(1), 3, 1, 12, false, true); // Well done!
|
||||
define(thisStock * 90 + 20, 30, 30, 0, 0, 7, false, false); // Face of man
|
||||
defineCameo(thisStock * 90 + 20 + 10, 35, 40, 7); // Splat!
|
||||
define(thisStock * 90 + 20 + 20, 50, 33 + _vm->_rnd->getRandomNumber(4), 0, 2, 9, false, true); // Oof!
|
||||
_stockStatus[thisStock] = 17;
|
||||
gain(3); // Score for hitting a face.
|
||||
|
||||
if (_escaping && (_escapeStock = thisStock)) { // Hit the escaper.
|
||||
_vm->_sound->playNote(1777, 1);
|
||||
_vm->_system->delayMillis(1);
|
||||
gain(5); // Bonus for hitting escaper.
|
||||
_escaping = false;
|
||||
newEscape();
|
||||
}
|
||||
} else {
|
||||
define(_sprites[i]._x, _sprites[i]._y, 82 + _vm->_rnd->getRandomNumber(2), 2, 2, 17, false, true); // Missed!
|
||||
if ((!_hasEscaped[thisStock]) && (distFromSide > 3) && (distFromSide < 43)) {
|
||||
define(thisStock * 90 + 20, 30, 29, 0, 0, 7, false, false); // Face of man
|
||||
if (distFromSide > 35)
|
||||
defineCameo(_sprites[i]._x - 27, 35, 40, 7); // Splat!
|
||||
else
|
||||
defineCameo(_sprites[i]._x - 7, 35, 40, 7);
|
||||
_stockStatus[thisStock] = 17;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::turnAround(byte who, bool randomX) {
|
||||
if (randomX) {
|
||||
int8 ix = (_vm->_rnd->getRandomNumber(4) + 1);
|
||||
if (_running[who]._ix > 0)
|
||||
_running[who]._ix = -(ix);
|
||||
else
|
||||
_running[who]._ix = ix;
|
||||
} else
|
||||
_running[who]._ix = -(_running[who]._ix);
|
||||
|
||||
_running[who]._iy = -(_running[who]._iy);
|
||||
}
|
||||
|
||||
void ShootEmUp::bumpFolk() {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (_running[i]._x != kFlag) {
|
||||
for (int j = i + 1; j < 4; j++) {
|
||||
bool overlaps = overlap(_running[i]._x, _running[i]._y, _running[i]._x + 17, _running[i]._y + 24,
|
||||
_running[j]._x, _running[j]._y, _running[j]._x + 17, _running[j]._y + 24);
|
||||
if ((_running[i]._x != kFlag) && overlaps) {
|
||||
turnAround(i, false); // Opp. directions.
|
||||
turnAround(j, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::peopleRunning() {
|
||||
if (_count321 != 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (_running[i]._x != kFlag) {
|
||||
if (((_running[i]._y + _running[i]._iy) <= 53) || ((_running[i]._y + _running[i]._iy) >= 120))
|
||||
_running[i]._iy = -(_running[i]._iy);
|
||||
|
||||
byte frame = 0;
|
||||
if (_running[i]._ix < 0)
|
||||
frame = _running[i]._frame - 1;
|
||||
else
|
||||
frame = _running[i]._frame + 6;
|
||||
define(_running[i]._x, _running[i]._y, frame, 0, 0, 1, false, true);
|
||||
|
||||
if (_running[i]._frameDelay == 0) {
|
||||
_running[i]._frame++;
|
||||
if (_running[i]._frame == _running[i]._tooHigh)
|
||||
_running[i]._frame = _running[i]._lowest;
|
||||
_running[i]._frameDelay = kFrameDelayMax;
|
||||
_running[i]._y += _running[i]._iy;
|
||||
} else
|
||||
_running[i]._frameDelay--;
|
||||
|
||||
if (((_running[i]._x + _running[i]._ix) <= 0) || ((_running[i]._x + _running[i]._ix) >= 620))
|
||||
turnAround(i, true);
|
||||
|
||||
_running[i]._x += _running[i]._ix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::updateTime() {
|
||||
if (_count321 != 0)
|
||||
return;
|
||||
|
||||
_timeThisSecond++;
|
||||
|
||||
if (_timeThisSecond < kTimesASecond)
|
||||
return;
|
||||
|
||||
_time--;
|
||||
showTime();
|
||||
_timeThisSecond = 0;
|
||||
|
||||
if (_time <= kFlashTime) {
|
||||
int timeMode = 0;
|
||||
if ((_time % 2) == 1)
|
||||
timeMode = 19; // Normal 'Time:'
|
||||
else
|
||||
timeMode = 85; // Flash 'Time:'
|
||||
|
||||
_vm->_graphics->seuDrawPicture(110, 0, timeMode);
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::hitPeople() {
|
||||
if (_count321 != 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < 99; i++) {
|
||||
if ((_sprites[i]._missile) && (_sprites[i]._x != kFlag)) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
|
||||
bool overlaps = overlap(_sprites[i]._x, _sprites[i]._y, _sprites[i]._x + 7, _sprites[i]._y + 10,
|
||||
_running[j]._x, _running[j]._y, _running[j]._x + 17, _running[j]._y + 24);
|
||||
|
||||
if ((_running[j]._x != kFlag) && (overlaps)) {
|
||||
_vm->_sound->playNote(7177, 1);
|
||||
_sprites[i]._x = kFlag;
|
||||
gain(-5);
|
||||
define(_running[j]._x + 20, _running[j]._y + 3, 33 + _vm->_rnd->getRandomNumber(5), 1, 3, 9, false, true); // Oof!
|
||||
define(_sprites[i]._x, _sprites[i]._y, 82, 1, 0, 17, false, true); // Oops!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::escapeCheck() {
|
||||
if (_count321 != 0)
|
||||
return;
|
||||
|
||||
if (_escapeCount > 0) {
|
||||
_escapeCount--;
|
||||
return;
|
||||
}
|
||||
|
||||
// Escape_count = 0; now what ?
|
||||
|
||||
if (_escaping) {
|
||||
if (_gotOut) {
|
||||
newEscape();
|
||||
_escaping = false;
|
||||
_vm->_graphics->seuDrawPicture(_escapeStock * 90 + 20, 30, kStocks + 4);
|
||||
} else {
|
||||
_vm->_graphics->seuDrawPicture(_escapeStock * 90 + 20, 30, kStocks + 5);
|
||||
_escapeCount = 20;
|
||||
_gotOut = true;
|
||||
define(_escapeStock * 90 + 20, 50, 24, 0, 2, 17, false, true); // Escaped!
|
||||
gain(-10);
|
||||
_hasEscaped[_escapeStock] = true;
|
||||
|
||||
_howManyHaveEscaped++;
|
||||
|
||||
if (_howManyHaveEscaped == 7) {
|
||||
_vm->_graphics->seuDrawPicture(266, 90, 23);
|
||||
_time = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_escapeStock = getStockNumber(_vm->_rnd->getRandomNumber(6));
|
||||
_escaping = true;
|
||||
_gotOut = false;
|
||||
_vm->_graphics->seuDrawPicture(_escapeStock * 90 + 20, 30, kStocks + 2); // Smiling!
|
||||
_escapeCount = 200;
|
||||
}
|
||||
}
|
||||
|
||||
void ShootEmUp::check321() {
|
||||
if (_count321 == 0)
|
||||
return;
|
||||
|
||||
_count321--;
|
||||
|
||||
switch (_count321) {
|
||||
case 84:
|
||||
define(320, 60, 15, 2, 1, 94, false, true);
|
||||
break;
|
||||
case 169:
|
||||
define(320, 60, 14, 0, 1, 94, false, true);
|
||||
break;
|
||||
case 254:
|
||||
define(320, 60, 13, -2, 1, 94, false, true);
|
||||
define(0, 100, 17, 2, 0, 254, false, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche
|
||||
133
engines/avalanche/shootemup.h
Normal file
133
engines/avalanche/shootemup.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AVALANCHE_SHOOTEMUP_H
|
||||
#define AVALANCHE_SHOOTEMUP_H
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
class ShootEmUp {
|
||||
public:
|
||||
ShootEmUp(AvalancheEngine *vm);
|
||||
|
||||
uint16 run();
|
||||
|
||||
private:
|
||||
struct Sprite {
|
||||
int8 _ix, _iy;
|
||||
int16 _x, _y;
|
||||
int8 _p;
|
||||
int16 _timeout;
|
||||
bool _cameo;
|
||||
byte _cameoFrame;
|
||||
bool _missile;
|
||||
bool _wipe;
|
||||
};
|
||||
|
||||
struct Runner {
|
||||
int16 _x, _y;
|
||||
byte _frame;
|
||||
byte _tooHigh;
|
||||
byte _lowest;
|
||||
int8 _ix, _iy;
|
||||
byte _frameDelay;
|
||||
};
|
||||
|
||||
static const byte kStocks;
|
||||
static const byte kAvvyShoots;
|
||||
static const byte kFacingRight;
|
||||
static const byte kFacingLeft;
|
||||
static const long int kFlag;
|
||||
static const byte kFrameDelayMax;
|
||||
static const byte kAvvyY;
|
||||
static const byte kShooting[7];
|
||||
static const byte kTimesASecond;
|
||||
static const byte kFlashTime;
|
||||
static const byte kLeftMargin;
|
||||
static const int16 kRightMargin;
|
||||
|
||||
AvalancheEngine *_vm;
|
||||
|
||||
uint16 _score;
|
||||
byte _time;
|
||||
byte _stockStatus[7];
|
||||
Sprite _sprites[99];
|
||||
byte _rectNum; // Original: 'rsize'
|
||||
Common::Rect _rectangles[99];
|
||||
uint16 _avvyWas;
|
||||
uint16 _avvyPos;
|
||||
byte _avvyAnim;
|
||||
byte _avvyFacing;
|
||||
bool _altWasPressedBefore;
|
||||
byte _throwNext;
|
||||
bool _firing;
|
||||
Runner _running[4];
|
||||
bool _hasEscaped[7];
|
||||
byte _count321;
|
||||
byte _howManyHaveEscaped;
|
||||
uint16 _escapeCount;
|
||||
bool _escaping;
|
||||
byte _timeThisSecond;
|
||||
bool _cp;
|
||||
byte _wasFacing;
|
||||
byte _escapeStock;
|
||||
bool _gotOut;
|
||||
|
||||
bool overlap(uint16 a1x, uint16 a1y, uint16 a2x, uint16 a2y, uint16 b1x, uint16 b1y, uint16 b2x, uint16 b2y);
|
||||
byte getStockNumber(byte index);
|
||||
void blankIt();
|
||||
void moveThem();
|
||||
void blank(Common::Rect rect);
|
||||
void plotThem();
|
||||
void define(int16 x, int16 y, int8 p, int8 ix, int8 iy, int16 time, bool isAMissile, bool doWeWipe);
|
||||
void defineCameo(int16 x, int16 y, int8 p, int16 time);
|
||||
void showStock(byte index);
|
||||
void drawNumber(int number, int size, int x);
|
||||
void showScore();
|
||||
void showTime();
|
||||
void gain(int8 howMuch);
|
||||
void newEscape();
|
||||
void nextPage(); // Internal function of 'instructions' in the original.
|
||||
void instructions();
|
||||
void setup();
|
||||
void initRunner(int16 xx, int16 yy, byte f1, byte f2, int8 ixx, int8 iyy);
|
||||
void moveAvvy();
|
||||
void readKbd();
|
||||
void animate();
|
||||
void collisionCheck();
|
||||
void turnAround(byte who, bool randomX);
|
||||
void bumpFolk();
|
||||
void peopleRunning();
|
||||
void updateTime();
|
||||
void hitPeople();
|
||||
void escapeCheck();
|
||||
void check321();
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_SHOOTEMUP_H
|
||||
87
engines/avalanche/sound.cpp
Normal file
87
engines/avalanche/sound.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "avalanche/avalanche.h"
|
||||
#include "avalanche/sound.h"
|
||||
|
||||
#include "audio/softsynth/pcspk.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
SoundHandler::SoundHandler(AvalancheEngine *vm) : _vm(vm) {
|
||||
_soundFl = true;
|
||||
_speaker = new Audio::PCSpeaker();
|
||||
_speaker->init();
|
||||
}
|
||||
|
||||
SoundHandler::~SoundHandler() {
|
||||
delete _speaker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop any sound that might be playing
|
||||
*/
|
||||
void SoundHandler::stopSound() {
|
||||
_vm->_mixer->stopAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn digitized sound on and off
|
||||
*/
|
||||
void SoundHandler::toggleSound() {
|
||||
_soundFl = !_soundFl;
|
||||
_vm->_graphics->drawSoundLight(_soundFl);
|
||||
}
|
||||
|
||||
void SoundHandler::syncVolume() {
|
||||
int soundVolume;
|
||||
|
||||
if (ConfMan.getBool("sfx_mute") || ConfMan.getBool("mute"))
|
||||
soundVolume = -1;
|
||||
else
|
||||
soundVolume = MIN(255, ConfMan.getInt("sfx_volume"));
|
||||
|
||||
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolume);
|
||||
}
|
||||
|
||||
void SoundHandler::playNote(int freq, int length) {
|
||||
// Does the user not want any sound?
|
||||
if (!_soundFl || !_vm->_mixer->isReady())
|
||||
return;
|
||||
|
||||
// Start a note playing (we will stop it when the timer expires).
|
||||
_speaker->play(Audio::PCSpeaker::kWaveFormSquare, freq, length);
|
||||
}
|
||||
|
||||
void SoundHandler::click() {
|
||||
_vm->_mixer->stopAll();
|
||||
|
||||
playNote(7177, 1);
|
||||
}
|
||||
|
||||
void SoundHandler::blip() {
|
||||
_vm->_mixer->stopAll();
|
||||
|
||||
playNote(177, 77);
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche
|
||||
54
engines/avalanche/sound.h
Normal file
54
engines/avalanche/sound.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AVALANCHE_SOUND_H
|
||||
#define AVALANCHE_SOUND_H
|
||||
|
||||
#include "audio/mixer.h"
|
||||
|
||||
namespace Audio {
|
||||
class PCSpeaker;
|
||||
}
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
class SoundHandler {
|
||||
public:
|
||||
bool _soundFl;
|
||||
|
||||
SoundHandler(AvalancheEngine *vm);
|
||||
~SoundHandler();
|
||||
|
||||
void toggleSound();
|
||||
void playNote(int freq, int length);
|
||||
void click();
|
||||
void blip();
|
||||
void syncVolume();
|
||||
void stopSound();
|
||||
|
||||
private:
|
||||
AvalancheEngine *_vm;
|
||||
Audio::PCSpeaker *_speaker;
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche
|
||||
|
||||
#endif // AVALANCHE_SOUND_H
|
||||
713
engines/avalanche/timer.cpp
Normal file
713
engines/avalanche/timer.cpp
Normal file
@@ -0,0 +1,713 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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: TIMEOUT The scheduling unit. */
|
||||
|
||||
#include "avalanche/avalanche.h"
|
||||
#include "avalanche/timer.h"
|
||||
|
||||
namespace Avalanche {
|
||||
|
||||
Timer::Timer(AvalancheEngine *vm) {
|
||||
_vm = vm;
|
||||
|
||||
resetVariables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a nex timer
|
||||
* @remarks Originally called 'set_up_timer'
|
||||
*/
|
||||
void Timer::addTimer(int32 duration, byte action, byte reason) {
|
||||
byte i = 0;
|
||||
while ((i < 7) && (_times[i]._timeLeft != 0)) {
|
||||
if (_times[i]._reason == reason) // We only add a timer if it's not already in the array.
|
||||
return;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == 7)
|
||||
return; // Oh dear... No timer left
|
||||
|
||||
// Everything's OK here!
|
||||
_times[i]._timeLeft = duration;
|
||||
_times[i]._action = action;
|
||||
_times[i]._reason = reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the timers
|
||||
* @remarks Originally called 'one_tick'
|
||||
*/
|
||||
void Timer::updateTimer() {
|
||||
if (_vm->_dropdown->isActive())
|
||||
return;
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
if (_times[i]._timeLeft <= 0)
|
||||
continue;
|
||||
|
||||
_times[i]._timeLeft--;
|
||||
|
||||
if (_times[i]._timeLeft == 0) {
|
||||
switch (_times[i]._action) {
|
||||
case kProcOpenDrawbridge :
|
||||
openDrawbridge();
|
||||
break;
|
||||
case kProcAvariciusTalks :
|
||||
avariciusTalks();
|
||||
break;
|
||||
case kProcUrinate :
|
||||
urinate();
|
||||
break;
|
||||
case kProcToilet :
|
||||
toilet();
|
||||
break;
|
||||
case kProcBang:
|
||||
bang();
|
||||
break;
|
||||
case kProcBang2:
|
||||
bang2();
|
||||
break;
|
||||
case kProcStairs:
|
||||
stairs();
|
||||
break;
|
||||
case kProcCardiffSurvey:
|
||||
cardiffSurvey();
|
||||
break;
|
||||
case kProcCardiffReturn:
|
||||
cardiffReturn();
|
||||
break;
|
||||
case kProcCwytalotInHerts:
|
||||
cwytalotInHerts();
|
||||
break;
|
||||
case kProcGetTiedUp:
|
||||
getTiedUp();
|
||||
break;
|
||||
case kProcGetTiedUp2:
|
||||
getTiedUp2();
|
||||
break;
|
||||
case kProcHangAround:
|
||||
hangAround();
|
||||
break;
|
||||
case kProcHangAround2:
|
||||
hangAround2();
|
||||
break;
|
||||
case kProcAfterTheShootemup:
|
||||
afterTheShootemup();
|
||||
break;
|
||||
case kProcJacquesWakesUp:
|
||||
jacquesWakesUp();
|
||||
break;
|
||||
case kProcNaughtyDuke:
|
||||
naughtyDuke();
|
||||
break;
|
||||
case kProcNaughtyDuke2:
|
||||
naughtyDuke2();
|
||||
break;
|
||||
case kProcNaughtyDuke3:
|
||||
naughtyDuke3();
|
||||
break;
|
||||
case kProcJump:
|
||||
jump();
|
||||
break;
|
||||
case kProcSequence:
|
||||
_vm->_sequence->callSequencer();
|
||||
break;
|
||||
case kProcCrapulusSpludOut:
|
||||
crapulusSaysSpludOut();
|
||||
break;
|
||||
case kProcDawnDelay:
|
||||
_vm->fadeIn();
|
||||
break;
|
||||
case kProcBuyDrinks:
|
||||
buyDrinks();
|
||||
break;
|
||||
case kProcBuyWine:
|
||||
buyWine();
|
||||
break;
|
||||
case kProcCallsGuards:
|
||||
callsGuards();
|
||||
break;
|
||||
case kProcGreetsMonk:
|
||||
greetsMonk();
|
||||
break;
|
||||
case kProcFallDownOubliette:
|
||||
fallDownOubliette();
|
||||
break;
|
||||
case kProcMeetAvaroid:
|
||||
meetAvaroid();
|
||||
break;
|
||||
case kProcRiseUpOubliette:
|
||||
riseUpOubliette();
|
||||
break;
|
||||
case kProcRobinHoodAndGeida:
|
||||
robinHoodAndGeida();
|
||||
break;
|
||||
case kProcRobinHoodAndGeidaTalk:
|
||||
robinHoodAndGeidaTalk();
|
||||
break;
|
||||
case kProcAvalotReturns:
|
||||
avalotReturns();
|
||||
break;
|
||||
case kProcAvvySitDown:
|
||||
avvySitDown();
|
||||
break;
|
||||
case kProcGhostRoomPhew:
|
||||
ghostRoomPhew();
|
||||
break;
|
||||
case kProcArkataShouts:
|
||||
arkataShouts();
|
||||
break;
|
||||
case kProcWinning:
|
||||
winning();
|
||||
break;
|
||||
case kProcAvalotFalls:
|
||||
avalotFalls();
|
||||
break;
|
||||
case kProcSpludwickGoesToCauldron:
|
||||
spludwickGoesToCauldron();
|
||||
break;
|
||||
case kProcSpludwickLeavesCauldron:
|
||||
spludwickLeavesCauldron();
|
||||
break;
|
||||
case kProcGiveLuteToGeida:
|
||||
giveLuteToGeida();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_roomCycles++; // Cycles since you've been in this room.
|
||||
}
|
||||
|
||||
void Timer::loseTimer(byte which) {
|
||||
for (int i = 0; i < 7; i++) {
|
||||
if (_times[i]._reason == which)
|
||||
_times[i]._timeLeft = 0; // Cancel this one!
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Timer::openDrawbridge() {
|
||||
_vm->_drawbridgeOpen++;
|
||||
_vm->_background->draw(-1, -1, _vm->_drawbridgeOpen - 2);
|
||||
|
||||
if (_vm->_drawbridgeOpen == 4)
|
||||
_vm->_magics[1]._operation = kMagicNothing; // You may enter the drawbridge.
|
||||
else
|
||||
addTimer(7, kProcOpenDrawbridge, kReasonDrawbridgeFalls);
|
||||
}
|
||||
|
||||
void Timer::avariciusTalks() {
|
||||
_vm->_dialogs->displayScrollChain('Q', _vm->_avariciusTalk);
|
||||
_vm->_avariciusTalk++;
|
||||
|
||||
if (_vm->_avariciusTalk < 17)
|
||||
addTimer(177, kProcAvariciusTalks, kReasonAvariciusTalks);
|
||||
else
|
||||
_vm->incScore(3);
|
||||
}
|
||||
|
||||
void Timer::urinate() {
|
||||
_vm->_animation->_sprites[0]->turn(kDirUp);
|
||||
_vm->_animation->stopWalking();
|
||||
_vm->drawDirection();
|
||||
addTimer(14, kProcToilet, kReasonGoToToilet);
|
||||
}
|
||||
|
||||
void Timer::toilet() {
|
||||
_vm->_dialogs->displayText("That's better!");
|
||||
}
|
||||
|
||||
void Timer::bang() {
|
||||
Common::String tmpStr = Common::String::format("%c< BANG! >", kControlItalic);
|
||||
_vm->_dialogs->displayText(tmpStr);
|
||||
addTimer(30, kProcBang2, kReasonExplosion);
|
||||
}
|
||||
|
||||
void Timer::bang2() {
|
||||
_vm->_dialogs->displayText("Hmm... sounds like Spludwick's up to something...");
|
||||
}
|
||||
|
||||
void Timer::stairs() {
|
||||
_vm->_sound->blip();
|
||||
_vm->_animation->_sprites[0]->walkTo(3);
|
||||
_vm->_background->draw(-1, -1, 1);
|
||||
_vm->_brummieStairs = 2;
|
||||
_vm->_magics[10]._operation = kMagicSpecial;
|
||||
_vm->_magics[10]._data = 2; // Reached the bottom of the stairs.
|
||||
_vm->_magics[3]._operation = kMagicNothing; // Stop them hitting the sides (or the game will hang.)
|
||||
}
|
||||
|
||||
void Timer::cardiffSurvey() {
|
||||
if (_vm->_cardiffQuestionNum == 0) {
|
||||
_vm->_cardiffQuestionNum++;
|
||||
_vm->_dialogs->displayScrollChain('Q', 27);
|
||||
}
|
||||
|
||||
_vm->_dialogs->displayScrollChain('Z', _vm->_cardiffQuestionNum);
|
||||
_vm->_interrogation = _vm->_cardiffQuestionNum;
|
||||
addTimer(182, kProcCardiffSurvey, kReasonCardiffsurvey);
|
||||
}
|
||||
|
||||
void Timer::cardiffReturn() {
|
||||
_vm->_dialogs->displayScrollChain('Q', 28);
|
||||
cardiffSurvey(); // Add end of question.
|
||||
}
|
||||
|
||||
void Timer::cwytalotInHerts() {
|
||||
_vm->_dialogs->displayScrollChain('Q', 29);
|
||||
}
|
||||
|
||||
void Timer::getTiedUp() {
|
||||
_vm->_dialogs->displayScrollChain('Q', 34); // ...Trouble!
|
||||
_vm->_userMovesAvvy = false;
|
||||
_vm->_beenTiedUp = true;
|
||||
_vm->_animation->stopWalking();
|
||||
|
||||
AnimationType *spr = _vm->_animation->_sprites[1];
|
||||
spr->stopWalk();
|
||||
spr->stopHoming();
|
||||
spr->_callEachStepFl = true;
|
||||
spr->_eachStepProc = Animation::kProcGrabAvvy;
|
||||
addTimer(70, kProcGetTiedUp2, kReasonGettingTiedUp);
|
||||
}
|
||||
|
||||
void Timer::getTiedUp2() {
|
||||
_vm->_animation->_sprites[0]->walkTo(3);
|
||||
_vm->_animation->_sprites[1]->walkTo(4);
|
||||
_vm->_magics[3]._operation = kMagicNothing; // No effect when you touch the boundaries.
|
||||
_vm->_friarWillTieYouUp = true;
|
||||
}
|
||||
|
||||
void Timer::hangAround() {
|
||||
_vm->_animation->_sprites[1]->_doCheck = false;
|
||||
|
||||
AnimationType *avvy = _vm->_animation->_sprites[0];
|
||||
avvy->init(7, true); // Robin Hood
|
||||
_vm->setRoom(kPeopleRobinHood, kRoomRobins);
|
||||
_vm->_animation->appearPed(0, 1);
|
||||
_vm->_dialogs->displayScrollChain('Q', 39);
|
||||
avvy->walkTo(6);
|
||||
addTimer(55, kProcHangAround2, kReasonHangingAround);
|
||||
}
|
||||
|
||||
void Timer::hangAround2() {
|
||||
_vm->_dialogs->displayScrollChain('Q', 40);
|
||||
AnimationType *spr = _vm->_animation->_sprites[1];
|
||||
spr->_vanishIfStill = false;
|
||||
spr->walkTo(3);
|
||||
_vm->setRoom(kPeopleFriarTuck, kRoomRobins);
|
||||
_vm->_dialogs->displayScrollChain('Q', 41);
|
||||
_vm->_animation->_sprites[0]->remove();
|
||||
spr->remove(); // Get rid of Robin Hood and Friar Tuck.
|
||||
|
||||
addTimer(1, kProcAfterTheShootemup, kReasonHangingAround); // Immediately call the following proc (when you have a chance).
|
||||
|
||||
_vm->_tiedUp = false;
|
||||
|
||||
// We don't need the ShootEmUp during the whole game, it's only playable once.
|
||||
ShootEmUp *shootemup = new ShootEmUp(_vm);
|
||||
_shootEmUpScore = shootemup->run();
|
||||
delete shootemup;
|
||||
}
|
||||
|
||||
void Timer::afterTheShootemup() {
|
||||
_vm->flipRoom(_vm->_room, 1);
|
||||
|
||||
_vm->_animation->_sprites[0]->init(0, true); // Avalot.
|
||||
_vm->_animation->appearPed(0, 1);
|
||||
_vm->_userMovesAvvy = true;
|
||||
_vm->_objects[kObjectCrossbow - 1] = true;
|
||||
_vm->refreshObjectList();
|
||||
|
||||
byte gain = (_shootEmUpScore + 5) / 10; // Rounding up.
|
||||
_vm->_dialogs->displayText(Common::String::format("%cYour score was %d.%c%cYou gain (%d \xf6 10) = %d points.", kControlItalic, _shootEmUpScore, kControlNewLine, kControlNewLine, _shootEmUpScore, gain));
|
||||
|
||||
if (gain > 20) {
|
||||
_vm->_dialogs->displayText("But we won't let you have more than 20 points!");
|
||||
_vm->incScore(20);
|
||||
} else
|
||||
_vm->incScore(gain);
|
||||
|
||||
|
||||
_vm->_dialogs->displayScrollChain('Q', 70);
|
||||
}
|
||||
|
||||
void Timer::jacquesWakesUp() {
|
||||
_vm->_jacquesState++;
|
||||
|
||||
switch (_vm->_jacquesState) { // Additional pictures.
|
||||
case 1:
|
||||
_vm->_background->draw(-1, -1, 0); // Eyes open.
|
||||
_vm->_dialogs->displayScrollChain('Q', 45);
|
||||
break;
|
||||
case 2: // Going through the door.
|
||||
_vm->_background->draw(-1, -1, 1); // Not on the floor.
|
||||
_vm->_background->draw(-1, -1, 2); // But going through the door.
|
||||
_vm->_magics[5]._operation = kMagicNothing; // You can't wake him up now.
|
||||
break;
|
||||
case 3: // Gone through the door.
|
||||
_vm->_background->draw(-1, -1, 1); // Not on the floor, either.
|
||||
_vm->_background->draw(-1, -1, 3); // He's gone... so the door's open.
|
||||
_vm->setRoom(kPeopleJacques, kRoomNowhere); // Gone!
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (_vm->_jacquesState == 5) {
|
||||
_vm->_bellsAreRinging = true;
|
||||
_vm->_aylesIsAwake = true;
|
||||
_vm->incScore(2);
|
||||
}
|
||||
|
||||
switch (_vm->_jacquesState) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
addTimer(12, kProcJacquesWakesUp, kReasonJacquesWakingUp);
|
||||
break;
|
||||
case 4:
|
||||
addTimer(24, kProcJacquesWakesUp, kReasonJacquesWakingUp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::naughtyDuke() { // This is when the Duke comes in and takes your money.
|
||||
AnimationType *spr = _vm->_animation->_sprites[1];
|
||||
spr->init(9, false); // Here comes the Duke.
|
||||
_vm->_animation->appearPed(1, 0); // He starts at the door...
|
||||
spr->walkTo(2); // He walks over to you.
|
||||
|
||||
// Let's get the door opening.
|
||||
_vm->_background->draw(-1, -1, 0);
|
||||
_vm->_sequence->startNaughtyDukeSeq();
|
||||
|
||||
addTimer(50, kProcNaughtyDuke2, kReasonNaughtyDuke);
|
||||
}
|
||||
|
||||
void Timer::naughtyDuke2() {
|
||||
AnimationType *spr = _vm->_animation->_sprites[1];
|
||||
_vm->_dialogs->displayScrollChain('Q', 48); // "Ha ha, it worked again!"
|
||||
spr->walkTo(0); // Walk to the door.
|
||||
spr->_vanishIfStill = true; // Then go away!
|
||||
|
||||
addTimer(32, kProcNaughtyDuke3, kReasonNaughtyDuke);
|
||||
}
|
||||
|
||||
void Timer::naughtyDuke3() {
|
||||
_vm->_background->draw(-1, -1, 0);
|
||||
_vm->_sequence->startNaughtyDukeSeq();
|
||||
}
|
||||
|
||||
void Timer::jump() {
|
||||
AnimationType *avvy = _vm->_animation->_sprites[0];
|
||||
|
||||
_vm->_jumpStatus++;
|
||||
switch (_vm->_jumpStatus) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 5:
|
||||
case 7:
|
||||
case 9:
|
||||
avvy->_y--;
|
||||
break;
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 16:
|
||||
case 18:
|
||||
case 19:
|
||||
avvy->_y++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (_vm->_jumpStatus == 20) { // End of jump.
|
||||
_vm->_userMovesAvvy = true;
|
||||
_vm->_jumpStatus = 0;
|
||||
} else // Still jumping.
|
||||
addTimer(1, kProcJump, kReasonJumping);
|
||||
|
||||
if ((_vm->_jumpStatus == 10) // You're at the highest point of your jump.
|
||||
&& (_vm->_room == kRoomInsideCardiffCastle)
|
||||
&& (_vm->_arrowInTheDoor == true)
|
||||
&& (_vm->_animation->inField(2))) { // Beside the wall
|
||||
// Grab the arrow!
|
||||
if (_vm->_carryNum >= kCarryLimit)
|
||||
_vm->_dialogs->displayText("You fail to grab it, because your hands are full.");
|
||||
else {
|
||||
_vm->_background->draw(-1, -1, 1);
|
||||
_vm->_arrowInTheDoor = false; // You've got it.
|
||||
_vm->_objects[kObjectBolt - 1] = true;
|
||||
_vm->refreshObjectList();
|
||||
_vm->_dialogs->displayScrollChain('Q', 50);
|
||||
_vm->incScore(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::crapulusSaysSpludOut() {
|
||||
_vm->_dialogs->displayScrollChain('Q', 56);
|
||||
_vm->_crapulusWillTell = false;
|
||||
}
|
||||
|
||||
void Timer::buyDrinks() {
|
||||
_vm->_background->draw(-1, -1, 10); // Malagauche gets up again.
|
||||
_vm->_malagauche = 0;
|
||||
|
||||
_vm->_dialogs->displayScrollChain('D', _vm->_drinking); // Display message about it.
|
||||
_vm->_animation->wobble(); // Do the special effects.
|
||||
_vm->_dialogs->displayScrollChain('D', 1); // That'll be thruppence.
|
||||
if (_vm->decreaseMoney(3)) // Pay 3d.
|
||||
_vm->_dialogs->displayScrollChain('D', 3); // Tell 'em you paid up.
|
||||
_vm->_parser->drink();
|
||||
}
|
||||
|
||||
void Timer::buyWine() {
|
||||
_vm->_background->draw(-1, -1, 10); // Malagauche gets up again.
|
||||
_vm->_malagauche = 0;
|
||||
|
||||
_vm->_dialogs->displayScrollChain('D', 50); // You buy the wine.
|
||||
_vm->_dialogs->displayScrollChain('D', 1); // It'll be thruppence.
|
||||
if (_vm->decreaseMoney(3)) {
|
||||
_vm->_dialogs->displayScrollChain('D', 4); // You paid up.
|
||||
_vm->_objects[kObjectWine - 1] = true;
|
||||
_vm->refreshObjectList();
|
||||
_vm->_wineState = 1; // OK Wine.
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::callsGuards() {
|
||||
_vm->_dialogs->displayScrollChain('Q', 58); // "GUARDS!!!"
|
||||
_vm->gameOver();
|
||||
}
|
||||
|
||||
void Timer::greetsMonk() {
|
||||
_vm->_dialogs->displayScrollChain('Q', 59);
|
||||
_vm->_enteredLustiesRoomAsMonk = true;
|
||||
}
|
||||
|
||||
void Timer::fallDownOubliette() {
|
||||
_vm->_magics[8]._operation = kMagicNothing;
|
||||
|
||||
AnimationType *avvy = _vm->_animation->_sprites[0];
|
||||
avvy->_moveY++; // Increments dx/dy!
|
||||
avvy->_y += avvy->_moveY; // Dowwwn we go...
|
||||
addTimer(3, kProcFallDownOubliette, kReasonFallingDownOubliette);
|
||||
}
|
||||
|
||||
void Timer::meetAvaroid() {
|
||||
if (_vm->_metAvaroid) {
|
||||
Common::String tmpStr = Common::String::format("You can't expect to be %cthat%c lucky twice in a row!",
|
||||
kControlItalic, kControlRoman);
|
||||
_vm->_dialogs->displayText(tmpStr);
|
||||
_vm->gameOver();
|
||||
} else {
|
||||
_vm->_dialogs->displayScrollChain('Q', 60);
|
||||
_vm->_metAvaroid = true;
|
||||
addTimer(1, kProcRiseUpOubliette, kReasonRisingUpOubliette);
|
||||
|
||||
AnimationType *avvy = _vm->_animation->_sprites[0];
|
||||
avvy->_facingDir = kDirLeft;
|
||||
avvy->_x = 151;
|
||||
avvy->_moveX = -3;
|
||||
avvy->_moveY = -5;
|
||||
|
||||
_vm->_graphics->setBackgroundColor(kColorGreen);
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::riseUpOubliette() {
|
||||
AnimationType *avvy = _vm->_animation->_sprites[0];
|
||||
avvy->_visible = true;
|
||||
avvy->_moveY++; // Decrements dx/dy!
|
||||
avvy->_y -= avvy->_moveY; // Uuuupppp we go...
|
||||
if (avvy->_moveY > 0)
|
||||
addTimer(3, kProcRiseUpOubliette, kReasonRisingUpOubliette);
|
||||
else
|
||||
_vm->_userMovesAvvy = true;
|
||||
}
|
||||
|
||||
void Timer::robinHoodAndGeida() {
|
||||
AnimationType *avvy = _vm->_animation->_sprites[0];
|
||||
avvy->init(7, true);
|
||||
_vm->_animation->appearPed(0, 6);
|
||||
avvy->walkTo(5);
|
||||
|
||||
AnimationType *spr = _vm->_animation->_sprites[1];
|
||||
spr->stopWalk();
|
||||
spr->_facingDir = kDirLeft;
|
||||
addTimer(20, kProcRobinHoodAndGeidaTalk, kReasonRobinHoodAndGeida);
|
||||
_vm->_geidaFollows = false;
|
||||
}
|
||||
|
||||
void Timer::robinHoodAndGeidaTalk() {
|
||||
_vm->_dialogs->displayScrollChain('Q', 66);
|
||||
|
||||
AnimationType *avvy = _vm->_animation->_sprites[0];
|
||||
AnimationType *spr = _vm->_animation->_sprites[1];
|
||||
avvy->walkTo(1);
|
||||
spr->walkTo(1);
|
||||
avvy->_vanishIfStill = true;
|
||||
spr->_vanishIfStill = true;
|
||||
|
||||
addTimer(162, kProcAvalotReturns, kReasonRobinHoodAndGeida);
|
||||
}
|
||||
|
||||
void Timer::avalotReturns() {
|
||||
AnimationType *avvy = _vm->_animation->_sprites[0];
|
||||
AnimationType *spr = _vm->_animation->_sprites[1];
|
||||
avvy->remove();
|
||||
spr->remove();
|
||||
avvy->init(0, true);
|
||||
_vm->_animation->appearPed(0, 0);
|
||||
_vm->_dialogs->displayScrollChain('Q', 67);
|
||||
_vm->_userMovesAvvy = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used when you sit down in the pub in Notts. It loops around
|
||||
* so that it will happen when Avvy stops walking.
|
||||
* @remarks Originally called 'avvy_sit_down'
|
||||
*/
|
||||
void Timer::avvySitDown() {
|
||||
AnimationType *avvy = _vm->_animation->_sprites[0];
|
||||
if (avvy->_homing) // Still walking.
|
||||
addTimer(1, kProcAvvySitDown, kReasonSittingDown);
|
||||
else {
|
||||
_vm->_background->draw(-1, -1, 2);
|
||||
_vm->_sittingInPub = true;
|
||||
_vm->_userMovesAvvy = false;
|
||||
avvy->_visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::ghostRoomPhew() {
|
||||
Common::String tmpStr = Common::String::format("%cPHEW!%c You're glad to get out of %cthere!",
|
||||
kControlItalic, kControlRoman, kControlItalic);
|
||||
_vm->_dialogs->displayText(tmpStr);
|
||||
}
|
||||
|
||||
void Timer::arkataShouts() {
|
||||
if (_vm->_teetotal)
|
||||
return;
|
||||
|
||||
_vm->_dialogs->displayScrollChain('Q', 76);
|
||||
addTimer(160, kProcArkataShouts, kReasonArkataShouts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks Contains the content of the function 'winning_pic', originally located in PINGO.
|
||||
*/
|
||||
void Timer::winning() {
|
||||
_vm->_dialogs->displayScrollChain('Q', 79);
|
||||
|
||||
// This was originally located in winning_pic:
|
||||
CursorMan.showMouse(false);
|
||||
_vm->_graphics->saveScreen();
|
||||
_vm->fadeOut();
|
||||
_vm->_graphics->drawWinningPic();
|
||||
_vm->_graphics->refreshScreen();
|
||||
_vm->fadeIn();
|
||||
|
||||
// Waiting for a keypress or a left mouseclick:
|
||||
Common::Event event;
|
||||
bool escape = false;
|
||||
while (!_vm->shouldQuit() && !escape) {
|
||||
_vm->_graphics->refreshScreen();
|
||||
while (_vm->getEvent(event)) {
|
||||
if ((event.type == Common::EVENT_LBUTTONUP) || (event.type == Common::EVENT_KEYDOWN)) {
|
||||
escape = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_vm->fadeOut();
|
||||
_vm->_graphics->restoreScreen();
|
||||
_vm->_graphics->removeBackup();
|
||||
_vm->fadeIn();
|
||||
CursorMan.showMouse(true);
|
||||
// winning_pic's end.
|
||||
|
||||
_vm->callVerb(kVerbCodeScore);
|
||||
_vm->_dialogs->displayText(" T H E E N D ");
|
||||
_vm->_letMeOut = true;
|
||||
}
|
||||
|
||||
void Timer::avalotFalls() {
|
||||
AnimationType *avvy = _vm->_animation->_sprites[0];
|
||||
if (avvy->_stepNum < 5) {
|
||||
avvy->_stepNum++;
|
||||
addTimer(3, kProcAvalotFalls, kReasonFallingOver);
|
||||
} else {
|
||||
Common::String toDisplay = Common::String::format("%c%c%c%c%c%c%c%c%c%c%c%c%cZ%c",
|
||||
kControlNewLine, kControlNewLine, kControlNewLine, kControlNewLine,
|
||||
kControlNewLine, kControlNewLine, kControlInsertSpaces, kControlInsertSpaces,
|
||||
kControlInsertSpaces, kControlInsertSpaces, kControlInsertSpaces,
|
||||
kControlInsertSpaces, kControlRegister, kControlIcon);
|
||||
_vm->_dialogs->displayText(toDisplay);
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::spludwickGoesToCauldron() {
|
||||
if (_vm->_animation->_sprites[1]->_homing)
|
||||
addTimer(1, kProcSpludwickGoesToCauldron, kReasonSpludwickWalk);
|
||||
else
|
||||
addTimer(17, kProcSpludwickLeavesCauldron, kReasonSpludwickWalk);
|
||||
}
|
||||
|
||||
void Timer::spludwickLeavesCauldron() {
|
||||
_vm->_animation->_sprites[1]->_callEachStepFl = true; // So that normal procs will continue.
|
||||
}
|
||||
|
||||
void Timer::giveLuteToGeida() { // Moved here from Acci.
|
||||
_vm->_dialogs->displayScrollChain('Q', 86);
|
||||
_vm->incScore(4);
|
||||
_vm->_lustieIsAsleep = true;
|
||||
_vm->_sequence->startGeidaLuteSeq();
|
||||
}
|
||||
|
||||
void Timer::resetVariables() {
|
||||
for (int i = 0; i < 7; i++) {
|
||||
_times[i]._timeLeft = 0;
|
||||
_times[i]._action = 0;
|
||||
_times[i]._reason = 0;
|
||||
}
|
||||
|
||||
_shootEmUpScore = 0;
|
||||
}
|
||||
|
||||
} // End of namespace Avalanche.
|
||||
177
engines/avalanche/timer.h
Normal file
177
engines/avalanche/timer.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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: TIMEOUT The scheduling unit. */
|
||||
|
||||
#ifndef AVALANCHE_TIMER_H
|
||||
#define AVALANCHE_TIMER_H
|
||||
|
||||
namespace Avalanche {
|
||||
class AvalancheEngine;
|
||||
|
||||
class Timer {
|
||||
public:
|
||||
// Reason runs between 1 and 28.
|
||||
enum Reason {
|
||||
kReasonDrawbridgeFalls = 2,
|
||||
kReasonAvariciusTalks = 3,
|
||||
kReasonGoToToilet = 4,
|
||||
kReasonExplosion = 5,
|
||||
kReasonBrummieStairs = 6,
|
||||
kReasonCardiffsurvey = 7,
|
||||
kReasonCwytalotInHerts = 8,
|
||||
kReasonGettingTiedUp = 9,
|
||||
kReasonHangingAround = 10, // Tied to the tree in Nottingham.
|
||||
kReasonJacquesWakingUp = 11,
|
||||
kReasonNaughtyDuke = 12,
|
||||
kReasonJumping = 13,
|
||||
kReasonSequencer = 14,
|
||||
kReasonCrapulusSaysSpludwickOut = 15,
|
||||
kReasonDawndelay = 16,
|
||||
kReasonDrinks = 17,
|
||||
kReasonDuLustieTalks = 18,
|
||||
kReasonFallingDownOubliette = 19,
|
||||
kReasonMeetingAvaroid = 20,
|
||||
kReasonRisingUpOubliette = 21,
|
||||
kReasonRobinHoodAndGeida = 22,
|
||||
kReasonSittingDown = 23,
|
||||
kReasonGhostRoomPhew = 1,
|
||||
kReasonArkataShouts = 24,
|
||||
kReasonWinning = 25,
|
||||
kReasonFallingOver = 26,
|
||||
kReasonSpludwickWalk = 27,
|
||||
kReasonGeidaSings = 28
|
||||
};
|
||||
|
||||
// Proc runs between 1 and 41.
|
||||
enum Proc {
|
||||
kProcOpenDrawbridge = 3,
|
||||
kProcAvariciusTalks = 4,
|
||||
kProcUrinate = 5,
|
||||
kProcToilet = 6,
|
||||
kProcBang = 7,
|
||||
kProcBang2 = 8,
|
||||
kProcStairs = 9,
|
||||
kProcCardiffSurvey = 10,
|
||||
kProcCardiffReturn = 11,
|
||||
kProcCwytalotInHerts = 12,
|
||||
kProcGetTiedUp = 13,
|
||||
kProcGetTiedUp2 = 1,
|
||||
kProcHangAround = 14,
|
||||
kProcHangAround2 = 15,
|
||||
kProcAfterTheShootemup = 32,
|
||||
kProcJacquesWakesUp = 16,
|
||||
kProcNaughtyDuke = 17,
|
||||
kProcNaughtyDuke2 = 18,
|
||||
kProcNaughtyDuke3 = 38,
|
||||
kProcJump = 19,
|
||||
kProcSequence = 20,
|
||||
kProcCrapulusSpludOut = 21,
|
||||
kProcDawnDelay = 22,
|
||||
kProcBuyDrinks = 23,
|
||||
kProcBuyWine = 24,
|
||||
kProcCallsGuards = 25,
|
||||
kProcGreetsMonk = 26,
|
||||
kProcFallDownOubliette = 27,
|
||||
kProcMeetAvaroid = 28,
|
||||
kProcRiseUpOubliette = 29,
|
||||
kProcRobinHoodAndGeida = 2,
|
||||
kProcRobinHoodAndGeidaTalk = 30,
|
||||
kProcAvalotReturns = 31,
|
||||
kProcAvvySitDown = 33, // In Nottingham.
|
||||
kProcGhostRoomPhew = 34,
|
||||
kProcArkataShouts = 35,
|
||||
kProcWinning = 36,
|
||||
kProcAvalotFalls = 37,
|
||||
kProcSpludwickGoesToCauldron = 39,
|
||||
kProcSpludwickLeavesCauldron = 40,
|
||||
kProcGiveLuteToGeida = 41
|
||||
};
|
||||
|
||||
struct TimerType {
|
||||
int32 _timeLeft;
|
||||
byte _action;
|
||||
byte _reason;
|
||||
};
|
||||
|
||||
TimerType _times[7];
|
||||
|
||||
Timer(AvalancheEngine *vm);
|
||||
|
||||
void resetVariables();
|
||||
void addTimer(int32 duration, byte action, byte reason);
|
||||
void updateTimer();
|
||||
void loseTimer(byte which);
|
||||
|
||||
// Procedures to do things at the end of amounts of time:
|
||||
void openDrawbridge();
|
||||
void avariciusTalks();
|
||||
void urinate();
|
||||
void toilet();
|
||||
void bang();
|
||||
void bang2();
|
||||
void stairs();
|
||||
void cardiffSurvey();
|
||||
void cardiffReturn();
|
||||
void cwytalotInHerts();
|
||||
void getTiedUp();
|
||||
void getTiedUp2();
|
||||
void hangAround();
|
||||
void hangAround2();
|
||||
void afterTheShootemup();
|
||||
void jacquesWakesUp();
|
||||
void naughtyDuke();
|
||||
void naughtyDuke2();
|
||||
void naughtyDuke3();
|
||||
void jump();
|
||||
void crapulusSaysSpludOut();
|
||||
void buyDrinks();
|
||||
void buyWine();
|
||||
void callsGuards();
|
||||
void greetsMonk();
|
||||
void fallDownOubliette();
|
||||
void meetAvaroid();
|
||||
void riseUpOubliette();
|
||||
void robinHoodAndGeida();
|
||||
void robinHoodAndGeidaTalk();
|
||||
void avalotReturns();
|
||||
void avvySitDown();
|
||||
void ghostRoomPhew();
|
||||
void arkataShouts();
|
||||
void winning();
|
||||
void avalotFalls();
|
||||
void spludwickGoesToCauldron();
|
||||
void spludwickLeavesCauldron();
|
||||
void giveLuteToGeida();
|
||||
|
||||
private:
|
||||
AvalancheEngine *_vm;
|
||||
byte _shootEmUpScore;
|
||||
};
|
||||
|
||||
} // End of namespace Avalanche.
|
||||
|
||||
#endif // AVALANCHE_TIMER_H
|
||||
Reference in New Issue
Block a user