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

mgerhardy martin.gerhardy at gmail.com
Sat Nov 21 14:56:13 UTC 2020


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

Summary:
631864146f TWINE: extended input class
65b3828cdc TWINE: fixed losing the active actor control if you activate the behaviour menu
db5a8551e2 TWINE: reduced cyclic complexity
0381111827 TWINE: replaced magic numbers
0f940c4f72 TWINE: comments and added missing termination byte to savegame
cc653184c3 TWINE: restore saving hero respawn position to the scene start position
28b5e2fb01 TWINE: ensure that we are ending with an invalid keymap state
b0a7b477a0 TWINE: comment about the animation type
025866af83 TWINE: removed unused member from input class
976e139d27 TWINE: simplified input code
95a331f78d TWINE: further cleanup on the input code
3a3dc880a5 TWINE: simplified input code
e10aecad31 TWINE: extracted into single methods and cleanup in input code handling
a5295d0fa6 TWINE: hide member of Movements class
d21bfbe914 TWINE: moved cursor key mask handling into movement class
689909012a TWINE: fixed invalid action states after reading text from signs
9acc282047 TWINE: minor refactoring in drawTextFullscreen
f46cd54294 TWINE: allow to use the cutscene abort keys to interrupt fullscreen texts
49be0a49a6 TWINE: changed behaviour of ScopedKeyMap
a515864167 TWINE: fixed default key mappings


Commit: 631864146ff95dc1cefee1607d7c75de15731b39
    https://github.com/scummvm/scummvm/commit/631864146ff95dc1cefee1607d7c75de15731b39
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: extended input class

Changed paths:
    engines/twine/input.cpp
    engines/twine/input.h


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index c3ea39196d..79528017c5 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -99,6 +99,15 @@ bool Input::isHeroActionActive() const {
 	return isActionActive(TwinEActionType::ExecuteBehaviourAction) || isActionActive(TwinEActionType::SpecialAction);
 }
 
+void Input::enableAdditionalKeyMap(const char *id, bool enable) {
+	Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
+	Common::Keymap *keymap = keymapper->getKeymap(id);
+	if (keymap == nullptr) {
+		return;
+	}
+	keymap->setEnabled(enable);
+}
+
 void Input::enableKeyMap(const char *id) {
 	if (_currentKeyMap == id) {
 		return;
diff --git a/engines/twine/input.h b/engines/twine/input.h
index 9aaf9339be..509f306792 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -117,6 +117,7 @@ public:
 	 * Like disabling ui keymaps when we are in-game - or vice versa.
 	 */
 	void enableKeyMap(const char *id);
+	void enableAdditionalKeyMap(const char *id, bool enable);
 
 	const Common::String currentKeyMap() const;
 


Commit: 65b3828cdc79a15d61258ed640995a47bd78434e
    https://github.com/scummvm/scummvm/commit/65b3828cdc79a15d61258ed640995a47bd78434e
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: fixed losing the active actor control if you activate the behaviour menu

Changed paths:
    engines/twine/menu.cpp


diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 60321505d5..614f1ce6f8 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -897,13 +897,14 @@ void Menu::processBehaviourMenu() {
 
 	int32 tmpTime = _engine->lbaTime;
 
+	_engine->_input->enableAdditionalKeyMap(uiKeyMapId, true);
 	while (_engine->_input->isActionActive(TwinEActionType::BehaviourMenu) || _engine->_input->isQuickBehaviourActionActive()) {
 		_engine->readKeys();
 
 		int heroBehaviour = (int)_engine->_actor->heroBehaviour;
-		if (_engine->_input->toggleActionIfActive(TwinEActionType::TurnLeft)) {
+		if (_engine->_input->toggleActionIfActive(TwinEActionType::UILeft)) {
 			heroBehaviour--;
-		} else if (_engine->_input->toggleActionIfActive(TwinEActionType::TurnRight)) {
+		} else if (_engine->_input->toggleActionIfActive(TwinEActionType::UIRight)) {
 			heroBehaviour++;
 		}
 
@@ -927,6 +928,7 @@ void Menu::processBehaviourMenu() {
 		_engine->_system->delayMillis(1000 / 50);
 		_engine->lbaTime++;
 	}
+	_engine->_input->enableAdditionalKeyMap(uiKeyMapId, false);
 
 	_engine->lbaTime = tmpTime;
 


Commit: db5a8551e29272983495a8eca3c2a7984eb83cf0
    https://github.com/scummvm/scummvm/commit/db5a8551e29272983495a8eca3c2a7984eb83cf0
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: reduced cyclic complexity

Changed paths:
    engines/twine/text.cpp


diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index f99dd03889..2074d6a451 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -398,39 +398,40 @@ void Text::processTextLine() {
 			buffer++;
 			continue;
 		}
+		if (*buffer == '\0') {
+			break;
+		}
 
-		if (*buffer != 0) {
-			printText8Var8 = buffer;
-			WordSize wordSize = getWordSize(buffer, buf1);
-			if (addLineBreakX + dialCharSpace + wordSize.inPixel < dialTextBoxParam2) {
-				char *temp = buffer + 1;
-				if (*buffer == 1) {
+		printText8Var8 = buffer;
+		WordSize wordSize = getWordSize(buffer, buf1);
+		if (addLineBreakX + dialCharSpace + wordSize.inPixel < dialTextBoxParam2) {
+			char *temp = buffer + 1;
+			if (*buffer == 1) {
+				var4 = 0;
+				buffer = temp;
+			} else {
+				if (*buf1 == '@') {
 					var4 = 0;
 					buffer = temp;
+					if (addLineBreakX == 0) {
+						addLineBreakX = 7;
+						*((int16 *)buf2) = spaceChar;
+					}
+					if (buf1[1] == 'P') {
+						printText8Var1 = dialTextBoxParam1;
+						buffer++;
+					}
 				} else {
-					if (*buf1 == '@') {
-						var4 = 0;
-						buffer = temp;
-						if (addLineBreakX == 0) {
-							addLineBreakX = 7;
-							*((int16 *)buf2) = spaceChar;
-						}
-						if (buf1[1] == 'P') {
-							printText8Var1 = dialTextBoxParam1;
-							buffer++;
-						}
-					} else {
-						buffer += wordSize.inChar;
-						printText8Var8 = buffer;
-						strncat(buf2, buf1, sizeof(buf2));
-						strncat(buf2, " ", sizeof(buf2)); // not 100% accurate
-						printText8PrepareBufferVar2++;
-
-						addLineBreakX += wordSize.inPixel + dialCharSpace;
-						if (*printText8Var8 != 0) {
-							printText8Var8++;
-							continue;
-						}
+					buffer += wordSize.inChar;
+					printText8Var8 = buffer;
+					strncat(buf2, buf1, sizeof(buf2));
+					strncat(buf2, " ", sizeof(buf2)); // not 100% accurate
+					printText8PrepareBufferVar2++;
+
+					addLineBreakX += wordSize.inPixel + dialCharSpace;
+					if (*printText8Var8 != '\0') {
+						printText8Var8++;
+						continue;
 					}
 				}
 			}
@@ -497,7 +498,7 @@ void Text::printText10Sub2() {
 			fontColor = dialTextStopColor;
 		}
 		ptr -= 3;
-	};
+	}
 }
 
 int32 Text::getCharWidth(uint8 chr) const {


Commit: 0381111827805caa5556548f04ab6c772ac129de
    https://github.com/scummvm/scummvm/commit/0381111827805caa5556548f04ab6c772ac129de
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: replaced magic numbers

Changed paths:
    engines/twine/gamestate.cpp


diff --git a/engines/twine/gamestate.cpp b/engines/twine/gamestate.cpp
index 8568be93f5..7aab89adb2 100644
--- a/engines/twine/gamestate.cpp
+++ b/engines/twine/gamestate.cpp
@@ -348,7 +348,7 @@ void GameState::processFoundItem(int32 item) {
 			}
 		}
 
-		_engine->_renderer->renderIsoModel(_engine->_scene->sceneHero->x - itemCameraX, _engine->_scene->sceneHero->y - itemCameraY, _engine->_scene->sceneHero->z - itemCameraZ, 0, 0x80, 0, _engine->_actor->bodyTable[_engine->_scene->sceneHero->entity]);
+		_engine->_renderer->renderIsoModel(_engine->_scene->sceneHero->x - itemCameraX, _engine->_scene->sceneHero->y - itemCameraY, _engine->_scene->sceneHero->z - itemCameraZ, ANGLE_0, ANGLE_45, ANGLE_0, _engine->_actor->bodyTable[_engine->_scene->sceneHero->entity]);
 		_engine->_interface->setClip(_engine->_redraw->renderLeft, _engine->_redraw->renderTop, _engine->_redraw->renderRight, _engine->_redraw->renderBottom);
 		_engine->_grid->drawOverModelActor(itemX, itemY, itemZ);
 		_engine->_redraw->addRedrawArea(_engine->_redraw->renderLeft, _engine->_redraw->renderTop, _engine->_redraw->renderRight, _engine->_redraw->renderBottom);


Commit: 0f940c4f727a0ac490212702a2542188234643df
    https://github.com/scummvm/scummvm/commit/0f940c4f727a0ac490212702a2542188234643df
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: comments and added missing termination byte to savegame

according to http://lbafileinfo.kazekr.net/index.php\?title\=LBA1:Savegame

Changed paths:
    engines/twine/actor.h
    engines/twine/gamestate.cpp
    engines/twine/gamestate.h


diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index afe9bd8589..63d541a587 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -147,6 +147,15 @@ public:
 	void loadModel(int32 modelIndex);
 
 	int32 entity = 0; // costumeIndex
+	/**
+	 * 0: tunic + medallion
+	 * 1: tunic
+	 * 2: tunic + medallion + sword
+	 * 3: prison suit
+	 * 4: nurse outfit
+	 * 5: tunic + medallion + horn
+	 * 6: snowboard (WARNING, this can crash the game when you change behavior)
+	 */
 	int32 body = 0;
 	AnimationTypes anim = AnimationTypes::kAnimNone;
 	AnimationTypes animExtra = AnimationTypes::kStanding;  //field_2
diff --git a/engines/twine/gamestate.cpp b/engines/twine/gamestate.cpp
index 7aab89adb2..4c11a71888 100644
--- a/engines/twine/gamestate.cpp
+++ b/engines/twine/gamestate.cpp
@@ -151,14 +151,17 @@ void GameState::initEngineVars() {
 	_engine->_actor->previousHeroBehaviour = HeroBehaviourType::kNormal;
 }
 
+// http://lbafileinfo.kazekr.net/index.php?title=LBA1:Savegame
 bool GameState::loadGame(Common::SeekableReadStream *file) {
 	if (file == nullptr) {
 		return false;
 	}
 
-	initEngineVars();
+	if (file->readByte() != 0x03) {
+		return false;
+	}
 
-	file->skip(1); // skip save game id
+	initEngineVars();
 
 	int playerNameIdx = 0;
 	do {
@@ -255,7 +258,8 @@ bool GameState::saveGame(Common::WriteStream *file) {
 	file->write(inventoryFlags, NUM_INVENTORY_ITEMS);
 
 	file->writeByte(inventoryNumLeafs);
-	file->writeByte(usingSabre);
+	file->writeByte(usingSabre ? 1 : 0);
+	file->writeByte(0);
 
 	return true;
 }
diff --git a/engines/twine/gamestate.h b/engines/twine/gamestate.h
index 73431ab4bc..e3ec8593a1 100644
--- a/engines/twine/gamestate.h
+++ b/engines/twine/gamestate.h
@@ -113,7 +113,25 @@ public:
 	// TODO: why not NUM_GAME_FLAGS?
 	uint8 gameFlags[256];
 
-	/** LBA engine chapter */
+	/**
+	 * LBA engine chapter
+	 *  0: Inprisoned
+	 *  1: Escape from the citadel
+	 *  2: Zoe got captured
+	 *  3: - looking for a young girl
+	 *  4: - looking for a "friend"
+	 *  5: The legend of Sendell
+	 *  6: The book of Bu
+	 *  7: Pirate LeBorne
+	 *  8: - "good day"
+	 *  9: - "good day"
+	 * 10: - ?? nothing
+	 * 11: - ?? nothing
+	 * 12: - ?? nothing
+	 * 13: - looking for plans
+	 * 14: - still looking for plans
+	 * 15: The final showdown - "good day"
+	 */
 	int16 gameChapter = 0;
 
 	/** Magic ball type index */
@@ -141,7 +159,10 @@ public:
 	/** Its using FunFrock Sabre */
 	bool usingSabre = false;
 
-	/** Inventory used flags */
+	/**
+	 * Inventory used flags
+	 * 0 means never used, 1 means already used and automatic re-use
+	 */
 	uint8 inventoryFlags[NUM_INVENTORY_ITEMS];
 
 	uint8 holomapFlags[NUM_LOCATIONS]; // GV14


Commit: cc653184c35c5d5b7ae48440064c03fae0a500e0
    https://github.com/scummvm/scummvm/commit/cc653184c35c5d5b7ae48440064c03fae0a500e0
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: restore saving hero respawn position to the scene start position

this is due to the fact that the lba save game doesn't save the whole scene state.
By not letting the hero restart the scene, you might end up in an unbeatable state.
Non of the already solved puzzles are still active after load, nor are any of the
other already destroyed actors still destroyed - they are just respawned with all
their lifes.

Changed paths:
    engines/twine/gamestate.cpp


diff --git a/engines/twine/gamestate.cpp b/engines/twine/gamestate.cpp
index 4c11a71888..dcc6dc1442 100644
--- a/engines/twine/gamestate.cpp
+++ b/engines/twine/gamestate.cpp
@@ -241,9 +241,11 @@ bool GameState::saveGame(Common::WriteStream *file) {
 	file->writeByte(magicLevelIdx);
 	file->writeByte(inventoryMagicPoints);
 	file->writeByte(inventoryNumLeafsBox);
-	file->writeSint16LE(_engine->_scene->sceneHero->x);
-	file->writeSint16LE(_engine->_scene->sceneHero->y);
-	file->writeSint16LE(_engine->_scene->sceneHero->z);
+	// we don't save the whole scene state - so we have to make sure that the hero is
+	// respawned at the start of the scene - and not at its current position
+	file->writeSint16LE(_engine->_scene->newHeroX);
+	file->writeSint16LE(_engine->_scene->newHeroY);
+	file->writeSint16LE(_engine->_scene->newHeroZ);
 	file->writeSint16LE(FromAngle(_engine->_scene->sceneHero->angle));
 	file->writeByte(_engine->_scene->sceneHero->body);
 


Commit: 28b5e2fb017dd424ab5b2e355238616b0831c582
    https://github.com/scummvm/scummvm/commit/28b5e2fb017dd424ab5b2e355238616b0831c582
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: ensure that we are ending with an invalid keymap state

Changed paths:
    engines/twine/input.cpp
    engines/twine/input.h
    engines/twine/menu.cpp


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 79528017c5..16eef04f4e 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -99,13 +99,15 @@ bool Input::isHeroActionActive() const {
 	return isActionActive(TwinEActionType::ExecuteBehaviourAction) || isActionActive(TwinEActionType::SpecialAction);
 }
 
-void Input::enableAdditionalKeyMap(const char *id, bool enable) {
+bool Input::enableAdditionalKeyMap(const char *id, bool enable) {
 	Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
 	Common::Keymap *keymap = keymapper->getKeymap(id);
 	if (keymap == nullptr) {
-		return;
+		return false;
 	}
+	const bool changed = keymap->isEnabled() != enable;
 	keymap->setEnabled(enable);
+	return changed;
 }
 
 void Input::enableKeyMap(const char *id) {
diff --git a/engines/twine/input.h b/engines/twine/input.h
index 509f306792..f643dd2f61 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -117,7 +117,7 @@ public:
 	 * Like disabling ui keymaps when we are in-game - or vice versa.
 	 */
 	void enableKeyMap(const char *id);
-	void enableAdditionalKeyMap(const char *id, bool enable);
+	bool enableAdditionalKeyMap(const char *id, bool enable);
 
 	const Common::String currentKeyMap() const;
 
diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 614f1ce6f8..9358752584 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -897,7 +897,7 @@ void Menu::processBehaviourMenu() {
 
 	int32 tmpTime = _engine->lbaTime;
 
-	_engine->_input->enableAdditionalKeyMap(uiKeyMapId, true);
+	const bool changedUiKeyMapState = _engine->_input->enableAdditionalKeyMap(uiKeyMapId, true);
 	while (_engine->_input->isActionActive(TwinEActionType::BehaviourMenu) || _engine->_input->isQuickBehaviourActionActive()) {
 		_engine->readKeys();
 
@@ -928,7 +928,9 @@ void Menu::processBehaviourMenu() {
 		_engine->_system->delayMillis(1000 / 50);
 		_engine->lbaTime++;
 	}
-	_engine->_input->enableAdditionalKeyMap(uiKeyMapId, false);
+	if (changedUiKeyMapState) {
+		_engine->_input->enableAdditionalKeyMap(uiKeyMapId, false);
+	}
 
 	_engine->lbaTime = tmpTime;
 


Commit: b0a7b477a0cea0f755a64dfc45185c36d5424785
    https://github.com/scummvm/scummvm/commit/b0a7b477a0cea0f755a64dfc45185c36d5424785
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: comment about the animation type

Changed paths:
    engines/twine/actor.h


diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index 63d541a587..eac260e21c 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -213,6 +213,7 @@ public:
 	int32 previousAnimIdx = 0;
 	int32 doorStatus = 0;
 	int32 animPosition = 0;
+	// 0 == loop
 	int32 animType = 0;   // field_78
 	int32 brickSound = 0; // field_7A
 


Commit: 025866af830ccdf9139e30c4d7908cfb559fbfaa
    https://github.com/scummvm/scummvm/commit/025866af830ccdf9139e30c4d7908cfb559fbfaa
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: removed unused member from input class

Changed paths:
    engines/twine/input.cpp
    engines/twine/input.h


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 16eef04f4e..568c02c082 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -230,12 +230,6 @@ void Input::readKeys() {
 			if (pressedKeyCharMap[i].key == localKey) {
 				if (pressedKeyCharMap[i].cursor) {
 					cursorKeys |= pressedKeyCharMap[i].high;
-				} else {
-					if (event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_END) {
-						pressedKey &= ~pressedKeyCharMap[i].high;
-					} else {
-						pressedKey |= pressedKeyCharMap[i].high;
-					}
 				}
 				break;
 			}
diff --git a/engines/twine/input.h b/engines/twine/input.h
index f643dd2f61..2922ad3c10 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -110,7 +110,6 @@ public:
 	Input(TwinEEngine *engine);
 
 	int16 cursorKeys = 0;
-	int16 pressedKey = 0;
 
 	/**
 	 * @brief Dependent on the context we are currently in the game, we might want to disable certain keymaps.


Commit: 976e139d2732c1e86eabe5058bd32d4a34731057
    https://github.com/scummvm/scummvm/commit/976e139d2732c1e86eabe5058bd32d4a34731057
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: simplified input code

Changed paths:
    engines/twine/input.cpp


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 568c02c082..729e9e1b68 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -37,20 +37,12 @@ const char *cutsceneKeyMapId = "cutsceneKeyMap";
 /** Pressed key char map - scanCodeTab2 */
 static const struct KeyProperties {
 	uint8 high;
-	bool cursor;
 	uint8 key;
 } pressedKeyCharMap[] = {
-    {0x01, true, 0x48}, // up
-    {0x02, true, 0x50}, // down
-    {0x04, true, 0x4B}, // left
-    {0x08, true, 0x4D}, // right
-    {0x01, false, 0x39},  // space bar
-    {0x02, false, 0x1C},  // enter
-    {0x04, false, 0x1D},  // ctrl
-    {0x08, false, 0x38},  // alt
-    {0x10, false, 0x53},  // del
-    {0x20, false, 0x2A},  // left shift
-    {0x20, false, 0x36}  // right shift
+    {0x01, 0x48}, // up
+    {0x02, 0x50}, // down
+    {0x04, 0x4B}, // left
+    {0x08, 0x4D} // right
 };
 
 ScopedKeyMap::ScopedKeyMap(TwinEEngine* engine, const char *id) : _engine(engine) {
@@ -228,9 +220,7 @@ void Input::readKeys() {
 
 		for (int i = 0; i < ARRAYSIZE(pressedKeyCharMap); i++) {
 			if (pressedKeyCharMap[i].key == localKey) {
-				if (pressedKeyCharMap[i].cursor) {
-					cursorKeys |= pressedKeyCharMap[i].high;
-				}
+				cursorKeys |= pressedKeyCharMap[i].high;
 				break;
 			}
 		}


Commit: 95a331f78d19a940665e7f60215563e0eea970b6
    https://github.com/scummvm/scummvm/commit/95a331f78d19a940665e7f60215563e0eea970b6
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: further cleanup on the input code

Changed paths:
    engines/twine/movements.cpp
    engines/twine/movements.h


diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index d0c08e713f..4c530e386e 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -210,6 +210,7 @@ void Movements::moveActor(int32 angleFrom, int32 angleTo, int32 speed, ActorMove
 }
 
 void Movements::update() {
+	previousLoopCursorKeys = loopCursorKeys;
 	previousLoopActionKey = heroActionKey;
 	heroActionKey = _engine->_input->isHeroActionActive();
 	loopCursorKeys = _engine->_input->cursorKeys;
@@ -304,7 +305,7 @@ void Movements::processManualAction(int actorIdx) {
 			heroMoved = false; // don't break animation
 		}
 
-		if (heroActionKey != heroPressedKey || loopCursorKeys != heroPressedKey2) {
+		if (heroActionKey != previousLoopActionKey || loopCursorKeys != previousLoopCursorKeys) {
 			if (heroMoved) {
 				_engine->_animations->initAnim(AnimationTypes::kStanding, 0, AnimationTypes::kAnimInvalid, actorIdx);
 			}
@@ -353,9 +354,6 @@ void Movements::processManualAction(int actorIdx) {
 	}
 
 	moveActor(actor->angle, actor->angle + tempAngle, actor->speed, &actor->move);
-
-	heroPressedKey = heroActionKey;
-	heroPressedKey2 = loopCursorKeys;
 }
 
 void Movements::processFollowAction(int actorIdx) {
@@ -423,8 +421,6 @@ void Movements::processActorMovements(int32 actorIdx) {
 		}
 
 		moveActor(actor->angle, actor->angle + tempAngle, actor->speed, &actor->move);
-
-		heroPressedKey = heroActionKey;
 		return;
 	}
 	if (!actor->staticFlags.bIsSpriteActor) {
diff --git a/engines/twine/movements.h b/engines/twine/movements.h
index 752c0e02e8..db78cd6def 100644
--- a/engines/twine/movements.h
+++ b/engines/twine/movements.h
@@ -34,16 +34,12 @@ class Movements {
 private:
 	TwinEEngine *_engine;
 
-	// enter, space, ...
-	int32 heroPressedKey = 0;
-	// cursor buttons
-	int32 heroPressedKey2 = 0;
 	// enter, space, ...
 	int16 heroActionKey = 0;
-	// enter, space, ...
-	int32 loopCursorKeys = 0;
-	// cursor keys
 	int32 previousLoopActionKey = 0;
+	// cursor keys
+	int32 loopCursorKeys = 0;
+	int32 previousLoopCursorKeys = 0;
 
 	/**
 	 * The Actor is controlled by the player. This works well only for the Hero Actor in general.


Commit: 3a3dc880a56507c1aa8d588055bae5e5944051c6
    https://github.com/scummvm/scummvm/commit/3a3dc880a56507c1aa8d588055bae5e5944051c6
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: simplified input code

Changed paths:
    engines/twine/input.cpp
    engines/twine/input.h


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 729e9e1b68..01f1230825 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -34,17 +34,6 @@ const char *mainKeyMapId = "mainKeyMap";
 const char *uiKeyMapId = "uiKeyMap";
 const char *cutsceneKeyMapId = "cutsceneKeyMap";
 
-/** Pressed key char map - scanCodeTab2 */
-static const struct KeyProperties {
-	uint8 high;
-	uint8 key;
-} pressedKeyCharMap[] = {
-    {0x01, 0x48}, // up
-    {0x02, 0x50}, // down
-    {0x04, 0x4B}, // left
-    {0x08, 0x4D} // right
-};
-
 ScopedKeyMap::ScopedKeyMap(TwinEEngine* engine, const char *id) : _engine(engine) {
 	_prevKeyMap = _engine->_input->currentKeyMap();
 	_engine->_input->enableKeyMap(id);
@@ -124,37 +113,37 @@ static constexpr const struct ActionMapping {
 	TwinEActionType action;
 	uint8 localKey;
 } twineactions[] = {
-    {Pause, 0x19},
-    {NextRoom, 0x13},
-    {PreviousRoom, 0x21},
-    {ApplyCellingGrid, 0x14},
-    {IncreaseCellingGridIndex, 0x22},
-    {DecreaseCellingGridIndex, 0x30},
-    {DebugGridCameraPressUp, 0x2E},
-    {DebugGridCameraPressDown, 0x2C},
-    {DebugGridCameraPressLeft, 0x1F},
-    {DebugGridCameraPressRight, 0x2D},
-	{DebugMenu, 0x00},
-	{DebugMenuActivate, 0x00},
-    {QuickBehaviourNormal, 0x3B},
-    {QuickBehaviourAthletic, 0x3C},
-    {QuickBehaviourAggressive, 0x3D},
-    {QuickBehaviourDiscreet, 0x3E},
-    {ExecuteBehaviourAction, 0x39},
-    {BehaviourMenu, 0x1D},
-    {OptionsMenu, 0x40},
-    {RecenterScreenOnTwinsen, 0x1C},
-    {UseSelectedObject, 0x1C},
-    {ThrowMagicBall, 0x38},
-    {MoveForward, 0x48},
-    {MoveBackward, 0x50},
-    {TurnRight, 0x4D},
-    {TurnLeft, 0x4B},
-    {UseProtoPack, 0x24},
-    {OpenHolomap, 0x23},
-    {InventoryMenu, 0x36},
-    {SpecialAction, 0x11},
-    {Escape, 0x01},
+    {Pause, 0x00},
+    {NextRoom, 0x00},
+    {PreviousRoom, 0x00},
+    {ApplyCellingGrid, 0x00},
+    {IncreaseCellingGridIndex, 0x00},
+    {DecreaseCellingGridIndex, 0x00},
+    {DebugGridCameraPressUp, 0x00},
+    {DebugGridCameraPressDown, 0x00},
+    {DebugGridCameraPressLeft, 0x00},
+    {DebugGridCameraPressRight, 0x00},
+    {DebugMenu, 0x00},
+    {DebugMenuActivate, 0x00},
+    {QuickBehaviourNormal, 0x00},
+    {QuickBehaviourAthletic, 0x00},
+    {QuickBehaviourAggressive, 0x00},
+    {QuickBehaviourDiscreet, 0x00},
+    {ExecuteBehaviourAction, 0x00},
+    {BehaviourMenu, 0x00},
+    {OptionsMenu, 0x00},
+    {RecenterScreenOnTwinsen, 0x00},
+    {UseSelectedObject, 0x00},
+    {ThrowMagicBall, 0x00},
+    {MoveForward, 0x01},
+    {MoveBackward, 0x02},
+    {TurnLeft, 0x04},
+    {TurnRight, 0x08},
+    {UseProtoPack, 0x00},
+    {OpenHolomap, 0x00},
+    {InventoryMenu, 0x00},
+    {SpecialAction, 0x00},
+    {Escape, 0x00},
     {UIEnter, 0x00},
     {UIAbort, 0x00},
     {UILeft, 0x00},
@@ -198,32 +187,19 @@ uint8 Input::processCustomEngineEventEnd(const Common::Event &event) {
 }
 
 void Input::readKeys() {
-	cursorKeys = 0;
-
+	cursorKeyMask = 0;
 	Common::Event event;
 	while (g_system->getEventManager()->pollEvent(event)) {
-		uint8 localKey = 0;
 		switch (event.type) {
 		case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
-			localKey = processCustomEngineEventEnd(event);
+			processCustomEngineEventEnd(event);
 			break;
 		case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
-			localKey = processCustomEngineEventStart(event);
+			cursorKeyMask |= processCustomEngineEventStart(event);
 			break;
 		default:
 			break;
 		}
-
-		if (localKey == 0) {
-			continue;
-		}
-
-		for (int i = 0; i < ARRAYSIZE(pressedKeyCharMap); i++) {
-			if (pressedKeyCharMap[i].key == localKey) {
-				cursorKeys |= pressedKeyCharMap[i].high;
-				break;
-			}
-		}
 	}
 }
 
diff --git a/engines/twine/input.h b/engines/twine/input.h
index 2922ad3c10..6275d858cc 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -109,7 +109,7 @@ private:
 public:
 	Input(TwinEEngine *engine);
 
-	int16 cursorKeys = 0;
+	uint8 cursorKeyMask = 0;
 
 	/**
 	 * @brief Dependent on the context we are currently in the game, we might want to disable certain keymaps.


Commit: e10aecad317056ea654965de84a7e8765d40d0b9
    https://github.com/scummvm/scummvm/commit/e10aecad317056ea654965de84a7e8765d40d0b9
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: extracted into single methods and cleanup in input code handling

Changed paths:
    engines/twine/input.cpp
    engines/twine/input.h
    engines/twine/movements.cpp
    engines/twine/movements.h


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 01f1230825..27c5baaaf5 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -192,7 +192,7 @@ void Input::readKeys() {
 	while (g_system->getEventManager()->pollEvent(event)) {
 		switch (event.type) {
 		case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
-			processCustomEngineEventEnd(event);
+			cursorKeyMask |= processCustomEngineEventEnd(event);
 			break;
 		case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
 			cursorKeyMask |= processCustomEngineEventStart(event);
diff --git a/engines/twine/input.h b/engines/twine/input.h
index 6275d858cc..b4fbeac56a 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -109,6 +109,12 @@ private:
 public:
 	Input(TwinEEngine *engine);
 
+	/**
+	 * @brief This is a bitmask of 4 bits that is changed whenever a cursor key has changed. A set bit
+	 * does not mean that the cursor is pressed - but that a change has happened in this particular frame
+	 *
+	 * @note This value is reset with every single call to @c readKeys()
+	 */
 	uint8 cursorKeyMask = 0;
 
 	/**
@@ -149,6 +155,9 @@ public:
 	 */
 	void getMousePositions(MouseStatusStruct *mouseData);
 
+	/**
+	 * @brief Updates the internal action states
+	 */
 	void readKeys();
 	uint8 processCustomEngineEventStart(const Common::Event& event);
 	uint8 processCustomEngineEventEnd(const Common::Event& event);
diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index 4c530e386e..bee63d34fc 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -210,103 +210,96 @@ void Movements::moveActor(int32 angleFrom, int32 angleTo, int32 speed, ActorMove
 }
 
 void Movements::update() {
-	previousLoopCursorKeys = loopCursorKeys;
+	previousChangedCursorKeys = changedCursorKeys;
 	previousLoopActionKey = heroActionKey;
 	heroActionKey = _engine->_input->isHeroActionActive();
-	loopCursorKeys = _engine->_input->cursorKeys;
+	changedCursorKeys = _engine->_input->cursorKeyMask;
 }
 
-void Movements::processManualAction(int actorIdx) {
-	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
-	if (IS_HERO(actorIdx)) {
-		heroAction = false;
-
-		// If press W for action
-		if (_engine->_input->toggleActionIfActive(TwinEActionType::SpecialAction)) {
-			heroAction = true;
-		}
-
-		// Process hero actions
-		if (_engine->_input->isActionActive(TwinEActionType::ExecuteBehaviourAction)) {
-			switch (_engine->_actor->heroBehaviour) {
-			case HeroBehaviourType::kNormal:
-				heroAction = true;
-				break;
-			case HeroBehaviourType::kAthletic:
-				_engine->_animations->initAnim(AnimationTypes::kJump, 1, AnimationTypes::kStanding, actorIdx);
-				break;
-			case HeroBehaviourType::kAggressive:
-				if (_engine->_actor->autoAgressive) {
-					heroMoved = true;
-					actor->angle = getRealAngle(&actor->move);
-					// TODO: previousLoopActionKey must be handled properly
-					if (!previousLoopActionKey || actor->anim == AnimationTypes::kStanding) {
-						const int32 aggresiveMode = _engine->getRandomNumber(3);
-
-						switch (aggresiveMode) {
-						case 0:
-							_engine->_animations->initAnim(AnimationTypes::kKick, 1, AnimationTypes::kStanding, actorIdx);
-							break;
-						case 1:
-							_engine->_animations->initAnim(AnimationTypes::kRightPunch, 1, AnimationTypes::kStanding, actorIdx);
-							break;
-						case 2:
-							_engine->_animations->initAnim(AnimationTypes::kLeftPunch, 1, AnimationTypes::kStanding, actorIdx);
-							break;
-						}
-					}
-				} else {
-					if (_engine->_input->isActionActive(TwinEActionType::TurnLeft)) {
-						_engine->_animations->initAnim(AnimationTypes::kLeftPunch, 1, AnimationTypes::kStanding, actorIdx);
-					} else if (_engine->_input->isActionActive(TwinEActionType::TurnRight)) {
-						_engine->_animations->initAnim(AnimationTypes::kRightPunch, 1, AnimationTypes::kStanding, actorIdx);
-					}
-
-					if (_engine->_input->isActionActive(TwinEActionType::MoveForward)) {
-						_engine->_animations->initAnim(AnimationTypes::kKick, 1, AnimationTypes::kStanding, actorIdx);
-					}
+bool Movements::processBehaviourExecution(int actorIdx) {
+	bool executeAction = false;
+	if (_engine->_input->toggleActionIfActive(TwinEActionType::SpecialAction)) {
+		executeAction = true;
+	}
+	switch (_engine->_actor->heroBehaviour) {
+	case HeroBehaviourType::kNormal:
+		executeAction = true;
+		break;
+	case HeroBehaviourType::kAthletic:
+		_engine->_animations->initAnim(AnimationTypes::kJump, 1, AnimationTypes::kStanding, actorIdx);
+		break;
+	case HeroBehaviourType::kAggressive:
+		if (_engine->_actor->autoAgressive) {
+			ActorStruct *actor = _engine->_scene->getActor(actorIdx);
+			heroMoved = true;
+			actor->angle = getRealAngle(&actor->move);
+			// TODO: previousLoopActionKey must be handled properly
+			if (!previousLoopActionKey || actor->anim == AnimationTypes::kStanding) {
+				const int32 aggresiveMode = _engine->getRandomNumber(3);
+
+				switch (aggresiveMode) {
+				case 0:
+					_engine->_animations->initAnim(AnimationTypes::kKick, 1, AnimationTypes::kStanding, actorIdx);
+					break;
+				case 1:
+					_engine->_animations->initAnim(AnimationTypes::kRightPunch, 1, AnimationTypes::kStanding, actorIdx);
+					break;
+				case 2:
+					_engine->_animations->initAnim(AnimationTypes::kLeftPunch, 1, AnimationTypes::kStanding, actorIdx);
+					break;
 				}
-				break;
-			case HeroBehaviourType::kDiscrete:
-				_engine->_animations->initAnim(AnimationTypes::kHide, 0, AnimationTypes::kAnimInvalid, actorIdx);
-				break;
-			case HeroBehaviourType::kProtoPack:
-				break;
+			}
+		} else {
+			if (_engine->_input->isActionActive(TwinEActionType::TurnLeft)) {
+				_engine->_animations->initAnim(AnimationTypes::kLeftPunch, 1, AnimationTypes::kStanding, actorIdx);
+			} else if (_engine->_input->isActionActive(TwinEActionType::TurnRight)) {
+				_engine->_animations->initAnim(AnimationTypes::kRightPunch, 1, AnimationTypes::kStanding, actorIdx);
+			}
+
+			if (_engine->_input->isActionActive(TwinEActionType::MoveForward)) {
+				_engine->_animations->initAnim(AnimationTypes::kKick, 1, AnimationTypes::kStanding, actorIdx);
 			}
 		}
+		break;
+	case HeroBehaviourType::kDiscrete:
+		_engine->_animations->initAnim(AnimationTypes::kHide, 0, AnimationTypes::kAnimInvalid, actorIdx);
+		break;
+	case HeroBehaviourType::kProtoPack:
+		break;
 	}
+	return executeAction;
+}
 
-	if (_engine->_input->isActionActive(TwinEActionType::ThrowMagicBall) && !_engine->_gameState->gameFlags[GAMEFLAG_INVENTORY_DISABLED]) {
-		if (!_engine->_gameState->usingSabre) { // Use Magic Ball
-			if (_engine->_gameState->gameFlags[InventoryItems::kiMagicBall]) {
-				if (_engine->_gameState->magicBallIdx == -1) {
-					_engine->_animations->initAnim(AnimationTypes::kThrowBall, 1, AnimationTypes::kStanding, actorIdx);
-				}
-
-				heroMoved = true;
-				actor->angle = getRealAngle(&actor->move);
-			}
-		} else if (_engine->_gameState->gameFlags[InventoryItems::kiUseSabre]) {
-			if (actor->body != InventoryItems::kiUseSabre) {
-				_engine->_actor->initModelActor(InventoryItems::kiUseSabre, actorIdx);
+bool Movements::processAttackExecution(int actorIdx) {
+	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
+	if (!_engine->_gameState->usingSabre) { // Use Magic Ball
+		if (_engine->_gameState->gameFlags[InventoryItems::kiMagicBall]) {
+			if (_engine->_gameState->magicBallIdx == -1) {
+				_engine->_animations->initAnim(AnimationTypes::kThrowBall, 1, AnimationTypes::kStanding, actorIdx);
 			}
 
-			_engine->_animations->initAnim(AnimationTypes::kSabreAttack, 1, AnimationTypes::kStanding, actorIdx);
-
-			heroMoved = true;
 			actor->angle = getRealAngle(&actor->move);
+			return true;
 		}
-	}
-
-	// TODO: remove loopCursorKeys here
-	if (!loopCursorKeys || heroAction) {
-		// if continue walking
-		if (_engine->_input->isActionActive(TwinEActionType::MoveForward) || _engine->_input->isActionActive(TwinEActionType::MoveBackward)) {
-			heroMoved = false; // don't break animation
+	} else if (_engine->_gameState->gameFlags[InventoryItems::kiUseSabre]) {
+		if (actor->body != InventoryItems::kiUseSabre) {
+			_engine->_actor->initModelActor(InventoryItems::kiUseSabre, actorIdx);
 		}
 
-		if (heroActionKey != previousLoopActionKey || loopCursorKeys != previousLoopCursorKeys) {
-			if (heroMoved) {
+		_engine->_animations->initAnim(AnimationTypes::kSabreAttack, 1, AnimationTypes::kStanding, actorIdx);
+
+		actor->angle = getRealAngle(&actor->move);
+		return true;
+	}
+	return false;
+}
+
+void Movements::processMovementExecution(int actorIdx) {
+	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
+	if (!changedCursorKeys || heroAction) {
+		// if walking should get stopped
+		if (!_engine->_input->isActionActive(TwinEActionType::MoveForward) && !_engine->_input->isActionActive(TwinEActionType::MoveBackward)) {
+			if (heroMoved && (heroActionKey != previousLoopActionKey || changedCursorKeys != previousChangedCursorKeys)) {
 				_engine->_animations->initAnim(AnimationTypes::kStanding, 0, AnimationTypes::kAnimInvalid, actorIdx);
 			}
 		}
@@ -324,7 +317,6 @@ void Movements::processManualAction(int actorIdx) {
 		}
 
 		if (_engine->_input->isActionActive(TwinEActionType::TurnLeft)) {
-			heroMoved = true;
 			if (actor->anim == AnimationTypes::kStanding) {
 				_engine->_animations->initAnim(AnimationTypes::kTurnLeft, 0, AnimationTypes::kAnimInvalid, actorIdx);
 			} else {
@@ -332,8 +324,8 @@ void Movements::processManualAction(int actorIdx) {
 					actor->angle = getRealAngle(&actor->move);
 				}
 			}
-		} else if (_engine->_input->isActionActive(TwinEActionType::TurnRight)) {
 			heroMoved = true;
+		} else if (_engine->_input->isActionActive(TwinEActionType::TurnRight)) {
 			if (actor->anim == AnimationTypes::kStanding) {
 				_engine->_animations->initAnim(AnimationTypes::kTurnRight, 0, AnimationTypes::kAnimInvalid, actorIdx);
 			} else {
@@ -341,9 +333,13 @@ void Movements::processManualAction(int actorIdx) {
 					actor->angle = getRealAngle(&actor->move);
 				}
 			}
+			heroMoved = true;
 		}
 	}
+}
 
+void Movements::processRotationExecution(int actorIdx) {
+	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 	int16 tempAngle;
 	if (_engine->_input->isActionActive(TwinEActionType::TurnLeft)) {
 		tempAngle = ANGLE_90;
@@ -356,6 +352,24 @@ void Movements::processManualAction(int actorIdx) {
 	moveActor(actor->angle, actor->angle + tempAngle, actor->speed, &actor->move);
 }
 
+void Movements::processManualAction(int actorIdx) {
+	if (IS_HERO(actorIdx)) {
+		heroAction = false;
+		if (_engine->_input->isActionActive(TwinEActionType::ExecuteBehaviourAction)) {
+			heroAction = processBehaviourExecution(actorIdx);
+		}
+	}
+
+	if (_engine->_input->isActionActive(TwinEActionType::ThrowMagicBall) && !_engine->_gameState->gameFlags[GAMEFLAG_INVENTORY_DISABLED]) {
+		if (processAttackExecution(actorIdx)) {
+			heroMoved = true;
+		}
+	}
+
+	processMovementExecution(actorIdx);
+	processRotationExecution(actorIdx);
+}
+
 void Movements::processFollowAction(int actorIdx) {
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 	const ActorStruct* followedActor = _engine->_scene->getActor(actor->followedActor);
diff --git a/engines/twine/movements.h b/engines/twine/movements.h
index db78cd6def..b23b4859e2 100644
--- a/engines/twine/movements.h
+++ b/engines/twine/movements.h
@@ -38,8 +38,8 @@ private:
 	int16 heroActionKey = 0;
 	int32 previousLoopActionKey = 0;
 	// cursor keys
-	int32 loopCursorKeys = 0;
-	int32 previousLoopCursorKeys = 0;
+	int32 changedCursorKeys = 0;
+	int32 previousChangedCursorKeys = 0;
 
 	/**
 	 * The Actor is controlled by the player. This works well only for the Hero Actor in general.
@@ -78,6 +78,15 @@ private:
 	 */
 	void processSameXZAction(int actorIdx);
 
+	/**
+	 * @return A value of @c true means that the actor should e.g. start reading a sign or checking
+	 * a locker for loot or secrets
+	 */
+	bool processBehaviourExecution(int actorIdx);
+	bool processAttackExecution(int actorIdx);
+	void processMovementExecution(int actorIdx);
+	void processRotationExecution(int actorIdx);
+
 public:
 	Movements(TwinEEngine *engine);
 


Commit: a5295d0fa6387942cc4fec1e4fcebf1b4aa5a34d
    https://github.com/scummvm/scummvm/commit/a5295d0fa6387942cc4fec1e4fcebf1b4aa5a34d
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: hide member of Movements class

Changed paths:
    engines/twine/input.cpp
    engines/twine/movements.cpp
    engines/twine/movements.h
    engines/twine/scene.cpp
    engines/twine/script_life_v1.cpp


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 27c5baaaf5..8d9cb7fdf2 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -108,52 +108,15 @@ void Input::enableKeyMap(const char *id) {
 	debug("enable keymap %s", id);
 }
 
-// TODO: get rid of this table
 static constexpr const struct ActionMapping {
 	TwinEActionType action;
-	uint8 localKey;
-} twineactions[] = {
-    {Pause, 0x00},
-    {NextRoom, 0x00},
-    {PreviousRoom, 0x00},
-    {ApplyCellingGrid, 0x00},
-    {IncreaseCellingGridIndex, 0x00},
-    {DecreaseCellingGridIndex, 0x00},
-    {DebugGridCameraPressUp, 0x00},
-    {DebugGridCameraPressDown, 0x00},
-    {DebugGridCameraPressLeft, 0x00},
-    {DebugGridCameraPressRight, 0x00},
-    {DebugMenu, 0x00},
-    {DebugMenuActivate, 0x00},
-    {QuickBehaviourNormal, 0x00},
-    {QuickBehaviourAthletic, 0x00},
-    {QuickBehaviourAggressive, 0x00},
-    {QuickBehaviourDiscreet, 0x00},
-    {ExecuteBehaviourAction, 0x00},
-    {BehaviourMenu, 0x00},
-    {OptionsMenu, 0x00},
-    {RecenterScreenOnTwinsen, 0x00},
-    {UseSelectedObject, 0x00},
-    {ThrowMagicBall, 0x00},
+	uint8 mask;
+} cursorChangeMask[] = {
     {MoveForward, 0x01},
     {MoveBackward, 0x02},
     {TurnLeft, 0x04},
-    {TurnRight, 0x08},
-    {UseProtoPack, 0x00},
-    {OpenHolomap, 0x00},
-    {InventoryMenu, 0x00},
-    {SpecialAction, 0x00},
-    {Escape, 0x00},
-    {UIEnter, 0x00},
-    {UIAbort, 0x00},
-    {UILeft, 0x00},
-    {UIRight, 0x00},
-    {UIUp, 0x00},
-    {UIDown, 0x00},
-    {UINextPage, 0x00},
-    {CutsceneAbort, 0x00}};
-
-static_assert(ARRAYSIZE(twineactions) == TwinEActionType::Max, "Unexpected action mapping array size");
+    {TurnRight, 0x08}
+};
 
 uint8 Input::processCustomEngineEventStart(const Common::Event &event) {
 	if (!_engine->cfgfile.Debug) {
@@ -172,18 +135,27 @@ uint8 Input::processCustomEngineEventStart(const Common::Event &event) {
 			break;
 		default:
 			actionStates[event.customType] = 1 + event.kbdRepeat;
-			return twineactions[event.customType].localKey;
+			break;
 		}
 	} else {
 		actionStates[event.customType] = 1 + event.kbdRepeat;
-		return twineactions[event.customType].localKey;
+	}
+	for (int i = 0; i < ARRAYSIZE(cursorChangeMask); ++i) {
+		if (event.customType == cursorChangeMask[i].action) {
+			return cursorChangeMask[i].mask;
+		}
 	}
 	return 0;
 }
 
 uint8 Input::processCustomEngineEventEnd(const Common::Event &event) {
 	actionStates[event.customType] = 0;
-	return twineactions[event.customType].localKey;
+	for (int i = 0; i < ARRAYSIZE(cursorChangeMask); ++i) {
+		if (event.customType == cursorChangeMask[i].action) {
+			return cursorChangeMask[i].mask;
+		}
+	}
+	return 0;
 }
 
 void Input::readKeys() {
diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index bee63d34fc..dc2aafe4f1 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -355,7 +355,7 @@ void Movements::processRotationExecution(int actorIdx) {
 void Movements::processManualAction(int actorIdx) {
 	if (IS_HERO(actorIdx)) {
 		heroAction = false;
-		if (_engine->_input->isActionActive(TwinEActionType::ExecuteBehaviourAction)) {
+		if (_engine->_input->isHeroActionActive()) {
 			heroAction = processBehaviourExecution(actorIdx);
 		}
 	}
diff --git a/engines/twine/movements.h b/engines/twine/movements.h
index b23b4859e2..ff44e5d870 100644
--- a/engines/twine/movements.h
+++ b/engines/twine/movements.h
@@ -87,17 +87,20 @@ private:
 	void processMovementExecution(int actorIdx);
 	void processRotationExecution(int actorIdx);
 
+	bool heroAction = false;
+
 public:
 	Movements(TwinEEngine *engine);
 
 	void update();
 
-	/** Hero moved */
-	bool heroMoved = false; // twinsenMove
 	/**
 	 * Hero executes the current action of the trigger zone
 	 */
-	bool heroAction = false;
+	bool shouldTriggerZoneAction() const;
+
+	/** Hero moved */
+	bool heroMoved = false; // twinsenMove
 
 	/** Process actor.x coordinate */
 	int16 processActorX = 0;
@@ -208,6 +211,10 @@ public:
 	void processActorMovements(int32 actorIdx);
 };
 
+inline bool Movements::shouldTriggerZoneAction() const {
+	return heroAction;
+}
+
 } // namespace TwinE
 
 #endif
diff --git a/engines/twine/scene.cpp b/engines/twine/scene.cpp
index 95b42ad2a7..865a14bb00 100644
--- a/engines/twine/scene.cpp
+++ b/engines/twine/scene.cpp
@@ -516,13 +516,13 @@ void Scene::processActorZones(int32 actorIdx) {
 				}
 				break;
 			case kObject:
-				if (IS_HERO(actorIdx) && _engine->_movements->heroAction) {
+				if (IS_HERO(actorIdx) && _engine->_movements->shouldTriggerZoneAction()) {
 					_engine->_animations->initAnim(AnimationTypes::kAction, 1, AnimationTypes::kStanding, 0);
 					processZoneExtraBonus(zone);
 				}
 				break;
 			case kText:
-				if (IS_HERO(actorIdx) && _engine->_movements->heroAction) {
+				if (IS_HERO(actorIdx) && _engine->_movements->shouldTriggerZoneAction()) {
 					_engine->freezeTime();
 					_engine->_text->setFontCrossColor(zone->infoData.DisplayText.textColor);
 					talkingActor = actorIdx;
diff --git a/engines/twine/script_life_v1.cpp b/engines/twine/script_life_v1.cpp
index 124c3973e8..774a2ba897 100644
--- a/engines/twine/script_life_v1.cpp
+++ b/engines/twine/script_life_v1.cpp
@@ -257,7 +257,7 @@ static int32 processLifeConditions(TwinEEngine *engine, LifeScriptContext &ctx)
 		engine->_scene->currentScriptValue = ctx.actor->hitBy;
 		break;
 	case kcACTION:
-		engine->_scene->currentScriptValue = engine->_movements->heroAction ? 1 : 0;
+		engine->_scene->currentScriptValue = engine->_movements->shouldTriggerZoneAction() ? 1 : 0;
 		break;
 	case kcFLAG_GAME: {
 		int32 flagIdx = ctx.stream.readByte();


Commit: d21bfbe914a6f037412ec0e4f668a2dc9559489e
    https://github.com/scummvm/scummvm/commit/d21bfbe914a6f037412ec0e4f668a2dc9559489e
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: moved cursor key mask handling into movement class

Changed paths:
    engines/twine/input.cpp
    engines/twine/input.h
    engines/twine/movements.cpp
    engines/twine/movements.h


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index 8d9cb7fdf2..a392933dd7 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -108,17 +108,7 @@ void Input::enableKeyMap(const char *id) {
 	debug("enable keymap %s", id);
 }
 
-static constexpr const struct ActionMapping {
-	TwinEActionType action;
-	uint8 mask;
-} cursorChangeMask[] = {
-    {MoveForward, 0x01},
-    {MoveBackward, 0x02},
-    {TurnLeft, 0x04},
-    {TurnRight, 0x08}
-};
-
-uint8 Input::processCustomEngineEventStart(const Common::Event &event) {
+void Input::processCustomEngineEventStart(const Common::Event &event) {
 	if (!_engine->cfgfile.Debug) {
 		switch (event.customType) {
 		case TwinEActionType::DebugGridCameraPressUp:
@@ -140,34 +130,21 @@ uint8 Input::processCustomEngineEventStart(const Common::Event &event) {
 	} else {
 		actionStates[event.customType] = 1 + event.kbdRepeat;
 	}
-	for (int i = 0; i < ARRAYSIZE(cursorChangeMask); ++i) {
-		if (event.customType == cursorChangeMask[i].action) {
-			return cursorChangeMask[i].mask;
-		}
-	}
-	return 0;
 }
 
-uint8 Input::processCustomEngineEventEnd(const Common::Event &event) {
+void Input::processCustomEngineEventEnd(const Common::Event &event) {
 	actionStates[event.customType] = 0;
-	for (int i = 0; i < ARRAYSIZE(cursorChangeMask); ++i) {
-		if (event.customType == cursorChangeMask[i].action) {
-			return cursorChangeMask[i].mask;
-		}
-	}
-	return 0;
 }
 
 void Input::readKeys() {
-	cursorKeyMask = 0;
 	Common::Event event;
 	while (g_system->getEventManager()->pollEvent(event)) {
 		switch (event.type) {
 		case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
-			cursorKeyMask |= processCustomEngineEventEnd(event);
+			processCustomEngineEventEnd(event);
 			break;
 		case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
-			cursorKeyMask |= processCustomEngineEventStart(event);
+			processCustomEngineEventStart(event);
 			break;
 		default:
 			break;
diff --git a/engines/twine/input.h b/engines/twine/input.h
index b4fbeac56a..5fdb24d0de 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -109,14 +109,6 @@ private:
 public:
 	Input(TwinEEngine *engine);
 
-	/**
-	 * @brief This is a bitmask of 4 bits that is changed whenever a cursor key has changed. A set bit
-	 * does not mean that the cursor is pressed - but that a change has happened in this particular frame
-	 *
-	 * @note This value is reset with every single call to @c readKeys()
-	 */
-	uint8 cursorKeyMask = 0;
-
 	/**
 	 * @brief Dependent on the context we are currently in the game, we might want to disable certain keymaps.
 	 * Like disabling ui keymaps when we are in-game - or vice versa.
@@ -159,8 +151,8 @@ public:
 	 * @brief Updates the internal action states
 	 */
 	void readKeys();
-	uint8 processCustomEngineEventStart(const Common::Event& event);
-	uint8 processCustomEngineEventEnd(const Common::Event& event);
+	void processCustomEngineEventStart(const Common::Event& event);
+	void processCustomEngineEventEnd(const Common::Event& event);
 };
 
 inline const Common::String Input::currentKeyMap() const {
diff --git a/engines/twine/movements.cpp b/engines/twine/movements.cpp
index dc2aafe4f1..0aa18e4d84 100644
--- a/engines/twine/movements.cpp
+++ b/engines/twine/movements.cpp
@@ -209,11 +209,46 @@ void Movements::moveActor(int32 angleFrom, int32 angleTo, int32 speed, ActorMove
 	movePtr->timeOfChange = _engine->lbaTime;
 }
 
+void Movements::ChangedCursorKeys::update(TwinEEngine* engine) {
+	if (engine->_input->isActionActive(TwinEActionType::TurnLeft)) {
+		leftChange = leftDown == 0;
+		leftDown = 1;
+	} else {
+		leftChange = leftDown;
+		leftDown = 0;
+	}
+
+	if (engine->_input->isActionActive(TwinEActionType::TurnRight)) {
+		rightChange = rightDown == 0;
+		rightDown = 1;
+	} else {
+		rightChange = rightDown;
+		rightDown = 0;
+	}
+
+	if (engine->_input->isActionActive(TwinEActionType::MoveBackward)) {
+		backwardChange = backwardDown == 0;
+		backwardDown = 1;
+	} else {
+		backwardChange = backwardDown;
+		backwardDown = 0;
+	}
+
+	if (engine->_input->isActionActive(TwinEActionType::MoveForward)) {
+		forwardChange = forwardDown == 0;
+		forwardDown = 1;
+	} else {
+		forwardChange = forwardDown;
+		forwardDown = 0;
+	}
+}
+
 void Movements::update() {
 	previousChangedCursorKeys = changedCursorKeys;
 	previousLoopActionKey = heroActionKey;
+
 	heroActionKey = _engine->_input->isHeroActionActive();
-	changedCursorKeys = _engine->_input->cursorKeyMask;
+	changedCursorKeys.update(_engine);
 }
 
 bool Movements::processBehaviourExecution(int actorIdx) {
diff --git a/engines/twine/movements.h b/engines/twine/movements.h
index ff44e5d870..23c3137981 100644
--- a/engines/twine/movements.h
+++ b/engines/twine/movements.h
@@ -34,12 +34,37 @@ class Movements {
 private:
 	TwinEEngine *_engine;
 
+	struct ChangedCursorKeys {
+		uint8 forwardChange = 0;
+		uint8 backwardChange = 0;
+		uint8 leftChange = 0;
+		uint8 rightChange = 0;
+		uint8 forwardDown = 0;
+		uint8 backwardDown = 0;
+		uint8 leftDown = 0;
+		uint8 rightDown = 0;
+
+		void update(TwinEEngine* engine);
+
+		inline bool operator==(const ChangedCursorKeys& rhs) const {
+			return forwardChange == rhs.forwardChange && backwardChange == rhs.backwardChange && leftChange == rhs.leftChange && rightChange == rhs.rightChange;
+		}
+
+		inline operator bool () const {
+			return forwardChange && backwardChange && leftChange && rightChange;
+		}
+
+		inline bool operator!=(const ChangedCursorKeys& rhs) const {
+			return forwardChange != rhs.forwardChange || backwardChange != rhs.backwardChange || leftChange != rhs.leftChange || rightChange != rhs.rightChange;
+		}
+	};
+
 	// enter, space, ...
 	int16 heroActionKey = 0;
 	int32 previousLoopActionKey = 0;
 	// cursor keys
-	int32 changedCursorKeys = 0;
-	int32 previousChangedCursorKeys = 0;
+	ChangedCursorKeys changedCursorKeys;
+	ChangedCursorKeys previousChangedCursorKeys;
 
 	/**
 	 * The Actor is controlled by the player. This works well only for the Hero Actor in general.
@@ -89,6 +114,14 @@ private:
 
 	bool heroAction = false;
 
+	/**
+	 * @brief This is a bitmask of 4 bits that is changed whenever a cursor key has changed. A set bit
+	 * does not mean that the cursor is pressed - but that a change has happened in this particular frame
+	 *
+	 * @note This value is reset with every single call to @c readKeys()
+	 */
+	uint8 cursorKeyMask = 0;
+
 public:
 	Movements(TwinEEngine *engine);
 


Commit: 689909012a986c347c860a4c24bb07c82b36d9e6
    https://github.com/scummvm/scummvm/commit/689909012a986c347c860a4c24bb07c82b36d9e6
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:24:46+01:00

Commit Message:
TWINE: fixed invalid action states after reading text from signs

Changed paths:
    engines/twine/text.cpp


diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index 2074d6a451..0162411908 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -596,8 +596,6 @@ int Text::printText10() {
 
 // TODO: refactor this code
 bool Text::drawTextFullscreen(int32 index) {
-	ScopedKeyMap scopedKeyMap(_engine, cutsceneKeyMapId);
-
 	_engine->_interface->saveClip();
 	_engine->_interface->resetClip();
 	_engine->_screens->copyScreen(_engine->frontVideoBuffer, _engine->workVideoBuffer);


Commit: 9acc282047b037f6e30129c65341a002595f6705
    https://github.com/scummvm/scummvm/commit/9acc282047b037f6e30129c65341a002595f6705
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:27:01+01:00

Commit Message:
TWINE: minor refactoring in drawTextFullscreen

Changed paths:
    engines/twine/text.cpp


diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index 0162411908..a67035d252 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -628,23 +628,19 @@ bool Text::drawTextFullscreen(int32 index) {
 		}
 		hasHiddenVox = false;
 
-		stopVox(currDialTextEntry);
-
 		printTextVar13 = 0;
 
-		if (printedText != 0) {
-			_engine->_interface->loadClip();
-			return aborted;
-		}
-
-		// wait displaying text
-		for (;;) {
-			_engine->readKeys();
-			if (_engine->shouldQuit() || _engine->_input->toggleAbortAction()) {
-				aborted = true;
-				break;
+		if (printedText == 0) {
+			stopVox(currDialTextEntry);
+			// wait displaying text
+			for (;;) {
+				_engine->readKeys();
+				if (_engine->shouldQuit() || _engine->_input->toggleAbortAction()) {
+					aborted = true;
+					break;
+				}
+				_engine->_system->delayMillis(1);
 			}
-			_engine->_system->delayMillis(1);
 		}
 	} else { // RECHECK THIS
 		while (playVox(currDialTextEntry)) {


Commit: f46cd54294f1503bb0ae7d4f4d0f1ddd83d88dd6
    https://github.com/scummvm/scummvm/commit/f46cd54294f1503bb0ae7d4f4d0f1ddd83d88dd6
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:34:05+01:00

Commit Message:
TWINE: allow to use the cutscene abort keys to interrupt fullscreen texts

Changed paths:
    engines/twine/text.cpp


diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index a67035d252..986c043acc 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -596,6 +596,7 @@ int Text::printText10() {
 
 // TODO: refactor this code
 bool Text::drawTextFullscreen(int32 index) {
+	const bool changedKeyMapState = _engine->_input->enableAdditionalKeyMap(cutsceneKeyMapId, true);
 	_engine->_interface->saveClip();
 	_engine->_interface->resetClip();
 	_engine->_screens->copyScreen(_engine->frontVideoBuffer, _engine->workVideoBuffer);
@@ -655,6 +656,10 @@ bool Text::drawTextFullscreen(int32 index) {
 		voxHiddenIndex = 0;
 	}
 
+	if (changedKeyMapState) {
+		_engine->_input->enableAdditionalKeyMap(cutsceneKeyMapId, false);
+	}
+
 	stopVox(currDialTextEntry);
 
 	_engine->_interface->loadClip();


Commit: 49be0a49a69da2b296f26c6b8f172e0c7cf40c5b
    https://github.com/scummvm/scummvm/commit/49be0a49a69da2b296f26c6b8f172e0c7cf40c5b
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:38:36+01:00

Commit Message:
TWINE: changed behaviour of ScopedKeyMap

it's dangerous to disable a keymap because you could lose the action state.
Now we just enable another keymap - and disable it after we are done. So
we don't lose the action state. This fixes a problem with the hero walking
along a sign and hit the action button. We are starting the text sequence.
Once this is over and you have released the cursor keys during read, the actor
would still move.

Changed paths:
    engines/twine/input.cpp
    engines/twine/input.h
    engines/twine/menu.cpp
    engines/twine/text.cpp


diff --git a/engines/twine/input.cpp b/engines/twine/input.cpp
index a392933dd7..2812f792e7 100644
--- a/engines/twine/input.cpp
+++ b/engines/twine/input.cpp
@@ -35,12 +35,13 @@ const char *uiKeyMapId = "uiKeyMap";
 const char *cutsceneKeyMapId = "cutsceneKeyMap";
 
 ScopedKeyMap::ScopedKeyMap(TwinEEngine* engine, const char *id) : _engine(engine) {
-	_prevKeyMap = _engine->_input->currentKeyMap();
-	_engine->_input->enableKeyMap(id);
+	_changed = _engine->_input->enableAdditionalKeyMap(id, true);
 }
 
 ScopedKeyMap::~ScopedKeyMap() {
-	_engine->_input->enableKeyMap(_prevKeyMap.c_str());
+	if (_changed) {
+		_engine->_input->enableAdditionalKeyMap(_keymap.c_str(), false);
+	}
 }
 
 Input::Input(TwinEEngine *engine) : _engine(engine) {}
diff --git a/engines/twine/input.h b/engines/twine/input.h
index 5fdb24d0de..e5e670cea1 100644
--- a/engines/twine/input.h
+++ b/engines/twine/input.h
@@ -93,7 +93,8 @@ struct MouseStatusStruct {
 class ScopedKeyMap {
 private:
 	TwinEEngine* _engine;
-	Common::String _prevKeyMap;
+	bool _changed;
+	Common::String _keymap;
 public:
 	ScopedKeyMap(TwinEEngine* engine, const char *id);
 	~ScopedKeyMap();
diff --git a/engines/twine/menu.cpp b/engines/twine/menu.cpp
index 9358752584..80738716d6 100644
--- a/engines/twine/menu.cpp
+++ b/engines/twine/menu.cpp
@@ -897,7 +897,7 @@ void Menu::processBehaviourMenu() {
 
 	int32 tmpTime = _engine->lbaTime;
 
-	const bool changedUiKeyMapState = _engine->_input->enableAdditionalKeyMap(uiKeyMapId, true);
+	ScopedKeyMap scoped(_engine, uiKeyMapId);
 	while (_engine->_input->isActionActive(TwinEActionType::BehaviourMenu) || _engine->_input->isQuickBehaviourActionActive()) {
 		_engine->readKeys();
 
@@ -928,9 +928,6 @@ void Menu::processBehaviourMenu() {
 		_engine->_system->delayMillis(1000 / 50);
 		_engine->lbaTime++;
 	}
-	if (changedUiKeyMapState) {
-		_engine->_input->enableAdditionalKeyMap(uiKeyMapId, false);
-	}
 
 	_engine->lbaTime = tmpTime;
 
diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index 986c043acc..66da6a3068 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -596,7 +596,7 @@ int Text::printText10() {
 
 // TODO: refactor this code
 bool Text::drawTextFullscreen(int32 index) {
-	const bool changedKeyMapState = _engine->_input->enableAdditionalKeyMap(cutsceneKeyMapId, true);
+	ScopedKeyMap scoped(_engine, cutsceneKeyMapId);
 	_engine->_interface->saveClip();
 	_engine->_interface->resetClip();
 	_engine->_screens->copyScreen(_engine->frontVideoBuffer, _engine->workVideoBuffer);
@@ -656,10 +656,6 @@ bool Text::drawTextFullscreen(int32 index) {
 		voxHiddenIndex = 0;
 	}
 
-	if (changedKeyMapState) {
-		_engine->_input->enableAdditionalKeyMap(cutsceneKeyMapId, false);
-	}
-
 	stopVox(currDialTextEntry);
 
 	_engine->_interface->loadClip();


Commit: a5158641673f9d6ea9e178dcf47f1fffbcdd349a
    https://github.com/scummvm/scummvm/commit/a5158641673f9d6ea9e178dcf47f1fffbcdd349a
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-11-21T15:55:44+01:00

Commit Message:
TWINE: fixed default key mappings

Changed paths:
    engines/twine/metaengine.cpp


diff --git a/engines/twine/metaengine.cpp b/engines/twine/metaengine.cpp
index 898842d557..d61be15caf 100644
--- a/engines/twine/metaengine.cpp
+++ b/engines/twine/metaengine.cpp
@@ -247,7 +247,8 @@ Common::KeymapArray TwinEMetaEngine::initKeymaps(const char *target) const {
 
 		act = new Action("CHANGEBEHAVIOUR", _("Change Behaviour"));
 		act->setCustomEngineActionEvent(TwinEActionType::BehaviourMenu);
-		act->addDefaultInputMapping("CTRL");
+		act->addDefaultInputMapping("LCTRL");
+		act->addDefaultInputMapping("RCTRL");
 		gameKeyMap->addAction(act);
 
 		act = new Action("OPTIONSMENU", _("Options Menu"));
@@ -263,13 +264,14 @@ Common::KeymapArray TwinEMetaEngine::initKeymaps(const char *target) const {
 
 		act = new Action("USESELECTEDOBJECT", _("Use Selected Object"));
 		act->setCustomEngineActionEvent(TwinEActionType::UseSelectedObject);
-		act->addDefaultInputMapping("SHIFT+RETURN");
-		act->addDefaultInputMapping("SHIFT+KP_ENTER");
+		act->addDefaultInputMapping("S+RETURN");
+		act->addDefaultInputMapping("S+KP_ENTER");
 		gameKeyMap->addAction(act);
 
 		act = new Action("THROWMAGICBALL", _("Throw Magic Ball"));
 		act->setCustomEngineActionEvent(TwinEActionType::ThrowMagicBall);
-		act->addDefaultInputMapping("ALT");
+		act->addDefaultInputMapping("LALT");
+		act->addDefaultInputMapping("RALT");
 		gameKeyMap->addAction(act);
 
 		act = new Action("MOVEFORWARD", _("Move Forward"));




More information about the Scummvm-git-logs mailing list