[Scummvm-git-logs] scummvm master -> faa58ab0981db521b090b5aa6aaf990984f6bb94

mduggan noreply at scummvm.org
Sat Apr 22 10:39:09 UTC 2023


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

Summary:
faa58ab098 TETRAEDGE: Implement more Amerzone support features


Commit: faa58ab0981db521b090b5aa6aaf990984f6bb94
    https://github.com/scummvm/scummvm/commit/faa58ab0981db521b090b5aa6aaf990984f6bb94
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2023-04-22T19:37:29+09:00

Commit Message:
TETRAEDGE: Implement more Amerzone support features

Game now plays intro movie and loads first scene, but scene is not yet drawn.

Changed paths:
    engines/tetraedge/game/amerzone_game.cpp
    engines/tetraedge/game/amerzone_game.h
    engines/tetraedge/game/application.cpp
    engines/tetraedge/game/application.h
    engines/tetraedge/game/game.cpp
    engines/tetraedge/game/lua_binds.cpp
    engines/tetraedge/te/te_core.cpp
    engines/tetraedge/te/te_mesh.cpp
    engines/tetraedge/te/te_pick_mesh.cpp
    engines/tetraedge/te/te_pick_mesh.h
    engines/tetraedge/te/te_ray_intersection.cpp
    engines/tetraedge/te/te_ray_intersection.h
    engines/tetraedge/te/te_warp.cpp
    engines/tetraedge/te/te_warp.h
    engines/tetraedge/te/te_warp_bloc.cpp
    engines/tetraedge/te/te_warp_bloc.h
    engines/tetraedge/te/te_warp_marker.h


diff --git a/engines/tetraedge/game/amerzone_game.cpp b/engines/tetraedge/game/amerzone_game.cpp
index 906a8eb2aaf..e8c80951d80 100644
--- a/engines/tetraedge/game/amerzone_game.cpp
+++ b/engines/tetraedge/game/amerzone_game.cpp
@@ -104,7 +104,7 @@ bool AmerzoneGame::changeWarp(const Common::String &zone, const Common::String &
 
 	dotpos = sceneXml.rfind('.');
 	Common::String sceneLua = sceneXml.substr(0, dotpos);
-	sceneLua += ".xml";
+	sceneLua += ".lua";
 	_luaScript.load(core->findFile(sceneLua));
 	_luaScript.execute();
 	_luaScript.execute("OnWarpEnter");
@@ -117,7 +117,12 @@ bool AmerzoneGame::changeWarp(const Common::String &zone, const Common::String &
 }
 
 void AmerzoneGame::draw() {
-	error("TODO: Implement AmerzoneGame::draw");
+	if (!_running)
+		return;
+	if (_warpX)
+		_warpX->render();
+	if (_warpY)
+		_warpY->render();
 }
 
 void AmerzoneGame::enter() {
@@ -164,12 +169,14 @@ void AmerzoneGame::enter() {
 	_warpX = new TeWarp();
 	_warpX->setRotation(app->frontOrientationLayout().rotation());
 	_warpX->init();
+	// TODO: Set FOV here?
 	_warpX->setVisible(true, false);
 	_luaContext.create();
 	_luaScript.attachToContext(&_luaContext);
 
-	warning("TODO: Finish AmerzoneGame::enter");
+	// Game also sets up fade sprites, which is set up in Game.
 
+	_running = true;
 	_playedTimer.start();
 	_edgeButtonRolloverCount = 0;
 
@@ -196,8 +203,64 @@ void AmerzoneGame::initLoadedBackupData() {
 	changeWarp(app->firstWarpPath(), app->firstScene(), true);
 }
 
+void AmerzoneGame::isInDrag(bool inDrag) {
+	const Common::Point mousePt = g_engine->getInputMgr()->lastMousePos();
+	if (inDrag != _isInDrag) {
+		_isInDrag = inDrag;
+		if (inDrag) {
+			// Start drag operation
+			_mouseDragStart = mousePt;
+			_mouseDragLast = mousePt;
+			_decelAnimX.stop();
+			_decelAnimY.stop();
+			_dragTimer.stop();
+			_dragTimer.start();
+		} else {
+			// Finish drag operation
+			_dragTimer.timeElapsed();
+			Application *app = g_engine->getApplication();
+			TeVector3f32 mouseDir(mousePt.x - _mouseDragLast.x, mousePt.y - _mouseDragLast.y, 0);
+			if (app->inverseLook())
+				mouseDir = mouseDir * -1.0f;
+			const TeMatrix4x4 layoutRot = app->frontOrientationLayout().rotation().toTeMatrix();
+			TeVector3f32 dest = layoutRot * mouseDir;
+			dest.x() /= 2;
+			dest.y() /= 2;
+			_speedX = CLIP(dest.x(), -10000.0f, 10000.0f);
+			_speedY = CLIP(dest.y(), -10000.0f, 10000.0f);
+			startDecelerationAnim();
+		}
+	}
+}
+
 void AmerzoneGame::leave(bool flag) {
-	error("TODO: Implement AmerzoneGame::leave");
+	_inGameGui.unload();
+	_question2.unload();
+	Application *app = g_engine->getApplication();
+	app->frontOrientationLayout().removeChild(&_dialog2);
+	_dialog2.unload();
+	if (_warpX) {
+		delete _warpX;
+		_warpX = nullptr;
+	}
+	if (_warpY) {
+		saveBackup("save.xml");
+	}
+	app->frontOrientationLayout().removeChild(&_inventoryMenu);
+	_inventoryMenu.unload();
+
+	// TODO: game does this.. doesn't this leak?
+	_warpY = nullptr;
+	_prevWarpY = nullptr;
+
+	// TODO: Game goes through a list of (cached?) warps here to clean up.
+	warning("TODO: Finish AmerzoneGame::leave");
+
+	_notifier.unload();
+	_luaContext.destroy();
+	_running = false;
+	_playedTimer.stop();
+	_music.stop();
 }
 
 bool AmerzoneGame::onChangeWarpAnimFinished() {
@@ -231,19 +294,30 @@ bool AmerzoneGame::onAnimationFinished(const Common::String &anim) {
 }
 
 bool AmerzoneGame::onMouseLeftUp(const Common::Point &pt) {
-	error("TODO: Implement AmerzoneGame::onMouseLeftUp");
+	_warpY->setMouseLeftUpForMakers();
+	TeVector3f32 offset = TeVector3f32(pt - _mouseDragStart);
+	if (offset.length() > 20.0f)
+		_warpY->checkObjectEvents();
+	isInDrag(false);
+	return false;
 }
 
 bool AmerzoneGame::onMouseLeftDown(const Common::Point &pt) {
-	error("TODO: Implement AmerzoneGame::onMouseLeftDown");
+	isInDrag(true);
+	return false;
 }
 
 bool AmerzoneGame::onObjectClick(const Common::String &obj) {
 	error("TODO: Implement AmerzoneGame::onObjectClick");
 }
 
+bool AmerzoneGame::onPuzzleEnterAnimLoadTime() {
+	error("TODO: Implement AmerzoneGame::onPuzzleEnterAnimLoadTime");
+}
+
 void AmerzoneGame::optimizeWarpResources() {
-	error("TODO: Implement AmerzoneGame::optimizeWarpResources");
+	// Note: original calls this OptimizeWarpRessources
+	warning("TODO: Implement AmerzoneGame::optimizeWarpResources");
 }
 
 void AmerzoneGame::setAngleX(float angle) {
@@ -284,11 +358,19 @@ void AmerzoneGame::setAngleY(float angle) {
 		_orientationY = 45.0f;
 }
 
-void AmerzoneGame::speedX(float speed) {
+void AmerzoneGame::showPuzzle(int puzzleNo, int puzParam1, int puzParam2) {
+	_puzzleNo = puzzleNo;
+	_puzParam1 = puzParam1;
+	_puzParam2 = puzParam2;
+	onPuzzleEnterAnimLoadTime();
+}
+
+
+void AmerzoneGame::speedX(const float &speed) {
 	_speedX = CLIP(speed, -10000.0f, 10000.0f);
 }
 
-void AmerzoneGame::speedY(float speed) {
+void AmerzoneGame::speedY(const float &speed) {
 	_speedY = CLIP(speed, -10000.0f, 10000.0f);
 }
 
@@ -313,6 +395,36 @@ void AmerzoneGame::startChangeWarpAnim() {
 	}
 }
 
+void AmerzoneGame::startDecelerationAnim() {
+	_decelAnimX.stop();
+	_decelAnimY.stop();
+
+	Common::Array<float> curve;
+	curve.push_back(0);
+	curve.push_back(0.35f);
+	curve.push_back(0.68f);
+	curve.push_back(0.85f);
+	curve.push_back(0.93f);
+	curve.push_back(0.97f);
+	curve.push_back(1);
+
+	_decelAnimX.setCurve(curve);
+	_decelAnimX._duration = 400;
+	_decelAnimX._startVal = _speedX;
+	_decelAnimX._endVal = 0;
+	_decelAnimX._callbackObj = this;
+	_decelAnimX._callbackMethod = &AmerzoneGame::speedX;
+	_decelAnimX.play();
+
+	_decelAnimY.setCurve(curve);
+	_decelAnimY._duration = 400;
+	_decelAnimY._startVal = _speedY;
+	_decelAnimY._endVal = 0;
+	_decelAnimY._callbackObj = this;
+	_decelAnimY._callbackMethod = &AmerzoneGame::speedY;
+	_decelAnimY.play();
+}
+
 void AmerzoneGame::update() {
 	TeInputMgr *inputMgr = g_engine->getInputMgr();
 
diff --git a/engines/tetraedge/game/amerzone_game.h b/engines/tetraedge/game/amerzone_game.h
index 291e61ae40a..71bae1c9c13 100644
--- a/engines/tetraedge/game/amerzone_game.h
+++ b/engines/tetraedge/game/amerzone_game.h
@@ -33,7 +33,6 @@ namespace Tetraedge {
 class AmerzoneGame : public Tetraedge::Game {
 public:
 	AmerzoneGame();
-
 	~AmerzoneGame() {}
 
 	virtual void addToBag(const Common::String &objname) override;
@@ -47,21 +46,29 @@ public:
 	virtual bool onDialogFinished(const Common::String &val) override;
 	virtual bool onVideoFinished() override;
 
-private:
-	void changeSpeedToMouseDirection();
+	TeWarp *warpY() { return _warpY; }
+	const Common::String lastObjectHitName() const { return _lastObjectHitName; }
+
 	void setAngleX(float angle);
 	void setAngleY(float angle);
-	void speedX(float speed);
-	void speedY(float speed);
+	void showPuzzle(int puzzleNo, int puzParam1, int puzParam2);
+
+private:
+	void changeSpeedToMouseDirection();
+	void isInDrag(bool val);
+	void speedX(const float &speed);
+	void speedY(const float &speed);
 
 	bool onHelpButtonValidated();
 	bool onAnimationFinished(const Common::String &anim);
 	bool onMouseLeftUp(const Common::Point &pt);
 	bool onMouseLeftDown(const Common::Point &pt);
 	bool onObjectClick(const Common::String &obj);
+	bool onPuzzleEnterAnimLoadTime();
 
 	void optimizeWarpResources();
 	void startChangeWarpAnim();
+	void startDecelerationAnim();
 	bool onChangeWarpAnimFinished();
 
 	TeTimer _dragTimer;
@@ -75,15 +82,17 @@ private:
 	float _speedY;
 	bool _isInDrag;
 	int _edgeButtonRolloverCount;
-	TeVector2s32 _mouseDragStart;
-	TeVector2s32 _mouseDragLast;
-	/*
-	TeCurveAnim<AmerzoneGame, float> _decelAnimX;
-	TeCurveAnim<AmerzoneGame, float> _decelAnimY;
-	*/
+	Common::Point _mouseDragStart;
+	Common::Point _mouseDragLast;
+	int _puzzleNo;
+	int _puzParam1;
+	int _puzParam2;
+	TeCurveAnim2<AmerzoneGame, float> _decelAnimX;
+	TeCurveAnim2<AmerzoneGame, float> _decelAnimY;
 	TeWarp *_warpX;
 	TeWarp *_warpY;
 	TeWarp *_prevWarpY;
+	Common::String _lastObjectHitName;
 };
 
 } // end namespace Tetraedge
diff --git a/engines/tetraedge/game/application.cpp b/engines/tetraedge/game/application.cpp
index 0ba25825c9f..aa097cc4896 100644
--- a/engines/tetraedge/game/application.cpp
+++ b/engines/tetraedge/game/application.cpp
@@ -301,7 +301,7 @@ void Application::create() {
 	onMainWindowSizeChanged();
 	_splashScreens.enter();
 
-	_drawShadows = (!ConfMan.getBool("disable_shadows"));
+	_drawShadows = !(g_engine->gameIsAmerzone() || ConfMan.getBool("disable_shadows"));
 
 	// Note: this is not in the original, but seems like a good place to do it..
 	g_engine->getGame()->loadUnlockedArtwork();
diff --git a/engines/tetraedge/game/application.h b/engines/tetraedge/game/application.h
index f24ccd069d0..513def1c88b 100644
--- a/engines/tetraedge/game/application.h
+++ b/engines/tetraedge/game/application.h
@@ -88,6 +88,7 @@ public:
 	MainMenu &mainMenu() { return _mainMenu; }
 	OptionsMenu &optionsMenu() { return _optionsMenu; }
 	TeMusic &music() { return _music; }
+	TeMusic &videoMusic() { return _videoMusic; }
 	Credits &credits() { return _credits; }
 	UpsellScreen &upsellScreen() { return _upsellScreen; }
 	TeVisualFade &visualFade() { return _visFade; }
@@ -131,6 +132,7 @@ private:
 
 	TeVisualFade _visFade;
 	TeMusic _music;
+	TeMusic _videoMusic; // Only used in Amerzone
 	TeSpriteLayout _appSpriteLayout;
 	TeSpriteLayout _mouseCursorLayout;
 	TeSpriteLayout _autoSaveIcon1;
diff --git a/engines/tetraedge/game/game.cpp b/engines/tetraedge/game/game.cpp
index 576577bd23b..3b7870f4c0e 100644
--- a/engines/tetraedge/game/game.cpp
+++ b/engines/tetraedge/game/game.cpp
@@ -291,7 +291,7 @@ bool Game::playMovie(const Common::String &vidPath, const Common::String &musicP
 	TeButtonLayout *skipVideoButton = _inGameGui.buttonLayoutChecked("skipVideoButton");
 	skipVideoButton->setVisible(false);
 
-	TeMusic &music = app->music();
+	TeMusic &music = (g_engine->gameIsAmerzone() ? app->videoMusic() : app->music());
 	music.stop();
 	music.setChannelName("video");
 	music.repeat(false);
diff --git a/engines/tetraedge/game/lua_binds.cpp b/engines/tetraedge/game/lua_binds.cpp
index ad5f50507ad..ed01d3ab476 100644
--- a/engines/tetraedge/game/lua_binds.cpp
+++ b/engines/tetraedge/game/lua_binds.cpp
@@ -28,8 +28,10 @@
 #include "tetraedge/game/lua_binds.h"
 #include "tetraedge/game/object3d.h"
 #include "tetraedge/game/syberia_game.h"
+#include "tetraedge/game/amerzone_game.h"
 #include "tetraedge/to_lua.h"
 #include "tetraedge/te/te_core.h"
+#include "tetraedge/te/te_sound_manager.h"
 #include "tetraedge/te/te_lua_thread.h"
 #include "tetraedge/te/te_particle.h"
 
@@ -203,10 +205,19 @@ static int tolua_ExportedFunctions_Selected00(lua_State *L) {
 	error("#ferror in function 'Selected': %d %d %s", err.index, err.array, err.type);
 }
 
-static void TakeObject(const Common::String &obj) {
+static void TakeObject_Amerzone(const Common::String &obj) {
+	AmerzoneGame *game = dynamic_cast<AmerzoneGame *>(g_engine->getGame());
+	assert(game);
+	game->luaContext().setGlobal(game->lastObjectHitName(), true);
+	game->warpY()->takeObject(game->lastObjectHitName());
+	if (!obj.empty()) {
+		game->addToBag(obj);
+		g_engine->getSoundManager()->playFreeSound("Sounds/SFX/N_prendre.ogg", 1.0, "sfx");
+	}
+}
+
+static void TakeObject_Syberia(const Common::String &obj) {
 	Game *game = g_engine->getGame();
-	// TODO: Set global _lastHitObjectName?? How is it used?
-	//game->luaContext().setGlobal(_lastHitObjectName, true);
 	if (!obj.empty())
 		game->addToBag(obj);
 }
@@ -215,7 +226,10 @@ static int tolua_ExportedFunctions_TakeObject00(lua_State *L) {
 	tolua_Error err;
 	if (tolua_isstring(L, 1, 0, &err) && tolua_isnoobj(L, 2, &err)) {
 		Common::String s1(tolua_tostring(L, 1, nullptr));
-		TakeObject(s1);
+		if (g_engine->gameIsAmerzone())
+			TakeObject_Amerzone(s1);
+		else
+			TakeObject_Syberia(s1);
 		return 0;
 	}
 	error("#ferror in function 'TakeObject': %d %d %s", err.index, err.array, err.type);
@@ -428,6 +442,11 @@ static int tolua_ExportedFunctions_ChangeWarp00(lua_State *L) {
 		bool flag = tolua_toboolean(L, 3, false);
 		ChangeWarp(s1, s2, flag);
 		return 0;
+	} else if (g_engine->gameIsAmerzone() && tolua_isstring(L, 1, 0, &err) && tolua_isboolean(L, 2, 1, &err) && tolua_isnoobj(L, 3, &err)) {
+		Common::String s1(tolua_tostring(L, 1, nullptr));
+		bool flag = tolua_toboolean(L, 2, false);
+		ChangeWarp(s1, "", flag);
+		return 0;
 	}
 	error("#ferror in function 'ChangeWarp': %d %d %s", err.index, err.array, err.type);
 }
@@ -2651,7 +2670,7 @@ static int tolua_EnableParticle(lua_State *L) {
 
 
 
-void LuaOpenBinds(lua_State *L) {
+static void LuaOpenBinds_Syberia(lua_State *L) {
 	tolua_open(L);
 	tolua_module(L, 0, 0);
 	tolua_beginmodule(L, 0);
@@ -2827,6 +2846,228 @@ void LuaOpenBinds(lua_State *L) {
 	tolua_endmodule(L);
 }
 
+// ======== Amerzone-specific bind functions below ========
+
+static int tolua_ExportedFunctions_PrintDebugMessage00(lua_State *L) {
+	tolua_Error err;
+	if (tolua_isstring(L, 1, 0, &err) && tolua_isnoobj(L, 2, &err)) {
+		Common::String s1(tolua_tostring(L, 1, nullptr));
+		debug("%s", s1.c_str());
+		return 0;
+	}
+	error("#ferror in function 'PrintDebugMessage': %d %d %s", err.index, err.array, err.type);
+}
+
+static void PutObject(const Common::String &name, bool enable) {
+	AmerzoneGame *game = dynamic_cast<AmerzoneGame *>(g_engine->getGame());
+	assert(game);
+	game->warpY()->putObject(name, enable);
+}
+
+static int tolua_ExportedFunctions_PutObject00(lua_State *L) {
+	tolua_Error err;
+	if (tolua_isstring(L, 1, 0, &err) && tolua_isboolean(L, 2, 1, &err)
+			&& tolua_isnoobj(L, 3, &err)) {
+		Common::String s1(tolua_tostring(L, 1, nullptr));
+		bool b1 = tolua_toboolean(L, 2, 1);
+		PutObject(s1, b1);
+		return 0;
+	}
+	error("#ferror in function 'PutObject': %d %d %s", err.index, err.array, err.type);
+}
+
+static void SetAnimationPart(const Common::String &name, int x, int y, int z, bool flag) {
+	AmerzoneGame *game = dynamic_cast<AmerzoneGame *>(g_engine->getGame());
+	assert(game);
+	game->warpY()->setAnimationPart(name, x, y, z, flag);
+}
+
+static int tolua_ExportedFunctions_StartAnimationPart00(lua_State *L) {
+	tolua_Error err;
+	if (tolua_isstring(L, 1, 0, &err) && tolua_isnumber(L, 2, 0, &err)
+		&& tolua_isnumber(L, 3, 0, &err) && tolua_isnumber(L, 4, 1, &err)
+		&& tolua_isboolean(L, 5, 1, &err) && tolua_isnoobj(L, 6, &err)) {
+		Common::String s1(tolua_tostring(L, 1, nullptr));
+		double d1 = tolua_tonumber(L, 2, 0.0);
+		double d2 = tolua_tonumber(L, 3, 0.0);
+		double d3 = tolua_tonumber(L, 4, -1.0);
+		bool b1 = tolua_tonumber(L, 5, 0);
+		SetAnimationPart(s1, (int)d1, (int)d2, (int)d3, b1);
+		return 0;
+	}
+	error("#ferror in function 'SetAnimationPart': %d %d %s", err.index, err.array, err.type);
+}
+
+static void RemoveObject_Amerzone(const Common::String &name) {
+	AmerzoneGame *game = dynamic_cast<AmerzoneGame *>(g_engine->getGame());
+	assert(game);
+	game->warpY()->takeObject(name);
+}
+
+static int tolua_ExportedFunctions_RemoveObject00_Amerzone(lua_State *L) {
+	tolua_Error err;
+	if (tolua_isstring(L, 1, 0, &err) && tolua_isnoobj(L, 2, &err)) {
+		Common::String s1(tolua_tostring(L, 1, nullptr));
+		RemoveObject_Amerzone(s1);
+		return 0;
+	}
+	error("#ferror in function 'RemoveObject': %d %d %s", err.index, err.array, err.type);
+}
+
+static int tolua_ExportedFunctions_AddToBag00(lua_State *L) {
+	tolua_Error err;
+	if (tolua_isstring(L, 1, 0, &err) && tolua_isnoobj(L, 2, &err)) {
+		Common::String s1(tolua_tostring(L, 1, nullptr));
+		debug("%s", s1.c_str());
+		return 0;
+	}
+	error("#ferror in function 'PrintDebugMessage': %d %d %s", err.index, err.array, err.type);
+}
+
+void SaveGame(const Common::String &name) {
+	g_engine->getGame()->saveBackup(name);
+}
+
+static int tolua_ExportedFunctions_SaveGame00(lua_State *L) {
+	tolua_Error err;
+	if (tolua_isstring(L, 1, 0, &err) && tolua_isnoobj(L, 2, &err)) {
+		Common::String s1(tolua_tostring(L, 1, nullptr));
+		SaveGame(s1);
+		return 0;
+	}
+	error("#ferror in function 'SaveGame': %d %d %s", err.index, err.array, err.type);
+}
+
+static void SetMarker(const Common::String &name, int imgNo, long markerId) {
+	AmerzoneGame *game = dynamic_cast<AmerzoneGame *>(g_engine->getGame());
+	assert(game);
+	game->warpY()->configMarker(name, imgNo, markerId);
+}
+
+static int tolua_ExportedFunctions_SetMarker00(lua_State *L) {
+	tolua_Error err;
+	if (tolua_isstring(L, 1, 0, &err) && tolua_isnumber(L, 2, 0, &err)
+		&& tolua_isnumber(L, 3, 0, &err) && tolua_isnoobj(L, 4, &err)) {
+		Common::String s1(tolua_tostring(L, 1, nullptr));
+		double d1 = tolua_tonumber(L, 2, 0.0);
+		double d2 = tolua_tonumber(L, 3, 0.0);
+		SetMarker(s1, (int)d1, (long)d2);
+		return 0;
+	}
+	error("#ferror in function 'SetMarker': %d %d %s", err.index, err.array, err.type);
+}
+
+static void LookAt(int x, int y) {
+	AmerzoneGame *game = dynamic_cast<AmerzoneGame *>(g_engine->getGame());
+	assert(game);
+	game->setAngleX(-x);
+	int yval = y + -360;
+	if (y < 90)
+		yval = y;
+	game->setAngleY(-yval);
+}
+
+static int tolua_ExportedFunctions_LookAt00(lua_State *L) {
+	tolua_Error err;
+	if (tolua_isnumber(L, 1, 0, &err) && tolua_isnumber(L, 2, 0, &err)
+			&& tolua_isnoobj(L, 3, &err)) {
+		double d1 = tolua_tonumber(L, 1, 0.0);
+		double d2 = tolua_tonumber(L, 2, 0.0);
+		LookAt((int)d1, (int)d2);
+		return 0;
+	}
+	error("#ferror in function 'LookAt': %d %d %s", err.index, err.array, err.type);
+}
+
+static void ShowPuzzle(int x, int y = 0, int z = 0) {
+	AmerzoneGame *game = dynamic_cast<AmerzoneGame *>(g_engine->getGame());
+	assert(game);
+	game->showPuzzle(x, y, z);
+}
+
+static int tolua_ExportedFunctions_ShowPuzzle00(lua_State *L) {
+	tolua_Error err;
+	if (tolua_isnumber(L, 1, 0, &err) && tolua_isnoobj(L, 2, &err)) {
+		double d1 = tolua_tonumber(L, 1, 0.0);
+		ShowPuzzle((int)d1);
+		return 0;
+	}
+	error("#ferror in function 'ShowPuzzle': %d %d %s", err.index, err.array, err.type);
+}
+
+static int tolua_ExportedFunctions_ShowPuzzle01(lua_State *L) {
+	tolua_Error err;
+	if (tolua_isnumber(L, 1, 0, &err) && tolua_isnumber(L, 2, 0, &err)
+			&& tolua_isnumber(L, 3, 0, &err) && tolua_isnoobj(L, 4, &err)) {
+		double d1 = tolua_tonumber(L, 1, 0.0);
+		double d2 = tolua_tonumber(L, 2, 0.0);
+		double d3 = tolua_tonumber(L, 3, 0.0);
+		ShowPuzzle((int)d1, (int)d2, (int)d3);
+		return 0;
+	}
+	return tolua_ExportedFunctions_ShowPuzzle00(L);
+}
+
+
+static void LuaOpenBinds_Amerzone(lua_State *L) {
+	tolua_open(L);
+	tolua_module(L, 0, 0);
+	tolua_beginmodule(L, 0);
+
+	tolua_function(L, "Selected", tolua_ExportedFunctions_Selected00);
+	//tolua_function(L, "TestObjectLimit", tolua_ExportedFunctions_TestObjectLimit00); // unused
+	tolua_function(L, "PrintDebugMessage", tolua_ExportedFunctions_PrintDebugMessage00);
+	//tolua_function(L, "SetCondition", tolua_ExportedFunctions_SetCondition00); // unused
+	//tolua_function(L, "UnsetCondition", tolua_ExportedFunctions_UnsetCondition00); // unused
+	tolua_function(L, "TakeObject", tolua_ExportedFunctions_TakeObject00);
+	tolua_function(L, "PutObject", tolua_ExportedFunctions_PutObject00);
+	// This is not the same as RemoveObject from Syberia.
+	tolua_function(L, "RemoveObject", tolua_ExportedFunctions_RemoveObject00_Amerzone);
+	tolua_function(L, "StartAnimationPart", tolua_ExportedFunctions_StartAnimationPart00);
+	//tolua_function(L, "StartAnimation", tolua_ExportedFunctions_StartAnimation00); // unused
+	//tolua_function(L, "AnimationSetToEnd", tolua_ExportedFunctions_AnimationSetToEnd00); // unused
+	//tolua_function(L, "AnimationSetToStart", tolua_ExportedFunctions_AnimationSetToStart00); // unused
+	//tolua_function(L, "DrawText", tolua_ExportedFunctions_DrawText00); // unused
+	tolua_function(L, "ChangeWarp", tolua_ExportedFunctions_ChangeWarp00);
+	tolua_function(L, "AddToBag", tolua_ExportedFunctions_AddToBag00);
+	// Note: same as RemoveObject in Syberia
+	tolua_function(L, "RemoveFromBag", tolua_ExportedFunctions_RemoveObject00);
+	tolua_function(L, "RemoveFromBag", tolua_ExportedFunctions_RemoveObject01);
+	tolua_function(L, "SaveGame", tolua_ExportedFunctions_SaveGame00);
+	tolua_function(L, "SetMarker", tolua_ExportedFunctions_SetMarker00);
+	tolua_function(L, "LookAt", tolua_ExportedFunctions_LookAt00);
+	//tolua_function(L, "Wait", tolua_ExportedFunctions_Wait00); // unused
+	tolua_function(L, "PlaySound", tolua_ExportedFunctions_PlaySound00);
+	tolua_function(L, "StopSound", tolua_ExportedFunctions_StopSound00);
+	tolua_function(L, "PlayMusic", tolua_ExportedFunctions_PlayMusic00);
+	tolua_function(L, "ShowPuzzle", tolua_ExportedFunctions_ShowPuzzle00);
+	tolua_function(L, "ShowPuzzle", tolua_ExportedFunctions_ShowPuzzle01);
+	tolua_function(L, "PlayMovie", tolua_ExportedFunctions_PlayMovie00);
+	//tolua_function(L, "SetFOV", tolua_ExportedFunctions_SetFOV00); // unused
+	//tolua_function(L, "LoadSprite", tolua_ExportedFunctions_LoadSprite00); // unused
+	//tolua_function(L, "UnloadSprite", tolua_ExportedFunctions_UnloadSprite00); // unused
+	//tolua_function(L, "PushAnswer", tolua_ExportedFunctions_PushAnswer00); // unused
+	tolua_function(L, "FinishGame", tolua_ExportedFunctions_FinishGame00);
+	tolua_function(L, "ShowDocument", tolua_ExportedFunctions_ShowDocument00);
+	tolua_function(L, "HideDocument", tolua_ExportedFunctions_HideDocument00);
+	tolua_function(L, "AddDocument", tolua_ExportedFunctions_AddDocument00);
+	//tolua_function(L, "ClearImportantDocuments", tolua_ExportedFunctions_ClearImportantDocuments00); // unused
+	//tolua_function(L, "SetImportantDocument", tolua_ExportedFunctions_SetImportantDocument00); // unused
+	tolua_function(L, "TestFileFlagSystemFlag", tolua_ExportedFunctions_TestFileFlagSystemFlag00);
+	//tolua_function(L, "SetViewAngleXLimits", tolua_ExportedFunctions_SetViewAngleXLimits00); // unused
+	//tolua_function(L, "SetViewAngleYLimits", tolua_ExportedFunctions_SetViewAngleYLimits00); // unused
+
+	tolua_endmodule(L);
+}
+
+void LuaOpenBinds(lua_State *L) {
+	if (g_engine->gameIsAmerzone())
+		LuaOpenBinds_Amerzone(L);
+	else
+		LuaOpenBinds_Syberia(L);
+}
+
+
 }
 
 } // end namespace Tetraedge
diff --git a/engines/tetraedge/te/te_core.cpp b/engines/tetraedge/te/te_core.cpp
index 8e5f11a9d4e..430136e7b59 100644
--- a/engines/tetraedge/te/te_core.cpp
+++ b/engines/tetraedge/te/te_core.cpp
@@ -192,7 +192,8 @@ Common::FSNode TeCore::findFile(const Common::Path &path) const {
 		"iPhone-iPad/DefaultDistributor",		// iOS Syb 1 paid
 		"Android-iPhone-iPad/iPhone-iPad",		// iOS Syb 2
 		"PC-MacOSX-Android-iPhone-iPad",		// iOS Syb 2
-		"Full/HD"								// Amerzone
+		"Full/HD",								// Amerzone
+		"Part1-Full/PC-MacOSX/DefaultDistributor" // Amerzone
 	};
 
 	const Common::Path langs[] = {
diff --git a/engines/tetraedge/te/te_mesh.cpp b/engines/tetraedge/te/te_mesh.cpp
index 0a23828d5b6..14e1c4fadee 100644
--- a/engines/tetraedge/te/te_mesh.cpp
+++ b/engines/tetraedge/te/te_mesh.cpp
@@ -42,6 +42,15 @@ void TeMesh::defaultMaterial(const TeIntrusivePtr<Te3DTexture> &texture) {
 	_materials[0] = TeMaterial(texture, mode);
 }
 
+TeMaterial *TeMesh::material(uint index) {
+	assert(!_materials.empty());
+	if (index < _materials.size()) {
+		return &_materials[index];
+	} else {
+		return &_materials[0];
+	}
+}
+
 const TeMaterial *TeMesh::material(uint index) const {
 	assert(!_materials.empty());
 	if (index < _materials.size()) {
diff --git a/engines/tetraedge/te/te_pick_mesh.cpp b/engines/tetraedge/te/te_pick_mesh.cpp
index 696a85c8ac6..df7e31ed1ee 100644
--- a/engines/tetraedge/te/te_pick_mesh.cpp
+++ b/engines/tetraedge/te/te_pick_mesh.cpp
@@ -66,11 +66,10 @@ void TePickMesh::getTriangle(uint triNum, TeVector3f32 &v1, TeVector3f32 &v2, Te
 	v3 = _verticies[triNum * 3 + 2];
 }
 
-bool TePickMesh::intersect(const TeVector3f32 &origin, const TeVector3f32 &dir, TeVector3f32 &ptOut, float &lenOut) {
+bool TePickMesh::intersect(const Math::Ray &ray, TeVector3f32 &ptOut, float &lenOut) {
 	if (!_flag || !_nTriangles)
 		return false;
 	float nearest = FLT_MAX;
-	const Math::Ray ray(origin, dir);
 	for (uint i = 0; i < _nTriangles; i++) {
 		float idist;
 		Math::Vector3d iloc;
@@ -80,7 +79,7 @@ bool TePickMesh::intersect(const TeVector3f32 &origin, const TeVector3f32 &dir,
 		}
 	}
 	if (nearest != FLT_MAX) {
-		ptOut = origin + dir * nearest;
+		ptOut = ray.getOrigin() + ray.getDirection() * nearest;
 		lenOut = nearest;
 		return true;
 	}
diff --git a/engines/tetraedge/te/te_pick_mesh.h b/engines/tetraedge/te/te_pick_mesh.h
index 02e99bfbc51..7e8f0c8aab9 100644
--- a/engines/tetraedge/te/te_pick_mesh.h
+++ b/engines/tetraedge/te/te_pick_mesh.h
@@ -35,7 +35,7 @@ public:
 	// void create(); // unused
 	void destroy();
 	void getTriangle(uint triNum, TeVector3f32 &v1, TeVector3f32 &v2, TeVector3f32 &v3) const;
-	bool intersect(const TeVector3f32 &origin, const TeVector3f32 &dir, TeVector3f32 &ptOut, float &lenOut);
+	bool intersect(const Math::Ray &ray, TeVector3f32 &ptOut, float &lenOut);
 	void nbTriangles(uint nTriangles);
 	TePickMesh &operator+=(const TePickMesh &other);
 	TePickMesh &operator=(const TePickMesh &other);
@@ -44,7 +44,9 @@ public:
 
 	void setName(const Common::String &name) { _name = name; }
 	void setFlag(bool val) { _flag = val; }
+	bool flag() const { return _flag; }
 	const Common::String &name() const { return _name; }
+	uint nTriangles() const { return _nTriangles; }
 
 private:
 	bool _flag;
diff --git a/engines/tetraedge/te/te_ray_intersection.cpp b/engines/tetraedge/te/te_ray_intersection.cpp
index fd645bf1c37..aaf3f55a724 100644
--- a/engines/tetraedge/te/te_ray_intersection.cpp
+++ b/engines/tetraedge/te/te_ray_intersection.cpp
@@ -19,96 +19,44 @@
  *
  */
 
+#include "math/ray.h"
+
 #include "tetraedge/te/te_ray_intersection.h"
+#include "tetraedge/te/te_pick_mesh.h"
 
 namespace Tetraedge {
 
 namespace TeRayIntersection {
 
-TePickMesh *getMesh(const TeVector3f32 &param_1, const TeVector3f32 &param_2, const Common::Array<TePickMesh *> &pickMeshes,
-			float param_4, float param_5, TeVector3f32 *param_6) {
-	error("TODO: implement TeRayIntersection::getMesh");
-}
-
-/*
-// This is a version from https://www.lighthouse3d.com/tutorials/maths/ray-triangle-intersection/
-int intersect(const TeVector3f32 &p, const TeVector3f32 &d, const TeVector3f32 &v0,
-			  const TeVector3f32 &v1, const TeVector3f32 &v2, TeVector3f32 &hitPt, float &hitDist) {
-	const TeVector3f32 e1 = v1 - v0;
-	const TeVector3f32 e2 = v2 - v0;
-	const TeVector3f32 h = TeVector3f32::crossProduct(d, e2);
-
-	if (h == TeVector3f32())
-		return -1;
-
-	float a = e1.dotProduct(h);
-	if (fabs(a) < 1e-6f)
-		return 0;
-
-	float f = 1.0f / a;
-	const TeVector3f32 s = p - v0;
-	float u = f * s.dotProduct(h);
-	if (u < 0.0f || u > 1.0f)
-		return 0;
-
-	const TeVector3f32 q = TeVector3f32::crossProduct(s, e1);
-	float v = f * d.dotProduct(q);
-
-	if (v < 0.0f || u + v > 1.0f)
-		return 0;
-
-	float t = f * e2.dotProduct(q);
-
-	if (t < 1e-6f)
-		return 0;
-
-	hitDist = t;
-	hitPt = p + t * d;
-
-	return 1;
-}*/
-
-/*
-int intersect(const TeVector3f32 &rayPos, const TeVector3f32 &rayDir, const TeVector3f32 &v1,
-			  const TeVector3f32 &v2, const TeVector3f32 &v3, TeVector3f32 &vout, float &fout) {
-	const TeVector3f32 v2_v1 = v2 - v1;
-	const TeVector3f32 v3_v1 = v3 - v1;
-	const TeVector3f32 v = v2_v1 ^ v3_v1;
-
-	if (v == TeVector3f32(0.0f, 0.0f, 0.0f))
-		return -1;
-
-	int result = -1;
-	float f1 = v.dotProduct(rayPos - v1);
-	float f2 = v.dotProduct(rayDir);
-	if (fabs(f2) > 1e-9) {
-		f2 = -f1 / f2;
-		fout = f2;
-		result = 0;
-		if (f2 >= 0.0) {
-			vout = rayPos + (rayDir * f2);
-			float dot1 = v2_v1.dotProduct(v2_v1);
-			float dot2 = v2_v1.dotProduct(v3_v1);
-			float dot3 = v3_v1.dotProduct(v3_v1);
-			const TeVector3f32 vout_v1 = vout - v1;
-			float dots1 = dot2 * dot2 - dot1 * dot3;
-			float dot4 = vout_v1.dotProduct(v2_v1);
-			float dot5 = vout_v1.dotProduct(v3_v1);
-			float dots2 = (dot2 * dot5 - dot3 * dot4) / dots1;
-			if (dots2 >= 0.0 && dots2 <= 1.0) {
-				float dots3 = (dot2 * dot4 - dot1 * dot5) / dots1;
-				if (dots3 >= 0.0 && dots2 + dots3 <= 1.0)
-					result = 1;
+// Note: the TeRayIntersection::intersect function is
+// replaced by Math::Ray::intersectTriangle
+
+TePickMesh *getMesh(const Math::Ray ray, const Common::Array<TePickMesh *> &pickMeshes,
+			float maxDist, float minDist, TeVector3f32 *ptOut) {
+	TeVector3f32 bestPt;
+	TePickMesh *bestMesh = nullptr;
+
+	for (auto *mesh : pickMeshes) {
+		if (!mesh->flag())
+			continue;
+		for (uint i = 0; i < mesh->nTriangles(); i++) {
+			TeVector3f32 v1;
+			TeVector3f32 v2;
+			TeVector3f32 v3;
+			mesh->getTriangle(i, v1, v2, v3);
+			float intersectDist;
+			TeVector3f32 intersectPt;
+			if (ray.intersectTriangle(v1, v2, v3, intersectPt, intersectDist) && intersectDist < maxDist && intersectDist >= minDist) {
+				bestPt = intersectPt;
+				bestMesh = mesh;
 			}
 		}
-	} else {
-		// Sorry about the logic.. this is what the decompiler gave me
-		// and I'm not brave enough to figure it out.
-		result = (-(uint)(f1 == -0.0) & 1) * 2;
 	}
-	return result;
+
+	if (ptOut)
+		*ptOut = bestPt;
+	return bestMesh;
 }
-*/
 
 } // end namespace TeRayIntersection
 
diff --git a/engines/tetraedge/te/te_ray_intersection.h b/engines/tetraedge/te/te_ray_intersection.h
index fccb6f79a58..cae02d35003 100644
--- a/engines/tetraedge/te/te_ray_intersection.h
+++ b/engines/tetraedge/te/te_ray_intersection.h
@@ -31,12 +31,8 @@ class TePickMesh;
 
 namespace TeRayIntersection {
 
-TePickMesh *getMesh(const TeVector3f32 &param_1, const TeVector3f32 &param_2, const Common::Array<TePickMesh *> &pickMeshes,
-			float param_4, float param_5, TeVector3f32 *param_6);
-
-// Replaced with Math::Ray::intersectTriangle
-//int intersect(const TeVector3f32 &rayPos, const TeVector3f32 &rayDir, const TeVector3f32 &v1,
-//				const TeVector3f32 &v2, const TeVector3f32 &v3, TeVector3f32 &vout, float &fout);
+TePickMesh *getMesh(const Math::Ray ray, const Common::Array<TePickMesh *> &pickMeshes,
+			float maxDist, float minDist, TeVector3f32 *ptOut);
 
 } // end namespace TeRayIntersection
 
diff --git a/engines/tetraedge/te/te_warp.cpp b/engines/tetraedge/te/te_warp.cpp
index 29f57d1ff65..5496c0946c0 100644
--- a/engines/tetraedge/te/te_warp.cpp
+++ b/engines/tetraedge/te/te_warp.cpp
@@ -19,12 +19,15 @@
  *
  */
 
+#include "common/math.h"
+
 #include "tetraedge/tetraedge.h"
 #include "tetraedge/game/application.h"
 #include "tetraedge/te/te_warp.h"
 #include "tetraedge/te/te_core.h"
 #include "tetraedge/te/te_input_mgr.h"
 #include "tetraedge/te/te_renderer.h"
+#include "tetraedge/te/te_ray_intersection.h"
 
 namespace Tetraedge {
 
@@ -32,7 +35,9 @@ namespace Tetraedge {
 bool TeWarp::debug = false;
 
 TeWarp::TeWarp() : _visible1(false), _loaded(false), _preloaded(false),
-	_numAnims(0), _someXVal(0), _someYVal(0), _someMeshX(0), _someMeshY(0) {
+	_numAnims(0), _someXVal(0), _someYVal(0), _someMeshX(0), _someMeshY(0),
+	_renderWarpBlocs(true), _xCount(0), _yCount(0), _clickedPickMesh(nullptr),
+	_clickedAnimData(nullptr) {
 }
 
 TeWarp::~TeWarp() {
@@ -115,31 +120,93 @@ TeMarker *TeWarp::allocMarker(unsigned long *nMarkers) {
 }
 
 void TeWarp::checkObjectEvents() {
-	//const Common::Point lastMouse = g_engine->getInputMgr()->lastMousePos();
-	//Math::Ray mouseRay = _camera.getRay(lastMouse);
-	//for (uint i = 0; i < _numAnims; i++) {
-	//
-	//}
-	error("TODO: Implement TeWarp::checkObjectEvents");
+	const Common::Point lastMouse = g_engine->getInputMgr()->lastMousePos();
+	Math::Ray mouseRay = _camera.getRay(lastMouse);
+	for (auto &animData : _loadedAnimData) {
+		if (_clickedAnimData == &animData) {
+			TePickMesh &pickMesh = animData._frameDatas[animData._curFrameMaybe]._pickMesh;
+			TeVector3f32 intersectPt;
+			float intersectLen;
+			if (pickMesh.flag() && pickMesh.intersect(mouseRay, intersectPt, intersectLen)) {
+				_markerValidatedSignal.call(pickMesh.name());
+				break;
+			}
+		}
+	}
+	TePickMesh *mesh = TeRayIntersection::getMesh(mouseRay, _pickMeshes2, FLT_MAX, 0, nullptr);
+	if (mesh && mesh == _clickedPickMesh)
+		_markerValidatedSignal.call(mesh->name());
+	_clickedAnimData = nullptr;
+	_clickedPickMesh = nullptr;
 }
 
 void TeWarp::clear() {
-	_animDatas.clear();
+	_putAnimData.clear();
 
 	error("TODO: Implement TeWarp::clear");
 }
 
-TeWarp::AnimData *TeWarp::findAnimation(const Common::String &name) {
+void TeWarp::configMarker(const Common::String &objname, int markerImgNo, long markerId) {
+	Exit *exit = findExit(objname, false);
+	long foundId = -1;
+	if (exit) {
+		foundId = exit->_markerId;
+	} else {
+		AnimData *anim = findAnimation(objname);
+		if (!anim || anim->_markerIds.empty())
+			return;
+		foundId = anim->_markerIds[0];
+	}
+	assert(foundId >= 0 && foundId < _warpMarkers.size());
+
+	TeWarpMarker *warpMarker = _warpMarkers[foundId];
+	if (markerImgNo == -1) {
+		warpMarker->marker()->visible(false);
+	} else {
+		Common::String markerPath = Common::String::format("2D/Menus/InGame/Marker_%d.png", markerImgNo);
+		Common::String markerPathOver = Common::String::format("2D/Menus/InGame/Marker_%d_over.png", markerImgNo);
+		if (exit)
+			warpMarker->setName(objname);
+		else
+			warpMarker->setName(Common::String("3D\\") + objname);
+
+		warpMarker->marker()->button().load(markerPath, markerPathOver, markerPathOver);
+		TeSpriteLayout *btnUp = dynamic_cast<TeSpriteLayout*>(warpMarker->marker()->button().upLayout());
+		if (!btnUp)
+			error("Loading button image %s failed", markerPath.c_str());
+		warning("TeWarp::configMarker: set anim values and something else here?");
+		//btnUp->_tiledSurfacePtr->_frameAnim._repeatCount = -1;
+		//btnUp->_tiledSurfacePtr->_frameAnim.setFrameRate(8.0);
+		btnUp->play();
+		warpMarker->marker()->visible(true);
+	}
+}
+
+TeWarp::AnimData *TeWarp::findAnimation(const Common::String &objname) {
 	for (uint i = 0; i < _numAnims; i++) {
-		if (_loadedAnimData[i]._name == name)
+		if (_loadedAnimData[i]._name == objname)
 			return _loadedAnimData.data() + i;
 	}
 	return nullptr;
 }
 
-bool TeWarp::hasObjectOrAnim(const Common::String &name) {
+TeWarp::Exit *TeWarp::findExit(const Common::String &objname, bool flag) {
+	Common::String fullName;
+	if (flag)
+		fullName = objname;
+	else
+		fullName = Common::String("3D\\") + objname;
+
+	for (auto &e : _exitList) {
+		if (e._name == fullName)
+			return &e;
+	}
+	return nullptr;
+}
+
+bool TeWarp::hasObjectOrAnim(const Common::String &objname) {
 	for (uint i = 0; i < _numAnims; i++) {
-		if (_loadedAnimData[i]._name == name)
+		if (_loadedAnimData[i]._name == objname)
 			return true;
 	}
 	return false;
@@ -147,7 +214,7 @@ bool TeWarp::hasObjectOrAnim(const Common::String &name) {
 
 void TeWarp::init() {
 	// This mostly sets up the camera.. maybe nothing to do?
-	warning("TODO: Implement TeWarp::init");
+	warning("TODO: Implement TeWarp::init?");
 }
 
 void TeWarp::load(const Common::String &path, bool flag) {
@@ -156,7 +223,7 @@ void TeWarp::load(const Common::String &path, bool flag) {
 	_warpPath = path;
 	TeCore *core = g_engine->getCore();
 	Common::FSNode node = core->findFile(_warpPath);
-	if (node.isReadable())
+	if (!node.isReadable())
 		error("Couldn't find TeWarp path '%s'", _warpPath.c_str());
 
 	if (_preloaded)
@@ -169,15 +236,14 @@ void TeWarp::load(const Common::String &path, bool flag) {
 	if (Common::String(header) != "TeWarp")
 		error("Invalid header in warp data %s", _warpPath.c_str());
 	uint32 globalTexDataOffset = file.readUint32LE();
-	Common::String encodingType = file.readPascalString();
+	_texEncodingType = file.readPascalString();
 	_xCount = file.readUint32LE();
 	_yCount = file.readUint32LE();
 	_numAnims = file.readUint32LE();
 	_someXVal = file.readUint32LE();
 	_someYVal = file.readUint32LE();
-	warning("TeWarp::load: TODO: Identify these ints..");
-	/*int someInt3 = */file.readUint32LE();
-	/*int someInt4 = */file.readUint32LE();
+	_someMeshX = file.readUint32LE();
+	_someMeshY = file.readUint32LE();
 	_warpBlocs.resize(_xCount * _yCount * 6);
 	for (uint i = 0; i < _xCount * _yCount * 6; i++) {
 		TeWarpBloc::CubeFace face = static_cast<TeWarpBloc::CubeFace>(file.readByte());
@@ -191,7 +257,7 @@ void TeWarp::load(const Common::String &path, bool flag) {
 		}
 	}
 	_loadedAnimData.resize(_numAnims);
-	_animDatas.reserve(_numAnims);
+	_putAnimData.reserve(_numAnims);
 	for (uint i = 0; i < _numAnims; i++) {
 		char aname[5];
 		file.read(aname, 4);
@@ -237,14 +303,14 @@ void TeWarp::load(const Common::String &path, bool flag) {
 				}
 			}
 			frameData._warpBlocs.resize(frameData._numWarpBlocs);
-
-			error("TODO: Finish line 323~343");
+			for (int k = 0; k < frameData._numWarpBlocs; k++) {
+				frameData._warpBlocs[k] = warpBlocs[k];
+			}
 		}
 
 	}
 
 	_loaded = true;
-	error("TODO: Finish TeWarp::load");
 }
 
 bool TeWarp::onMarkerValidated(const Common::String &name) {
@@ -253,7 +319,59 @@ bool TeWarp::onMarkerValidated(const Common::String &name) {
 }
 
 bool TeWarp::onMouseLeftDown(const Common::Point &pt) {
-	error("TODO: Implement TeWarp::onMouseLeftDown");
+	const Math::Ray mouseRay = _camera.getRay(pt);
+	_clickedPickMesh = nullptr;
+	_clickedAnimData = nullptr;
+
+	bool hitAnimData = false;
+	FrameData *frameData;
+	for (auto &animData : _loadedAnimData) {
+		frameData = &(animData._frameDatas[animData._curFrameMaybe]);
+		TeVector3f32 interesctPt;
+		float intersectDist;
+		if (frameData->_pickMesh.flag() && frameData->_pickMesh.intersect(mouseRay, interesctPt, intersectDist)) {
+			_clickedAnimData = &animData;
+			hitAnimData = true;
+			break;
+		}
+	}
+
+	if (!hitAnimData) {
+		_clickedPickMesh = TeRayIntersection::getMesh(mouseRay, _pickMeshes2, FLT_MAX, 0, nullptr);
+		if (_clickedPickMesh) {
+			Exit *exit = findExit(_clickedPickMesh->name(), true);
+			_warpMarkers[exit->_markerId]->marker()->button().setEnable(false);
+		}
+		return false;
+	}
+
+	AnimData *data = findAnimation(frameData->_pickMesh.name());
+	for (auto &markerId : data->_markerIds) {
+		_warpMarkers[markerId]->marker()->button().setEnable(false);
+	}
+	return false;
+}
+
+void TeWarp::putObject(const Common::String &name, bool enable) {
+	for (auto &animData : _loadedAnimData) {
+		if (animData._name != name || animData._frameDatas.size() != 1
+				|| animData._curFrameMaybe != 0)
+			continue;
+		bool alreadyAdded = false;
+		for (auto putAnim : _putAnimData) {
+			if (putAnim == &animData) {
+				alreadyAdded = true;
+				break;
+			}
+		}
+		if (!alreadyAdded)
+			_putAnimData.push_back(&animData);
+		for (auto &frameData : animData._frameDatas) {
+			frameData._pickMesh.setFlag(enable);
+		}
+		return;
+	}
+	warning("Impossible de trouver l\'objet %s dans le Warp", name.c_str());
 }
 
 void TeWarp::update() {
@@ -261,7 +379,15 @@ void TeWarp::update() {
 		return;
 	Application *app = g_engine->getApplication();
 	_frustum.update(app->mainWindowCamera());
-	error("TODO: Implement TeWarp::update");
+	for (uint i = 0; i < _xCount * _yCount * 6; i++) {
+		_warpBlocs[i].loadTexture(_file, _texEncodingType);
+	}
+
+	if (!_loadedAnimData.empty())
+		error("TODO: Finish updating anims in TeWarp::update");
+	// for (uint i = 0; i < _loadedAnimData.size(); i++) {
+	//
+	// }
 }
 
 void TeWarp::sendExit(TeWarp::Exit &exit) {
@@ -289,6 +415,10 @@ void TeWarp::sendMarker(const Common::String &name, unsigned long markerId) {
 		anim->_markerIds.push_back(markerId);
 }
 
+void TeWarp::setAnimationPart(const Common::String &name, int x, int y, int z, bool flag) {
+	error("TODO: Implement TeWarp::setAnimationPart");
+}
+
 void TeWarp::setColor(const TeColor &col) {
 	Te3DObject2::setColor(col);
 	for (auto &warpMarker : _warpMarkers) {
@@ -332,7 +462,31 @@ void TeWarp::render() {
 	renderer->disableZBuffer();
 	renderer->pushMatrix();
 
-	// TODO: Render the WarpBlocs here.
+	if (_renderWarpBlocs) {
+		for (uint i = 0; i < _xCount * _yCount * 6; i++) {
+			_warpBlocs[i].render();
+		}
+	}
+
+	TeVector3f32 vertexes[6];
+	for (uint i = 0; i < _putAnimData.size(); i++) {
+		AnimData *animData = _putAnimData[i];
+		for (uint j = 0; j < animData->_frameDatas.size(); j++) {
+			FrameData &frameData = animData->_frameDatas[j];
+			for (uint k = 0; k < frameData._warpBlocs.size(); k++) {
+				TeWarpBloc &bloc = frameData._warpBlocs[k];
+				vertexes[0] = bloc.vertex(0);
+				vertexes[1] = bloc.vertex(1);
+				vertexes[2] = bloc.vertex(3);
+				vertexes[3] = bloc.vertex(1);
+				vertexes[4] = bloc.vertex(2);
+				vertexes[5] = bloc.vertex(3);
+				if (_frustum.triangleIsIn(vertexes) && _frustum.triangleIsIn(vertexes + 3)) {
+					bloc.render();
+				}
+			}
+		}
+	}
 
 	for (auto &warpMarker : _warpMarkers) {
 		warpMarker->marker()->update(&_camera);
@@ -346,8 +500,6 @@ void TeWarp::render() {
 	renderer->popMatrix();
 	renderer->setMatrixMode(TeRenderer::MM_GL_MODELVIEW);
 	renderer->popMatrix();
-
-	error("TODO: Finish TeWarp::render");
 }
 
 void TeWarp::rotateCamera(const TeQuaternion &rot) {
@@ -360,6 +512,10 @@ void TeWarp::setFov(float fov) {
 	_camera.setFov(fov);
 }
 
+void TeWarp::takeObject(const Common::String &name) {
+	error("TODO: Implement TeWarp::takeObject");
+}
+
 void TeWarp::unload() {
 	error("TODO: Implement TeWarp::unload");
 }
diff --git a/engines/tetraedge/te/te_warp.h b/engines/tetraedge/te/te_warp.h
index 94e6bc2ea05..4da38eb91f0 100644
--- a/engines/tetraedge/te/te_warp.h
+++ b/engines/tetraedge/te/te_warp.h
@@ -46,9 +46,10 @@ public:
 
 	class AnimData {
 	public:
-		AnimData() : _fps(15.0f), _flag(false) {}
+		AnimData() : _fps(15.0f), _flag(false), _curFrameMaybe(0) {}
 		Common::Array<unsigned long> _markerIds;
 		float _fps;
+		int _curFrameMaybe;
 		bool _flag;
 		TeTimer _timer;
 		Common::String _name;
@@ -78,7 +79,7 @@ public:
 	uint addQuadToPickMesh(TePickMesh &pickmesh, uint trinum, TeWarpBloc::CubeFace face,
 		const TeVector2s32 &param_4, uint param_5, uint param_6);
 	TeMarker *allocMarker(unsigned long *nMarkers);
-	void configMarker(const Common::String objname, int markerImgNo, long markerId);
+	void configMarker(const Common::String &objname, int markerImgNo, long markerId);
 	void checkObjectEvents();
 	void clear();
 	//void entry(); // unused
@@ -90,16 +91,19 @@ public:
 	void load(const Common::String &path, bool flag);
 	//void loadTextures(); // unused
 	//void preload(const Common::String &path); // unused
+	void putObject(const Common::String &name, bool enable);
 	void update();
 	void render();
 	void rotateCamera(const TeQuaternion &rot);
 	void sendExit(Exit &exit);
 	void sendMarker(const Common::String &name, unsigned long markerId);
+	void setAnimationPart(const Common::String &name, int x, int y, int z, bool flag);
 	void setColor(const TeColor &col) override;
 	void setMarkersOpacity(float opacity);
 	void setMouseLeftUpForMakers();
 	void setFov(float fov);
 	void setVisible(bool v1, bool v2);
+	void takeObject(const Common::String &name);
 	void unload();
 	void unloadTextures();
 	void updateCamera(const TeVector3f32 &screen);
@@ -121,12 +125,16 @@ private:
 	bool _visible1;
 	bool _loaded;
 	bool _preloaded;
+	bool _renderWarpBlocs;
+
+	TePickMesh *_clickedPickMesh;
+	AnimData *_clickedAnimData;
 
 	TeFrustum _frustum;
 
 	Common::Array<TeWarpMarker *> _warpMarkers;
 	Common::List<Common::String> _paths;
-	Common::Array<AnimData> _animDatas;
+	Common::Array<AnimData *> _putAnimData;
 	Common::List<TeWarp::Exit> _exitList;
 	uint _someXVal;
 	uint _someYVal;
@@ -136,9 +144,11 @@ private:
 	uint _yCount;
 	uint _numAnims;
 	Common::Array<TeWarpBloc> _warpBlocs;
+	Common::Array<TePickMesh *> _pickMeshes2;
 	Common::Array<AnimData> _loadedAnimData;
 	TeSignal1Param<const Common::String &> _markerValidatedSignal;
 	TeSignal1Param<const Common::String &> _animFinishedSignal;
+	Common::String _texEncodingType;
 };
 
 } // end namespace Tetraedge
diff --git a/engines/tetraedge/te/te_warp_bloc.cpp b/engines/tetraedge/te/te_warp_bloc.cpp
index 9a31d46bf71..815d2a12499 100644
--- a/engines/tetraedge/te/te_warp_bloc.cpp
+++ b/engines/tetraedge/te/te_warp_bloc.cpp
@@ -20,15 +20,16 @@
  */
 
 #include "tetraedge/te/te_warp_bloc.h"
+#include "tetraedge/te/te_renderer.h"
+#include "tetraedge/tetraedge.h"
 
 namespace Tetraedge {
 
-TeWarpBloc::TeWarpBloc() : _colors(nullptr), _cubeFace(FaceInvalid) {
+TeWarpBloc::TeWarpBloc() : _cubeFace(FaceInvalid) {
+	_mesh.reset(TeMesh::makeInstance());
 }
 
 TeWarpBloc::~TeWarpBloc() {
-	if (_colors)
-		delete _colors;
 }
 
 void TeWarpBloc::color(const TeColor &col) {
@@ -39,88 +40,85 @@ void TeWarpBloc::color(const TeColor &col) {
 }
 
 void TeWarpBloc::color(uint num, const TeColor &col) {
-	if (_colors == nullptr) {
-		_colors = new TeColor[4];
-	}
-	assert(num < 4);
-	_colors[num] = col;
+	_mesh->setColor(num, col);
 }
 
 void TeWarpBloc::create(CubeFace face, uint x, uint y, const TeVector2s32 &offset) {
 	_cubeFace = face;
 	_offset = offset;
 
+	_mesh->setConf(4, 4, TeMesh::MeshMode_TriangleStrip, 0, 0);
+
 	float y1 = offset._y * (1000.0f / y) - 500.0f;
 	float y2 = y1 + 1000.0f / y;
 	float x1 = offset._x * (1000.0f / x) - 500.0f;
 	float x2 = x1 + 1000.0f / x;
 	switch (face) {
 	case Face0:
-		_verticies[0] = TeVector3f32(-x1, 500, -y1);
-		_verticies[1] = TeVector3f32(-x2, 500, -y1);
-		_verticies[2] = TeVector3f32(-x2, 500, -y2);
-		_verticies[3] = TeVector3f32(-x1, 500, -y2);
+		_mesh->setVertex(0, TeVector3f32(-x1, 500, -y1));
+		_mesh->setVertex(1, TeVector3f32(-x2, 500, -y1));
+		_mesh->setVertex(2, TeVector3f32(-x2, 500, -y2));
+		_mesh->setVertex(3, TeVector3f32(-x1, 500, -y2));
 		break;
 	case Face1:
-		_verticies[0] = TeVector3f32(-x1, -500, y1);
-		_verticies[1] = TeVector3f32(-x2, -500, y1);
-		_verticies[2] = TeVector3f32(-x2, -500, y2);
-		_verticies[3] = TeVector3f32(-x1, -500, y2);
+		_mesh->setVertex(0, TeVector3f32(-x1, -500, y1));
+		_mesh->setVertex(1, TeVector3f32(-x2, -500, y1));
+		_mesh->setVertex(2, TeVector3f32(-x2, -500, y2));
+		_mesh->setVertex(3, TeVector3f32(-x1, -500, y2));
 		break;
 	case Face2:
-		_verticies[0] = TeVector3f32(-x1, y1, 500);
-		_verticies[1] = TeVector3f32(-x2, y1, 500);
-		_verticies[2] = TeVector3f32(-x2, y2, 500);
-		_verticies[3] = TeVector3f32(-x1, y2, 500);
+		_mesh->setVertex(0, TeVector3f32(-x1, y1, 500));
+		_mesh->setVertex(1, TeVector3f32(-x2, y1, 500));
+		_mesh->setVertex(2, TeVector3f32(-x2, y2, 500));
+		_mesh->setVertex(3, TeVector3f32(-x1, y2, 500));
 		break;
 	case Face3:
-		_verticies[0] = TeVector3f32(x1, y1, -500);
-		_verticies[1] = TeVector3f32(x2, y1, -500);
-		_verticies[2] = TeVector3f32(x2, y2, -500);
-		_verticies[3] = TeVector3f32(x1, y2, -500);
+		_mesh->setVertex(0, TeVector3f32(x1, y1, -500));
+		_mesh->setVertex(1, TeVector3f32(x2, y1, -500));
+		_mesh->setVertex(2, TeVector3f32(x2, y2, -500));
+		_mesh->setVertex(3, TeVector3f32(x1, y2, -500));
 		break;
 	case Face4:
-		_verticies[0] = TeVector3f32(500, y1, x1);
-		_verticies[1] = TeVector3f32(500, y1, x2);
-		_verticies[2] = TeVector3f32(500, y2, x2);
-		_verticies[3] = TeVector3f32(500, y2, x1);
+		_mesh->setVertex(0, TeVector3f32(500, y1, x1));
+		_mesh->setVertex(1, TeVector3f32(500, y1, x2));
+		_mesh->setVertex(2, TeVector3f32(500, y2, x2));
+		_mesh->setVertex(3, TeVector3f32(500, y2, x1));
 		break;
 	case Face5:
-		_verticies[0] = TeVector3f32(-500, y1, -x1);
-		_verticies[1] = TeVector3f32(-500, y1, -x2);
-		_verticies[2] = TeVector3f32(-500, y2, -x2);
-		_verticies[3] = TeVector3f32(-500, y2, -x1);
+		_mesh->setVertex(0, TeVector3f32(-500, y1, -x1));
+		_mesh->setVertex(1, TeVector3f32(-500, y1, -x2));
+		_mesh->setVertex(2, TeVector3f32(-500, y2, -x2));
+		_mesh->setVertex(3, TeVector3f32(-500, y2, -x1));
 		break;
 	default:
 		break;
 	}
 
-	_texCoords[0] = TeVector2f32(0, 0);
-	_texCoords[1] = TeVector2f32(1, 0);
-	_texCoords[2] = TeVector2f32(1, 1);
-	_texCoords[3] = TeVector2f32(0, 1);
-	_indexes[0] = 0;
-	_indexes[1] = 1;
-	_indexes[2] = 2;
-	_indexes[3] = 3;
+	_mesh->setTextureUV(0, TeVector2f32(0, 0));
+	_mesh->setTextureUV(1, TeVector2f32(1, 0));
+	_mesh->setTextureUV(2, TeVector2f32(1, 1));
+	_mesh->setTextureUV(3, TeVector2f32(0, 1));
+	_mesh->setIndex(0, 0);
+	_mesh->setIndex(1, 1);
+	_mesh->setIndex(2, 2);
+	_mesh->setIndex(3, 3);
 }
 
 void TeWarpBloc::create() {
-	_colors = nullptr;
-	_texture.release();
+	_mesh->materials().clear();
 }
 
 void TeWarpBloc::index(uint offset, uint val) {
 	assert(offset < 4);
-	_indexes[offset] = val;
+	_mesh->setIndex(offset, val);
 }
 
 bool TeWarpBloc::isLoaded() const {
-	return _texture.get() != nullptr;
+	return _mesh->materials().size() > 0 && _mesh->material(0)->_texture;
 }
 
 void TeWarpBloc::loadTexture(Common::File &file, const Common::String &type) {
-	if (_texture)
+	if (isLoaded())
 		return;
 
 	if (!file.seek(_textureDataFileOffset))
@@ -129,34 +127,34 @@ void TeWarpBloc::loadTexture(Common::File &file, const Common::String &type) {
 	TeImage img;
 	img.load(file, type);
 
-	_texture = Te3DTexture::makeInstance();
-	_texture->load(img);
+	_mesh->materials().resize(1);
+	_mesh->material(0)->_texture = Te3DTexture::makeInstance();
+	_mesh->material(0)->_texture->load(img);
 }
 
 void TeWarpBloc::render() {
-	error("Implement TeWarpBloc::render");
+	_mesh->draw();
 }
 
 void TeWarpBloc::texture(uint idx, float x, float y) {
 	assert(idx < 4);
-	_texCoords[idx].setX(x);
-	_texCoords[idx].setY(y);
+	_mesh->setTextureUV(idx, TeVector2f32(x, y));
 }
 
 void TeWarpBloc::unloadTexture() {
-	_texture.release();
+	if (!isLoaded())
+		return;
+	_mesh->material(0)->_texture.release();
 }
 
 void TeWarpBloc::vertex(uint idx, float x, float y, float z) {
 	assert(idx < 4);
-	_verticies[idx].x() = x;
-	_verticies[idx].y() = y;
-	_verticies[idx].z() = z;
+	_mesh->setVertex(idx, TeVector3f32(x, y, z));
 }
 
-const TeVector3f32 &TeWarpBloc::vertex(uint idx) const {
+TeVector3f32 TeWarpBloc::vertex(uint idx) const {
 	assert(idx < 4);
-	return _verticies[idx];
+	return _mesh->vertex(idx);
 }
 
 } // end namespace Tetraedge
diff --git a/engines/tetraedge/te/te_warp_bloc.h b/engines/tetraedge/te/te_warp_bloc.h
index 0a6532f1df7..f16868b8c78 100644
--- a/engines/tetraedge/te/te_warp_bloc.h
+++ b/engines/tetraedge/te/te_warp_bloc.h
@@ -28,6 +28,7 @@
 #include "tetraedge/te/te_vector3f32.h"
 #include "tetraedge/te/te_intrusive_ptr.h"
 #include "tetraedge/te/te_3d_texture.h"
+#include "tetraedge/te/te_mesh.h"
 
 #include "common/file.h"
 
@@ -61,7 +62,7 @@ public:
 	void texture(uint idx, float x, float y);
 	void unloadTexture();
 	void vertex(uint n, float x, float y, float z);
-	const TeVector3f32 &vertex(uint n) const;
+	TeVector3f32 vertex(uint n) const;
 
 	const TeVector2s32 offset() const { return _offset; }
 	CubeFace face() const { return _cubeFace; }
@@ -69,13 +70,10 @@ public:
 	void setTextureFileOffset(long offset) { _textureDataFileOffset = offset; }
 
 private:
-	TeColor *_colors;
 	TeVector2s32 _offset;
-	TeIntrusivePtr<Te3DTexture> _texture;
 	CubeFace _cubeFace;
-	TeVector3f32 _verticies[4];
-	TeVector2f32 _texCoords[4];
-	short _indexes[4];
+	// Tex UV / indexes / texture from orig now in here.
+	Common::SharedPtr<TeMesh> _mesh;
 	long _textureDataFileOffset;
 };
 
diff --git a/engines/tetraedge/te/te_warp_marker.h b/engines/tetraedge/te/te_warp_marker.h
index 31d8f653972..68ced45bcac 100644
--- a/engines/tetraedge/te/te_warp_marker.h
+++ b/engines/tetraedge/te/te_warp_marker.h
@@ -38,6 +38,8 @@ public:
 	void marker(TeMarker *marker);
 	bool onMarkerButtonValidated();
 	TeSignal1Param<const Common::String &> &markerButtonSignal() { return _markerButtonSignal; };
+	void setName(const Common::String newName) { _name = newName; }
+
 
 private:
 	TeMarker *_marker;




More information about the Scummvm-git-logs mailing list