Files
scummvm-cursorfix/engines/hypno/boyz/arcade.cpp
2026-02-02 04:50:13 +01:00

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