Improve walk when lagging
This commit is contained in:
parent
0891e2b30a
commit
e9e4dcd71b
|
@ -104,8 +104,8 @@ function bindKeys()
|
||||||
g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel)
|
g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel)
|
||||||
g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel)
|
g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel)
|
||||||
g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel)
|
g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel)
|
||||||
g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel)
|
g_keyboard.bindKeyDown('Ctrl+Q', tryLogout, gameRootPanel)
|
||||||
g_keyboard.bindKeyDown('Ctrl+L', logout, gameRootPanel)
|
g_keyboard.bindKeyDown('Ctrl+L', tryLogout, gameRootPanel)
|
||||||
g_keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel)
|
g_keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel)
|
||||||
g_keyboard.bindKeyDown('Ctrl+.', nextViewMode, gameRootPanel)
|
g_keyboard.bindKeyDown('Ctrl+.', nextViewMode, gameRootPanel)
|
||||||
end
|
end
|
||||||
|
@ -215,8 +215,8 @@ function tryExit()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local exitFunc = function() logout() forceExit() end
|
local exitFunc = function() g_game.safeLogout() forceExit() end
|
||||||
local logoutFunc = function() logout() exitWindow:destroy() exitWindow = nil end
|
local logoutFunc = function() g_game.safeLogout() exitWindow:destroy() exitWindow = nil end
|
||||||
local cancelFunc = function() exitWindow:destroy() exitWindow = nil end
|
local cancelFunc = function() exitWindow:destroy() exitWindow = nil end
|
||||||
|
|
||||||
exitWindow = displayGeneralBox(tr('Exit'), tr("If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character."),
|
exitWindow = displayGeneralBox(tr('Exit'), tr("If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character."),
|
||||||
|
@ -228,13 +228,6 @@ function tryExit()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function logout()
|
|
||||||
if g_game.isOnline() then
|
|
||||||
g_game.safeLogout()
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function tryLogout()
|
function tryLogout()
|
||||||
if not g_game.isOnline() then
|
if not g_game.isOnline() then
|
||||||
exit()
|
exit()
|
||||||
|
@ -245,13 +238,33 @@ function tryLogout()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local yesCallback = function() logout() logoutWindow:destroy() logoutWindow=nil end
|
if not g_game.isConnectionOk() then
|
||||||
local noCallback = function() logoutWindow:destroy() logoutWindow=nil end
|
local yesCallback = function()
|
||||||
|
g_game.forceLogout()
|
||||||
|
logoutWindow=nil
|
||||||
|
end
|
||||||
|
local noCallback = function()
|
||||||
|
logoutWindow=nil
|
||||||
|
end
|
||||||
|
|
||||||
logoutWindow = displayGeneralBox(tr('Logout'), tr('Are you sure you want to logout?'), {
|
logoutWindow = displayGeneralBox(tr('Logout'), tr('Your connection is failing, if you logout now your character will be still online, do you want to force logout?'), {
|
||||||
{ text=tr('Yes'), callback=yesCallback },
|
{ text=tr('Yes'), callback=yesCallback },
|
||||||
{ text=tr('No'), callback=noCallback },
|
{ text=tr('No'), callback=noCallback },
|
||||||
anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
|
anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
|
||||||
|
else
|
||||||
|
local yesCallback = function()
|
||||||
|
g_game.safeLogout()
|
||||||
|
logoutWindow=nil
|
||||||
|
end
|
||||||
|
local noCallback = function()
|
||||||
|
logoutWindow=nil
|
||||||
|
end
|
||||||
|
|
||||||
|
logoutWindow = displayGeneralBox(tr('Logout'), tr('Are you sure you want to logout?'), {
|
||||||
|
{ text=tr('Yes'), callback=yesCallback },
|
||||||
|
{ text=tr('No'), callback=noCallback },
|
||||||
|
anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function stopSmartWalk()
|
function stopSmartWalk()
|
||||||
|
|
|
@ -99,6 +99,11 @@ void Game::resetGameStates()
|
||||||
m_walkEvent = nullptr;
|
m_walkEvent = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(m_checkConnectionEvent) {
|
||||||
|
m_checkConnectionEvent->cancel();
|
||||||
|
m_checkConnectionEvent = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
m_containers.clear();
|
m_containers.clear();
|
||||||
m_vips.clear();
|
m_vips.clear();
|
||||||
m_gmActions.clear();
|
m_gmActions.clear();
|
||||||
|
@ -183,6 +188,16 @@ void Game::processGameStart()
|
||||||
g_game.ping();
|
g_game.ping();
|
||||||
}, m_pingDelay);
|
}, m_pingDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_checkConnectionEvent = g_dispatcher.cycleEvent([this] {
|
||||||
|
if(!g_game.isConnectionOk() && !m_connectionFailWarned) {
|
||||||
|
g_lua.callGlobalField("g_game", "onConnectionFailing", true);
|
||||||
|
m_connectionFailWarned = true;
|
||||||
|
} else if(g_game.isConnectionOk() && m_connectionFailWarned) {
|
||||||
|
g_lua.callGlobalField("g_game", "onConnectionFailing", false);
|
||||||
|
m_connectionFailWarned = false;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::processGameEnd()
|
void Game::processGameEnd()
|
||||||
|
@ -190,6 +205,11 @@ void Game::processGameEnd()
|
||||||
m_online = false;
|
m_online = false;
|
||||||
g_lua.callGlobalField("g_game", "onGameEnd");
|
g_lua.callGlobalField("g_game", "onGameEnd");
|
||||||
|
|
||||||
|
if(m_connectionFailWarned) {
|
||||||
|
g_lua.callGlobalField("g_game", "onConnectionFailing", false);
|
||||||
|
m_connectionFailWarned = false;
|
||||||
|
}
|
||||||
|
|
||||||
// reset game state
|
// reset game state
|
||||||
resetGameStates();
|
resetGameStates();
|
||||||
|
|
||||||
|
@ -551,6 +571,7 @@ bool Game::walk(Otc::Direction direction)
|
||||||
|
|
||||||
// check we can walk and add new walk event if false
|
// check we can walk and add new walk event if false
|
||||||
if(!m_localPlayer->canWalk(direction)) {
|
if(!m_localPlayer->canWalk(direction)) {
|
||||||
|
/*
|
||||||
if(m_lastWalkDir != direction) {
|
if(m_lastWalkDir != direction) {
|
||||||
// must add a new walk event
|
// must add a new walk event
|
||||||
float ticks = m_localPlayer->getStepTicksLeft();
|
float ticks = m_localPlayer->getStepTicksLeft();
|
||||||
|
@ -562,6 +583,7 @@ bool Game::walk(Otc::Direction direction)
|
||||||
}
|
}
|
||||||
m_walkEvent = g_dispatcher.scheduleEvent([=] { walk(direction); }, ticks);
|
m_walkEvent = g_dispatcher.scheduleEvent([=] { walk(direction); }, ticks);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -697,15 +719,16 @@ void Game::autoWalk(std::vector<Otc::Direction> dirs)
|
||||||
|
|
||||||
auto it = dirs.begin();
|
auto it = dirs.begin();
|
||||||
Otc::Direction direction = *it;
|
Otc::Direction direction = *it;
|
||||||
if(m_localPlayer->canWalk(direction)) {
|
if(!m_localPlayer->canWalk(direction))
|
||||||
TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction));
|
return;
|
||||||
if(toTile && toTile->isWalkable() && !m_localPlayer->isServerWalking()) {
|
|
||||||
m_localPlayer->preWalk(direction);
|
|
||||||
|
|
||||||
if(getFeature(Otc::GameForceFirstAutoWalkStep)) {
|
TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction));
|
||||||
forceWalk(direction);
|
if(toTile && toTile->isWalkable() && !m_localPlayer->isServerWalking()) {
|
||||||
dirs.erase(it);
|
m_localPlayer->preWalk(direction);
|
||||||
}
|
|
||||||
|
if(getFeature(Otc::GameForceFirstAutoWalkStep)) {
|
||||||
|
forceWalk(direction);
|
||||||
|
dirs.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -231,7 +231,7 @@ public:
|
||||||
void openRuleViolation(const std::string& reporter);
|
void openRuleViolation(const std::string& reporter);
|
||||||
void closeRuleViolation(const std::string& reporter);
|
void closeRuleViolation(const std::string& reporter);
|
||||||
void cancelRuleViolation();
|
void cancelRuleViolation();
|
||||||
|
|
||||||
// reports
|
// reports
|
||||||
void reportBug(const std::string& comment);
|
void reportBug(const std::string& comment);
|
||||||
void reportRuleViolation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment);
|
void reportRuleViolation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment);
|
||||||
|
@ -281,6 +281,7 @@ public:
|
||||||
bool isDead() { return m_dead; }
|
bool isDead() { return m_dead; }
|
||||||
bool isAttacking() { return !!m_attackingCreature; }
|
bool isAttacking() { return !!m_attackingCreature; }
|
||||||
bool isFollowing() { return !!m_followingCreature; }
|
bool isFollowing() { return !!m_followingCreature; }
|
||||||
|
bool isConnectionOk() { return m_protocolGame && m_protocolGame->getElapsedTicksSinceLastRead() < 5000; }
|
||||||
|
|
||||||
int getPing() { return m_ping >= 0 ? std::max(m_ping, m_pingTimer.elapsed_millis()) : -1; }
|
int getPing() { return m_ping >= 0 ? std::max(m_ping, m_pingTimer.elapsed_millis()) : -1; }
|
||||||
ContainerPtr getContainer(int index) { return m_containers[index]; }
|
ContainerPtr getContainer(int index) { return m_containers[index]; }
|
||||||
|
@ -340,6 +341,8 @@ private:
|
||||||
std::bitset<Otc::LastGameFeature> m_features;
|
std::bitset<Otc::LastGameFeature> m_features;
|
||||||
ScheduledEventPtr m_pingEvent;
|
ScheduledEventPtr m_pingEvent;
|
||||||
ScheduledEventPtr m_walkEvent;
|
ScheduledEventPtr m_walkEvent;
|
||||||
|
ScheduledEventPtr m_checkConnectionEvent;
|
||||||
|
bool m_connectionFailWarned;
|
||||||
int m_protocolVersion;
|
int m_protocolVersion;
|
||||||
int m_clientVersion;
|
int m_clientVersion;
|
||||||
std::string m_clientSignature;
|
std::string m_clientSignature;
|
||||||
|
|
|
@ -83,7 +83,7 @@ bool LocalPlayer::canWalk(Otc::Direction direction)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// cannot walk while already walking
|
// cannot walk while already walking
|
||||||
if(m_walking && !prewalkTimeouted)
|
if(m_walking && (!prewalkTimeouted || m_secondPreWalk))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -95,6 +95,7 @@ void LocalPlayer::walk(const Position& oldPos, const Position& newPos)
|
||||||
if(m_preWalking) {
|
if(m_preWalking) {
|
||||||
// switch to normal walking
|
// switch to normal walking
|
||||||
m_preWalking = false;
|
m_preWalking = false;
|
||||||
|
m_secondPreWalk = false;
|
||||||
m_lastPrewalkDone = true;
|
m_lastPrewalkDone = true;
|
||||||
// if is to the last prewalk destination, updates the walk preserving the animation
|
// if is to the last prewalk destination, updates the walk preserving the animation
|
||||||
if(newPos == m_lastPrewalkDestination) {
|
if(newPos == m_lastPrewalkDestination) {
|
||||||
|
@ -118,7 +119,8 @@ void LocalPlayer::preWalk(Otc::Direction direction)
|
||||||
Position newPos = m_position.translatedToDirection(direction);
|
Position newPos = m_position.translatedToDirection(direction);
|
||||||
|
|
||||||
// avoid reanimating prewalks
|
// avoid reanimating prewalks
|
||||||
if(m_preWalking && m_lastPrewalkDestination == newPos) {
|
if(m_preWalking) {
|
||||||
|
m_secondPreWalk = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,6 +279,7 @@ void LocalPlayer::terminateWalk()
|
||||||
{
|
{
|
||||||
Creature::terminateWalk();
|
Creature::terminateWalk();
|
||||||
m_preWalking = false;
|
m_preWalking = false;
|
||||||
|
m_secondPreWalk = false;
|
||||||
m_idleTimer.restart();
|
m_idleTimer.restart();
|
||||||
|
|
||||||
auto self = asLocalPlayer();
|
auto self = asLocalPlayer();
|
||||||
|
|
|
@ -126,6 +126,7 @@ private:
|
||||||
ticks_t m_walkLockExpiration;
|
ticks_t m_walkLockExpiration;
|
||||||
stdext::boolean<false> m_preWalking;
|
stdext::boolean<false> m_preWalking;
|
||||||
stdext::boolean<true> m_lastPrewalkDone;
|
stdext::boolean<true> m_lastPrewalkDone;
|
||||||
|
stdext::boolean<false> m_secondPreWalk;
|
||||||
stdext::boolean<false> m_serverWalking;
|
stdext::boolean<false> m_serverWalking;
|
||||||
stdext::boolean<false> m_knownCompletePath;
|
stdext::boolean<false> m_knownCompletePath;
|
||||||
|
|
||||||
|
|
|
@ -230,6 +230,7 @@ void Client::registerLuaFunctions()
|
||||||
g_lua.bindSingletonFunction("g_game", "isDead", &Game::isDead, &g_game);
|
g_lua.bindSingletonFunction("g_game", "isDead", &Game::isDead, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "isAttacking", &Game::isAttacking, &g_game);
|
g_lua.bindSingletonFunction("g_game", "isAttacking", &Game::isAttacking, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "isFollowing", &Game::isFollowing, &g_game);
|
g_lua.bindSingletonFunction("g_game", "isFollowing", &Game::isFollowing, &g_game);
|
||||||
|
g_lua.bindSingletonFunction("g_game", "isConnectionOk", &Game::isConnectionOk, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "getPing", &Game::getPing, &g_game);
|
g_lua.bindSingletonFunction("g_game", "getPing", &Game::getPing, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "getContainer", &Game::getContainer, &g_game);
|
g_lua.bindSingletonFunction("g_game", "getContainer", &Game::getContainer, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "getContainers", &Game::getContainers, &g_game);
|
g_lua.bindSingletonFunction("g_game", "getContainers", &Game::getContainers, &g_game);
|
||||||
|
|
|
@ -125,7 +125,7 @@ void Connection::write(uint8* buffer, size_t size)
|
||||||
m_outputStream = std::shared_ptr<asio::streambuf>(new asio::streambuf);
|
m_outputStream = std::shared_ptr<asio::streambuf>(new asio::streambuf);
|
||||||
|
|
||||||
m_delayedWriteTimer.cancel();
|
m_delayedWriteTimer.cancel();
|
||||||
m_delayedWriteTimer.expires_from_now(boost::posix_time::milliseconds(1));
|
m_delayedWriteTimer.expires_from_now(boost::posix_time::milliseconds(10));
|
||||||
m_delayedWriteTimer.async_wait(std::bind(&Connection::onCanWrite, asConnection(), std::placeholders::_1));
|
m_delayedWriteTimer.async_wait(std::bind(&Connection::onCanWrite, asConnection(), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +215,7 @@ void Connection::onResolve(const boost::system::error_code& error, asio::ip::bas
|
||||||
void Connection::onConnect(const boost::system::error_code& error)
|
void Connection::onConnect(const boost::system::error_code& error)
|
||||||
{
|
{
|
||||||
m_readTimer.cancel();
|
m_readTimer.cancel();
|
||||||
|
m_activityTimer.restart();
|
||||||
|
|
||||||
if(error == asio::error::operation_aborted)
|
if(error == asio::error::operation_aborted)
|
||||||
return;
|
return;
|
||||||
|
@ -263,6 +264,7 @@ void Connection::onWrite(const boost::system::error_code& error, size_t writeSiz
|
||||||
void Connection::onRecv(const boost::system::error_code& error, size_t recvSize)
|
void Connection::onRecv(const boost::system::error_code& error, size_t recvSize)
|
||||||
{
|
{
|
||||||
m_readTimer.cancel();
|
m_readTimer.cancel();
|
||||||
|
m_activityTimer.restart();
|
||||||
|
|
||||||
if(error == asio::error::operation_aborted)
|
if(error == asio::error::operation_aborted)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -61,6 +61,7 @@ public:
|
||||||
boost::system::error_code getError() { return m_error; }
|
boost::system::error_code getError() { return m_error; }
|
||||||
bool isConnecting() { return m_connecting; }
|
bool isConnecting() { return m_connecting; }
|
||||||
bool isConnected() { return m_connected; }
|
bool isConnected() { return m_connected; }
|
||||||
|
ticks_t getElapsedTicksSinceLastRead() { return m_connected ? m_activityTimer.elapsed_millis() : -1; }
|
||||||
|
|
||||||
ConnectionPtr asConnection() { return static_self_cast<Connection>(); }
|
ConnectionPtr asConnection() { return static_self_cast<Connection>(); }
|
||||||
|
|
||||||
|
@ -91,6 +92,7 @@ protected:
|
||||||
bool m_connected;
|
bool m_connected;
|
||||||
bool m_connecting;
|
bool m_connecting;
|
||||||
boost::system::error_code m_error;
|
boost::system::error_code m_error;
|
||||||
|
stdext::timer m_activityTimer;
|
||||||
|
|
||||||
friend class Server;
|
friend class Server;
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,6 +42,8 @@ public:
|
||||||
|
|
||||||
bool isConnected();
|
bool isConnected();
|
||||||
bool isConnecting();
|
bool isConnecting();
|
||||||
|
ticks_t getElapsedTicksSinceLastRead() { return m_connection ? m_connection->getElapsedTicksSinceLastRead() : -1; }
|
||||||
|
|
||||||
ConnectionPtr getConnection() { return m_connection; }
|
ConnectionPtr getConnection() { return m_connection; }
|
||||||
void setConnection(const ConnectionPtr& connection) { m_connection = connection; }
|
void setConnection(const ConnectionPtr& connection) { m_connection = connection; }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue