Implement new cool features

* Implement walk booster (dash) as an option in settings menu
* Dash is smarter (can pre-animate)
* Implement smart walking (walk in diagonal when holding two arrow keys)
* Implement ping meter for all protocols
* Ping meter uses uses real ping packet for 9.6 and walk for others
This commit is contained in:
Eduardo Bart 2012-08-25 16:11:54 -03:00
parent 0763b266d5
commit 4bac36d3bc
15 changed files with 193 additions and 63 deletions

View File

@ -1,12 +1,4 @@
Panel Panel
OptionCheckBox
id: classicControl
!text: tr('Classic control')
OptionCheckBox
id: autoChaseOverride
!text: tr('Allow auto chase override')
OptionCheckBox OptionCheckBox
id: showInfoMessagesInConsole id: showInfoMessagesInConsole
!text: tr('Show info messages in console') !text: tr('Show info messages in console')
@ -34,11 +26,3 @@ Panel
OptionCheckBox OptionCheckBox
id: showPrivateMessagesOnScreen id: showPrivateMessagesOnScreen
!text: tr('Show private messages on screen') !text: tr('Show private messages on screen')
OptionCheckBox
id: enableMusic
!text: tr('Enable music')
OptionCheckBox
id: showLeftPanel
!text: tr('Show left panel')

View File

@ -0,0 +1,21 @@
Panel
OptionCheckBox
id: classicControl
!text: tr('Classic control')
OptionCheckBox
id: autoChaseOverride
!text: tr('Allow auto chase override')
OptionCheckBox
id: walkBooster
!text: tr('Enable walk booster')
!tooltip: tr('Also know as dash in tibia community, recommended\nfor playing characters with high speed')
OptionCheckBox
id: enableMusic
!text: tr('Enable music')
OptionCheckBox
id: showLeftPanel
!text: tr('Show left panel')

View File

@ -5,6 +5,8 @@ local defaultOptions = {
showfps = true, showfps = true,
fullscreen = false, fullscreen = false,
classicControl = false, classicControl = false,
walkBooster = false,
smartWalk = false,
autoChaseOverride = true, autoChaseOverride = true,
showStatusMessagesInConsole = true, showStatusMessagesInConsole = true,
showEventMessagesInConsole = true, showEventMessagesInConsole = true,
@ -68,8 +70,8 @@ function Options.init()
end end
end end
g_keyboard.bindKeyDown('Ctrl+D', Options.toggle)
g_keyboard.bindKeyDown('Ctrl+F', function() Options.toggleOption('fullscreen') end) g_keyboard.bindKeyDown('Ctrl+F', function() Options.toggleOption('fullscreen') end)
g_keyboard.bindKeyDown('Ctrl+D', function() Options.toggleOption('walkBooster') end)
optionsWindow = g_ui.displayUI('options.otui') optionsWindow = g_ui.displayUI('options.otui')
optionsWindow:hide() optionsWindow:hide()
@ -78,8 +80,11 @@ function Options.init()
optionsTabBar = optionsWindow:getChildById('optionsTabBar') optionsTabBar = optionsWindow:getChildById('optionsTabBar')
optionsTabBar:setContentWidget(optionsWindow:getChildById('optionsTabContent')) optionsTabBar:setContentWidget(optionsWindow:getChildById('optionsTabContent'))
generalPanel = g_ui.loadUI('general.otui') generalPanel = g_ui.loadUI('game.otui')
optionsTabBar:addTab(tr('General'), generalPanel) optionsTabBar:addTab(tr('Game'), generalPanel)
generalPanel = g_ui.loadUI('console.otui')
optionsTabBar:addTab(tr('Console'), generalPanel)
graphicsPanel = g_ui.loadUI('graphics.otui') graphicsPanel = g_ui.loadUI('graphics.otui')
optionsTabBar:addTab(tr('Graphics'), graphicsPanel) optionsTabBar:addTab(tr('Graphics'), graphicsPanel)
@ -147,8 +152,8 @@ function Options.setOption(key, value)
end end
if graphicsPanel then if graphicsPanel then
graphicsPanel:getChildById('backgroundFrameRateLabel'):setText(tr('Game framerate limit: %s', text)) graphicsPanel:getChildById('backgroundFrameRateLabel'):setText(tr('Game framerate limit: %s', text))
end end
g_app.setBackgroundPaneMaxFps(value) g_app.setBackgroundPaneMaxFps(value)
elseif key == 'foregroundFrameRate' then elseif key == 'foregroundFrameRate' then
local text = value local text = value
@ -158,7 +163,7 @@ function Options.setOption(key, value)
end end
if graphicsPanel then if graphicsPanel then
graphicsPanel:getChildById('foregroundFrameRateLabel'):setText(tr('Interface framerate limit: %s', text)) graphicsPanel:getChildById('foregroundFrameRateLabel'):setText(tr('Interface framerate limit: %s', text))
end end
g_app.setForegroundPaneMaxFps(value) g_app.setForegroundPaneMaxFps(value)
elseif key == 'painterEngine' then elseif key == 'painterEngine' then

View File

@ -24,9 +24,43 @@ GameLabel < UILabel
color: #bbbbbb color: #bbbbbb
FrameCounterLabel < Label FrameCounterLabel < Label
font: verdana-11px-rounded
@onSetup: | @onSetup: |
self.updateEvent = cycleEvent(function() self.updateEvent = cycleEvent(function()
local text = 'FPS: ' .. g_app.getBackgroundPaneFps() local text = 'FPS: ' .. g_app.getBackgroundPaneFps()
self:setText(text) self:setText(text)
end, 1000) end, 1000)
@onDestroy: self.updateEvent:cancel() @onDestroy: self.updateEvent:cancel()
PingLabel < Label
font: verdana-11px-rounded
@onSetup: |
self.updateEvent = cycleEvent(function()
if g_game.isOnline() then
local ping = -1
if g_game.getFeature(GameClientPing) then
ping = g_game.getPing()
else
ping = g_game.getLocalPlayer():getWalkPing()
end
local text = 'Ping: '
if ping < 0 then
text = text .. "??"
self:setColor('yellow')
else
text = text .. ping .. ' ms'
if ping >= 500 then
self:setColor('red')
elseif ping >= 250 then
self:setColor('yellow')
else
self:setColor('green')
end
end
self:setText(text)
self:show()
else
self:hide()
end
end, 1000)
@onDestroy: self.updateEvent:cancel()

View File

@ -67,11 +67,21 @@ TopMenuPanel
anchors.left: prev.right anchors.left: prev.right
visible: false visible: false
TopMenuFrameCounterLabel FrameCounterLabel
color: white
margin-top: 4
margin-left: 5
id: frameCounter id: frameCounter
text-auto-resize: true text-auto-resize: true
anchors.top: parent.top anchors.top: parent.top
anchors.left: prev.right anchors.left: leftGameButtonsPanel.right
PingLabel
color: white
id: pingLabel
text-auto-resize: true
anchors.top: frameCounter.bottom
anchors.left: frameCounter.left
TopMenuButtonsPanel TopMenuButtonsPanel
id: rightButtonsPanel id: rightButtonsPanel

View File

@ -15,6 +15,14 @@ function translateKeyCombo(keyCombo)
return keyComboDesc return keyComboDesc
end end
local function getKeyCode(key)
for keyCode, keyDesc in pairs(KeyCodeDescs) do
if keyDesc:lower() == key:trim():lower() then
return keyCode
end
end
end
local function retranslateKeyComboDesc(keyComboDesc) local function retranslateKeyComboDesc(keyComboDesc)
if keyComboDesc == nil then if keyComboDesc == nil then
error('Unable to translate key combo \'' .. keyComboDesc .. '\'') error('Unable to translate key combo \'' .. keyComboDesc .. '\'')
@ -140,6 +148,13 @@ function g_keyboard.getModifiers()
return g_window.getKeyboardModifiers() return g_window.getKeyboardModifiers()
end end
function g_keyboard.isKeyPressed(key)
if type(key) == 'string' then
key = getKeyCode(key)
end
return g_window.isKeyPressed(key)
end
function g_keyboard.isCtrlPressed() function g_keyboard.isCtrlPressed()
return bit32.band(g_window.getKeyboardModifiers(), KeyboardCtrlModifier) ~= 0 return bit32.band(g_window.getKeyboardModifiers(), KeyboardCtrlModifier) ~= 0
end end

View File

@ -33,10 +33,18 @@ function init()
logoutButton = TopMenu.addRightButton('logoutButton', 'Logout', '/images/logout.png', tryLogout) logoutButton = TopMenu.addRightButton('logoutButton', 'Logout', '/images/logout.png', tryLogout)
logoutButton:hide() logoutButton:hide()
g_keyboard.bindKeyPress('Up', function() g_game.walk(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) bindKeys()
g_keyboard.bindKeyPress('Right', function() g_game.walk(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Down', function() g_game.walk(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) if g_game.isOnline() then
g_keyboard.bindKeyPress('Left', function() g_game.walk(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) show()
end
end
function bindKeys()
g_keyboard.bindKeyPress('Up', smartWalk, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Right', smartWalk, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Down', smartWalk, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Left', smartWalk, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Numpad8', function() g_game.walk(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Numpad8', function() g_game.walk(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Numpad9', function() g_game.walk(NorthEast) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Numpad9', function() g_game.walk(NorthEast) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Numpad6', function() g_game.walk(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Numpad6', function() g_game.walk(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
@ -59,19 +67,8 @@ function init()
g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+L', logout, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+L', logout, 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+;', toggleDash, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+.', function() g_keyboard.bindKeyDown('Ctrl+.', toggleAspectRatio, gameRootPanel)
if gameMapPanel:isKeepAspectRatioEnabled() then
gameMapPanel:setKeepAspectRatio(false)
else
gameMapPanel:setKeepAspectRatio(true)
gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
end
end, gameRootPanel)
if g_game.isOnline() then
show()
end
end end
function terminate() function terminate()
@ -155,6 +152,46 @@ function tryLogout()
anchor=AnchorHorizontalCenter}, yesCallback, noCallback) anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
end end
function smartWalk()
local dir
if g_keyboard.isKeyPressed('Up') and g_keyboard.isKeyPressed('Left') then
dir = NorthWest
elseif g_keyboard.isKeyPressed('Up') and g_keyboard.isKeyPressed('Right') then
dir = NorthEast
elseif g_keyboard.isKeyPressed('Down') and g_keyboard.isKeyPressed('Left') then
dir = SouthWest
elseif g_keyboard.isKeyPressed('Down') and g_keyboard.isKeyPressed('Right') then
dir = SouthEast
elseif g_keyboard.isKeyPressed('Up') then
dir = North
elseif g_keyboard.isKeyPressed('Down') then
dir = South
elseif g_keyboard.isKeyPressed('Left') then
dir = West
elseif g_keyboard.isKeyPressed('Right') then
dir = East
end
if Options.getOption('walkBooster') then
if g_game.getLocalPlayer():canWalk(dir) then
g_game.walk(dir)
else
g_game.forceWalk(dir)
end
else
g_game.walk(dir)
end
end
function toggleAspectRatio()
if gameMapPanel:isKeepAspectRatioEnabled() then
gameMapPanel:setKeepAspectRatio(false)
else
gameMapPanel:setKeepAspectRatio(true)
gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
end
end
function onMouseGrabberRelease(self, mousePosition, mouseButton) function onMouseGrabberRelease(self, mousePosition, mouseButton)
if selectedThing == nil then return false end if selectedThing == nil then return false end
if mouseButton == MouseLeftButton then if mouseButton == MouseLeftButton then

View File

@ -64,6 +64,7 @@ GameOfflineTrainingTime = 20
GamePurseSlot = 21 GamePurseSlot = 21
GameFormatCreatureName = 22 GameFormatCreatureName = 22
GameSpellList = 23 GameSpellList = 23
GameClientPing = 24
TextColors = { TextColors = {
red = '#f55e5e', --'#c83200' red = '#f55e5e', --'#c83200'

View File

@ -339,6 +339,7 @@ namespace Otc
GamePurseSlot = 21, GamePurseSlot = 21,
GameFormatCreatureName = 22, GameFormatCreatureName = 22,
GameSpellList = 23, GameSpellList = 23,
GameClientPing = 24,
// 23-50 unused yet // 23-50 unused yet
// 51-100 reserved to be defined in lua // 51-100 reserved to be defined in lua
LastGameFeature = 101 LastGameFeature = 101

View File

@ -55,6 +55,7 @@ void Game::resetGameStates()
m_dead = false; m_dead = false;
m_serverBeat = 50; m_serverBeat = 50;
m_seq = 0; m_seq = 0;
m_ping = -1;
m_canReportBugs = false; m_canReportBugs = false;
m_fightMode = Otc::FightBalanced; m_fightMode = Otc::FightBalanced;
m_chaseMode = Otc::DontChase; m_chaseMode = Otc::DontChase;
@ -68,6 +69,12 @@ void Game::resetGameStates()
if(container) if(container)
container->onClose(); container->onClose();
} }
if(m_pingEvent) {
m_pingEvent->cancel();
m_pingEvent = nullptr;
}
m_containers.clear(); m_containers.clear();
m_vips.clear(); m_vips.clear();
m_gmActions.clear(); m_gmActions.clear();
@ -122,6 +129,16 @@ void Game::processGameStart()
enableBotCall(); enableBotCall();
g_lua.callGlobalField("g_game", "onGameStart"); g_lua.callGlobalField("g_game", "onGameStart");
disableBotCall(); disableBotCall();
if(g_game.getFeature(Otc::GameClientPing)) {
m_pingEvent = g_dispatcher.cycleEvent([this] {
if(m_protocolGame && m_protocolGame->isConnected()) {
enableBotCall();
m_protocolGame->sendPing();
disableBotCall();
}
}, 1000);
}
} }
void Game::processGameEnd() void Game::processGameEnd()
@ -159,6 +176,7 @@ void Game::processPing()
void Game::processPingBack(int elapsed) void Game::processPingBack(int elapsed)
{ {
m_ping = elapsed;
g_lua.callGlobalField("g_game", "onPingBack", elapsed); g_lua.callGlobalField("g_game", "onPingBack", elapsed);
} }
@ -1175,8 +1193,9 @@ void Game::setClientVersion(int version)
enableFeature(Otc::GamePlayerMarket); enableFeature(Otc::GamePlayerMarket);
} }
if(version >= 954) { if(version >= 953) {
enableFeature(Otc::GamePurseSlot); enableFeature(Otc::GamePurseSlot);
enableFeature(Otc::GameClientPing);
} }
if(version >= 960) { if(version >= 960) {

View File

@ -252,6 +252,7 @@ public:
bool isAttacking() { return !!m_attackingCreature; } bool isAttacking() { return !!m_attackingCreature; }
bool isFollowing() { return !!m_followingCreature; } bool isFollowing() { return !!m_followingCreature; }
int getPing() { return m_ping; }
ContainerPtr getContainer(int index) { return m_containers[index]; } ContainerPtr getContainer(int index) { return m_containers[index]; }
std::map<int, ContainerPtr> getContainers() { return m_containers; } std::map<int, ContainerPtr> getContainers() { return m_containers; }
std::map<int, Vip> getVips() { return m_vips; } std::map<int, Vip> getVips() { return m_vips; }
@ -289,6 +290,7 @@ private:
bool m_denyBotCall; bool m_denyBotCall;
bool m_dead; bool m_dead;
int m_serverBeat; int m_serverBeat;
int m_ping;
uint m_seq; uint m_seq;
Otc::FightModes m_fightMode; Otc::FightModes m_fightMode;
Otc::ChaseModes m_chaseMode; Otc::ChaseModes m_chaseMode;
@ -298,6 +300,7 @@ private:
std::string m_characterName; std::string m_characterName;
std::string m_worldName; std::string m_worldName;
std::bitset<Otc::LastGameFeature> m_features; std::bitset<Otc::LastGameFeature> m_features;
ScheduledEventPtr m_pingEvent;
int m_clientVersion; int m_clientVersion;
}; };

View File

@ -37,6 +37,7 @@ LocalPlayer::LocalPlayer()
m_states = 0; m_states = 0;
m_vocation = 0; m_vocation = 0;
m_walkLockExpiration = 0; m_walkLockExpiration = 0;
m_lastWalkPing = -1;
m_skillsLevel.fill(-1); m_skillsLevel.fill(-1);
m_skillsBaseLevel.fill(-1); m_skillsBaseLevel.fill(-1);
@ -99,11 +100,8 @@ void LocalPlayer::walk(const Position& oldPos, const Position& newPos)
// a prewalk was going on // a prewalk was going on
if(m_preWalking) { if(m_preWalking) {
if(m_waitingWalkPong) { if(m_waitingWalkPong) {
if(newPos == m_lastPrewalkDestionation) { if(newPos == m_lastPrewalkDestionation)
m_lastWalkPings.push_back(m_walkPingTimer.ticksElapsed()); m_lastWalkPing = m_walkPingTimer.ticksElapsed();
if(m_lastWalkPings.size() > 10)
m_lastWalkPings.pop_front();
}
m_waitingWalkPong = false; m_waitingWalkPong = false;
} }
@ -120,6 +118,7 @@ void LocalPlayer::walk(const Position& oldPos, const Position& newPos)
} }
// no prewalk was going on, this must be an server side automated walk // no prewalk was going on, this must be an server side automated walk
else { else {
m_walkPingTimer.restart();
m_autoWalking = true; m_autoWalking = true;
if(m_autoWalkEndEvent) if(m_autoWalkEndEvent)
m_autoWalkEndEvent->cancel(); m_autoWalkEndEvent->cancel();
@ -136,6 +135,12 @@ void LocalPlayer::preWalk(Otc::Direction direction)
if(m_preWalking && m_lastPrewalkDestionation == newPos) if(m_preWalking && m_lastPrewalkDestionation == newPos)
return; return;
m_waitingWalkPong = false;
if(m_walkPingTimer.ticksElapsed() > getStepDuration() && m_idleTimer.ticksElapsed() > getStepDuration()*2) {
m_waitingWalkPong = true;
m_walkPingTimer.restart();
}
m_preWalking = true; m_preWalking = true;
if(m_autoWalkEndEvent) if(m_autoWalkEndEvent)
@ -155,6 +160,8 @@ void LocalPlayer::cancelWalk(Otc::Direction direction)
m_lastPrewalkDone = true; m_lastPrewalkDone = true;
m_waitingWalkPong = false; m_waitingWalkPong = false;
m_walkPingTimer.restart();
m_idleTimer.restart();
// turn to the cancel direction // turn to the cancel direction
if(direction != Otc::InvalidDirection) if(direction != Otc::InvalidDirection)
@ -206,6 +213,7 @@ void LocalPlayer::terminateWalk()
{ {
Creature::terminateWalk(); Creature::terminateWalk();
m_preWalking = false; m_preWalking = false;
m_idleTimer.restart();
auto self = asLocalPlayer(); auto self = asLocalPlayer();
@ -458,17 +466,6 @@ void LocalPlayer::setSpells(const std::vector<int>& spells)
} }
} }
double LocalPlayer::getWalkPing()
{
if(m_lastWalkPings.empty())
return 9999;
double sum = 0;
for(int p : m_lastWalkPings)
sum += p;
return sum / (double)m_lastWalkPings.size();
}
bool LocalPlayer::hasSight(const Position& pos) bool LocalPlayer::hasSight(const Position& pos)
{ {
return m_position.isInRange(pos, (Otc::VISIBLE_X_TILES - 1)/2, (Otc::VISIBLE_Y_TILES - 1)/2); return m_position.isInRange(pos, (Otc::VISIBLE_X_TILES - 1)/2, (Otc::VISIBLE_Y_TILES - 1)/2);

View File

@ -66,7 +66,7 @@ public:
int getSkillBaseLevel(Otc::Skill skill) { return m_skillsBaseLevel[skill]; } int getSkillBaseLevel(Otc::Skill skill) { return m_skillsBaseLevel[skill]; }
int getSkillLevelPercent(Otc::Skill skill) { return m_skillsLevelPercent[skill]; } int getSkillLevelPercent(Otc::Skill skill) { return m_skillsLevelPercent[skill]; }
int getVocation() { return m_vocation; } int getVocation() { return m_vocation; }
double getWalkPing(); int getWalkPing() { return m_lastWalkPing; }
double getHealth() { return m_health; } double getHealth() { return m_health; }
double getMaxHealth() { return m_maxHealth; } double getMaxHealth() { return m_maxHealth; }
double getFreeCapacity() { return m_freeCapacity; } double getFreeCapacity() { return m_freeCapacity; }
@ -122,7 +122,8 @@ private:
ScheduledEventPtr m_autoWalkEndEvent; ScheduledEventPtr m_autoWalkEndEvent;
stdext::boolean<false> m_waitingWalkPong; stdext::boolean<false> m_waitingWalkPong;
Timer m_walkPingTimer; Timer m_walkPingTimer;
std::deque<int> m_lastWalkPings; Timer m_idleTimer;
int m_lastWalkPing;
std::array<int, Otc::LastSkill> m_skillsLevel; std::array<int, Otc::LastSkill> m_skillsLevel;
std::array<int, Otc::LastSkill> m_skillsBaseLevel; std::array<int, Otc::LastSkill> m_skillsBaseLevel;

View File

@ -199,6 +199,7 @@ void OTClient::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", "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);
g_lua.bindSingletonFunction("g_game", "getVips", &Game::getVips, &g_game); g_lua.bindSingletonFunction("g_game", "getVips", &Game::getVips, &g_game);
@ -412,6 +413,7 @@ void OTClient::registerLuaFunctions()
g_lua.bindClassMemberFunction<LocalPlayer>("getTotalCapacity", &LocalPlayer::getTotalCapacity); g_lua.bindClassMemberFunction<LocalPlayer>("getTotalCapacity", &LocalPlayer::getTotalCapacity);
g_lua.bindClassMemberFunction<LocalPlayer>("getInventoryItem", &LocalPlayer::getInventoryItem); g_lua.bindClassMemberFunction<LocalPlayer>("getInventoryItem", &LocalPlayer::getInventoryItem);
g_lua.bindClassMemberFunction<LocalPlayer>("getVocation", &LocalPlayer::getVocation); g_lua.bindClassMemberFunction<LocalPlayer>("getVocation", &LocalPlayer::getVocation);
g_lua.bindClassMemberFunction<LocalPlayer>("getWalkPing", &LocalPlayer::getWalkPing);
g_lua.bindClassMemberFunction<LocalPlayer>("isPremium", &LocalPlayer::isPremium); g_lua.bindClassMemberFunction<LocalPlayer>("isPremium", &LocalPlayer::isPremium);
g_lua.bindClassMemberFunction<LocalPlayer>("isKnown", &LocalPlayer::isKnown); g_lua.bindClassMemberFunction<LocalPlayer>("isKnown", &LocalPlayer::isKnown);
g_lua.bindClassMemberFunction<LocalPlayer>("isPreWalking", &LocalPlayer::isPreWalking); g_lua.bindClassMemberFunction<LocalPlayer>("isPreWalking", &LocalPlayer::isPreWalking);

View File

@ -73,8 +73,8 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
break; break;
case Proto::GameServerPing: case Proto::GameServerPing:
case Proto::GameServerPingBack: case Proto::GameServerPingBack:
if((opcode == Proto::GameServerPing && g_game.getClientVersion() >= 953) || if((opcode == Proto::GameServerPing && g_game.getFeature(Otc::GameClientPing)) ||
(opcode == Proto::GameServerPingBack && g_game.getClientVersion() < 953)) (opcode == Proto::GameServerPingBack && !g_game.getFeature(Otc::GameClientPing)))
parsePingBack(msg); parsePingBack(msg);
else else
parsePing(msg); parsePing(msg);