Fix for bug 1196.

This bug would cause the player to jump when jump was assigned to
Space and they closed a dialog with Space. I tested vanilla
MW for behaviour and found that Jump was the only basic input which
MW does not allow when closing dialogs (i.e. if Space is assigned to
move forward, MW will move you forward after closing the dialog).

There were two reasons for the bug:
1) OpenMW GUI does not consume UI events
2) Jump occurs so long as key is down (not only on first key down)

To minimally fix the bug, I made it so that keypress events can be
consumed by the GUI and not passed along to the player control
input manager (1). However, if the player holds space, they will still
jump (as the subsequent key held events will be captured and cause
a jump).

Unfortunately, there is no idiomatic way that I could find in the
OpenMW input manager to perform events only on key down. Instead,
I introduced a variable which tracks whether the jump key has been
pressed for the first time within the current frame (2).

Note: I was initially concerned that limiting the jump event to
KeyDown and not Key Hold would cause issues with swimming,
levitating, or variable height jumping. However, after a bunch
of testing in vanilla MW and exploration of the OpenMW codebase
I could find nothing suggesting the need to capture the jump
key being held.
deque
Fil Krynicki 11 years ago
parent 65161c3e24
commit 91f4967614

@ -113,6 +113,7 @@ namespace MWInput
, mTimeIdle(0.f)
, mOverencumberedMessageDelay(0.f)
, mAlwaysRunActive(false)
, mAttemptJump(false)
{
Ogre::RenderWindow* window = ogre.getWindow ();
@ -173,6 +174,11 @@ namespace MWInput
MWWorld::Class::get(mPlayer->getPlayer()).getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue);
}
if (action == A_Jump)
{
mAttemptJump = (currentValue == 1.0 && previousValue == 0.0);
}
if (currentValue == 1)
{
// trigger action activated
@ -292,107 +298,107 @@ namespace MWInput
}
// Disable movement in Gui mode
if (MWBase::Environment::get().getWindowManager()->isGuiMode()
|| MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running)
return;
// Configure player movement according to keyboard input. Actual movement will
// be done in the physics system.
if (mControlSwitch["playercontrols"])
if (!(MWBase::Environment::get().getWindowManager()->isGuiMode()
|| MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running))
{
bool triedToMove = false;
if (actionIsActive(A_MoveLeft))
// Configure player movement according to keyboard input. Actual movement will
// be done in the physics system.
if (mControlSwitch["playercontrols"])
{
triedToMove = true;
mPlayer->setLeftRight (-1);
}
else if (actionIsActive(A_MoveRight))
{
triedToMove = true;
mPlayer->setLeftRight (1);
}
bool triedToMove = false;
if (actionIsActive(A_MoveLeft))
{
triedToMove = true;
mPlayer->setLeftRight (-1);
}
else if (actionIsActive(A_MoveRight))
{
triedToMove = true;
mPlayer->setLeftRight (1);
}
if (actionIsActive(A_MoveForward))
{
triedToMove = true;
mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (1);
}
else if (actionIsActive(A_MoveBackward))
{
triedToMove = true;
mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (-1);
}
if (actionIsActive(A_MoveForward))
{
triedToMove = true;
mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (1);
}
else if (actionIsActive(A_MoveBackward))
{
triedToMove = true;
mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (-1);
}
else if(mPlayer->getAutoMove())
{
triedToMove = true;
mPlayer->setForwardBackward (1);
}
else if(mPlayer->getAutoMove())
{
triedToMove = true;
mPlayer->setForwardBackward (1);
}
mPlayer->setSneak(actionIsActive(A_Sneak));
mPlayer->setSneak(actionIsActive(A_Sneak));
if (actionIsActive(A_Jump) && mControlSwitch["playerjumping"])
{
mPlayer->setUpDown (1);
triedToMove = true;
}
if (mAttemptJump && mControlSwitch["playerjumping"])
{
mPlayer->setUpDown (1);
triedToMove = true;
}
if (mAlwaysRunActive)
mPlayer->setRunState(!actionIsActive(A_Run));
else
mPlayer->setRunState(actionIsActive(A_Run));
if (mAlwaysRunActive)
mPlayer->setRunState(!actionIsActive(A_Run));
else
mPlayer->setRunState(actionIsActive(A_Run));
// if player tried to start moving, but can't (due to being overencumbered), display a notification.
if (triedToMove)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
mOverencumberedMessageDelay -= dt;
if (MWWorld::Class::get(player).getEncumbrance(player) >= MWWorld::Class::get(player).getCapacity(player))
// if player tried to start moving, but can't (due to being overencumbered), display a notification.
if (triedToMove)
{
mPlayer->setAutoMove (false);
if (mOverencumberedMessageDelay <= 0)
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
mOverencumberedMessageDelay -= dt;
if (MWWorld::Class::get(player).getEncumbrance(player) >= MWWorld::Class::get(player).getCapacity(player))
{
MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage59}");
mOverencumberedMessageDelay = 1.0;
mPlayer->setAutoMove (false);
if (mOverencumberedMessageDelay <= 0)
{
MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage59}");
mOverencumberedMessageDelay = 1.0;
}
}
}
}
if (mControlSwitch["playerviewswitch"]) {
// work around preview mode toggle when pressing Alt+Tab
if (actionIsActive(A_TogglePOV) && !mInputManager->isModifierHeld(SDL_Keymod(KMOD_ALT))) {
if (mPreviewPOVDelay <= 0.5 &&
(mPreviewPOVDelay += dt) > 0.5)
{
mPreviewPOVDelay = 1.f;
MWBase::Environment::get().getWorld()->togglePreviewMode(true);
if (mControlSwitch["playerviewswitch"]) {
// work around preview mode toggle when pressing Alt+Tab
if (actionIsActive(A_TogglePOV) && !mInputManager->isModifierHeld(SDL_Keymod(KMOD_ALT))) {
if (mPreviewPOVDelay <= 0.5 &&
(mPreviewPOVDelay += dt) > 0.5)
{
mPreviewPOVDelay = 1.f;
MWBase::Environment::get().getWorld()->togglePreviewMode(true);
}
} else {
//disable preview mode
MWBase::Environment::get().getWorld()->togglePreviewMode(false);
if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= 0.5) {
MWBase::Environment::get().getWorld()->togglePOV();
}
mPreviewPOVDelay = 0.f;
}
} else {
//disable preview mode
MWBase::Environment::get().getWorld()->togglePreviewMode(false);
if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= 0.5) {
MWBase::Environment::get().getWorld()->togglePOV();
}
mPreviewPOVDelay = 0.f;
}
}
if (actionIsActive(A_MoveForward) ||
actionIsActive(A_MoveBackward) ||
actionIsActive(A_MoveLeft) ||
actionIsActive(A_MoveRight) ||
actionIsActive(A_Jump) ||
actionIsActive(A_Sneak) ||
actionIsActive(A_TogglePOV))
{
resetIdleTime();
} else {
updateIdleTime(dt);
}
}
if (actionIsActive(A_MoveForward) ||
actionIsActive(A_MoveBackward) ||
actionIsActive(A_MoveLeft) ||
actionIsActive(A_MoveRight) ||
actionIsActive(A_Jump) ||
actionIsActive(A_Sneak) ||
actionIsActive(A_TogglePOV))
{
resetIdleTime();
} else {
updateIdleTime(dt);
}
mAttemptJump = false; // Can only jump on first frame input is on
}
void InputManager::setDragDrop(bool dragDrop)
@ -502,12 +508,13 @@ namespace MWInput
}
}
mInputBinder->keyPressed (arg);
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym);
bool passToBinder = true;
if (kc != OIS::KC_UNASSIGNED)
MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0);
passToBinder = !MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0);
if(passToBinder)
mInputBinder->keyPressed (arg);
}
void InputManager::textInput(const SDL_TextInputEvent &arg)

@ -161,6 +161,7 @@ namespace MWInput
int mMouseWheel;
bool mUserFileExists;
bool mAlwaysRunActive;
bool mAttemptJump;
std::map<std::string, bool> mControlSwitch;

Loading…
Cancel
Save