diff --git a/src/framework/util/color.h b/src/framework/util/color.h index 1a1f95e3..35d341d6 100644 --- a/src/framework/util/color.h +++ b/src/framework/util/color.h @@ -61,6 +61,16 @@ public: bool operator==(const Color& other) const { return other.m_rgba == m_rgba; } bool operator!=(const Color& other) const { return other.m_rgba != m_rgba; } + static Color from8bit(int color) { + if(color >= 216 || color <= 0) + return Color(0, 0, 0); + + int r = int(color / 36) % 6 * 51; + int g = int(color / 6) % 6 * 51; + int b = color % 6 * 51; + return Color(r, g, b); + } + private: union { uint32 m_rgba; diff --git a/src/otclient/CMakeLists.txt b/src/otclient/CMakeLists.txt index 738a489b..7d46925a 100644 --- a/src/otclient/CMakeLists.txt +++ b/src/otclient/CMakeLists.txt @@ -29,6 +29,7 @@ SET(otclient_SOURCES ${otclient_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/core/missile.cpp ${CMAKE_CURRENT_LIST_DIR}/core/localplayer.cpp ${CMAKE_CURRENT_LIST_DIR}/core/outfit.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/animatedtext.cpp # otclient ui ${CMAKE_CURRENT_LIST_DIR}/ui/uiitem.cpp diff --git a/src/otclient/core/animatedtext.cpp b/src/otclient/core/animatedtext.cpp new file mode 100644 index 00000000..c6bedddd --- /dev/null +++ b/src/otclient/core/animatedtext.cpp @@ -0,0 +1,61 @@ +/* + * 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 "animatedtext.h" +#include "outfit.h" +#include "map.h" +#include +#include + +AnimatedText::AnimatedText() +{ + m_font = g_fonts.getFont("verdana-11px-rounded"); +} + +void AnimatedText::start() +{ + m_startTime = g_clock.time(); + + auto self = asAnimatedText(); + + // schedule removal + g_dispatcher.scheduleEvent([self]() { + g_map.removeThing(self); + }, DURATION); +} + +void AnimatedText::draw(const Point& p) +{ + assert(m_font); + m_font->renderText(m_text, Rect(p + Point(0, -20.0 * g_clock.timeElapsed(m_startTime) / (DURATION / 1000)), m_textSize), Fw::AlignTopCenter, m_color); +} + +void AnimatedText::setColor(int color) +{ + m_color = Color::from8bit(color); +} + +void AnimatedText::setText(const std::string& text) +{ + m_textSize = m_font->calculateTextRectSize(text); + m_text = text; +} diff --git a/src/otclient/core/animatedtext.h b/src/otclient/core/animatedtext.h new file mode 100644 index 00000000..67e7e29d --- /dev/null +++ b/src/otclient/core/animatedtext.h @@ -0,0 +1,55 @@ +/* + * 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 ANIMATEDTEXT_H +#define ANIMATEDTEXT_H + +#include "thing.h" +#include + +class AnimatedText : public Thing +{ +public: + enum { + DURATION = 1000 + }; + + AnimatedText(); + + void start(); + void draw(const Point& p); + + void setColor(int color); + void setText(const std::string& text); + + AnimatedTextPtr asAnimatedText() { return std::static_pointer_cast(shared_from_this()); } + +private: + FontPtr m_font; + Size m_textSize; + std::string m_text; + Color m_color; + double m_startTime; +}; + + +#endif diff --git a/src/otclient/core/declarations.h b/src/otclient/core/declarations.h index d5e97a88..3331293b 100644 --- a/src/otclient/core/declarations.h +++ b/src/otclient/core/declarations.h @@ -33,6 +33,7 @@ class Effect; class Missile; class Player; class LocalPlayer; +class AnimatedText; typedef std::shared_ptr TilePtr; typedef std::shared_ptr ThingPtr; @@ -42,6 +43,7 @@ typedef std::shared_ptr EffectPtr; typedef std::shared_ptr MissilePtr; typedef std::shared_ptr PlayerPtr; typedef std::shared_ptr LocalPlayerPtr; +typedef std::shared_ptr AnimatedTextPtr; typedef std::vector ThingList; diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index 269bdc26..e00a46f6 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -127,6 +127,14 @@ void Map::draw(const Rect& rect) } } } + + // draw animated text + for(auto it = m_animatedTexts.begin(), end = m_animatedTexts.end(); it != end; ++it) { + Point pos = positionTo2D((*it)->getPosition()) - m_drawOffset; + pos.x *= horizontalStretchFactor; + pos.y *= verticalStretchFactor; + (*it)->draw(rect.topLeft() + pos); + } } void Map::clean() @@ -225,6 +233,11 @@ void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos) m_missilesAtFloor[shot->getPosition().z].push_back(shot); return; } + else if(AnimatedTextPtr animatedText = thing->asAnimatedText()) { + animatedText->start(); + m_animatedTexts.push_back(animatedText); + return; + } TilePtr tile = getTile(pos); tile->addThing(thing, stackPos); @@ -258,6 +271,12 @@ void Map::removeThing(const ThingPtr& thing) } return; } + else if(AnimatedTextPtr animatedText = thing->asAnimatedText()) { + auto it = std::find(m_animatedTexts.begin(), m_animatedTexts.end(), animatedText); + if(it != m_animatedTexts.end()) + m_animatedTexts.erase(it); + 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 e8a3845a..1f36e915 100644 --- a/src/otclient/core/map.h +++ b/src/otclient/core/map.h @@ -24,6 +24,8 @@ #define MAP_H #include "creature.h" +#include "animatedtext.h" +#include #include class Map @@ -76,6 +78,7 @@ private: std::unordered_map m_tiles; std::map m_creatures; std::array, MAX_Z> m_missilesAtFloor; + std::vector m_animatedTexts; Light m_light; Position m_centralPosition; diff --git a/src/otclient/core/thing.cpp b/src/otclient/core/thing.cpp index 109a0d0a..cd237ded 100644 --- a/src/otclient/core/thing.cpp +++ b/src/otclient/core/thing.cpp @@ -81,3 +81,7 @@ int Thing::getStackPriority() return 5; } +ThingType *Thing::getType() +{ + return g_thingsType.getEmptyThingType(); +} diff --git a/src/otclient/core/thing.h b/src/otclient/core/thing.h index 29328d47..a731bb92 100644 --- a/src/otclient/core/thing.h +++ b/src/otclient/core/thing.h @@ -47,7 +47,7 @@ public: uint32 getId() const { return m_id; } Position getPosition() const { return m_position; } int getStackPriority(); - virtual ThingType *getType() = 0; + virtual ThingType *getType(); int getAnimationPhases() { return m_type->dimensions[ThingType::AnimationPhases]; } void setXPattern(int xPattern) { m_xPattern = xPattern; } @@ -61,6 +61,7 @@ public: virtual MissilePtr asMissile() { return nullptr; } virtual PlayerPtr asPlayer() { return nullptr; } virtual LocalPlayerPtr asLocalPlayer() { return nullptr; } + virtual AnimatedTextPtr asAnimatedText() { return nullptr; } protected: void internalDraw(const Point& p, int layers); diff --git a/src/otclient/net/protocolgameparse.cpp b/src/otclient/net/protocolgameparse.cpp index b68c5d56..0a6da929 100644 --- a/src/otclient/net/protocolgameparse.cpp +++ b/src/otclient/net/protocolgameparse.cpp @@ -537,9 +537,16 @@ void ProtocolGame::parseMagicEffect(InputMessage& msg) void ProtocolGame::parseAnimatedText(InputMessage& msg) { - parsePosition(msg); // textPos - msg.getU8(); // color - msg.getString(); // text + Position position = parsePosition(msg); + uint8 color = msg.getU8(); + std::string text = msg.getString(); + + AnimatedTextPtr animatedText = AnimatedTextPtr(new AnimatedText); + animatedText->setPosition(position); + animatedText->setColor(color); + animatedText->setText(text); + + g_map.addThing(animatedText, position); } void ProtocolGame::parseDistanceMissile(InputMessage& msg) diff --git a/src/otclient/ui/uimap.cpp b/src/otclient/ui/uimap.cpp index 79b746dc..1eb092a4 100644 --- a/src/otclient/ui/uimap.cpp +++ b/src/otclient/ui/uimap.cpp @@ -27,6 +27,7 @@ #include #include #include +#include UIMap::UIMap() { @@ -72,10 +73,17 @@ bool UIMap::onMousePress(const Point& mousePos, Fw::MouseButton button) // cool testing \/ if(button == Fw::MouseLeftButton) { - MissilePtr shot = MissilePtr(new Missile()); + /*MissilePtr shot = MissilePtr(new Missile()); shot->setId(1); shot->setPath(g_map.getCentralPosition(), tilePos); - g_map.addThing(shot, g_map.getCentralPosition()); + g_map.addThing(shot, g_map.getCentralPosition());*/ + + AnimatedTextPtr animatedText = AnimatedTextPtr(new AnimatedText); + animatedText->setPosition(g_map.getCentralPosition()); + animatedText->setColor(12); + animatedText->setText("text"); + + g_map.addThing(animatedText, g_map.getCentralPosition()); } else if(button == Fw::MouseRightButton) { EffectPtr effect = EffectPtr(new Effect());