From 606fc381091c7cede3d7ebcd82ef08dd45429799 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Wed, 9 May 2012 19:19:05 -0300 Subject: [PATCH] fixes and missing file * fix walking on tile that has too many creatures * add missing file * some walk rework --- BUGS | 10 +++ src/otclient/core/creature.cpp | 4 + src/otclient/core/game.cpp | 6 +- src/otclient/core/map.cpp | 31 +++++-- src/otclient/core/thingtype.cpp | 110 +++++++++++++++++++++++++ src/otclient/core/tile.cpp | 5 ++ src/otclient/core/tile.h | 1 + src/otclient/net/protocolgameparse.cpp | 3 +- 8 files changed, 158 insertions(+), 12 deletions(-) create mode 100644 src/otclient/core/thingtype.cpp diff --git a/BUGS b/BUGS index 7a9ef712..e23f83c3 100644 --- a/BUGS +++ b/BUGS @@ -5,9 +5,19 @@ modules recursivity makes client crash, it should generate a warning sometimes minimap desync Z pos follow and autowalk doesn't cancel when walking via hotkeys +when walking on a tile with too many creatures, the following errors occurrs: +ERROR: [ProtocolGame::parseCreatureHealth] could not get greature +ERROR: [ProtocolGame::parseCreatureHealth] could not get greature +ERROR: [Map::setCentralPosition] invalid creature +ERROR: [Map::setCentralPosition] invalid creature +ERROR: [Map::setCentralPosition] invalid creature +ERROR: [Map::setCentralPosition] invalid creature + + == P2 BUGS battle sometimes doesn't clear attacked/followed creatures when they go out of range when looking from floor 5 in floor 7, sometimes a tile have 2 invisible grounds in floor 6 that should be ignored +invisible creatures name offset is incorrect == P3 BUGS widgets may have been destroyed when adding event in onSetup (UIResizeBorder), generating invalid events diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index ae32a552..441ba93e 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -290,6 +290,9 @@ void Creature::turn(Otc::Direction direction) void Creature::walk(const Position& oldPos, const Position& newPos) { + if(oldPos == newPos) + return; + // get walk direction Otc::Direction direction = oldPos.getDirectionFromPosition(newPos); @@ -492,6 +495,7 @@ void Creature::setHealthPercent(uint8 healthPercent) void Creature::setDirection(Otc::Direction direction) { + assert(direction != Otc::InvalidDirection); m_direction = direction; } diff --git a/src/otclient/core/game.cpp b/src/otclient/core/game.cpp index dd29eb7d..3b44d317 100644 --- a/src/otclient/core/game.cpp +++ b/src/otclient/core/game.cpp @@ -279,8 +279,7 @@ void Game::processInventoryChange(int slot, const ItemPtr& item) void Game::processCreatureMove(const CreaturePtr& creature, const Position& oldPos, const Position& newPos) { // animate walk - if(oldPos.isInRange(newPos, 1, 1)) - creature->walk(oldPos, newPos); + creature->walk(oldPos, newPos); } void Game::processCreatureTeleport(const CreaturePtr& creature) @@ -480,8 +479,9 @@ void Game::walk(Otc::Direction direction) return; // only do prewalks to walkable tiles + TilePtr fromTile = m_localPlayer->getTile(); TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction)); - if(toTile && toTile->isWalkable()) + if(toTile && toTile->isWalkable()/* && fromTile && fromTile->hasThing(m_localPlayer)*/) m_localPlayer->preWalk(direction); else m_localPlayer->lockWalk(); diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index 1dd28a81..779bb9c7 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -132,15 +132,10 @@ void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos) if(!thing) return; + Position oldPos = thing->getPosition(); TilePtr tile = getOrCreateTile(pos); - if(CreaturePtr creature = thing->asCreature()) { - Position oldPos = thing->getPosition(); - tile->addThing(thing, stackPos); - - if(oldPos.isValid() && !oldPos.isInRange(pos,1,1)) - g_game.processCreatureTeleport(creature); - } else if(MissilePtr missile = thing->asMissile()) { + if(MissilePtr missile = thing->asMissile()) { m_floorMissiles[pos.z].push_back(missile); } else if(AnimatedTextPtr animatedText = thing->asAnimatedText()) { m_animatedTexts.push_back(animatedText); @@ -169,6 +164,15 @@ void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos) thing->startAnimation(); thing->setPosition(pos); + if(CreaturePtr creature = thing->asCreature()) { + if(oldPos != pos) { + if(oldPos.isInRange(pos,1,1)) + g_game.processCreatureMove(creature, oldPos, pos); + else + g_game.processCreatureTeleport(creature); + } + } + notificateTileUpdateToMapViews(pos); } @@ -291,6 +295,19 @@ void Map::setCentralPosition(const Position& centralPosition) else logTraceError("invalid creature"); } + + // this fixes local player position when the local player is removed fro the map, + // the local player is removed from the map when there are too many creatures on his tile + // so there is not enough stackpos to the server send him + g_eventDispatcher.addEvent([this] { + LocalPlayerPtr localPlayer = g_game.getLocalPlayer(); + if(!localPlayer || localPlayer->getPosition() == m_centralPosition) + return; + TilePtr tile = getTile(localPlayer->getPosition()); + if(!tile || tile->hasThing(localPlayer)) + return; + localPlayer->setPosition(m_centralPosition); + }); } std::vector Map::getSpectators(const Position& centerPos, bool multiFloor) diff --git a/src/otclient/core/thingtype.cpp b/src/otclient/core/thingtype.cpp new file mode 100644 index 00000000..22a1cb72 --- /dev/null +++ b/src/otclient/core/thingtype.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "thingtype.h" +#include "spritemanager.h" + +#include +#include +#include + +ThingType::ThingType() +{ + m_dimensions.fill(0); + m_parameters.fill(0); + m_properties.fill(false); +} + +void ThingType::draw(const Point& dest, float scaleFactor, int w, int h, int xPattern, int yPattern, int zPattern, int layer, int animationPhase) +{ + int scaledSize = Otc::TILE_PIXELS * scaleFactor; + + Point displacement(m_parameters[DisplacementX], m_parameters[DisplacementY]); + + Rect drawRect(dest - displacement*scaleFactor, Size(scaledSize, scaledSize)); + g_painter->setColor(Color::white); + g_painter->drawTexturedRect(drawRect, getSprite(w, h, layer, xPattern, yPattern, zPattern, animationPhase)); +} + +void ThingType::draw(const Point& dest, float scaleFactor, int xPattern, int yPattern, int zPattern, int animationPhase) +{ + for(int l = 0; l < m_dimensions[Layers]; ++l) + for(int w = 0; w < m_dimensions[Width]; ++w) + for(int h = 0; h < m_dimensions[Height]; ++h) + draw(dest - Point(w,h)*Otc::TILE_PIXELS*scaleFactor, scaleFactor, w, h, xPattern, yPattern, zPattern, l, animationPhase); +} + +void ThingType::drawMask(const Point& dest, float scaleFactor, int w, int h, int xPattern, int yPattern, int zPattern, int layer, int animationPhase, ThingType::SpriteMask mask) +{ + int scaledSize = Otc::TILE_PIXELS * scaleFactor; + + Point displacement(m_parameters[DisplacementX], m_parameters[DisplacementY]); + + Rect drawRect(dest - displacement*scaleFactor, Size(scaledSize, scaledSize)); + g_painter->drawTexturedRect(drawRect, getSpriteMask(w, h, layer, xPattern, yPattern, zPattern, animationPhase, mask)); +} + +TexturePtr& ThingType::getSprite(int w, int h, int l, int x, int y, int z, int a) +{ + uint index = getSpriteIndex(w,h,l,x,y,z,a); + TexturePtr& spriteTexture = m_sprites[index]; + if(!spriteTexture) { + ImagePtr spriteImage = g_sprites.getSpriteImage(m_spritesIndex[index]); + if(!spriteImage) + spriteTexture = g_graphics.getEmptyTexture(); + else { + spriteTexture = TexturePtr(new Texture(spriteImage)); + spriteTexture->setSmooth(true); + + if(g_graphics.canUseMipmaps()) + spriteTexture->generateSoftwareMipmaps(spriteImage->getPixels()); + } + } + + return spriteTexture; +} + +TexturePtr& ThingType::getSpriteMask(int w, int h, int l, int x, int y, int z, int a, ThingType::SpriteMask mask) +{ + if(m_spritesMask.size() == 0) + m_spritesMask.resize(m_spritesIndex.size()); + + uint index = getSpriteIndex(w,h,l,x,y,z,a); + TexturePtr& maskTexture = m_spritesMask[index][mask]; + if(!maskTexture) { + ImagePtr maskImage = g_sprites.getSpriteImage(m_spritesIndex[index]); + if(!maskImage) + maskTexture = g_graphics.getEmptyTexture(); + else { + static Color maskColors[LastMask] = { Color::yellow, Color::red, Color::green, Color::blue }; + maskImage->overwriteMask(maskColors[mask]); + + maskTexture = TexturePtr(new Texture(maskImage)); + maskTexture->setSmooth(true); + + if(g_graphics.canUseMipmaps()) + maskTexture->generateSoftwareMipmaps(maskImage->getPixels()); + } + } + + return maskTexture; +} diff --git a/src/otclient/core/tile.cpp b/src/otclient/core/tile.cpp index 134be456..cec4d8be 100644 --- a/src/otclient/core/tile.cpp +++ b/src/otclient/core/tile.cpp @@ -221,6 +221,11 @@ ThingPtr Tile::getThing(int stackPos) return nullptr; } +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) { for(uint stackpos = 0; stackpos < m_things.size(); ++stackpos) diff --git a/src/otclient/core/tile.h b/src/otclient/core/tile.h index 2720fbc6..920ed526 100644 --- a/src/otclient/core/tile.h +++ b/src/otclient/core/tile.h @@ -42,6 +42,7 @@ public: ThingPtr addThing(const ThingPtr& thing, int stackPos = -1); bool removeThing(ThingPtr thing); ThingPtr getThing(int stackPos); + bool hasThing(const ThingPtr& thing); int getThingStackpos(const ThingPtr& thing); ThingPtr getTopThing(); diff --git a/src/otclient/net/protocolgameparse.cpp b/src/otclient/net/protocolgameparse.cpp index cf51fe94..1180492a 100644 --- a/src/otclient/net/protocolgameparse.cpp +++ b/src/otclient/net/protocolgameparse.cpp @@ -446,7 +446,7 @@ void ProtocolGame::parseCreatureMove(InputMessage& msg) logTraceError("could not remove thing"); g_map.addThing(thing, newPos); - g_game.processCreatureMove(creature, oldPos, newPos); + //g_game.processCreatureMove(creature, oldPos, newPos); } void ProtocolGame::parseOpenContainer(InputMessage& msg) @@ -1269,7 +1269,6 @@ ThingPtr ProtocolGame::internalGetThing(InputMessage& msg) if(emblem != -1) creature->setEmblem(emblem); creature->setPassable(passable); - creature->setDirection(direction); // now that the local player is known, we can schedule login event if(creature == m_localPlayer && !m_localPlayer->isKnown()) {