diff --git a/modules/game_shaders/item.frag b/modules/game_shaders/item.frag deleted file mode 100644 index 8aaeed95..00000000 --- a/modules/game_shaders/item.frag +++ /dev/null @@ -1,11 +0,0 @@ -uniform float opacity; // painter opacity -uniform vec4 color; // painter color -uniform float time; // time in seconds since shader linkage -uniform sampler2D tex0; // map texture -varying vec2 texCoord; // map texture coords -//uniform int itemId; // item id - -void main() -{ - gl_FragColor = texture2D(tex0, texCoord); -} diff --git a/modules/game_shaders/outfit.frag b/modules/game_shaders/outfit.frag deleted file mode 100644 index 869c69ec..00000000 --- a/modules/game_shaders/outfit.frag +++ /dev/null @@ -1,62 +0,0 @@ -uniform float opacity; // painter opacity -uniform vec4 color; // painter color -uniform float time; // time in seconds since shader linkage - -uniform sampler2D tex0; // outfit texture -uniform sampler2D tex1; // outfit color mask -varying vec2 texCoord; // outfit texture coords - -uniform vec4 headColor; -uniform vec4 bodyColor; -uniform vec4 legsColor; -uniform vec4 feetColor; - - -vec4 calcOutfitPixel() -{ - vec4 pixel = texture2D(tex0, texCoord); - vec4 maskColor = texture2D(tex1, texCoord); - - vec4 outColor = vec4(1.0, 1.0, 1.0, 1.0); - if(maskColor.r > 0.1 && maskColor.g > 0.1) - outColor = headColor; - else if(maskColor.r > 0.1) - outColor = bodyColor; - else if(maskColor.g > 0.1) - outColor = legsColor; - else if(maskColor.b > 0.1) - outColor = feetColor; - - return pixel * outColor; -} - -/* -// optimized to handle antialising -vec4 calcOutfitPixel() -{ - vec4 pixel = texture2D(texture, textureCoords); - vec4 maskColor = texture2D(maskTexture, textureCoords); - const vec4 white = vec4(1,1,1,1); - - float headFactor = 0.0; - if(maskColor.r > 0.1 && maskColor.g > 0.1) { - headFactor = min(maskColor.r, maskColor.g); - - maskColor.r -= headFactor; - maskColor.g -= headFactor; - } - - float tot = headFactor + maskColor.r + maskColor.g + maskColor.b; - vec4 outColor = headFactor * headColor + bodyColor * maskColor.r + legsColor * maskColor.g + feetColor * maskColor.b; - if(tot < 1.0) - outColor += white * (1.0 - tot); - outColor.a = 1.0; - - return pixel * outColor; -} -*/ -void main() -{ - gl_FragColor = calcOutfitPixel(); -} - diff --git a/modules/game_shaders/shaders.lua b/modules/game_shaders/shaders.lua index 99536f12..b88a740c 100644 --- a/modules/game_shaders/shaders.lua +++ b/modules/game_shaders/shaders.lua @@ -1,17 +1,23 @@ Shaders = {} local HOTKEY = 'Ctrl+X' -local SHADERS = { - ['Default'] = 'shaders/default.frag', - ['Bloom'] = 'shaders/bloom.frag', - ['Sepia'] = 'shaders/sepia.frag', - ['Grayscale'] = 'shaders/grayscale.frag', - ['Pulse'] = 'shaders/pulse.frag', - ['Old Tv'] = 'shaders/oldtv.frag', - ['Fog'] = 'shaders/fog.frag', - ['Party'] = 'shaders/party.frag', - ['Radial Blur'] = 'shaders/radialblur.frag', - ['Zomg'] = 'shaders/zomg.frag', +local MAP_SHADERS = { + { name = 'Default', frag = 'shaders/default.frag' }, + { name = 'Bloom', frag = 'shaders/bloom.frag'}, + { name = 'Sepia', frag ='shaders/sepia.frag' }, + { name = 'Grayscale', frag ='shaders/grayscale.frag' }, + { name = 'Pulse', frag = 'shaders/pulse.frag' }, + { name = 'Old Tv', frag = 'shaders/oldtv.frag' }, + { name = 'Fog', frag = 'shaders/fog.frag', tex1 = 'images/clouds.png' }, + { name = 'Party', frag = 'shaders/party.frag' }, + { name = 'Radial Blur', frag ='shaders/radialblur.frag' }, + { name = 'Zomg', frag ='shaders/zomg.frag' }, + { name = 'Heat', frag ='shaders/heat.frag' }, + { name = 'Noise', frag ='shaders/noise.frag' }, +} + +local ITEM_SHADERS = { + { name = 'Fake 3D', vert = 'shaders/fake3d.vert' } } local shadersPanel @@ -29,16 +35,19 @@ function Shaders.init() mapComboBox.onOptionChange = function(combobox, option) local map = GameInterface.getMapPanel() map:setMapShader(g_shaders.getShader(option)) - print(option) end - for name,file in pairs(SHADERS) do - local shader = g_shaders.createFragmentShader(name, file) - mapComboBox:addOption(name) + for _i,opts in pairs(MAP_SHADERS) do + local shader = g_shaders.createFragmentShader(opts.name, opts.frag) - if name == 'Fog' then - shader:addMultiTexture('images/clouds.png') + if opts.tex1 then + shader:addMultiTexture(opts.tex1) end + if opts.tex2 then + shader:addMultiTexture(opts.tex2) + end + + mapComboBox:addOption(opts.name) end local map = GameInterface.getMapPanel() diff --git a/modules/game_shaders/shaders/heat.frag b/modules/game_shaders/shaders/heat.frag new file mode 100644 index 00000000..1d0216a7 --- /dev/null +++ b/modules/game_shaders/shaders/heat.frag @@ -0,0 +1,56 @@ +uniform sampler2D u_Tex0; +varying vec2 v_TexCoord; +uniform float u_Time; +uniform vec2 u_Resolution; +const float PI = 3.1415926535897932; + +// speed +const float speed = 0.06; +const float speed_x = 0.03; +const float speed_y = 0.02; + +// geometry +const float intensity = 30.; +const int steps = 5; +const float frequency = 3.0; +const int angle = 7; // better when a prime + +// reflection and emboss +const float delta = 100.; +const float intence = 1.2; +const float emboss = 0.1; + +//---------- crystals effect +float col(vec2 coord) +{ + float delta_theta = 2.0 * PI / float(angle); + float col = 0.0; + float theta = 0.0; + for(int i = 0; i < steps; i++) { + vec2 adjc = coord; + theta = delta_theta*float(i); + adjc.x += cos(theta)*u_Time*speed + u_Time * speed_x; + adjc.y -= sin(theta)*u_Time*speed - u_Time * speed_y; + col = col + cos( (adjc.x*cos(theta) - adjc.y*sin(theta))*frequency)*intensity; + } + return cos(col); +} + +void main(void) +{ + vec2 p = v_TexCoord, c1 = p, c2 = p; + float cc1 = col(c1); + + c2.x += u_Resolution.x/delta; + float dx = emboss*(cc1-col(c2))/delta; + + c2.x = p.x; + c2.y += u_Resolution.y/delta; + float dy = emboss*(cc1-col(c2))/delta; + + c1.x += dx; + c1.y += dy; + + float alpha = 1.+dot(dx,dy)*intence; + gl_FragColor = texture2D(u_Tex0,c1)*(alpha); +} diff --git a/modules/game_shaders/shaders/noise.frag b/modules/game_shaders/shaders/noise.frag new file mode 100644 index 00000000..48f4d71d --- /dev/null +++ b/modules/game_shaders/shaders/noise.frag @@ -0,0 +1,56 @@ +uniform sampler2D u_Tex0; +varying vec2 v_TexCoord; +uniform float u_Time; +uniform vec2 u_Resolution; +const float PI = 3.1415926535897932; + +// speed +const float speed = 0.16; +const float speed_x = 0.13; +const float speed_y = 0.12; + +// geometry +const float intensity = 100.; +const int steps = 3; +const float frequency = 100.0; +const int angle = 7; // better when a prime + +// reflection and emboss +const float delta = 1000.; +const float intence = 10.2; +const float emboss = 1.; + +//---------- crystals effect +float col(vec2 coord) +{ + float delta_theta = 2.0 * PI / float(angle); + float col = 0.0; + float theta = 0.0; + for(int i = 0; i < steps; i++) { + vec2 adjc = coord; + theta = delta_theta*float(i); + adjc.x += cos(theta)*u_Time*speed + u_Time * speed_x; + adjc.y -= sin(theta)*u_Time*speed - u_Time * speed_y; + col = col + cos( (adjc.x*cos(theta) - adjc.y*sin(theta))*frequency)*intensity; + } + return cos(col); +} + +void main(void) +{ + vec2 p = v_TexCoord, c1 = p, c2 = p; + float cc1 = col(c1); + + c2.x += u_Resolution.x/delta; + float dx = emboss*(cc1-col(c2))/delta; + + c2.x = p.x; + c2.y += u_Resolution.y/delta; + float dy = emboss*(cc1-col(c2))/delta; + + c1.x += dx; + c1.y += dy; + + float alpha = 1.+dot(dx,dy)*intence; + gl_FragColor = texture2D(u_Tex0,c1)*(alpha); +} diff --git a/modules/game_shaders/shaders/party.frag b/modules/game_shaders/shaders/party.frag index a3e801a3..bdf4ed77 100644 --- a/modules/game_shaders/shaders/party.frag +++ b/modules/game_shaders/shaders/party.frag @@ -5,9 +5,9 @@ varying vec2 v_TexCoord; void main() { vec4 col = texture2D(u_Tex0, v_TexCoord); - float d = u_Time * 2; + float d = u_Time * 2.0; col.x += (1.0 + sin(d))*0.25; - col.y += (1.0 + sin(d*2))*0.25; - col.z += (1.0 + sin(d*4))*0.25; + col.y += (1.0 + sin(d*2.0))*0.25; + col.z += (1.0 + sin(d*4.0))*0.25; gl_FragColor = col; } diff --git a/modules/game_shaders/shaders/radialblur.frag b/modules/game_shaders/shaders/radialblur.frag index b07301bc..c3b3e8c9 100644 --- a/modules/game_shaders/shaders/radialblur.frag +++ b/modules/game_shaders/shaders/radialblur.frag @@ -8,8 +8,7 @@ const float sampleStrength = 2.2; void main(void) { // some sample positions - float samples[10] = - float[](-0.08,-0.05,-0.03,-0.02,-0.01,0.01,0.02,0.03,0.05,0.08); + float samples[] = { -0.08,-0.05,-0.03,-0.02,-0.01,0.01,0.02,0.03,0.05,0.08 }; // 0.5,0.5 is the center of the screen // so substracting v_TexCoord from it will result in diff --git a/modules/game_textmessage/textmessage.otui b/modules/game_textmessage/textmessage.otui index 9eca1262..4e26dfbb 100644 --- a/modules/game_textmessage/textmessage.otui +++ b/modules/game_textmessage/textmessage.otui @@ -14,7 +14,7 @@ TopCenterLabel < UILabel anchors.top: parent.top anchors.bottom: centerTextMessagePanel.top anchors.horizontalCenter: parent.horizontalCenter - width: 360 + width: 275 BottomLabel < CenterLabel anchors.bottom: parent.bottom diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index fa25364a..5de06801 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -22,8 +22,7 @@ ELSE() SET(ARCH_FLAGS "-m32 -march=i686 -mtune=generic") ENDIF() SET(WARNS_FLAGS "-Wall -Wextra -Werror -Wno-unused-parameter -Wno-unused-but-set-variable") -SET(SECURE_FLAGS "-fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2") -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARNS} ${SECURE_FLAGS} ${ARCH_FLAGS} -std=gnu++0x -pipe") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARNS} ${ARCH_FLAGS} -std=gnu++0x -pipe") SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -ggdb") SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O1 -ggdb -fno-omit-frame-pointer") SET(CMAKE_CXX_FLAGS_RELEASE "-O2") diff --git a/src/framework/graphics/painter.cpp b/src/framework/graphics/painter.cpp index d92fad10..9b9bd449 100644 --- a/src/framework/graphics/painter.cpp +++ b/src/framework/graphics/painter.cpp @@ -60,6 +60,7 @@ void Painter::refreshState() void Painter::saveState() { assert(m_oldStateIndex<10); + m_olderStates[m_oldStateIndex].resolution = m_resolution; m_olderStates[m_oldStateIndex].projectionMatrix = m_projectionMatrix; m_olderStates[m_oldStateIndex].textureMatrix = m_textureMatrix; m_olderStates[m_oldStateIndex].color = m_color; @@ -69,7 +70,6 @@ void Painter::saveState() m_olderStates[m_oldStateIndex].shaderProgram = m_shaderProgram; m_olderStates[m_oldStateIndex].texture = m_texture; m_olderStates[m_oldStateIndex].alphaWriting = m_alphaWriting; - m_olderStates[m_oldStateIndex].resolution = m_resolution; m_oldStateIndex++; } @@ -82,6 +82,7 @@ void Painter::saveAndResetState() void Painter::restoreSavedState() { m_oldStateIndex--; + setResolution(m_olderStates[m_oldStateIndex].resolution); setProjectionMatrix(m_olderStates[m_oldStateIndex].projectionMatrix); setTextureMatrix(m_olderStates[m_oldStateIndex].textureMatrix); setColor(m_olderStates[m_oldStateIndex].color); @@ -90,7 +91,7 @@ void Painter::restoreSavedState() setClipRect(m_olderStates[m_oldStateIndex].clipRect); setShaderProgram(m_olderStates[m_oldStateIndex].shaderProgram); setTexture(m_olderStates[m_oldStateIndex].texture); - setResolution(m_olderStates[m_oldStateIndex].resolution); + setAlphaWriting(m_olderStates[m_oldStateIndex].alphaWriting); } void Painter::clear(const Color& color) diff --git a/src/framework/graphics/painter.h b/src/framework/graphics/painter.h index 9ba17f90..fdb69c99 100644 --- a/src/framework/graphics/painter.h +++ b/src/framework/graphics/painter.h @@ -44,6 +44,7 @@ public: }; struct PainterState { + Size resolution; Matrix3 projectionMatrix; Matrix3 textureMatrix; Color color; @@ -53,7 +54,6 @@ public: Texture *texture; PainterShaderProgram *shaderProgram; bool alphaWriting; - Size resolution; }; Painter(); diff --git a/src/framework/graphics/paintershadermanager.h b/src/framework/graphics/paintershadermanager.h deleted file mode 100644 index 5b011263..00000000 --- a/src/framework/graphics/paintershadermanager.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2010-2012 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 PAINTERSHADERMANAGER_H -#define PAINTERSHADERMANAGER_H - -#include "paintershaderprogram.h" - -class PainterShaderManager -{ -public: - void init(); - void terminate(); - - PainterShaderProgramPtr createShader(); - PainterShaderProgramPtr createTexturedFragmentShader(const std::string& shaderFile); - - const PainterShaderProgramPtr& getDrawTexturedProgram() { return m_drawTexturedProgram; } - const PainterShaderProgramPtr& getDrawSolidColorProgram() { return m_drawSolidColorProgram; } - -private: - PainterShaderProgramPtr m_drawTexturedProgram; - PainterShaderProgramPtr m_drawSolidColorProgram; -}; - -extern PainterShaderManager g_shaders; - -#endif diff --git a/src/framework/platform/win32window.cpp b/src/framework/platform/win32window.cpp index faa46fe6..d88fa9ef 100644 --- a/src/framework/platform/win32window.cpp +++ b/src/framework/platform/win32window.cpp @@ -205,6 +205,7 @@ void WIN32Window::init() internalCreateWindow(); internalCreateGLContext(); + internalRestoreGLContext(); } void WIN32Window::terminate() @@ -253,7 +254,7 @@ void WIN32Window::internalCreateWindow() wc.hInstance = m_instance; wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); wc.hCursor = m_defaultCursor; - wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = g_app->getName().c_str(); @@ -344,8 +345,6 @@ void WIN32Window::internalCreateGLContext() if(m_eglContext == EGL_NO_CONTEXT ) g_logger.fatal(stdext::format("Unable to create EGL context: %s", eglGetError())); - if(!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext)) - g_logger.fatal("Unable to make current EGL context"); #else uint pixelFormat; static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), @@ -374,9 +373,6 @@ void WIN32Window::internalCreateGLContext() if(!(m_wglContext = wglCreateContext(m_deviceContext))) g_logger.fatal("Unable to create GL context"); - - if(!wglMakeCurrent(m_deviceContext, m_wglContext)) - g_logger.fatal("Unable to set GLX context on WIN32 window"); #endif } @@ -406,6 +402,17 @@ void WIN32Window::internalDestroyGLContext() #endif } +void WIN32Window::internalRestoreGLContext() +{ +#ifdef OPENGL_ES + if(!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext)) + g_logger.fatal("Unable to make current EGL context"); +#else + if(!wglMakeCurrent(m_deviceContext, m_wglContext)) + g_logger.fatal("Unable to make current WGL context"); +#endif +} + bool WIN32Window::isExtensionSupported(const char *ext) { #ifdef OPENGL_ES @@ -707,6 +714,9 @@ LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar break; } + if(m_visible && m_deviceContext) + internalRestoreGLContext(); + Size size; size.setWidth(std::max(std::min((int)LOWORD(lParam), 7680), m_minimumSize.width())); size.setHeight(std::max(std::min((int)HIWORD(lParam), 4320), m_minimumSize.height())); diff --git a/src/framework/platform/win32window.h b/src/framework/platform/win32window.h index b456a3a3..9453561d 100644 --- a/src/framework/platform/win32window.h +++ b/src/framework/platform/win32window.h @@ -38,6 +38,7 @@ class WIN32Window : public PlatformWindow void internalCreateWindow(); void internalCreateGLContext(); void internalDestroyGLContext(); + void internalRestoreGLContext(); void *getExtensionProcAddress(const char *ext); bool isExtensionSupported(const char *ext); diff --git a/src/otclient/const.h b/src/otclient/const.h index 373db62d..de067a0b 100644 --- a/src/otclient/const.h +++ b/src/otclient/const.h @@ -50,7 +50,7 @@ namespace Otc INVISIBLE_TICKS_PER_FRAME = 500, ITEM_TICKS_PER_FRAME = 500, ANIMATED_TEXT_DURATION = 1000, - STATIC_DURATION_PER_CHARACTER = 75, + STATIC_DURATION_PER_CHARACTER = 60, MIN_STATIC_TEXT_DURATION = 3000, MAX_STATIC_TEXT_WIDTH = 200, }; diff --git a/src/otclient/core/mapview.cpp b/src/otclient/core/mapview.cpp index ec8088b7..dc9cded2 100644 --- a/src/otclient/core/mapview.cpp +++ b/src/otclient/core/mapview.cpp @@ -170,8 +170,8 @@ void MapView::draw(const Rect& rect) Position pos = staticText->getPosition(); // ony draw static texts from current camera floor, unless yells - if(pos.z != cameraPosition.z && !staticText->isYell()) - continue; + //if(pos.z != cameraPosition.z && !staticText->isYell()) + // continue; Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset; p.x = p.x * horizontalStretchFactor; diff --git a/src/otclient/core/shadermanager.cpp b/src/otclient/core/shadermanager.cpp index 88892a45..8aacdb57 100644 --- a/src/otclient/core/shadermanager.cpp +++ b/src/otclient/core/shadermanager.cpp @@ -49,7 +49,7 @@ void ShaderManager::terminate() PainterShaderProgramPtr ShaderManager::createShader(const std::string& name) { if(!g_graphics.canUseShaders()) { - g_logger.error(stdext::format("unable to create shader, shaders are not supported")); + g_logger.error(stdext::format("unable to create shader '%s', shaders are not supported", name)); return nullptr; } diff --git a/src/otclient/core/statictext.cpp b/src/otclient/core/statictext.cpp index 0092e71b..71e4ba56 100644 --- a/src/otclient/core/statictext.cpp +++ b/src/otclient/core/statictext.cpp @@ -40,50 +40,63 @@ void StaticText::draw(const Point& dest, const Rect& parentRect) boundRect.bind(parentRect); // draw only if the real center is not too far from the parent center, or its a yell - if((boundRect.center() - rect.center()).length() < parentRect.width() / 15 || isYell()) { + //if(g_map.isAwareOfPosition(m_position) || isYell()) { g_painter->setColor(m_color); m_cachedText.draw(boundRect); - } + //} } bool StaticText::addMessage(const std::string& name, Otc::SpeakType type, const std::string& message) { //TODO: this could be moved to lua - // First message + // first message if(m_messages.size() == 0) { m_name = name; m_messageType = type; } - else if(m_messages.size() > 20) { - // to many messages, ignore to avoid lag + // check if we can really own the message + else if(m_name != name || m_messageType != type) { return false; - } else { - // we can only add another message if it follows these conditions - if(m_name != name || m_messageType != type) - return false; + } + // too many messages + else if(m_messages.size() > 10) { + m_messages.pop_front(); + m_updateEvent->cancel(); + m_updateEvent = nullptr; } m_messages.push_back(message); compose(); - auto self = asStaticText(); - g_eventDispatcher.scheduleEvent([self]() { - self->removeMessage(); - }, std::max(Otc::STATIC_DURATION_PER_CHARACTER * message.length(), Otc::MIN_STATIC_TEXT_DURATION)); + if(!m_updateEvent) + scheduleUpdate(); return true; } -void StaticText::removeMessage() +void StaticText::update() { m_messages.pop_front(); - if(m_messages.empty()) { // schedule removal auto self = asStaticText(); g_eventDispatcher.addEvent([self]() { g_map.removeThing(self); }); - } else + } else { compose(); + scheduleUpdate(); + } +} + +void StaticText::scheduleUpdate() +{ + int len = m_messages.front().length(); + int delay = std::max(Otc::STATIC_DURATION_PER_CHARACTER * len, (int)Otc::MIN_STATIC_TEXT_DURATION); + + auto self = asStaticText(); + m_updateEvent = g_eventDispatcher.scheduleEvent([self]() { + self->m_updateEvent = nullptr; + self->update(); + }, delay); } void StaticText::compose() @@ -121,5 +134,5 @@ void StaticText::compose() } m_cachedText.setText(text); - m_cachedText.wrapText(Otc::MAX_STATIC_TEXT_WIDTH); + m_cachedText.wrapText(275); } diff --git a/src/otclient/core/statictext.h b/src/otclient/core/statictext.h index 93293823..66ae774e 100644 --- a/src/otclient/core/statictext.h +++ b/src/otclient/core/statictext.h @@ -26,6 +26,7 @@ #include "thing.h" #include #include +#include class StaticText : public Thing { @@ -41,12 +42,13 @@ public: bool isYell() { return m_messageType == Otc::SpeakYell || m_messageType == Otc::SpeakMonsterYell; } bool addMessage(const std::string& name, Otc::SpeakType type, const std::string& message); - void removeMessage(); StaticTextPtr asStaticText() { return std::static_pointer_cast(shared_from_this()); } bool isStaticText() { return true; } private: + void update(); + void scheduleUpdate(); void compose(); Boolean m_yell; @@ -55,6 +57,7 @@ private: Otc::SpeakType m_messageType; Color m_color; CachedText m_cachedText; + ScheduledEventPtr m_updateEvent; }; #endif