diff --git a/src/game/boe.actions.cpp b/src/game/boe.actions.cpp index c68123d2..a7039ee9 100644 --- a/src/game/boe.actions.cpp +++ b/src/game/boe.actions.cpp @@ -1648,6 +1648,8 @@ bool handle_keystroke(const sf::Event& event, cFramerateLimiter& fps_limiter){ Key::Numpad4,Key::Numpad5,Key::Numpad6, Key::Numpad7,Key::Numpad8,Key::Numpad9 }; + // Terrain map coordinates to simulate a click for 8-directional movement/waiting + // ordered to correspond with keypad keys location terrain_click[10] = { {150,185},{120,215},{150,215},{180,215}, {120,185},{150,185},{180,185}, @@ -1678,23 +1680,7 @@ bool handle_keystroke(const sf::Event& event, cFramerateLimiter& fps_limiter){ if(chr2 == Key::LShift || chr2 == Key::LAlt || chr2 == Key::LControl || chr2 == Key::LSystem) return false; if(chr2 == Key::RShift || chr2 == Key::RAlt || chr2 == Key::RControl || chr2 == Key::RSystem) return false; - if(chr2 == Key::Up && !kb.isDownPressed()) { - if(kb.isLeftPressed()) chr2 = Key::Numpad7; - else if(kb.isRightPressed()) chr2 = Key::Numpad9; - else chr2 = Key::Numpad8; - } else if(chr2 == Key::Down && !kb.isUpPressed()) { - if(kb.isLeftPressed()) chr2 = Key::Numpad1; - else if(kb.isRightPressed()) chr2 = Key::Numpad3; - else chr2 = Key::Numpad2; - } else if(chr2 == Key::Left && !kb.isRightPressed()) { - if(kb.isUpPressed()) chr2 = Key::Numpad7; - else if(kb.isDownPressed()) chr2 = Key::Numpad1; - else chr2 = Key::Numpad4; - } else if(chr2 == Key::Right && !kb.isLeftPressed()) { - if(kb.isUpPressed()) chr2 = Key::Numpad9; - else if(kb.isDownPressed()) chr2 = Key::Numpad3; - else chr2 = Key::Numpad6; - } else if(chr2 == Key::Home) chr2 = Key::Numpad7; + if(chr2 == Key::Home) chr2 = Key::Numpad7; else if(chr2 == Key::End) chr2 = Key::Numpad1; else if(chr2 == Key::PageUp) chr2 = Key::Numpad9; else if(chr2 == Key::PageDown) chr2 = Key::Numpad3; diff --git a/src/game/boe.main.cpp b/src/game/boe.main.cpp index 5d22fc4a..9001522f 100644 --- a/src/game/boe.main.cpp +++ b/src/game/boe.main.cpp @@ -471,10 +471,103 @@ void showWelcome() { welcome.show(); } +using Key = sf::Keyboard::Key; +std::map delayed_keys; +const int ARROW_SIMUL_FRAMES = 3; + +// Terrain map coordinates to simulate a click for 8-directional movement +// ordered to correspond with eDirection +// TODO terrain_click is duplicated (with different ordering) in boe.actions.cpp +location terrain_click[8] = { + {150,155}, // north + {180,135}, // northeast + {180,185}, // east + {180,215}, // southeast + {150,215}, // south + {120,215}, // southwest + {120,185}, // west + {120,155}, // northwest +}; + +void fire_delayed_key(Key code) { + bool isUpPressed = delayed_keys[Key::Up] > 0; + bool isDownPressed = delayed_keys[Key::Down] > 0; + bool isLeftPressed = delayed_keys[Key::Left] > 0; + bool isRightPressed = delayed_keys[Key::Right] > 0; + delayed_keys[Key::Up] = 0; + delayed_keys[Key::Down] = 0; + delayed_keys[Key::Left] = 0; + delayed_keys[Key::Right] = 0; + + bool diagonal = false; + int dir = -1; + + if(code == Key::Up && !isDownPressed) { + if(isLeftPressed){ dir = DIR_NW; diagonal = true; } + else if(isRightPressed){ dir = DIR_NE; diagonal = true; } + else dir = DIR_N; + } else if(code == Key::Down && !isUpPressed) { + if(isLeftPressed){ dir = DIR_SW; diagonal = true; } + else if(isRightPressed){ dir = DIR_SE; diagonal = true; } + else dir = DIR_S; + } else if(code == Key::Left && !isRightPressed) { + if(isUpPressed){ dir = DIR_NW; diagonal = true; } + else if(isDownPressed){ dir = DIR_SW; diagonal = true; } + else dir = DIR_W; + } else if(code == Key::Right && !isLeftPressed) { + if(isUpPressed){ dir = DIR_NE; diagonal = true; } + else if(isDownPressed){ dir = DIR_SE; diagonal = true; } + else dir = DIR_E; + } else { + return; + } + if(diagonal){ + mainPtr.setKeyRepeatEnabled(false); + }else{ + mainPtr.setKeyRepeatEnabled(true); + } + + if(dir != -1){ + sf::Event pass_event = {sf::Event::MouseButtonPressed}; + location pass_point = mainPtr.mapCoordsToPixel(terrain_click[dir], mainView); + pass_event.mouseButton.x = pass_point.x; + pass_event.mouseButton.y = pass_point.y; + queue_fake_event(pass_event); + } +} + +void handle_delayed_key(Key code) { + // a keypress of this code is already delayed, so push it through: + if(delayed_keys[code] > 0) + fire_delayed_key(code); + + delayed_keys[code] = ARROW_SIMUL_FRAMES; +} + +void update_delayed_keys() { + for(auto elem : delayed_keys){ + Key code = elem.first; + int countdown = elem.second; + + if(countdown > 0){ + --countdown; + delayed_keys[code] = countdown; + if(countdown == 0){ + fire_delayed_key(code); + } + } + } +} + void handle_events() { sf::Event currentEvent; cFramerateLimiter fps_limiter; + delayed_keys[Key::Left] = 0; + delayed_keys[Key::Right] = 0; + delayed_keys[Key::Up] = 0; + delayed_keys[Key::Down] = 0; + while(!All_Done) { if(replaying && has_next_action()){ replay_next_action(); @@ -499,6 +592,7 @@ void handle_events() { menuChoiceId=-1; } #endif + update_delayed_keys(); while(!fake_event_queue.empty()){ const sf::Event& next_event = fake_event_queue.front(); fake_event_queue.pop_front(); @@ -581,7 +675,12 @@ void handle_one_event(const sf::Event& event, cFramerateLimiter& fps_limiter) { switch(event.type) { case sf::Event::KeyPressed: if(flushingInput) return; - if(!(event.key.*systemKey)) handle_keystroke(event, fps_limiter); + if (delayed_keys.find(event.key.code) != delayed_keys.end()){ + handle_delayed_key(event.key.code); + } else if(!(event.key.*systemKey)) { + mainPtr.setKeyRepeatEnabled(true); + handle_keystroke(event, fps_limiter); + } break; case sf::Event::MouseButtonPressed: