missiles and some reworking

This commit is contained in:
Henrique 2011-11-07 23:44:30 -02:00
parent 61ce6d6331
commit a3c65f3a7e
19 changed files with 383 additions and 109 deletions

View File

@ -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

View File

@ -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; }

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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;
};

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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; }