904 lines
28 KiB
C++
904 lines
28 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 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 "hypno/grammar.h"
|
|
#include "hypno/hypno.h"
|
|
|
|
#include "common/events.h"
|
|
|
|
#include "backends/keymapper/keymapper.h"
|
|
|
|
namespace Hypno {
|
|
|
|
void BoyzEngine::runBeforeArcade(ArcadeShooting *arc) {
|
|
_checkpoint = _currentLevel;
|
|
_lastStats = _stats;
|
|
if (!_flashbackMode) {
|
|
// if we are flashback mode,
|
|
// then we are testing some level
|
|
// and we should not save
|
|
saveProfile(_name, int(arc->id));
|
|
}
|
|
|
|
if (arc->mode == "YM") {
|
|
assert(!arc->player.empty());
|
|
_playerFrames = decodeFrames(arc->player);
|
|
_playerFrameSep = 0;
|
|
|
|
Common::Rect healthBarBox(0, 3, 107, 18);
|
|
Common::Rect ammoBarBox(0, 20, 103, 34);
|
|
Common::Rect portraitBox(0, 40, 57, 94);
|
|
|
|
for (int i = 0; i < int(_playerFrames.size()); i++) {
|
|
_healthBar[i+1] = _playerFrames[i]->getSubArea(healthBarBox);
|
|
_ammoBar[i+1] = _playerFrames[i]->getSubArea(ammoBarBox);
|
|
_portrait[i+1] = _playerFrames[i]->getSubArea(portraitBox);
|
|
}
|
|
|
|
_playerFrameSep = _playerFrames.size();
|
|
_playerFrameIdx = -1;
|
|
} else {
|
|
uint32 r = 1 + _rnd->getRandomNumber(1);
|
|
arc->backgroundVideo = Common::String::format("c3/c35c0%ds.smk", r);
|
|
_playerFrameSep = 0;
|
|
_playerFrameIdx = -1;
|
|
if (arc->mode != "YS")
|
|
error("Invalid mode: %s", arc->mode.c_str());
|
|
}
|
|
|
|
if (!arc->beforeVideo.empty()) {
|
|
MVideo video(arc->beforeVideo, Common::Point(0, 0), false, true, false);
|
|
runIntro(video);
|
|
}
|
|
|
|
_currentScript = arc->script;
|
|
// Reload all weapons
|
|
for (Script::iterator it = _currentScript.begin(); it != _currentScript.end(); ++it) {
|
|
_ammo = _weaponMaxAmmo[it->cursor];
|
|
}
|
|
_currentActor = 0;
|
|
updateFromScript();
|
|
_shootsDestroyed.clear();
|
|
_health = _previousHealth;
|
|
_selectedCorrectBox = 0;
|
|
}
|
|
|
|
void BoyzEngine::runAfterArcade(ArcadeShooting *arc) {
|
|
for (int i = 0; i < int(_playerFrames.size()); i++) {
|
|
_playerFrames[i]->free();
|
|
delete _playerFrames[i];
|
|
}
|
|
_playerFrames.clear();
|
|
|
|
if (_flashbackMode) {
|
|
resetStatistics();
|
|
_nextLevel = "<select_t1>";
|
|
return;
|
|
}
|
|
|
|
if (_health <= 0) {
|
|
if (_arcadeMode == "YS")
|
|
return;
|
|
_stats = _lastStats;
|
|
disableCursor();
|
|
|
|
if (_levelId == 36 && !checkArcadeObjectives()) {
|
|
MVideo video("warnings/w09s.smk", Common::Point(0, 0), false, true, false);
|
|
runIntro(video);
|
|
} else {
|
|
if (getTerritory(_currentLevel) <= 4) {
|
|
MVideo video(_deathDay[_currentActor], Common::Point(0, 0), false, true, false);
|
|
runIntro(video);
|
|
} else {
|
|
MVideo video(_deathNight[_currentActor], Common::Point(0, 0), false, true, false);
|
|
runIntro(video);
|
|
}
|
|
}
|
|
return;
|
|
} else {
|
|
if (_levelId == 33 && checkArcadeObjectives()) {
|
|
MVideo video("c3/c33a02s.smk", Common::Point(0, 0), false, true, false);
|
|
runIntro(video);
|
|
defaultCursor();
|
|
waitForUserClick(1);
|
|
} else if (_levelId == 42) {
|
|
disableCursor();
|
|
MVideo video("c4/c4bro8s.smk", Common::Point(0, 0), false, true, false);
|
|
runIntro(video);
|
|
}
|
|
}
|
|
|
|
if (_currentLevel == lastLevelTerritory(_currentLevel)) {
|
|
int territory = getTerritory(_currentLevel) - 1;
|
|
showArcadeStats(territory, _stats);
|
|
// Merge current stats with the global ones
|
|
_globalStats.livesUsed = _stats.livesUsed + _globalStats.livesUsed;
|
|
_globalStats.shootsFired = _stats.shootsFired + _globalStats.shootsFired;
|
|
_globalStats.enemyHits = _stats.enemyHits + _globalStats.enemyHits;
|
|
_globalStats.enemyTargets = _stats.enemyTargets + _globalStats.enemyTargets;
|
|
_globalStats.targetsDestroyed = _stats.targetsDestroyed + _globalStats.targetsDestroyed;
|
|
_globalStats.targetsMissed = _stats.targetsMissed + _globalStats.targetsMissed;
|
|
_globalStats.friendliesEncountered = _stats.friendliesEncountered + _globalStats.friendliesEncountered;
|
|
_globalStats.infoReceived = _stats.infoReceived + _globalStats.infoReceived;
|
|
// If we are finishing the last level, show final stats
|
|
if (_currentLevel == "c59.mi_")
|
|
showArcadeStats(5, _globalStats);
|
|
|
|
// After that, we can reset the current stats
|
|
resetStatistics();
|
|
}
|
|
|
|
_previousHealth = _health;
|
|
_sceneState[Common::String::format("GS_SEQ_%d", _levelId)] = 1;
|
|
}
|
|
|
|
void BoyzEngine::showArcadeStats(int territory, const ArcadeStats &data) {
|
|
byte *palette;
|
|
Graphics::Surface *stats = decodeFrame("preload/stats.smk", territory, &palette);
|
|
loadPalette(palette, 0, 256);
|
|
drawImage(*stats, 0, 0, true);
|
|
stats->free();
|
|
delete stats;
|
|
free(palette);
|
|
uint32 enemiesAvailable = data.targetsDestroyed + data.targetsMissed;
|
|
drawString("scifi08.fgx", Common::String::format("%d", enemiesAvailable), 278, 41, 0, kHypnoColorWhiteOrBlue);
|
|
uint32 killRatio = enemiesAvailable > 0 ? 100 * data.targetsDestroyed / enemiesAvailable : 0;
|
|
drawString("scifi08.fgx", Common::String::format("%d%%", killRatio), 278, 56, 0, kHypnoColorWhiteOrBlue);
|
|
drawString("scifi08.fgx", Common::String::format("%d", data.shootsFired), 278, 79, 0, kHypnoColorWhiteOrBlue);
|
|
uint32 accuracyRatio = data.shootsFired > 0 ? 100 * data.enemyHits / data.shootsFired : 0;
|
|
drawString("scifi08.fgx", Common::String::format("%d%%", accuracyRatio), 278, 94, 0, kHypnoColorWhiteOrBlue);
|
|
drawString("scifi08.fgx", Common::String::format("%d", data.livesUsed), 278, 119, 0, kHypnoColorWhiteOrBlue);
|
|
drawString("scifi08.fgx", Common::String::format("%d", data.friendliesEncountered), 278, 144, 0, kHypnoColorWhiteOrBlue);
|
|
drawString("scifi08.fgx", Common::String::format("%d", data.infoReceived), 278, 159, 0, kHypnoColorWhiteOrBlue);
|
|
uint32 scorePercentage = (killRatio + accuracyRatio) / 2;
|
|
drawString("scifi08.fgx", Common::String::format("%d%%", scorePercentage), 278, 184, 0, kHypnoColorWhiteOrBlue);
|
|
|
|
bool cont = true;
|
|
while (!shouldQuit() && cont) {
|
|
Common::Event event;
|
|
while (g_system->getEventManager()->pollEvent(event)) {
|
|
switch (event.type) {
|
|
case Common::EVENT_KEYDOWN:
|
|
cont = false;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
drawScreen();
|
|
g_system->delayMillis(10);
|
|
}
|
|
}
|
|
|
|
void BoyzEngine::pressedKey(const int keycode) {
|
|
if (keycode == kActionSkipLevel) {
|
|
_skipLevel = true;
|
|
return;
|
|
} else if (keycode == kActionKillPlayer) { // Added for testing
|
|
_health = 0;
|
|
} else if (keycode == kActionPause) {
|
|
openMainMenuDialog();
|
|
}
|
|
}
|
|
|
|
void BoyzEngine::updateFromScript() {
|
|
if (_currentScript.size() > 0) {
|
|
ScriptInfo si = *_currentScript.begin();
|
|
//debug("%d %d %d", si.time, _background->decoder->getCurFrame(), si.actor);
|
|
if (!_background || int(si.time) <= _background->decoder->getCurFrame()) {
|
|
if (_currentActor != si.actor)
|
|
_ammo = _weaponMaxAmmo[si.cursor];
|
|
|
|
_currentActor = si.actor;
|
|
_currentMode = si.mode;
|
|
_currentWeapon = si.cursor;
|
|
_currentScript.pop_front();
|
|
|
|
if (_currentMode == NonInteractive)
|
|
changeCursor(_crosshairsInactive[_currentWeapon], _crosshairsPalette, true);
|
|
else
|
|
changeCursor(_crosshairsActive[_currentWeapon], _crosshairsPalette, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void BoyzEngine::drawCursorArcade(const Common::Point &mousePos) {
|
|
if (_currentMode == NonInteractive) {
|
|
return;
|
|
}
|
|
|
|
int i = detectTarget(mousePos);
|
|
if (i >= 0)
|
|
changeCursor(_crosshairsTarget[_currentWeapon], _crosshairsPalette, true);
|
|
else
|
|
changeCursor(_crosshairsActive[_currentWeapon], _crosshairsPalette, true);
|
|
}
|
|
|
|
void BoyzEngine::drawPlayer() {
|
|
updateFromScript();
|
|
if (_arcadeMode != "YS")
|
|
drawImage(_portrait[_currentActor], 0, 200 - _portrait[_currentActor].h, true);
|
|
}
|
|
|
|
void BoyzEngine::drawHealth() {
|
|
updateFromScript();
|
|
if(_arcadeMode == "YS")
|
|
return;
|
|
|
|
float w = float(_health) / float(_maxHealth);
|
|
if (w <= 0 || _healthBar[_currentActor].w - 3 <= 0 || _healthBar[_currentActor].h / 2 <= 0)
|
|
return;
|
|
|
|
Common::Rect healthBarBox(0, 0, int((_healthBar[_currentActor].w - 3) * w), _healthBar[_currentActor].h / 2);
|
|
|
|
uint32 c = kHypnoColorWhiteOrBlue; // white
|
|
_compositeSurface->fillRect(healthBarBox, c);
|
|
|
|
for (int i = 0; i < _maxHealth; i = i + 10) {
|
|
int x = (_healthBar[_currentActor].w - 3) * float(i) / float(_maxHealth);
|
|
_compositeSurface->drawLine(x, 2, x, 6, 0);
|
|
}
|
|
|
|
drawImage(_healthBar[_currentActor], 0, 0, true);
|
|
}
|
|
|
|
void BoyzEngine::drawAmmo() {
|
|
updateFromScript();
|
|
if(_arcadeMode == "YS")
|
|
return;
|
|
|
|
float w = float(_ammoBar[_currentActor].w) / float(_weaponMaxAmmo[_currentWeapon]);
|
|
|
|
Common::Rect ammoBarBox(320 - int(_ammo * w), 0, 320, _ammoBar[_currentActor].h / 2);
|
|
uint32 c = kHypnoColorGreen; // green
|
|
_compositeSurface->fillRect(ammoBarBox, c);
|
|
|
|
drawImage(_ammoBar[_currentActor], 320 - _ammoBar[_currentActor].w, 0, true);
|
|
for (int i = 1; i < _weaponMaxAmmo[_currentWeapon]; i++) {
|
|
int x = 320 - _ammoBar[_currentActor].w + int (i * w);
|
|
_compositeSurface->drawLine(x, 2, x, 6, 0);
|
|
}
|
|
}
|
|
|
|
void BoyzEngine::hitPlayer() {
|
|
if(_arcadeMode == "YS")
|
|
return; // Should never happen?
|
|
|
|
uint32 c = kHypnoColorRed; // red
|
|
_compositeSurface->fillRect(Common::Rect(0, 0, _screenW, _screenH), c);
|
|
drawScreen();
|
|
if (!_infiniteHealthCheat) {
|
|
_health = _health - 10;
|
|
}
|
|
if (!_hitSound.empty())
|
|
playSound(_soundPath + _hitSound, 1, 11025);
|
|
}
|
|
void BoyzEngine::drawShoot(const Common::Point &target) {}
|
|
|
|
void BoyzEngine::initSegment(ArcadeShooting *arc) {
|
|
_segmentShootSequenceOffset = 0;
|
|
_segmentShootSequenceMax = 0;
|
|
|
|
uint32 randomSegmentShootSequence = _segmentShootSequenceOffset + _rnd->getRandomNumber(_segmentShootSequenceMax);
|
|
SegmentShoots segmentShoots = arc->shootSequence[randomSegmentShootSequence];
|
|
_shootSequence = segmentShoots.shootSequence;
|
|
_segmentRepetitionMax = segmentShoots.segmentRepetition; // Usually zero
|
|
_segmentRepetition = 0;
|
|
_segmentOffset = 0;
|
|
_segmentIdx = _segmentOffset;
|
|
}
|
|
|
|
void BoyzEngine::findNextSegment(ArcadeShooting *arc) {
|
|
_segmentIdx = _segmentIdx + 1;
|
|
}
|
|
|
|
bool BoyzEngine::checkTransition(ArcadeTransitions &transitions, ArcadeShooting *arc) {
|
|
ArcadeTransition at = *transitions.begin();
|
|
int ttime = at.time;
|
|
if (_background->decoder->getCurFrame() > ttime) {
|
|
if (_background->decoder->getCurFrame() > ttime + 3) {
|
|
debugC(1, kHypnoDebugArcade, "Skipped transition of %d at %d", ttime, _background->decoder->getCurFrame());
|
|
} else if (at.video == "NONE") {
|
|
if (!at.palette.empty()) {
|
|
_background->decoder->pauseVideo(true);
|
|
_currentPalette = at.palette;
|
|
loadPalette(_currentPalette);
|
|
_background->decoder->pauseVideo(false);
|
|
drawPlayer();
|
|
updateScreen(*_background);
|
|
drawScreen();
|
|
} else if (!arc->additionalSound.empty())
|
|
playSound(arc->additionalSound, 1, arc->additionalSoundRate);
|
|
else if (_levelId == 36) {
|
|
if (!checkArcadeObjectives()) {
|
|
_health = 0;
|
|
// Not sure how to handle this
|
|
}
|
|
} else if (_levelId == 354) {
|
|
if (ttime == 70) {
|
|
incInfoReceived();
|
|
_background->decoder->pauseVideo(true);
|
|
MVideo video("tempdir/c35h4a1s.smk", Common::Point(0, 0), false, true, false);
|
|
disableCursor();
|
|
runIntro(video);
|
|
defaultCursor();
|
|
waitForUserClick(1);
|
|
_skipLevel = true;
|
|
}
|
|
} else if (_levelId == 51) {
|
|
if (_selectedCorrectBox == 0) {
|
|
_background->decoder->pauseVideo(true);
|
|
_background->decoder->forceSeekToFrame(ttime - 2);
|
|
_masks->decoder->forceSeekToFrame(ttime - 2);
|
|
const Graphics::Surface *frame = _background->decoder->decodeNextFrame();
|
|
Graphics::Surface *boxes = frame->convertTo(frame->format, _background->decoder->getPalette());
|
|
drawImage(*boxes, 0, 0, false);
|
|
drawScreen();
|
|
boxes->free();
|
|
delete boxes;
|
|
_selectedCorrectBox = pickABox();
|
|
if (_selectedCorrectBox == 1) {
|
|
_background->decoder->forceSeekToFrame(582);
|
|
_masks->decoder->forceSeekToFrame(582);
|
|
} else if (_selectedCorrectBox == -1) {
|
|
_background->decoder->forceSeekToFrame(525);
|
|
_masks->decoder->forceSeekToFrame(525);
|
|
} else
|
|
error("Invalid value for _selectedCorrectBox: %d", _selectedCorrectBox);
|
|
_background->decoder->pauseVideo(false);
|
|
updateScreen(*_background);
|
|
drawScreen();
|
|
} else if (_selectedCorrectBox == -1) {
|
|
_health = 0;
|
|
}
|
|
}
|
|
} else if (!at.video.empty()) {
|
|
_background->decoder->pauseVideo(true);
|
|
_masks->decoder->pauseVideo(true);
|
|
|
|
debugC(1, kHypnoDebugArcade, "Playing transition %s", at.video.c_str());
|
|
MVideo video(at.video, Common::Point(0, 0), false, true, false);
|
|
disableCursor();
|
|
runIntro(video);
|
|
|
|
if (!at.palette.empty())
|
|
_currentPalette = at.palette;
|
|
|
|
loadPalette(_currentPalette);
|
|
if (_levelId == 59) {
|
|
_background->decoder->forceSeekToFrame(97);
|
|
_masks->decoder->forceSeekToFrame(97);
|
|
}
|
|
|
|
_background->decoder->pauseVideo(false);
|
|
_masks->decoder->pauseVideo(false);
|
|
drawPlayer();
|
|
updateScreen(*_background);
|
|
drawScreen();
|
|
drawCursorArcade(g_system->getEventManager()->getMousePos());
|
|
} else if (!at.sound.empty()) {
|
|
playSound(at.sound, 1, at.soundRate, at.soundStereo);
|
|
} else if (at.jumpToTime > 0) {
|
|
_background->decoder->forceSeekToFrame(at.jumpToTime);
|
|
_masks->decoder->forceSeekToFrame(at.jumpToTime);
|
|
} else if (at.loseLevel) {
|
|
debugC(1, kHypnoDebugArcade, "Losing level in transition at %d", _background->decoder->getCurFrame());
|
|
_health = 0;
|
|
} else if (at.winLevel) {
|
|
debugC(1, kHypnoDebugArcade, "Wining level in transition at %d", _background->decoder->getCurFrame());
|
|
_skipLevel = true;
|
|
} else
|
|
error ("Invalid transition at %d", ttime);
|
|
|
|
transitions.pop_front();
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int BoyzEngine::detectTarget(const Common::Point &mousePos) {
|
|
Common::Point target = computeTargetPosition(mousePos);
|
|
if (!_mask)
|
|
return -1;
|
|
|
|
uint32 m = _mask->getPixel(target.x, target.y);
|
|
if (m == 0)
|
|
return -1;
|
|
|
|
int i = 0;
|
|
for (Shoots::iterator it = _shoots.begin(); it != _shoots.end(); ++it) {
|
|
if (!it->bodyFrames.empty() && _background->decoder->getCurFrame() > int(it->bodyFrames.back().start)) {
|
|
i++;
|
|
continue; // This shoot is old!
|
|
}
|
|
|
|
if (m == it->paletteOffset && !_shoots[i].destroyed)
|
|
return i;
|
|
i++;
|
|
}
|
|
if (i == int(_shoots.size()))
|
|
return -1;
|
|
|
|
error("Invalid mask state (%d)!", m);
|
|
}
|
|
|
|
char BoyzEngine::selectDirection() {
|
|
Common::Event event;
|
|
Common::Rect button(252, 158, 315, 195);
|
|
Graphics::Surface *screen = _compositeSurface->convertTo(_compositeSurface->format, _background->decoder->getPalette());
|
|
Frames mapFrames = decodeFrames("c4/minemap.smk");
|
|
bool showMap = _sceneState["GS_MINEMAP"];
|
|
bool viewingMap = false;
|
|
if (showMap)
|
|
drawImage(*mapFrames[0], 0, 0, true);
|
|
|
|
while (!shouldQuit()) {
|
|
while (g_system->getEventManager()->pollEvent(event)) {
|
|
Common::Point mousePos = g_system->getEventManager()->getMousePos();
|
|
switch (event.type) {
|
|
case Common::EVENT_MOUSEMOVE:
|
|
if (showMap && button.contains(mousePos))
|
|
defaultCursor();
|
|
else if (!viewingMap && mousePos.x <= _screenW / 3)
|
|
changeCursor(_leftArrowPointer, _crosshairsPalette, true);
|
|
else if (!viewingMap && mousePos.x >= 2 * _screenW / 3)
|
|
changeCursor(_rightArrowPointer, _crosshairsPalette, true);
|
|
else if (!viewingMap)
|
|
changeCursor(_crossPointer, _crosshairsPalette, true);
|
|
break;
|
|
|
|
case Common::EVENT_LBUTTONDOWN:
|
|
if (showMap && button.contains(mousePos)) {
|
|
if (viewingMap) {
|
|
drawImage(*screen, 0, 0, false);
|
|
drawImage(*mapFrames[0], 0, 0, true);
|
|
} else {
|
|
drawImage(*mapFrames[1], 0, 0, true);
|
|
}
|
|
viewingMap = !viewingMap;
|
|
} else if (!viewingMap && mousePos.x <= _screenH / 2) {
|
|
screen->free();
|
|
delete screen;
|
|
return 'L';
|
|
} else if (!viewingMap) {
|
|
screen->free();
|
|
delete screen;
|
|
return 'R';
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
drawScreen();
|
|
g_system->delayMillis(10);
|
|
}
|
|
screen->free();
|
|
delete screen;
|
|
return 0;
|
|
}
|
|
|
|
|
|
void BoyzEngine::waitForUserClick(uint32 timeout) {
|
|
Common::Event event;
|
|
bool cont = true;
|
|
Common::Rect button(252, 158, 315, 195);
|
|
while (!shouldQuit() && cont) {
|
|
while (g_system->getEventManager()->pollEvent(event)) {
|
|
Common::Point mousePos = g_system->getEventManager()->getMousePos();
|
|
switch (event.type) {
|
|
case Common::EVENT_QUIT:
|
|
case Common::EVENT_RETURN_TO_LAUNCHER:
|
|
cont = false;
|
|
break;
|
|
|
|
case Common::EVENT_LBUTTONDOWN:
|
|
if (button.contains(mousePos))
|
|
cont = false;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
drawScreen();
|
|
g_system->delayMillis(10);
|
|
}
|
|
}
|
|
|
|
int BoyzEngine::pickABox() {
|
|
Common::Event event;
|
|
|
|
Common::Rect correctBox(84, 14, 135, 66);
|
|
Common::Rect incorrectBoxes[6];
|
|
incorrectBoxes[0] = Common::Rect(15, 17, 77, 66);
|
|
incorrectBoxes[1] = Common::Rect(2, 69, 84, 92);
|
|
incorrectBoxes[2] = Common::Rect(74, 108, 242, 138);
|
|
incorrectBoxes[3] = Common::Rect(62, 134, 245, 160);
|
|
incorrectBoxes[4] = Common::Rect(59, 161, 239, 190);
|
|
incorrectBoxes[5] = Common::Rect(135, 29, 223, 101);
|
|
int i;
|
|
while (!shouldQuit()) {
|
|
while (g_system->getEventManager()->pollEvent(event)) {
|
|
Common::Point mousePos = g_system->getEventManager()->getMousePos();
|
|
switch (event.type) {
|
|
case Common::EVENT_MOUSEMOVE:
|
|
if (correctBox.contains(mousePos)) {
|
|
changeCursor(_crosshairsTarget[_currentWeapon], _crosshairsPalette, true);
|
|
break;
|
|
}
|
|
for (i = 0; i < 6; i++)
|
|
if (incorrectBoxes[i].contains(mousePos)) {
|
|
changeCursor(_crosshairsTarget[_currentWeapon], _crosshairsPalette, true);
|
|
break;
|
|
}
|
|
if (i == 6)
|
|
changeCursor(_crosshairsActive[_currentWeapon], _crosshairsPalette, true);
|
|
break;
|
|
|
|
case Common::EVENT_LBUTTONDOWN:
|
|
if (correctBox.contains(mousePos))
|
|
return 1;
|
|
for (i = 0; i < 6; i++)
|
|
if (incorrectBoxes[i].contains(mousePos))
|
|
return -1;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
drawScreen();
|
|
g_system->delayMillis(10);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
bool BoyzEngine::shoot(const Common::Point &mousePos, ArcadeShooting *arc, bool secondary) {
|
|
if (_currentMode == NonInteractive) {
|
|
return false;
|
|
}
|
|
|
|
if (!secondary && _currentWeapon > 0) {
|
|
if (_ammo == 0) {
|
|
if (!arc->noAmmoSound.empty())
|
|
playSound(_soundPath + arc->noAmmoSound, 1, arc->noAmmoSoundRate);
|
|
return false;
|
|
}
|
|
if (!_infiniteAmmoCheat)
|
|
_ammo--;
|
|
playSound(_soundPath + _weaponShootSound[_currentWeapon], 1);
|
|
incShotsFired();
|
|
}
|
|
int i = detectTarget(mousePos);
|
|
if (i < 0) {
|
|
missNoTarget(arc);
|
|
} else {
|
|
debugC(1, kHypnoDebugArcade, "Hit target %s", _shoots[i].name.c_str());
|
|
if (_shoots[i].nonHostile && secondary) {
|
|
playSound(_soundPath + _heySound[_currentActor], 1);
|
|
|
|
if (_shoots[i].isAnimal) {
|
|
playSound(_soundPath + _shoots[i].animalSound, 1);
|
|
return false;
|
|
}
|
|
|
|
// Not really killed, but counted as objective
|
|
_objKillsCount[_objIdx] = _objKillsCount[_objIdx] + _shoots[i].objKillsCount;
|
|
|
|
if (!_shoots[i].additionalVideo.empty()) {
|
|
incFriendliesEncountered();
|
|
incInfoReceived();
|
|
_background->decoder->pauseVideo(true);
|
|
MVideo video(_shoots[i].additionalVideo, Common::Point(0, 0), false, true, false);
|
|
disableCursor();
|
|
runIntro(video);
|
|
defaultCursor();
|
|
|
|
if (_shoots[i].waitForClickAfterInteraction > 0) {
|
|
waitForUserClick(_shoots[i].waitForClickAfterInteraction);
|
|
if (_shoots[i].name == "LILKID")
|
|
_sceneState["GS_MINEMAP"] = true;
|
|
else if (_shoots[i].name == "HO3") {
|
|
_sceneState["GS_C5MAP"] = true;
|
|
}
|
|
}
|
|
|
|
loadPalette(_currentPalette);
|
|
_background->decoder->pauseVideo(false);
|
|
// Skip the rest of the interaction
|
|
if (_shoots[i].explosionFrames[0].start == uint32(-1))
|
|
_skipLevel = true;
|
|
else {
|
|
_background->decoder->forceSeekToFrame(_shoots[i].explosionFrames[0].start + 3);
|
|
_masks->decoder->forceSeekToFrame(_shoots[i].explosionFrames[0].start + 3);
|
|
_shoots[i].destroyed = true;
|
|
_shootsDestroyed[_shoots[i].name] = true;
|
|
updateScreen(*_background);
|
|
drawScreen();
|
|
}
|
|
} else if (_shoots[i].interactionFrame > 0) {
|
|
incFriendliesEncountered();
|
|
incInfoReceived();
|
|
_background->decoder->forceSeekToFrame(_shoots[i].interactionFrame);
|
|
_masks->decoder->forceSeekToFrame(_shoots[i].interactionFrame);
|
|
if (!arc->missBoss2Video.empty()) {
|
|
_additionalVideo = new MVideo(arc->missBoss2Video, Common::Point(0, 0), true, false, false);
|
|
playVideo(*_additionalVideo);
|
|
}
|
|
//_shoots[i].lastFrame = _background->decoder->getFrameCount();
|
|
_shoots[i].destroyed = true;
|
|
_shootsDestroyed[_shoots[i].name] = true;
|
|
updateScreen(*_background);
|
|
drawScreen();
|
|
}
|
|
return false;
|
|
} else if (_shoots[i].nonHostile && !secondary) {
|
|
|
|
if (checkCup(_shoots[i].name))
|
|
return false;
|
|
|
|
if (!_shoots[i].hitSound.empty())
|
|
playSound(_soundPath + _shoots[i].hitSound, 1);
|
|
|
|
if (!_shoots[i].deathSound.empty())
|
|
playSound(_soundPath + _shoots[i].deathSound, 1);
|
|
|
|
if (!_shoots[i].additionalVideo.empty() || _shoots[i].interactionFrame > 0) // Only count the ones with info
|
|
incFriendliesEncountered();
|
|
|
|
uint32 idx = _shoots[i].warningVideoIdx;
|
|
if (idx > 0) {
|
|
Common::String filename = _warningVideosDay[idx];
|
|
|
|
_background->decoder->pauseVideo(true);
|
|
MVideo video(filename, Common::Point(0, 0), false, true, false);
|
|
disableCursor();
|
|
runIntro(video);
|
|
// Should be currentPalette?
|
|
loadPalette(arc->backgroundPalette);
|
|
_background->decoder->pauseVideo(false);
|
|
updateScreen(*_background);
|
|
drawScreen();
|
|
hitPlayer();
|
|
}
|
|
if (_shoots[i].explosionFrames.size() == 0)
|
|
return false;
|
|
|
|
debugC(1, kHypnoDebugArcade, "Jumping to %d", _shoots[i].explosionFrames[0].start - 3);
|
|
_background->decoder->forceSeekToFrame(_shoots[i].explosionFrames[0].start - 3);
|
|
_masks->decoder->forceSeekToFrame(_shoots[i].explosionFrames[0].start - 3);
|
|
|
|
|
|
if (_shoots[i].jumpToTimeAfterKilled == -1000) {
|
|
ArcadeTransition at("", 0, "", 0, _shoots[i].explosionFrames[0].lastFrame() - 1);
|
|
at.loseLevel = true;
|
|
_transitions.push_front(at);
|
|
}
|
|
|
|
return false;
|
|
} else if (!_shoots[i].nonHostile && secondary) {
|
|
if (_shoots[i].interactionFrame > 0) {
|
|
_background->decoder->forceSeekToFrame(_shoots[i].interactionFrame);
|
|
_masks->decoder->forceSeekToFrame(_shoots[i].interactionFrame);
|
|
_shoots[i].destroyed = true;
|
|
|
|
updateScreen(*_background);
|
|
drawScreen();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (!_shoots[i].hitSound.empty())
|
|
playSound(_soundPath + _shoots[i].hitSound, 1);
|
|
|
|
incEnemyHits();
|
|
if (!_shoots[i].deathSound.empty())
|
|
playSound(_soundPath + _shoots[i].deathSound, 1);
|
|
|
|
if (_shoots[i].playInteractionAudio && !arc->missBoss2Video.empty()) {
|
|
incInfoReceived();
|
|
_additionalVideo = new MVideo(arc->missBoss2Video, Common::Point(0, 0), true, false, false);
|
|
playVideo(*_additionalVideo);
|
|
}
|
|
|
|
incTargetsDestroyed();
|
|
incScore(_shoots[i].pointsToShoot);
|
|
incBonus(_shoots[i].pointsToShoot);
|
|
_shoots[i].destroyed = true;
|
|
_objKillsCount[_objIdx] = _objKillsCount[_objIdx] + _shoots[i].objKillsCount;
|
|
_shootsDestroyed[_shoots[i].name] = true;
|
|
|
|
if (_shoots[i].name == "HELICOPTER") {
|
|
_background->decoder->pauseVideo(true);
|
|
MVideo video(arc->hitBoss2Video, Common::Point(0, 0), false, true, false);
|
|
disableCursor();
|
|
runIntro(video);
|
|
_skipLevel = true;
|
|
_skipNextVideo = true;
|
|
return false;
|
|
}
|
|
|
|
_background->decoder->forceSeekToFrame(_shoots[i].explosionFrames[0].start - 3);
|
|
_masks->decoder->forceSeekToFrame(_shoots[i].explosionFrames[0].start - 3);
|
|
debugC(1, kHypnoDebugArcade, "Jumping to: %d", _shoots[i].explosionFrames[0].start - 3);
|
|
|
|
changeCursor(_crosshairsActive[_currentWeapon], _crosshairsPalette, true);
|
|
|
|
if (_shoots[i].jumpToTimeAfterKilled > 0) {
|
|
ArcadeTransition at("", 0, "", 0, _shoots[i].explosionFrames[0].lastFrame() - 1);
|
|
at.jumpToTime = _shoots[i].jumpToTimeAfterKilled;
|
|
_transitions.push_front(at);
|
|
} else if ( _shoots[i].jumpToTimeAfterKilled == -1 ) {
|
|
ArcadeTransition at("", 0, "", 0, _shoots[i].explosionFrames[0].lastFrame() - 1);
|
|
at.winLevel = true;
|
|
_transitions.push_front(at);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void BoyzEngine::missedTarget(Shoot *s, ArcadeShooting *arc) {
|
|
debugC(1, kHypnoDebugArcade, "Missed target %s!", s->name.c_str());
|
|
if (!s->checkIfDestroyed.empty()) {
|
|
if (_shootsDestroyed.contains(s->checkIfDestroyed))
|
|
return; // Precondition was destroyed, so we ignore the missed shoot
|
|
}
|
|
|
|
if (s->nonHostile) {
|
|
if (!s->additionalVideo.empty() || s->interactionFrame > 0) // Only count the ones with info
|
|
incFriendliesEncountered();
|
|
_stats.targetsMissed--; // If the target was not hostile, it should *not* count as missed
|
|
}
|
|
|
|
if (s->name == "CAPTOR" || (s->name == "G1" && _currentLevel == "c354.mi_")) {
|
|
_background->decoder->pauseVideo(true);
|
|
MVideo video(_warningHostage, Common::Point(0, 0), false, true, false);
|
|
disableCursor();
|
|
runIntro(video);
|
|
hitPlayer();
|
|
if (_health > 0)
|
|
_skipLevel = true;
|
|
return;
|
|
} else if (s->name.hasPrefix("ALARM")) {
|
|
if (s->missedAnimation != uint32(-1) && uint32(_background->decoder->getCurFrame()) > s->missedAnimation)
|
|
return;
|
|
_background->decoder->pauseVideo(true);
|
|
int territory = getTerritory(_currentLevel);
|
|
Filename path;
|
|
if (territory <= 2)
|
|
path = "misc/alrm_brs.smk";
|
|
else if (territory <= 4)
|
|
path = "misc/alrm_mbs.smk";
|
|
else
|
|
path = "misc/alrm_c5s.smk";
|
|
|
|
disableCursor();
|
|
MVideo alarmVideo(path, Common::Point(0, 0), false, true, false);
|
|
runIntro(alarmVideo);
|
|
|
|
MVideo warningVideo(_warningAlarmVideos.front(), Common::Point(0, 0), false, true, false);
|
|
runIntro(warningVideo);
|
|
_health = 0;
|
|
return;
|
|
} else if (s->direction > 0) {
|
|
char selected = selectDirection();
|
|
defaultCursor();
|
|
|
|
if (selected == s->direction) {
|
|
int missedAnimation = s->missedAnimation;
|
|
debugC(1, kHypnoDebugArcade, "Jumping to: %d", missedAnimation);
|
|
_background->decoder->forceSeekToFrame(missedAnimation);
|
|
_masks->decoder->forceSeekToFrame(missedAnimation);
|
|
} else {
|
|
_background->decoder->forceSeekToFrame(s->explosionFrames[0].start - 3);
|
|
_masks->decoder->forceSeekToFrame(s->explosionFrames[0].start - 3);
|
|
|
|
if (s->jumpToTimeAfterKilled == -1000) {
|
|
ArcadeTransition at("", 0, "", 0, s->explosionFrames[0].lastFrame() - 1);
|
|
at.loseLevel = true;
|
|
_transitions.push_front(at);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (s->missedAnimation == 0) {
|
|
return;
|
|
} else if (s->missedAnimation == uint32(-1)) {
|
|
debugC(1, kHypnoDebugArcade, "Jumping to end of level");
|
|
_skipLevel = true;
|
|
} else if (s->missedAnimation == uint32(-1000)) {
|
|
if (_background->decoder->getCurFrame() > int(s->explosionFrames[0].start))
|
|
return; // Too late for this
|
|
_health = 0;
|
|
} else {
|
|
int missedAnimation = s->missedAnimation;
|
|
if (missedAnimation + 3 > int(_background->decoder->getFrameCount()) - 1) {
|
|
_skipLevel = true;
|
|
return;
|
|
}
|
|
if (_background->decoder->getCurFrame() > missedAnimation)
|
|
return; // Too late for this
|
|
debugC(1, kHypnoDebugArcade, "Jumping to: %d", missedAnimation);
|
|
_background->decoder->forceSeekToFrame(missedAnimation);
|
|
_masks->decoder->forceSeekToFrame(missedAnimation);
|
|
}
|
|
|
|
if (s->attackFrames.size() > 0 && s->attackFrames.front() == 0)
|
|
return;
|
|
|
|
if (!s->nonHostile)
|
|
hitPlayer();
|
|
}
|
|
|
|
bool BoyzEngine::checkCup(const Common::String &name) {
|
|
if (name == "CUP1") {
|
|
if (_background->path == "c3/c35c01s.smk") {
|
|
MVideo video("c3/c35c07s.smk", Common::Point(0, 0), false, true, false);
|
|
disableCursor();
|
|
runIntro(video);
|
|
_skipLevel = true;
|
|
_sceneState["GS_WONSHELLGAME"] = 1;
|
|
} else {
|
|
MVideo video("c3/c35c06s.smk", Common::Point(0, 0), false, true, false);
|
|
disableCursor();
|
|
runIntro(video);
|
|
_health = 0;
|
|
}
|
|
return true;
|
|
} else if (name == "CUP2") {
|
|
if (_background->path == "c3/c35c02s.smk") {
|
|
MVideo video("c3/c35c07s.smk", Common::Point(0, 0), false, true, false);
|
|
disableCursor();
|
|
runIntro(video);
|
|
_skipLevel = true;
|
|
_sceneState["GS_WONSHELLGAME"] = 1;
|
|
} else {
|
|
MVideo video("c3/c35c06s.smk", Common::Point(0, 0), false, true, false);
|
|
disableCursor();
|
|
runIntro(video);
|
|
_health = 0;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool BoyzEngine::clickedSecondaryShoot(const Common::Point &mousePos) {
|
|
if (_currentMode == NonInteractive) {
|
|
return false;
|
|
}
|
|
|
|
Common::Rect ammoBarBox(320 - _ammoBar[_currentActor].w, 0, 320, _ammoBar[_currentActor].h);
|
|
if (ammoBarBox.contains(mousePos)) {
|
|
_ammo = _weaponMaxAmmo[_currentWeapon];
|
|
playSound(_soundPath + _weaponReloadSound[_currentWeapon], 1);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
} // namespace Hypno
|