[Scummvm-cvs-logs] scummvm master -> d9ede873d5043cc6c389afdcb6ec403cb9655a9a

Littleboy littleboy22 at gmail.com
Thu Jun 23 02:27:09 CEST 2011


This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
3c2a9b292f LASTEXPRESS: Move Fight class to its own folder
434a2e66b1 LASTEXPRESS: Refactor Fight class
85bb5ef45e LASTEXPRESS: Fix leak and corruption of event handlers function pointers
27934d061e CONFIGURE: Fix Unity checks
2b53aff08b GIT: Ignore Qt Creator project files
d9ede873d5 BACKENDS: Add missing enumeration value and GUID for compilation under older versions of mingw64


Commit: 3c2a9b292f5a851529fb0196eab662fd9996a459
    https://github.com/scummvm/scummvm/commit/3c2a9b292f5a851529fb0196eab662fd9996a459
Author: Littleboy (littleboy at users.sourceforge.net)
Date: 2011-06-22T16:31:30-07:00

Commit Message:
LASTEXPRESS: Move Fight class to its own folder

Changed paths:
  A engines/lastexpress/fight/fight.cpp
  A engines/lastexpress/fight/fight.h
  R engines/lastexpress/game/fight.cpp
  R engines/lastexpress/game/fight.h
    engines/lastexpress/debug.cpp
    engines/lastexpress/entities/anna.cpp
    engines/lastexpress/entities/ivo.cpp
    engines/lastexpress/entities/milos.cpp
    engines/lastexpress/entities/salko.cpp
    engines/lastexpress/entities/vesna.cpp
    engines/lastexpress/game/logic.cpp
    engines/lastexpress/game/menu.cpp
    engines/lastexpress/module.mk



diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp
index 4b7c5f6..d5c7df0 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 0bedda4..bce99ad 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 35f4ccf..861c3cf 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 587c43c..45fd688 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 4d510bb..bbaff5f 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 8e09dbf..79ac934 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 0000000..5b3530f
--- /dev/null
+++ b/engines/lastexpress/fight/fight.cpp
@@ -0,0 +1,1583 @@
+/* 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/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/fight/fight.h b/engines/lastexpress/fight/fight.h
new file mode 100644
index 0000000..a33cc93
--- /dev/null
+++ b/engines/lastexpress/fight/fight.h
@@ -0,0 +1,266 @@
+/* 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/fight.cpp b/engines/lastexpress/game/fight.cpp
deleted file mode 100644
index ecc43be..0000000
--- 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 a33cc93..0000000
--- 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 0911c60..a8a2ce8 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 f9eef26..27a43d8 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/module.mk b/engines/lastexpress/module.mk
index 12fbb4f..3827c16 100644
--- a/engines/lastexpress/module.mk
+++ b/engines/lastexpress/module.mk
@@ -45,10 +45,10 @@ MODULE_OBJS := \
 	entities/verges.o \
 	entities/vesna.o \
 	entities/yasmin.o \
+	fight/fight.o \
 	game/action.o \
 	game/beetle.o \
 	game/entities.o \
-	game/fight.o \
 	game/inventory.o \
 	game/logic.o \
 	game/menu.o \


Commit: 434a2e66b1fc59e1b7732591cfefd7e389905817
    https://github.com/scummvm/scummvm/commit/434a2e66b1fc59e1b7732591cfefd7e389905817
Author: Littleboy (littleboy at users.sourceforge.net)
Date: 2011-06-22T16:31:32-07:00

Commit Message:
LASTEXPRESS: Refactor Fight class

 - Replace structs holding function pointers by proper classes
 - Move each fighter functions to separate files

Changed paths:
  A engines/lastexpress/fight/fighter.cpp
  A engines/lastexpress/fight/fighter.h
  A engines/lastexpress/fight/fighter_anna.cpp
  A engines/lastexpress/fight/fighter_anna.h
  A engines/lastexpress/fight/fighter_ivo.cpp
  A engines/lastexpress/fight/fighter_ivo.h
  A engines/lastexpress/fight/fighter_milos.cpp
  A engines/lastexpress/fight/fighter_milos.h
  A engines/lastexpress/fight/fighter_salko.cpp
  A engines/lastexpress/fight/fighter_salko.h
  A engines/lastexpress/fight/fighter_vesna.cpp
  A engines/lastexpress/fight/fighter_vesna.h
    engines/lastexpress/fight/fight.cpp
    engines/lastexpress/fight/fight.h
    engines/lastexpress/module.mk



diff --git a/engines/lastexpress/fight/fight.cpp b/engines/lastexpress/fight/fight.cpp
index 5b3530f..685b3b0 100644
--- a/engines/lastexpress/fight/fight.cpp
+++ b/engines/lastexpress/fight/fight.cpp
@@ -22,16 +22,19 @@
 
 #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/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"
@@ -39,34 +42,24 @@
 #include "lastexpress/lastexpress.h"
 #include "lastexpress/resource.h"
 
-#include "common/func.h"
-
 namespace LastExpress {
 
-#define CALL_FUNCTION0(fighter, name) \
-	(*fighter->name)(fighter)
+Fight::FightData::FightData() {
+	player = NULL;
+	opponent = NULL;
 
-#define CALL_FUNCTION1(fighter, name, a) \
-	(*fighter->name)(fighter, a)
+	index = 0;
 
-#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);
+	isFightRunning = false;
+}
 
-#define CHECK_SEQUENCE2(fighter, value) \
-	(fighter->frame->getInfo()->field_33 & value)
+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(LastExpressEngine *engine) : _engine(engine), _data(NULL), _endType(kFightEndLost), _state(0), _handleTimer(false) {
+}
 
 Fight::~Fight() {
 	clearData();
@@ -79,7 +72,6 @@ Fight::~Fight() {
 //////////////////////////////////////////////////////////////////////////
 // Events
 //////////////////////////////////////////////////////////////////////////
-
 void Fight::eventMouse(const Common::Event &ev) {
 	if (!_data || _data->index)
 		return;
@@ -120,9 +112,9 @@ void Fight::eventMouse(const Common::Event &ev) {
 			_engine->getCursor()->setStyle((CursorStyle)hotspot->cursor);
 
 			// Call player function
-			if (CALL_FUNCTION1(_data->player, canInteract, (FightAction)hotspot->action)) {
+			if (_data->player->canInteract((Fighter::FightAction)hotspot->action)) {
 				if (ev.type == Common::EVENT_LBUTTONUP)
-					CALL_FUNCTION1(_data->player, handleAction, (FightAction)hotspot->action);
+					_data->player->handleAction((Fighter::FightAction)hotspot->action);
 			} else {
 				_engine->getCursor()->setStyle(kCursorNormal);
 			}
@@ -175,17 +167,17 @@ void Fight::handleTick(const Common::Event &ev, bool isProcessing) {
 		return;
 
 	SceneHotspot *hotspot = NULL;
-	if (!getScenes()->get(getState()->scene)->checkHotSpot(ev.mouse, &hotspot) || !CALL_FUNCTION1(_data->player, canInteract, (FightAction)hotspot->action)) {
+	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);
 	}
 
-	CALL_FUNCTION0(_data->player, update);
-	CALL_FUNCTION0(_data->opponent, update);
+	_data->player->update();
+	_data->opponent->update();
 
 	// Draw sequences
-	if (!_data->isRunning)
+	if (!_data->isFightRunning)
 		return;
 
 	if (isProcessing)
@@ -201,7 +193,6 @@ void Fight::handleTick(const Common::Event &ev, bool isProcessing) {
 //////////////////////////////////////////////////////////////////////////
 // Setup
 //////////////////////////////////////////////////////////////////////////
-
 Fight::FightEndType Fight::setup(FightType type) {
 	if (_data)
 		error("Fight::setup - calling fight setup again while a fight is already in progress!");
@@ -282,7 +273,7 @@ Fight::FightEndType Fight::setup(FightType type) {
 
 	// Start fight
 	_endType = kFightEndLost;
-	while (_data->isRunning) {
+	while (_data->isFightRunning) {
 		if (_engine->handleEvents())
 			continue;
 
@@ -298,10 +289,9 @@ Fight::FightEndType Fight::setup(FightType type) {
 //////////////////////////////////////////////////////////////////////////
 // Status
 //////////////////////////////////////////////////////////////////////////
-
 void Fight::setStopped() {
 	if (_data)
-		_data->isRunning = false;
+		_data->isFightRunning = false;
 }
 
 void Fight::bailout(FightEndType type) {
@@ -313,80 +303,19 @@ void Fight::bailout(FightEndType type) {
 //////////////////////////////////////////////////////////////////////////
 // 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!");
@@ -396,41 +325,44 @@ void Fight::loadData(FightType type) {
 		break;
 
 	case kFightMilos:
-		loadMilosPlayer();
-		loadMilosOpponent();
+		_data->player   = new FighterPlayerMilos(_engine);
+		_data->opponent = new FighterOpponentMilos(_engine);
 		break;
 
 	case kFightAnna:
-		loadAnnaPlayer();
-		loadAnnaOpponent();
+		_data->player   = new FighterPlayerAnna(_engine);
+		_data->opponent = new FighterOpponentAnna(_engine);
 		break;
 
 	case kFightIvo:
-		loadIvoPlayer();
-		loadIvoOpponent();
+		_data->player   = new FighterPlayerIvo(_engine);
+		_data->opponent = new FighterOpponentIvo(_engine);
 		break;
 
 	case kFightSalko:
-		loadSalkoPlayer();
-		loadSalkoOpponent();
+		_data->player   = new FighterPlayerSalko(_engine);
+		_data->opponent = new FighterOpponentSalko(_engine);
 		break;
 
 	case kFightVesna:
-		loadVesnaPlayer();
-		loadVesnaOpponent();
+		_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->isRunning = true;
+	_data->isFightRunning = true;
 
 	if (_state < 5) {
-		setSequenceAndDraw(_data->player, 0, kFightSequenceType0);
-		setSequenceAndDraw(_data->opponent, 0, kFightSequenceType0);
+		_data->player->setSequenceAndDraw(0, Fighter::kFightSequenceType0);
+		_data->opponent->setSequenceAndDraw(0, Fighter::kFightSequenceType0);
 		goto end_load;
 	}
 
@@ -439,22 +371,22 @@ void Fight::loadData(FightType type) {
 		break;
 
 	case kFightMilos:
-		_data->opponent->countdown = 1;
-		setSequenceAndDraw(_data->player, 4, kFightSequenceType0);
-		setSequenceAndDraw(_data->opponent, 0, kFightSequenceType0);
+		_data->opponent->setCountdown(1);
+		_data->player->setSequenceAndDraw(4, Fighter::kFightSequenceType0);
+		_data->opponent->setSequenceAndDraw(0, Fighter::kFightSequenceType0);
 		break;
 
 	case kFightIvo:
-		_data->opponent->countdown = 1;
-		setSequenceAndDraw(_data->player, 3, kFightSequenceType0);
-		setSequenceAndDraw(_data->opponent, 6, kFightSequenceType0);
+		_data->opponent->setCountdown(1);
+		_data->player->setSequenceAndDraw(3, Fighter::kFightSequenceType0);
+		_data->opponent->setSequenceAndDraw(6, Fighter::kFightSequenceType0);
 		break;
 
 	case kFightVesna:
-		_data->opponent->countdown = 1;
-		setSequenceAndDraw(_data->player, 0, kFightSequenceType0);
-		setSequenceAndDraw(_data->player, 3, kFightSequenceType2);
-		setSequenceAndDraw(_data->opponent, 5, kFightSequenceType0);
+		_data->opponent->setCountdown(1);
+		_data->player->setSequenceAndDraw(0, Fighter::kFightSequenceType0);
+		_data->player->setSequenceAndDraw(3, Fighter::kFightSequenceType2);
+		_data->opponent->setSequenceAndDraw(5, Fighter::kFightSequenceType0);
 		break;
 	}
 
@@ -464,1120 +396,12 @@ end_load:
 	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;
-		}
-	}
+void Fight::setOpponents() {
+	_data->player->setOpponent(_data->opponent);
+	_data->opponent->setOpponent(_data->player);
 
-	updateOpponent(opponent);
+	_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
index a33cc93..fffb520 100644
--- a/engines/lastexpress/fight/fight.h
+++ b/engines/lastexpress/fight/fight.h
@@ -57,16 +57,14 @@
 
 #include "lastexpress/eventhandler.h"
 
-#include "common/array.h"
-
 namespace LastExpress {
 
 class LastExpressEngine;
 class Sequence;
-class SequenceFrame;
 
-//////////////////////////////////////////////////////////////////////////
-// TODO : objectify!
+class Fighter;
+class Opponent;
+
 class Fight : public EventHandler {
 public:
 	enum FightEndType {
@@ -83,82 +81,15 @@ public:
 	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:
-	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;
@@ -167,20 +98,10 @@ private:
 		Sequence *sequences[20];
 		Common::String names[20];
 
-		bool isRunning;
-
-		FightData() {
-			player = new Fighter();
-			opponent = new Opponent();
-
-			// Set opponents
-			player->opponent = opponent;
-			opponent->opponent = player;
+		bool isFightRunning;
 
-			index = 0;
-
-			isRunning = false;
-		}
+		FightData();
+		~FightData();
 	};
 
 	LastExpressEngine *_engine;
@@ -193,72 +114,10 @@ private:
 	// 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
+	// Data
 	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);
+	void clearData();
+	void setOpponents();
 };
 
 } // End of namespace LastExpress
diff --git a/engines/lastexpress/fight/fighter.cpp b/engines/lastexpress/fight/fighter.cpp
new file mode 100644
index 0000000..fcd6918
--- /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 0000000..e37fe49
--- /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 0000000..db2ab54
--- /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 0000000..abb6f9d
--- /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 0000000..423b6b4
--- /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 0000000..ca54fea
--- /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 0000000..46e4bde
--- /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 0000000..2126dd1
--- /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 0000000..795dd41
--- /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 0000000..0a2a615
--- /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 0000000..a246010
--- /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 0000000..5c8ec85
--- /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/module.mk b/engines/lastexpress/module.mk
index 3827c16..e811519 100644
--- a/engines/lastexpress/module.mk
+++ b/engines/lastexpress/module.mk
@@ -46,6 +46,12 @@ MODULE_OBJS := \
 	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 \


Commit: 85bb5ef45e6b62b52317df2d83a7ad8663dbdfc0
    https://github.com/scummvm/scummvm/commit/85bb5ef45e6b62b52317df2d83a7ad8663dbdfc0
Author: Littleboy (littleboy at users.sourceforge.net)
Date: 2011-06-22T16:31:34-07:00

Commit Message:
LASTEXPRESS: Fix leak and corruption of event handlers function pointers

 - Add better error handling
 - Properly delete previous event handlers when setting new ones or restoring from backup

Changed paths:
    engines/lastexpress/lastexpress.cpp



diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp
index e162998..120e6eb 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;


Commit: 27934d061ecef6456460265171ebccfc065d26e0
    https://github.com/scummvm/scummvm/commit/27934d061ecef6456460265171ebccfc065d26e0
Author: Littleboy (littleboy at users.sourceforge.net)
Date: 2011-06-22T16:31:36-07:00

Commit Message:
CONFIGURE: Fix Unity checks

 - Redirect pkgconfig errors to log file
 - Remove duplicated -lunity option
 - Fix output of selected taskbar integration when libunity is selected

Changed paths:
    configure



diff --git a/configure b/configure
index 04ca85f..8c89afa 100755
--- a/configure
+++ b/configure
@@ -2995,8 +2995,8 @@ if test "$_libunity" = auto ; then
 			;;
 		*)
 			# Unity has a lots of dependencies, update the libs and cflags var with them
-			LIBUNITY_LIBS="$LIBUNITY_LIBS $(pkg-config --libs unity = 3.8.4)"
-			LIBUNITY_CFLAGS="$LIBUNITY_CFLAGS $(pkg-config --cflags unity = 3.8.4)"
+			LIBUNITY_LIBS="$LIBUNITY_LIBS $(pkg-config --libs unity = 3.8.4 2>> "$TMPLOG")"
+			LIBUNITY_CFLAGS="$LIBUNITY_CFLAGS $(pkg-config --cflags unity = 3.8.4 2>> "$TMPLOG")"
 			_libunity=no
 			cat > $TMPC << EOF
 #include <unity.h>
@@ -3005,12 +3005,12 @@ int main(void) {
 	return 0;
 }
 EOF
-			cc_check $LIBUNITY_CFLAGS $LIBUNITY_LIBS -lunity && _libunity=yes
+			cc_check $LIBUNITY_CFLAGS $LIBUNITY_LIBS && _libunity=yes
 			;;
 	esac
 fi
 if test "$_libunity" = yes ; then
-	LIBS="$LIBS $LIBUNITY_LIBS -lunity"
+	LIBS="$LIBS $LIBUNITY_LIBS"
 	INCLUDES="$INCLUDES $LIBUNITY_CFLAGS"
 fi
 define_in_config_h_if_yes "$_libunity" 'USE_TASKBAR_UNITY'
@@ -3204,7 +3204,7 @@ if test "$_taskbar" = yes; then
 		echo "win32"
 		;;
 	*)
-		if test "$_unity" = yes; then
+		if test "$_libunity" = yes; then
 			echo "unity"
 		else
 			echo "$_taskbar"


Commit: 2b53aff08b6949cf089630703876b8640406d374
    https://github.com/scummvm/scummvm/commit/2b53aff08b6949cf089630703876b8640406d374
Author: Littleboy (littleboy at users.sourceforge.net)
Date: 2011-06-22T16:31:38-07:00

Commit Message:
GIT: Ignore Qt Creator project files

Changed paths:
    .gitignore



diff --git a/.gitignore b/.gitignore
index 6294cb4..9cb3984 100644
--- a/.gitignore
+++ b/.gitignore
@@ -155,3 +155,9 @@ ipch/
 #Ignore default Visual Studio build folders
 [Dd]ebug/
 [Rr]elease/
+
+#Ignore Qt Creator project files
+ScummVM.config
+ScummVM.creator
+ScummVM.files
+ScummVM.includes


Commit: d9ede873d5043cc6c389afdcb6ec403cb9655a9a
    https://github.com/scummvm/scummvm/commit/d9ede873d5043cc6c389afdcb6ec403cb9655a9a
Author: Littleboy (littleboy at users.sourceforge.net)
Date: 2011-06-22T17:22:26-07:00

Commit Message:
BACKENDS: Add missing enumeration value and GUID for compilation under older versions of mingw64

Changed paths:
    backends/taskbar/win32/mingw-compat.h



diff --git a/backends/taskbar/win32/mingw-compat.h b/backends/taskbar/win32/mingw-compat.h
index 06968b6..bf03db9 100644
--- a/backends/taskbar/win32/mingw-compat.h
+++ b/backends/taskbar/win32/mingw-compat.h
@@ -24,7 +24,7 @@
  */
 
 // TODO: Remove header when the latest changes to the Windows SDK have been integrated into MingW
-//       For reference, the interface definitions here are imported the SDK headers and from the 
+//       For reference, the interface definitions here are imported the SDK headers and from the
 //       EcWin7 project (https://code.google.com/p/dukto/)
 
 #ifndef BACKEND_WIN32_TASKBAR_MINGW_H
@@ -42,8 +42,14 @@
 #include <commctrl.h>
 #include <initguid.h>
 #include <shlwapi.h>
+#include <shlguid.h>
 #define CMIC_MASK_ASYNCOK SEE_MASK_ASYNCOK
 
+// Misc enumeration values
+#ifndef SHARD_LINK
+#define SHARD_LINK 0x00000006
+#endif
+
 // Taskbar GUID definitions
 DEFINE_GUID(CLSID_TaskbarList,0x56fdf344,0xfd6d,0x11d0,0x95,0x8a,0x0,0x60,0x97,0xc9,0xa0,0x90);
 DEFINE_GUID(IID_ITaskbarList3,0xea1afb91,0x9e28,0x4b86,0x90,0xE9,0x9e,0x9f,0x8a,0x5e,0xef,0xaf);






More information about the Scummvm-git-logs mailing list