diff --git a/CMakeLists.txt b/CMakeLists.txt index bb562fe3..29ff9feb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ SET(SOURCES src/otclient/core/thing.cpp src/otclient/core/creature.cpp src/otclient/core/effect.cpp + src/otclient/core/missile.cpp src/otclient/core/localplayer.cpp # otclient ui diff --git a/src/framework/util/point.h b/src/framework/util/point.h index 9d1be34f..0b3f87d6 100644 --- a/src/framework/util/point.h +++ b/src/framework/util/point.h @@ -34,27 +34,32 @@ template class TPoint { public: - TPoint() : x(0), y(0) {}; - TPoint(T x, T y) : x(x), y(y) { }; - TPoint(const TPoint& other) : x(other.x), y(other.y) { }; + TPoint() : x(0), y(0) {} + TPoint(T x, T y) : x(x), y(y) { } + TPoint(const TPoint& other) : x(other.x), y(other.y) { } bool isNull() const { return x==0 && y==0; } TSize toSize() const { return TSize(x, y); } TPoint operator-() const { return TPoint(-x, -y); } - TPoint operator+(const TPoint& other) const { return TPoint(x + other.x, y + other.y); } + TPoint operator+(const TPoint& other) const { return TPoint(x + other.x, y + other.y); } TPoint& operator+=(const TPoint& other) { x+=other.x; y+=other.y; return *this; } - TPoint operator-(const TPoint& other) const { return TPoint(x - other.x, y - other.y); } + TPoint operator-(const TPoint& other) const { return TPoint(x - other.x, y - other.y); } TPoint& operator-=(const TPoint& other) { x-=other.x; y-=other.y; return *this; } - TPoint operator*(const TPoint& other) const { return TPoint(x * other.x, y * other.y); } + TPoint operator*(const TPoint& other) const { return TPoint(x * other.x, y * other.y); } TPoint& operator*=(const TPoint& other) { x*=other.x; y*=other.y; return *this; } TPoint operator*(const T v) const { return TPoint(x * v, y * v); } TPoint& operator*=(const T v) { x*=v; y*=v; return *this; } - TPoint operator/(const TPoint& other) const { return TPoint(x/other.x, y/other.y); } + TPoint operator/(const TPoint& other) const { return TPoint(x/other.x, y/other.y); } TPoint& operator/=(const TPoint& other) { x/=other.x; y/=other.y; return *this; } - TPoint operator/(const T v) const { return TPoint(x/v, y/v); } + TPoint operator/(const T v) const { return TPoint(x/v, y/v); } TPoint& operator/=(const T v) { x/=v; y/=v; return *this; } + TPoint operator+(T other) const { return TPoint(x + other, y + other); } + TPoint& operator+=(T other) { x+=other; y+=other; return *this; } + TPoint operator-(T other) const { return TPoint(x - other, y - other); } + TPoint& operator-=(T other) { x-=other; y-=other; return *this; } + bool operator<=(const TPoint&other) const { return x<=other.x && y<=other.y; } bool operator>=(const TPoint&other) const { return x>=other.x && y>=other.y; } bool operator<(const TPoint&other) const { return x 1) { @@ -70,19 +63,19 @@ void Creature::draw(int x, int y) // head g_graphics.bindColor(Otc::OutfitColors[m_outfit.head]); - internalDraw(x, y, 1, Otc::SpriteYellowMask); + internalDraw(p + m_walkOffset, 1, Otc::SpriteYellowMask); // body g_graphics.bindColor(Otc::OutfitColors[m_outfit.body]); - internalDraw(x, y, 1, Otc::SpriteRedMask); + internalDraw(p + m_walkOffset, 1, Otc::SpriteRedMask); // legs g_graphics.bindColor(Otc::OutfitColors[m_outfit.legs]); - internalDraw(x, y, 1, Otc::SpriteGreenMask); + internalDraw(p + m_walkOffset, 1, Otc::SpriteGreenMask); // feet g_graphics.bindColor(Otc::OutfitColors[m_outfit.feet]); - internalDraw(x, y, 1, Otc::SpriteBlueMask); + internalDraw(p + m_walkOffset, 1, Otc::SpriteBlueMask); // restore default blend func g_graphics.bindBlendFunc(Fw::BlendDefault); @@ -137,55 +130,55 @@ void Creature::walk(const Position& position, bool inverse) // set new direction if(m_position + Position(0, -1, 0) == position) { setDirection(Otc::North); - m_walkOffsetY = 32; + m_walkOffset.y = 32; } else if(m_position + Position(1, 0, 0) == position) { setDirection(Otc::East); - m_walkOffsetX = -32; + m_walkOffset.x = -32; } else if(m_position + Position(0, 1, 0) == position) { setDirection(Otc::South); - m_walkOffsetY = -32; + m_walkOffset.y = -32; } else if(m_position + Position(-1, 0, 0) == position) { setDirection(Otc::West); - m_walkOffsetX = 32; + m_walkOffset.x = 32; } else if(m_position + Position(1, -1, 0) == position) { setDirection(Otc::NorthEast); - m_walkOffsetX = -32; - m_walkOffsetY = 32; + m_walkOffset.x = -32; + m_walkOffset.y = 32; walkTimeFactor = 2; } else if(m_position + Position(1, 1, 0) == position) { setDirection(Otc::SouthEast); - m_walkOffsetX = -32; - m_walkOffsetY = -32; + m_walkOffset.x = -32; + m_walkOffset.y = -32; walkTimeFactor = 2; } else if(m_position + Position(-1, 1, 0) == position) { setDirection(Otc::SouthWest); - m_walkOffsetX = 32; - m_walkOffsetY = -32; + m_walkOffset.x = 32; + m_walkOffset.y = -32; walkTimeFactor = 2; } else if(m_position + Position(-1, -1, 0) == position) { setDirection(Otc::NorthWest); - m_walkOffsetX = 32; - m_walkOffsetY = 32; + m_walkOffset.x = 32; + m_walkOffset.y = 32; walkTimeFactor = 2; } else { // Teleport // we teleported, dont walk or change direction m_walking = false; - m_walkOffsetX = 0; - m_walkOffsetY = 0; + m_walkOffset.x = 0; + m_walkOffset.y = 0; m_animation = 0; } if(!m_inverseWalking) { - m_walkOffsetX = 0; - m_walkOffsetY = 0; + m_walkOffset.x = 0; + m_walkOffset.y = 0; } if(m_walking) { @@ -215,28 +208,28 @@ void Creature::updateWalk() if(m_inverseWalking) { if(m_direction == Otc::North || m_direction == Otc::NorthEast || m_direction == Otc::NorthWest) - m_walkOffsetY = 32 - totalPixelsWalked; + m_walkOffset.y = 32 - totalPixelsWalked; else if(m_direction == Otc::South || m_direction == Otc::SouthEast || m_direction == Otc::SouthWest) - m_walkOffsetY = totalPixelsWalked - 32; + m_walkOffset.y = totalPixelsWalked - 32; if(m_direction == Otc::East || m_direction == Otc::NorthEast || m_direction == Otc::SouthEast) - m_walkOffsetX = totalPixelsWalked - 32; + m_walkOffset.x = totalPixelsWalked - 32; else if(m_direction == Otc::West || m_direction == Otc::NorthWest || m_direction == Otc::SouthWest) - m_walkOffsetX = 32 - totalPixelsWalked; + m_walkOffset.x = 32 - totalPixelsWalked; - if(m_walkOffsetX == 0 && m_walkOffsetY == 0) + if(m_walkOffset.x == 0 && m_walkOffset.y == 0) cancelWalk(m_direction); } else { if(m_direction == Otc::North || m_direction == Otc::NorthEast || m_direction == Otc::NorthWest) - m_walkOffsetY = -totalPixelsWalked; + m_walkOffset.y = -totalPixelsWalked; else if(m_direction == Otc::South || m_direction == Otc::SouthEast || m_direction == Otc::SouthWest) - m_walkOffsetY = totalPixelsWalked; + m_walkOffset.y = totalPixelsWalked; if(m_direction == Otc::East || m_direction == Otc::NorthEast || m_direction == Otc::SouthEast) - m_walkOffsetX = totalPixelsWalked; + m_walkOffset.x = totalPixelsWalked; else if(m_direction == Otc::West || m_direction == Otc::NorthWest || m_direction == Otc::SouthWest) - m_walkOffsetX = -totalPixelsWalked; + m_walkOffset.x = -totalPixelsWalked; } int totalWalkTileTicks = (int)m_walkTimePerPixel*32 * 0.5; @@ -252,8 +245,8 @@ void Creature::cancelWalk(Otc::Direction direction) { m_walking = false; m_walkStartTicks = 0; - m_walkOffsetX = 0; - m_walkOffsetY = 0; + m_walkOffset.x = 0; + m_walkOffset.y = 0; m_direction = direction; auto self = asCreature(); diff --git a/src/otclient/core/creature.h b/src/otclient/core/creature.h index 807ed29b..171b4335 100644 --- a/src/otclient/core/creature.h +++ b/src/otclient/core/creature.h @@ -42,7 +42,7 @@ public: Creature(); virtual ~Creature() { } - virtual void draw(int x, int y); + virtual void draw(const Point& p); void drawInformation(int x, int y, bool useGray, const Rect& rect); void setName(const std::string& name) { m_name = name; } @@ -73,8 +73,7 @@ public: virtual void walk(const Position& position, bool inverse = true); virtual void cancelWalk(Otc::Direction direction); - int getWalkOffsetX() { return m_walkOffsetX; } - int getWalkOffsetY() { return m_walkOffsetY; } + Point getWalkOffset() { return m_walkOffset; } bool isWalking() { return m_walking; } @@ -101,7 +100,7 @@ protected: bool m_walking, m_inverseWalking; float m_walkTimePerPixel; Position m_walkingFromPosition; - int m_walkOffsetX, m_walkOffsetY; + Point m_walkOffset; }; #endif diff --git a/src/otclient/core/declarations.h b/src/otclient/core/declarations.h index f3779d3d..d5e97a88 100644 --- a/src/otclient/core/declarations.h +++ b/src/otclient/core/declarations.h @@ -30,6 +30,7 @@ class Thing; class Item; class Creature; class Effect; +class Missile; class Player; class LocalPlayer; @@ -38,6 +39,7 @@ typedef std::shared_ptr ThingPtr; typedef std::shared_ptr ItemPtr; typedef std::shared_ptr CreaturePtr; typedef std::shared_ptr EffectPtr; +typedef std::shared_ptr MissilePtr; typedef std::shared_ptr PlayerPtr; typedef std::shared_ptr LocalPlayerPtr; diff --git a/src/otclient/core/effect.cpp b/src/otclient/core/effect.cpp index 6f810edd..b37a5e2b 100644 --- a/src/otclient/core/effect.cpp +++ b/src/otclient/core/effect.cpp @@ -32,13 +32,13 @@ Effect::Effect() : Thing() m_animationStartTicks = 0; } -void Effect::draw(int x, int y) +void Effect::draw(const Point& p) { int animationPhase = (g_platform.getTicks() - m_animationStartTicks) / TICKS_PER_FRAME; if(animationPhase < getAnimationPhases()) { m_animation = animationPhase; - internalDraw(x, y, 0); + internalDraw(p, 0); } } diff --git a/src/otclient/core/effect.h b/src/otclient/core/effect.h index 914575dc..0e2d2281 100644 --- a/src/otclient/core/effect.h +++ b/src/otclient/core/effect.h @@ -35,7 +35,7 @@ class Effect : public Thing public: Effect(); - void draw(int x, int y); + void draw(const Point& p); void startAnimation(); void updateAnimation(); diff --git a/src/otclient/core/item.cpp b/src/otclient/core/item.cpp index 9bbe903b..7d566d80 100644 --- a/src/otclient/core/item.cpp +++ b/src/otclient/core/item.cpp @@ -28,31 +28,26 @@ Item::Item() : Thing() { - m_count = 0; + m_data = 0; m_lastTicks = g_platform.getTicks(); } -void Item::draw(int x, int y) +void Item::draw(const Point& p) { const ThingType& type = g_thingsType.getItemType(m_id); if(type.animationPhases > 1) m_animation = (g_platform.getTicks() % (TICKS_PER_FRAME * type.animationPhases)) / TICKS_PER_FRAME; - /*if(type.group == Otc::ThingSplashGroup || type.group == Otc::ThingFluidGroup) { - //xPattern = m_count % type.xPattern; - //yPattern = m_count / type.yPattern; - }*/ - for(int b = 0; b < type.layers; b++) - internalDraw(x, y, b); + internalDraw(p, b); } -void Item::setCount(int count) +void Item::setData(int count) { - int oldCount = m_count; - m_count = count; - onCountChange(oldCount); + int oldData = m_data; + m_data = count; + onDataChange(oldData); } const ThingType& Item::getType() @@ -71,30 +66,104 @@ void Item::onPositionChange(const Position&) } } -void Item::onCountChange(int) +void Item::onDataChange(int) { const ThingType& type = g_thingsType.getItemType(m_id); if(type.isStackable && type.xPattern == 4 && type.yPattern == 2) { - if(m_count < 5) { - m_xPattern = m_count-1; + if(m_data < 5) { + m_xPattern = m_data-1; m_yPattern = 0; } - else if(m_count < 10) { + else if(m_data < 10) { m_xPattern = 0; m_yPattern = 1; } - else if(m_count < 25) { + else if(m_data < 25) { m_xPattern = 1; m_yPattern = 1; } - else if(m_count < 50) { + else if(m_data < 50) { m_xPattern = 2; m_yPattern = 1; } - else if(m_count <= 100) { + else if(m_data <= 100) { m_xPattern = 3; m_yPattern = 1; } } + else if(type.isHangable) { + if(type.isHookSouth) { + m_xPattern = type.xPattern >= 2 ? 1 : 0; + } + else if(type.isHookEast) { + m_xPattern = type.xPattern >= 3 ? 2 : 0; + } + } + else if(type.isSplash || type.isFluidContainer) { + int var = 0; + // TODO: find out what the heck does it mean + switch(m_data) { + case 0: + var = 0; + break; + case 1: + var = 1; + break; + case 2: + var = 7; + break; + case 3: + var = 3; + break; + case 4: + var = 3; + break; + case 5: + var = 2; + break; + case 6: + var = 4; + break; + case 7: + var = 3; + break; + case 8: + var = 5; + break; + case 9: + var = 6; + break; + case 10: + var = 7; + break; + case 11: + var = 2; + break; + case 12: + var = 5; + break; + case 13: + var = 3; + break; + case 14: + var = 5; + break; + case 15: + var = 6; + break; + case 16: + var = 3; + break; + case 17: + var = 3; + break; + default: + var = 1; + break; + } + + m_xPattern = (var & 3) % type.xPattern; + m_yPattern = (var >> 2) % type.yPattern; + } } diff --git a/src/otclient/core/item.h b/src/otclient/core/item.h index c27e8cda..480bc619 100644 --- a/src/otclient/core/item.h +++ b/src/otclient/core/item.h @@ -35,20 +35,20 @@ public: TICKS_PER_FRAME = 500 }; - void draw(int x, int y); + void draw(const Point& p); - void setCount(int count); + void setData(int count); - int getCount() { return m_count; } + int getData() { return m_data; } const ThingType& getType(); void onPositionChange(const Position&); - void onCountChange(int); + void onDataChange(int); ItemPtr asItem() { return std::static_pointer_cast(shared_from_this()); } private: - int m_count; + int m_data; int m_lastTicks; }; diff --git a/src/otclient/core/localplayer.cpp b/src/otclient/core/localplayer.cpp index 50f29ac1..52aa1e52 100644 --- a/src/otclient/core/localplayer.cpp +++ b/src/otclient/core/localplayer.cpp @@ -43,18 +43,17 @@ void LocalPlayer::walk(const Position& position, bool inverse) { if(m_clientWalking) { Position pos = Position::getPositionFromDirection(m_direction); - int walkOffsetX = m_walkOffsetX - pos.x * 32; - int walkOffsetY = m_walkOffsetY - pos.y * 32; + Point walkOffset = Point(m_walkOffset.x - pos.x * 32, + m_walkOffset.y - pos.y * 32); Creature::walk(position, inverse); - m_walkOffsetX = walkOffsetX; - m_walkOffsetY = walkOffsetY; + m_walkOffset = walkOffset; m_clientWalking = false; } else { - m_walkOffsetX = 0; - m_walkOffsetY = 0; + m_walkOffset.x = 0; + m_walkOffset.y = 0; Creature::walk(position, inverse); } } diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index 63f56a37..efaa35a8 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -25,6 +25,7 @@ #include "localplayer.h" #include "tile.h" #include "item.h" +#include "missile.h" #include #include @@ -40,8 +41,7 @@ void Map::draw(const Rect& rect) // draw offsets LocalPlayerPtr localPlayer = g_game.getLocalPlayer(); - int walkOffsetX = localPlayer->getWalkOffsetX(); - int walkOffsetY = localPlayer->getWalkOffsetY(); + Point walkOffset = localPlayer->getWalkOffset(); //TODO: cache first/last visible floor // draw from bottom floors to top floors @@ -62,10 +62,16 @@ void Map::draw(const Rect& rect) // skip tiles that are behind another tile //if(isCompletlyCovered(tilePos, firstFloor)) // continue; - tile->draw(tilePos.to2D(m_centralPosition) - Point(walkOffsetX, walkOffsetY)); + tile->draw(tilePos.to2D(m_centralPosition) - walkOffset); } } } + + // after drawing all tiles, draw shots + for(const MissilePtr& shot : m_missilesAtFloor[iz]) { + Position missilePos = shot->getPosition(); + shot->draw(missilePos.to2D(m_centralPosition) - walkOffset); + } } m_framebuffer->unbind(); @@ -89,15 +95,14 @@ void Map::draw(const Rect& rect) continue; for(const CreaturePtr& creature : creatures) { - int x = (7 + (tilePos.x - m_centralPosition.x))*NUM_TILE_PIXELS + 10 - tile->getDrawElevation(); - int y = (5 + (tilePos.y - m_centralPosition.y))*NUM_TILE_PIXELS - 10 - tile->getDrawElevation(); + Point p((7 + (tilePos.x - m_centralPosition.x))*NUM_TILE_PIXELS + 10 - tile->getDrawElevation(), + (5 + (tilePos.y - m_centralPosition.y))*NUM_TILE_PIXELS - 10 - tile->getDrawElevation()); if(creature != localPlayer) { - x += creature->getWalkOffsetX() - walkOffsetX; - y += creature->getWalkOffsetY() - walkOffsetY; + p += creature->getWalkOffset() - walkOffset; } - creature->drawInformation(rect.x() + x*horizontalStretchFactor, rect.y() + y*verticalStretchFactor, isCovered(tilePos, firstFloor), rect); + creature->drawInformation(rect.x() + p.x*horizontalStretchFactor, rect.y() + p.y*verticalStretchFactor, isCovered(tilePos, firstFloor), rect); } } } @@ -196,6 +201,11 @@ void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos) if(!thing) return; + if(MissilePtr shot = thing->asMissile()) { + m_missilesAtFloor[shot->getPosition().z].push_back(shot); + return; + } + TilePtr tile = getTile(pos); tile->addThing(thing, stackPos); @@ -221,6 +231,17 @@ void Map::removeThing(const ThingPtr& thing) if(!thing) return; + if(MissilePtr shot = thing->asMissile()) { + m_missilesAtFloor[shot->getPosition().z]; + for(auto it = m_missilesAtFloor[shot->getPosition().z].begin(), end = m_missilesAtFloor[shot->getPosition().z].end(); it != end; ++it) { + if(shot == *it) { + m_missilesAtFloor[shot->getPosition().z].erase(it); + break; + } + } + return; + } + if(TilePtr& tile = m_tiles[thing->getPosition()]) tile->removeThing(thing); } diff --git a/src/otclient/core/map.h b/src/otclient/core/map.h index dbc027ae..49712329 100644 --- a/src/otclient/core/map.h +++ b/src/otclient/core/map.h @@ -69,6 +69,7 @@ public: private: std::unordered_map m_tiles; std::map m_creatures; + std::map > m_missilesAtFloor; Light m_light; Position m_centralPosition; diff --git a/src/otclient/core/missile.cpp b/src/otclient/core/missile.cpp new file mode 100644 index 00000000..db0298f9 --- /dev/null +++ b/src/otclient/core/missile.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2010-2011 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 "missile.h" +#include "thingstype.h" +#include "map.h" +#include "tile.h" +#include +#include + +Missile::Missile() : Thing() +{ + m_startTicks = 0; +} + +void Missile::draw(const Point& p) +{ + float time = (g_platform.getTicks() - m_startTicks) / m_duration; + internalDraw(p + Point(m_positionDelta.x * time, m_positionDelta.y * time), 0); +} + +void Missile::setPath(const Position& fromPosition, const Position& toPosition) +{ + m_position = fromPosition; + m_positionDelta = toPosition - fromPosition; + + if(m_positionDelta.x == 0 && m_positionDelta.y == 0) { + m_xPattern = 1; + m_yPattern = 1; + } + else if(m_positionDelta.x == 0) { + m_xPattern = 1; + if(m_positionDelta.y < 0) { + m_yPattern = 0; + } + else if(m_positionDelta.y > 0) { + m_yPattern = 2; + } + } + else if(m_positionDelta.y == 0) { + m_yPattern = 1; + if(m_positionDelta.x < 0) { + m_xPattern = 0; + } + else if(m_positionDelta.x > 0) { + m_xPattern = 2; + } + } + else { + float angle = std::atan2(m_positionDelta.y * -1, m_positionDelta.x) * 180.0 / 3.141592; + if(angle < 0) + angle += 360; + + if(angle >= 360 - 22.5 || angle < 0 + 22.5) { + m_xPattern = 2; + m_yPattern = 1; + } + else if(angle >= 45 - 22.5 && angle < 45 + 22.5) { + m_xPattern = 2; + m_yPattern = 0; + } + else if(angle >= 90 - 22.5 && angle < 90 + 22.5) { + m_xPattern = 1; + m_yPattern = 0; + } + else if(angle >= 135 - 22.5 && angle < 135 + 22.5) { + m_xPattern = 0; + m_yPattern = 0; + } + else if(angle >= 180 - 22.5 && angle < 180 + 22.5) { + m_xPattern = 0; + m_yPattern = 1; + } + else if(angle >= 225 - 22.5 && angle < 225 + 22.5) { + m_xPattern = 0; + m_yPattern = 2; + } + else if(angle >= 270 - 22.5 && angle < 270 + 22.5) { + m_xPattern = 1; + m_yPattern = 2; + } + else if(angle >= 315 - 22.5 && angle < 315 + 22.5) { + m_xPattern = 2; + m_yPattern = 2; + } + } + + m_duration = 150 * std::sqrt(Point(m_positionDelta.x, m_positionDelta.y).length()); + m_positionDelta.x *= 32; + m_positionDelta.y *= 32; + + m_startTicks = g_platform.getTicks(); + + // schedule removal + auto self = asMissile(); + g_dispatcher.scheduleEvent([self]() { + g_map.removeThing(self); + }, m_duration); +} + +const ThingType& Missile::getType() +{ + return g_thingsType.getShotType(m_id); +} diff --git a/src/otclient/core/missile.h b/src/otclient/core/missile.h new file mode 100644 index 00000000..f1a1f03e --- /dev/null +++ b/src/otclient/core/missile.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010-2011 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. + */ + +#ifndef SHOT_H +#define SHOT_H + +#include +#include "thing.h" + +class Missile : public Thing +{ + enum { + TICKS_PER_FRAME = 75 + }; + +public: + Missile(); + + void draw(const Point& p); + + void updateAnimation(); + + void setPath(const Position& fromPosition, const Position& toPosition); + + const ThingType& getType(); + + MissilePtr asMissile() { return std::static_pointer_cast(shared_from_this()); } + +private: + int m_startTicks; + Position m_positionDelta; + float m_duration; +}; + +#endif diff --git a/src/otclient/core/thing.cpp b/src/otclient/core/thing.cpp index 6138cb9d..fd5f7760 100644 --- a/src/otclient/core/thing.cpp +++ b/src/otclient/core/thing.cpp @@ -48,7 +48,7 @@ void Thing::setPosition(const Position& position) onPositionChange(oldPosition); } -void Thing::internalDraw(int x, int y, int layers, Otc::SpriteMask mask) +void Thing::internalDraw(const Point& p, int layers, Otc::SpriteMask mask) { const ThingType& type = getType(); @@ -68,8 +68,8 @@ void Thing::internalDraw(int x, int y, int layers, Otc::SpriteMask mask) TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId, mask); - Rect drawRect((x - xi*32) - type.xDisplacement, - (y - yi*32) - type.yDisplacement, + Rect drawRect((p.x - xi*32) - type.xDisplacement, + (p.y - yi*32) - type.yDisplacement, 32, 32); g_graphics.drawTexturedRect(drawRect, spriteTex); } diff --git a/src/otclient/core/thing.h b/src/otclient/core/thing.h index 889fe167..9741dc38 100644 --- a/src/otclient/core/thing.h +++ b/src/otclient/core/thing.h @@ -39,7 +39,7 @@ public: Thing(); virtual ~Thing() { } - virtual void draw(int x, int y) = 0; + virtual void draw(const Point& p) = 0; void setId(uint32 id); void setPosition(const Position& position); @@ -57,11 +57,12 @@ public: virtual ItemPtr asItem() { return nullptr; } virtual CreaturePtr asCreature() { return nullptr; } virtual EffectPtr asEffect() { return nullptr; } + virtual MissilePtr asMissile() { return nullptr; } virtual PlayerPtr asPlayer() { return nullptr; } virtual LocalPlayerPtr asLocalPlayer() { return nullptr; } protected: - void internalDraw(int x, int y, int layers, Otc::SpriteMask mask = Otc::SpriteNoMask); + void internalDraw(const Point& p, int layers, Otc::SpriteMask mask = Otc::SpriteNoMask); uint32 m_id; Position m_position; diff --git a/src/otclient/core/tile.cpp b/src/otclient/core/tile.cpp index 2c08eb8a..32353b8a 100644 --- a/src/otclient/core/tile.cpp +++ b/src/otclient/core/tile.cpp @@ -44,7 +44,7 @@ void Tile::draw(const Point& p) const ThingType& type = thing->getType(); if(!type.isGround && !type.isGroundClip && !type.isOnBottom) break; - thing->draw(p.x - m_drawElevation, p.y - m_drawElevation); + thing->draw(p - m_drawElevation); m_drawElevation += type.elevation; if(m_drawElevation > MAX_DRAW_ELEVATION) m_drawElevation = MAX_DRAW_ELEVATION; @@ -56,7 +56,7 @@ void Tile::draw(const Point& p) const ThingType& type = thing->getType(); if(thing->asCreature() || type.isOnTop || type.isOnBottom || type.isGroundClip || type.isGround) break; - thing->draw(p.x - m_drawElevation, p.y - m_drawElevation); + thing->draw(p - m_drawElevation); m_drawElevation += type.elevation; if(m_drawElevation > MAX_DRAW_ELEVATION) m_drawElevation = MAX_DRAW_ELEVATION; @@ -68,12 +68,12 @@ void Tile::draw(const Point& p) for(int yi = -1; yi <= 1; ++yi) { for(CreaturePtr creature : g_map.getTile(m_position + Position(xi, yi, 0))->getCreatures()) { auto& type = creature->getType(); - Rect creatureRect(p.x + xi*32 + creature->getWalkOffsetX() - type.xDisplacement, p.y + yi*32 + creature->getWalkOffsetY() - type.yDisplacement, 32, 32); + Rect creatureRect(p.x + xi*32 + creature->getWalkOffset().x - type.xDisplacement, p.y + yi*32 + creature->getWalkOffset().y - type.yDisplacement, 32, 32); Rect thisTileRect(p.x, p.y, 32, 32); // only render creatures where bottom right is inside our rect if(thisTileRect.contains(creatureRect.bottomRight())) { - creature->draw(p.x + xi*32 - m_drawElevation, p.y + yi*32 - m_drawElevation); + creature->draw(Point(p.x + xi*32 - m_drawElevation, p.y + yi*32 - m_drawElevation)); } } } @@ -81,13 +81,13 @@ void Tile::draw(const Point& p) // effects for(const EffectPtr& effect : m_effects) - effect->draw(p.x - m_drawElevation, p.y - m_drawElevation); + effect->draw(p - m_drawElevation); // top items for(const ThingPtr& thing : m_things) { const ThingType& type = thing->getType(); if(type.isOnTop) - thing->draw(p.x, p.y); + thing->draw(p); } } diff --git a/src/otclient/net/protocolgameparse.cpp b/src/otclient/net/protocolgameparse.cpp index 4a5e03e7..f1b1c569 100644 --- a/src/otclient/net/protocolgameparse.cpp +++ b/src/otclient/net/protocolgameparse.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -531,9 +532,14 @@ void ProtocolGame::parseAnimatedText(InputMessage& msg) void ProtocolGame::parseDistanceShot(InputMessage& msg) { - parsePosition(msg); // fromPos - parsePosition(msg); // toPos - msg.getU8(); // effect + Position fromPos = parsePosition(msg); + Position toPos = parsePosition(msg); + int shotId = msg.getU8(); + + MissilePtr shot = MissilePtr(new Missile()); + shot->setId(shotId); + shot->setPath(fromPos, toPos); + g_map.addThing(shot, fromPos); } void ProtocolGame::parseCreatureSquare(InputMessage& msg) @@ -1052,7 +1058,7 @@ ItemPtr ProtocolGame::internalGetItem(InputMessage& msg, uint16 id) const ThingType& itemType = g_thingsType.getItemType(id); if(itemType.isStackable || itemType.isFluidContainer || itemType.isSplash) - item->setCount(msg.getU8()); + item->setData(msg.getU8()); return item; } diff --git a/src/otclient/util/position.h b/src/otclient/util/position.h index 7e862e3d..f505236b 100644 --- a/src/otclient/util/position.h +++ b/src/otclient/util/position.h @@ -60,7 +60,7 @@ public: Position operator+(const Position& other) const { return Position(x + other.x, y + other.y, z + other.z); } Position& operator+=(const Position& other) { x+=other.x; y+=other.y; z +=other.z; return *this; } - Position operator-(const Position& other) const { return Position(x - other.x, y - other.y, z + other.z); } + Position operator-(const Position& other) const { return Position(x - other.x, y - other.y, z - other.z); } Position& operator-=(const Position& other) { x-=other.x; y-=other.y; z-=other.z; return *this; } Position& operator=(const Position& other) { x = other.x; y = other.y; z = other.z; return *this; }