Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

334
engines/got/game/back.cpp Normal file
View File

@@ -0,0 +1,334 @@
/* 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 "got/game/back.h"
#include "common/file.h"
#include "got/events.h"
#include "got/game/boss1.h"
#include "got/game/boss2.h"
#include "got/game/boss3.h"
#include "got/game/move.h"
#include "got/game/object.h"
#include "got/game/script.h"
#include "got/gfx/image.h"
#include "got/vars.h"
namespace Got {
const char *OBJECT_NAMES[] = {
"Shrub", "Child's Doll", "UNUSED", "FUTURE",
"FUTURE", "FUTURE", "FUTURE", "FUTURE", "FUTURE",
"FUTURE", "FUTURE", "FUTURE", "FUTURE", "FUTURE",
"FUTURE"};
const char *ITEM_NAMES[] = {
"Enchanted Apple", "Lightning Power",
"Winged Boots", "Wind Power",
"Amulet of Protection", "Thunder Power"};
static const char *odinEndMessage;
void showLevel(const int newLevel) {
if (_G(area) == 2 && newLevel == 105) { // Shovel Maze
_G(thorInfo)._armor = 2; // eyeballs mode
loadNewThor();
_G(eyeballs) = 1;
} else if (_G(eyeballs) == 1) {
_G(setup).f25 = 0;
_G(thorInfo)._armor = 1;
loadNewThor();
_G(eyeballs) = 0;
}
_G(bossActive) = false;
if (!_G(shieldOn))
_G(actor[2])._active = false;
_G(slipping) = false;
if (_G(scrn)._iconGrid[_G(thor)->_centerY][_G(thor)->_centerX] == 154)
_G(thor)->_dir = 0;
// The original copied 130 bytes from _G(scrn).static_object onwards into sd_data.
// This doesn't make sense, because that would put the ending in the middle of _staticY.
// Plus, it follows with an entire copy of scrn into sd_data anyway, so the first
// move seems entirely redundant.
_G(scrn).save(_G(currentLevel));
_G(scrn).load(_G(newLevel));
_G(levelMusic) = _G(scrn)._music;
_G(thor)->_nextFrame = 0;
showObjects();
showEnemies();
// The original was probably shortly displaying Thor in direction 0 before switching back to its prior position.
// This behavior wasn't noticed during initial playthrough by Dreammaster - Warning has been added so it can be checked eventually.
if (_G(scrn)._iconGrid[_G(thor)->_centerY][_G(thor)->_centerX] == 154)
warning("showLevel - Potential short move missing");
if (_G(warpFlag))
_G(currentLevel) = newLevel - 5; // Force phase
_G(warpFlag) = false;
if (_G(warpScroll)) {
_G(warpScroll) = false;
if (_G(thor)->_dir == 0)
_G(currentLevel) = newLevel + 10;
else if (_G(thor)->_dir == 1)
_G(currentLevel) = newLevel - 10;
else if (_G(thor)->_dir == 2)
_G(currentLevel) = newLevel + 1;
else if (_G(thor)->_dir == 3)
_G(currentLevel) = newLevel - 1;
}
if (!_G(setup)._scrollFlag)
_G(currentLevel) = newLevel; // Force no scroll
switch (_G(newLevel) - _G(currentLevel)) {
case 0:
// Nothing to do
showLevelDone();
break;
case -1:
_G(gameMode) = MODE_AREA_CHANGE;
_G(transitionDir) = DIR_LEFT;
break;
case 1:
_G(gameMode) = MODE_AREA_CHANGE;
_G(transitionDir) = DIR_RIGHT;
break;
case -10:
_G(gameMode) = MODE_AREA_CHANGE;
_G(transitionDir) = DIR_UP;
break;
case 10:
_G(gameMode) = MODE_AREA_CHANGE;
_G(transitionDir) = DIR_DOWN;
break;
default:
_G(gameMode) = MODE_AREA_CHANGE;
_G(transitionDir) = DIR_PHASED;
break;
}
}
void showLevelDone() {
_G(currentLevel) = _G(newLevel);
_G(thorInfo)._lastHealth = _G(thor)->_health;
_G(thorInfo)._lastMagic = _G(thorInfo)._magic;
_G(thorInfo)._lastJewels = _G(thorInfo)._jewels;
_G(thorInfo)._lastKeys = _G(thorInfo)._keys;
_G(thorInfo)._lastScore = _G(thorInfo)._score;
_G(thorInfo)._lastItem = _G(thorInfo)._selectedItem;
_G(thorInfo)._lastScreen = _G(currentLevel);
_G(thorInfo)._lastIcon = ((_G(thor)->_x + 8) / 16) + (((_G(thor)->_y + 14) / 16) * 20);
_G(thorInfo)._lastDir = _G(thor)->_dir;
_G(thorInfo)._lastInventory = _G(thorInfo)._inventory;
_G(thorInfo)._lastObject = _G(thorInfo)._object;
_G(thorInfo)._lastObjectName = _G(thorInfo)._objectName;
_G(lastSetup) = _G(setup);
bool f = true;
if (GAME1 && _G(newLevel) == BOSS_LEVEL1 && !_G(setup)._bossDead[0]) {
boss1SetupLevel();
f = false;
}
if (GAME2 && _G(newLevel) == BOSS_LEVEL2 && !_G(setup)._bossDead[1]) {
boss2SetupLevel();
f = false;
}
if (GAME3) {
if (_G(newLevel) == BOSS_LEVEL3 && !_G(setup)._bossDead[2]) {
boss3SetupLevel();
f = false;
}
if (_G(currentLevel) == ENDING_SCREEN) {
endingScreen();
f = false;
}
}
if (_G(startup))
f = false;
if (f)
musicPlay(_G(levelMusic), false);
}
static void odin_speaks_end() {
// In case Thor is now dead, flag as such
if (!_G(thor)->_health) {
_G(thor)->_show = 0;
_G(exitFlag) = 2;
}
// If there's an end message, pass it on to the view hierarchy.
// This is used in cases like the game end where multiple
// odinSpeaks are done in sequence
if (odinEndMessage)
g_events->send(GameMessage(odinEndMessage));
}
void odinSpeaks(const int index, int item, const char *endMessage) {
odinEndMessage = endMessage;
executeScript((long)index, _G(odin), odin_speaks_end);
}
int switchIcons() {
playSound(WOOP, false);
for (int y = 0; y < 12; y++) {
for (int x = 0; x < 20; x++) {
const int ix = x * 16;
const int iy = y * 16;
if (_G(scrn)._iconGrid[y][x] == 93) {
placeTile(x, y, 144);
} else if (_G(scrn)._iconGrid[y][x] == 144) {
placeTile(x, y, 93);
killEnemies(iy, ix);
}
if (_G(scrn)._iconGrid[y][x] == 94) {
placeTile(x, y, 146);
} else if (_G(scrn)._iconGrid[y][x] == 146) {
placeTile(x, y, 94);
killEnemies(iy, ix);
}
}
}
return 0;
}
int rotateArrows() {
playSound(WOOP, false);
for (int y = 0; y < 12; y++) {
for (int x = 0; x < 20; x++) {
if (_G(scrn)._iconGrid[y][x] == 205)
placeTile(x, y, 208);
else if (_G(scrn)._iconGrid[y][x] == 206)
placeTile(x, y, 207);
else if (_G(scrn)._iconGrid[y][x] == 207)
placeTile(x, y, 205);
else if (_G(scrn)._iconGrid[y][x] == 208)
placeTile(x, y, 206);
}
}
return 0;
}
void killEnemies(const int iy, const int ix) {
int x1, y1, x2, y2;
for (int i = 3; i < MAX_ACTORS; i++) {
if (_G(actor[i])._active) {
x1 = _G(actor[i])._x;
y1 = _G(actor[i])._y + _G(actor[i])._sizeY - 2;
x2 = (_G(actor[i])._x + _G(actor[i])._sizeX);
y2 = _G(actor[i])._y + _G(actor[i])._sizeY - 1;
if (pointWithin(x1, y1, ix, iy, ix + 15, iy + 15) || pointWithin(x2, y1, ix, iy, ix + 15, iy + 15)
|| pointWithin(x1, y2, ix, iy, ix + 15, iy + 15) || pointWithin(x2, y2, ix, iy, ix + 15, iy + 15))
actorDestroyed(&_G(actor[i]));
}
}
x1 = _G(thor)->_x;
y1 = _G(thor)->_y + 11;
x2 = x1 + 13;
y2 = y1 + 5;
if (pointWithin(x1, y1, ix, iy, ix + 15, iy + 15) || pointWithin(x2, y1, ix, iy, ix + 15, iy + 15)
|| pointWithin(x1, y2, ix, iy, ix + 15, iy + 15) || pointWithin(x2, y2, ix, iy, ix + 15, iy + 15)) {
if (!_G(cheats)._freezeHealth) {
_G(thor)->_health = 0;
g_events->send(GameMessage("THOR_DIES"));
}
}
}
void removeObjects(const int y, const int x) {
const int p = (y * 20) + x;
if (_G(objectMap[p]) > 0) {
_G(objectMap[p]) = 0;
_G(objectIndex[p]) = 0;
}
}
void placeTile(const int x, const int y, const int tile) {
_G(scrn)._iconGrid[y][x] = tile;
removeObjects(y, x);
}
int backgroundTile(int x, int y) {
if (x < 0 || x >= 319 || y < 0 || y >= 191)
return 0;
x = (x + 1) >> 4;
y = (y + 1) >> 4;
return _G(scrn)._iconGrid[y][x];
}
void selectItem() {
// Only allow opening the dialog if something isn't currently going on
if (g_engine->canSaveAutosaveCurrently()) {
g_events->addView("SelectItem");
}
}
void actorSpeaks(const Actor *actor, int index, int item) {
if (actor->_type != 4)
return;
const int v = atoi(actor->_name);
if (v < 1 || v > 20)
return;
long lind = (long)_G(currentLevel);
lind = lind * 1000;
lind += (long)actor->_actorNum;
const Common::String str = Common::String::format("FACE%d", v);
if (Common::File::exists(Common::Path(str))) {
Gfx::Pics pics(str, 262);
executeScript(lind, pics);
} else {
executeScript(lind, _G(odin));
}
if (!_G(thor)->_health) {
_G(thor)->_show = 0;
_G(exitFlag) = 2;
}
}
} // namespace Got

52
engines/got/game/back.h Normal file
View 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/>.
*
*/
#ifndef GOT_GAME_BACK_H
#define GOT_GAME_BACK_H
#include "got/data/defines.h"
namespace Got {
extern const char *OBJECT_NAMES[];
extern const char *ITEM_NAMES[];
/**
* Shows a new level
* In the original this did some initial actors setup and rendering.
* Now in ScummVM, it only does the setup portions, since the
* GameContent view takes care of the scene rendering.
*/
extern void showLevel(int newLevel);
extern void showLevelDone();
extern void odinSpeaks(int index, int item, const char *endMessage = nullptr);
extern int switchIcons();
extern int rotateArrows();
extern void killEnemies(int iy, int ix);
extern void removeObjects(int y, int x);
extern void placeTile(int x, int y, int tile);
extern int backgroundTile(int x, int y);
extern void selectItem();
extern void actorSpeaks(const Actor *actor, int index, int item);
} // namespace Got
#endif

298
engines/got/game/boss1.cpp Normal file
View File

@@ -0,0 +1,298 @@
/* 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 "got/game/boss1.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/game/move.h"
#include "got/game/move_patterns.h"
#include "got/game/status.h"
#include "got/gfx/image.h"
#include "got/sound.h"
#include "got/vars.h"
namespace Got {
static int boss1_dead();
int boss1Movement(Actor *actor) {
bool f = false;
if (_G(bossDead))
return boss1_dead();
int d = actor->_lastDir;
int x1 = actor->_x;
int y1 = actor->_y;
if (actor->_edgeCounter) {
actor->_edgeCounter--;
goto done;
}
if (overlap(actor->_x + 2, actor->_y + 8, actor->_x + 30, actor->_y + 30,
_G(thor)->_x, _G(thor)->_y + 8, _G(thor)->_x + 15, _G(thor)->_y + 15)) {
thorDamaged(actor);
}
if (actor->_temp3) { //start striking
actor->_temp3--;
if (!actor->_temp3)
playSound(BOSS11, false);
actor->_numMoves = 6;
goto done0;
}
// Strike
if (actor->_temp1) {
actor->_temp1--;
if (actor->_x < (_G(thorX1) + 12))
actor->_temp1 = 0;
actor->_temp2 = 1;
d = 2;
actor->_x -= 2;
if (overlap(actor->_x + 2, actor->_y + 8, actor->_x + 32, actor->_y + 30,
_G(thor)->_x, _G(thor)->_y + 8, _G(thor)->_x + 15, _G(thor)->_y + 15)) {
actor->_temp1 = 0;
goto done1;
}
actor->_nextFrame = 3;
actor->_numMoves = _G(setup)._difficultyLevel + 2;
goto done1;
}
if (actor->_temp2) { // Retreating
if (actor->_x < 256) {
d = 3;
actor->_x += 2;
if (overlap(actor->_x + 2, actor->_y + 8, actor->_x + 32, actor->_y + 30,
_G(thor)->_x, _G(thor)->_y + 8, _G(thor)->_x + 15, _G(thor)->_y + 15)) {
goto done1;
}
actor->_numMoves = _G(setup)._difficultyLevel + 1;
goto done0;
}
actor->_temp2 = 0;
}
if (actor->_x > _G(thorX1) && ABS((_G(thorY1)) - (actor->_y + 20)) < 8) {
actor->_temp3 = 75;
actor->_temp1 = 130;
actor->_temp2 = 0;
}
if (actor->_counter) {
actor->_counter--;
switch (d) {
case 1:
case 3:
x1 = _G(actor[5])._x;
y1 = _G(actor[5])._y;
y1 += 2;
if (!checkMove2(x1, y1, &_G(actor[5])))
f = true;
else {
actor->_x = _G(actor[5])._x;
actor->_y = _G(actor[5])._y - 16;
}
break;
case 0:
case 2:
y1 -= 2;
if (!checkMove2(x1, y1, actor))
f = true;
break;
default:
break;
}
} else
f = true;
if (f) {
actor->_counter = g_events->getRandomNumber(10, 99);
d = g_events->getRandomNumber(1);
actor->_edgeCounter = 20;
}
done:
if (d > 1)
d -= 2;
done0:
nextFrame(actor);
if (actor->_nextFrame == 3)
actor->_nextFrame = 0;
done1:
actor->_lastDir = d;
_G(actor[4])._nextFrame = actor->_nextFrame;
_G(actor[5])._nextFrame = actor->_nextFrame;
_G(actor[6])._nextFrame = actor->_nextFrame;
_G(actor[4])._lastDir = d;
_G(actor[5])._lastDir = d;
_G(actor[6])._lastDir = d;
_G(actor[4])._x = actor->_x + 16;
_G(actor[4])._y = actor->_y;
_G(actor[5])._x = actor->_x;
_G(actor[5])._y = actor->_y + 16;
_G(actor[6])._x = actor->_x + 16;
_G(actor[6])._y = actor->_y + 16;
_G(actor[4])._numMoves = actor->_numMoves;
_G(actor[5])._numMoves = actor->_numMoves;
_G(actor[6])._numMoves = actor->_numMoves;
if (actor->_directions == 1)
return 0;
return d;
}
void boss1CheckHit(const Actor *actor, const int x1, const int y1, const int x2, const int y2, const int actorNum) {
if (actor->_moveType == 15 && actorNum == 4) {
if ((!_G(actor[3])._vulnerableCountdown) && (_G(actor[3])._nextFrame != 3) &&
overlap(x1, y1, x2, y2, actor->_x + 6, actor->_y + 4, actor->_x + 14, actor->_y + 20)) {
actorDamaged(&_G(actor[3]), _G(hammer)->_hitStrength);
if (_G(cheat) && _G(keyFlag[GOT_Z]))
_G(actor[3])._health = 0;
else
_G(actor[3])._health -= 10;
_G(actor[3])._moveCountdown = 50;
_G(actor[3])._vulnerableCountdown = 100;
playSound(BOSS13, true);
_G(actor[3])._nextFrame = 1;
for (int rep = 4; rep < 7; rep++) {
_G(actor[rep])._nextFrame = 1;
_G(actor[rep])._moveCountdown = 50;
}
if (_G(actor[3])._health == 0)
_G(bossDead) = true;
}
}
}
void boss1SetupLevel() {
setupBoss(1);
_G(bossActive) = true;
musicPause();
playSound(BOSS11, true);
g_events->send("Game", GameMessage("PAUSE", 40));
musicPlay(5, true);
}
static int boss1_dead() {
if (_G(bossDead)) {
for (int rep = 0; rep < 4; rep++) {
const int x1 = _G(actor[3 + rep])._lastX[_G(pge)];
const int y1 = _G(actor[3 + rep])._lastY[_G(pge)];
const int x = _G(actor[3 + rep])._x;
const int y = _G(actor[3 + rep])._y;
const int n = _G(actor[3 + rep])._actorNum;
const int r = _G(actor[3 + rep])._dropRating;
_G(actor[3 + rep]) = _G(explosion);
_G(actor[3 + rep])._actorNum = n;
_G(actor[3 + rep])._dropRating = r;
_G(actor[3 + rep])._x = x;
_G(actor[3 + rep])._y = y;
_G(actor[3 + rep])._lastX[_G(pge)] = x1;
_G(actor[3 + rep])._lastX[_G(pge) ^ 1] = x;
_G(actor[3 + rep])._lastY[_G(pge)] = y1;
_G(actor[3 + rep])._lastY[_G(pge) ^ 1] = y;
_G(actor[3 + rep])._active = true;
_G(actor[3 + rep])._vulnerableCountdown = 255;
_G(actor[3 + rep])._moveType = 6;
_G(actor[3 + rep])._nextFrame = rep;
_G(actor[3 + rep])._speed = g_events->getRandomNumber(6, 8);
_G(actor[3 + rep])._currNumShots = (10 - _G(actor[3 + rep])._speed) * 10;
_G(actor[3 + rep])._moveCountdown = _G(actor[3 + rep])._speed;
}
playSound(EXPLODE, true);
_G(bossDead) = true;
for (int rep = 7; rep < MAX_ACTORS; rep++) {
if (_G(actor[rep])._active)
actorDestroyed(&_G(actor[rep]));
}
}
return _G(actor[3])._lastDir;
}
void boss1ClosingSequence1() {
_G(gameOver) = true;
musicPlay(4, true);
odinSpeaks(1001, 13, "CLOSING");
}
void boss1ClosingSequence2() {
_G(thorInfo)._armor = 1;
loadNewThor();
_G(thor)->_dir = 1;
_G(thor)->_nextFrame = 0;
fillScore(20, "CLOSING");
}
void boss1ClosingSequence3() {
fillHealth();
fillMagic();
odinSpeaks(1002, 0, "CLOSING");
}
void boss1ClosingSequence4() {
for (int rep = 0; rep < 16; rep++)
_G(scrn)._actorType[rep] = 0;
_G(bossDead) = false;
_G(setup)._bossDead[0] = true;
_G(bossActive) = false;
_G(scrn)._music = 4;
showLevel(BOSS_LEVEL1);
#ifdef USE_TTS
_G(thorInfo)._previousScore = -1;
#endif
playSound(ANGEL, true);
placeTile(18, 6, 148);
placeTile(19, 6, 202);
actorVisible(1);
actorVisible(2);
Level lvl;
lvl.load(59);
lvl._iconGrid[6][18] = 148;
lvl._iconGrid[6][19] = 202;
lvl.save(59);
}
} // namespace Got

40
engines/got/game/boss1.h Normal file
View 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/>.
*
*/
#ifndef GOT_GAME_BOSS1_H
#define GOT_GAME_BOSS1_H
#include "got/data/defines.h"
namespace Got {
// Boss 1 - Snake (Jormangund)
extern int boss1Movement(Actor *actor);
extern void boss1CheckHit(const Actor *actor, int x1, int y1, int x2, int y2, int actorNum);
extern void boss1SetupLevel();
extern void boss1ClosingSequence1();
extern void boss1ClosingSequence2();
extern void boss1ClosingSequence3();
extern void boss1ClosingSequence4();
} // namespace Got
#endif

436
engines/got/game/boss2.cpp Normal file
View File

@@ -0,0 +1,436 @@
/* 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 "got/game/boss2.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/game/move.h"
#include "got/game/status.h"
#include "got/gfx/image.h"
#include "got/sound.h"
#include "got/vars.h"
namespace Got {
static const byte EXPLOSION[] = {
61, 62, 65, 66, 69, 70, 73, 74, 77, 78,
81, 82, 85, 86, 89, 90, 93, 94, 97, 98,
101, 102, 105, 106, 109, 110, 113, 114, 117, 118,
121, 122, 125, 126, 129, 130, 133, 134, 137, 138,
141, 142, 145, 146, 149, 150, 153, 154, 157, 158,
161, 162, 165, 166, 169, 170, 173, 174, 177, 178
};
static bool expf[60];
static byte numSkulls;
static byte numSpikes;
static bool dropFlag;
static byte su[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static int boss2MovementExplode(Actor *actor);
static int boss2MovementShake(Actor *actor);
static int boss2Die();
static void bossSet(byte d, int x, int y);
int boss2Movement(Actor *actor) {
switch (_G(setup)._difficultyLevel) {
case 0:
numSkulls = 3;
numSpikes = 5;
break;
case 1:
numSkulls = 6;
numSpikes = 8;
break;
case 2:
numSkulls = 9;
numSpikes = 11;
break;
default:
break;
}
if (_G(bossDead))
return boss2Die();
if (actor->_i1) {
if (actor->_i1 == 1)
return boss2MovementExplode(actor);
return boss2MovementShake(actor);
}
byte d = actor->_lastDir;
int x = actor->_x;
if (actor->_temp6)
actor->_temp6--;
if (!actor->_temp6) {
bool f = false;
dropFlag = false;
if (actor->_temp5)
actor->_temp5--;
if (!actor->_temp5)
f = true;
else {
if (d == 2) {
if (x > 18)
actor->_x -= 2;
else
f = true;
} else if (d == 3) {
if (x < 272)
actor->_x += 2;
else
f = true;
}
}
if (f) {
actor->_temp5 = _G(rand1) + 60;
if (d == 2)
d = 3;
else
d = 2;
}
}
const int count = actor->_frameCount - 1;
if (count <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 2)
actor->_nextFrame = 0;
actor->_frameCount = actor->_frameSpeed;
} else
actor->_frameCount = count;
x = actor->_x;
if (actor->_currNumShots < numSkulls && !dropFlag) {
if (x == 48 || x == 112 || x == 176 || x == 240) {
dropFlag = true;
_G(actor[3])._temp6 = 40;
actorAlwaysShoots(actor, 1);
playSound(FALL, false);
_G(actor[actor->_shotActor])._x = actor->_x + 12;
_G(actor[actor->_shotActor])._y = actor->_y + 32;
_G(actor[actor->_shotActor])._temp2 = 0;
_G(actor[actor->_shotActor])._temp3 = 4;
_G(actor[actor->_shotActor])._temp4 = 4;
}
}
bossSet(d, x, actor->_y);
if (actor->_directions == 1)
return 0;
return d;
}
static void bossSet(const byte d, const int x, const int y) {
_G(actor[4])._nextFrame = _G(actor[3])._nextFrame;
_G(actor[5])._nextFrame = _G(actor[3])._nextFrame;
_G(actor[6])._nextFrame = _G(actor[3])._nextFrame;
_G(actor[3])._lastDir = d;
_G(actor[4])._lastDir = d;
_G(actor[5])._lastDir = d;
_G(actor[6])._lastDir = d;
_G(actor[4])._x = x + 16;
_G(actor[4])._y = y;
_G(actor[5])._x = x;
_G(actor[5])._y = y + 16;
_G(actor[6])._x = x + 16;
_G(actor[6])._y = y + 16;
}
void boss2CheckHit(Actor *actor) {
if (!_G(actor[3])._vulnerableCountdown) {
actorDamaged(&_G(actor[3]), _G(hammer)->_hitStrength);
_G(actor[3])._health -= 10;
if (_G(actor[3])._health == 50) {
playSound(BOSS12, true);
g_events->send("Game", GameMessage("PAUSE", 40));
_G(actor[3])._i1 = 1;
_G(actor[3])._i2 = 0;
memset(expf, 0, sizeof(expf));
for (int rep = 7; rep < MAX_ACTORS; rep++) {
if (_G(actor[rep])._active)
actorDestroyed(&_G(actor[rep]));
}
_G(actor[3])._currNumShots = 0;
} else
playSound(BOSS13, true);
_G(actor[3])._moveCountdown = 75;
_G(actor[3])._vulnerableCountdown = 75;
_G(actor[3])._nextFrame = 1;
for (int rep = 4; rep < 7; rep++) {
_G(actor[rep])._nextFrame = 1;
_G(actor[rep])._moveCountdown = 50;
}
if (_G(actor[3])._health == 0) {
_G(bossDead) = true;
for (int rep = 7; rep < MAX_ACTORS; rep++) {
if (_G(actor[rep])._active)
actorDestroyed(&_G(actor[rep]));
}
}
}
}
void boss2SetupLevel() {
setupBoss(2);
_G(bossActive) = true;
musicPause();
playSound(BOSS11, true);
dropFlag = false;
Common::fill(su, su + 18, 0);
g_events->send("Game", GameMessage("PAUSE", 40));
musicPlay(7, true);
}
static int boss2Die() {
_G(thunderSnakeCounter) = 0;
if (_G(bossDead)) {
for (int rep = 0; rep < 4; rep++) {
const int x1 = _G(actor[3 + rep])._lastX[_G(pge)];
const int y1 = _G(actor[3 + rep])._lastY[_G(pge)];
const int x = _G(actor[3 + rep])._x;
const int y = _G(actor[3 + rep])._y;
const int n = _G(actor[3 + rep])._actorNum;
const int r = _G(actor[3 + rep])._dropRating;
_G(actor[3 + rep]) = _G(explosion);
_G(actor[3 + rep])._actorNum = n;
_G(actor[3 + rep])._dropRating = r;
_G(actor[3 + rep])._x = x;
_G(actor[3 + rep])._y = y;
_G(actor[3 + rep])._lastX[_G(pge)] = x1;
_G(actor[3 + rep])._lastX[_G(pge) ^ 1] = x;
_G(actor[3 + rep])._lastY[_G(pge)] = y1;
_G(actor[3 + rep])._lastY[_G(pge) ^ 1] = y;
_G(actor[3 + rep])._active = true;
_G(actor[3 + rep])._vulnerableCountdown = 255;
_G(actor[3 + rep])._moveType = 6;
_G(actor[3 + rep])._nextFrame = rep;
_G(actor[3 + rep])._speed = g_events->getRandomNumber(6, 8);
_G(actor[3 + rep])._currNumShots = (10 - _G(actor[3 + rep])._speed) * 10;
_G(actor[3 + rep])._moveCountdown = _G(actor[3 + rep])._speed;
}
playSound(EXPLODE, true);
_G(bossDead) = true;
}
return _G(actor[3])._lastDir;
}
// Boss - skull (explode)
static int boss2MovementExplode(Actor *actor) {
nextFrame(actor);
_G(actor[4])._nextFrame = actor->_nextFrame;
_G(actor[5])._nextFrame = actor->_nextFrame;
_G(actor[6])._nextFrame = actor->_nextFrame;
actor->_vulnerableCountdown = 20;
if (actor->_currNumShots || _G(actor[5])._currNumShots)
return 0;
playSound(EXPLODE, true);
actorAlwaysShoots(&_G(actor[5]), 0);
const int an = _G(actor[5])._shotActor;
_G(actor[an])._moveType = 9;
int r = _G(rand1) % 60;
while (expf[r]) {
r++;
if (r > 59)
r = 0;
}
expf[r] = true;
const int x = (EXPLOSION[r] % 20) * 16;
const int y = (EXPLOSION[r] / 20) * 16;
_G(actor[an])._x = x;
_G(actor[an])._y = y;
_G(scrn)._iconGrid[y / 16][x / 16] = _G(scrn)._backgroundColor;
_G(actor[3])._i2++;
if (_G(actor[3])._i2 > 59) {
_G(actor[3])._i1 = 2;
_G(actor[3])._i2 = 0;
_G(actor[3])._numMoves = 3;
}
return 0;
}
// Boss - skull - shake
static int boss2MovementShake(Actor *actor) {
int rep, hx;
if (_G(hammer)->_active && _G(hammer)->_moveType != 5) {
hx = _G(hammer)->_x;
const int hy = _G(hammer)->_y;
for (rep = 7; rep < 15; rep++) {
if (!_G(actor[rep])._active)
continue;
if (overlap(hx + 1, hy + 1, hx + 10, hy + 10, _G(actor[rep])._x, _G(actor[rep])._y,
_G(actor[rep])._x + _G(actor[rep])._sizeX - 1, _G(actor[rep])._y + _G(actor[rep])._sizeY - 1)) {
_G(hammer)->_moveType = 5;
_G(hammer)->_dir = reverseDirection(_G(hammer));
break;
}
}
}
if (actor->_i4) {
actor->_i4--;
if (!actor->_i4)
_G(thunderSnakeCounter) = 0;
}
if (!actor->_i2) {
if (actor->_x < 144)
actor->_x += 2;
else if (actor->_x > 144)
actor->_x -= 2;
else {
actor->_i2 = 1;
actor->_i3 = 0;
}
goto done;
}
if (_G(actor[4])._currNumShots)
goto done;
if (!actor->_i3) {
actor->_i3 = g_events->getRandomNumber(2, 3);
}
if (actor->_i3 == 2)
actor->_x -= 2;
else
actor->_x += 2;
if (actor->_x < 20 || actor->_x > 270) {
_G(thunderSnakeCounter) = 100;
actor->_i4 = 50;
playSound(EXPLODE, true);
actor->_i2 = 0;
Common::fill(su, su + 18, 0);
actorAlwaysShoots(&_G(actor[4]), 1);
int an = _G(actor[4])._shotActor;
hx = (_G(thor)->_x / 16);
_G(actor[an])._x = _G(thor)->_x; //hx*16;
_G(actor[an])._y = g_events->getRandomNumber(15);
su[hx] = 1;
_G(actor[an])._nextFrame = g_events->getRandomNumber(3);
for (rep = 0; rep < numSpikes; rep++) {
while (true) {
hx = g_events->getRandomNumber(17);
if (!su[hx])
break;
}
su[hx] = 1;
actorAlwaysShoots(&_G(actor[4]), 1);
an = _G(actor[4])._shotActor;
_G(actor[an])._nextFrame = g_events->getRandomNumber(3);
_G(actor[an])._x = 16 + hx * 16;
_G(actor[an])._y = g_events->getRandomNumber(15);
}
}
done:
nextFrame(actor);
bossSet(actor->_dir, actor->_x, actor->_y);
return 0;
}
void boss2ClosingSequence1() {
musicPlay(6, true);
odinSpeaks(1001, 0, "CLOSING");
}
void boss2ClosingSequence2() {
_G(thorInfo)._armor = 10;
loadNewThor();
_G(thor)->_dir = 1;
_G(thor)->_nextFrame = 0;
fillScore(20, "CLOSING");
}
void boss2ClosingSequence3() {
fillHealth();
fillMagic();
odinSpeaks(1002, 0, "CLOSING");
}
void boss2ClosingSequence4() {
for (int rep = 0; rep < 16; rep++)
_G(scrn)._actorType[rep] = 0;
_G(bossDead) = false;
_G(setup)._bossDead[1] = true;
_G(gameOver) = true;
_G(bossActive) = false;
_G(scrn)._music = 6;
showLevel(BOSS_LEVEL2);
#ifdef USE_TTS
_G(thorInfo)._previousScore = -1;
#endif
playSound(ANGEL, true);
placeTile(18, 10, 152);
placeTile(19, 10, 202);
actorVisible(1);
actorVisible(2);
_G(actor[7])._x = 288;
_G(actor[7])._y = 160;
_G(actor[8])._x = 304;
_G(actor[8])._y = 160;
Level lvl;
lvl.load(BOSS_LEVEL2);
lvl._iconGrid[6][18] = 152;
lvl._iconGrid[6][19] = 202;
lvl.save(BOSS_LEVEL2);
}
} // namespace Got

40
engines/got/game/boss2.h Normal file
View 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/>.
*
*/
#ifndef GOT_GAME_BOSS2_H
#define GOT_GAME_BOSS2_H
#include "got/data/defines.h"
namespace Got {
// Boss 2 - Skull (Nognir)
extern int boss2Movement(Actor *actor);
extern void boss2CheckHit(Actor *actor);
extern void boss2SetupLevel();
extern void boss2ClosingSequence1();
extern void boss2ClosingSequence2();
extern void boss2ClosingSequence3();
extern void boss2ClosingSequence4();
} // namespace Got
#endif

666
engines/got/game/boss3.cpp Normal file
View File

@@ -0,0 +1,666 @@
/* 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 "got/game/boss3.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/game/move.h"
#include "got/game/move_patterns.h"
#include "got/game/status.h"
#include "got/sound.h"
#include "got/vars.h"
namespace Got {
#define LFC 10
static const byte EXPLOSION[4][8] = {
{126, 127, 128, 129, 130, 131, 132, 133},
{146, 147, 148, 149, 150, 151, 152, 153},
{166, 167, 168, 169, 170, 171, 172, 173},
{186, 187, 188, 189, 190, 191, 192, 193}
};
static int bossMode;
static int numPods1;
static byte podSpeed;
static bool explosionFlag[4][8];
static byte explosionCounter;
static int bossDie();
static void boss3CheckHit();
static void bossChangeMode();
static void setBoss(Actor *actor) {
_G(actor[4])._nextFrame = actor->_nextFrame;
_G(actor[5])._nextFrame = actor->_nextFrame;
_G(actor[6])._nextFrame = actor->_nextFrame;
_G(actor[4])._lastDir = actor->_dir;
_G(actor[5])._lastDir = actor->_dir;
_G(actor[6])._lastDir = actor->_dir;
_G(actor[4])._dir = actor->_dir;
_G(actor[5])._dir = actor->_dir;
_G(actor[6])._dir = actor->_dir;
_G(actor[4])._x = actor->_x + 16;
_G(actor[4])._y = actor->_y;
_G(actor[5])._x = actor->_x;
_G(actor[5])._y = actor->_y + 16;
_G(actor[6])._x = actor->_x + 16;
_G(actor[6])._y = actor->_y + 16;
}
// Boss - Loki-2
static int boss3Movement1(Actor *actor) {
int rx, ry, i, numPods = 0;
int fcount;
actor->_numMoves = 2;
podSpeed = 2;
switch (_G(setup)._difficultyLevel) {
case 0:
numPods = 3;
break;
case 1:
numPods = 5;
break;
case 2:
numPods = 8;
break;
default:
break;
}
if (!actor->_temp1) {
// Disappear
actor->_dir = 1;
actor->_frameCount = LFC;
actor->_nextFrame = 0;
actor->_temp1 = 1;
actor->_i6 = 1;
actor->_solid |= 128;
_G(actor[4])._solid |= 128;
_G(actor[5])._solid |= 128;
_G(actor[6])._solid |= 128;
playSound(EXPLODE, true);
goto done;
}
if (actor->_i6) {
// Fade out
fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 2) {
actor->_i6 = 0;
actor->_temp3 = 160;
}
actor->_frameCount = 3;
} else
actor->_frameCount = fcount;
goto done1;
}
if (actor->_temp3 > 1) {
actor->_temp3--;
goto done1;
}
if (actor->_temp3) {
for (i = 0; i < numPods1; i++)
if (_G(actor[19 + i])._active)
goto done1;
while (true) {
rx = g_events->getRandomNumber(255) + 16;
ry = g_events->getRandomNumber(143);
if (!overlap(rx, ry, rx + 32, ry + 32, _G(thorX1), _G(thorY1), _G(thorX2), _G(thorY2)))
break;
}
actor->_x = rx;
actor->_y = ry;
actor->_frameCount = LFC;
actor->_temp4 = 40;
actor->_temp3 = 0;
playSound(EXPLODE, true);
goto done1;
}
if (actor->_temp4) {
// Fade in
fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame--;
if (actor->_nextFrame > 254) {
actor->_nextFrame = 0;
actor->_dir = 0;
actor->_temp4 = 0;
actor->_temp5 = 80;
actor->_solid &= 0x7f;
_G(actor[4])._solid &= 0x7f;
_G(actor[5])._solid &= 0x7f;
_G(actor[6])._solid &= 0x7f;
}
actor->_frameCount = 3;
} else
actor->_frameCount = fcount;
goto done1;
}
if (actor->_temp5) {
// Shoot
actor->_temp5--;
if (actor->_temp5 == 20) {
actor->_nextFrame = 3;
goto done1;
}
if (!actor->_temp5) {
if (_G(actor[4])._currNumShots < _G(actor[4])._numShotsAllowed) {
actorAlwaysShoots(&_G(actor[4]), 0);
const byte shot_actor = _G(actor[4])._shotActor;
_G(actor[shot_actor])._numMoves = podSpeed;
_G(actor[shot_actor])._x = actor->_x + 8;
_G(actor[shot_actor])._y = actor->_y + 16;
_G(actor[shot_actor])._temp5 = 0;
for (i = 0; i < numPods; i++)
_G(actor[20 + i]) = _G(actor[19]);
numPods1 = numPods;
actor->_temp1 = 0;
}
}
if (actor->_temp5 < 31)
goto done1;
}
done:
fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 2)
actor->_nextFrame = 0;
actor->_frameCount = LFC;
} else
actor->_frameCount = fcount;
done1:
setBoss(actor);
return actor->_dir;
}
// Boss - Loki-1
int boss3Movement(Actor *actor) {
int x1, y1, ox, oy;
int fcount;
if (actor->_temp2)
actor->_temp2--;
if (_G(bossDead))
return bossDie();
boss3CheckHit();
if (!bossMode)
return boss3Movement1(actor);
numPods1 = 10;
switch (_G(setup)._difficultyLevel) {
case 0:
actor->_numMoves = 3;
actor->_speed = 2;
break;
case 1:
actor->_numMoves = 2;
actor->_speed = 1;
break;
case 2:
actor->_numMoves = 5;
actor->_speed = 2;
break;
default:
break;
}
int d = actor->_lastDir;
actor->_temp3++;
int f = 0;
if (actor->_temp4) {
actor->_temp4--;
if (!actor->_temp4) {
actor->_temp3 = 0;
_G(actor[3])._frameSpeed = 4;
_G(actor[3])._dir = 0;
_G(actor[3])._lastDir = 0;
_G(actor[3])._nextFrame = 3;
_G(actor[4])._dir = 0;
_G(actor[4])._lastDir = 0;
_G(actor[4])._nextFrame = 3;
}
goto skip_move;
}
if (actor->_edgeCounter)
actor->_edgeCounter--;
else
goto new_dir;
if (overlap(actor->_x + 2, actor->_y + 8, actor->_x + 30, actor->_y + 30, _G(thor)->_x, _G(thor)->_y + 4, _G(thor)->_x + 15, _G(thor)->_y + 15))
thorDamaged(actor);
ox = actor->_x;
oy = actor->_y;
switch (actor->_temp5) {
case 0:
x1 = _G(actor[3])._x;
y1 = _G(actor[3])._y - 2;
if (!checkMove2(x1, y1, &_G(actor[3]))) {
f = 1;
break;
}
if (!checkMove2(x1 + 16, y1, &_G(actor[4])))
f = 1;
actor->_y = oy - 2;
break;
case 1:
x1 = _G(actor[5])._x;
y1 = _G(actor[5])._y + 2;
if (!checkMove2(x1, y1, &_G(actor[5]))) {
f = 1;
break;
}
if (!checkMove2(x1 + 16, y1, &_G(actor[6])))
f = 1;
actor->_y = oy + 2;
break;
case 2:
x1 = _G(actor[3])._x - 2;
y1 = _G(actor[3])._y;
if (!checkMove2(x1, y1, &_G(actor[3]))) {
f = 1;
break;
}
if (!checkMove2(x1, y1 + 16, &_G(actor[5])))
f = 1;
actor->_x = ox - 2;
break;
case 3:
x1 = _G(actor[4])._x + 2;
y1 = _G(actor[4])._y;
if (!checkMove2(x1, y1, &_G(actor[4]))) {
f = 1;
break;
}
if (!checkMove2(x1, y1 + 16, &_G(actor[6])))
f = 1;
actor->_x = ox + 2;
break;
case 4: //ul
x1 = _G(actor[3])._x - 2;
y1 = _G(actor[3])._y - 2;
if (!checkMove2(x1, y1, &_G(actor[3]))) {
f = 1;
break;
}
actor->_x = ox - 2;
actor->_y = oy - 2;
break;
case 5:
x1 = _G(actor[4])._x + 2;
y1 = _G(actor[4])._y - 2;
if (!checkMove2(x1, y1, &_G(actor[4]))) {
f = 1;
break;
}
actor->_x = ox + 2;
actor->_y = oy - 2;
break;
case 6:
x1 = _G(actor[6])._x + 2;
y1 = _G(actor[6])._y + 2;
if (!checkMove2(x1, y1, &_G(actor[6]))) {
f = 1;
break;
}
actor->_x = ox + 2;
actor->_y = oy + 2;
break;
case 7:
x1 = _G(actor[5])._x - 2;
y1 = _G(actor[5])._y + 2;
if (!checkMove2(x1, y1, &_G(actor[5]))) {
f = 1;
break;
}
actor->_x = ox - 2;
actor->_y = oy + 2;
break;
default:
break;
}
fcount = actor->_frameCount - 1;
if (fcount) {
actor->_nextFrame++;
if (actor->_nextFrame > 2)
actor->_nextFrame = 0;
actor->_frameCount = 30;
} else
actor->_frameCount = fcount;
skip_move:
setBoss(actor);
if (!f)
goto done;
new_dir:
if (actor->_temp3 < 120)
goto new_dir1;
_G(actor[3])._frameSpeed = 8;
_G(actor[3])._nextFrame = 3;
_G(actor[4])._nextFrame = 3;
actor->_temp4 = 120;
actorAlwaysShoots(actor, 0);
_G(actor[actor->_shotActor])._x = actor->_x + 8;
_G(actor[actor->_shotActor])._y = actor->_y - 8;
_G(actor[actor->_shotActor])._temp1 = g_events->getRandomNumber(90, 189);
_G(actor[actor->_shotActor])._temp5 = 30;
_G(actor[actor->_shotActor])._speed = 2;
playSound(BOSS12, true);
new_dir1:
actor->_temp5 = _G(rand1) % 8;
actor->_edgeCounter = _G(rand2) + 60;
done:
if (actor->_directions == 1)
return 0;
return d;
}
static void boss3CheckHit() {
if (_G(actor[3])._solid & 128) {
for (int rep = 3; rep < 7; rep++)
_G(actor[rep])._magicHit = 0;
return;
}
if (_G(actor[3])._magicHit || _G(actor[4])._magicHit || _G(actor[5])._magicHit || _G(actor[6])._magicHit) {
if (!_G(actor[3])._temp2) {
actorDamaged(&_G(actor[3]), 10);
if (_G(cheat) && _G(keyFlag[GOT_Z]))
_G(actor[3])._health -= 50;
else
_G(actor[3])._health -= 10;
_G(actor[3])._moveCountdown = 50;
_G(actor[3])._vulnerableCountdown = 50;
playSound(BOSS13, true);
for (int rep = 4; rep < 7; rep++) {
_G(actor[rep])._magicHit = 0;
_G(actor[rep])._nextFrame = 1;
_G(actor[rep])._moveCountdown = 50;
}
if (_G(actor[3])._health == 0) {
_G(bossDead) = true;
for (int rep = 7; rep < MAX_ACTORS; rep++) {
if (_G(actor[rep])._active)
actorDestroyed(&_G(actor[rep]));
}
}
if (_G(actor[3])._health == 50) {
bossChangeMode();
_G(actor[3])._temp1 = 0;
_G(actor[3])._temp2 = 0;
_G(actor[3])._temp3 = 0;
_G(actor[3])._temp4 = 0;
_G(actor[3])._temp5 = 0;
_G(actor[3])._i6 = 0;
_G(actor[3])._moveCountdown = 2;
} else {
_G(actor[3])._temp2 = 40;
}
}
for (int rep = 3; rep < 7; rep++)
_G(actor[rep])._magicHit = 0;
}
}
static void bossChangeMode() {
if (!_G(bossIntro2)) {
Gfx::Pics loki("FACE18", 262);
executeScript(1003, loki);
_G(bossIntro2) = true;
}
bossMode = 0;
}
void boss3SetupLevel() {
setupBoss(3);
_G(bossActive) = true;
musicPause();
playSound(BOSS11, true);
g_events->send("Game", GameMessage("PAUSE", 40));
if (!_G(bossIntro1)) {
Gfx::Pics loki("FACE18", 262);
executeScript(1002, loki);
_G(bossIntro1) = true;
}
musicPlay(7, true);
_G(appleDropCounter) = 0;
bossMode = 1;
}
static int bossDie() {
if (_G(bossDead)) {
for (int rep = 0; rep < 4; rep++) {
const int x1 = _G(actor[3 + rep])._lastX[_G(pge)];
const int y1 = _G(actor[3 + rep])._lastY[_G(pge)];
const int x = _G(actor[3 + rep])._x;
const int y = _G(actor[3 + rep])._y;
const int n = _G(actor[3 + rep])._actorNum;
const int r = _G(actor[3 + rep])._dropRating;
_G(actor[3 + rep]) = _G(explosion);
_G(actor[3 + rep])._actorNum = n;
_G(actor[3 + rep])._dropRating = r;
_G(actor[3 + rep])._x = x;
_G(actor[3 + rep])._y = y;
_G(actor[3 + rep])._lastX[_G(pge)] = x1;
_G(actor[3 + rep])._lastX[_G(pge) ^ 1] = x;
_G(actor[3 + rep])._lastY[_G(pge)] = y1;
_G(actor[3 + rep])._lastY[_G(pge) ^ 1] = y;
_G(actor[3 + rep])._active = true;
_G(actor[3 + rep])._vulnerableCountdown = 255;
_G(actor[3 + rep])._moveType = 6;
_G(actor[3 + rep])._nextFrame = rep;
_G(actor[3 + rep])._speed = g_events->getRandomNumber(6, 8);
_G(actor[3 + rep])._currNumShots = (10 - _G(actor[3 + rep])._speed) * 10;
_G(actor[3 + rep])._moveCountdown = _G(actor[3 + rep])._speed;
}
playSound(EXPLODE, true);
_G(bossDead) = true;
}
return _G(actor[3])._lastDir;
}
void boss3ClosingSequence1() {
musicPlay(6, true);
odinSpeaks(1001, 0, "CLOSING");
}
void boss3ClosingSequence2() {
fillScore(20, "CLOSING");
}
void boss3ClosingSequence3() {
fillHealth();
fillMagic();
for (int rep = 0; rep < 16; rep++)
_G(scrn)._actorType[rep] = 0;
_G(bossDead) = false;
_G(setup)._bossDead[2] = true;
_G(gameOver) = true;
_G(bossActive) = false;
_G(scrn)._music = 6;
showLevel(BOSS_LEVEL3);
#ifdef USE_TTS
_G(thorInfo)._previousScore = -1;
#endif
_G(exitFlag) = 0;
musicPause();
_G(newLevel) = ENDING_SCREEN;
_G(thor)->_x = 152;
_G(thor)->_y = 160;
_G(thor)->_dir = 1;
}
void endingScreen() {
for (int i = 3; i < MAX_ACTORS; i++)
_G(actor[i])._moveType = 1;
musicPlay(6, true);
memset(explosionFlag, 0, sizeof(explosionFlag));
_G(endGame) = 1;
_G(explosionRow) = 0;
explosionCounter = 0;
_G(actor[34]) = _G(explosion);
_G(actor[34])._active = false;
_G(actor[34])._speed = 2;
_G(actor[34])._moveCountdown = _G(actor[34])._speed;
_G(actor[34])._currNumShots = 3; // Used to reverse explosion
_G(actor[34])._vulnerableCountdown = 255;
_G(actor[34])._i2 = 6;
}
// Explode
int endgame_one() {
if (_G(actor[34])._i2) {
_G(actor[34])._i2--;
return 0;
}
_G(actor[34])._i2 = 6;
playSound(EXPLODE, true);
int r = _G(rand1) % 32;
while (explosionFlag[r / 8][r % 8]) {
r++;
if (r > 31)
r = 0;
}
explosionFlag[r / 8][r % 8] = true;
int x = (EXPLOSION[r / 8][r % 8] % 20) * 16;
int y = (EXPLOSION[r / 8][r % 8] / 20) * 16;
_G(actor[34])._x = x;
_G(actor[34])._y = y;
_G(actor[34])._active = true;
_G(actor[34])._nextFrame = 0;
_G(actor[34])._currNumShots = 3;
_G(scrn)._iconGrid[y / 16][x / 16] = _G(scrn)._backgroundColor;
_G(endGame++);
if (_G(endGame) > 32) {
_G(actor[34])._active = false;
_G(endGame) = 0;
}
return 1;
}
// Explode
int endGameMovement() {
if (!_G(endGame))
return 0;
if (explosionCounter > 3) {
endgame_one();
return 0;
}
if (_G(actor[34])._i2) {
_G(actor[34])._i2--;
return 0;
}
_G(actor[34])._i2 = 6;
playSound(EXPLODE, true);
int r = _G(rand1) % 8;
while (explosionFlag[_G(explosionRow)][r]) {
r++;
if (r > 7)
r = 0;
}
explosionFlag[_G(explosionRow)][r] = true;
const int x = (EXPLOSION[_G(explosionRow)][r] % 20) * 16;
const int y = (EXPLOSION[_G(explosionRow)][r] / 20) * 16;
_G(actor[34])._x = x;
_G(actor[34])._y = y;
_G(actor[34])._active = true;
_G(actor[34])._nextFrame = 0;
_G(actor[34])._currNumShots = 3;
_G(scrn)._iconGrid[y / 16][x / 16] = _G(scrn)._backgroundColor;
_G(scrn)._iconGrid[(y / 16) - 4][x / 16] = _G(scrn)._backgroundColor;
_G(endGame++);
if (_G(endGame) > 8) {
_G(endGame) = 1;
_G(explosionRow++);
explosionCounter++;
if (explosionCounter > 3) {
memset(explosionFlag, 0, sizeof(explosionFlag));
}
}
return 1;
}
} // namespace Got

40
engines/got/game/boss3.h Normal file
View 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/>.
*
*/
#ifndef GOT_GAME_BOSS3_H
#define GOT_GAME_BOSS3_H
#include "got/data/defines.h"
namespace Got {
// Boss 3 - Loki
extern int boss3Movement(Actor *actor);
extern void boss3SetupLevel();
extern void endingScreen();
extern void boss3ClosingSequence1();
extern void boss3ClosingSequence2();
extern void boss3ClosingSequence3();
extern int endGameMovement();
} // namespace Got
#endif

118
engines/got/game/init.cpp Normal file
View 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/>.
*
*/
#include "got/game/init.h"
#include "common/memstream.h"
#include "common/textconsole.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/gfx/image.h"
#include "got/sound.h"
#include "got/utils/file.h"
#include "got/vars.h"
namespace Got {
void setupPlayer() {
_G(thorInfo).clear();
_G(thorInfo)._inventory = 0;
if (_G(area) > 1)
_G(thorInfo)._inventory |= APPLE_MAGIC + LIGHTNING_MAGIC;
if (_G(area) > 2)
_G(thorInfo)._inventory |= BOOTS_MAGIC + WIND_MAGIC;
_G(thor)->_health = 150;
_G(thorInfo)._magic = _G(area) > 1 ? 150 : 0;
_G(thorInfo)._jewels = 0;
_G(thorInfo)._score = 0;
_G(thorInfo)._keys = 0;
_G(thorInfo)._lastItem = 0;
_G(thorInfo)._object = 0;
_G(thorInfo)._objectName = nullptr;
_G(thor)->_lastX[0] = _G(thor)->_x;
_G(thor)->_lastX[1] = _G(thor)->_x;
_G(thor)->_lastY[0] = _G(thor)->_y;
_G(thor)->_lastY[1] = _G(thor)->_y;
_G(thorInfo)._lastIcon = (6 * 20) + 8;
_G(thorInfo)._lastScreen = 23;
_G(thor)->_dir = 1;
switch (_G(area)) {
case 1:
_G(thor)->_x = 152;
_G(thor)->_y = 96;
break;
case 2:
_G(thor)->_x = 32;
_G(thor)->_y = 32;
break;
case 3:
_G(thor)->_x = 272;
_G(thor)->_y = 80;
break;
default:
break;
}
}
void initGame() {
if (_G(area) == 2)
_G(thorInfo)._armor = 1;
if (_G(area) == 3)
_G(thorInfo)._armor = 10;
loadStandardActors();
setupPlayer();
if (_G(demo)) {
g_vars->setArea(1);
_G(thor)->_health = 100;
_G(thorInfo)._magic = 100;
_G(thorInfo)._jewels = 463;
_G(thorInfo)._score = 12455;
_G(setup)._difficultyLevel = 0;
_G(thorInfo)._inventory = 1 + 2;
_G(currentLevel) = 54;
_G(thorInfo)._selectedItem = 2;
File f("DEMO");
_G(demoKeys).clear();
for (int i = 0; i < DEMO_LEN; ++i)
_G(demoKeys).push(f.readByte());
// Drop the first six bytes off. This comprises of
// the "part I" display in the original, and ScummVM
// doesn't do demo key processing until the game view
for (int i = 0; i < 6; ++i)
_G(demoKeys).pop();
}
_G(thor)->_moveCountdown = 6;
// Load level data
_G(newLevel) = _G(currentLevel);
_G(scrn).load(_G(currentLevel));
showLevel(_G(currentLevel));
g_vars->resetEndGameFlags();
_G(startup) = false;
}
} // namespace Got

34
engines/got/game/init.h Normal file
View File

@@ -0,0 +1,34 @@
/* 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 GOT_GAME_INIT_H
#define GOT_GAME_INIT_H
namespace Got {
/**
* Handles in-game initialization the first time
*/
extern void initGame();
} // namespace Got
#endif

80
engines/got/game/main.cpp Normal file
View File

@@ -0,0 +1,80 @@
/* 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 "common/memstream.h"
#include "got/game/back.h"
#include "got/vars.h"
#include "got/gfx/image.h" // loadNewThor
namespace Got {
void setupLoad() {
_G(thor)->_active = true;
_G(newLevel) = _G(thorInfo)._lastScreen;
_G(thor)->_x = (_G(thorInfo)._lastIcon % 20) * 16;
_G(thor)->_y = ((_G(thorInfo)._lastIcon / 20) * 16) - 1;
if (_G(thor)->_x < 1)
_G(thor)->_x = 1;
if (_G(thor)->_y < 0)
_G(thor)->_y = 0;
_G(thor)->_lastX[0] = _G(thor)->_x;
_G(thor)->_lastX[1] = _G(thor)->_x;
_G(thor)->_lastY[0] = _G(thor)->_y;
_G(thor)->_lastY[1] = _G(thor)->_y;
_G(thor)->_dir = _G(thorInfo)._lastDir;
_G(thor)->_lastDir = _G(thorInfo)._lastDir;
_G(thor)->_health = _G(thorInfo)._lastHealth;
_G(thorInfo)._magic = _G(thorInfo)._lastMagic;
_G(thorInfo)._jewels = _G(thorInfo)._lastJewels;
_G(thorInfo)._keys = _G(thorInfo)._lastKeys;
_G(thorInfo)._score = _G(thorInfo)._lastScore;
_G(thorInfo)._selectedItem = _G(thorInfo)._lastItem;
_G(thorInfo)._inventory = _G(thorInfo)._lastInventory;
_G(thorInfo)._object = _G(thorInfo)._lastObject;
_G(thorInfo)._objectName = _G(thorInfo)._lastObjectName;
_G(thor)->_numMoves = 1;
_G(thor)->_vulnerableCountdown = 60;
_G(thor)->_show = 60;
_G(appleFlag) = false;
_G(thunderSnakeCounter) = 0;
_G(tornadoUsed) = false;
_G(shieldOn) = false;
_G(actor[1])._active = false;
_G(actor[2])._active = false;
_G(thor)->_moveCountdown = 6;
_G(scrn).load(_G(newLevel));
_G(currentLevel) = _G(newLevel);
showLevel(_G(newLevel));
if (_G(area) == 2 && _G(currentLevel) == 105) { // Shovel Maze
_G(thorInfo)._armor = 2; // eyeballs mode
loadNewThor();
_G(eyeballs) = 1;
}
}
void pause(int delay) {
g_system->delayMillis(delay);
}
} // namespace Got

32
engines/got/game/main.h Normal file
View File

@@ -0,0 +1,32 @@
/* 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 GOT_GAME_MAIN_H
#define GOT_GAME_MAIN_H
namespace Got {
extern void setupLoad();
extern void pause(int delay);
} // namespace Got
#endif

380
engines/got/game/move.cpp Normal file
View File

@@ -0,0 +1,380 @@
/* 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 "got/game/move.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/game/move_patterns.h"
#include "got/game/shot_movement.h"
#include "got/game/shot_pattern.h"
#include "got/game/status.h"
#include "got/vars.h"
namespace Got {
void nextFrame(Actor *actor) {
const int fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 3)
actor->_nextFrame = 0;
actor->_frameCount = actor->_frameSpeed;
} else
actor->_frameCount = fcount;
}
bool pointWithin(int x, int y, int x1, int y1, int x2, int y2) {
return ((x >= x1) && (x <= x2) && (y >= y1) && (y <= y2));
}
bool overlap(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
if ((x1 >= x3) && (x1 <= x4) && (y1 >= y3) && (y1 <= y4))
return true;
if ((x2 >= x3) && (x2 <= x4) && (y2 >= y3) && (y2 <= y4))
return true;
if ((x1 >= x3) && (x1 <= x4) && (y2 >= y3) && (y2 <= y4))
return true;
if ((x2 >= x3) && (x2 <= x4) && (y1 >= y3) && (y1 <= y4))
return true;
if ((x3 >= x1) && (x3 <= x2) && (y3 >= y1) && (y3 <= y2))
return true;
if ((x4 >= x1) && (x4 <= x2) && (y4 >= y1) && (y4 <= y2))
return true;
if ((x3 >= x1) && (x3 <= x2) && (y4 >= y1) && (y4 <= y2))
return true;
if ((x4 >= x1) && (x4 <= x2) && (y3 >= y1) && (y3 <= y2))
return true;
return false;
}
int reverseDirection(Actor *actor) {
if (actor->_dir == 1)
return 0;
if (actor->_dir == 2)
return 3;
if (actor->_dir == 3)
return 2;
return 1;
}
void thorShoots() {
if (!_G(hammer)->_active && (!_G(hammer)->_dead) && (!_G(thor)->_shotCountdown)) {
playSound(SWISH, false);
_G(thor)->_shotCountdown = 20;
_G(hammer)->_active = true;
_G(hammer)->_dir = _G(thor)->_dir;
_G(hammer)->_lastDir = _G(thor)->_dir;
_G(hammer)->_x = _G(thor)->_x;
_G(hammer)->_y = _G(thor)->_y + 2;
_G(hammer)->_moveType = 2;
_G(hammer)->_nextFrame = 0;
_G(hammer)->_lastX[0] = _G(hammer)->_x;
_G(hammer)->_lastX[1] = _G(hammer)->_x;
_G(hammer)->_lastY[0] = _G(hammer)->_y;
_G(hammer)->_lastY[1] = _G(hammer)->_y;
}
}
int killGoodGuy() {
if (!_G(killGoodGuyInform) && !_G(thunderSnakeCounter)) {
odinSpeaks(2010, 0);
_G(killGoodGuyInform) = true;
}
addScore(-1000);
return 0;
}
void actorDamaged(Actor *actor, int damage) {
if (!_G(setup)._difficultyLevel)
damage *= 2;
else if (_G(setup)._difficultyLevel == 2)
damage /= 2;
if (!actor->_vulnerableCountdown && actor->_type != 3 && (actor->_solid & 0x7f) != 2) {
actor->_vulnerableCountdown = STAMINA;
if (damage >= actor->_health) {
if (actor->_type != 4) {
addScore(actor->_initHealth * 10);
} else {
killGoodGuy();
}
actorDestroyed(actor);
} else {
actor->_show = 10;
actor->_health -= damage;
actor->_moveCountdown += 8;
}
} else if (!actor->_vulnerableCountdown) {
actor->_vulnerableCountdown = STAMINA;
if (actor->_funcNum == 4) {
switchIcons();
}
if (actor->_funcNum == 7) {
rotateArrows();
}
}
}
void thorDamaged(Actor *actor) {
actor->_hitThor = true;
// If we're invincible, ignore any damage
if (_G(cheats)._freezeHealth)
return;
if (GAME3 && actor->_funcNum == 11) {
if (actor->_talkCounter) {
actor->_talkCounter--;
return;
}
const int currType = actor->_type;
actor->_type = 4;
actorSpeaks(actor, 0, 0);
actor->_type = currType;
actor->_talkCounter = 30;
return;
}
int damage = actor->_hitStrength;
if (damage != 255) {
if (!_G(setup)._difficultyLevel)
damage /= 2;
else if (_G(setup)._difficultyLevel == 2)
damage *= 2;
}
if ((!_G(thor)->_vulnerableCountdown && !_G(shieldOn)) || damage == 255) {
if (damage >= _G(thor)->_health) {
_G(thor)->_vulnerableCountdown = 40;
_G(thor)->_show = 0;
_G(thor)->_health = 0;
_G(exitFlag) = 2;
g_events->send(GameMessage("THOR_DIES"));
} else if (damage) {
_G(thor)->_vulnerableCountdown = 40;
_G(sound).playSound(OW, false);
_G(thor)->_show = 10;
_G(thor)->_health -= damage;
}
}
}
void actorDestroyed(Actor *actor) {
if (actor->_actorNum > 2) {
const int curPage = _G(pge);
const int x = actor->_lastX[curPage ^ 1];
const int y = actor->_lastY[curPage ^ 1];
const int x1 = actor->_lastX[curPage];
const int y1 = actor->_lastY[curPage];
const int r = actor->_dropRating;
const int n = actor->_actorNum;
const int t = actor->_type;
if (actor->_funcNum == 255)
actor->copyFixedAndPics(_G(explosion));
else
actor->copyFixedAndPics(_G(sparkle));
actor->_type = t;
actor->_actorNum = n;
actor->_dropRating = r;
actor->_x = x;
actor->_y = y;
actor->_lastX[curPage] = x1;
actor->_lastX[curPage ^ 1] = x;
actor->_lastY[curPage] = y1;
actor->_lastY[curPage ^ 1] = y;
actor->_moveCountdown = actor->_speed;
actor->_active = true;
actor->_currNumShots = 3; // used to reverse explosion
actor->_vulnerableCountdown = 255;
} else {
actor->_dead = 2;
actor->_active = false;
}
}
int _actor_shoots(Actor *actor, int dir) {
const int t = actor->_shotType - 1;
for (int i = MAX_ENEMIES + 3; i < MAX_ACTORS; i++) {
if ((!_G(actor[i])._active) && (!_G(actor[i])._dead)) {
Actor *act = &_G(actor[i]);
*act = _G(shot[t]);
int cx, cy;
if (actor->_sizeY < act->_sizeY)
cy = actor->_y - ((act->_sizeY - actor->_sizeY) / 2);
else
cy = actor->_y + ((actor->_sizeY - act->_sizeY) / 2);
if (actor->_sizeX < act->_sizeX)
cx = actor->_x - ((act->_sizeX - actor->_sizeX) / 2);
else
cx = actor->_x + ((actor->_sizeX - act->_sizeX) / 2);
if (cy > 174)
cy = 174;
if (cx > 304)
cx = 304;
act->_x = cx;
act->_y = cy;
act->_lastDir = dir;
act->_nextFrame = 0;
act->_dir = dir;
if (act->_directions == 1)
act->_dir = 0;
else if (act->_directions == 4 && act->_framesPerDirection == 1) {
act->_nextFrame = dir;
act->_dir = 0;
}
act->_frameCount = act->_frameSpeed;
act->_moveCountdown = act->_speed;
act->_lastX[0] = cx;
act->_lastX[1] = cx;
act->_lastX[0] = actor->_x;
act->_lastX[1] = actor->_x;
act->_lastY[0] = cy;
act->_lastY[1] = cy;
act->_active = true;
act->_creator = actor->_actorNum;
act->_moveCount = act->_numMoves;
act->_dead = 0;
actor->_shotActor = i;
actor->_currNumShots++;
actor->_shotCountdown = 20;
_G(shotOk) = false;
return 1;
}
}
return 0;
}
void actorAlwaysShoots(Actor *actor, int dir) {
_actor_shoots(actor, dir);
}
int actorShoots(Actor *actor, int dir) {
const int cx = (actor->_x + (actor->_sizeX / 2)) >> 4;
const int cy = ((actor->_y + actor->_sizeY) - 2) >> 4;
const int tx = _G(thor)->_centerX;
const int ty = _G(thor)->_centerY;
int icn = 140;
if (_G(shot[actor->_shotType - 1])._flying)
icn = 80;
switch (dir) {
case 0:
for (int i = ty + 1; i <= cy; i++) {
if (_G(scrn)._iconGrid[i][cx] < icn)
return 0;
}
break;
case 1:
for (int i = cy; i <= ty; i++) {
if (_G(scrn)._iconGrid[i][cx] < icn)
return 0;
}
break;
case 2:
for (int i = tx; i < cx; i++) {
if (_G(scrn)._iconGrid[cy][i] < icn)
return 0;
}
break;
case 3:
for (int i = cx; i < tx; i++) {
if (_G(scrn)._iconGrid[cy][i] < icn)
return 0;
}
break;
default:
break;
}
return _actor_shoots(actor, dir);
}
void moveActor(Actor *actor) {
if (actor->_vulnerableCountdown != 0)
actor->_vulnerableCountdown--;
if (actor->_shotCountdown != 0)
actor->_shotCountdown--;
if (actor->_show != 0)
actor->_show--;
if (!actor->_shotCountdown && _G(shotOk) && actor->_numShotsAllowed && actor->_currNumShots < actor->_numShotsAllowed) {
shotPatternFunc[actor->_shotPattern](actor);
}
const int scount = actor->_moveCountdown - 1;
if (scount <= 0) {
if (!actor->_moveCounter)
actor->_moveCountdown = actor->_speed;
else
actor->_moveCountdown = (actor->_speed << 1);
int i;
if (actor->_type == 3)
i = shotMovementFunc[actor->_moveType](actor);
else
i = _movementFunc[actor->_moveType](actor);
if (actor->_directions == 2)
i &= 1;
if (i != actor->_dir)
actor->_dir = i;
if (actor->_moveType == 0 && _G(currentLevel) != _G(newLevel) && _G(shieldOn)) {
_G(actor[2])._x = actor->_x - 2;
if (_G(actor[2])._x < 0)
_G(actor[2])._x = 0;
_G(actor[2])._y = actor->_y;
_G(actor[2])._lastX[0] = _G(actor[2])._x;
_G(actor[2])._lastX[1] = _G(actor[2])._x;
_G(actor[2])._lastY[0] = _G(actor[2])._y;
_G(actor[2])._lastY[1] = _G(actor[2])._y;
}
} else
actor->_moveCountdown = scount;
actor->_x &= 0xfffe;
}
} // namespace Got

43
engines/got/game/move.h Normal file
View File

@@ -0,0 +1,43 @@
/* 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 GOT_GAME_MOVE_H
#define GOT_GAME_MOVE_H
#include "got/data/defines.h"
namespace Got {
extern void nextFrame(Actor *actor);
extern bool pointWithin(int x, int y, int x1, int y1, int x2, int y2);
extern bool overlap(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
extern int reverseDirection(Actor *actor);
extern void thorShoots();
extern void thorDamaged(Actor *actor);
extern void actorDestroyed(Actor *actor);
extern int actorShoots(Actor *actor, int dir);
extern void actorAlwaysShoots(Actor *actor, int dir);
extern void actorDamaged(Actor *actor, int damage);
extern void moveActor(Actor *actor);
} // namespace Got
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
/* 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 GOT_GAME_MOVE_PATTERNS_H
#define GOT_GAME_MOVE_PATTERNS_H
#include "got/data/defines.h"
namespace Got {
extern int (*const _movementFunc[]) (Actor *actor);
int checkMove2(int x, int y, Actor *actor);
int checkMove3(int x, int y, Actor *actor);
int checkMove4(int x, int y, Actor *actor);
void setThorVars();
} // namespace Got
#endif

437
engines/got/game/object.cpp Normal file
View File

@@ -0,0 +1,437 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property _G(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 _G(of) the GNU General Public License as published by
* the Free Software Foundation, either version 3 _G(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 _G(of)
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy _G(of) the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "got/game/object.h"
#include "got/data/flags.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/game/move.h"
#include "got/game/status.h"
#include "got/gfx/image.h"
#include "got/vars.h"
namespace Got {
void notEnoughMagic();
void cannotCarryMore();
void showObjects() {
Common::fill(_G(objectMap), _G(objectMap) + TILES_COUNT, 0);
Common::fill(_G(objectIndex), _G(objectIndex) + TILES_COUNT, 0);
for (int i = 0; i < OBJECTS_COUNT; i++) {
if (_G(scrn)._staticObject[i]) {
const int p = _G(scrn)._staticX[i] + (_G(scrn)._staticY[i] * TILES_X);
_G(objectIndex[p]) = i;
_G(objectMap[p]) = _G(scrn)._staticObject[i];
}
}
}
void pickUpObject(int p) {
switch (_G(objectMap[p])) {
case 1: // Red jewel
if (_G(thorInfo)._jewels >= 999) {
cannotCarryMore();
return;
}
addJewels(10);
break;
case 2: // Blue jewel
if (_G(thorInfo)._jewels >= 999) {
cannotCarryMore();
return;
}
addJewels(1);
break;
case 3: // Red potion
if (_G(thorInfo)._magic >= 150) {
cannotCarryMore();
return;
}
addMagic(10);
break;
case 4: // Blue potion
if (_G(thorInfo)._magic >= 150) {
cannotCarryMore();
return;
}
addMagic(3);
break;
case 5: // Good apple
if (_G(thor)->_health >= 150) {
cannotCarryMore();
return;
}
playSound(GULP, false);
addHealth(5);
break;
case 6: // Bad apple
playSound(OW, false);
addHealth(-10);
break;
case 7: // Key (reset on exit)
addKeys(1);
break;
case 8: // Treasure
if (_G(thorInfo)._jewels >= 999) {
cannotCarryMore();
return;
}
addJewels(50);
break;
case 9: // Trophy
addScore(100);
break;
case 10: // Crown
addScore(1000);
break;
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
if (_G(objectMap[p]) == 13 && HERMIT_HAS_DOLL)
return;
_G(thor)->_numMoves = 1;
_G(hammer)->_numMoves = 2;
_G(actor[2])._active = false;
_G(shieldOn) = false;
_G(tornadoUsed) = false;
_G(thorInfo)._inventory |= 64;
_G(thorInfo)._selectedItem = 7;
_G(thorInfo)._object = _G(objectMap[p]) - 11;
_G(thorInfo)._objectName = OBJECT_NAMES[_G(thorInfo)._object - 1];
odinSpeaks((_G(objectMap[p]) - 12) + 501, _G(objectMap[p]) - 1);
break;
case 27:
case 28:
case 29:
case 30:
case 31:
case 32: {
_G(thunderSnakeCounter) = 0;
_G(shieldOn) = false;
_G(tornadoUsed) = false;
_G(hammer)->_numMoves = 2;
_G(thor)->_numMoves = 1;
_G(actor[2])._active = false;
const int s = 1 << (_G(objectMap[p]) - 27);
_G(thorInfo)._inventory |= s;
odinSpeaks((_G(objectMap[p]) - 27) + 516, _G(objectMap[p]) - 1);
_G(thorInfo)._selectedItem = _G(objectMap[p]) - 26;
addMagic(150);
fillScore(5);
}
break;
default:
break;
}
playSound(YAH, false);
_G(objectMap[p]) = 0;
// Reset so it doesn't reappear on reentry to screen
if (_G(objectIndex[p]) < 30)
_G(scrn)._staticObject[_G(objectIndex[p])] = 0;
_G(objectIndex[p]) = 0;
}
void dropRandomObject(Actor *actor) {
int objId;
const int rnd1 = g_events->getRandomNumber(99);
const int rnd2 = g_events->getRandomNumber(99);
if (rnd1 < 25)
objId = 5; // Apple
else if (rnd1 & 1) {
// Jewels
if (rnd2 < 10)
objId = 1; // Red
else
objId = 2; // Blue
} else {
// Potion
if (rnd2 < 10)
objId = 3; // Red
else
objId = 4; // Blue
}
dropObject(actor, objId);
}
bool dropObject(Actor *actor, const int objId) {
const int p = (actor->_x + (actor->_sizeX / 2)) / 16 + (((actor->_y + (actor->_sizeY / 2)) / 16) * 20);
if (!_G(objectMap[p]) && _G(scrn)._iconGrid[p / 20][p % 20] >= 140) { //nothing there and solid
_G(objectMap[p]) = objId;
_G(objectIndex[p]) = 27 + actor->_actorNum; //actor is 3-15
return true;
}
return false;
}
bool useApple(int flag) {
if (_G(thor)->_health == 150)
return false;
if (flag && _G(thorInfo)._magic > 0) {
if (!_G(appleFlag)) {
_G(magicCounter) = 0;
addMagic(-2);
addHealth(1);
playSound(ANGEL, false);
} else if (_G(magicCounter) > 8) {
_G(magicCounter) = 0;
addMagic(-2);
addHealth(1);
if (!soundPlaying())
playSound(ANGEL, false);
}
_G(appleFlag) = true;
return true;
}
_G(appleFlag) = false;
if (flag)
notEnoughMagic();
return false;
}
bool useThunder(int flag) {
if (flag && _G(thorInfo)._magic > 29) {
if (!_G(thunderSnakeCounter)) {
addMagic(-30);
playSound(THUNDER, false);
_G(thunderSnakeCounter) = 60;
}
return true;
}
if (flag && !_G(thunderSnakeCounter))
notEnoughMagic();
if (_G(thunderSnakeCounter))
return true;
return false;
}
bool useBoots(int flag) {
if (flag) {
if (_G(thorInfo)._magic > 0) {
if (_G(thor)->_numMoves == 1 || _G(magicCounter) > 8) {
_G(magicCounter) = 0;
addMagic(-1);
}
_G(thor)->_numMoves = 2;
_G(hammer)->_numMoves = 3;
return true;
}
notEnoughMagic();
_G(thor)->_numMoves = 1;
_G(hammer)->_numMoves = 2;
} else {
_G(thor)->_numMoves = 1;
_G(hammer)->_numMoves = 2;
}
return false;
}
bool useShield(int flag) {
if (flag) {
if (_G(thorInfo)._magic) {
if (!_G(shieldOn)) {
_G(magicCounter) = 0;
addMagic(-1);
setupMagicItem(1);
_G(actor[2]) = _G(magicItem[1]);
setupActor(&_G(actor[2]), 2, 0, _G(thor)->_x, _G(thor)->_y);
_G(actor[2])._moveCountdown = 1;
_G(actor[2])._speed = 1;
_G(shieldOn) = true;
} else if (_G(magicCounter) > 8) {
_G(magicCounter) = 0;
addMagic(-1);
}
return true;
}
notEnoughMagic();
}
if (_G(shieldOn)) {
_G(actor[2])._dead = 2;
_G(actor[2])._active = false;
_G(shieldOn) = false;
}
return false;
}
bool useLightning(int flag) {
if (flag) {
if (_G(thorInfo)._magic > 14) {
addMagic(-15);
g_events->send("Game", GameMessage("THROW_LIGHTNING"));
} else {
notEnoughMagic();
return false;
}
}
return true;
}
bool useTornado(int flag) {
if (flag) {
if (_G(thorInfo)._magic > 10) {
if (!_G(tornadoUsed) && !_G(actor[2])._dead && _G(magicCounter) > 20) {
_G(magicCounter) = 0;
addMagic(-10);
setupMagicItem(0);
_G(actor[2]) = _G(magicItem[0]);
setupActor(&_G(actor[2]), 2, 0, _G(thor)->_x, _G(thor)->_y);
_G(actor[2])._lastDir = _G(thor)->_dir;
_G(actor[2])._moveType = 16;
_G(tornadoUsed) = true;
playSound(WIND, false);
}
} else if (!_G(tornadoUsed)) {
notEnoughMagic();
return false;
}
if (_G(magicCounter) > 8) {
if (_G(tornadoUsed)) {
_G(magicCounter) = 0;
addMagic(-1);
}
}
if (_G(thorInfo)._magic < 1) {
actorDestroyed(&_G(actor[2]));
_G(tornadoUsed) = false;
notEnoughMagic();
return false;
}
return true;
}
return false;
}
bool useObject(int flag) {
if (!flag || !(_G(thorInfo)._inventory & 64))
return false;
odinSpeaks((_G(thorInfo)._object - 1) + 5501, _G(thorInfo)._object - 1);
return true;
}
void useItem() {
bool ret = false;
const int kf = _G(keyFlag[key_magic]);
if (!kf && _G(tornadoUsed)) {
actorDestroyed(&_G(actor[2]));
_G(tornadoUsed) = false;
}
const bool mf = _G(magicMissingInform);
switch (_G(thorInfo)._selectedItem) {
case 1:
ret = useApple(kf);
break;
case 2:
ret = useLightning(kf);
break;
case 3:
ret = useBoots(kf);
break;
case 4:
ret = useTornado(kf);
break;
case 5:
ret = useShield(kf);
break;
case 6:
ret = useThunder(kf);
break;
case 7:
ret = useObject(kf);
break;
default:
break;
}
if (kf) {
if (!ret && !_G(useItemFlag)) {
if (mf)
playSound(BRAAPP, false);
_G(useItemFlag) = true;
}
} else {
_G(useItemFlag) = false;
}
}
void notEnoughMagic() {
if (_G(magicMissingInform))
return;
odinSpeaks(2006, 0);
_G(magicMissingInform) = true;
}
void cannotCarryMore() {
if (_G(cantCarryInform))
return;
odinSpeaks(2007, 0);
_G(cantCarryInform) = true;
}
void deleteObject() {
_G(thorInfo)._inventory &= 0xbf;
_G(thorInfo)._selectedItem = 1;
}
} // namespace Got

38
engines/got/game/object.h Normal file
View File

@@ -0,0 +1,38 @@
/* 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 GOT_GAME_OBJECT_H
#define GOT_GAME_OBJECT_H
#include "got/data/defines.h"
namespace Got {
extern void showObjects();
extern void pickUpObject(int p);
extern void dropRandomObject(Actor *actor);
extern bool dropObject(Actor *actor, int objId);
extern void deleteObject();
extern void useItem();
} // namespace Got
#endif

1265
engines/got/game/script.cpp Normal file

File diff suppressed because it is too large Load Diff

127
engines/got/game/script.h Normal file
View File

@@ -0,0 +1,127 @@
/* 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 GOT_GAME_SCRIPT_H
#define GOT_GAME_SCRIPT_H
#include "got/data/defines.h"
#include "got/gfx/gfx_pics.h"
namespace Got {
typedef void (*ScriptEndFn)();
enum ScriptPause {
SCRIPT_READY, SCRIPT_PAUSED, SCRIPT_RESUMING
};
class Scripts {
public:
Scripts();
~Scripts();
void executeScript(long index, const Gfx::Pics &speakerIcon, ScriptEndFn endFn = nullptr);
void pause();
void resume();
void setAskResponse(int option);
void runIfResuming();
private:
ScriptEndFn _endFn = nullptr;
long _numVar[26] = {}; // numeric variables
char _strVar[26][81] = {}; // string vars
char _lineLabel[32][9] = {}; // line label look up table
char *_linePtr[32] = {}; // line label pointers
char *_newPtr = nullptr;
int _numLabels = 0; // number of labels
char *_gosubStack[32] = {}; // stack for GOSUB return addresses
int _gosubPtr = 0; // GOSUB stack pointer
char *_forStack[11] = {}; // FOR stack
long _forVal[11] = {}; // current FOR value
int8 _forVar[11] = {}; // ending FOR value (target var)
int8 _forPtr = 0; // FOR stack pointer
char *_buffPtr = nullptr; // pointer to current command
char *_buffEnd = nullptr; // pointer to end of buffer
char *_buffer = nullptr; // buffer space (alloc'ed)
long _scrIndex = 0;
Gfx::Pics _scrPic;
long _lValue = 0;
long _lTemp = 0;
char _tempS[255] = {};
ScriptPause _paused = SCRIPT_READY;
int _askVar = -1;
private:
int readScriptFile();
void scriptError(int err_num);
int getCommand();
int skipColon();
int calcValue();
int getNextValue();
int calcString(int mode);
void getStr();
int getInternalVariable();
int execCommand(int num);
int getLine(char *src, char *dst);
void scriptEntry() {}
void scriptExit();
int cmd_goto();
int cmd_if();
int cmd_run();
int cmd_addJewels();
int cmd_addHealth();
int cmd_addMagic();
int cmd_addKeys();
int cmd_addScore();
int cmd_say(int mode, int type);
int cmd_ask();
int cmd_sound();
int cmd_setTile();
int cmd_itemGive();
int cmd_itemTake();
int cmd_setFlag();
int cmd_ltoa();
int cmd_pause();
int cmd_visible();
int cmd_random();
int cmd_exec();
void scr_func1();
void scr_func2();
void scr_func3();
void scr_func4();
void scr_func5();
typedef void (Scripts:: *ScrFunction)();
static ScrFunction scr_func[5];
void runScript(bool firstTime = true);
void scriptLoop();
};
extern void executeScript(long index, const Gfx::Pics &speakerIcon,
ScriptEndFn endFn = nullptr);
} // namespace Got
#endif

View File

@@ -0,0 +1,734 @@
/* 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 "got/game/shot_movement.h"
#include "got/events.h"
#include "got/game/move.h"
#include "got/game/move_patterns.h"
#include "got/game/object.h"
#include "got/vars.h"
namespace Got {
int shotMovementNone(Actor *actor);
int shotMovementOne(Actor *actor);
int shotMovementTwo(Actor *actor);
int shotMovementThree(Actor *actor);
int shotMovementFour(Actor *actor);
int shotMovementFive(Actor *actor);
int shotMovementSix(Actor *actor);
int shotMovementSeven(Actor *actor);
int shotMovementEight(Actor *actor);
int shotMovementNine(Actor *actor);
int shotMovementTen(Actor *actor);
int shotMovementEleven(Actor *actor);
int shotMovementTwelve(Actor *actor);
int shotMovementThirteen(Actor *actor);
int (*const shotMovementFunc[])(Actor *actor) = {
shotMovementNone,
shotMovementOne,
shotMovementTwo,
shotMovementThree,
shotMovementFour,
shotMovementFive,
shotMovementSix,
shotMovementSeven,
shotMovementEight,
shotMovementNine,
shotMovementTen,
shotMovementEleven,
shotMovementTwelve,
shotMovementThirteen
};
void next_shot_frame(Actor *actor) {
if (actor->_directions == 4 && actor->_framesPerDirection == 1) {
actor->_nextFrame = actor->_lastDir;
actor->_dir = 0;
} else {
const int fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 3)
actor->_nextFrame = 0;
actor->_frameCount = actor->_frameSpeed;
} else
actor->_frameCount = fcount;
}
}
// Boss - snake
int shotMovementNone(Actor *actor) {
actor->_temp3--;
if (!actor->_temp3) {
actorDestroyed(actor);
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
}
next_shot_frame(actor);
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
int shotMovementOne(Actor *actor) {
int x1 = 0, y1 = 0;
const int d = actor->_lastDir;
switch (d) {
case 0:
x1 = actor->_x;
y1 = actor->_y - 2;
break;
case 1:
x1 = actor->_x;
y1 = actor->_y + 2;
break;
case 2:
x1 = actor->_x - 2;
y1 = actor->_y;
break;
case 3:
x1 = actor->_x + 2;
y1 = actor->_y;
break;
default:
break;
}
if (!checkMove3(x1, y1, actor)) {
actorDestroyed(actor);
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
} else {
next_shot_frame(actor);
actor->_lastDir = d;
}
if (actor->_directions == 1)
return 0;
if (actor->_directions == 4 && actor->_framesPerDirection == 1)
return 0;
return d;
}
int shotMovementTwo(Actor *actor) {
int x1 = 0, y1 = 0;
const int d = actor->_lastDir;
switch (d) {
case 0:
x1 = actor->_x;
y1 = actor->_y - 2;
break;
case 1:
x1 = actor->_x;
y1 = actor->_y + 2;
break;
case 2:
x1 = actor->_x - 2;
y1 = actor->_y;
break;
case 3:
x1 = actor->_x + 2;
y1 = actor->_y;
break;
default:
break;
}
if (!checkMove4(x1, y1, actor)) {
actorDestroyed(actor);
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
} else {
next_shot_frame(actor);
actor->_lastDir = d;
}
if (actor->_directions == 1)
return 0;
if (actor->_directions == 4 && actor->_framesPerDirection == 1)
return 0;
return d;
}
// Serpent fire
int shotMovementThree(Actor *actor) {
const int d = actor->_lastDir;
actor->_x -= 2;
actor->_temp3--;
actor->_temp4--;
if (overlap(_G(thorX1) - 1, _G(thorY1) - 1, _G(thorX2) + 1, _G(thorY2) + 1,
actor->_x, actor->_y, actor->_x + 15, actor->_y + 15)) {
actor->_moveType = 0;
actor->_speed = 6;
thorDamaged(actor);
actor->_x += 2;
}
if (!actor->_temp4) {
actor->_temp4 = actor->_temp5;
actor->_speed++;
if (actor->_speed > 6)
actor->_moveType = 0;
}
if (!actor->_temp3) {
actorDestroyed(actor);
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
} else {
next_shot_frame(actor);
actor->_lastDir = d;
}
if (actor->_directions == 1)
return 0;
return d;
}
// Wraith balls
int shotMovementFour(Actor *actor) {
if (actor->_temp1) {
actor->_temp1--;
if (!actor->_temp1) {
actorDestroyed(actor);
_G(appleDropCounter++);
if (_G(appleDropCounter) == 4) {
if (dropObject(actor, 5))
_G(appleDropCounter) = 0;
else
_G(appleDropCounter) = 3;
} else
dropObject(actor, 3);
return 0;
}
}
if (overlap(_G(thor)->_x - 1, _G(thor)->_y - 1, _G(thorX2) + 1, _G(thorY2) + 1,
actor->_x, actor->_y, actor->_x + 15, actor->_y + 15)) {
thorDamaged(actor);
actorDestroyed(actor);
return 0;
}
int x1 = actor->_x;
int y1 = actor->_y;
int yd = 0;
int xd = 0;
int d = actor->_lastDir;
if ((x1 > (_G(thorX1)) + 1))
xd = -2;
else if ((x1 < (_G(thorX1)) - 1))
xd = 2;
if (actor->_actorNum == 1) {
if (y1 < (_G(thorY1) - 6))
yd = 2;
else if (y1 > (_G(thorY1) - 6))
yd = -2;
} else {
if (y1 < (_G(thorRealY1) - 1))
yd = 2;
else if (y1 > (_G(thorRealY1) + 1))
yd = -2;
}
if (xd && yd) {
if (xd == -2 && ABS(yd) == 2)
d = 2;
else if (xd == 2 && ABS(yd) == 2)
d = 3;
x1 += xd;
y1 += yd;
if (checkMove3(x1, y1, actor)) {
nextFrame(actor);
actor->_lastDir = d;
if (actor->_directions == 1)
return 0;
return d;
}
} else if (xd == 0 && yd == 2)
d = 1;
else if (xd == 0 && yd == -2)
d = 0;
else if (xd == 2 && yd == 0)
d = 3;
else if (xd == -2 && yd == 0)
d = 2;
x1 = actor->_x;
y1 = actor->_y;
actor->_toggle ^= 1;
if (actor->_toggle) {
if (xd) {
x1 += xd;
if (checkMove3(x1, y1, actor)) {
if (xd > 0)
d = 3;
else
d = 2;
nextFrame(actor);
actor->_lastDir = d;
if (actor->_directions == 1)
return 0;
return d;
}
x1 = actor->_x;
}
if (yd) {
y1 += yd;
if (checkMove3(x1, y1, actor)) {
if (yd > 0)
d = 1;
else
d = 0;
nextFrame(actor);
actor->_lastDir = d;
if (actor->_directions == 1)
return 0;
return d;
}
}
} else {
if (yd) {
y1 += yd;
if (checkMove3(x1, y1, actor)) {
if (yd > 0)
d = 1;
else
d = 0;
nextFrame(actor);
actor->_lastDir = d;
if (actor->_directions == 1)
return 0;
return d;
}
y1 = actor->_y;
}
if (xd) {
x1 += xd;
if (checkMove3(x1, y1, actor)) {
if (xd > 0)
d = 3;
else
d = 2;
nextFrame(actor);
actor->_lastDir = d;
if (actor->_directions == 1)
return 0;
return d;
}
}
}
checkMove3(actor->_x, actor->_y, actor);
nextFrame(actor);
actor->_lastDir = d;
if (actor->_directions == 1)
return 0;
return d;
}
// No move, frame cycle
int shotMovementFive(Actor *actor) {
next_shot_frame(actor);
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
// Wraith spots
int shotMovementSix(Actor *actor) {
actor->_temp1--;
if (!actor->_temp1) {
actorDestroyed(actor);
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
} else
next_shot_frame(actor);
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
#define YV actor->_i1
#define YC actor->_i2
#define BC actor->_i3
#define YD actor->_i4
#define XD actor->_i5
#define XC actor->_i6
#define IV 100
#define IC 50
// Skull drop
int shotMovementSeven(Actor *actor) {
if (actor->_temp3) {
actor->_temp3--;
goto done;
}
if (overlap(actor->_x, actor->_y, actor->_x + actor->_sizeX, actor->_y + actor->_sizeY,
_G(thor)->_x, _G(thor)->_y + 4, _G(thor)->_x + 15, _G(thor)->_y + 15))
thorDamaged(actor);
actor->_temp2++;
if (actor->_temp2 > 2) {
if (actor->_temp4)
actor->_temp4--;
actor->_temp2 = 0;
}
actor->_temp3 = actor->_temp4;
actor->_y += 2;
if (actor->_y > 160 - 36) {
actor->_x += (4 - g_events->getRandomNumber(8));
actor->_moveType = 8;
YV = IV;
YC = 0;
BC = IC;
YD = 0;
XC = 3;
if (actor->_x < 150)
XD = 1;
else
XD = 0;
}
done:
next_shot_frame(actor);
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
// Skull bounce
int shotMovementEight(Actor *actor) {
int x = actor->_x;
int y = actor->_y;
XC--;
if (!XC) {
XC = 3;
if (XD)
x += 2;
else
x -= 2;
}
YC += YV;
if (YC > (IV - 1)) {
if (!YD) {
YV -= 8;
YC -= IV;
y -= 2;
} else {
YV += 8;
YC -= IV;
y += 2;
}
}
if (YV < 0) {
YV = 0;
BC = 1;
}
if (YV > IV) {
YV = IV;
BC = 1;
}
BC--;
if (!BC) {
BC = IC;
if (YD)
YV = IV;
YD ^= 1;
}
if (y > 164)
y = 164;
// 8 311
if (x < 1 || x > (319 - actor->_sizeX)) {
if (!actor->_dead)
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
actorDestroyed(actor);
}
if (overlap(actor->_x, actor->_y, actor->_x + actor->_sizeX, actor->_y + actor->_sizeY,
_G(thor)->_x, _G(thor)->_y + 4, _G(thor)->_x + 15, _G(thor)->_y + 15))
thorDamaged(actor);
actor->_x = x;
actor->_y = y;
//done:
next_shot_frame(actor);
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
// Skull explode
int shotMovementNine(Actor *actor) {
actor->_nextFrame++;
if (actor->_nextFrame == 3) {
_G(actor[actor->_creator])._currNumShots--;
actorDestroyed(actor);
return 0;
}
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
// Skull - stalagtites
int shotMovementTen(Actor *actor) {
bool check = false;
actor->_y += 2;
if (overlap(actor->_x, actor->_y, actor->_x + actor->_sizeX, actor->_y + actor->_sizeY,
_G(thor)->_x, _G(thor)->_y + 4, _G(thor)->_x + 15, _G(thor)->_y + 15)) {
thorDamaged(actor);
check = true;
}
if (actor->_y > 160 || check) {
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
actorDestroyed(actor);
}
return 0;
}
#undef YD
#undef XD
#define YA actor->_i1
#define XA actor->_i2
#define YD actor->_i3
#define XD actor->_i4
#define DIR actor->_i5
#define CNT actor->_i6
void calc_angle(const int x1, const int y1, const int x2, const int y2, Actor *actor) {
if (x1 < x2) {
XA = -2;
XD = x2 - x1;
} else if (x1 > x2) {
XA = 2;
XD = x1 - x2;
} else {
XA = 0;
XD = 0;
}
if (y1 < y2) {
YA = -2;
YD = y2 - y1;
} else if (y1 > y2) {
YA = 2;
YD = y1 - y2;
} else {
YA = 0;
YD = 0;
}
if (YD >= XD)
DIR = 1;
else
DIR = 0;
CNT = 0;
}
// Angle throw
int shotMovementEleven(Actor *actor) {
int x1 = actor->_x;
int y1 = actor->_y;
if (!actor->_temp1) {
calc_angle(_G(thorX1), _G(thorRealY1), x1, y1, actor);
actor->_temp1 = 1;
}
if (DIR) {
y1 += YA;
CNT += XD;
if (CNT >= YD) {
x1 += XA;
CNT -= YD;
}
} else {
x1 += XA;
CNT += YD;
if (CNT >= XD) {
y1 += YA;
CNT -= XD;
}
}
if (!checkMove3(x1, y1, actor)) {
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
actorDestroyed(actor);
} else
nextFrame(actor);
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
// Angle throw Loki
int shotMovementTwelve(Actor *actor) {
int x1 = actor->_x;
int y1 = actor->_y;
if (!actor->_temp5) {
calc_angle(_G(thorX1), _G(thorRealY1), x1, y1, actor);
actor->_temp5 = 1;
}
if (DIR) {
y1 += YA;
CNT += XD;
if (CNT >= YD) {
x1 += XA;
CNT -= YD;
}
} else {
x1 += XA;
CNT += YD;
if (CNT >= XD) {
y1 += YA;
CNT -= XD;
}
}
if (x1 < 16 || x1 > 287 || y1 < 16 || y1 > 159) {
calc_angle(g_events->getRandomNumber(319),
g_events->getRandomNumber(191), x1, y1, actor);
actor->_moveType = 13;
actor->_temp4 = 240;
actor->_nextFrame = 2;
} else {
if (overlap(x1 + 2, y1 + 2, x1 + 14, y1 + 14, _G(thorX1), _G(thorY1), _G(thorX2), _G(thorY2))) {
thorDamaged(actor);
}
actor->_x = x1;
actor->_y = y1;
}
const int fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 1)
actor->_nextFrame = 0;
actor->_frameCount = actor->_frameSpeed;
} else
actor->_frameCount = fcount;
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
// Angle throw Loki-2
int shotMovementThirteen(Actor *actor) {
int x1 = actor->_x;
int y1 = actor->_y;
if (!actor->_temp5) {
calc_angle(_G(thorX1), _G(thorRealY1), x1, y1, actor);
actor->_temp5 = 1;
}
if (DIR) {
y1 += YA;
CNT += XD;
if (CNT >= YD) {
x1 += XA;
CNT -= YD;
}
} else {
x1 += XA;
CNT += YD;
if (CNT >= XD) {
y1 += YA;
CNT -= XD;
}
}
if (actor->_temp4)
actor->_temp4--;
if (!actor->_temp4) {
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
actorDestroyed(actor);
_G(appleDropCounter++);
if (_G(appleDropCounter) > 4) {
if (dropObject(actor, 5))
_G(appleDropCounter) = 0;
else
_G(appleDropCounter) = 4;
} else
dropObject(actor, 4);
return 0;
}
if (x1 < 16 || x1 > 287 || y1 < 16 || y1 > 159) {
if (x1 < 16 || x1 > 287)
XA = 0 - XA;
else
YA = 0 - YA;
} else {
if (overlap(x1 + 4, y1 + 4, x1 + 12, y1 + 12, _G(thorX1), _G(thorY1), _G(thorX2), _G(thorY2))) {
thorDamaged(actor);
}
actor->_x = x1;
actor->_y = y1;
}
const int fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 3)
actor->_nextFrame = 2;
actor->_frameCount = actor->_frameSpeed;
} else
actor->_frameCount = fcount;
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
} // namespace Got

View File

@@ -0,0 +1,33 @@
/* 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 GOT_GAME_SHOT_MOVEMENT_H
#define GOT_GAME_SHOT_MOVEMENT_H
#include "got/data/defines.h"
namespace Got {
extern int (*const shotMovementFunc[]) (Actor *actor);
} // namespace Got
#endif

View File

@@ -0,0 +1,222 @@
/* 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 "got/game/shot_pattern.h"
#include "got/game/move.h"
#include "got/vars.h"
namespace Got {
int shotPatternNone(Actor *actor);
int shotPatternOne(Actor *actor);
int shotPatternTwo(Actor *actor);
int shotPatternThree(Actor *actor);
int shotPatternFour(Actor *actor);
int shotPatternFive(Actor *actor);
int shotPatternSix(Actor *actor);
int shotPatternSeven(Actor *actor);
int shotPatternEight(Actor *actor);
int (*const shotPatternFunc[])(Actor *actor) = {
shotPatternNone,
shotPatternOne,
shotPatternTwo,
shotPatternThree,
shotPatternFour,
shotPatternFive,
shotPatternSix,
shotPatternSeven,
shotPatternEight,
};
// No shooting
int shotPatternNone(Actor *actor) {
return 0;
}
// Uni-directional seek
int shotPatternOne(Actor *actor) {
switch (actor->_lastDir) {
case 0:
if (ABS(_G(thorX1) - actor->_x) < 8) {
if (actor->_y > _G(thorRealY1)) { //r
if (actorShoots(actor, 0))
return 1;
}
}
break;
case 1:
if (ABS(_G(thorX1) - actor->_x) < 8) {
if (actor->_y < _G(thorRealY1)) { //r
if (actorShoots(actor, 1))
return 1;
}
}
break;
case 2:
if (ABS(_G(thorRealY1) - actor->_y) < 8) { //r
if (actor->_x > _G(thorX1)) {
if (actorShoots(actor, 2))
return 1;
}
}
break;
case 3:
if (ABS(_G(thorRealY1) - actor->_y) < 8) { //r
if (actor->_x < _G(thorX1)) {
if (actorShoots(actor, 3))
return 1;
}
}
break;
default:
break;
}
return 0;
}
// Omni directional
int shotPatternTwo(Actor *actor) {
if (ABS(_G(thor)->_x - actor->_x) < 8) {
if (_G(thor)->_y > actor->_y)
actorShoots(actor, 1);
else if (_G(thor)->_y < actor->_y)
actorShoots(actor, 0);
else
return 0;
} else if (ABS(_G(thor)->_y - actor->_y) < 8) {
if (_G(thor)->_x > actor->_x)
actorShoots(actor, 3);
else if (_G(thor)->_x < actor->_x)
actorShoots(actor, 2);
} else {
return 0;
}
return 1;
}
// Uni directional (backwards)
int shotPatternThree(Actor *actor) {
const int oldDir = actor->_lastDir;
if (shotPatternOne(actor)) {
actor->_lastDir = reverseDirection(actor);
return 1;
}
actor->_lastDir = reverseDirection(actor);
shotPatternOne(actor);
actor->_lastDir = oldDir;
return 1;
}
// Omni-directional not solid shot
int shotPatternFour(Actor *actor) {
if (ABS(_G(thor)->_x - actor->_x) < 8) {
if (_G(thor)->_y > actor->_y)
actorAlwaysShoots(actor, 1);
else if (_G(thor)->_y < actor->_y)
actorAlwaysShoots(actor, 0);
else
return 0;
} else if (ABS(_G(thor)->_y - actor->_y) < 8) {
if (_G(thor)->_x > actor->_x)
actorAlwaysShoots(actor, 3);
else if (_G(thor)->_x < actor->_x)
actorAlwaysShoots(actor, 2);
} else {
return 0;
}
return 1;
}
// Boss - snake
int shotPatternFive(Actor *actor) {
if (_G(rand1) < 15 && (actor->_temp1 == 0) && (actor->_temp2 == 0)) {
actor->_y += 16;
actor->_numShotsAllowed = 3 + _G(setup)._difficultyLevel;
actorShoots(actor, 2);
playSound(BOSS12, false);
const int num = actor->_shotActor;
actor->_shotCountdown = 50;
_G(actor[num])._temp3 = 120;
_G(actor[num])._temp4 = 5 + (_G(rand2) % 17);
_G(actor[num])._temp5 = _G(actor[num])._temp4;
actor->_y -= 16;
return 1;
}
return 0;
}
// 4 surrounding squares
int shotPatternSix(Actor *actor) {
const int pos = ((actor->_x) / 16) + (((actor->_y) / 16) * 20);
if (_G(thorPos) == pos - 20)
actorShoots(actor, 0);
else if (_G(thorPos) == pos + 20)
actorShoots(actor, 1);
else if (_G(thorPos) == pos - 1)
actorShoots(actor, 2);
else if (_G(thorPos) == pos + 1)
actorShoots(actor, 3);
else
return 0;
actor->_frameSequence[3] = 3;
actor->_nextFrame = 3;
return 1;
}
// none
int shotPatternSeven(Actor *actor) {
return 0;
}
// random
int shotPatternEight(Actor *actor) {
if (!actor->_i2) {
actor->_i1 = actor->_funcPass;
actor->_i2 = 1;
}
if (actor->_i1) {
actor->_i1--;
} else if (_G(rand1) < 10) {
actor->_i1 = actor->_funcPass;
actor->_i2 = _G(thorRealY1);
actorShoots(actor, 0);
return 1;
}
return 0;
}
} // namespace Got

View File

@@ -0,0 +1,33 @@
/* 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 GOT_GAME_SHOT_PATTERN_H
#define GOT_GAME_SHOT_PATTERN_H
#include "got/data/defines.h"
namespace Got {
extern int (*const shotPatternFunc[])(Actor *actor);
} // namespace Got
#endif

View File

@@ -0,0 +1,290 @@
/* 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 "got/game/special_tile.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/game/object.h"
#include "got/gfx/image.h"
#include "got/vars.h"
namespace Got {
int openDoor1(int y, int x);
int cashDoor1(int y, int x, int amount);
void eraseDoor(int x, int y);
int specialTileThor(const int x, const int y, const int icon) {
int cx, cy;
int f = 0;
switch (icon) {
case 201:
return openDoor1(x, y);
case 202:
if (GAME3) {
if (_G(thorInfo)._inventory & 64) {
if (_G(thorInfo)._object == 4) {
eraseDoor(y, x);
deleteObject();
return 1;
}
}
return 0;
}
if (_G(thor)->_x > 300)
// Ending bridge
_G(endTile) = true;
return 1;
case 203:
if (!GAME1) {
if ((_G(thorInfo)._inventory & 64) && _G(thorInfo)._object == 5) {
odinSpeaks(2012, 0);
deleteObject();
_G(setup).f10 = true;
} else if (!_G(setup).f10) {
odinSpeaks(2011, 0);
_G(setup).f10 = true;
}
return 1;
}
return 0;
case 204:
if (GAME2) {
if (!_G(setup).f19)
_G(slipFlag) = true;
return 1;
}
if (GAME3) {
if (_G(thor)->_x < 4)
_G(endTile) = true;
return 1;
}
return 0;
case 205:
if (!_G(diag) && _G(thor)->_dir != 1)
return 1;
break;
case 206:
if (!_G(diag) && _G(thor)->_dir != 0)
return 1;
break;
case 207:
if (!_G(diag) && _G(thor)->_dir != 3)
return 1;
break;
case 208:
if (!_G(diag) && _G(thor)->_dir != 2)
return 1;
break;
case 209:
return cashDoor1(x, y, 10);
case 210:
return cashDoor1(x, y, 100);
case 211:
if (GAME1) {
placeTile(y, x, 79);
_G(exitFlag) = 2;
} else if (GAME2) {
if (_G(thor)->_dir == 0 && _G(setup).f29 && _G(setup).f21 && !_G(setup).f22) {
actorVisible(1);
actorVisible(2);
actorVisible(3);
actorVisible(4);
actorVisible(5);
Common::fill(_G(scrn)._actorInvis, _G(scrn)._actorInvis + 16, 0);
_G(thunderSnakeCounter) = 60;
playSound(THUNDER, true);
_G(setup).f22 = true;
}
} else {
// Game 3
return 0;
}
return 1;
case 212:
case 213:
return 0;
case 214: // Teleport tiles
case 215:
case 216:
case 217:
if ((GAME2 && icon == 217) || GAME3) {
cx = (_G(thorX1) + 7) / 16;
cy = (_G(thorRealY1) + 8) / 16;
if (_G(scrn)._iconGrid[cy][cx] == icon) {
_G(thor)->_vulnerableCountdown = STAMINA;
playSound(WOOP, false);
const int nt = _G(scrn)._newLevelLocation[icon - 214];
const int displayPage = _G(pge);
const int drawPage = _G(pge) ^ 1;
_G(thor)->_lastX[displayPage] = _G(thor)->_x;
_G(thor)->_lastY[displayPage] = _G(thor)->_y;
_G(thor)->_x = (nt % 20) * 16;
_G(thor)->_y = ((nt / 20) * 16) - 2;
_G(thor)->_lastX[drawPage] = _G(thor)->_x;
_G(thor)->_lastY[drawPage] = _G(thor)->_y;
return 0;
}
return 1;
}
return 0;
case 218:
case 219:
// Hole tiles
f = 1;
// fall through
case 220:
case 221:
case 222:
case 223:
case 224:
case 225:
case 226:
case 227:
case 228:
case 229:
// Hole tiles
cx = (_G(thorX1) + 7) / 16;
cy = (_G(thorRealY1) + 8) / 16;
if (_G(scrn)._iconGrid[cy][cx] == icon) {
_G(thor)->_vulnerableCountdown = STAMINA;
if (icon < 224 && icon > 219)
playSound(FALL, false);
_G(newLevel) = _G(scrn)._newLevel[icon - 220 + (f * 6)];
_G(warpScroll) = false;
if (_G(newLevel) > 119) {
_G(warpScroll) = true;
_G(newLevel) -= 128;
}
_G(newLevelTile) = _G(scrn)._newLevelLocation[icon - 220 + (f * 6)];
_G(warpFlag) = true;
if (_G(warpScroll)) {
if (_G(thor)->_dir == 0)
_G(thor)->_y = 175;
else if (_G(thor)->_dir == 1)
_G(thor)->_y = 0;
else if (_G(thor)->_dir == 2)
_G(thor)->_x = 304;
else if (_G(thor)->_dir == 3)
_G(thor)->_x = 0;
} else {
_G(thor)->_x = (_G(newLevelTile) % 20) * 16;
_G(thor)->_y = ((_G(newLevelTile) / 20) * 16) - 2;
}
_G(thor)->_lastX[0] = _G(thor)->_x;
_G(thor)->_lastX[1] = _G(thor)->_x;
_G(thor)->_lastY[0] = _G(thor)->_y;
_G(thor)->_lastY[1] = _G(thor)->_y;
return 0;
}
return 1;
default:
break;
}
return 0;
}
int specialTile(const Actor *actor, int x, int y, const int icon) {
switch (icon) {
case 201:
case 202:
case 203:
case 204:
break;
case 205:
case 206:
case 207:
case 208:
return 1;
case 209:
case 210:
case 214:
case 215:
case 216:
case 217:
return 0;
case 224:
case 225:
case 226:
case 227:
if (!actor->_flying)
return 0;
return 1;
default:
return 1;
}
return 0;
}
void eraseDoor(const int x, const int y) {
playSound(DOOR, false);
_G(scrn)._iconGrid[y][x] = _G(scrn)._backgroundColor;
}
int openDoor1(const int y, const int x) {
if (_G(thorInfo)._keys > 0) {
eraseDoor(x, y);
_G(thorInfo)._keys--;
return 1;
}
if (!_G(keyDoorInform)) {
odinSpeaks(2003, 0);
_G(keyDoorInform) = true;
}
return 0;
}
int cashDoor1(const int y, const int x, const int amount) {
if (_G(thorInfo)._jewels >= amount) {
eraseDoor(x, y);
_G(thorInfo)._jewels -= amount;
return 1;
}
if (amount == 10 && !_G(cashDoor1Inform)) {
odinSpeaks(2005, 0);
_G(cashDoor1Inform) = true;
}
if (amount == 100 && !_G(cashDoor2Inform)) {
odinSpeaks(2004, 0);
_G(cashDoor2Inform) = true;
}
return 0;
}
} // namespace Got

View File

@@ -0,0 +1,34 @@
/* 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 GOT_GAME_SPECIAL_TILE_H
#define GOT_GAME_SPECIAL_TILE_H
#include "got/data/defines.h"
namespace Got {
extern int specialTileThor(int x, int y, int icon);
extern int specialTile(const Actor *actor, int x, int y, int icon);
} // namespace Got
#endif

View File

@@ -0,0 +1,67 @@
/* 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 "got/game/status.h"
#include "got/events.h"
#include "got/vars.h"
namespace Got {
void addJewels(int num) {
_G(thorInfo)._jewels = CLIP(_G(thorInfo)._jewels + num, 0, 999);
}
void addScore(int num) {
_G(thorInfo)._score = CLIP(_G(thorInfo)._score + num, 0l, 999999l);
}
void addMagic(int num) {
_G(thorInfo)._magic = CLIP(_G(thorInfo)._magic + num, 0, 150);
}
void addHealth(int num) {
_G(thor)->_health = CLIP(_G(thor)->_health + num, 0, 150);
if (_G(thor)->_health < 1)
g_events->send(GameMessage("THOR_DIES"));
}
void addKeys(int num) {
_G(thorInfo)._keys = CLIP(_G(thorInfo)._keys + num, 0, 99);
}
void fillHealth() {
addHealth(150);
}
void fillMagic() {
addMagic(150);
}
void fillScore(int num, const char *endMessage) {
GameMessage msg("FILL_SCORE");
if (endMessage)
msg._stringValue = endMessage;
msg._value = num;
g_events->send("GameStatus", msg);
}
} // namespace Got

38
engines/got/game/status.h Normal file
View File

@@ -0,0 +1,38 @@
/* 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 GOT_GAME_STATUS_H
#define GOT_GAME_STATUS_H
namespace Got {
extern void addJewels(int num);
extern void addScore(int num);
extern void addMagic(int num);
extern void addHealth(int num);
extern void addKeys(int num);
extern void fillHealth();
extern void fillMagic();
extern void fillScore(int num, const char *endMessage = nullptr);
} // namespace Got
#endif