Initial commit
This commit is contained in:
434
engines/hadesch/rooms/athena.cpp
Normal file
434
engines/hadesch/rooms/athena.cpp
Normal file
@@ -0,0 +1,434 @@
|
||||
/* 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/>.
|
||||
*
|
||||
* Copyright 2020 Google
|
||||
*
|
||||
*/
|
||||
#include "hadesch/hadesch.h"
|
||||
#include "hadesch/video.h"
|
||||
#include "hadesch/ambient.h"
|
||||
|
||||
namespace Hadesch {
|
||||
static const char *kAthenaAnim = "c8060ba0";
|
||||
static const char *kLights = "c8110bb0";
|
||||
|
||||
// Keep in order
|
||||
enum {
|
||||
kWonPuzzle = -2,
|
||||
kNowhere = -1,
|
||||
kBubo = 0,
|
||||
kArtist = 1,
|
||||
kOrator = 2,
|
||||
kScholar = 3,
|
||||
kWarrior = 4
|
||||
};
|
||||
static const int kNumPuzzleElements = 5;
|
||||
static const struct {
|
||||
const char *hotname;
|
||||
int lights[2];
|
||||
int rays[2];
|
||||
} puzzleElements[kNumPuzzleElements] = {
|
||||
{"Bubo", { kArtist, kOrator}, {2, 1}},
|
||||
{"Artist", { kNowhere, kOrator}, {6, 5}},
|
||||
{"Orator", { kArtist, kScholar}, {3, 4}},
|
||||
{"Scholar", { kNowhere, kWarrior}, {8, 9}},
|
||||
{"Warrior", { kScholar, kWonPuzzle}, {7, 10}}
|
||||
};
|
||||
|
||||
enum {
|
||||
kBackgroundZ = 10000,
|
||||
kLightsZ = 201
|
||||
};
|
||||
|
||||
enum {
|
||||
kPhilForgettingEnd = 23009,
|
||||
kPhilHardwareFinished = 23012,
|
||||
kIntroFinished = 1023001
|
||||
};
|
||||
|
||||
class AthenaHandler : public Handler {
|
||||
public:
|
||||
AthenaHandler() {
|
||||
_playAreYouForgetting = true;
|
||||
_playAthenaTempleHardware = true;
|
||||
_isPuzzleWon = false;
|
||||
_hintTimerLength = 20000;
|
||||
memset(_puzzleState, 0, sizeof (_puzzleState));
|
||||
}
|
||||
|
||||
void handleClick(const Common::String &name) override {
|
||||
Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
|
||||
Persistent *persistent = g_vm->getPersistent();
|
||||
Quest quest = persistent->_quest;
|
||||
if (name == "Seriphos") {
|
||||
if (quest == kMedusaQuest) {
|
||||
if (persistent->_athenaPuzzleSolved &&
|
||||
(!persistent->_athenaSwordTaken
|
||||
|| !persistent->_athenaShieldTaken)
|
||||
&& persistent->_hintsAreEnabled
|
||||
&& _playAreYouForgetting) {
|
||||
_playAreYouForgetting = false;
|
||||
room->disableMouse();
|
||||
room->playVideo("c8020ba0", 0,
|
||||
kPhilForgettingEnd,
|
||||
Common::Point(0, 216));
|
||||
return;
|
||||
} else if (persistent->_athenaPuzzleSolved &&
|
||||
persistent->_athenaSwordTaken &&
|
||||
persistent->_athenaShieldTaken &&
|
||||
!persistent->_athenaPlayedPainAndPanic
|
||||
) {
|
||||
persistent->_athenaPlayedPainAndPanic = true;
|
||||
room->disableMouse();
|
||||
room->fadeOut(1000, 23019);
|
||||
return;
|
||||
} else if (persistent->_athenaPuzzleSolved &&
|
||||
!_playAthenaTempleHardware
|
||||
&& persistent->_hintsAreEnabled) {
|
||||
_playAthenaTempleHardware = false;
|
||||
room->disableMouse();
|
||||
room->playVideo("c8160ba0", 0,
|
||||
kPhilHardwareFinished,
|
||||
Common::Point(0, 216));
|
||||
return;
|
||||
}
|
||||
}
|
||||
g_vm->moveToRoom(kSeriphosRoom);
|
||||
return;
|
||||
}
|
||||
|
||||
if (name == "Athena") {
|
||||
Common::Array<Common::String> videos;
|
||||
if (quest == kMedusaQuest && !persistent->_athenaPuzzleSolved) {
|
||||
videos.push_back(persistent->_gender == kMale ? "c8060wa0" : "c8060wb0");
|
||||
} else {
|
||||
videos.push_back("c8060wc0");
|
||||
videos.push_back("c8060wd0");
|
||||
}
|
||||
|
||||
room->playStatueSMK(kAthenaStatue,
|
||||
kAthenaAnim,
|
||||
1101,
|
||||
videos, 26, 42);
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < kNumPuzzleElements; i++)
|
||||
if (name == puzzleElements[i].hotname) {
|
||||
handlePuzzleClick(i);
|
||||
return;
|
||||
}
|
||||
|
||||
if (name == "Sword") {
|
||||
persistent->_athenaSwordTaken = true;
|
||||
g_vm->getHeroBelt()->placeToInventory(kSword);
|
||||
room->stopAnim("c8130bf0");
|
||||
room->disableHotzone("Sword");
|
||||
room->disableMouse();
|
||||
room->playSpeech(TranscribedSound::make(
|
||||
"c8140wa0",
|
||||
"The magic sword will never leave Perseus' hand, "
|
||||
"so he can successfully cut off Medusa's head"),
|
||||
23026);
|
||||
return;
|
||||
}
|
||||
|
||||
if (name == "Shield") {
|
||||
persistent->_athenaShieldTaken = true;
|
||||
g_vm->getHeroBelt()->placeToInventory(kShield);
|
||||
room->stopAnim("c8130be0");
|
||||
room->disableHotzone("Shield");
|
||||
room->disableMouse();
|
||||
room->playSpeech(TranscribedSound::make(
|
||||
"c8150wa0",
|
||||
"Medusa can only turn Perseus to stone if he looks directly at her. "
|
||||
"He'll use this shield to block her gaze"),
|
||||
23027);
|
||||
return;
|
||||
}
|
||||
|
||||
if (name == "Athena's Sword") {
|
||||
room->disableMouse();
|
||||
room->playAnimLoop("c8010oc0", 2101);
|
||||
room->playVideo("c8080wa0", 0, 23043);
|
||||
room->playSFX("C8080eA1");
|
||||
return;
|
||||
}
|
||||
|
||||
if (name == "Athena's Shield") {
|
||||
room->disableMouse();
|
||||
room->playAnimLoop("c8010ob0", 2101);
|
||||
room->playVideo("c8070wa0", 0, 23044);
|
||||
room->playSFX("C8080eA1");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void handleEvent(int eventId) override {
|
||||
Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
|
||||
Persistent *persistent = g_vm->getPersistent();
|
||||
switch(eventId) {
|
||||
case kIntroFinished:
|
||||
room->stopAnim(kAthenaAnim);
|
||||
room->playAnim("c8110ba0", 0, PlayAnimParams::disappear(), 23035);
|
||||
room->enableMouse();
|
||||
_hintTimerLength = 20000;
|
||||
rescheduleHintTimer();
|
||||
break;
|
||||
case kPhilForgettingEnd:
|
||||
case kPhilHardwareFinished:
|
||||
case 23026:
|
||||
case 23027:
|
||||
room->enableMouse();
|
||||
break;
|
||||
case 23007:
|
||||
handleEvent(23010);
|
||||
_hintTimerLength = 40000;
|
||||
rescheduleHintTimer(true);
|
||||
break;
|
||||
case 23008:
|
||||
room->playAnim("c8140ba0", 1101, PlayAnimParams::disappear(), 23015);
|
||||
room->playAnim("c8150ba0", 1101, PlayAnimParams::disappear(), 23016);
|
||||
room->playMusic("c8130ma0", 23020);
|
||||
room->playSFX("c8130eb0");
|
||||
room->playSFX("c8130ec0");
|
||||
break;
|
||||
case 23010:
|
||||
if (persistent->_hintsAreEnabled && room->isMouseEnabled()) {
|
||||
room->disableMouse();
|
||||
room->playVideo("c8170ba0", 0, 23011, Common::Point(0, 216));
|
||||
}
|
||||
break;
|
||||
case 23011:
|
||||
room->enableMouse();
|
||||
break;
|
||||
case 23015:
|
||||
room->playAnimKeepLastFrame("c8130bf0", 1101, 23017);
|
||||
room->playSFX("c8130ef0");
|
||||
break;
|
||||
case 23016:
|
||||
room->playAnimKeepLastFrame("c8130be0", 1101, 23018);
|
||||
room->playSFX("c8130ee0");
|
||||
break;
|
||||
case 23017:
|
||||
room->enableHotzone("Sword");
|
||||
room->enableMouse();
|
||||
break;
|
||||
case 23018:
|
||||
room->enableHotzone("Shield");
|
||||
room->enableMouse();
|
||||
break;
|
||||
case 23019:
|
||||
room->resetFade();
|
||||
room->disableHeroBelt();
|
||||
room->resetLayers();
|
||||
room->addStaticLayer("c8180pa0", 9000);
|
||||
room->playSFX("g0261ma0", 23031);
|
||||
room->playSpeech(persistent->_gender == kMale
|
||||
? TranscribedSound::make(
|
||||
"c8180wa0",
|
||||
"Oh no. Why did I shine that light in Athena's temple. "
|
||||
"I was just trying to see what the hero was doing")
|
||||
: TranscribedSound::make(
|
||||
"c8180wb0",
|
||||
"Oh no. Why did I shine that light in Athena's temple. "
|
||||
"I was just trying to see what the heroine was doing"),
|
||||
23029);
|
||||
break;
|
||||
case 23029:
|
||||
room->playSpeech(TranscribedSound::make("c8180wc0", "Well now you can see what I'm doing: tomato heads"), 23030);
|
||||
break;
|
||||
case 23030:
|
||||
room->playVideo("c8180ba0", 0, 23032);
|
||||
break;
|
||||
case 23031:
|
||||
break;
|
||||
case 23032:
|
||||
room->selectFrame("c8180bb0", 101, 0);
|
||||
g_vm->moveToRoom(kSeriphosRoom);
|
||||
break;
|
||||
// TODO: lighting up of the beam: 23035/23036 are for lighting up
|
||||
case 23035:
|
||||
case 23036:
|
||||
room->selectFrame(LayerId(kLights, 0, "source"), kLightsZ, 0);
|
||||
/* Fallthrough */
|
||||
case 23037:
|
||||
room->playAnimLoop("c8110bc0", 211);
|
||||
room->enableHotzone("Athena's Sword");
|
||||
room->enableHotzone("Athena's Shield");
|
||||
for (unsigned i = 0; i < kNumPuzzleElements; i++)
|
||||
room->enableHotzone(puzzleElements[i].hotname);
|
||||
break;
|
||||
case 23020:
|
||||
room->playAnim("c8130bd0", 0, PlayAnimParams::disappear(), 23041);
|
||||
/*Fallthrough */
|
||||
case 23038:
|
||||
g_vm->addTimer(23040, 640);
|
||||
g_vm->addTimer(23039, 40, 15);
|
||||
break;
|
||||
case 23039:
|
||||
//TODO progressive beams
|
||||
break;
|
||||
case 23040:
|
||||
for (unsigned i = 0; i < 12; i++)
|
||||
room->stopAnim(LayerId(kLights, i, "internal"));
|
||||
room->stopAnim(LayerId(kLights, 0, "source"));
|
||||
room->stopAnim("c8110bc0");
|
||||
break;
|
||||
case 23043:
|
||||
room->stopAnim("c8010oc0");
|
||||
room->enableMouse();
|
||||
break;
|
||||
case 23044:
|
||||
room->stopAnim("c8010ob0");
|
||||
room->enableMouse();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void prepareRoom() override {
|
||||
Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
|
||||
Persistent *persistent = g_vm->getPersistent();
|
||||
Quest quest = persistent->_quest;
|
||||
room->loadHotZones("Athena.HOT", false);
|
||||
room->addStaticLayer("c8010pa0", kBackgroundZ);
|
||||
room->addStaticLayer("c8010ta0", 601);
|
||||
room->enableHotzone("Athena");
|
||||
room->enableHotzone("Seriphos");
|
||||
|
||||
if (quest == kMedusaQuest && !persistent->_athenaPuzzleSolved) {
|
||||
persistent->_athenaIntroPlayed = true;
|
||||
room->disableMouse();
|
||||
room->playVideo(persistent->_gender == kMale ? "c8040wa0" : "c8040wb0",
|
||||
1101, kIntroFinished);
|
||||
room->playAnim(kAthenaAnim, 1101, PlayAnimParams::loop());
|
||||
room->playMusic("c8040ma0", 23013);
|
||||
}
|
||||
|
||||
if (!persistent->_athenaShieldTaken) {
|
||||
if (persistent->_athenaPuzzleSolved) {
|
||||
room->selectFrame("c8130be0", 1101, 4);
|
||||
room->enableHotzone("Shield");
|
||||
} else {
|
||||
room->selectFrame("c8150ba0", 1101, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!persistent->_athenaSwordTaken) {
|
||||
if (persistent->_athenaPuzzleSolved) {
|
||||
room->selectFrame("c8130bf0", 1101, 7);
|
||||
room->enableHotzone("Sword");
|
||||
} else {
|
||||
room->selectFrame("c8140ba0", 1101, 0);
|
||||
}
|
||||
}
|
||||
|
||||
room->playAnimLoop("c8030ba0", 201);
|
||||
g_vm->getHeroBelt()->setColour(HeroBelt::kCool);
|
||||
}
|
||||
private:
|
||||
void rescheduleHintTimer(bool isInHandler = false) {
|
||||
Persistent *persistent = g_vm->getPersistent();
|
||||
|
||||
if (!isInHandler)
|
||||
g_vm->cancelTimer(23007);
|
||||
if (!persistent->_athenaPuzzleSolved)
|
||||
g_vm->addTimer(23007, _hintTimerLength);
|
||||
}
|
||||
|
||||
void handlePuzzleClick(int num) {
|
||||
Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
|
||||
Persistent *persistent = g_vm->getPersistent();
|
||||
|
||||
rescheduleHintTimer();
|
||||
|
||||
_puzzleState[num] = (_puzzleState[num] + 1) % 3;
|
||||
memset(_isPuzzleLit, 0, sizeof (_isPuzzleLit));
|
||||
_isPuzzleLit[0] = true;
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
done = true;
|
||||
for (unsigned i = 0; i < kNumPuzzleElements; i++)
|
||||
if (_puzzleState[i] != 0 && _isPuzzleLit[i]
|
||||
&& puzzleElements[i].lights[_puzzleState[i] - 1] >= 0
|
||||
&& !_isPuzzleLit[puzzleElements[i].lights[_puzzleState[i] - 1]]) {
|
||||
_isPuzzleLit[puzzleElements[i].lights[_puzzleState[i] - 1]] = true;
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < kNumPuzzleElements; i++)
|
||||
if (_puzzleState[i] != 0 && _isPuzzleLit[i]
|
||||
&& puzzleElements[i].lights[_puzzleState[i] - 1] == kWonPuzzle) {
|
||||
_isPuzzleWon = true;
|
||||
break;
|
||||
}
|
||||
for (unsigned i = 0; i < kNumPuzzleElements; i++)
|
||||
if (!_isPuzzleLit[i])
|
||||
_puzzleState[i] = 0;
|
||||
for (unsigned i = 0; i < 11; i++)
|
||||
room->stopAnim(LayerId(kLights, i, "internal"));
|
||||
for (unsigned i = 0; i < kNumPuzzleElements; i++)
|
||||
if (_puzzleState[i] != 0 && _isPuzzleLit[i]) {
|
||||
int ray = puzzleElements[i].rays[_puzzleState[i] - 1];
|
||||
if (ray <= 0)
|
||||
continue;
|
||||
room->selectFrame(LayerId(kLights, ray, "internal"), kLightsZ, ray);
|
||||
}
|
||||
|
||||
if (_isPuzzleLit[kArtist] && _puzzleState[kArtist] == 1)
|
||||
room->playAnimLoop("c8120bg0", 601);
|
||||
else
|
||||
room->stopAnim("c8120bg0");
|
||||
if (_isPuzzleLit[kScholar] && _puzzleState[kScholar] == 1)
|
||||
room->playAnimLoop("c8120bg1", 601);
|
||||
else
|
||||
room->stopAnim("c8120bg1");
|
||||
|
||||
if (_isPuzzleLit[num] && _puzzleState[num])
|
||||
room->playSFX("c8120ea0");
|
||||
|
||||
if (_isPuzzleWon) {
|
||||
room->selectFrame(LayerId(kLights, 11, "internal"), kLightsZ, 11);
|
||||
room->playSFX("C8130eA0");
|
||||
g_vm->addTimer(23008, 1000);
|
||||
room->disableHotzone("Athena's Sword");
|
||||
room->disableHotzone("Athena's Shield");
|
||||
for (unsigned i = 0; i < kNumPuzzleElements; i++)
|
||||
room->disableHotzone(puzzleElements[i].hotname);
|
||||
room->disableMouse();
|
||||
persistent->_athenaPuzzleSolved = true;
|
||||
}
|
||||
|
||||
room->playMusicLoop(
|
||||
persistent->_quest != kMedusaQuest || persistent->_athenaPuzzleSolved
|
||||
? "c8010ea0" : "c8110ea0");
|
||||
}
|
||||
bool _playAreYouForgetting;
|
||||
bool _playAthenaTempleHardware;
|
||||
bool _isPuzzleLit[kNumPuzzleElements];
|
||||
int _puzzleState[kNumPuzzleElements];
|
||||
bool _isPuzzleWon;
|
||||
int _hintTimerLength;
|
||||
};
|
||||
|
||||
Common::SharedPtr<Hadesch::Handler> makeAthenaHandler() {
|
||||
return Common::SharedPtr<Hadesch::Handler>(new AthenaHandler());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user