introduce statictext

This commit is contained in:
Henrique Santiago 2011-12-29 15:45:59 -02:00
parent ad82c549b8
commit d67442dc49
13 changed files with 234 additions and 12 deletions

View File

@ -51,7 +51,8 @@ namespace Fw
darkTeal = 0xff808000, darkTeal = 0xff808000,
gray = 0xffa0a0a0, gray = 0xffa0a0a0,
darkGray = 0xff808080, darkGray = 0xff808080,
lightGray = 0xffc0c0c0 lightGray = 0xffc0c0c0,
orange = 0xffff8c00
}; };
enum Key : uint8 { enum Key : uint8 {

View File

@ -153,6 +153,8 @@ inline std::istream& operator>>(std::istream& in, Color& color)
color = Fw::darkGray; color = Fw::darkGray;
} else if(tmp == "lightGray") { } else if(tmp == "lightGray") {
color = Fw::lightGray; color = Fw::lightGray;
} else if(tmp == "orange") {
color = Fw::orange;
} else { } else {
in.seekg(-tmp.length(), ios_base::cur); in.seekg(-tmp.length(), ios_base::cur);
} }

View File

@ -30,6 +30,7 @@ SET(otclient_SOURCES ${otclient_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/core/localplayer.cpp ${CMAKE_CURRENT_LIST_DIR}/core/localplayer.cpp
${CMAKE_CURRENT_LIST_DIR}/core/outfit.cpp ${CMAKE_CURRENT_LIST_DIR}/core/outfit.cpp
${CMAKE_CURRENT_LIST_DIR}/core/animatedtext.cpp ${CMAKE_CURRENT_LIST_DIR}/core/animatedtext.cpp
${CMAKE_CURRENT_LIST_DIR}/core/statictext.cpp
# otclient ui # otclient ui
${CMAKE_CURRENT_LIST_DIR}/ui/uiitem.cpp ${CMAKE_CURRENT_LIST_DIR}/ui/uiitem.cpp

View File

@ -21,7 +21,6 @@
*/ */
#include "animatedtext.h" #include "animatedtext.h"
#include "outfit.h"
#include "map.h" #include "map.h"
#include <framework/core/clock.h> #include <framework/core/clock.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>

View File

@ -51,5 +51,4 @@ private:
double m_startTime; double m_startTime;
}; };
#endif #endif

View File

@ -34,6 +34,7 @@ class Missile;
class Player; class Player;
class LocalPlayer; class LocalPlayer;
class AnimatedText; class AnimatedText;
class StaticText;
typedef std::shared_ptr<Tile> TilePtr; typedef std::shared_ptr<Tile> TilePtr;
typedef std::shared_ptr<Thing> ThingPtr; typedef std::shared_ptr<Thing> ThingPtr;
@ -44,6 +45,7 @@ typedef std::shared_ptr<Missile> MissilePtr;
typedef std::shared_ptr<Player> PlayerPtr; typedef std::shared_ptr<Player> PlayerPtr;
typedef std::shared_ptr<LocalPlayer> LocalPlayerPtr; typedef std::shared_ptr<LocalPlayer> LocalPlayerPtr;
typedef std::shared_ptr<AnimatedText> AnimatedTextPtr; typedef std::shared_ptr<AnimatedText> AnimatedTextPtr;
typedef std::shared_ptr<StaticText> StaticTextPtr;
typedef std::vector<ThingPtr> ThingList; typedef std::vector<ThingPtr> ThingList;

View File

@ -26,6 +26,7 @@
#include "tile.h" #include "tile.h"
#include "item.h" #include "item.h"
#include "missile.h" #include "missile.h"
#include "statictext.h"
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/graphics/framebuffer.h> #include <framework/graphics/framebuffer.h>
#include <framework/graphics/paintershaderprogram.h> #include <framework/graphics/paintershaderprogram.h>
@ -135,6 +136,14 @@ void Map::draw(const Rect& rect)
pos.y *= verticalStretchFactor; pos.y *= verticalStretchFactor;
(*it)->draw(rect.topLeft() + pos); (*it)->draw(rect.topLeft() + pos);
} }
// draw static text
for(auto it = m_staticTexts.begin(), end = m_staticTexts.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() void Map::clean()
@ -240,18 +249,36 @@ void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos)
} }
else if(MissilePtr shot = thing->asMissile()) { else if(MissilePtr shot = thing->asMissile()) {
m_missilesAtFloor[shot->getPosition().z].push_back(shot); m_missilesAtFloor[shot->getPosition().z].push_back(shot);
return;
} }
else if(AnimatedTextPtr animatedText = thing->asAnimatedText()) { else if(AnimatedTextPtr animatedText = thing->asAnimatedText()) {
animatedText->start();
m_animatedTexts.push_back(animatedText); m_animatedTexts.push_back(animatedText);
return; }
else if(StaticTextPtr staticText = thing->asStaticText()) {
bool mustAdd = true;
for(auto it = m_staticTexts.begin(), end = m_staticTexts.end(); it != end; ++it) {
StaticTextPtr cStaticText = *it;
if(cStaticText->getPosition() == pos) {
// try to combine messages
if(cStaticText->addMessage(staticText->getName(), staticText->getMessageType(), staticText->getFirstMessage())) {
mustAdd = false;
break;
}
else {
// must add another message and rearrenge current
}
}
}
if(mustAdd)
m_staticTexts.push_back(staticText);
} }
else { else {
tile->addThing(thing, stackPos); tile->addThing(thing, stackPos);
} }
thing->start(); thing->start();
thing->setPosition(pos);
} }
ThingPtr Map::getThing(const Position& pos, int stackPos) ThingPtr Map::getThing(const Position& pos, int stackPos)
@ -285,6 +312,12 @@ void Map::removeThing(const ThingPtr& thing)
m_animatedTexts.erase(it); m_animatedTexts.erase(it);
return; return;
} }
else if(StaticTextPtr staticText = thing->asStaticText()) {
auto it = std::find(m_staticTexts.begin(), m_staticTexts.end(), staticText);
if(it != m_staticTexts.end())
m_staticTexts.erase(it);
return;
}
if(TilePtr& tile = m_tiles[thing->getPosition()]) if(TilePtr& tile = m_tiles[thing->getPosition()])
tile->removeThing(thing); tile->removeThing(thing);

View File

@ -79,6 +79,7 @@ private:
std::map<uint32, CreaturePtr> m_creatures; std::map<uint32, CreaturePtr> m_creatures;
std::array<std::vector<MissilePtr>, MAX_Z> m_missilesAtFloor; std::array<std::vector<MissilePtr>, MAX_Z> m_missilesAtFloor;
std::vector<AnimatedTextPtr> m_animatedTexts; std::vector<AnimatedTextPtr> m_animatedTexts;
std::vector<StaticTextPtr> m_staticTexts;
Light m_light; Light m_light;
Position m_centralPosition; Position m_centralPosition;

View File

@ -0,0 +1,117 @@
/*
* 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 "statictext.h"
#include "map.h"
#include <framework/core/clock.h>
#include <framework/core/eventdispatcher.h>
#include <framework/graphics/graphics.h>
StaticText::StaticText()
{
m_font = g_fonts.getFont("verdana-11px-rounded");
}
void StaticText::draw(const Point& p)
{
if(m_font)
m_font->renderText(m_text, Rect(p - Point(m_textSize.width() / 2, m_textSize.height()) + Point(20, 5), m_textSize), Fw::AlignCenter, m_color);
}
bool StaticText::addMessage(const std::string& name, int type, const std::string& message)
{
// First message
if(m_messages.size() == 0) {
m_name = name;
m_type = type;
}
else {
// we can only add another message if it follows these conditions
if(m_name != name || m_type != type)
return false;
}
m_messages.push_back(message);
compose();
auto self = asStaticText();
g_dispatcher.scheduleEvent([self]() {
self->removeMessage();
}, DURATION);
return true;
}
void StaticText::removeMessage()
{
m_messages.erase(m_messages.begin());
if(m_messages.empty()) {
// schedule removal
auto self = asStaticText();
g_dispatcher.scheduleEvent([self]() {
g_map.removeThing(self);
}, 0);
}
else
compose();
}
void StaticText::compose()
{
m_text.clear();
if(m_type == Otc::SpeakSay) {
m_text += m_name;
m_text += " says:\n";
m_color = Fw::yellow;
}
else if(m_type == Otc::SpeakWhisper) {
m_text += m_name;
m_text += " whispers:\n";
m_color = Fw::yellow;
}
else if(m_type == Otc::SpeakYell) {
m_text += m_name;
m_text += " yells:\n";
m_color = Fw::yellow;
}
else if(m_type == Otc::SpeakMonsterSay || m_type == Otc::SpeakMonsterYell) {
m_color = Fw::orange;
}
else if(m_type == Otc::SpeakPrivateNpcToPlayer) {
m_text += m_name;
m_text += " says:\n";
m_color = Fw::blue;
}
// Todo: add break lines
for(uint i = 0; i < m_messages.size(); ++i) {
m_text += m_messages[i];
if(i < m_messages.size() - 1)
m_text += "\n";
}
if(m_font)
m_textSize = m_font->calculateTextRectSize(m_text);
}

View File

@ -0,0 +1,60 @@
/*
* 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 STATICTEXT_H
#define STATICTEXT_H
#include "thing.h"
#include <framework/graphics/fontmanager.h>
class StaticText : public Thing
{
public:
enum {
DURATION = 3000
};
StaticText();
void draw(const Point& p);
std::string getName() { return m_name; }
int getMessageType() { return m_type; }
std::string getFirstMessage() { return m_messages[0]; }
bool addMessage(const std::string& name, int type, const std::string& message);
void removeMessage();
StaticTextPtr asStaticText() { return std::static_pointer_cast<StaticText>(shared_from_this()); }
private:
void compose();
FontPtr m_font;
Size m_textSize;
std::vector<std::string> m_messages;
std::string m_name, m_text;
int m_type;
Color m_color;
};
#endif

View File

@ -64,6 +64,7 @@ public:
virtual PlayerPtr asPlayer() { return nullptr; } virtual PlayerPtr asPlayer() { return nullptr; }
virtual LocalPlayerPtr asLocalPlayer() { return nullptr; } virtual LocalPlayerPtr asLocalPlayer() { return nullptr; }
virtual AnimatedTextPtr asAnimatedText() { return nullptr; } virtual AnimatedTextPtr asAnimatedText() { return nullptr; }
virtual StaticTextPtr asStaticText() { return nullptr; }
protected: protected:
void internalDraw(const Point& p, int layer); void internalDraw(const Point& p, int layer);

View File

@ -132,7 +132,6 @@ ThingPtr Tile::addThing(const ThingPtr& thing, int stackPos)
if(stackPos < (int)m_things.size()) if(stackPos < (int)m_things.size())
oldObject = m_things[stackPos]; oldObject = m_things[stackPos];
m_things.insert(m_things.begin() + stackPos, thing); m_things.insert(m_things.begin() + stackPos, thing);
thing->setPosition(m_position);
return oldObject; return oldObject;
} }

View File

@ -33,6 +33,7 @@
#include <otclient/luascript/luavaluecasts.h> #include <otclient/luascript/luavaluecasts.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
#include <framework/graphics/particlemanager.h> #include <framework/graphics/particlemanager.h>
#include <otclient/core/statictext.h>
void ProtocolGame::parseMessage(InputMessage& msg) void ProtocolGame::parseMessage(InputMessage& msg)
{ {
@ -746,8 +747,8 @@ void ProtocolGame::parsePlayerCancelAttack(InputMessage& msg)
void ProtocolGame::parseCreatureSpeak(InputMessage& msg) void ProtocolGame::parseCreatureSpeak(InputMessage& msg)
{ {
msg.getU32(); // unkSpeak msg.getU32(); // unkSpeak
std::string name = msg.getString(); // name std::string name = msg.getString();
int level = msg.getU16(); // level int level = msg.getU16();
int type = msg.getU8(); int type = msg.getU8();
int channelId = 0; int channelId = 0;
Position creaturePos; Position creaturePos;
@ -759,13 +760,13 @@ void ProtocolGame::parseCreatureSpeak(InputMessage& msg)
case Otc::SpeakMonsterSay: case Otc::SpeakMonsterSay:
case Otc::SpeakMonsterYell: case Otc::SpeakMonsterYell:
case Otc::SpeakPrivateNpcToPlayer: case Otc::SpeakPrivateNpcToPlayer:
creaturePos = parsePosition(msg); // creaturePos creaturePos = parsePosition(msg);
break; break;
case Otc::SpeakChannelRed: case Otc::SpeakChannelRed:
case Otc::SpeakChannelOrange: case Otc::SpeakChannelOrange:
case Otc::SpeakChannelYellow: case Otc::SpeakChannelYellow:
case Otc::SpeakChannelWhite: case Otc::SpeakChannelWhite:
channelId = msg.getU16(); // channelId channelId = msg.getU16();
break; break;
case Otc::SpeakPrivate: case Otc::SpeakPrivate:
case Otc::SpeakPrivatePlayerToNpc: case Otc::SpeakPrivatePlayerToNpc:
@ -777,11 +778,17 @@ void ProtocolGame::parseCreatureSpeak(InputMessage& msg)
break; break;
} }
std::string message = msg.getString(); // message std::string message = msg.getString();
g_dispatcher.addEvent([=] { g_dispatcher.addEvent([=] {
g_lua.callGlobalField("Game", "onCreatureSpeak", name, level, type, message, channelId, creaturePos); g_lua.callGlobalField("Game", "onCreatureSpeak", name, level, type, message, channelId, creaturePos);
}); });
if(creaturePos.isValid()) {
StaticTextPtr staticText = StaticTextPtr(new StaticText);
staticText->addMessage(name, type, message);
g_map.addThing(staticText, creaturePos);
}
} }
void ProtocolGame::parseChannelList(InputMessage& msg) void ProtocolGame::parseChannelList(InputMessage& msg)