aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/agos/string.cpp3
-rw-r--r--engines/draci/script.cpp4
-rw-r--r--engines/draci/sound.cpp13
-rw-r--r--engines/dreamweb/dreamgen.cpp47
-rw-r--r--engines/dreamweb/stubs.cpp22
-rw-r--r--engines/kyra/debugger.cpp9
-rw-r--r--engines/lastexpress/debug.cpp3
-rw-r--r--engines/lastexpress/entities/anna.cpp3
-rw-r--r--engines/lastexpress/entities/ivo.cpp3
-rw-r--r--engines/lastexpress/entities/milos.cpp3
-rw-r--r--engines/lastexpress/entities/salko.cpp3
-rw-r--r--engines/lastexpress/entities/vesna.cpp3
-rw-r--r--engines/lastexpress/fight/fight.cpp407
-rw-r--r--engines/lastexpress/fight/fight.h125
-rw-r--r--engines/lastexpress/fight/fighter.cpp248
-rw-r--r--engines/lastexpress/fight/fighter.h123
-rw-r--r--engines/lastexpress/fight/fighter_anna.cpp186
-rw-r--r--engines/lastexpress/fight/fighter_anna.h48
-rw-r--r--engines/lastexpress/fight/fighter_ivo.cpp244
-rw-r--r--engines/lastexpress/fight/fighter_ivo.h51
-rw-r--r--engines/lastexpress/fight/fighter_milos.cpp221
-rw-r--r--engines/lastexpress/fight/fighter_milos.h51
-rw-r--r--engines/lastexpress/fight/fighter_salko.cpp201
-rw-r--r--engines/lastexpress/fight/fighter_salko.h51
-rw-r--r--engines/lastexpress/fight/fighter_vesna.cpp264
-rw-r--r--engines/lastexpress/fight/fighter_vesna.h51
-rw-r--r--engines/lastexpress/game/fight.cpp1583
-rw-r--r--engines/lastexpress/game/fight.h266
-rw-r--r--engines/lastexpress/game/logic.cpp4
-rw-r--r--engines/lastexpress/game/menu.cpp3
-rw-r--r--engines/lastexpress/lastexpress.cpp20
-rw-r--r--engines/lastexpress/module.mk8
-rw-r--r--engines/lure/debugger.cpp14
-rw-r--r--engines/lure/memory.cpp8
-rw-r--r--engines/saga/actor.cpp1
-rw-r--r--engines/sci/decompressor.cpp45
-rw-r--r--engines/sword25/fmv/theora_decoder.cpp11
-rw-r--r--engines/sword25/gfx/image/art.cpp69
-rw-r--r--engines/sword25/gfx/image/art.h5
-rw-r--r--engines/sword25/gfx/image/vectorimage.cpp2
-rw-r--r--engines/sword25/gfx/image/vectorimagerenderer.cpp7
-rw-r--r--engines/sword25/package/packagemanager.h3
-rw-r--r--engines/teenagent/resources.cpp11
-rw-r--r--engines/teenagent/teenagent.cpp129
-rw-r--r--engines/toon/path.cpp24
-rw-r--r--engines/touche/resource.cpp22
-rw-r--r--engines/tsage/resources.cpp11
-rw-r--r--engines/tsage/ringworld_logic.cpp15
-rw-r--r--engines/tsage/ringworld_scenes1.cpp2
49 files changed, 2664 insertions, 1986 deletions
diff --git a/engines/agos/string.cpp b/engines/agos/string.cpp
index f9a06cbecb..410fd5a1ce 100644
--- a/engines/agos/string.cpp
+++ b/engines/agos/string.cpp
@@ -517,8 +517,7 @@ void AGOSEngine::printScreenText(uint vgaSpriteId, uint color, const char *strin
y -= textHeight;
} else
pos = stringLength;
- padding = (lettersPerRow - pos) % 2 ?
- (lettersPerRow - pos) / 2 + 1 : (lettersPerRow - pos) / 2;
+ padding = ((lettersPerRow - pos) % 2) ? (lettersPerRow - pos) / 2 + 1 : (lettersPerRow - pos) / 2;
while (padding--)
*convertedString2++ = ' ';
stringLength -= pos;
diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp
index c4df9d9dde..8ff60033ed 100644
--- a/engines/draci/script.cpp
+++ b/engines/draci/script.cpp
@@ -1160,9 +1160,7 @@ void Script::run(const GPL2Program &program, uint16 offset) {
}
}
} else {
- debugC(1, kDraciBytecodeDebugLevel, "Unknown opcode %d, %d",
- num, subnum);
- abort();
+ error("Unknown opcode %d, %d", num, subnum);
}
GPLHandler handler = cmd->_handler;
diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp
index 106167ef8a..d534f46a6e 100644
--- a/engines/draci/sound.cpp
+++ b/engines/draci/sound.cpp
@@ -67,8 +67,12 @@ void LegacySoundArchive::openArchive(const char *path) {
debugC(1, kDraciArchiverDebugLevel, "Loading header");
uint totalLength = _f->readUint32LE();
+
const uint kMaxSamples = 4095; // The no-sound file is exactly 16K bytes long, so don't fail on short reads
- uint sampleStarts[kMaxSamples];
+ uint *sampleStarts = (uint *)malloc(kMaxSamples * sizeof(uint));
+ if (!sampleStarts)
+ error("[LegacySoundArchive::openArchive] Cannot allocate buffer for no-sound file");
+
for (uint i = 0; i < kMaxSamples; ++i) {
sampleStarts[i] = _f->readUint32LE();
}
@@ -90,17 +94,22 @@ void LegacySoundArchive::openArchive(const char *path) {
}
if (_samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length != totalLength &&
_samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length - _samples[0]._offset != totalLength) {
- // WORKAROUND: the stored length is stored with the header for sounds and without the hader for dubbing. Crazy.
+ // WORKAROUND: the stored length is stored with the header for sounds and without the header for dubbing. Crazy.
debugC(1, kDraciArchiverDebugLevel, "Broken sound archive: %d != %d",
_samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length,
totalLength);
closeArchive();
+
+ free(sampleStarts);
+
return;
}
} else {
debugC(1, kDraciArchiverDebugLevel, "Archive info: empty");
}
+ free(sampleStarts);
+
// Indicate that the archive has been successfully opened
_opened = true;
}
diff --git a/engines/dreamweb/dreamgen.cpp b/engines/dreamweb/dreamgen.cpp
index da0d71f7fe..462ae596f8 100644
--- a/engines/dreamweb/dreamgen.cpp
+++ b/engines/dreamweb/dreamgen.cpp
@@ -4329,52 +4329,6 @@ noeffects:
cx = pop();
}
-void DreamGenContext::frameoutv() {
- STACK_CHECK;
- push(dx);
- ax = bx;
- bx = dx;
- _mul(bx);
- _add(di, ax);
- dx = pop();
- push(cx);
- ch = 0;
- _sub(dx, cx);
- cx = pop();
-frameloop1:
- push(cx);
- ch = 0;
-frameloop2:
- _lodsb();
- _cmp(al, 0);
- if (!flags.z())
- goto backtosolid;
-backtoother:
- _inc(di);
- if (--cx)
- goto frameloop2;
- cx = pop();
- _add(di, dx);
- _dec(ch);
- if (!flags.z())
- goto frameloop1;
- return;
-frameloop3:
- _lodsb();
- _cmp(al, 0);
- if (flags.z())
- goto backtoother;
-backtosolid:
- _stosb();
- if (--cx)
- goto frameloop3;
- cx = pop();
- _add(di, dx);
- _dec(ch);
- if (!flags.z())
- goto frameloop1;
-}
-
void DreamGenContext::frameoutbh() {
STACK_CHECK;
push(dx);
@@ -22126,7 +22080,6 @@ void DreamGenContext::__dispatch_call(uint16 addr) {
case 0xc214: delthisone(); break;
case 0xc228: doblocks(); break;
case 0xc22c: showframe(); break;
- case 0xc230: frameoutv(); break;
case 0xc238: frameoutbh(); break;
case 0xc23c: frameoutfx(); break;
case 0xc240: transferinv(); break;
diff --git a/engines/dreamweb/stubs.cpp b/engines/dreamweb/stubs.cpp
index eebfbeb0d4..1869f1b109 100644
--- a/engines/dreamweb/stubs.cpp
+++ b/engines/dreamweb/stubs.cpp
@@ -503,4 +503,26 @@ void DreamGenContext::showpcx() {
pcxFile.close();
}
+void DreamGenContext::frameoutv() {
+ uint16 pitch = dx;
+ uint16 width = cx & 0xff;
+ uint16 height = cx >> 8;
+ uint16 stride = pitch - width;
+
+ const uint8* src = ds.ptr(si, width * height);
+ uint8* base = es.ptr(di, stride * height);
+ uint8* dst = base + pitch * bx;
+
+ // NB: Original code assumes non-zero width and height, "for" are unneeded, do-while would suffice but would be less readable
+ for (uint16 y = 0; y < height; ++y) {
+ for (uint16 x = 0; x < width; ++x) {
+ uint8 pixel = *src++;
+ if (pixel)
+ *dst = pixel;
+ ++dst;
+ }
+ dst += stride;
+ }
+}
+
} /*namespace dreamgen */
diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp
index d0baf8a133..e8dd9e9a15 100644
--- a/engines/kyra/debugger.cpp
+++ b/engines/kyra/debugger.cpp
@@ -71,11 +71,18 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) {
}
if (_vm->game() != GI_KYRA1 && _vm->resource()->getFileSize(argv[1]) != 768) {
- uint8 buffer[320*200];
+ uint8 *buffer = (uint8 *)malloc(320 * 200 * sizeof(uint8));
+ if (!buffer) {
+ DebugPrintf("ERROR: Cannot allocate buffer for screen region!\n");
+ return true;
+ }
+
_vm->screen()->copyRegionToBuffer(5, 0, 0, 320, 200, buffer);
_vm->screen()->loadBitmap(argv[1], 5, 5, 0);
palette.copy(_vm->screen()->getCPagePtr(5), 0, 256);
_vm->screen()->copyBlockToPage(5, 0, 0, 320, 200, buffer);
+
+ free(buffer);
} else if (!_vm->screen()->loadPalette(argv[1], palette)) {
DebugPrintf("ERROR: Palette '%s' not found!\n", argv[1]);
return true;
diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp
index 4b7c5f6a9a..d5c7df0e55 100644
--- a/engines/lastexpress/debug.cpp
+++ b/engines/lastexpress/debug.cpp
@@ -31,9 +31,10 @@
#include "lastexpress/data/snd.h"
#include "lastexpress/data/subtitle.h"
+#include "lastexpress/fight/fight.h"
+
#include "lastexpress/game/action.h"
#include "lastexpress/game/beetle.h"
-#include "lastexpress/game/fight.h"
#include "lastexpress/game/inventory.h"
#include "lastexpress/game/logic.h"
#include "lastexpress/game/object.h"
diff --git a/engines/lastexpress/entities/anna.cpp b/engines/lastexpress/entities/anna.cpp
index 0bedda41e8..bce99ad16d 100644
--- a/engines/lastexpress/entities/anna.cpp
+++ b/engines/lastexpress/entities/anna.cpp
@@ -22,9 +22,10 @@
#include "lastexpress/entities/anna.h"
+#include "lastexpress/fight/fight.h"
+
#include "lastexpress/game/action.h"
#include "lastexpress/game/entities.h"
-#include "lastexpress/game/fight.h"
#include "lastexpress/game/inventory.h"
#include "lastexpress/game/logic.h"
#include "lastexpress/game/object.h"
diff --git a/engines/lastexpress/entities/ivo.cpp b/engines/lastexpress/entities/ivo.cpp
index 35f4ccfb8c..861c3cf9bd 100644
--- a/engines/lastexpress/entities/ivo.cpp
+++ b/engines/lastexpress/entities/ivo.cpp
@@ -22,9 +22,10 @@
#include "lastexpress/entities/ivo.h"
+#include "lastexpress/fight/fight.h"
+
#include "lastexpress/game/action.h"
#include "lastexpress/game/entities.h"
-#include "lastexpress/game/fight.h"
#include "lastexpress/game/logic.h"
#include "lastexpress/game/object.h"
#include "lastexpress/game/savepoint.h"
diff --git a/engines/lastexpress/entities/milos.cpp b/engines/lastexpress/entities/milos.cpp
index 587c43cade..45fd6883f0 100644
--- a/engines/lastexpress/entities/milos.cpp
+++ b/engines/lastexpress/entities/milos.cpp
@@ -24,9 +24,10 @@
#include "lastexpress/entities/vesna.h"
+#include "lastexpress/fight/fight.h"
+
#include "lastexpress/game/action.h"
#include "lastexpress/game/entities.h"
-#include "lastexpress/game/fight.h"
#include "lastexpress/game/inventory.h"
#include "lastexpress/game/logic.h"
#include "lastexpress/game/object.h"
diff --git a/engines/lastexpress/entities/salko.cpp b/engines/lastexpress/entities/salko.cpp
index 4d510bb9bf..bbaff5f1d9 100644
--- a/engines/lastexpress/entities/salko.cpp
+++ b/engines/lastexpress/entities/salko.cpp
@@ -22,9 +22,10 @@
#include "lastexpress/entities/salko.h"
+#include "lastexpress/fight/fight.h"
+
#include "lastexpress/game/action.h"
#include "lastexpress/game/entities.h"
-#include "lastexpress/game/fight.h"
#include "lastexpress/game/logic.h"
#include "lastexpress/game/object.h"
#include "lastexpress/game/savepoint.h"
diff --git a/engines/lastexpress/entities/vesna.cpp b/engines/lastexpress/entities/vesna.cpp
index 8e09dbf7b0..79ac934ef9 100644
--- a/engines/lastexpress/entities/vesna.cpp
+++ b/engines/lastexpress/entities/vesna.cpp
@@ -22,9 +22,10 @@
#include "lastexpress/entities/vesna.h"
+#include "lastexpress/fight/fight.h"
+
#include "lastexpress/game/action.h"
#include "lastexpress/game/entities.h"
-#include "lastexpress/game/fight.h"
#include "lastexpress/game/logic.h"
#include "lastexpress/game/object.h"
#include "lastexpress/game/savepoint.h"
diff --git a/engines/lastexpress/fight/fight.cpp b/engines/lastexpress/fight/fight.cpp
new file mode 100644
index 0000000000..685b3b09d1
--- /dev/null
+++ b/engines/lastexpress/fight/fight.cpp
@@ -0,0 +1,407 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "lastexpress/fight/fight.h"
+
+#include "lastexpress/fight/fighter_anna.h"
+#include "lastexpress/fight/fighter_ivo.h"
+#include "lastexpress/fight/fighter_milos.h"
+#include "lastexpress/fight/fighter_salko.h"
+#include "lastexpress/fight/fighter_vesna.h"
+
+#include "lastexpress/data/cursor.h"
+#include "lastexpress/data/sequence.h"
+
+#include "lastexpress/game/inventory.h"
+#include "lastexpress/game/logic.h"
+#include "lastexpress/game/object.h"
+#include "lastexpress/game/scenes.h"
+#include "lastexpress/game/state.h"
+
+#include "lastexpress/graphics.h"
+#include "lastexpress/helpers.h"
+#include "lastexpress/lastexpress.h"
+#include "lastexpress/resource.h"
+
+namespace LastExpress {
+
+Fight::FightData::FightData() {
+ player = NULL;
+ opponent = NULL;
+
+ index = 0;
+
+ isFightRunning = false;
+}
+
+Fight::FightData::~FightData() {
+ SAFE_DELETE(player);
+ SAFE_DELETE(opponent);
+}
+
+Fight::Fight(LastExpressEngine *engine) : _engine(engine), _data(NULL), _endType(kFightEndLost), _state(0), _handleTimer(false) {
+}
+
+Fight::~Fight() {
+ clearData();
+ _data = NULL;
+
+ // Zero passed pointers
+ _engine = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Events
+//////////////////////////////////////////////////////////////////////////
+void Fight::eventMouse(const Common::Event &ev) {
+ if (!_data || _data->index)
+ return;
+
+ // TODO move all the egg handling to inventory functions
+
+ getFlags()->mouseLeftClick = false;
+ getFlags()->shouldRedraw = false;
+ getFlags()->mouseRightClick = false;
+
+ if (ev.mouse.x < 608 || ev.mouse.y < 448 || ev.mouse.x >= 640 || ev.mouse.x >= 480) {
+
+ // Handle right button click
+ if (ev.type == Common::EVENT_RBUTTONUP) {
+ getSound()->removeFromQueue(kEntityTables0);
+ setStopped();
+
+ getGlobalTimer() ? _state = 0 : ++_state;
+
+ getFlags()->mouseRightClick = true;
+ }
+
+ if (_handleTimer) {
+ // Timer expired => show with full brightness
+ if (!getGlobalTimer())
+ getInventory()->drawBlinkingEgg();
+
+ _handleTimer = false;
+ }
+
+ // Check hotspots
+ Scene *scene = getScenes()->get(getState()->scene);
+ SceneHotspot *hotspot = NULL;
+
+ if (!scene->checkHotSpot(ev.mouse, &hotspot)) {
+ _engine->getCursor()->setStyle(kCursorNormal);
+ } else {
+ _engine->getCursor()->setStyle((CursorStyle)hotspot->cursor);
+
+ // Call player function
+ if (_data->player->canInteract((Fighter::FightAction)hotspot->action)) {
+ if (ev.type == Common::EVENT_LBUTTONUP)
+ _data->player->handleAction((Fighter::FightAction)hotspot->action);
+ } else {
+ _engine->getCursor()->setStyle(kCursorNormal);
+ }
+ }
+ } else {
+ // Handle clicks on menu icon
+
+ if (!_handleTimer) {
+ // Timer expired => show with full brightness
+ if (!getGlobalTimer())
+ getInventory()->drawBlinkingEgg();
+
+ _handleTimer = true;
+ }
+
+ // Stop fight if clicked
+ if (ev.type == Common::EVENT_LBUTTONUP) {
+ _handleTimer = false;
+ getSound()->removeFromQueue(kEntityTables0);
+ bailout(kFightEndExit);
+ }
+
+ // Reset timer on right click
+ if (ev.type == Common::EVENT_RBUTTONUP) {
+ if (getGlobalTimer()) {
+ if (getSound()->isBuffered("TIMER"))
+ getSound()->removeFromQueue("TIMER");
+
+ setGlobalTimer(900);
+ }
+ }
+ }
+
+ getFlags()->shouldRedraw = true;
+}
+
+void Fight::eventTick(const Common::Event &ev) {
+ handleTick(ev, true);
+}
+
+void Fight::handleTick(const Common::Event &ev, bool isProcessing) {
+ // TODO move all the egg handling to inventory functions
+
+ // Blink egg
+ if (getGlobalTimer()) {
+ warning("Fight::handleMouseMove - egg blinking not implemented!");
+ }
+
+ if (!_data || _data->index)
+ return;
+
+ SceneHotspot *hotspot = NULL;
+ if (!getScenes()->get(getState()->scene)->checkHotSpot(ev.mouse, &hotspot) || !_data->player->canInteract((Fighter::FightAction)hotspot->action)) {
+ _engine->getCursor()->setStyle(kCursorNormal);
+ } else {
+ _engine->getCursor()->setStyle((CursorStyle)hotspot->cursor);
+ }
+
+ _data->player->update();
+ _data->opponent->update();
+
+ // Draw sequences
+ if (!_data->isFightRunning)
+ return;
+
+ if (isProcessing)
+ getScenes()->drawFrames(true);
+
+ if (_data->index) {
+ // Set next sequence name index
+ _data->index--;
+ _data->sequences[_data->index] = loadSequence(_data->names[_data->index]);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Setup
+//////////////////////////////////////////////////////////////////////////
+Fight::FightEndType Fight::setup(FightType type) {
+ if (_data)
+ error("Fight::setup - calling fight setup again while a fight is already in progress!");
+
+ //////////////////////////////////////////////////////////////////////////
+ // Prepare UI & state
+ if (_state >= 5 && (type == kFightSalko || type == kFightVesna)) {
+ _state = 0;
+ return kFightEndWin;
+ }
+
+ getInventory()->showHourGlass();
+ // TODO events function
+ getFlags()->flag_0 = false;
+ getFlags()->mouseRightClick = false;
+ getEntities()->reset();
+
+ // Compute scene to use
+ SceneIndex sceneIndex;
+ switch(type) {
+ default:
+ sceneIndex = kSceneFightDefault;
+ break;
+
+ case kFightMilos:
+ sceneIndex = (getObjects()->get(kObjectCompartment1).location2 < kObjectLocation3) ? kSceneFightMilos : kSceneFightMilosBedOpened;
+ break;
+
+ case kFightAnna:
+ sceneIndex = kSceneFightAnna;
+ break;
+
+ case kFightIvo:
+ sceneIndex = kSceneFightIvo;
+ break;
+
+ case kFightSalko:
+ sceneIndex = kSceneFightSalko;
+ break;
+
+ case kFightVesna:
+ sceneIndex = kSceneFightVesna;
+ break;
+ }
+
+ if (getFlags()->shouldRedraw) {
+ getFlags()->shouldRedraw = false;
+ askForRedraw();
+ //redrawScreen();
+ }
+
+ // Load the scene object
+ Scene *scene = getScenes()->get(sceneIndex);
+
+ // Update game entities and state
+ getEntityData(kEntityPlayer)->entityPosition = scene->entityPosition;
+ getEntityData(kEntityPlayer)->location = scene->location;
+
+ getState()->scene = sceneIndex;
+
+ getFlags()->flag_3 = true;
+
+ // Draw the scene
+ _engine->getGraphicsManager()->draw(scene, GraphicsManager::kBackgroundC);
+ // FIXME move to start of fight?
+ askForRedraw();
+ redrawScreen();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Setup the fight
+ _data = new FightData;
+ loadData(type);
+
+ // Show opponents & egg button
+ Common::Event emptyEvent;
+ handleTick(emptyEvent, false);
+ getInventory()->drawEgg();
+
+ // Start fight
+ _endType = kFightEndLost;
+ while (_data->isFightRunning) {
+ if (_engine->handleEvents())
+ continue;
+
+ getSound()->updateQueue();
+ }
+
+ // Cleanup after fight is over
+ clearData();
+
+ return _endType;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Status
+//////////////////////////////////////////////////////////////////////////
+void Fight::setStopped() {
+ if (_data)
+ _data->isFightRunning = false;
+}
+
+void Fight::bailout(FightEndType type) {
+ _state = 0;
+ _endType = type;
+ setStopped();
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Cleanup
+//////////////////////////////////////////////////////////////////////////
+void Fight::clearData() {
+ if (!_data)
+ return;
+
+ // Clear data
+ SAFE_DELETE(_data);
+
+ _engine->restoreEventHandlers();
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Loading
+//////////////////////////////////////////////////////////////////////////
+void Fight::loadData(FightType type) {
+ if (!_data)
+ error("Fight::loadData - invalid data!");
+
+ switch (type) {
+ default:
+ break;
+
+ case kFightMilos:
+ _data->player = new FighterPlayerMilos(_engine);
+ _data->opponent = new FighterOpponentMilos(_engine);
+ break;
+
+ case kFightAnna:
+ _data->player = new FighterPlayerAnna(_engine);
+ _data->opponent = new FighterOpponentAnna(_engine);
+ break;
+
+ case kFightIvo:
+ _data->player = new FighterPlayerIvo(_engine);
+ _data->opponent = new FighterOpponentIvo(_engine);
+ break;
+
+ case kFightSalko:
+ _data->player = new FighterPlayerSalko(_engine);
+ _data->opponent = new FighterOpponentSalko(_engine);
+ break;
+
+ case kFightVesna:
+ _data->player = new FighterPlayerVesna(_engine);
+ _data->opponent = new FighterOpponentVesna(_engine);
+ break;
+ }
+
+ if (!_data->player || !_data->opponent)
+ error("Fight::loadData - error loading fight data (type=%d)", type);
+
+ // Setup opponent pointers
+ setOpponents();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Start running the fight
+ _data->isFightRunning = true;
+
+ if (_state < 5) {
+ _data->player->setSequenceAndDraw(0, Fighter::kFightSequenceType0);
+ _data->opponent->setSequenceAndDraw(0, Fighter::kFightSequenceType0);
+ goto end_load;
+ }
+
+ switch(type) {
+ default:
+ break;
+
+ case kFightMilos:
+ _data->opponent->setCountdown(1);
+ _data->player->setSequenceAndDraw(4, Fighter::kFightSequenceType0);
+ _data->opponent->setSequenceAndDraw(0, Fighter::kFightSequenceType0);
+ break;
+
+ case kFightIvo:
+ _data->opponent->setCountdown(1);
+ _data->player->setSequenceAndDraw(3, Fighter::kFightSequenceType0);
+ _data->opponent->setSequenceAndDraw(6, Fighter::kFightSequenceType0);
+ break;
+
+ case kFightVesna:
+ _data->opponent->setCountdown(1);
+ _data->player->setSequenceAndDraw(0, Fighter::kFightSequenceType0);
+ _data->player->setSequenceAndDraw(3, Fighter::kFightSequenceType2);
+ _data->opponent->setSequenceAndDraw(5, Fighter::kFightSequenceType0);
+ break;
+ }
+
+end_load:
+ // Setup event handlers
+ _engine->backupEventHandlers();
+ SET_EVENT_HANDLERS(Fight, this);
+}
+
+void Fight::setOpponents() {
+ _data->player->setOpponent(_data->opponent);
+ _data->opponent->setOpponent(_data->player);
+
+ _data->player->setFight(this);
+ _data->opponent->setFight(this);
+}
+
+} // End of namespace LastExpress
diff --git a/engines/lastexpress/fight/fight.h b/engines/lastexpress/fight/fight.h
new file mode 100644
index 0000000000..fffb520789
--- /dev/null
+++ b/engines/lastexpress/fight/fight.h
@@ -0,0 +1,125 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef LASTEXPRESS_FIGHT_H
+#define LASTEXPRESS_FIGHT_H
+
+/*
+ Fight structure
+ ---------------
+ uint32 {4} - player struct
+ uint32 {4} - opponent struct
+ uint32 {4} - hasLost flag
+
+ byte {1} - isRunning
+
+ Fight participant structure
+ ---------------------------
+ uint32 {4} - function pointer
+ uint32 {4} - pointer to fight structure
+ uint32 {4} - pointer to opponent (fight participant structure)
+ uint32 {4} - array of sequences
+ uint32 {4} - number of sequences
+ uint32 {4} - ??
+ uint32 {4} - ??
+ uint32 {4} - ??
+ uint32 {4} - ??
+ uint32 {4} - ??
+ uint32 {4} - ??
+ uint32 {4} - ??
+ uint32 {4} - ??
+ uint16 {2} - ??
+ uint16 {2} - ?? - only for opponent structure
+ uint32 {4} - ?? - only for opponent structure
+
+*/
+
+#include "lastexpress/shared.h"
+
+#include "lastexpress/eventhandler.h"
+
+namespace LastExpress {
+
+class LastExpressEngine;
+class Sequence;
+
+class Fighter;
+class Opponent;
+
+class Fight : public EventHandler {
+public:
+ enum FightEndType {
+ kFightEndWin = 0,
+ kFightEndLost = 1,
+ kFightEndExit = 2
+ };
+
+ Fight(LastExpressEngine *engine);
+ ~Fight();
+
+ FightEndType setup(FightType type);
+
+ void eventMouse(const Common::Event &ev);
+ void eventTick(const Common::Event &ev);
+
+ // State
+ bool isRunning() { return _data->isFightRunning; }
+ void setRunningState(bool state) { _data->isFightRunning = state; }
+ void bailout(FightEndType type);
+ void setStopped();
+ void resetState() { _state = 0; }
+ void setEndType(FightEndType endType) { _endType = endType; }
+
+private:
+ struct FightData {
+ Fighter *player;
+ Opponent *opponent;
+ int32 index;
+
+ Sequence *sequences[20];
+ Common::String names[20];
+
+ bool isFightRunning;
+
+ FightData();
+ ~FightData();
+ };
+
+ LastExpressEngine *_engine;
+ FightData *_data;
+ FightEndType _endType;
+ int _state;
+
+ bool _handleTimer;
+
+ // Events
+ void handleTick(const Common::Event &ev, bool unknown);
+
+ // Data
+ void loadData(FightType type);
+ void clearData();
+ void setOpponents();
+};
+
+} // End of namespace LastExpress
+
+#endif // LASTEXPRESS_FIGHT_H
diff --git a/engines/lastexpress/fight/fighter.cpp b/engines/lastexpress/fight/fighter.cpp
new file mode 100644
index 0000000000..fcd69183fb
--- /dev/null
+++ b/engines/lastexpress/fight/fighter.cpp
@@ -0,0 +1,248 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "lastexpress/fight/fighter.h"
+
+#include "lastexpress/data/sequence.h"
+
+#include "lastexpress/game/scenes.h"
+#include "lastexpress/game/sound.h"
+
+#include "lastexpress/helpers.h"
+#include "lastexpress/lastexpress.h"
+
+namespace LastExpress {
+
+Fighter::Fighter(LastExpressEngine *engine) : _engine(engine) {
+ _opponent = NULL;
+ _fight = NULL;
+
+ _sequenceIndex = 0;
+ _sequence = NULL;
+ _frame = NULL;
+ _frameIndex = 0;
+
+ _field_24 = 0;
+
+ _action = kFightAction101;
+ _sequenceIndex2 = 0;
+
+ _countdown = 1;
+
+ _field_34 = 0;
+}
+
+Fighter::~Fighter() {
+ clearSequences();
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Cleanup
+//////////////////////////////////////////////////////////////////////////
+void Fighter::clearSequences() {
+ // The original game resets the function pointers to default values, just before deleting the struct
+
+ getScenes()->removeAndRedraw(&_frame, false);
+
+ // Free sequences
+ for (int i = 0; i < (int)_sequences.size(); i++)
+ SAFE_DELETE(_sequences[i]);
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Drawing
+//////////////////////////////////////////////////////////////////////////
+void Fighter::setSequenceAndDraw(uint32 sequenceIndex, FightSequenceType type) {
+ if (_sequences.size() < sequenceIndex)
+ return;
+
+ switch (type) {
+ default:
+ break;
+
+ case kFightSequenceType0:
+ if (_sequenceIndex)
+ return;
+
+ _sequence = _sequences[sequenceIndex];
+ _sequenceIndex = sequenceIndex;
+ draw();
+ break;
+
+ case kFightSequenceType1:
+ _sequence = _sequences[sequenceIndex];
+ _sequenceIndex = sequenceIndex;
+ _sequenceIndex2 = 0;
+ draw();
+ break;
+
+ case kFightSequenceType2:
+ _sequenceIndex2 = sequenceIndex;
+ break;
+ }
+}
+
+void Fighter::draw() {
+ getScenes()->removeAndRedraw(&_frame, false);
+
+ _frameIndex = 0;
+ _field_24 = 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Processing
+//////////////////////////////////////////////////////////////////////////
+void Fighter::process() {
+ if (!_sequence) {
+ if (_frame) {
+ getScenes()->removeFromQueue(_frame);
+ getScenes()->setCoordinates(_frame);
+ }
+ SAFE_DELETE(_frame);
+ return;
+ }
+
+ if (_sequence->count() <= _frameIndex) {
+ switch(_action) {
+ default:
+ break;
+
+ case kFightAction101:
+ setSequenceAndDraw(_sequenceIndex2, kFightSequenceType1);
+ _sequenceIndex2 = 0;
+ break;
+
+ case kFightActionResetFrame:
+ _frameIndex = 0;
+ break;
+
+ case kFightAction103:
+ setSequenceAndDraw(0, kFightSequenceType1);
+ handleAction(kFightAction101);
+ _opponent->setSequenceAndDraw(0, kFightSequenceType1);
+ _opponent->handleAction(kFightAction101);
+ _opponent->update();
+ break;
+
+ case kFightActionWin:
+ _fight->bailout(Fight::kFightEndWin);
+ break;
+
+ case kFightActionLost:
+ _fight->bailout(Fight::kFightEndLost);
+ break;
+ }
+ }
+
+ if (_fight->isRunning()) {
+
+ // Get the current sequence frame
+ SequenceFrame *frame = new SequenceFrame(_sequence, (uint16)_frameIndex);
+ frame->getInfo()->location = 1;
+
+ if (_frame == frame) {
+ delete frame;
+ return;
+ }
+
+ getSound()->playFightSound(frame->getInfo()->soundAction, frame->getInfo()->field_31);
+
+ // Add current frame to queue and advance
+ getScenes()->addToQueue(frame);
+ _frameIndex++;
+
+ if (_frame) {
+ getScenes()->removeFromQueue(_frame);
+
+ if (!frame->getInfo()->field_2E)
+ getScenes()->setCoordinates(_frame);
+ }
+
+ // Replace by new frame
+ delete _frame;
+ _frame = frame;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Default actions
+//////////////////////////////////////////////////////////////////////////
+void Fighter::handleAction(FightAction action) {
+ switch (action) {
+ default:
+ return;
+
+ case kFightAction101:
+ break;
+
+ case kFightActionResetFrame:
+ _countdown--;
+ break;
+
+ case kFightAction103:
+ _opponent->handleAction(kFightActionResetFrame);
+ break;
+
+ case kFightActionWin:
+ _fight->setEndType(Fight::kFightEndWin);
+ _opponent->handleAction(kFightActionResetFrame);
+ break;
+
+ case kFightActionLost:
+ _fight->setEndType(Fight::kFightEndLost);
+ _opponent->handleAction(kFightActionResetFrame);
+ break;
+ }
+
+ // Update action
+ _action = action;
+}
+
+bool Fighter::canInteract(FightAction /*action = kFightActionNone*/ ) {
+ return (_action == kFightAction101 && !_sequenceIndex);
+}
+
+void Fighter::update() {
+ process();
+
+ if (_frame)
+ _frame->getInfo()->location = (_action == kFightActionResetFrame ? 2 : 0);
+}
+
+void Opponent::update() {
+ process();
+
+ if (_field_38 && !_sequenceIndex)
+ _field_38--;
+
+ if (_frame)
+ _frame->getInfo()->location = 1;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Helpers
+//////////////////////////////////////////////////////////////////////////
+bool Fighter::checkFrame(uint32 val) {
+ return (_frame->getInfo()->field_33 & val);
+}
+
+} // End of namespace LastExpress
diff --git a/engines/lastexpress/fight/fighter.h b/engines/lastexpress/fight/fighter.h
new file mode 100644
index 0000000000..e37fe49d86
--- /dev/null
+++ b/engines/lastexpress/fight/fighter.h
@@ -0,0 +1,123 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef LASTEXPRESS_FIGHTER_H
+#define LASTEXPRESS_FIGHTER_H
+
+#include "lastexpress/fight/fight.h"
+
+#include "common/array.h"
+
+namespace LastExpress {
+
+class Fight;
+class Sequence;
+class SequenceFrame;
+
+class Fighter {
+public:
+ enum FightAction {
+ kFightActionNone = 0,
+ kFightAction1 = 1,
+ kFightAction2 = 2,
+ kFightAction3 = 3,
+ kFightAction4 = 4,
+ kFightAction5 = 5,
+ kFightAction101 = 101,
+ kFightActionResetFrame = 102,
+ kFightAction103 = 103,
+ kFightActionWin = 104,
+ kFightActionLost = 105,
+ kFightAction128 = 128,
+ kFightAction129 = 129,
+ kFightAction130 = 130,
+ kFightAction131 = 131,
+ kFightAction132 = 132
+ };
+
+ enum FightSequenceType {
+ kFightSequenceType0 = 0,
+ kFightSequenceType1 = 1,
+ kFightSequenceType2 = 2
+ };
+
+ Fighter(LastExpressEngine *engine);
+ virtual ~Fighter();
+
+ // Default functions
+ virtual void handleAction(FightAction action);
+ virtual void update();
+ virtual bool canInteract(FightAction action = kFightActionNone);
+
+ // Drawing
+ void setSequenceAndDraw(uint32 sequenceIndex, FightSequenceType type);
+
+ // Accessors
+ void setOpponent(Fighter *opponent) { _opponent = opponent; }
+ void setCountdown(int32 countdown) { _countdown = countdown; }
+ void setFight(Fight *fight) { _fight = fight; }
+
+ int getCountdown() { return _countdown; }
+ uint32 getSequenceIndex() { return _sequenceIndex; }
+ uint32 getField34() { return _field_34; }
+
+protected:
+ LastExpressEngine *_engine;
+ Fight *_fight;
+ Fighter *_opponent;
+ Sequence *_sequence;
+ SequenceFrame *_frame;
+ uint32 _sequenceIndex;
+ Common::Array<Sequence *> _sequences;
+ uint32 _frameIndex;
+ uint32 _field_24;
+ FightAction _action;
+ uint32 _sequenceIndex2;
+ int32 _countdown; // countdown before loosing ?
+ uint32 _field_34;
+
+ // Drawing and processing
+ void draw();
+ void process();
+
+ // Cleanup
+ void clearSequences();
+
+ // Helpers
+ bool checkFrame(uint32 val);
+};
+
+class Opponent : public Fighter {
+public:
+ Opponent(LastExpressEngine *engine) : Fighter(engine) {
+ _field_38 = 0;
+ }
+
+ virtual void update();
+
+protected:
+ int32 _field_38;
+};
+
+} // End of namespace LastExpress
+
+#endif // LASTEXPRESS_FIGHTER_H
diff --git a/engines/lastexpress/fight/fighter_anna.cpp b/engines/lastexpress/fight/fighter_anna.cpp
new file mode 100644
index 0000000000..db2ab54c4b
--- /dev/null
+++ b/engines/lastexpress/fight/fighter_anna.cpp
@@ -0,0 +1,186 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "lastexpress/fight/fighter_anna.h"
+
+#include "lastexpress/data/sequence.h"
+
+#include "lastexpress/game/sound.h"
+
+#include "lastexpress/helpers.h"
+#include "lastexpress/lastexpress.h"
+#include "lastexpress/resource.h"
+
+namespace LastExpress {
+
+//////////////////////////////////////////////////////////////////////////
+// Player
+//////////////////////////////////////////////////////////////////////////
+FighterPlayerAnna::FighterPlayerAnna(LastExpressEngine *engine) : Fighter(engine) {
+ _sequences.push_back(loadSequence("2002cr.seq"));
+ _sequences.push_back(loadSequence("2002cdl.seq"));
+ _sequences.push_back(loadSequence("2002cdr.seq"));
+ _sequences.push_back(loadSequence("2002cdm.seq"));
+ _sequences.push_back(loadSequence("2002lbk.seq"));
+}
+
+void FighterPlayerAnna::handleAction(FightAction action) {
+ switch (action) {
+ default:
+ Fighter::handleAction(action);
+ return;
+
+ case kFightAction1:
+ if ((_sequenceIndex != 1 && _sequenceIndex != 3) || checkFrame(4)) {
+ setSequenceAndDraw(4, kFightSequenceType1);
+ _opponent->setSequenceAndDraw(4, kFightSequenceType1);
+
+ _opponent->handleAction(kFightAction103);
+ update();
+ } else {
+ _field_34++;
+ }
+ break;
+
+ case kFightAction2:
+ if ((_sequenceIndex != 2 && _sequenceIndex != 3) || checkFrame(4)) {
+ setSequenceAndDraw(4, kFightSequenceType1);
+ _opponent->setSequenceAndDraw(5, kFightSequenceType1);
+
+ _opponent->handleAction(kFightAction103);
+ update();
+ } else {
+ _field_34++;
+ }
+ break;
+
+ case kFightAction3:
+ if ((_sequenceIndex != 2 && _sequenceIndex != 1) || checkFrame(4)) {
+ setSequenceAndDraw(4, kFightSequenceType1);
+ _opponent->setSequenceAndDraw(6, kFightSequenceType1);
+
+ _opponent->handleAction(kFightAction103);
+ update();
+ } else {
+ _field_34++;
+ }
+ break;
+
+ case kFightAction128:
+ switch (_opponent->getSequenceIndex()) {
+ default:
+ setSequenceAndDraw(3, kFightSequenceType0);
+ break;
+
+ case 1:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ break;
+
+ case 2:
+ setSequenceAndDraw(3, kFightSequenceType0);
+ break;
+
+ case 3:
+ setSequenceAndDraw(2, kFightSequenceType0);
+ break;
+ }
+ break;
+ }
+
+ if (_field_34 > 4) {
+ getSound()->removeFromQueue(kEntityTables0);
+ _fight->bailout(Fight::kFightEndWin);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Opponent
+//////////////////////////////////////////////////////////////////////////
+FighterOpponentAnna::FighterOpponentAnna(LastExpressEngine *engine) : Opponent(engine) {
+ _sequences.push_back(loadSequence("2002or.seq"));
+ _sequences.push_back(loadSequence("2002oal.seq"));
+ _sequences.push_back(loadSequence("2002oam.seq"));
+ _sequences.push_back(loadSequence("2002oar.seq"));
+ _sequences.push_back(loadSequence("2002okr.seq"));
+ _sequences.push_back(loadSequence("2002okml.seq"));
+ _sequences.push_back(loadSequence("2002okm.seq"));
+
+ getSound()->playSound(kEntityTables0, "MUS030", SoundManager::kFlagDefault);
+
+ _field_38 = 30;
+}
+
+void FighterOpponentAnna::update() {
+ if (!_field_38 && canInteract(kFightAction1) && !_sequenceIndex2) {
+
+ if (_opponent->getField34() >= 2) {
+ switch (rnd(6)) {
+ default:
+ break;
+
+ case 0:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ break;
+
+ case 1:
+ setSequenceAndDraw(2, kFightSequenceType0);
+ break;
+
+ case 2:
+ setSequenceAndDraw(3, kFightSequenceType0);
+ break;
+
+ case 3:
+ setSequenceAndDraw(3, kFightSequenceType0);
+ setSequenceAndDraw(2, kFightSequenceType2);
+ break;
+
+ case 4:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ setSequenceAndDraw(2, kFightSequenceType2);
+ break;
+
+ case 5:
+ setSequenceAndDraw(3, kFightSequenceType0);
+ setSequenceAndDraw(2, kFightSequenceType2);
+ break;
+ }
+ }
+
+ // Update field_38
+ _field_38 = (int32)rnd(15);
+ }
+
+ if (_frame && checkFrame(2)) {
+ if (_sequenceIndex == 1 || _sequenceIndex == 2 || _sequenceIndex == 3)
+ _opponent->handleAction((FightAction)_sequenceIndex);
+
+ if (_opponent->getCountdown() <= 0) {
+ getSound()->removeFromQueue(kEntityTables0);
+ handleAction(kFightActionLost);
+ }
+ }
+
+ Fighter::update();
+}
+
+} // End of namespace LastExpress
diff --git a/engines/lastexpress/fight/fighter_anna.h b/engines/lastexpress/fight/fighter_anna.h
new file mode 100644
index 0000000000..abb6f9dc64
--- /dev/null
+++ b/engines/lastexpress/fight/fighter_anna.h
@@ -0,0 +1,48 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef LASTEXPRESS_FIGHTER_ANNA_H
+#define LASTEXPRESS_FIGHTER_ANNA_H
+
+#include "lastexpress/fight/fighter.h"
+
+namespace LastExpress {
+
+class LastExpressEngine;
+
+class FighterPlayerAnna : public Fighter {
+public:
+ FighterPlayerAnna(LastExpressEngine *engine);
+
+ virtual void handleAction(FightAction action);
+};
+
+class FighterOpponentAnna : public Opponent {
+public:
+ FighterOpponentAnna(LastExpressEngine *engine);
+
+ virtual void update();
+};
+
+} // End of namespace LastExpress
+
+#endif // LASTEXPRESS_FIGHTER_ANNA_H
diff --git a/engines/lastexpress/fight/fighter_ivo.cpp b/engines/lastexpress/fight/fighter_ivo.cpp
new file mode 100644
index 0000000000..423b6b4ce5
--- /dev/null
+++ b/engines/lastexpress/fight/fighter_ivo.cpp
@@ -0,0 +1,244 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "lastexpress/fight/fighter_ivo.h"
+
+#include "lastexpress/data/sequence.h"
+
+#include "lastexpress/game/sound.h"
+
+#include "lastexpress/helpers.h"
+#include "lastexpress/lastexpress.h"
+#include "lastexpress/resource.h"
+
+namespace LastExpress {
+
+//////////////////////////////////////////////////////////////////////////
+// Player
+//////////////////////////////////////////////////////////////////////////
+FighterPlayerIvo::FighterPlayerIvo(LastExpressEngine *engine) : Fighter(engine) {
+ _sequences.push_back(loadSequence("2003cr.seq"));
+ _sequences.push_back(loadSequence("2003car.seq"));
+ _sequences.push_back(loadSequence("2003cal.seq"));
+ _sequences.push_back(loadSequence("2003cdr.seq"));
+ _sequences.push_back(loadSequence("2003cdm.seq"));
+ _sequences.push_back(loadSequence("2003chr.seq"));
+ _sequences.push_back(loadSequence("2003chl.seq"));
+ _sequences.push_back(loadSequence("2003ckr.seq"));
+ _sequences.push_back(loadSequence("2003lbk.seq"));
+ _sequences.push_back(loadSequence("2003fbk.seq"));
+
+ _countdown = 5;
+}
+
+void FighterPlayerIvo::handleAction(FightAction action) {
+ switch (action) {
+ default:
+ Fighter::handleAction(action);
+ return;
+
+ case kFightAction1:
+ if (_sequenceIndex != 1 || checkFrame(4)) {
+ setSequenceAndDraw(7, kFightSequenceType1);
+ _opponent->setSequenceAndDraw(4, kFightSequenceType1);
+
+ _opponent->handleAction(kFightAction103);
+ update();
+ }
+ break;
+
+ case kFightAction2:
+ if ((_sequenceIndex != 2 && _sequenceIndex != 3) || checkFrame(4)) {
+ setSequenceAndDraw(7, kFightSequenceType1);
+ _opponent->setSequenceAndDraw(5, kFightSequenceType1);
+
+ _opponent->handleAction(kFightAction103);
+ update();
+ }
+ break;
+
+ case kFightAction128:
+ switch (_opponent->getSequenceIndex()) {
+ default:
+ case 1:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ break;
+
+ case 2:
+ setSequenceAndDraw(2, kFightSequenceType0);
+ break;
+ }
+ break;
+
+ case kFightAction129:
+ setSequenceAndDraw((_opponent->getCountdown() > 1) ? 4 : 3, _sequenceIndex ? kFightSequenceType2 : kFightSequenceType0);
+ break;
+
+ case kFightAction130:
+ setSequenceAndDraw(3, _sequenceIndex ? kFightSequenceType2 : kFightSequenceType0);
+ break;
+ }
+}
+
+void FighterPlayerIvo::update() {
+
+ if ((_sequenceIndex == 3 || _sequenceIndex == 4) && !_frameIndex)
+ _opponent->handleAction(kFightAction131);
+
+ if (_frame && checkFrame(2)) {
+
+ // Draw sequences
+ if (_opponent->getCountdown() <= 0) {
+ setSequenceAndDraw(9, kFightSequenceType1);
+ _opponent->setSequenceAndDraw(8, kFightSequenceType1);
+ getSound()->removeFromQueue(kEntityTables0);
+
+ handleAction(kFightActionWin);
+ return;
+ }
+
+ if (_sequenceIndex == 3 || _sequenceIndex == 4)
+ _opponent->handleAction((FightAction)_sequenceIndex);
+ }
+
+ Fighter::update();
+}
+
+bool FighterPlayerIvo::canInteract(FightAction action) {
+ if (action == kFightAction129 || action == kFightAction130)
+ return (_sequenceIndex >= 8);
+
+ return Fighter::canInteract();
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Opponent
+//////////////////////////////////////////////////////////////////////////
+FighterOpponentIvo::FighterOpponentIvo(LastExpressEngine *engine) : Opponent(engine) {
+ _sequences.push_back(loadSequence("2003or.seq"));
+ _sequences.push_back(loadSequence("2003oal.seq"));
+ _sequences.push_back(loadSequence("2003oar.seq"));
+ _sequences.push_back(loadSequence("2003odm.seq"));
+ _sequences.push_back(loadSequence("2003okl.seq"));
+ _sequences.push_back(loadSequence("2003okj.seq"));
+ _sequences.push_back(loadSequence("blank.seq"));
+ _sequences.push_back(loadSequence("csdr.seq"));
+ _sequences.push_back(loadSequence("2003l.seq"));
+
+ getSound()->playSound(kEntityTables0, "MUS032", SoundManager::kFlagDefault);
+
+ _countdown = 5;
+ _field_38 = 15;
+}
+
+void FighterOpponentIvo::handleAction(FightAction action) {
+ switch (action) {
+ default:
+ Fighter::handleAction(action);
+ break;
+
+ case kFightAction3:
+ if ((_sequenceIndex != 1 && _sequenceIndex != 3) || checkFrame(4)) {
+ setSequenceAndDraw(6, kFightSequenceType1);
+ _opponent->setSequenceAndDraw(6, kFightSequenceType1);
+ _opponent->handleAction(kFightAction103);
+ }
+ break;
+
+ case kFightAction4:
+ if ((_sequenceIndex != 2 && _sequenceIndex != 3) || checkFrame(4)) {
+ setSequenceAndDraw(6, kFightSequenceType1);
+ _opponent->setSequenceAndDraw(5, kFightSequenceType1);
+ _opponent->handleAction(kFightAction103);
+ }
+ break;
+
+ case kFightAction131:
+ if (_sequenceIndex)
+ break;
+
+ if (rnd(100) <= (unsigned int)(_countdown > 2 ? 60 : 75)) {
+ setSequenceAndDraw(3 , kFightSequenceType1);
+ if (_opponent->getSequenceIndex() == 4)
+ setSequenceAndDraw(2, kFightSequenceType2);
+ }
+ break;
+ }
+}
+
+void FighterOpponentIvo::update() {
+ if (!_field_38 && canInteract(kFightAction1) && !_sequenceIndex2) {
+
+ if (_opponent->getField34() >= 2) {
+ switch (rnd(5)) {
+ default:
+ break;
+
+ case 0:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ break;
+
+ case 1:
+ setSequenceAndDraw(2, kFightSequenceType0);
+ break;
+
+ case 2:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ setSequenceAndDraw(2, kFightSequenceType2);
+ break;
+
+ case 3:
+ setSequenceAndDraw(0, kFightSequenceType2);
+ setSequenceAndDraw(1, kFightSequenceType2);
+ break;
+
+ case 4:
+ setSequenceAndDraw(0, kFightSequenceType1);
+ setSequenceAndDraw(1, kFightSequenceType2);
+ break;
+ }
+ }
+
+ // Update field_38
+ _field_38 = 3 * _countdown + (int32)rnd(10);
+ }
+
+ if (_frame && checkFrame(2)) {
+
+ if (_opponent->getCountdown() <= 0) {
+ setSequenceAndDraw(7, kFightSequenceType1);
+ _opponent->setSequenceAndDraw(8, kFightSequenceType1);
+ getSound()->removeFromQueue(kEntityTables0);
+
+ _opponent->handleAction(kFightActionWin);
+
+ return;
+ }
+
+ if (_sequenceIndex == 1 || _sequenceIndex == 2)
+ _opponent->handleAction((FightAction)_sequenceIndex);
+ }
+
+ Fighter::update();
+}
+
+} // End of namespace LastExpress
diff --git a/engines/lastexpress/fight/fighter_ivo.h b/engines/lastexpress/fight/fighter_ivo.h
new file mode 100644
index 0000000000..ca54fea904
--- /dev/null
+++ b/engines/lastexpress/fight/fighter_ivo.h
@@ -0,0 +1,51 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef LASTEXPRESS_FIGHTER_IVO_H
+#define LASTEXPRESS_FIGHTER_IVO_H
+
+#include "lastexpress/fight/fighter.h"
+
+namespace LastExpress {
+
+class LastExpressEngine;
+
+class FighterPlayerIvo : public Fighter {
+public:
+ FighterPlayerIvo(LastExpressEngine *engine);
+
+ virtual void handleAction(FightAction action);
+ virtual void update();
+ virtual bool canInteract(FightAction action = kFightActionNone);
+};
+
+class FighterOpponentIvo : public Opponent {
+public:
+ FighterOpponentIvo(LastExpressEngine *engine);
+
+ virtual void handleAction(FightAction action);
+ virtual void update();
+};
+
+} // End of namespace LastExpress
+
+#endif // LASTEXPRESS_FIGHTER_IVO_H
diff --git a/engines/lastexpress/fight/fighter_milos.cpp b/engines/lastexpress/fight/fighter_milos.cpp
new file mode 100644
index 0000000000..46e4bde7a6
--- /dev/null
+++ b/engines/lastexpress/fight/fighter_milos.cpp
@@ -0,0 +1,221 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "lastexpress/fight/fighter_milos.h"
+
+#include "lastexpress/data/cursor.h"
+#include "lastexpress/data/sequence.h"
+
+#include "lastexpress/game/sound.h"
+
+#include "lastexpress/helpers.h"
+#include "lastexpress/lastexpress.h"
+#include "lastexpress/resource.h"
+
+namespace LastExpress {
+
+//////////////////////////////////////////////////////////////////////////
+// Player
+//////////////////////////////////////////////////////////////////////////
+FighterPlayerMilos::FighterPlayerMilos(LastExpressEngine *engine) : Fighter(engine) {
+ _sequences.push_back(loadSequence("2001cr.seq"));
+ _sequences.push_back(loadSequence("2001cdl.seq"));
+ _sequences.push_back(loadSequence("2001cdr.seq"));
+ _sequences.push_back(loadSequence("2001cdm.seq"));
+ _sequences.push_back(loadSequence("2001csgr.seq"));
+ _sequences.push_back(loadSequence("2001csgl.seq"));
+ _sequences.push_back(loadSequence("2001dbk.seq"));
+}
+
+void FighterPlayerMilos::handleAction(FightAction action) {
+ switch (action) {
+ default:
+ Fighter::handleAction(action);
+ return;
+
+ case kFightAction1:
+ if (_sequenceIndex != 1 || checkFrame(4)) {
+ setSequenceAndDraw(6, kFightSequenceType1);
+ _opponent->setSequenceAndDraw(3, kFightSequenceType1);
+
+ _opponent->handleAction(kFightAction103);
+ update();
+ } else {
+ _field_34++;
+ }
+ break;
+
+ case kFightAction2:
+ if ((_sequenceIndex != 2 && _sequenceIndex != 3) || checkFrame(4)) {
+ setSequenceAndDraw(6, kFightSequenceType1);
+ _opponent->setSequenceAndDraw(4, kFightSequenceType1);
+
+ _opponent->handleAction(kFightAction103);
+ update();
+ } else {
+ _field_34++;
+ }
+ break;
+
+ case kFightAction128:
+ if (_sequenceIndex != 1 || checkFrame(4) || _opponent->getSequenceIndex() != 1) {
+ switch (_opponent->getSequenceIndex()) {
+ default:
+ setSequenceAndDraw(rnd(3) + 1, kFightSequenceType0);
+ break;
+
+ case 1:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ break;
+
+ case 2:
+ setSequenceAndDraw(3, kFightSequenceType0);
+ break;
+ }
+ } else {
+ setSequenceAndDraw(4, kFightSequenceType1);
+ update();
+ }
+ break;
+ }
+}
+
+void FighterPlayerMilos::update() {
+ if (_frame && checkFrame(2)) {
+
+ // Draw sequences
+ if (_opponent->getCountdown() <= 0) {
+ setSequenceAndDraw(5, kFightSequenceType1);
+ _opponent->setSequenceAndDraw(6, kFightSequenceType1);
+
+ getSound()->removeFromQueue(kEntityTables0);
+ getSound()->playSound(kEntityTrain, "MUS029", SoundManager::kFlagDefault);
+
+ handleAction(kFightActionWin);
+ }
+
+ if (_sequenceIndex == 4) {
+ _opponent->handleAction(kFightAction4);
+ _fight->setEndType(Fight::kFightEndLost);
+ }
+ }
+
+ Fighter::update();
+}
+
+bool FighterPlayerMilos::canInteract(FightAction action) {
+ if (action != kFightAction128
+ || _sequenceIndex != 1
+ || !_frame
+ || checkFrame(4)
+ || _opponent->getSequenceIndex() != 1) {
+ return Fighter::canInteract();
+ }
+
+ _engine->getCursor()->setStyle(kCursorHand);
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Opponent
+//////////////////////////////////////////////////////////////////////////
+FighterOpponentMilos::FighterOpponentMilos(LastExpressEngine *engine) : Opponent(engine) {
+ _sequences.push_back(loadSequence("2001or.seq"));
+ _sequences.push_back(loadSequence("2001oal.seq"));
+ _sequences.push_back(loadSequence("2001oam.seq"));
+ _sequences.push_back(loadSequence("2001okl.seq"));
+ _sequences.push_back(loadSequence("2001okm.seq"));
+ _sequences.push_back(loadSequence("2001dbk.seq"));
+ _sequences.push_back(loadSequence("2001wbk.seq"));
+
+ getSound()->playSound(kEntityTables0, "MUS027", SoundManager::kFlagDefault);
+
+ _field_38 = 35;
+}
+
+void FighterOpponentMilos::handleAction(FightAction action) {
+ if (action == kFightAction4) {
+ setSequenceAndDraw(5, kFightSequenceType1);
+ _opponent->handleAction(kFightAction103);
+ } else {
+ if (action != kFightAction131)
+ Fighter::handleAction(action);
+ }
+}
+
+void FighterOpponentMilos::update() {
+ if (!_field_38 && canInteract(kFightAction1) && !_sequenceIndex2) {
+
+ if (_opponent->getField34() >= 2) {
+ switch (rnd(5)) {
+ default:
+ break;
+
+ case 0:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ break;
+
+ case 1:
+ setSequenceAndDraw(2, kFightSequenceType0);
+ break;
+
+ case 2:
+ setSequenceAndDraw(2, kFightSequenceType0);
+ setSequenceAndDraw(2, kFightSequenceType1);
+ break;
+
+ case 3:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ setSequenceAndDraw(2, kFightSequenceType2);
+ break;
+
+ case 4:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ setSequenceAndDraw(1, kFightSequenceType2);
+ break;
+ }
+ } else {
+ setSequenceAndDraw(2, kFightSequenceType0);
+ }
+
+ // Update field_38
+ if (_opponent->getField34() < 5)
+ _field_38 = 6 * (5 - _opponent->getField34());
+ else
+ _field_38 = 0;
+ }
+
+ if (_frame && checkFrame(2)) {
+ if (_sequenceIndex == 1 || _sequenceIndex == 2)
+ _opponent->handleAction((FightAction)_sequenceIndex);
+
+ if (_opponent->getCountdown() <= 0) {
+ getSound()->removeFromQueue(kEntityTables0);
+ handleAction(kFightActionLost);
+ }
+ }
+
+ Fighter::update();
+}
+
+} // End of namespace LastExpress
diff --git a/engines/lastexpress/fight/fighter_milos.h b/engines/lastexpress/fight/fighter_milos.h
new file mode 100644
index 0000000000..2126dd1838
--- /dev/null
+++ b/engines/lastexpress/fight/fighter_milos.h
@@ -0,0 +1,51 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef LASTEXPRESS_FIGHTER_MILOS_H
+#define LASTEXPRESS_FIGHTER_MILOS_H
+
+#include "lastexpress/fight/fighter.h"
+
+namespace LastExpress {
+
+class LastExpressEngine;
+
+class FighterPlayerMilos : public Fighter {
+public:
+ FighterPlayerMilos(LastExpressEngine *engine);
+
+ virtual void handleAction(FightAction action);
+ virtual void update();
+ virtual bool canInteract(FightAction action = kFightActionNone);
+};
+
+class FighterOpponentMilos : public Opponent {
+public:
+ FighterOpponentMilos(LastExpressEngine *engine);
+
+ virtual void handleAction(FightAction action);
+ virtual void update();
+};
+
+} // End of namespace LastExpress
+
+#endif // LASTEXPRESS_FIGHTER_MILOS_H
diff --git a/engines/lastexpress/fight/fighter_salko.cpp b/engines/lastexpress/fight/fighter_salko.cpp
new file mode 100644
index 0000000000..795dd41b93
--- /dev/null
+++ b/engines/lastexpress/fight/fighter_salko.cpp
@@ -0,0 +1,201 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "lastexpress/fight/fighter_salko.h"
+
+#include "lastexpress/data/cursor.h"
+#include "lastexpress/data/sequence.h"
+
+#include "lastexpress/game/sound.h"
+
+#include "lastexpress/helpers.h"
+#include "lastexpress/lastexpress.h"
+#include "lastexpress/resource.h"
+
+namespace LastExpress {
+
+//////////////////////////////////////////////////////////////////////////
+// Player
+//////////////////////////////////////////////////////////////////////////
+FighterPlayerSalko::FighterPlayerSalko(LastExpressEngine *engine) : Fighter(engine) {
+ _sequences.push_back(loadSequence("2004cr.seq"));
+ _sequences.push_back(loadSequence("2004cdr.seq"));
+ _sequences.push_back(loadSequence("2004chj.seq"));
+ _sequences.push_back(loadSequence("2004bk.seq"));
+
+ _countdown = 2;
+}
+
+void FighterPlayerSalko::handleAction(FightAction action) {
+ switch (action) {
+ default:
+ Fighter::handleAction(action);
+ return;
+
+ case kFightAction1:
+ case kFightAction2:
+ if (_sequenceIndex != 1 && checkFrame(4)) {
+ _field_34 = 0;
+
+ setSequenceAndDraw(3, kFightSequenceType1);
+ _opponent->setSequenceAndDraw((action == kFightAction1 ? 3 : 4), kFightSequenceType1);
+
+ _opponent->handleAction(kFightAction103);
+
+ if (action == kFightAction2)
+ _countdown= 0;
+
+ update();
+ } else {
+ _field_34++;
+ }
+ break;
+
+ case kFightAction5:
+ if (_sequenceIndex != 3) {
+ _opponent->handleAction(kFightAction103);
+ update();
+ }
+ break;
+
+ case kFightAction128:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ _field_34 = 0;
+ break;
+
+ case kFightAction131:
+ setSequenceAndDraw(2, (_sequenceIndex ? kFightSequenceType2 : kFightSequenceType0));
+ break;
+ }
+}
+
+void FighterPlayerSalko::update() {
+ Fighter::update();
+
+ // The original doesn't check for currentSequence2 != NULL (might not happen when everything is working properly, but crashes with our current implementation)
+ if (_frame && checkFrame(2)) {
+
+ if (_opponent->getCountdown() <= 0) {
+ getSound()->removeFromQueue(kEntityTables0);
+ _fight->bailout(Fight::kFightEndWin);
+
+ return;
+ }
+
+ if (_sequenceIndex == 2)
+ _opponent->handleAction(kFightAction2);
+ }
+}
+
+bool FighterPlayerSalko::canInteract(FightAction action) {
+ if (action == kFightAction131) {
+ if (_sequenceIndex == 1) {
+ if (_opponent->getCountdown() <= 0)
+ _engine->getCursor()->setStyle(kCursorHand);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ return Fighter::canInteract();
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Opponent
+//////////////////////////////////////////////////////////////////////////
+FighterOpponentSalko::FighterOpponentSalko(LastExpressEngine *engine) : Opponent(engine) {
+ _sequences.push_back(loadSequence("2004or.seq"));
+ _sequences.push_back(loadSequence("2004oam.seq"));
+ _sequences.push_back(loadSequence("2004oar.seq"));
+ _sequences.push_back(loadSequence("2004okr.seq"));
+ _sequences.push_back(loadSequence("2004ohm.seq"));
+ _sequences.push_back(loadSequence("blank.seq"));
+
+ getSound()->playSound(kEntityTables0, "MUS035", SoundManager::kFlagDefault);
+
+ _countdown = 3;
+ _field_38 = 30;
+}
+
+void FighterOpponentSalko::handleAction(FightAction action) {
+ if (action == kFightAction2) {
+ setSequenceAndDraw(5, kFightSequenceType1);
+ _opponent->handleAction(kFightAction103);
+ } else {
+ Fighter::handleAction(action);
+ }
+}
+
+void FighterOpponentSalko::update() {
+ if (!_field_38 && canInteract(kFightAction1) && !_sequenceIndex2) {
+
+ switch (rnd(5)) {
+ default:
+ break;
+
+ case 0:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ break;
+
+ case 1:
+ setSequenceAndDraw(2, kFightSequenceType0);
+ break;
+
+ case 2:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ setSequenceAndDraw(2, kFightSequenceType2);
+ break;
+
+ case 3:
+ setSequenceAndDraw(2, kFightSequenceType0);
+ setSequenceAndDraw(1, kFightSequenceType2);
+ break;
+
+ case 4:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ setSequenceAndDraw(1, kFightSequenceType2);
+ break;
+ }
+
+ // Update field_38
+ _field_38 = 4 * _countdown;
+ }
+
+ if (_frame && checkFrame(2)) {
+ if (_opponent->getCountdown() <= 0) {
+ getSound()->removeFromQueue(kEntityTables0);
+ _fight->bailout(Fight::kFightEndLost);
+
+ // Stop processing
+ return;
+ }
+
+ if (_sequenceIndex == 1 || _sequenceIndex == 2)
+ _opponent->handleAction((FightAction)_sequenceIndex);
+ }
+
+ Fighter::update();
+}
+
+} // End of namespace LastExpress
diff --git a/engines/lastexpress/fight/fighter_salko.h b/engines/lastexpress/fight/fighter_salko.h
new file mode 100644
index 0000000000..0a2a615867
--- /dev/null
+++ b/engines/lastexpress/fight/fighter_salko.h
@@ -0,0 +1,51 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef LASTEXPRESS_FIGHTER_SALKO_H
+#define LASTEXPRESS_FIGHTER_SALKO_H
+
+#include "lastexpress/fight/fighter.h"
+
+namespace LastExpress {
+
+class LastExpressEngine;
+
+class FighterPlayerSalko : public Fighter {
+public:
+ FighterPlayerSalko(LastExpressEngine *engine);
+
+ virtual void handleAction(FightAction action);
+ virtual void update();
+ virtual bool canInteract(FightAction action = kFightActionNone);
+};
+
+class FighterOpponentSalko : public Opponent {
+public:
+ FighterOpponentSalko(LastExpressEngine *engine);
+
+ virtual void handleAction(FightAction action);
+ virtual void update();
+};
+
+} // End of namespace LastExpress
+
+#endif // LASTEXPRESS_FIGHTER_SALKO_H
diff --git a/engines/lastexpress/fight/fighter_vesna.cpp b/engines/lastexpress/fight/fighter_vesna.cpp
new file mode 100644
index 0000000000..a2460106b0
--- /dev/null
+++ b/engines/lastexpress/fight/fighter_vesna.cpp
@@ -0,0 +1,264 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "lastexpress/fight/fighter_vesna.h"
+
+#include "lastexpress/data/cursor.h"
+#include "lastexpress/data/sequence.h"
+
+#include "lastexpress/game/sound.h"
+
+#include "lastexpress/helpers.h"
+#include "lastexpress/lastexpress.h"
+#include "lastexpress/resource.h"
+
+namespace LastExpress {
+
+//////////////////////////////////////////////////////////////////////////
+// Player
+//////////////////////////////////////////////////////////////////////////
+FighterPlayerVesna::FighterPlayerVesna(LastExpressEngine *engine) : Fighter(engine) {
+ _sequences.push_back(loadSequence("2005cr.seq"));
+ _sequences.push_back(loadSequence("2005cdr.seq"));
+ _sequences.push_back(loadSequence("2005cbr.seq"));
+ _sequences.push_back(loadSequence("2005bk.seq"));
+ _sequences.push_back(loadSequence("2005cdm1.seq"));
+ _sequences.push_back(loadSequence("2005chl.seq"));
+}
+
+void FighterPlayerVesna::handleAction(FightAction action) {
+ switch (action) {
+ default:
+ Fighter::handleAction(action);
+ return;
+
+ case kFightAction1:
+ if (_sequenceIndex != 1) {
+ _opponent->handleAction(kFightAction103);
+ update();
+ } else {
+ _field_34++;
+ }
+ break;
+
+ case kFightAction2:
+ if (_sequenceIndex != 2) {
+ _opponent->handleAction(kFightAction103);
+ update();
+ } else {
+ _field_34++;
+ }
+ break;
+
+ case kFightAction5:
+ if (_sequenceIndex != 3) {
+ _opponent->handleAction(kFightAction103);
+ update();
+ }
+ break;
+
+ case kFightAction128:
+ if (_sequenceIndex == 1 && _opponent->getSequenceIndex() == 1 && checkFrame(4)) {
+ setSequenceAndDraw(5, kFightSequenceType1);
+ } else {
+ setSequenceAndDraw((_opponent->getSequenceIndex() == 5) ? 3 : 1, kFightSequenceType0);
+ }
+ break;
+
+ case kFightAction132:
+ setSequenceAndDraw(2, kFightSequenceType0);
+ break;
+ }
+
+ if (_field_34 > 10) {
+ _opponent->setSequenceAndDraw(5, kFightSequenceType2);
+ _opponent->setCountdown(1);
+ _field_34 = 0;
+ }
+}
+
+void FighterPlayerVesna::update() {
+ if (_frame && checkFrame(2)) {
+
+ if (_sequenceIndex == 3)
+ _opponent->handleAction(kFightAction3);
+
+ if (_opponent->getCountdown() <= 0) {
+ getSound()->removeFromQueue(kEntityTables0);
+ _fight->bailout(Fight::kFightEndWin);
+ return;
+ }
+
+ if (_sequenceIndex == 5)
+ _opponent->handleAction(kFightAction5);
+ }
+
+ Fighter::update();
+}
+
+bool FighterPlayerVesna::canInteract(FightAction action) {
+ if (action != kFightAction128)
+ return Fighter::canInteract();
+
+ if (_sequenceIndex != 1) {
+
+ if (_opponent->getSequenceIndex() == 5) {
+ _engine->getCursor()->setStyle(kCursorDown);
+ return true;
+ }
+
+ return Fighter::canInteract();
+ }
+
+ if (_opponent->getSequenceIndex() == 1 && checkFrame(4)) {
+ _engine->getCursor()->setStyle(kCursorPunchLeft);
+ return true;
+ }
+
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Opponent
+//////////////////////////////////////////////////////////////////////////
+FighterOpponentVesna::FighterOpponentVesna(LastExpressEngine *engine) : Opponent(engine) {
+ _sequences.push_back(loadSequence("2005or.seq"));
+ _sequences.push_back(loadSequence("2005oam.seq"));
+ _sequences.push_back(loadSequence("2005oar.seq"));
+ _sequences.push_back(loadSequence("2005okml.seq"));
+ _sequences.push_back(loadSequence("2005okr.seq"));
+ _sequences.push_back(loadSequence("2005odm1.seq"));
+ _sequences.push_back(loadSequence("2005csbm.seq"));
+ _sequences.push_back(loadSequence("2005oam4.seq"));
+
+ getSound()->playSound(kEntityTables0, "MUS038", SoundManager::kFlagDefault);
+
+ _countdown = 4;
+ _field_38 = 30;
+}
+
+void FighterOpponentVesna::handleAction(FightAction action) {
+ switch (action) {
+ default:
+ Fighter::handleAction(action);
+ break;
+
+ case kFightAction3:
+ _opponent->handleAction(kFightAction103);
+ break;
+
+ case kFightAction5:
+ setSequenceAndDraw(7, kFightSequenceType1);
+ _opponent->handleAction(kFightAction103);
+ if (_countdown <= 1)
+ _countdown = 1;
+ break;
+
+ case kFightAction131:
+ break;
+ }
+}
+
+void FighterOpponentVesna::update() {
+ if (!_field_38 && canInteract(kFightAction1) && !_sequenceIndex2) {
+
+ if (_opponent->getField34() == 1) {
+ setSequenceAndDraw(2, kFightSequenceType0);
+ } else {
+ switch (rnd(6)) {
+ default:
+ break;
+
+ case 0:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ break;
+
+ case 1:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ setSequenceAndDraw(1, kFightSequenceType2);
+ break;
+
+ case 2:
+ setSequenceAndDraw(2, kFightSequenceType0);
+ break;
+
+ case 3:
+ setSequenceAndDraw(2, kFightSequenceType0);
+ setSequenceAndDraw(2, kFightSequenceType2);
+ break;
+
+ case 4:
+ setSequenceAndDraw(1, kFightSequenceType0);
+ setSequenceAndDraw(2, kFightSequenceType2);
+ break;
+
+ case 5:
+ setSequenceAndDraw(2, kFightSequenceType0);
+ setSequenceAndDraw(1, kFightSequenceType2);
+ break;
+ }
+ }
+
+ // Update field_38
+ _field_38 = 4 * _countdown;
+ }
+
+ if (_frame && checkFrame(2)) {
+ if (_sequenceIndex == 1 || _sequenceIndex == 2 || _sequenceIndex == 5)
+ _opponent->handleAction((FightAction)_sequenceIndex);
+
+ if (_opponent->getCountdown() <= 0) {
+
+ switch (_sequenceIndex) {
+ default:
+ break;
+
+ case 1:
+ setSequenceAndDraw(3, kFightSequenceType1);
+ break;
+
+ case 2:
+ setSequenceAndDraw(4, kFightSequenceType1);
+ break;
+
+ case 5:
+ setSequenceAndDraw(6, kFightSequenceType1);
+ break;
+ }
+
+ _opponent->setSequenceAndDraw(4, kFightSequenceType1);
+
+ handleAction(kFightActionLost);
+ _opponent->update();
+ Fighter::update();
+
+ getSound()->removeFromQueue(kEntityTables0);
+
+ // Stop processing
+ return;
+ }
+ }
+
+ Fighter::update();
+}
+
+} // End of namespace LastExpress
diff --git a/engines/lastexpress/fight/fighter_vesna.h b/engines/lastexpress/fight/fighter_vesna.h
new file mode 100644
index 0000000000..5c8ec855ae
--- /dev/null
+++ b/engines/lastexpress/fight/fighter_vesna.h
@@ -0,0 +1,51 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef LASTEXPRESS_FIGHTER_VESNA_H
+#define LASTEXPRESS_FIGHTER_VESNA_H
+
+#include "lastexpress/fight/fighter.h"
+
+namespace LastExpress {
+
+class LastExpressEngine;
+
+class FighterPlayerVesna : public Fighter {
+public:
+ FighterPlayerVesna(LastExpressEngine *engine);
+
+ virtual void handleAction(FightAction action);
+ virtual void update();
+ virtual bool canInteract(FightAction action = kFightActionNone);
+};
+
+class FighterOpponentVesna : public Opponent {
+public:
+ FighterOpponentVesna(LastExpressEngine *engine);
+
+ virtual void handleAction(FightAction action);
+ virtual void update();
+};
+
+} // End of namespace LastExpress
+
+#endif // LASTEXPRESS_FIGHTER_VESNA_H
diff --git a/engines/lastexpress/game/fight.cpp b/engines/lastexpress/game/fight.cpp
deleted file mode 100644
index ecc43bed2b..0000000000
--- a/engines/lastexpress/game/fight.cpp
+++ /dev/null
@@ -1,1583 +0,0 @@
-/* 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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "lastexpress/game/fight.h"
-
-#include "lastexpress/data/cursor.h"
-#include "lastexpress/data/scene.h"
-#include "lastexpress/data/sequence.h"
-
-#include "lastexpress/game/entities.h"
-#include "lastexpress/game/inventory.h"
-#include "lastexpress/game/logic.h"
-#include "lastexpress/game/object.h"
-#include "lastexpress/game/scenes.h"
-#include "lastexpress/game/sound.h"
-#include "lastexpress/game/state.h"
-
-#include "lastexpress/graphics.h"
-#include "lastexpress/helpers.h"
-#include "lastexpress/lastexpress.h"
-#include "lastexpress/resource.h"
-
-#include "common/func.h"
-
-namespace LastExpress {
-
-#define CALL_FUNCTION0(fighter, name) \
- (*fighter->name)(fighter)
-
-#define CALL_FUNCTION1(fighter, name, a) \
- (*fighter->name)(fighter, a)
-
-#define REGISTER_PLAYER_FUNCTIONS(name) \
- if (!_data) \
- error("Fight::load##namePlayer - invalid data!"); \
- _data->player->handleAction = new Common::Functor2Mem<Fighter *, FightAction, void, Fight>(this, &Fight::handleAction##name); \
- _data->player->update = new Common::Functor1Mem<Fighter *, void, Fight>(this, &Fight::update##name); \
- _data->player->canInteract = new Common::Functor2Mem<Fighter const *, FightAction, bool, Fight>(this, &Fight::canInteract##name);
-
-#define REGISTER_OPPONENT_FUNCTIONS(name) \
- if (!_data) \
- error("Fight::load##nameOpponent - invalid data!"); \
- _data->opponent->handleAction = new Common::Functor2Mem<Fighter *, FightAction, void, Fight>(this, &Fight::handleOpponentAction##name); \
- _data->opponent->update = new Common::Functor1Mem<Fighter *, void, Fight>(this, &Fight::updateOpponent##name); \
- _data->opponent->canInteract = new Common::Functor2Mem<Fighter const *, FightAction, bool, Fight>(this, &Fight::canInteract);
-
-#define CHECK_SEQUENCE2(fighter, value) \
- (fighter->frame->getInfo()->field_33 & value)
-
-Fight::Fight(LastExpressEngine *engine) : _engine(engine), _data(NULL), _endType(kFightEndLost), _state(0), _handleTimer(false) {}
-
-Fight::~Fight() {
- clearData();
- _data = NULL;
-
- // Zero passed pointers
- _engine = NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Events
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::eventMouse(const Common::Event &ev) {
- if (!_data || _data->index)
- return;
-
- // TODO move all the egg handling to inventory functions
-
- getFlags()->mouseLeftClick = false;
- getFlags()->shouldRedraw = false;
- getFlags()->mouseRightClick = false;
-
- if (ev.mouse.x < 608 || ev.mouse.y < 448 || ev.mouse.x >= 640 || ev.mouse.x >= 480) {
-
- // Handle right button click
- if (ev.type == Common::EVENT_RBUTTONUP) {
- getSound()->removeFromQueue(kEntityTables0);
- setStopped();
-
- getGlobalTimer() ? _state = 0 : ++_state;
-
- getFlags()->mouseRightClick = true;
- }
-
- if (_handleTimer) {
- // Timer expired => show with full brightness
- if (!getGlobalTimer())
- getInventory()->drawBlinkingEgg();
-
- _handleTimer = false;
- }
-
- // Check hotspots
- Scene *scene = getScenes()->get(getState()->scene);
- SceneHotspot *hotspot = NULL;
-
- if (!scene->checkHotSpot(ev.mouse, &hotspot)) {
- _engine->getCursor()->setStyle(kCursorNormal);
- } else {
- _engine->getCursor()->setStyle((CursorStyle)hotspot->cursor);
-
- // Call player function
- if (CALL_FUNCTION1(_data->player, canInteract, (FightAction)hotspot->action)) {
- if (ev.type == Common::EVENT_LBUTTONUP)
- CALL_FUNCTION1(_data->player, handleAction, (FightAction)hotspot->action);
- } else {
- _engine->getCursor()->setStyle(kCursorNormal);
- }
- }
- } else {
- // Handle clicks on menu icon
-
- if (!_handleTimer) {
- // Timer expired => show with full brightness
- if (!getGlobalTimer())
- getInventory()->drawBlinkingEgg();
-
- _handleTimer = true;
- }
-
- // Stop fight if clicked
- if (ev.type == Common::EVENT_LBUTTONUP) {
- _handleTimer = false;
- getSound()->removeFromQueue(kEntityTables0);
- bailout(kFightEndExit);
- }
-
- // Reset timer on right click
- if (ev.type == Common::EVENT_RBUTTONUP) {
- if (getGlobalTimer()) {
- if (getSound()->isBuffered("TIMER"))
- getSound()->removeFromQueue("TIMER");
-
- setGlobalTimer(900);
- }
- }
- }
-
- getFlags()->shouldRedraw = true;
-}
-
-void Fight::eventTick(const Common::Event &ev) {
- handleTick(ev, true);
-}
-
-void Fight::handleTick(const Common::Event &ev, bool isProcessing) {
- // TODO move all the egg handling to inventory functions
-
- // Blink egg
- if (getGlobalTimer()) {
- warning("Fight::handleMouseMove - egg blinking not implemented!");
- }
-
- if (!_data || _data->index)
- return;
-
- SceneHotspot *hotspot = NULL;
- if (!getScenes()->get(getState()->scene)->checkHotSpot(ev.mouse, &hotspot) || !CALL_FUNCTION1(_data->player, canInteract, (FightAction)hotspot->action)) {
- _engine->getCursor()->setStyle(kCursorNormal);
- } else {
- _engine->getCursor()->setStyle((CursorStyle)hotspot->cursor);
- }
-
- CALL_FUNCTION0(_data->player, update);
- CALL_FUNCTION0(_data->opponent, update);
-
- // Draw sequences
- if (!_data->isRunning)
- return;
-
- if (isProcessing)
- getScenes()->drawFrames(true);
-
- if (_data->index) {
- // Set next sequence name index
- _data->index--;
- _data->sequences[_data->index] = loadSequence(_data->names[_data->index]);
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Setup
-//////////////////////////////////////////////////////////////////////////
-
-Fight::FightEndType Fight::setup(FightType type) {
- if (_data)
- error("Fight::setup - calling fight setup again while a fight is already in progress!");
-
- //////////////////////////////////////////////////////////////////////////
- // Prepare UI & state
- if (_state >= 5 && (type == kFightSalko || type == kFightVesna)) {
- _state = 0;
- return kFightEndWin;
- }
-
- getInventory()->showHourGlass();
- // TODO events function
- getFlags()->flag_0 = false;
- getFlags()->mouseRightClick = false;
- getEntities()->reset();
-
- // Compute scene to use
- SceneIndex sceneIndex;
- switch(type) {
- default:
- sceneIndex = kSceneFightDefault;
- break;
-
- case kFightMilos:
- sceneIndex = (getObjects()->get(kObjectCompartment1).location2 < kObjectLocation3) ? kSceneFightMilos : kSceneFightMilosBedOpened;
- break;
-
- case kFightAnna:
- sceneIndex = kSceneFightAnna;
- break;
-
- case kFightIvo:
- sceneIndex = kSceneFightIvo;
- break;
-
- case kFightSalko:
- sceneIndex = kSceneFightSalko;
- break;
-
- case kFightVesna:
- sceneIndex = kSceneFightVesna;
- break;
- }
-
- if (getFlags()->shouldRedraw) {
- getFlags()->shouldRedraw = false;
- askForRedraw();
- //redrawScreen();
- }
-
- // Load the scene object
- Scene *scene = getScenes()->get(sceneIndex);
-
- // Update game entities and state
- getEntityData(kEntityPlayer)->entityPosition = scene->entityPosition;
- getEntityData(kEntityPlayer)->location = scene->location;
-
- getState()->scene = sceneIndex;
-
- getFlags()->flag_3 = true;
-
- // Draw the scene
- _engine->getGraphicsManager()->draw(scene, GraphicsManager::kBackgroundC);
- // FIXME move to start of fight?
- askForRedraw();
- redrawScreen();
-
- //////////////////////////////////////////////////////////////////////////
- // Setup the fight
- _data = new FightData;
- loadData(type);
-
- // Show opponents & egg button
- Common::Event emptyEvent;
- handleTick(emptyEvent, false);
- getInventory()->drawEgg();
-
- // Start fight
- _endType = kFightEndLost;
- while (_data->isRunning) {
- if (_engine->handleEvents())
- continue;
-
- getSound()->updateQueue();
- }
-
- // Cleanup after fight is over
- clearData();
-
- return _endType;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Status
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::setStopped() {
- if (_data)
- _data->isRunning = false;
-}
-
-void Fight::bailout(FightEndType type) {
- _state = 0;
- _endType = type;
- setStopped();
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Cleanup
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::clearData() {
- if (!_data)
- return;
-
- // Clear data
- clearSequences(_data->player);
- clearSequences(_data->opponent);
-
- SAFE_DELETE(_data->player);
- SAFE_DELETE(_data->opponent);
-
- SAFE_DELETE(_data);
-
- _engine->restoreEventHandlers();
-}
-
-void Fight::clearSequences(Fighter *combatant) const {
- if (!combatant)
- return;
-
- // The original game resets the function pointers to default values, just before deleting the struct
- getScenes()->removeAndRedraw(&combatant->frame, false);
-
- // Free sequences
- for (int i = 0; i < (int)combatant->sequences.size(); i++)
- SAFE_DELETE(combatant->sequences[i]);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Drawing
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::setSequenceAndDraw(Fighter *combatant, uint32 sequenceIndex, FightSequenceType type) const {
- if (combatant->sequences.size() < sequenceIndex)
- return;
-
- switch (type) {
- default:
- break;
-
- case kFightSequenceType0:
- if (combatant->sequenceIndex)
- return;
-
- combatant->sequence = combatant->sequences[sequenceIndex];
- combatant->sequenceIndex = sequenceIndex;
- draw(combatant);
- break;
-
- case kFightSequenceType1:
- combatant->sequence = combatant->sequences[sequenceIndex];
- combatant->sequenceIndex = sequenceIndex;
- combatant->sequenceIndex2 = 0;
- draw(combatant);
- break;
-
- case kFightSequenceType2:
- combatant->sequenceIndex2 = sequenceIndex;
- break;
- }
-}
-
-void Fight::draw(Fighter *combatant) const {
- getScenes()->removeAndRedraw(&combatant->frame, false);
-
- combatant->frameIndex = 0;
- combatant->field_24 = 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Loading
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::loadData(FightType type) {
- if (!_data)
- error("Fight::loadData - invalid data!");
-
- switch (type) {
- default:
- break;
-
- case kFightMilos:
- loadMilosPlayer();
- loadMilosOpponent();
- break;
-
- case kFightAnna:
- loadAnnaPlayer();
- loadAnnaOpponent();
- break;
-
- case kFightIvo:
- loadIvoPlayer();
- loadIvoOpponent();
- break;
-
- case kFightSalko:
- loadSalkoPlayer();
- loadSalkoOpponent();
- break;
-
- case kFightVesna:
- loadVesnaPlayer();
- loadVesnaOpponent();
- break;
- }
-
- if (!_data->player || !_data->opponent)
- error("Fight::loadData - error loading fight data (type=%d)", type);
-
- //////////////////////////////////////////////////////////////////////////
- // Start running the fight
- _data->isRunning = true;
-
- if (_state < 5) {
- setSequenceAndDraw(_data->player, 0, kFightSequenceType0);
- setSequenceAndDraw(_data->opponent, 0, kFightSequenceType0);
- goto end_load;
- }
-
- switch(type) {
- default:
- break;
-
- case kFightMilos:
- _data->opponent->countdown = 1;
- setSequenceAndDraw(_data->player, 4, kFightSequenceType0);
- setSequenceAndDraw(_data->opponent, 0, kFightSequenceType0);
- break;
-
- case kFightIvo:
- _data->opponent->countdown = 1;
- setSequenceAndDraw(_data->player, 3, kFightSequenceType0);
- setSequenceAndDraw(_data->opponent, 6, kFightSequenceType0);
- break;
-
- case kFightVesna:
- _data->opponent->countdown = 1;
- setSequenceAndDraw(_data->player, 0, kFightSequenceType0);
- setSequenceAndDraw(_data->player, 3, kFightSequenceType2);
- setSequenceAndDraw(_data->opponent, 5, kFightSequenceType0);
- break;
- }
-
-end_load:
- // Setup event handlers
- _engine->backupEventHandlers();
- SET_EVENT_HANDLERS(Fight, this);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Shared
-//////////////////////////////////////////////////////////////////////////
-void Fight::processFighter(Fighter *fighter) {
- if (!_data)
- error("Fight::processFighter - invalid data!");
-
- if (!fighter->sequence) {
- if (fighter->frame) {
- getScenes()->removeFromQueue(fighter->frame);
- getScenes()->setCoordinates(fighter->frame);
- }
- SAFE_DELETE(fighter->frame);
- return;
- }
-
- if (fighter->sequence->count() <= fighter->frameIndex) {
- switch(fighter->action) {
- default:
- break;
-
- case kFightAction101:
- setSequenceAndDraw(fighter, fighter->sequenceIndex2, kFightSequenceType1);
- fighter->sequenceIndex2 = 0;
- break;
-
- case kFightActionResetFrame:
- fighter->frameIndex = 0;
- break;
-
- case kFightAction103:
- setSequenceAndDraw(fighter, 0, kFightSequenceType1);
- CALL_FUNCTION1(fighter, handleAction, kFightAction101);
- setSequenceAndDraw(fighter->opponent, 0, kFightSequenceType1);
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction101);
- CALL_FUNCTION0(fighter->opponent, update);
- break;
-
- case kFightActionWin:
- bailout(kFightEndWin);
- break;
-
- case kFightActionLost:
- bailout(kFightEndLost);
- break;
- }
- }
-
- if (_data->isRunning) {
-
- // Get the current sequence frame
- SequenceFrame *frame = new SequenceFrame(fighter->sequence, (uint16)fighter->frameIndex);
- frame->getInfo()->location = 1;
-
- if (fighter->frame == frame) {
- delete frame;
- return;
- }
-
- getSound()->playFightSound(frame->getInfo()->soundAction, frame->getInfo()->field_31);
-
- // Add current frame to queue and advance
- getScenes()->addToQueue(frame);
- fighter->frameIndex++;
-
- if (fighter->frame) {
- getScenes()->removeFromQueue(fighter->frame);
-
- if (!frame->getInfo()->field_2E)
- getScenes()->setCoordinates(fighter->frame);
- }
-
- // Replace by new frame
- delete fighter->frame;
- fighter->frame = frame;
- }
-}
-
-void Fight::handleAction(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- return;
-
- case kFightAction101:
- break;
-
- case kFightActionResetFrame:
- fighter->countdown--;
- break;
-
- case kFightAction103:
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame);
- break;
-
- case kFightActionWin:
- _endType = kFightEndWin;
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame);
- break;
-
- case kFightActionLost:
- _endType = kFightEndLost;
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame);
- break;
- }
-
- // Update action
- fighter->action = action;
-}
-
-bool Fight::canInteract(Fighter const *fighter, FightAction /*= (FightAction)0*/ ) {
- return (fighter->action == kFightAction101 && !fighter->sequenceIndex);
-}
-
-void Fight::update(Fighter *fighter) {
-
- processFighter(fighter);
-
- if (fighter->frame)
- fighter->frame->getInfo()->location = (fighter->action == kFightActionResetFrame ? 2 : 0);
-}
-
-void Fight::updateOpponent(Fighter *fighter) {
-
- // This is an opponent struct!
- Opponent *opponent = (Opponent *)fighter;
-
- processFighter(opponent);
-
- if (opponent->field_38 && !opponent->sequenceIndex)
- opponent->field_38--;
-
- if (fighter->frame)
- fighter->frame->getInfo()->location = 1;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Milos
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::loadMilosPlayer() {
- REGISTER_PLAYER_FUNCTIONS(Milos)
-
- _data->player->sequences.push_back(loadSequence("2001cr.seq"));
- _data->player->sequences.push_back(loadSequence("2001cdl.seq"));
- _data->player->sequences.push_back(loadSequence("2001cdr.seq"));
- _data->player->sequences.push_back(loadSequence("2001cdm.seq"));
- _data->player->sequences.push_back(loadSequence("2001csgr.seq"));
- _data->player->sequences.push_back(loadSequence("2001csgl.seq"));
- _data->player->sequences.push_back(loadSequence("2001dbk.seq"));
-}
-
-void Fight::loadMilosOpponent() {
- REGISTER_OPPONENT_FUNCTIONS(Milos)
-
- _data->opponent->sequences.push_back(loadSequence("2001or.seq"));
- _data->opponent->sequences.push_back(loadSequence("2001oal.seq"));
- _data->opponent->sequences.push_back(loadSequence("2001oam.seq"));
- _data->opponent->sequences.push_back(loadSequence("2001okl.seq"));
- _data->opponent->sequences.push_back(loadSequence("2001okm.seq"));
- _data->opponent->sequences.push_back(loadSequence("2001dbk.seq"));
- _data->opponent->sequences.push_back(loadSequence("2001wbk.seq"));
-
- getSound()->playSound(kEntityTables0, "MUS027", SoundManager::kFlagDefault);
-
- _data->opponent->field_38 = 35;
-}
-
-void Fight::handleActionMilos(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- handleAction(fighter, action);
- return;
-
- case kFightAction1:
- if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 6, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 3, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction2:
- if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 6, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction128:
- if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4) || fighter->opponent->sequenceIndex != 1) {
- switch (fighter->opponent->sequenceIndex) {
- default:
- setSequenceAndDraw(fighter, rnd(3) + 1, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(fighter, 1, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(fighter, 3, kFightSequenceType0);
- break;
- }
- } else {
- setSequenceAndDraw(fighter, 4, kFightSequenceType1);
- CALL_FUNCTION0(fighter, update);
- }
- break;
- }
-}
-
-void Fight::updateMilos(Fighter *fighter) {
- if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) {
-
- // Draw sequences
- if (fighter->opponent->countdown <= 0) {
- setSequenceAndDraw(fighter, 5, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 6, kFightSequenceType1);
-
- getSound()->removeFromQueue(kEntityTables0);
- getSound()->playSound(kEntityTrain, "MUS029", SoundManager::kFlagDefault);
-
- CALL_FUNCTION1(fighter, handleAction, kFightActionWin);
- }
-
- if (fighter->sequenceIndex == 4) {
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction4);
- _endType = kFightEndLost;
- }
- }
-
- update(fighter);
-}
-
-bool Fight::canInteractMilos(Fighter const *fighter, FightAction action) {
- if (!_data)
- error("Fight::canInteractMilos - invalid data!");
-
- if (action != kFightAction128
- || _data->player->sequenceIndex != 1
- || !fighter->frame
- || CHECK_SEQUENCE2(fighter, 4)
- || fighter->opponent->sequenceIndex != 1) {
- return canInteract(fighter);
- }
-
- _engine->getCursor()->setStyle(kCursorHand);
-
- return true;
-}
-
-void Fight::handleOpponentActionMilos(Fighter *fighter, FightAction action) {
- if (action == kFightAction4) {
- setSequenceAndDraw(fighter, 5, kFightSequenceType1);
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- } else {
- if (action != kFightAction131)
- handleAction(fighter, action);
- }
-}
-
-void Fight::updateOpponentMilos(Fighter *fighter) {
- // This is an opponent struct!
- Opponent *opponent = (Opponent *)fighter;
-
- if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) {
-
- if (opponent->opponent->field_34 >= 2) {
- switch (rnd(5)) {
- default:
- break;
-
- case 0:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType1);
- break;
-
- case 3:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 4:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
- }
- } else {
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- }
-
- // Update field_38
- if (opponent->opponent->field_34 < 5)
- opponent->field_38 = 6 * (5 - opponent->opponent->field_34);
- else
- opponent->field_38 = 0;
- }
-
- if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) {
- if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2)
- CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex);
-
- if (opponent->opponent->countdown <= 0) {
- getSound()->removeFromQueue(kEntityTables0);
- CALL_FUNCTION1(opponent, handleAction, kFightActionLost);
- }
- }
-
- updateOpponent(opponent);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Anna
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::loadAnnaPlayer() {
- if (!_data)
- error("Fight::loadAnnaPlayer - invalid data!");
-
- // Special case: we are using some shared functions directly
- _data->player->handleAction = new Common::Functor2Mem<Fighter *, FightAction, void, Fight>(this, &Fight::handleActionAnna);
- _data->player->update = new Common::Functor1Mem<Fighter *, void, Fight>(this, &Fight::update);
- _data->player->canInteract = new Common::Functor2Mem<Fighter const *, FightAction, bool, Fight>(this, &Fight::canInteract);
-
- _data->player->sequences.push_back(loadSequence("2002cr.seq"));
- _data->player->sequences.push_back(loadSequence("2002cdl.seq"));
- _data->player->sequences.push_back(loadSequence("2002cdr.seq"));
- _data->player->sequences.push_back(loadSequence("2002cdm.seq"));
- _data->player->sequences.push_back(loadSequence("2002lbk.seq"));
-}
-
-void Fight::loadAnnaOpponent() {
- if (!_data)
- error("Fight::loadAnnaOpponent - invalid data!");
-
- // Special case: we are using some shared functions directly
- _data->opponent->handleAction = new Common::Functor2Mem<Fighter *, FightAction, void, Fight>(this, &Fight::handleAction);
- _data->opponent->update = new Common::Functor1Mem<Fighter *, void, Fight>(this, &Fight::updateOpponentAnna);
- _data->opponent->canInteract = new Common::Functor2Mem<Fighter const *, FightAction, bool, Fight>(this, &Fight::canInteract);
-
- _data->opponent->sequences.push_back(loadSequence("2002or.seq"));
- _data->opponent->sequences.push_back(loadSequence("2002oal.seq"));
- _data->opponent->sequences.push_back(loadSequence("2002oam.seq"));
- _data->opponent->sequences.push_back(loadSequence("2002oar.seq"));
- _data->opponent->sequences.push_back(loadSequence("2002okr.seq"));
- _data->opponent->sequences.push_back(loadSequence("2002okml.seq"));
- _data->opponent->sequences.push_back(loadSequence("2002okm.seq"));
-
- getSound()->playSound(kEntityTables0, "MUS030", SoundManager::kFlagDefault);
-
- _data->opponent->field_38 = 30;
-}
-
-void Fight::handleActionAnna(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- handleAction(fighter, action);
- return;
-
- case kFightAction1:
- if ((fighter->sequenceIndex != 1 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 4, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction2:
- if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 4, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction3:
- if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 1) || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 4, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 6, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction128:
- switch (fighter->opponent->sequenceIndex) {
- default:
- setSequenceAndDraw(fighter, 3, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(fighter, 1, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(fighter, 3, kFightSequenceType0);
- break;
-
- case 3:
- setSequenceAndDraw(fighter, 2, kFightSequenceType0);
- break;
- }
- break;
- }
-
- if (fighter->field_34 > 4) {
- getSound()->removeFromQueue(kEntityTables0);
- bailout(kFightEndWin);
- }
-}
-
-void Fight::updateOpponentAnna(Fighter *fighter) {
- // This is an opponent struct!
- Opponent *opponent = (Opponent *)fighter;
-
- if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) {
-
- if (opponent->opponent->field_34 >= 2) {
- switch (rnd(6)) {
- default:
- break;
-
- case 0:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(opponent, 3, kFightSequenceType0);
- break;
-
- case 3:
- setSequenceAndDraw(opponent, 3, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 4:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 5:
- setSequenceAndDraw(opponent, 3, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
- }
- }
-
- // Update field_38
- opponent->field_38 = (int32)rnd(15);
- }
-
- if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) {
- if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2 || opponent->sequenceIndex == 3)
- CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex);
-
- if (opponent->opponent->countdown <= 0) {
- getSound()->removeFromQueue(kEntityTables0);
- CALL_FUNCTION1(opponent, handleAction, kFightActionLost);
- }
- }
-
- updateOpponent(opponent);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Ivo
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::loadIvoPlayer() {
- REGISTER_PLAYER_FUNCTIONS(Ivo)
-
- _data->player->sequences.push_back(loadSequence("2003cr.seq"));
- _data->player->sequences.push_back(loadSequence("2003car.seq"));
- _data->player->sequences.push_back(loadSequence("2003cal.seq"));
- _data->player->sequences.push_back(loadSequence("2003cdr.seq"));
- _data->player->sequences.push_back(loadSequence("2003cdm.seq"));
- _data->player->sequences.push_back(loadSequence("2003chr.seq"));
- _data->player->sequences.push_back(loadSequence("2003chl.seq"));
- _data->player->sequences.push_back(loadSequence("2003ckr.seq"));
- _data->player->sequences.push_back(loadSequence("2003lbk.seq"));
- _data->player->sequences.push_back(loadSequence("2003fbk.seq"));
-
- _data->player->countdown = 5;
-}
-
-void Fight::loadIvoOpponent() {
- REGISTER_OPPONENT_FUNCTIONS(Ivo)
-
- _data->opponent->sequences.push_back(loadSequence("2003or.seq"));
- _data->opponent->sequences.push_back(loadSequence("2003oal.seq"));
- _data->opponent->sequences.push_back(loadSequence("2003oar.seq"));
- _data->opponent->sequences.push_back(loadSequence("2003odm.seq"));
- _data->opponent->sequences.push_back(loadSequence("2003okl.seq"));
- _data->opponent->sequences.push_back(loadSequence("2003okj.seq"));
- _data->opponent->sequences.push_back(loadSequence("blank.seq"));
- _data->opponent->sequences.push_back(loadSequence("csdr.seq"));
- _data->opponent->sequences.push_back(loadSequence("2003l.seq"));
-
- getSound()->playSound(kEntityTables0, "MUS032", SoundManager::kFlagDefault);
-
- _data->opponent->countdown = 5;
- _data->opponent->field_38 = 15;
-}
-
-void Fight::handleActionIvo(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- handleAction(fighter, action);
- return;
-
- case kFightAction1:
- if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 7, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- }
- break;
-
- case kFightAction2:
- if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 7, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- }
- break;
-
- case kFightAction128:
- switch (fighter->opponent->sequenceIndex) {
- default:
- case 1:
- setSequenceAndDraw(fighter, 1, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(fighter, 2, kFightSequenceType0);
- break;
- }
- break;
-
- case kFightAction129:
- setSequenceAndDraw(fighter, (fighter->opponent->countdown > 1) ? 4 : 3, fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0);
- break;
-
- case kFightAction130:
- setSequenceAndDraw(fighter, 3, fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0);
- break;
- }
-}
-
-void Fight::updateIvo(Fighter *fighter) {
-
- if ((fighter->sequenceIndex == 3 || fighter->sequenceIndex == 4) && !fighter->frameIndex)
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction131);
-
- if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) {
-
- // Draw sequences
- if (fighter->opponent->countdown <= 0) {
- setSequenceAndDraw(fighter, 9, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 8, kFightSequenceType1);
- getSound()->removeFromQueue(kEntityTables0);
-
- CALL_FUNCTION1(fighter, handleAction, kFightActionWin);
- return;
- }
-
- if (fighter->sequenceIndex == 3 || fighter->sequenceIndex == 4)
- CALL_FUNCTION1(fighter->opponent, handleAction, (FightAction)fighter->sequenceIndex);
- }
-
- update(fighter);
-}
-
-bool Fight::canInteractIvo(Fighter const *fighter, FightAction action) {
- if (action == kFightAction129 || action == kFightAction130)
- return (fighter->sequenceIndex >= 8);
-
- return canInteract(fighter);
-}
-
-void Fight::handleOpponentActionIvo(Fighter *fighter, FightAction action) {
- // This is an opponent struct!
- Opponent *opponent = (Opponent *)fighter;
-
- switch (action) {
- default:
- handleAction(fighter, action);
- break;
-
- case kFightAction3:
- if ((opponent->sequenceIndex != 1 && opponent->sequenceIndex != 3) || CHECK_SEQUENCE2(opponent, 4)) {
- setSequenceAndDraw(opponent, 6, kFightSequenceType1);
- setSequenceAndDraw(opponent->opponent, 6, kFightSequenceType1);
- CALL_FUNCTION1(opponent->opponent, handleAction, kFightAction103);
- }
- break;
-
- case kFightAction4:
- if ((opponent->sequenceIndex != 2 && opponent->sequenceIndex != 3) || CHECK_SEQUENCE2(opponent, 4)) {
- setSequenceAndDraw(opponent, 6, kFightSequenceType1);
- setSequenceAndDraw(opponent->opponent, 5, kFightSequenceType1);
- CALL_FUNCTION1(opponent->opponent, handleAction, kFightAction103);
- }
- break;
-
- case kFightAction131:
- if (opponent->sequenceIndex)
- break;
-
- if (rnd(100) <= (unsigned int)(opponent->countdown > 2 ? 60 : 75)) {
- setSequenceAndDraw(opponent, 3 , kFightSequenceType1);
- if (opponent->opponent->sequenceIndex == 4)
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- }
- break;
- }
-}
-
-void Fight::updateOpponentIvo(Fighter *fighter) {
- // This is an opponent struct!
- Opponent *opponent = (Opponent *)fighter;
-
- if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) {
-
- if (opponent->opponent->field_34 >= 2) {
- switch (rnd(5)) {
- default:
- break;
-
- case 0:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 3:
- setSequenceAndDraw(opponent, 0, kFightSequenceType2);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
-
- case 4:
- setSequenceAndDraw(opponent, 0, kFightSequenceType1);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
- }
- }
-
- // Update field_38
- opponent->field_38 = 3 * opponent->countdown + (int32)rnd(10);
- }
-
- if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) {
-
- if (opponent->opponent->countdown <= 0) {
- setSequenceAndDraw(opponent, 7, kFightSequenceType1);
- setSequenceAndDraw(opponent->opponent, 8, kFightSequenceType1);
- getSound()->removeFromQueue(kEntityTables0);
-
- CALL_FUNCTION1(opponent->opponent, handleAction, kFightActionWin);
-
- return;
- }
-
- if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2)
- CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex);
- }
-
- updateOpponent(opponent);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Salko
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::loadSalkoPlayer() {
- REGISTER_PLAYER_FUNCTIONS(Salko)
-
- _data->player->sequences.push_back(loadSequence("2004cr.seq"));
- _data->player->sequences.push_back(loadSequence("2004cdr.seq"));
- _data->player->sequences.push_back(loadSequence("2004chj.seq"));
- _data->player->sequences.push_back(loadSequence("2004bk.seq"));
-
- _data->player->countdown = 2;
-}
-
-void Fight::loadSalkoOpponent() {
- REGISTER_OPPONENT_FUNCTIONS(Salko)
-
- _data->opponent->sequences.push_back(loadSequence("2004or.seq"));
- _data->opponent->sequences.push_back(loadSequence("2004oam.seq"));
- _data->opponent->sequences.push_back(loadSequence("2004oar.seq"));
- _data->opponent->sequences.push_back(loadSequence("2004okr.seq"));
- _data->opponent->sequences.push_back(loadSequence("2004ohm.seq"));
- _data->opponent->sequences.push_back(loadSequence("blank.seq"));
-
- getSound()->playSound(kEntityTables0, "MUS035", SoundManager::kFlagDefault);
-
- _data->opponent->countdown = 3;
- _data->opponent->field_38 = 30;
-}
-
-void Fight::handleActionSalko(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- handleAction(fighter, action);
- return;
-
- case kFightAction1:
- case kFightAction2:
- if (fighter->sequenceIndex != 1 && CHECK_SEQUENCE2(fighter, 4)) {
- fighter->field_34 = 0;
-
- setSequenceAndDraw(fighter, 3, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, (action == kFightAction1 ? 3 : 4), kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
-
- if (action == kFightAction2)
- fighter->countdown= 0;
-
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction5:
- if (fighter->sequenceIndex != 3) {
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- }
- break;
-
- case kFightAction128:
- setSequenceAndDraw(fighter, 1, kFightSequenceType0);
- fighter->field_34 = 0;
- break;
-
- case kFightAction131:
- setSequenceAndDraw(fighter, 2, (fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0));
- break;
- }
-}
-
-void Fight::updateSalko(Fighter *fighter) {
- update(fighter);
-
- // The original doesn't check for currentSequence2 != NULL (might not happen when everything is working properly, but crashes with our current implementation)
- if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) {
-
- if (fighter->opponent->countdown <= 0) {
- getSound()->removeFromQueue(kEntityTables0);
- bailout(kFightEndWin);
-
- return;
- }
-
- if (fighter->sequenceIndex == 2)
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction2);
- }
-}
-
-bool Fight::canInteractSalko(Fighter const *fighter, FightAction action) {
- if (action == kFightAction131) {
- if (fighter->sequenceIndex == 1) {
- if (fighter->opponent->countdown <= 0)
- _engine->getCursor()->setStyle(kCursorHand);
-
- return true;
- }
-
- return false;
- }
-
- return canInteract(fighter);
-}
-
-void Fight::handleOpponentActionSalko(Fighter *fighter, FightAction action) {
- if (action == kFightAction2) {
- setSequenceAndDraw(fighter, 5, kFightSequenceType1);
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- } else {
- handleAction(fighter, action);
- }
-}
-
-void Fight::updateOpponentSalko(Fighter *fighter) {
- // This is an opponent struct
- Opponent *opponent = (Opponent *)fighter;
-
- if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) {
-
- switch (rnd(5)) {
- default:
- break;
-
- case 0:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 3:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
-
- case 4:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
- }
-
- // Update field_38
- opponent->field_38 = 4 * opponent->countdown;
- }
-
- if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) {
- if (opponent->opponent->countdown <= 0) {
- getSound()->removeFromQueue(kEntityTables0);
- bailout(kFightEndLost);
-
- // Stop processing
- return;
- }
-
- if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2)
- CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex);
- }
-
- updateOpponent(opponent);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Vesna
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::loadVesnaPlayer() {
- REGISTER_PLAYER_FUNCTIONS(Vesna)
-
- _data->player->sequences.push_back(loadSequence("2005cr.seq"));
- _data->player->sequences.push_back(loadSequence("2005cdr.seq"));
- _data->player->sequences.push_back(loadSequence("2005cbr.seq"));
- _data->player->sequences.push_back(loadSequence("2005bk.seq"));
- _data->player->sequences.push_back(loadSequence("2005cdm1.seq"));
- _data->player->sequences.push_back(loadSequence("2005chl.seq"));
-}
-
-void Fight::loadVesnaOpponent() {
- REGISTER_OPPONENT_FUNCTIONS(Vesna)
-
- _data->opponent->sequences.push_back(loadSequence("2005or.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005oam.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005oar.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005okml.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005okr.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005odm1.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005csbm.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005oam4.seq"));
-
- getSound()->playSound(kEntityTables0, "MUS038", SoundManager::kFlagDefault);
-
- _data->opponent->countdown = 4;
- _data->opponent->field_38 = 30;
-}
-
-void Fight::handleActionVesna(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- handleAction(fighter, action);
- return;
-
- case kFightAction1:
- if (fighter->sequenceIndex != 1) {
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction2:
- if (fighter->sequenceIndex != 2) {
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction5:
- if (fighter->sequenceIndex != 3) {
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- }
- break;
-
- case kFightAction128:
- if (fighter->sequenceIndex == 1 && fighter->opponent->sequenceIndex == 1 && CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 5, kFightSequenceType1);
- } else {
- setSequenceAndDraw(fighter, (fighter->opponent->sequenceIndex == 5) ? 3 : 1, kFightSequenceType0);
- }
- break;
-
- case kFightAction132:
- setSequenceAndDraw(fighter, 2, kFightSequenceType0);
- break;
- }
-
- if (fighter->field_34 > 10) {
- setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType2);
- fighter->opponent->countdown = 1;
- fighter->field_34 = 0;
- }
-}
-
-void Fight::updateVesna(Fighter *fighter) {
- if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) {
-
- if (fighter->sequenceIndex == 3)
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction3);
-
- if (fighter->opponent->countdown <= 0) {
- getSound()->removeFromQueue(kEntityTables0);
- bailout(kFightEndWin);
- return;
- }
-
- if (fighter->sequenceIndex == 5)
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction5);
- }
-
- update(fighter);
-}
-
-bool Fight::canInteractVesna(Fighter const *fighter, FightAction action) {
- if (action != kFightAction128)
- return canInteract(fighter);
-
- if (fighter->sequenceIndex != 1) {
-
- if (fighter->opponent->sequenceIndex == 5) {
- _engine->getCursor()->setStyle(kCursorDown);
- return true;
- }
-
- return canInteract(fighter);
- }
-
- if (fighter->opponent->sequenceIndex == 1 && CHECK_SEQUENCE2(fighter, 4)) {
- _engine->getCursor()->setStyle(kCursorPunchLeft);
- return true;
- }
-
- return false;
-}
-
-void Fight::handleOpponentActionVesna(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- handleAction(fighter, action);
- break;
-
- case kFightAction3:
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- break;
-
- case kFightAction5:
- setSequenceAndDraw(fighter, 7, kFightSequenceType1);
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- if (fighter->countdown <= 1)
- fighter->countdown = 1;
- break;
-
- case kFightAction131:
- break;
- }
-}
-
-void Fight::updateOpponentVesna(Fighter *fighter) {
- // This is an opponent struct
- Opponent *opponent = (Opponent *)fighter;
-
- if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) {
-
- if (opponent->opponent->field_34 == 1) {
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- } else {
- switch (rnd(6)) {
- default:
- break;
-
- case 0:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
-
- case 2:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- break;
-
- case 3:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 4:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 5:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
- }
- }
-
- // Update field_38
- opponent->field_38 = 4 * opponent->countdown;
- }
-
- if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) {
- if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2 || opponent->sequenceIndex == 5)
- CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex);
-
- if (opponent->opponent->countdown <= 0) {
-
- switch (opponent->sequenceIndex) {
- default:
- break;
-
- case 1:
- setSequenceAndDraw(opponent, 3, kFightSequenceType1);
- break;
-
- case 2:
- setSequenceAndDraw(opponent, 4, kFightSequenceType1);
- break;
-
- case 5:
- setSequenceAndDraw(opponent, 6, kFightSequenceType1);
- break;
- }
-
- setSequenceAndDraw(opponent->opponent, 4, kFightSequenceType1);
-
- CALL_FUNCTION1(opponent, handleAction, kFightActionLost);
- CALL_FUNCTION0(opponent->opponent, update);
- CALL_FUNCTION0(opponent, update);
-
- getSound()->removeFromQueue(kEntityTables0);
-
- // Stop processing
- return;
- }
- }
-
- updateOpponent(opponent);
-}
-
-} // End of namespace LastExpress
diff --git a/engines/lastexpress/game/fight.h b/engines/lastexpress/game/fight.h
deleted file mode 100644
index a33cc93a29..0000000000
--- a/engines/lastexpress/game/fight.h
+++ /dev/null
@@ -1,266 +0,0 @@
-/* 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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef LASTEXPRESS_FIGHT_H
-#define LASTEXPRESS_FIGHT_H
-
-/*
- Fight structure
- ---------------
- uint32 {4} - player struct
- uint32 {4} - opponent struct
- uint32 {4} - hasLost flag
-
- byte {1} - isRunning
-
- Fight participant structure
- ---------------------------
- uint32 {4} - function pointer
- uint32 {4} - pointer to fight structure
- uint32 {4} - pointer to opponent (fight participant structure)
- uint32 {4} - array of sequences
- uint32 {4} - number of sequences
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint16 {2} - ??
- uint16 {2} - ?? - only for opponent structure
- uint32 {4} - ?? - only for opponent structure
-
-*/
-
-#include "lastexpress/shared.h"
-
-#include "lastexpress/eventhandler.h"
-
-#include "common/array.h"
-
-namespace LastExpress {
-
-class LastExpressEngine;
-class Sequence;
-class SequenceFrame;
-
-//////////////////////////////////////////////////////////////////////////
-// TODO : objectify!
-class Fight : public EventHandler {
-public:
- enum FightEndType {
- kFightEndWin = 0,
- kFightEndLost = 1,
- kFightEndExit = 2
- };
-
- Fight(LastExpressEngine *engine);
- ~Fight();
-
- FightEndType setup(FightType type);
-
- void eventMouse(const Common::Event &ev);
- void eventTick(const Common::Event &ev);
-
- void setStopped();
- void resetState() { _state = 0; }
-
-private:
- enum FightSequenceType {
- kFightSequenceType0 = 0,
- kFightSequenceType1 = 1,
- kFightSequenceType2 = 2
- };
-
- enum FightAction {
- kFightAction1 = 1,
- kFightAction2 = 2,
- kFightAction3 = 3,
- kFightAction4 = 4,
- kFightAction5 = 5,
- kFightAction101 = 101,
- kFightActionResetFrame = 102,
- kFightAction103 = 103,
- kFightActionWin = 104,
- kFightActionLost = 105,
- kFightAction128 = 128,
- kFightAction129 = 129,
- kFightAction130 = 130,
- kFightAction131 = 131,
- kFightAction132 = 132
- };
-
- struct Fighter {
- Common::Functor2<Fighter *, FightAction, void> *handleAction;
- Common::Functor1<Fighter *, void> *update;
- Common::Functor2<Fighter const *, FightAction, bool> *canInteract;
- Fighter *opponent;
- Common::Array<Sequence *> sequences;
- uint32 sequenceIndex;
- Sequence *sequence;
- SequenceFrame *frame;
- uint32 frameIndex;
- uint32 field_24;
- FightAction action;
- uint32 sequenceIndex2;
- int32 countdown; // countdown before loosing ?
- uint32 field_34;
-
- Fighter() {
- handleAction = NULL;
- update = NULL;
- canInteract = NULL;
-
- opponent = NULL;
-
- sequenceIndex = 0;
- sequence = NULL;
- frame = NULL;
- frameIndex = 0;
-
- field_24 = 0;
-
- action = kFightAction101;
- sequenceIndex2 = 0;
-
- countdown = 1;
-
- field_34 = 0;
- }
- };
-
- // Opponent struct
- struct Opponent : Fighter {
- int32 field_38;
-
- Opponent() : Fighter() {
- field_38 = 0;
- }
- };
-
- struct FightData {
- Fighter *player;
- Opponent *opponent;
- int32 index;
-
- Sequence *sequences[20];
- Common::String names[20];
-
- bool isRunning;
-
- FightData() {
- player = new Fighter();
- opponent = new Opponent();
-
- // Set opponents
- player->opponent = opponent;
- opponent->opponent = player;
-
- index = 0;
-
- isRunning = false;
- }
- };
-
- LastExpressEngine *_engine;
- FightData *_data;
- FightEndType _endType;
- int _state;
-
- bool _handleTimer;
-
- // Events
- void handleTick(const Common::Event &ev, bool unknown);
-
- // State
- void bailout(FightEndType type);
-
-
- // Drawing
- void setSequenceAndDraw(Fighter *fighter, uint32 sequenceIndex, FightSequenceType type) const;
- void draw(Fighter *fighter) const;
-
- // Cleanup
- void clearData();
- void clearSequences(Fighter *fighter) const;
-
- //////////////////////////////////////////////////////////////////////////
- // Loading
- void loadData(FightType type);
-
- // Shared
- void processFighter(Fighter *fighter);
-
- // Default functions
- void handleAction(Fighter *fighter, FightAction action);
- void update(Fighter *fighter);
- bool canInteract(Fighter const *fighter, FightAction = (FightAction)0);
- void updateOpponent(Fighter *fighter);
-
- // Milos
- void loadMilosPlayer();
- void loadMilosOpponent();
- void handleActionMilos(Fighter *fighter, FightAction action);
- void updateMilos(Fighter *fighter);
- bool canInteractMilos(Fighter const *fighter, FightAction action);
- void handleOpponentActionMilos(Fighter *fighter, FightAction action);
- void updateOpponentMilos(Fighter *fighter);
-
- // Anna
- void loadAnnaPlayer();
- void loadAnnaOpponent();
- void handleActionAnna(Fighter *fighter, FightAction action);
- void updateOpponentAnna(Fighter *fighter);
-
- // Ivo
- void loadIvoPlayer();
- void loadIvoOpponent();
- void handleActionIvo(Fighter *fighter, FightAction action);
- void updateIvo(Fighter *fighter);
- bool canInteractIvo(Fighter const *fighter, FightAction action);
- void handleOpponentActionIvo(Fighter *fighter, FightAction action);
- void updateOpponentIvo(Fighter *fighter);
-
- // Salko
- void loadSalkoPlayer();
- void loadSalkoOpponent();
- void handleActionSalko(Fighter *fighter, FightAction action);
- void updateSalko(Fighter *fighter);
- bool canInteractSalko(Fighter const *fighter, FightAction action);
- void handleOpponentActionSalko(Fighter *fighter, FightAction action);
- void updateOpponentSalko(Fighter *fighter);
-
- // Vesna
- void loadVesnaPlayer();
- void loadVesnaOpponent();
- void handleActionVesna(Fighter *fighter, FightAction action);
- void updateVesna(Fighter *fighter);
- bool canInteractVesna(Fighter const *fighter, FightAction action);
- void handleOpponentActionVesna(Fighter *fighter, FightAction action);
- void updateOpponentVesna(Fighter *fighter);
-};
-
-} // End of namespace LastExpress
-
-#endif // LASTEXPRESS_FIGHT_H
diff --git a/engines/lastexpress/game/logic.cpp b/engines/lastexpress/game/logic.cpp
index 0911c60de0..a8a2ce87b1 100644
--- a/engines/lastexpress/game/logic.cpp
+++ b/engines/lastexpress/game/logic.cpp
@@ -30,11 +30,13 @@
// Entities
#include "lastexpress/entities/chapters.h"
+// Fight
+#include "lastexpress/fight/fight.h"
+
// Game
#include "lastexpress/game/action.h"
#include "lastexpress/game/beetle.h"
#include "lastexpress/game/entities.h"
-#include "lastexpress/game/fight.h"
#include "lastexpress/game/inventory.h"
#include "lastexpress/game/menu.h"
#include "lastexpress/game/object.h"
diff --git a/engines/lastexpress/game/menu.cpp b/engines/lastexpress/game/menu.cpp
index f9eef26326..27a43d8f61 100644
--- a/engines/lastexpress/game/menu.cpp
+++ b/engines/lastexpress/game/menu.cpp
@@ -28,7 +28,8 @@
#include "lastexpress/data/snd.h"
#include "lastexpress/data/scene.h"
-#include "lastexpress/game/fight.h"
+#include "lastexpress/fight/fight.h"
+
#include "lastexpress/game/inventory.h"
#include "lastexpress/game/logic.h"
#include "lastexpress/game/savegame.h"
diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp
index e162998719..120e6eb28b 100644
--- a/engines/lastexpress/lastexpress.cpp
+++ b/engines/lastexpress/lastexpress.cpp
@@ -288,22 +288,34 @@ void LastExpressEngine::handleSoundTimer() {
/// Event Handling
///////////////////////////////////////////////////////////////////////////////////
void LastExpressEngine::backupEventHandlers() {
+ if (_eventMouseBackup != NULL || _eventTickBackup != NULL)
+ error("[LastExpressEngine::backupEventHandlers] backup event handlers are already set");
+
_eventMouseBackup = _eventMouse;
_eventTickBackup = _eventTick;
}
void LastExpressEngine::restoreEventHandlers() {
if (_eventMouseBackup == NULL || _eventTickBackup == NULL)
- error("LastExpressEngine::restoreEventHandlers: restore called before backing up the event handlers!");
+ error("[LastExpressEngine::restoreEventHandlers] restore called before backing up the event handlers");
+
+ // Cleanup previous event handlers
+ SAFE_DELETE(_eventMouse);
+ SAFE_DELETE(_eventTick);
_eventMouse = _eventMouseBackup;
_eventTick = _eventTickBackup;
+
+ _eventMouseBackup = NULL;
+ _eventTickBackup = NULL;
}
void LastExpressEngine::setEventHandlers(EventHandler::EventFunction *mouse, EventHandler::EventFunction *tick) {
- // Cleanup previous event handlers
- delete _eventMouse;
- delete _eventTick;
+ if (_eventMouse != _eventMouseBackup)
+ SAFE_DELETE(_eventMouse);
+
+ if (_eventTick != _eventTickBackup)
+ SAFE_DELETE(_eventTick);
_eventMouse = mouse;
_eventTick = tick;
diff --git a/engines/lastexpress/module.mk b/engines/lastexpress/module.mk
index 12fbb4f85b..e81151910b 100644
--- a/engines/lastexpress/module.mk
+++ b/engines/lastexpress/module.mk
@@ -45,10 +45,16 @@ MODULE_OBJS := \
entities/verges.o \
entities/vesna.o \
entities/yasmin.o \
+ fight/fight.o \
+ fight/fighter.o \
+ fight/fighter_anna.o \
+ fight/fighter_ivo.o \
+ fight/fighter_milos.o \
+ fight/fighter_salko.o \
+ fight/fighter_vesna.o \
game/action.o \
game/beetle.o \
game/entities.o \
- game/fight.o \
game/inventory.o \
game/logic.o \
game/menu.o \
diff --git a/engines/lure/debugger.cpp b/engines/lure/debugger.cpp
index 68410875f7..ef4a22f73a 100644
--- a/engines/lure/debugger.cpp
+++ b/engines/lure/debugger.cpp
@@ -549,14 +549,19 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) {
}
bool Debugger::cmd_saveStrings(int argc, const char **argv) {
- StringData &strings = StringData::getReference();
- char buffer[32768];
-
if (argc != 2) {
DebugPrintf("strings <stringId>\n");
return true;
}
+ StringData &strings = StringData::getReference();
+
+ char *buffer = (char *)malloc(32768);
+ if (!buffer) {
+ DebugPrintf("Cannot allocate strings buffer\n");
+ return true;
+ }
+
uint16 id = strToInt(argv[1]);
strings.getString(id, buffer, NULL, NULL);
DebugPrintf("%s\n", buffer);
@@ -577,6 +582,9 @@ bool Debugger::cmd_saveStrings(int argc, const char **argv) {
DebugPrintf("Done\n");
*/
+
+ free(buffer);
+
return true;
}
diff --git a/engines/lure/memory.cpp b/engines/lure/memory.cpp
index c5c28fa8bc..137a8f6bee 100644
--- a/engines/lure/memory.cpp
+++ b/engines/lure/memory.cpp
@@ -93,8 +93,12 @@ void MemoryBlock::copyFrom(const byte *src, uint32 srcPos, uint32 destPos, uint3
void MemoryBlock::reallocate(uint32 size1) {
_size = size1;
- _data = (byte *) realloc(_data, size1);
- if (!_data) error ("Failed reallocating memory block");
+
+ byte *tmp = (byte *) realloc(_data, size1);
+ if (!tmp)
+ error ("[MemoryBlock::reallocate] Failed reallocating memory block");
+
+ _data = tmp;
}
} // End of namespace Lure
diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp
index 862a0b4d64..06ce335518 100644
--- a/engines/saga/actor.cpp
+++ b/engines/saga/actor.cpp
@@ -385,6 +385,7 @@ void Actor::loadActorList(int protagonistIdx, int actorCount, int actorsResource
ByteArrayReadStreamEndian actorS(actorListData);
+ _actors.clear();
_actors.resize(actorCount);
i = 0;
for (ActorDataArray::iterator actor = _actors.begin(); actor != _actors.end(); ++actor, i++) {
diff --git a/engines/sci/decompressor.cpp b/engines/sci/decompressor.cpp
index 03a06d240d..7e7acab994 100644
--- a/engines/sci/decompressor.cpp
+++ b/engines/sci/decompressor.cpp
@@ -181,16 +181,27 @@ int DecompressorLZW::unpackLZW(Common::ReadStream *src, byte *dest, uint32 nPack
init(src, dest, nPacked, nUnpacked);
uint16 token; // The last received value
-
- uint16 tokenlist[4096]; // pointers to dest[]
- uint16 tokenlengthlist[4096]; // char length of each token
uint16 tokenlastlength = 0;
+ uint16 *tokenlist = (uint16 *)malloc(4096 * sizeof(uint16)); // pointers to dest[]
+ uint16* tokenlengthlist = (uint16 *)malloc(4096 * sizeof(uint16)); // char length of each token
+ if (!tokenlist || !tokenlengthlist) {
+ free(tokenlist);
+ free(tokenlengthlist);
+
+ error("[DecompressorLZW::unpackLZW] Cannot allocate token memory buffers");
+ }
+
while (!isFinished()) {
token = getBitsLSB(_numbits);
- if (token == 0x101)
+ if (token == 0x101) {
+ free(tokenlist);
+ free(tokenlengthlist);
+
return 0; // terminator
+ }
+
if (token == 0x100) { // reset command
_numbits = 9;
_endtoken = 0x1FF;
@@ -199,6 +210,10 @@ int DecompressorLZW::unpackLZW(Common::ReadStream *src, byte *dest, uint32 nPack
if (token > 0xff) {
if (token >= _curtoken) {
warning("unpackLZW: Bad token %x", token);
+
+ free(tokenlist);
+ free(tokenlengthlist);
+
return SCI_ERROR_DECOMPRESSION_ERROR;
}
tokenlastlength = tokenlengthlist[token] + 1;
@@ -231,6 +246,9 @@ int DecompressorLZW::unpackLZW(Common::ReadStream *src, byte *dest, uint32 nPack
}
}
+ free(tokenlist);
+ free(tokenlengthlist);
+
return _dwWrote == _szUnpacked ? 0 : SCI_ERROR_DECOMPRESSION_ERROR;
}
@@ -238,12 +256,19 @@ int DecompressorLZW::unpackLZW1(Common::ReadStream *src, byte *dest, uint32 nPac
uint32 nUnpacked) {
init(src, dest, nPacked, nUnpacked);
- byte stak[0x1014];
- byte lastchar = 0;
- uint16 stakptr = 0, lastbits = 0;
- Tokenlist tokens[0x1004];
+ byte *stak = (byte *)malloc(0x1014);
+ Tokenlist *tokens = (Tokenlist *)malloc(0x1004 * sizeof(Tokenlist));
+ if (!stak || !tokens) {
+ free(stak);
+ free(tokens);
+
+ error("[DecompressorLZW::unpackLZW1] Cannot allocate decompression buffers");
+ }
+
memset(tokens, 0, sizeof(tokens));
+ byte lastchar = 0;
+ uint16 stakptr = 0, lastbits = 0;
byte decryptstart = 0;
uint16 bitstring;
@@ -310,6 +335,10 @@ int DecompressorLZW::unpackLZW1(Common::ReadStream *src, byte *dest, uint32 nPac
break;
}
}
+
+ free(stak);
+ free(tokens);
+
return _dwWrote == _szUnpacked ? 0 : SCI_ERROR_DECOMPRESSION_ERROR;
}
diff --git a/engines/sword25/fmv/theora_decoder.cpp b/engines/sword25/fmv/theora_decoder.cpp
index 098bd2c6b9..a7ebb5df8c 100644
--- a/engines/sword25/fmv/theora_decoder.cpp
+++ b/engines/sword25/fmv/theora_decoder.cpp
@@ -424,6 +424,12 @@ bool TheoraDecoder::queueAudio() {
if (!_audStream)
return false;
+ // An audio buffer should have been allocated (either in the constructor or after queuing the current buffer)
+ if (!_audiobuf) {
+ warning("[TheoraDecoder::queueAudio] Invalid audio buffer");
+ return false;
+ }
+
bool queuedAudio = false;
for (;;) {
@@ -454,6 +460,11 @@ bool TheoraDecoder::queueAudio() {
// The audio mixer is now responsible for the old audio buffer.
// We need to create a new one.
_audiobuf = (ogg_int16_t *)malloc(AUDIOFD_FRAGSIZE * sizeof(ogg_int16_t));
+ if (!_audiobuf) {
+ warning("[TheoraDecoder::queueAudio] Cannot allocate memory for audio buffer");
+ return false;
+ }
+
_audiobufFill = 0;
queuedAudio = true;
}
diff --git a/engines/sword25/gfx/image/art.cpp b/engines/sword25/gfx/image/art.cpp
index 2df8bd4f3e..e9715481c6 100644
--- a/engines/sword25/gfx/image/art.cpp
+++ b/engines/sword25/gfx/image/art.cpp
@@ -151,6 +151,8 @@ ArtSVP *art_svp_from_vpath(ArtVpath *vpath) {
n_segs_max = 16;
svp = (ArtSVP *)malloc(sizeof(ArtSVP) +
(n_segs_max - 1) * sizeof(ArtSVPSeg));
+ if (!svp)
+ error("[art_svp_from_vpath] Cannot allocate memory");
dir = 0;
n_points = 0;
@@ -167,9 +169,14 @@ ArtSVP *art_svp_from_vpath(ArtVpath *vpath) {
if (points != NULL && n_points >= 2) {
if (n_segs == n_segs_max) {
n_segs_max <<= 1;
- svp = (ArtSVP *)realloc(svp, sizeof(ArtSVP) +
- (n_segs_max - 1) *
- sizeof(ArtSVPSeg));
+ ArtSVP *tmp = (ArtSVP *)realloc(svp, sizeof(ArtSVP) +
+ (n_segs_max - 1) *
+ sizeof(ArtSVPSeg));
+
+ if (!tmp)
+ error("Cannot reallocate memory in art_svp_from_vpath()");
+
+ svp = tmp;
}
svp->segs[n_segs].n_points = n_points;
svp->segs[n_segs].dir = (dir > 0);
@@ -204,9 +211,14 @@ ArtSVP *art_svp_from_vpath(ArtVpath *vpath) {
y = points[n_points - 1].y;
if (n_segs == n_segs_max) {
n_segs_max <<= 1;
- svp = (ArtSVP *)realloc(svp, sizeof(ArtSVP) +
- (n_segs_max - 1) *
- sizeof(ArtSVPSeg));
+ ArtSVP *tmp = (ArtSVP *)realloc(svp, sizeof(ArtSVP) +
+ (n_segs_max - 1) *
+ sizeof(ArtSVPSeg));
+
+ if (!tmp)
+ error("Cannot reallocate memory in art_svp_from_vpath()");
+
+ svp = tmp;
}
svp->segs[n_segs].n_points = n_points;
svp->segs[n_segs].dir = (dir > 0);
@@ -246,9 +258,14 @@ ArtSVP *art_svp_from_vpath(ArtVpath *vpath) {
if (n_points >= 2) {
if (n_segs == n_segs_max) {
n_segs_max <<= 1;
- svp = (ArtSVP *)realloc(svp, sizeof(ArtSVP) +
- (n_segs_max - 1) *
- sizeof(ArtSVPSeg));
+ ArtSVP *tmp = (ArtSVP *)realloc(svp, sizeof(ArtSVP) +
+ (n_segs_max - 1) *
+ sizeof(ArtSVPSeg));
+
+ if (!tmp)
+ error("Cannot reallocate memory in art_svp_from_vpath()");
+
+ svp = tmp;
}
svp->segs[n_segs].n_points = n_points;
svp->segs[n_segs].dir = (dir > 0);
@@ -1026,6 +1043,8 @@ struct _ArtPriPoint {
static ArtPriQ *art_pri_new(void) {
ArtPriQ *result = art_new(ArtPriQ, 1);
+ if (!result)
+ error("[art_pri_new] Cannot allocate memory");
result->n_items = 0;
result->n_items_max = 16;
@@ -1157,8 +1176,13 @@ static int art_svp_writer_rewind_add_segment(ArtSvpWriter *self, int wind_left,
(swr->n_segs_max - 1) *
sizeof(ArtSVPSeg));
swr->svp = svp;
- swr->n_points_max = art_renew(swr->n_points_max, int,
- swr->n_segs_max);
+ int *tmp = art_renew(swr->n_points_max, int,
+ swr->n_segs_max);
+
+ if (!tmp)
+ error("Cannot reallocate memory in art_svp_writer_rewind_add_segment()");
+
+ swr->n_points_max = tmp;
}
seg = &svp->segs[seg_num];
seg->n_points = 1;
@@ -1169,6 +1193,9 @@ static int art_svp_writer_rewind_add_segment(ArtSvpWriter *self, int wind_left,
seg->bbox.x1 = x;
seg->bbox.y1 = y;
seg->points = art_new(ArtPoint, init_n_points_max);
+ if (!seg->points)
+ error("[art_svp_writer_rewind_add_segment] Cannot allocate memory");
+
seg->points[0].x = x;
seg->points[0].y = y;
return seg_num;
@@ -1213,6 +1240,8 @@ ArtSVP *art_svp_writer_rewind_reap(ArtSvpWriter *self) {
ArtSvpWriter *art_svp_writer_rewind_new(ArtWindRule rule) {
ArtSvpWriterRewind *result = art_new(ArtSvpWriterRewind, 1);
+ if (!result)
+ error("[art_svp_writer_rewind_new] Cannot allocate memory");
result->super.add_segment = art_svp_writer_rewind_add_segment;
result->super.add_point = art_svp_writer_rewind_add_point;
@@ -1222,6 +1251,9 @@ ArtSvpWriter *art_svp_writer_rewind_new(ArtWindRule rule) {
result->n_segs_max = 16;
result->svp = (ArtSVP *)malloc(sizeof(ArtSVP) +
(result->n_segs_max - 1) * sizeof(ArtSVPSeg));
+ if (!result->svp)
+ error("[art_svp_writer_rewind_new] Cannot allocate memory");
+
result->svp->n_segs = 0;
result->n_points_max = art_new(int, result->n_segs_max);
@@ -1392,6 +1424,9 @@ static void art_svp_intersect_push_pt(ArtIntersectCtx *ctx, ArtActiveSeg *seg,
seg->y1 = y;
pri_pt = art_new(ArtPriPoint, 1);
+ if (!pri_pt)
+ error("[art_svp_intersect_push_pt] Cannot allocate memory");
+
pri_pt->x = x;
pri_pt->y = y;
pri_pt->user_data = seg;
@@ -1855,6 +1890,8 @@ static void art_svp_intersect_horiz(ArtIntersectCtx *ctx, ArtActiveSeg *seg,
return;
hs = art_new(ArtActiveSeg, 1);
+ if (!hs)
+ error("[art_svp_intersect_horiz] Cannot allocate memory");
hs->flags = ART_ACTIVE_FLAGS_DEL | (seg->flags & ART_ACTIVE_FLAGS_OUT);
if (seg->flags & ART_ACTIVE_FLAGS_OUT) {
@@ -1997,6 +2034,8 @@ static void art_svp_intersect_add_seg(ArtIntersectCtx *ctx, const ArtSVPSeg *in_
ArtActiveSeg *last = NULL;
ArtActiveSeg *left, *right;
ArtPriPoint *pri_pt = art_new(ArtPriPoint, 1);
+ if (!pri_pt)
+ error("[art_svp_intersect_add_seg] Cannot allocate memory");
seg->flags = 0;
seg->in_seg = in_seg;
@@ -2166,6 +2205,9 @@ void art_svp_intersector(const ArtSVP *in, ArtSvpWriter *out) {
return;
ctx = art_new(ArtIntersectCtx, 1);
+ if (!ctx)
+ error("[art_svp_intersector] Cannot allocate memory");
+
ctx->in = in;
ctx->out = out;
pq = art_pri_new();
@@ -2178,6 +2220,9 @@ void art_svp_intersector(const ArtSVP *in, ArtSvpWriter *out) {
ctx->in_curs = 0;
first_point = art_new(ArtPriPoint, 1);
+ if (!first_point)
+ error("[art_svp_intersector] Cannot allocate memory");
+
first_point->x = in->segs[0].points[0].x;
first_point->y = in->segs[0].points[0].y;
first_point->user_data = NULL;
@@ -2319,6 +2364,8 @@ static void art_svp_render_delete_active(int *active_segs, int j, int n_active_s
ArtSVPRenderAAIter *art_svp_render_aa_iter(const ArtSVP *svp,
int x0, int y0, int x1, int y1) {
ArtSVPRenderAAIter *iter = art_new(ArtSVPRenderAAIter, 1);
+ if (!iter)
+ error("[art_svp_render_aa_iter] Cannot allocate memory");
iter->svp = svp;
iter->y = y0;
diff --git a/engines/sword25/gfx/image/art.h b/engines/sword25/gfx/image/art.h
index bfeb31cc30..8c9c97bc57 100644
--- a/engines/sword25/gfx/image/art.h
+++ b/engines/sword25/gfx/image/art.h
@@ -51,10 +51,13 @@ namespace Sword25 {
#define art_expand(p, type, max) \
do { \
if(max) {\
- p = art_renew(p, type, max <<= 1); \
+ type *tmp = art_renew(p, type, max <<= 1); \
+ if (!tmp) error("Cannot reallocate memory for art data"); \
+ p = tmp; \
} else { \
max = 1; \
p = art_new(type, 1); \
+ if (!p) error("Cannot allocate memory for art data"); \
} \
} while (0)
diff --git a/engines/sword25/gfx/image/vectorimage.cpp b/engines/sword25/gfx/image/vectorimage.cpp
index 9235ec2fcf..b9ce5f7e00 100644
--- a/engines/sword25/gfx/image/vectorimage.cpp
+++ b/engines/sword25/gfx/image/vectorimage.cpp
@@ -321,6 +321,8 @@ ArtBpath *VectorImage::storeBez(ArtBpath *bez, int lineStyle, int fillStyle0, in
bez[*bezNodes].code = ART_END;
ArtBpath *bez1 = art_new(ArtBpath, *bezNodes + 1);
+ if (!bez1)
+ error("[VectorImage::storeBez] Cannot allocate memory");
for (int i = 0; i <= *bezNodes; i++)
bez1[i] = bez[i];
diff --git a/engines/sword25/gfx/image/vectorimagerenderer.cpp b/engines/sword25/gfx/image/vectorimagerenderer.cpp
index 97dad3346d..6d4dc213f2 100644
--- a/engines/sword25/gfx/image/vectorimagerenderer.cpp
+++ b/engines/sword25/gfx/image/vectorimagerenderer.cpp
@@ -270,6 +270,9 @@ ArtVpath *art_vpath_cat(ArtVpath *a, ArtVpath *b) {
len_a = art_vpath_len(a);
len_b = art_vpath_len(b);
dest = art_new(ArtVpath, len_a + len_b + 1);
+ if (!dest)
+ error("[art_vpath_cat] Cannot allocate memory");
+
p = dest;
for (int i = 0; i < len_a; i++)
@@ -299,6 +302,8 @@ ArtVpath *art_vpath_reverse(ArtVpath *a) {
len = art_vpath_len(a);
dest = art_new(ArtVpath, len + 1);
+ if (!dest)
+ error("[art_vpath_reverse] Cannot allocate memory");
for (i = 0; i < len; i++) {
it = a[len - i - 1];
@@ -371,6 +376,8 @@ void drawBez(ArtBpath *bez1, ArtBpath *bez2, byte *buffer, int width, int height
int size = art_vpath_len(vec);
ArtVpath *vect = art_new(ArtVpath, size + 1);
+ if (!vect)
+ error("[drawBez] Cannot allocate memory");
int k;
for (k = 0; k < size; k++) {
diff --git a/engines/sword25/package/packagemanager.h b/engines/sword25/package/packagemanager.h
index c57c30636d..b0c6718008 100644
--- a/engines/sword25/package/packagemanager.h
+++ b/engines/sword25/package/packagemanager.h
@@ -141,6 +141,9 @@ public:
uint fileSize;
char *data = (char *)getFile(fileName, &fileSize);
char *result = (char *)malloc(fileSize + strlen(versionStr) + 1);
+ if (!result)
+ error("[PackageManager::getXmlFile] Cannot allocate memory");
+
strcpy(result, versionStr);
Common::copy(data, data + fileSize, result + strlen(versionStr));
result[fileSize + strlen(versionStr)] = '\0';
diff --git a/engines/teenagent/resources.cpp b/engines/teenagent/resources.cpp
index 9e69383215..597ca670c0 100644
--- a/engines/teenagent/resources.cpp
+++ b/engines/teenagent/resources.cpp
@@ -106,13 +106,20 @@ void Resources::loadOff(Graphics::Surface &surface, byte *palette, int id) {
error("invalid background %d", id);
return;
}
- byte buf[64768];
- off.read(id, buf, sizeof(buf));
+
+ const uint bufferSize = 64768;
+ byte *buf = (byte *)malloc(bufferSize);
+ if (!buf)
+ error("[Resources::loadOff] Cannot allocate buffer");
+
+ off.read(id, buf, bufferSize);
byte *src = buf;
byte *dst = (byte *)surface.pixels;
memcpy(dst, src, 64000);
memcpy(palette, buf + 64000, 768);
+
+ free(buf);
}
Common::SeekableReadStream *Resources::loadLan(uint32 id) const {
diff --git a/engines/teenagent/teenagent.cpp b/engines/teenagent/teenagent.cpp
index 724f75be2f..0289b994e6 100644
--- a/engines/teenagent/teenagent.cpp
+++ b/engines/teenagent/teenagent.cpp
@@ -216,14 +216,22 @@ Common::Error TeenAgentEngine::loadGameState(int slot) {
Resources *res = Resources::instance();
- assert(res->dseg.size() >= 0x6478 + 0x777a);
- char data[0x777a];
+ const uint dataSize = 0x777a;
+ assert(res->dseg.size() >= 0x6478 + dataSize);
+
+ char *data = (char *)malloc(dataSize);
+ if (!data)
+ error("[TeenAgentEngine::loadGameState] Cannot allocate buffer");
+
in->seek(0);
- if (in->read(data, 0x777a) != 0x777a) {
+ if (in->read(data, dataSize) != dataSize) {
+ free(data);
return Common::kReadingFailed;
}
- memcpy(res->dseg.ptr(0x6478), data, sizeof(data));
+ memcpy(res->dseg.ptr(0x6478), data, dataSize);
+
+ free(data);
scene->clear();
inventory->activate(false);
@@ -290,17 +298,32 @@ bool TeenAgentEngine::showCDLogo() {
if (!cdlogo.exists("cdlogo.res") || !cdlogo.open("cdlogo.res"))
return true;
- byte bg[0xfa00];
- byte palette[3*256];
+ const uint bgSize = 0xfa00;
+ const uint paletteSize = 3 * 256;
+
+ byte *bg = (byte *)malloc(bgSize);
+ if (!bg)
+ error("[TeenAgentEngine::showCDLogo] Cannot allocate background buffer");
+
+ byte *palette = (byte *)malloc(paletteSize);
+ if (!palette) {
+ free(bg);
+ error("[TeenAgentEngine::showCDLogo] Cannot allocate palette buffer");
+ }
+
+ cdlogo.read(bg, bgSize);
+ cdlogo.read(palette, paletteSize);
- cdlogo.read(bg, sizeof(bg));
- cdlogo.read(palette, sizeof(palette));
- for (uint c = 0; c < 3*256; ++c)
+ for (uint c = 0; c < paletteSize; ++c)
palette[c] *= 4;
+
_system->getPaletteManager()->setPalette(palette, 0, 0x100);
_system->copyRectToScreen(bg, 320, 0, 0, 320, 200);
_system->updateScreen();
+ free(bg);
+ free(palette);
+
for(uint i = 0; i < 20; ++i) {
int r = skipEvents();
if (r != 0)
@@ -317,43 +340,66 @@ bool TeenAgentEngine::showLogo() {
if (!logo.open("unlogic.res"))
return true;
- byte bg[0xfa00];
- byte palette[3*256];
-
Common::ScopedPtr<Common::SeekableReadStream> frame(logo.getStream(1));
if (!frame)
return true;
- frame->read(bg, sizeof(bg));
- frame->read(palette, sizeof(palette));
- for (uint c = 0; c < 3*256; ++c)
+ const uint bgSize = 0xfa00;
+ const uint paletteSize = 3 * 256;
+
+ byte *bg = (byte *)malloc(bgSize);
+ if (!bg)
+ error("[TeenAgentEngine::showLogo] Cannot allocate background buffer");
+
+ byte *palette = (byte *)malloc(paletteSize);
+ if (!palette) {
+ free(bg);
+ error("[TeenAgentEngine::showLogo] Cannot allocate palette buffer");
+ }
+
+ frame->read(bg, bgSize);
+ frame->read(palette, paletteSize);
+
+ for (uint c = 0; c < paletteSize; ++c)
palette[c] *= 4;
+
_system->getPaletteManager()->setPalette(palette, 0, 0x100);
+ free(palette);
+
uint n = logo.fileCount();
for(uint f = 0; f < 4; ++f)
for(uint i = 2; i <= n; ++i) {
{
int r = skipEvents();
- if (r != 0)
+ if (r != 0) {
+ free(bg);
return r > 0? true: false;
+ }
}
_system->copyRectToScreen(bg, 320, 0, 0, 320, 200);
frame.reset(logo.getStream(i));
- if (!frame)
+ if (!frame) {
+ free(bg);
return true;
+ }
Surface s;
s.load(frame, Surface::kTypeOns);
- if (s.empty())
+ if (s.empty()) {
+ free(bg);
return true;
+ }
_system->copyRectToScreen((const byte *)s.pixels, s.w, s.x, s.y, s.w, s.h);
_system->updateScreen();
_system->delayMillis(100);
}
+
+ free(bg);
+
return true;
}
@@ -364,29 +410,53 @@ bool TeenAgentEngine::showMetropolis() {
FilePack varia;
varia.open("varia.res");
- byte palette[3*256];
+ const uint paletteSize = 3 * 256;
+ byte *palette = (byte *)malloc(paletteSize);
+ if (!palette)
+ error("[TeenAgentEngine::showMetropolis] Cannot allocate palette buffer");
+
{
Common::ScopedPtr<Common::SeekableReadStream> s(varia.getStream(5));
- s->read(palette, sizeof(palette));
- for (uint c = 0; c < 3*256; ++c)
+ s->read(palette, paletteSize);
+ for (uint c = 0; c < paletteSize; ++c)
palette[c] *= 4;
}
_system->getPaletteManager()->setPalette(palette, 0, 0x100);
- byte varia_6[21760], varia_9[18302];
- varia.read(6, varia_6, sizeof(varia_6));
- varia.read(9, varia_9, sizeof(varia_9));
+ free(palette);
- byte colors[56 * 160 * 2];
- memset(colors, 0, sizeof(colors));
+ const uint varia6Size = 21760;
+ const uint varia9Size = 18302;
+ byte *varia_6 = (byte *)malloc(varia6Size);
+ byte *varia_9 = (byte *)malloc(varia9Size);
+ if (!varia_6 || !varia_9) {
+ free(varia_6);
+ free(varia_9);
+
+ error("[TeenAgentEngine::showMetropolis] Cannot allocate buffer");
+ }
+
+ varia.read(6, varia_6, varia6Size);
+ varia.read(9, varia_9, varia9Size);
+
+ const uint colorsSize = 56 * 160 * 2;
+ byte *colors = (byte *)malloc(colorsSize);
+ if (!colors)
+ error("[TeenAgentEngine::showMetropolis] Cannot allocate colors buffer");
+
+ memset(colors, 0, colorsSize);
int logo_y = -56;
for(uint f = 0; f < 300; ++f) {
{
int r = skipEvents();
- if (r != 0)
+ if (r != 0) {
+ free(varia_6);
+ free(varia_9);
+ free(colors);
return r > 0? true: false;
+ }
}
Graphics::Surface *surface = _system->lockScreen();
@@ -441,6 +511,11 @@ bool TeenAgentEngine::showMetropolis() {
_system->updateScreen();
_system->delayMillis(100);
}
+
+ free(varia_6);
+ free(varia_9);
+ free(colors);
+
return true;
}
diff --git a/engines/toon/path.cpp b/engines/toon/path.cpp
index dde7be07d0..43a134e39b 100644
--- a/engines/toon/path.cpp
+++ b/engines/toon/path.cpp
@@ -342,8 +342,15 @@ next:
curX = destx;
curY = desty;
- int32 retPathX[4096];
- int32 retPathY[4096];
+ int32 *retPathX = (int32 *)malloc(4096 * sizeof(int32));
+ int32 *retPathY = (int32 *)malloc(4096 * sizeof(int32));
+ if (!retPathX || !retPathY) {
+ free(retPathX);
+ free(retPathY);
+
+ error("[PathFinding::findPath] Cannot allocate pathfinding buffers");
+ }
+
int32 numpath = 0;
retPathX[numpath] = curX;
@@ -377,8 +384,12 @@ next:
}
}
- if (bestX < 0 || bestY < 0)
+ if (bestX < 0 || bestY < 0) {
+ free(retPathX);
+ free(retPathY);
+
return 0;
+ }
retPathX[numpath] = bestX;
retPathY[numpath] = bestY;
@@ -389,6 +400,10 @@ next:
memcpy(_tempPathX, retPathX, sizeof(int32) * numpath);
memcpy(_tempPathY, retPathY, sizeof(int32) * numpath);
+
+ free(retPathX);
+ free(retPathY);
+
return true;
}
@@ -396,6 +411,9 @@ next:
curY = bestY;
}
+ free(retPathX);
+ free(retPathY);
+
return false;
}
diff --git a/engines/touche/resource.cpp b/engines/touche/resource.cpp
index 8f4752e912..6df6fc0e5f 100644
--- a/engines/touche/resource.cpp
+++ b/engines/touche/resource.cpp
@@ -468,14 +468,22 @@ void ToucheEngine::res_loadSprite(int num, int index) {
if (size > spr->size) {
debug(8, "Reallocating memory for sprite %d (index %d), %d bytes needed", num, index, size - spr->size);
spr->size = size;
- if (spr->ptr) {
- spr->ptr = (uint8 *)realloc(spr->ptr, size);
- } else {
- spr->ptr = (uint8 *)malloc(size);
- }
- if (!spr->ptr) {
- error("Unable to reallocate memory for sprite %d (%d bytes)", num, size);
+
+ uint8 *buffer = NULL;
+ if (spr->ptr)
+ buffer = (uint8 *)realloc(spr->ptr, size);
+
+ if (!buffer) {
+ // Free previously allocated sprite (when realloc failed)
+ free(spr->ptr);
+
+ buffer = (uint8 *)malloc(size);
}
+
+ if (!buffer)
+ error("[ToucheEngine::res_loadSprite] Unable to reallocate memory for sprite %d (%d bytes)", num, size);
+
+ spr->ptr = buffer;
}
for (int i = 0; i < _currentImageHeight; ++i) {
res_decodeScanLineImageRLE(spr->ptr + _currentImageWidth * i, _currentImageWidth);
diff --git a/engines/tsage/resources.cpp b/engines/tsage/resources.cpp
index d24c564a1f..e6a561f3a7 100644
--- a/engines/tsage/resources.cpp
+++ b/engines/tsage/resources.cpp
@@ -237,8 +237,13 @@ byte *TLib::getResource(uint16 id, bool suppressErrors) {
uint16 ctrCurrent = 0x102, ctrMax = 0x200;
uint16 word_48050 = 0, currentToken = 0, word_48054 =0;
byte byte_49068 = 0, byte_49069 = 0;
- DecodeReference table[0x1000];
- for (int i = 0; i < 0x1000; ++i) {
+
+ const uint tableSize = 0x1000;
+ DecodeReference *table = (DecodeReference *)malloc(tableSize * sizeof(DecodeReference));
+ if (!table)
+ error("[TLib::getResource] Cannot allocate table buffer");
+
+ for (int i = 0; i < tableSize; ++i) {
table[i].vByte = table[i].vWord = 0;
}
Common::Stack<uint16> tokenList;
@@ -302,6 +307,8 @@ byte *TLib::getResource(uint16 id, bool suppressErrors) {
}
}
+ free(table);
+
assert(bytesWritten == re->uncompressedSize);
delete compStream;
return dataOut;
diff --git a/engines/tsage/ringworld_logic.cpp b/engines/tsage/ringworld_logic.cpp
index 1dd905b3b6..58501172af 100644
--- a/engines/tsage/ringworld_logic.cpp
+++ b/engines/tsage/ringworld_logic.cpp
@@ -1333,9 +1333,20 @@ void RingworldGame::start() {
RING_INVENTORY._scanner._sceneNumber = 1;
RING_INVENTORY._ring._sceneNumber = 1;
+ int slot = -1;
+
+ if (ConfMan.hasKey("save_slot")) {
+ slot = ConfMan.getInt("save_slot");
+ Common::String file = _vm->generateSaveName(slot);
+ Common::InSaveFile *in = _vm->_system->getSavefileManager()->openForLoading(file);
+ if (in)
+ delete in;
+ else
+ slot = -1;
+ }
- if (ConfMan.hasKey("save_slot"))
- _globals->_sceneHandler._loadGameSlot = ConfMan.getInt("save_slot");
+ if (slot >= 0)
+ _globals->_sceneHandler._loadGameSlot = slot;
else
// Switch to the title screen
_globals->_sceneManager.setNewScene(1000);
diff --git a/engines/tsage/ringworld_scenes1.cpp b/engines/tsage/ringworld_scenes1.cpp
index 29b7c9b997..7fe2610fd7 100644
--- a/engines/tsage/ringworld_scenes1.cpp
+++ b/engines/tsage/ringworld_scenes1.cpp
@@ -342,7 +342,7 @@ void Scene20::Action2::signal() {
}
case 8:
scene->_sound.release();
- scene->_sound.fadeOut(this);
+ _globals->_soundHandler.fadeOut(this);
break;
case 9:
SceneItem::display(0, 0, LIST_END);