Finalizing auto walk enhancements, closes #63, also other fixes:

* Can now auto walk up to 1000 steps!
* Re-added sexy topmenu buttons :)
* Tooltip for logout/edit will now change
* Changed xxStackpos to xxStackPos
This commit is contained in:
BeniS 2013-01-21 05:09:14 +13:00
parent c28596292f
commit 8c6d5a0f5c
16 changed files with 110 additions and 54 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 B

After

Width:  |  Height:  |  Size: 223 B

View File

@ -209,7 +209,7 @@ function addCreature(creature)
battleButton:setup(creature) battleButton:setup(creature)
battleButton.onHoverChange = onBattleButtonHoverChange battleButton.onHoverChange = onBattleButtonHoverChange
battleButton.onMouseRelease = onMouseRelease battleButton.onMouseRelease = onBattleButtonMouseRelease
battleButtonsByCreaturesList[creatureId] = battleButton battleButtonsByCreaturesList[creatureId] = battleButton
@ -225,7 +225,27 @@ function addCreature(creature)
end end
end end
function onMouseRelease(self, mousePosition, mouseButton) function removeAllCreatures()
for i, v in pairs(battleButtonsByCreaturesList) do
removeCreature(v.creature)
end
end
function removeCreature(creature)
if hasCreature(creature) then
local creatureId = creature:getId()
if lastBattleButtonSwitched == battleButtonsByCreaturesList[creatureId] then
lastBattleButtonSwitched = nil
end
battleButtonsByCreaturesList[creatureId].creature:hideStaticSquare()
battleButtonsByCreaturesList[creatureId]:destroy()
battleButtonsByCreaturesList[creatureId] = nil
end
end
function onBattleButtonMouseRelease(self, mousePosition, mouseButton)
if mouseWidget.cancelNextRelease then if mouseWidget.cancelNextRelease then
mouseWidget.cancelNextRelease = false mouseWidget.cancelNextRelease = false
return false return false
@ -249,26 +269,6 @@ function onMouseRelease(self, mousePosition, mouseButton)
return false return false
end end
function removeAllCreatures()
for i, v in pairs(battleButtonsByCreaturesList) do
removeCreature(v.creature)
end
end
function removeCreature(creature)
if hasCreature(creature) then
local creatureId = creature:getId()
if lastBattleButtonSwitched == battleButtonsByCreaturesList[creatureId] then
lastBattleButtonSwitched = nil
end
battleButtonsByCreaturesList[creatureId].creature:hideStaticSquare()
battleButtonsByCreaturesList[creatureId]:destroy()
battleButtonsByCreaturesList[creatureId] = nil
end
end
function onBattleButtonHoverChange(widget, hovered) function onBattleButtonHoverChange(widget, hovered)
if widget.isBattleButton then if widget.isBattleButton then
widget.isHovered = hovered widget.isHovered = hovered

View File

@ -49,7 +49,7 @@ function init()
gameBottomPanel = gameRootPanel:getChildById('gameBottomPanel') gameBottomPanel = gameRootPanel:getChildById('gameBottomPanel')
connect(gameLeftPanel, { onVisibilityChange = onLeftPanelVisibilityChange }) connect(gameLeftPanel, { onVisibilityChange = onLeftPanelVisibilityChange })
logoutButton = modules.client_topmenu.addLeftButton('logoutButton', 'Logout', '/images/topbuttons/logout', tryLogout, true) logoutButton = modules.client_topmenu.addLeftButton('logoutButton', 'Exit', '/images/topbuttons/logout', tryLogout, true)
bindKeys() bindKeys()
@ -111,6 +111,7 @@ function terminate()
end end
function onGameStart() function onGameStart()
logoutButton:setTooltip('Logout')
show() show()
-- open tibia has delay in auto walking -- open tibia has delay in auto walking
@ -120,6 +121,7 @@ function onGameStart()
end end
function onGameEnd() function onGameEnd()
logoutButton:setTooltip('Exit')
hide() hide()
end end

View File

@ -40,7 +40,8 @@ namespace Otc
STATIC_DURATION_PER_CHARACTER = 60, STATIC_DURATION_PER_CHARACTER = 60,
MIN_STATIC_TEXT_DURATION = 3000, MIN_STATIC_TEXT_DURATION = 3000,
MAX_STATIC_TEXT_WIDTH = 200, MAX_STATIC_TEXT_WIDTH = 200,
MAX_AUTOWALK_STEPS_RETRY = 10 MAX_AUTOWALK_STEPS_RETRY = 10,
MAX_AUTOWALK_DIST = 127
}; };
enum DrawFlags { enum DrawFlags {

View File

@ -717,7 +717,7 @@ void Game::look(const ThingPtr& thing)
if(thing->isCreature() && m_protocolVersion >= 961) if(thing->isCreature() && m_protocolVersion >= 961)
m_protocolGame->sendLookCreature(thing->getId()); m_protocolGame->sendLookCreature(thing->getId());
else else
m_protocolGame->sendLook(thing->getPosition(), thing->getId(), thing->getStackpos()); m_protocolGame->sendLook(thing->getPosition(), thing->getId(), thing->getStackPos());
} }
void Game::move(const ThingPtr& thing, const Position& toPos, int count) void Game::move(const ThingPtr& thing, const Position& toPos, int count)
@ -734,7 +734,7 @@ void Game::move(const ThingPtr& thing, const Position& toPos, int count)
id = Proto::Creature; id = Proto::Creature;
} }
m_protocolGame->sendMove(thing->getPosition(), id, thing->getStackpos(), toPos, count); m_protocolGame->sendMove(thing->getPosition(), id, thing->getStackPos(), toPos, count);
} }
void Game::moveToParentContainer(const ThingPtr& thing, int count) void Game::moveToParentContainer(const ThingPtr& thing, int count)
@ -751,7 +751,7 @@ void Game::rotate(const ThingPtr& thing)
if(!canPerformGameAction() || !thing) if(!canPerformGameAction() || !thing)
return; return;
m_protocolGame->sendRotateItem(thing->getPosition(), thing->getId(), thing->getStackpos()); m_protocolGame->sendRotateItem(thing->getPosition(), thing->getId(), thing->getStackPos());
} }
void Game::use(const ThingPtr& thing) void Game::use(const ThingPtr& thing)
@ -765,7 +765,7 @@ void Game::use(const ThingPtr& thing)
// some itens, e.g. parcel, are not set as containers but they are. // some itens, e.g. parcel, are not set as containers but they are.
// always try to use these items in free container slots. // always try to use these items in free container slots.
m_protocolGame->sendUseItem(pos, thing->getId(), thing->getStackpos(), findEmptyContainerId()); m_protocolGame->sendUseItem(pos, thing->getId(), thing->getStackPos(), findEmptyContainerId());
} }
void Game::useInventoryItem(int itemId) void Game::useInventoryItem(int itemId)
@ -788,9 +788,9 @@ void Game::useWith(const ItemPtr& item, const ThingPtr& toThing)
pos = Position(0xFFFF, 0, 0); // means that is a item in inventory pos = Position(0xFFFF, 0, 0); // means that is a item in inventory
if(toThing->isCreature()) if(toThing->isCreature())
m_protocolGame->sendUseOnCreature(pos, item->getId(), item->getStackpos(), toThing->getId()); m_protocolGame->sendUseOnCreature(pos, item->getId(), item->getStackPos(), toThing->getId());
else else
m_protocolGame->sendUseItemWith(pos, item->getId(), item->getStackpos(), toThing->getPosition(), toThing->getId(), toThing->getStackpos()); m_protocolGame->sendUseItemWith(pos, item->getId(), item->getStackPos(), toThing->getPosition(), toThing->getId(), toThing->getStackPos());
} }
void Game::useInventoryItemWith(int itemId, const ThingPtr& toThing) void Game::useInventoryItemWith(int itemId, const ThingPtr& toThing)
@ -803,7 +803,7 @@ void Game::useInventoryItemWith(int itemId, const ThingPtr& toThing)
if(toThing->isCreature()) if(toThing->isCreature())
m_protocolGame->sendUseOnCreature(pos, itemId, 0, toThing->getId()); m_protocolGame->sendUseOnCreature(pos, itemId, 0, toThing->getId());
else else
m_protocolGame->sendUseItemWith(pos, itemId, 0, toThing->getPosition(), toThing->getId(), toThing->getStackpos()); m_protocolGame->sendUseItemWith(pos, itemId, 0, toThing->getPosition(), toThing->getId(), toThing->getStackPos());
} }
int Game::open(const ItemPtr& item, const ContainerPtr& previousContainer) int Game::open(const ItemPtr& item, const ContainerPtr& previousContainer)
@ -817,7 +817,7 @@ int Game::open(const ItemPtr& item, const ContainerPtr& previousContainer)
else else
id = previousContainer->getId(); id = previousContainer->getId();
m_protocolGame->sendUseItem(item->getPosition(), item->getId(), item->getStackpos(), id); m_protocolGame->sendUseItem(item->getPosition(), item->getId(), item->getStackPos(), id);
return id; return id;
} }
@ -1121,7 +1121,7 @@ void Game::requestTrade(const ItemPtr& item, const CreaturePtr& creature)
{ {
if(!canPerformGameAction() || !item || !creature) if(!canPerformGameAction() || !item || !creature)
return; return;
m_protocolGame->sendRequestTrade(item->getPosition(), item->getId(), item->getStackpos(), creature->getId()); m_protocolGame->sendRequestTrade(item->getPosition(), item->getId(), item->getStackPos(), creature->getId());
} }
void Game::inspectTrade(bool counterOffer, int index) void Game::inspectTrade(bool counterOffer, int index)

View File

@ -184,33 +184,41 @@ void LocalPlayer::cancelWalk(Otc::Direction direction)
void LocalPlayer::updateAutoWalkSteps(bool walkFailed) void LocalPlayer::updateAutoWalkSteps(bool walkFailed)
{ {
if(!m_autoWalking) {
m_autoWalkSteps.clear();
return;
}
if(!m_lastAutoWalkDestination.isValid()) { if(!m_lastAutoWalkDestination.isValid()) {
return; return;
} }
// for now this cannot be done from lua, due to bot protection m_autoWalkSteps.push_back(m_position);
m_autoWalkSteps.push_back(m_lastAutoWalkDestination); if(m_lastAutoWalkDestination != m_position && (m_autoWalkSteps.size() >= Otc::MAX_AUTOWALK_STEPS_RETRY || walkFailed)) {
if(m_autoWalkSteps.size() >= Otc::MAX_AUTOWALK_STEPS_RETRY || walkFailed) {
autoWalk(m_lastAutoWalkDestination); autoWalk(m_lastAutoWalkDestination);
} }
else if(m_position == m_lastAutoWalkDestination && !m_autoWalkQueue.empty()) {
m_autoWalkQueue.pop_back();
// task the next destination
if(!m_autoWalkQueue.empty()) {
std::vector<Position> destinations = m_position.translatedToDirections(m_autoWalkQueue.back());
autoWalk(destinations.back());
}
}
} }
bool LocalPlayer::autoWalk(const Position& destination) bool LocalPlayer::autoWalk(const Position& destination)
{ {
m_autoWalkSteps.clear(); m_autoWalkSteps.clear();
m_lastAutoWalkDestination = destination; m_lastAutoWalkDestination = destination;
std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> result = g_map.findPath(m_position, destination, 127, Otc::PathFindAllowNullTiles);
std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> result = g_map.findPath(m_position, destination, 1000, Otc::PathFindAllowNullTiles);
std::vector<Otc::Direction> dirs = std::get<0>(result); std::vector<Otc::Direction> dirs = std::get<0>(result);
if(dirs.size() == 0) if(dirs.size() == 0)
return false; return false;
if(dirs.size() > Otc::MAX_AUTOWALK_DIST) {
dirs = calculateAutoWalk(dirs);
m_lastAutoWalkDestination = m_position.translatedToDirections(dirs).back();
}
g_game.autoWalk(dirs); g_game.autoWalk(dirs);
return true; return true;
} }
@ -219,6 +227,7 @@ void LocalPlayer::stopAutoWalkUpdate()
{ {
m_lastAutoWalkDestination = Position(); m_lastAutoWalkDestination = Position();
m_autoWalkSteps.clear(); m_autoWalkSteps.clear();
m_autoWalkQueue.clear();
} }
void LocalPlayer::stopWalk() void LocalPlayer::stopWalk()
@ -229,6 +238,29 @@ void LocalPlayer::stopWalk()
m_lastPrewalkDestionation = Position(); m_lastPrewalkDestionation = Position();
} }
std::vector<Otc::Direction> LocalPlayer::calculateAutoWalk(std::vector<Otc::Direction>& dirs)
{
if(dirs.size() > Otc::MAX_AUTOWALK_DIST) {
// populate auto walk queue
m_autoWalkQueue.clear();
size_t blocks = std::ceil((float)dirs.size() / Otc::MAX_AUTOWALK_DIST);
size_t size = Otc::MAX_AUTOWALK_DIST;
for(size_t i = 0, offset=0 ; i < blocks ; ++i) {
std::vector<Otc::Direction>::iterator next = dirs.begin() + offset;
if((offset + size) < dirs.size())
m_autoWalkQueue.push_back(std::vector<Otc::Direction>(next, next + size));
else
m_autoWalkQueue.push_back(std::vector<Otc::Direction>(next, dirs.end()));
offset += size;
}
std::reverse(m_autoWalkQueue.begin(), m_autoWalkQueue.end());
return m_autoWalkQueue.back();
}
return dirs;
}
void LocalPlayer::updateWalkOffset(int totalPixelsWalked) void LocalPlayer::updateWalkOffset(int totalPixelsWalked)
{ {
// pre walks offsets are calculated in the oposite direction // pre walks offsets are calculated in the oposite direction

View File

@ -43,6 +43,7 @@ public:
void updateAutoWalkSteps(bool walkFailed = false); void updateAutoWalkSteps(bool walkFailed = false);
bool autoWalk(const Position& destination); bool autoWalk(const Position& destination);
bool canWalk(Otc::Direction direction); bool canWalk(Otc::Direction direction);
std::vector<Otc::Direction> calculateAutoWalk(std::vector<Otc::Direction>& dirs);
void setStates(int states); void setStates(int states);
void setSkill(Otc::Skill skill, int level, int levelPercent); void setSkill(Otc::Skill skill, int level, int levelPercent);
@ -145,6 +146,7 @@ private:
std::array<int, Otc::LastSkill> m_skillsLevelPercent; std::array<int, Otc::LastSkill> m_skillsLevelPercent;
std::vector<int> m_spells; std::vector<int> m_spells;
std::vector<Position> m_autoWalkSteps; std::vector<Position> m_autoWalkSteps;
std::vector<std::vector<Otc::Direction> > m_autoWalkQueue;
int m_states; int m_states;
int m_vocation; int m_vocation;

View File

@ -285,6 +285,7 @@ void Client::registerLuaFunctions()
g_lua.bindClassMemberFunction<Thing>("getId", &Thing::getId); g_lua.bindClassMemberFunction<Thing>("getId", &Thing::getId);
g_lua.bindClassMemberFunction<Thing>("getPosition", &Thing::getPosition); g_lua.bindClassMemberFunction<Thing>("getPosition", &Thing::getPosition);
g_lua.bindClassMemberFunction<Thing>("getStackPriority", &Thing::getStackPriority); g_lua.bindClassMemberFunction<Thing>("getStackPriority", &Thing::getStackPriority);
g_lua.bindClassMemberFunction<Thing>("getStackPos", &Thing::getStackPos);
g_lua.bindClassMemberFunction<Thing>("getAnimationPhases", &Thing::getAnimationPhases); g_lua.bindClassMemberFunction<Thing>("getAnimationPhases", &Thing::getAnimationPhases);
g_lua.bindClassMemberFunction<Thing>("getTile", &Thing::getTile); g_lua.bindClassMemberFunction<Thing>("getTile", &Thing::getTile);
g_lua.bindClassMemberFunction<Thing>("isItem", &Thing::isItem); g_lua.bindClassMemberFunction<Thing>("isItem", &Thing::isItem);
@ -486,7 +487,7 @@ void Client::registerLuaFunctions()
g_lua.bindClassMemberFunction<Tile>("getThing", &Tile::getThing); g_lua.bindClassMemberFunction<Tile>("getThing", &Tile::getThing);
g_lua.bindClassMemberFunction<Tile>("getThings", &Tile::getThings); g_lua.bindClassMemberFunction<Tile>("getThings", &Tile::getThings);
g_lua.bindClassMemberFunction<Tile>("getItems", &Tile::getItems); g_lua.bindClassMemberFunction<Tile>("getItems", &Tile::getItems);
g_lua.bindClassMemberFunction<Tile>("getThingStackpos", &Tile::getThingStackpos); g_lua.bindClassMemberFunction<Tile>("getThingStackPos", &Tile::getThingStackPos);
g_lua.bindClassMemberFunction<Tile>("getThingCount", &Tile::getThingCount); g_lua.bindClassMemberFunction<Tile>("getThingCount", &Tile::getThingCount);
g_lua.bindClassMemberFunction<Tile>("getTopThing", &Tile::getTopThing); g_lua.bindClassMemberFunction<Tile>("getTopThing", &Tile::getTopThing);
g_lua.bindClassMemberFunction<Tile>("removeThing", &Tile::removeThing); g_lua.bindClassMemberFunction<Tile>("removeThing", &Tile::removeThing);

View File

@ -28,6 +28,8 @@
#include <framework/const.h> #include <framework/const.h>
#include <framework/util/point.h> #include <framework/util/point.h>
#include <vector>
class Position class Position
{ {
public: public:
@ -122,6 +124,22 @@ public:
return angle; return angle;
} }
std::vector<Position> translatedToDirections(const std::vector<Otc::Direction>& dirs) const {
Position lastPos = *this;
std::vector<Position> positions;
positions.push_back(lastPos);
for(auto dir : dirs) {
if(lastPos.isValid()) {
positions.push_back(lastPos);
}
lastPos = lastPos.translatedToDirection(dir);
}
return positions;
}
Otc::Direction getDirectionFromPosition(const Position& position) const { Otc::Direction getDirectionFromPosition(const Position& position) const {
int dx = position.x - x; int dx = position.x - x;
int dy = position.y - y; int dy = position.y - y;

View File

@ -65,7 +65,7 @@ public:
void sendAcceptTrade(); void sendAcceptTrade();
void sendRejectTrade(); void sendRejectTrade();
void sendUseItem(const Position& position, int itemId, int stackpos, int index); void sendUseItem(const Position& position, int itemId, int stackpos, int index);
void sendUseItemWith(const Position& fromPos, int itemId, int fromStackpos, const Position& toPos, int toThingId, int toStackpos); void sendUseItemWith(const Position& fromPos, int itemId, int fromStackPos, const Position& toPos, int toThingId, int toStackPos);
void sendUseOnCreature(const Position& pos, int thingId, int stackpos, uint creatureId); void sendUseOnCreature(const Position& pos, int thingId, int stackpos, uint creatureId);
void sendRotateItem(const Position& pos, int thingId, int stackpos); void sendRotateItem(const Position& pos, int thingId, int stackpos);
void sendCloseContainer(int containerId); void sendCloseContainer(int containerId);

View File

@ -553,7 +553,7 @@ void ProtocolGame::parseTileTransformThing(const InputMessagePtr& msg)
} }
Position pos = thing->getPosition(); Position pos = thing->getPosition();
int stackpos = thing->getStackpos(); int stackpos = thing->getStackPos();
if(!g_map.removeThing(thing)) { if(!g_map.removeThing(thing)) {
g_logger.traceError("unable to remove thing"); g_logger.traceError("unable to remove thing");

View File

@ -390,16 +390,16 @@ void ProtocolGame::sendUseItem(const Position& position, int itemId, int stackpo
send(msg); send(msg);
} }
void ProtocolGame::sendUseItemWith(const Position& fromPos, int itemId, int fromStackpos, const Position& toPos, int toThingId, int toStackpos) void ProtocolGame::sendUseItemWith(const Position& fromPos, int itemId, int fromStackPos, const Position& toPos, int toThingId, int toStackPos)
{ {
OutputMessagePtr msg(new OutputMessage); OutputMessagePtr msg(new OutputMessage);
msg->addU8(Proto::ClientUseItemWith); msg->addU8(Proto::ClientUseItemWith);
addPosition(msg, fromPos); addPosition(msg, fromPos);
msg->addU16(itemId); msg->addU16(itemId);
msg->addU8(fromStackpos); msg->addU8(fromStackPos);
addPosition(msg, toPos); addPosition(msg, toPos);
msg->addU16(toThingId); msg->addU16(toThingId);
msg->addU8(toStackpos); msg->addU8(toStackPos);
send(msg); send(msg);
} }

View File

@ -73,12 +73,12 @@ ContainerPtr Thing::getParentContainer()
return nullptr; return nullptr;
} }
int Thing::getStackpos() int Thing::getStackPos()
{ {
if(m_position.x == 65535 && isItem()) // is inside a container if(m_position.x == 65535 && isItem()) // is inside a container
return m_position.z; return m_position.z;
else if(const TilePtr& tile = getTile()) else if(const TilePtr& tile = getTile())
return tile->getThingStackpos(static_self_cast<Thing>()); return tile->getThingStackPos(static_self_cast<Thing>());
else { else {
g_logger.traceError("got a thing with invalid stackpos"); g_logger.traceError("got a thing with invalid stackpos");
return -1; return -1;

View File

@ -46,7 +46,7 @@ public:
int getStackPriority(); int getStackPriority();
const TilePtr& getTile(); const TilePtr& getTile();
ContainerPtr getParentContainer(); ContainerPtr getParentContainer();
int getStackpos(); int getStackPos();
virtual bool isItem() { return false; } virtual bool isItem() { return false; }
virtual bool isEffect() { return false; } virtual bool isEffect() { return false; }

View File

@ -276,7 +276,7 @@ bool Tile::hasThing(const ThingPtr& thing)
return std::find(m_things.begin(), m_things.end(), thing) != m_things.end(); return std::find(m_things.begin(), m_things.end(), thing) != m_things.end();
} }
int Tile::getThingStackpos(const ThingPtr& thing) int Tile::getThingStackPos(const ThingPtr& thing)
{ {
for(uint stackpos = 0; stackpos < m_things.size(); ++stackpos) for(uint stackpos = 0; stackpos < m_things.size(); ++stackpos)
if(thing == m_things[stackpos]) if(thing == m_things[stackpos])

View File

@ -74,7 +74,7 @@ public:
ThingPtr getThing(int stackPos); ThingPtr getThing(int stackPos);
EffectPtr getEffect(uint16 id); EffectPtr getEffect(uint16 id);
bool hasThing(const ThingPtr& thing); bool hasThing(const ThingPtr& thing);
int getThingStackpos(const ThingPtr& thing); int getThingStackPos(const ThingPtr& thing);
ThingPtr getTopThing(); ThingPtr getTopThing();
ThingPtr getTopLookThing(); ThingPtr getTopLookThing();