missiles and some reworking
This commit is contained in:
parent
61ce6d6331
commit
a3c65f3a7e
|
@ -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
|
||||
|
|
|
@ -34,27 +34,32 @@ template<class T>
|
|||
class TPoint
|
||||
{
|
||||
public:
|
||||
TPoint() : x(0), y(0) {};
|
||||
TPoint(T x, T y) : x(x), y(y) { };
|
||||
TPoint(const TPoint<T>& other) : x(other.x), y(other.y) { };
|
||||
TPoint() : x(0), y(0) {}
|
||||
TPoint(T x, T y) : x(x), y(y) { }
|
||||
TPoint(const TPoint<T>& other) : x(other.x), y(other.y) { }
|
||||
|
||||
bool isNull() const { return x==0 && y==0; }
|
||||
TSize<T> toSize() const { return TSize<T>(x, y); }
|
||||
|
||||
TPoint<T> operator-() const { return TPoint<T>(-x, -y); }
|
||||
TPoint<T> operator+(const TPoint<T>& other) const { return TPoint<T>(x + other.x, y + other.y); }
|
||||
TPoint<T> operator+(const TPoint<T>& other) const { return TPoint<T>(x + other.x, y + other.y); }
|
||||
TPoint<T>& operator+=(const TPoint<T>& other) { x+=other.x; y+=other.y; return *this; }
|
||||
TPoint<T> operator-(const TPoint<T>& other) const { return TPoint<T>(x - other.x, y - other.y); }
|
||||
TPoint<T> operator-(const TPoint<T>& other) const { return TPoint<T>(x - other.x, y - other.y); }
|
||||
TPoint<T>& operator-=(const TPoint<T>& other) { x-=other.x; y-=other.y; return *this; }
|
||||
TPoint<T> operator*(const TPoint<T>& other) const { return TPoint<T>(x * other.x, y * other.y); }
|
||||
TPoint<T> operator*(const TPoint<T>& other) const { return TPoint<T>(x * other.x, y * other.y); }
|
||||
TPoint<T>& operator*=(const TPoint<T>& other) { x*=other.x; y*=other.y; return *this; }
|
||||
TPoint<T> operator*(const T v) const { return TPoint<T>(x * v, y * v); }
|
||||
TPoint<T>& operator*=(const T v) { x*=v; y*=v; return *this; }
|
||||
TPoint<T> operator/(const TPoint<T>& other) const { return TPoint<T>(x/other.x, y/other.y); }
|
||||
TPoint<T> operator/(const TPoint<T>& other) const { return TPoint<T>(x/other.x, y/other.y); }
|
||||
TPoint<T>& operator/=(const TPoint<T>& other) { x/=other.x; y/=other.y; return *this; }
|
||||
TPoint<T> operator/(const T v) const { return TPoint<T>(x/v, y/v); }
|
||||
TPoint<T> operator/(const T v) const { return TPoint<T>(x/v, y/v); }
|
||||
TPoint<T>& operator/=(const T v) { x/=v; y/=v; return *this; }
|
||||
|
||||
TPoint<T> operator+(T other) const { return TPoint<T>(x + other, y + other); }
|
||||
TPoint<T>& operator+=(T other) { x+=other; y+=other; return *this; }
|
||||
TPoint<T> operator-(T other) const { return TPoint<T>(x - other, y - other); }
|
||||
TPoint<T>& operator-=(T other) { x-=other; y-=other; return *this; }
|
||||
|
||||
bool operator<=(const TPoint<T>&other) const { return x<=other.x && y<=other.y; }
|
||||
bool operator>=(const TPoint<T>&other) const { return x>=other.x && y>=other.y; }
|
||||
bool operator<(const TPoint<T>&other) const { return x<other.x && y<other.y; }
|
||||
|
|
|
@ -38,19 +38,12 @@ Creature::Creature() : Thing()
|
|||
m_direction = Otc::South;
|
||||
|
||||
m_walking = false;
|
||||
m_walkOffsetX = 0;
|
||||
m_walkOffsetY = 0;
|
||||
|
||||
m_informationFont = g_fonts.getFont("verdana-11px-rounded");
|
||||
}
|
||||
|
||||
void Creature::draw(int x, int y)
|
||||
void Creature::draw(const Point& p)
|
||||
{
|
||||
if(m_walking) {
|
||||
x += m_walkOffsetX;
|
||||
y += m_walkOffsetY;
|
||||
}
|
||||
|
||||
const ThingType& type = getType();
|
||||
|
||||
// Render creature
|
||||
|
@ -61,7 +54,7 @@ void Creature::draw(int x, int y)
|
|||
continue;
|
||||
|
||||
// draw white item
|
||||
internalDraw(x, y, 0);
|
||||
internalDraw(p + m_walkOffset, 0);
|
||||
|
||||
// draw mask if exists
|
||||
if(type.layers > 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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<Thing> ThingPtr;
|
|||
typedef std::shared_ptr<Item> ItemPtr;
|
||||
typedef std::shared_ptr<Creature> CreaturePtr;
|
||||
typedef std::shared_ptr<Effect> EffectPtr;
|
||||
typedef std::shared_ptr<Missile> MissilePtr;
|
||||
typedef std::shared_ptr<Player> PlayerPtr;
|
||||
typedef std::shared_ptr<LocalPlayer> LocalPlayerPtr;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Item>(shared_from_this()); }
|
||||
|
||||
private:
|
||||
int m_count;
|
||||
int m_data;
|
||||
int m_lastTicks;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "localplayer.h"
|
||||
#include "tile.h"
|
||||
#include "item.h"
|
||||
#include "missile.h"
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/framebuffer.h>
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
private:
|
||||
std::unordered_map<Position, TilePtr, PositionHasher> m_tiles;
|
||||
std::map<uint32, CreaturePtr> m_creatures;
|
||||
std::map<int, std::vector<MissilePtr> > m_missilesAtFloor;
|
||||
|
||||
Light m_light;
|
||||
Position m_centralPosition;
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 OTClient <https://github.com/edubart/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 <framework/platform/platform.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 OTClient <https://github.com/edubart/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 <framework/global.h>
|
||||
#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<Missile>(shared_from_this()); }
|
||||
|
||||
private:
|
||||
int m_startTicks;
|
||||
Position m_positionDelta;
|
||||
float m_duration;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <otclient/core/map.h>
|
||||
#include <otclient/core/item.h>
|
||||
#include <otclient/core/effect.h>
|
||||
#include <otclient/core/missile.h>
|
||||
#include <otclient/core/tile.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
Loading…
Reference in New Issue