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.onHoverChange = onBattleButtonHoverChange
battleButton.onMouseRelease = onMouseRelease
battleButton.onMouseRelease = onBattleButtonMouseRelease
battleButtonsByCreaturesList[creatureId] = battleButton
@ -225,7 +225,27 @@ function addCreature(creature)
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
mouseWidget.cancelNextRelease = false
return false
@ -249,26 +269,6 @@ function onMouseRelease(self, mousePosition, mouseButton)
return false
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)
if widget.isBattleButton then
widget.isHovered = hovered

View File

@ -49,7 +49,7 @@ function init()
gameBottomPanel = gameRootPanel:getChildById('gameBottomPanel')
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()
@ -111,6 +111,7 @@ function terminate()
end
function onGameStart()
logoutButton:setTooltip('Logout')
show()
-- open tibia has delay in auto walking
@ -120,6 +121,7 @@ function onGameStart()
end
function onGameEnd()
logoutButton:setTooltip('Exit')
hide()
end

View File

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

View File

@ -717,7 +717,7 @@ void Game::look(const ThingPtr& thing)
if(thing->isCreature() && m_protocolVersion >= 961)
m_protocolGame->sendLookCreature(thing->getId());
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)
@ -734,7 +734,7 @@ void Game::move(const ThingPtr& thing, const Position& toPos, int count)
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)
@ -751,7 +751,7 @@ void Game::rotate(const ThingPtr& thing)
if(!canPerformGameAction() || !thing)
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)
@ -765,7 +765,7 @@ void Game::use(const ThingPtr& thing)
// some itens, e.g. parcel, are not set as containers but they are.
// 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)
@ -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
if(toThing->isCreature())
m_protocolGame->sendUseOnCreature(pos, item->getId(), item->getStackpos(), toThing->getId());
m_protocolGame->sendUseOnCreature(pos, item->getId(), item->getStackPos(), toThing->getId());
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)
@ -803,7 +803,7 @@ void Game::useInventoryItemWith(int itemId, const ThingPtr& toThing)
if(toThing->isCreature())
m_protocolGame->sendUseOnCreature(pos, itemId, 0, toThing->getId());
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)
@ -817,7 +817,7 @@ int Game::open(const ItemPtr& item, const ContainerPtr& previousContainer)
else
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;
}
@ -1121,7 +1121,7 @@ void Game::requestTrade(const ItemPtr& item, const CreaturePtr& creature)
{
if(!canPerformGameAction() || !item || !creature)
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)

View File

@ -184,33 +184,41 @@ void LocalPlayer::cancelWalk(Otc::Direction direction)
void LocalPlayer::updateAutoWalkSteps(bool walkFailed)
{
if(!m_autoWalking) {
m_autoWalkSteps.clear();
return;
}
if(!m_lastAutoWalkDestination.isValid()) {
return;
}
// for now this cannot be done from lua, due to bot protection
m_autoWalkSteps.push_back(m_lastAutoWalkDestination);
if(m_autoWalkSteps.size() >= Otc::MAX_AUTOWALK_STEPS_RETRY || walkFailed) {
m_autoWalkSteps.push_back(m_position);
if(m_lastAutoWalkDestination != m_position && (m_autoWalkSteps.size() >= Otc::MAX_AUTOWALK_STEPS_RETRY || walkFailed)) {
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)
{
m_autoWalkSteps.clear();
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);
if(dirs.size() == 0)
return false;
if(dirs.size() > Otc::MAX_AUTOWALK_DIST) {
dirs = calculateAutoWalk(dirs);
m_lastAutoWalkDestination = m_position.translatedToDirections(dirs).back();
}
g_game.autoWalk(dirs);
return true;
}
@ -219,6 +227,7 @@ void LocalPlayer::stopAutoWalkUpdate()
{
m_lastAutoWalkDestination = Position();
m_autoWalkSteps.clear();
m_autoWalkQueue.clear();
}
void LocalPlayer::stopWalk()
@ -229,6 +238,29 @@ void LocalPlayer::stopWalk()
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)
{
// pre walks offsets are calculated in the oposite direction

View File

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

View File

@ -285,6 +285,7 @@ void Client::registerLuaFunctions()
g_lua.bindClassMemberFunction<Thing>("getId", &Thing::getId);
g_lua.bindClassMemberFunction<Thing>("getPosition", &Thing::getPosition);
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>("getTile", &Thing::getTile);
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>("getThings", &Tile::getThings);
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>("getTopThing", &Tile::getTopThing);
g_lua.bindClassMemberFunction<Tile>("removeThing", &Tile::removeThing);

View File

@ -28,6 +28,8 @@
#include <framework/const.h>
#include <framework/util/point.h>
#include <vector>
class Position
{
public:
@ -122,6 +124,22 @@ public:
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 {
int dx = position.x - x;
int dy = position.y - y;

View File

@ -65,7 +65,7 @@ public:
void sendAcceptTrade();
void sendRejectTrade();
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 sendRotateItem(const Position& pos, int thingId, int stackpos);
void sendCloseContainer(int containerId);

View File

@ -553,7 +553,7 @@ void ProtocolGame::parseTileTransformThing(const InputMessagePtr& msg)
}
Position pos = thing->getPosition();
int stackpos = thing->getStackpos();
int stackpos = thing->getStackPos();
if(!g_map.removeThing(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);
}
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);
msg->addU8(Proto::ClientUseItemWith);
addPosition(msg, fromPos);
msg->addU16(itemId);
msg->addU8(fromStackpos);
msg->addU8(fromStackPos);
addPosition(msg, toPos);
msg->addU16(toThingId);
msg->addU8(toStackpos);
msg->addU8(toStackPos);
send(msg);
}

View File

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

View File

@ -46,7 +46,7 @@ public:
int getStackPriority();
const TilePtr& getTile();
ContainerPtr getParentContainer();
int getStackpos();
int getStackPos();
virtual bool isItem() { 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();
}
int Tile::getThingStackpos(const ThingPtr& thing)
int Tile::getThingStackPos(const ThingPtr& thing)
{
for(uint stackpos = 0; stackpos < m_things.size(); ++stackpos)
if(thing == m_things[stackpos])

View File

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