Castillo Posted May 27, 2012 Share Posted May 27, 2012 Hi everyone. I've been working on an Announcement box script, but I have a big problem, if the messages are too long, it'll start on another line, but now the problem comes when you send another message, it'll mess with the previous one. Part of script: if ( messages [ #messages ] ) then y = messages [ #messages ] [ "y" ] else y = originalY end local numLines = math.floor ( ( dxGetTextWidth ( text, 1, "default-bold" ) / 370 ) + 1 ) local height = ( dxGetFontHeight ( 1, "default-bold" ) + 3 ) local y = ( y + height + numLines ) Screenshot of the problem: If someone could find a way to fix this, I'll be very thankful. Thanks in advance. Link to comment
myonlake Posted May 27, 2012 Share Posted May 27, 2012 I know this sounds a little weird, but are you able to add some kind of data on the message to mark it as a longer message, and if it's a longer message, the next message will be sent one line lower? I know, it sounds pretty lame and unofficial fix but yeah. Link to comment
Edikosh998 Posted May 27, 2012 Share Posted May 27, 2012 I know this sounds a little weird, but are you able to add some kind of data on the message to mark it as a longer message, and if it's a longer message, the next message will be sent one line lower? I know, it sounds pretty lame and unofficial fix but yeah. I was going to say the same. Like using a "string.len" function. PD : Castillo asking something on the scripting forum Link to comment
Kenix Posted May 27, 2012 Share Posted May 27, 2012 (edited) function string.transfer( s, nMax ) if type( s ) == 'string' and type( nMax ) == 'number' then local nMaxOld = nMax local nLength = #s -- change to utfLen( s ) if you working with unicode. if nLength >= nMax then local sNew = '' local nStart = 0 for nCount = 1, math.ceil( nLength / nMax ) do sNew = sNew .. '\n'.. s:sub( nStart + 1, nMax ) nStart = nMax nMax = nMax + nMaxOld end return sNew:sub( 2, #sNew ) -- -- change #sNew to utfLen( sNew ) if you working with unicode. end return s end return false end print( string.transfer( '123456', 2 ) ) --[[ 12 34 56 ]] ? Edited June 8, 2012 by Guest Link to comment
CapY Posted May 27, 2012 Share Posted May 27, 2012 but now the problem comes when you send another message, it'll mess with the previous one. Mind adding the timers? Link to comment
Kenix Posted May 27, 2012 Share Posted May 27, 2012 Solidsnake14 Can you upload your resource? I test and fix. Link to comment
Castillo Posted May 27, 2012 Author Share Posted May 27, 2012 @myonlake: You mean split the whole string and send it as many messages? if so, then I already had that idea and didn't work either. @CapY: Why would I use timers? @Kenix: I didn't post the whole code because it was not required, that part of script is the part which fails. Link to comment
CapY Posted May 27, 2012 Share Posted May 27, 2012 @CapY: Why would I use timers? To not to mess the whole thing up. Link to comment
Castillo Posted May 27, 2012 Author Share Posted May 27, 2012 You don't understand how it works, the problem is the HEIGHT of the word wrapped texts. Link to comment
Kenix Posted May 27, 2012 Share Posted May 27, 2012 (edited) @Kenix: I didn't post the whole code because it was not required, that part of script is the part which fails. If you not want fix. Okay .. Better council. Check variables height, numLines, .. Edited May 27, 2012 by Guest Link to comment
Castillo Posted May 27, 2012 Author Share Posted May 27, 2012 I'm not one of these who ask for the script done, if you tell me how you think I can fix it. Edit: I've edited the function you've posted Kenix, and made it to use a table instead: function string.transfer ( s, nMax ) if ( type ( s ) == 'string' ) and ( type ( nMax ) == 'number' ) then local stringsTable = { } local nMaxOld = nMax local nLength = #s -- change to utfLen( s ) if you working with unicode. if ( nLength >= nMax ) then local nStart = 0 for nCount = 1, math.ceil ( nLength / nMax ) do table.insert ( stringsTable, s:sub ( nStart + 1, nMax ) ) nStart = nMax nMax = ( nMax + nMaxOld ) end return stringsTable end return s end return false end local stringT = string.transfer ( text, 45 ) if ( type ( stringT ) ~= "table" ) then local y = ( originalY + 18 * #messages ) table.insert ( messages, { [ "text" ] = text, [ "y" ] = y, [ "r" ] = r, [ "g" ] = g, [ "b" ] = b, [ "addTime" ] = getTickCount ( ), [ "table" ] = formatTable } ) else for index, msg in ipairs ( stringT ) do local y = ( originalY + 18 * #messages ) table.insert ( messages, { [ "text" ] = msg, [ "y" ] = y, [ "r" ] = r, [ "g" ] = g, [ "b" ] = b, [ "addTime" ] = getTickCount ( ), [ "table" ] = formatTable } ) end end That kinda fixed the problem, but now I got this new issue: As you can see, there is one extra text, it should only support 6. Link to comment
Kenix Posted May 27, 2012 Share Posted May 27, 2012 As you can see, there is one extra text, it should only support 6. Write number string like 123456 ... and test again and you can see this more good. This function should transfer string. Link to comment
Castillo Posted May 27, 2012 Author Share Posted May 27, 2012 What? that doesn't help. Link to comment
Cadu12 Posted May 27, 2012 Share Posted May 27, 2012 Kenix, I guess he want LONG STRING. Solidsnake14, edit string.transfer a bit, add return how much "/n" or numLines. Link to comment
Castillo Posted May 27, 2012 Author Share Posted May 27, 2012 I already have a way to get the total lines the string will use, I just need a way to make it work without bug. Edit: Kenix, the function: string.transfer only works with character len, but that doesn't work for this I noticed, I would need a function that divides text by width. Link to comment
Cadu12 Posted May 27, 2012 Share Posted May 27, 2012 (edited) function fixBug() if ( #messages >= 6 ) then table.remove( messages, 1 ) fixBug ( ) end end local stringT = string.transfer ( text, 45 ) if ( type ( stringT ) ~= "table" ) then local y = ( originalY + 18 * #messages ) table.insert ( messages, { [ "text" ] = text, [ "y" ] = y, [ "r" ] = r, [ "g" ] = g, [ "b" ] = b, [ "addTime" ] = getTickCount ( ), [ "table" ] = formatTable } ) fixBug ( ) else for index, msg in ipairs ( stringT ) do local y = ( originalY + 18 * #messages ) table.insert ( messages, { [ "text" ] = msg, [ "y" ] = y, [ "r" ] = r, [ "g" ] = g, [ "b" ] = b, [ "addTime" ] = getTickCount ( ), [ "table" ] = formatTable } ) fixBug ( ) end end Try use, I didnt tested yet. Edited May 28, 2012 by Guest Link to comment
Castillo Posted May 28, 2012 Author Share Posted May 28, 2012 Sorry, but I already done something similar. At start of function: local numLines = math.floor ( ( dxGetTextWidth ( text, 1, "default-bold" ) / 370 ) + 1 ) if ( #messages >= 6 ) then local extraLines = ( 6 - #messages + numLines ) for line = 1, extraLines do table.remove ( messages, line ) end end At end of function: for index, msg in ipairs ( messages ) do local index = ( index - 1 ) msg [ "y" ] = ( originalY + 18 * index ) end Link to comment
Cadu12 Posted May 28, 2012 Share Posted May 28, 2012 Try copy my code again, I missed one and fixed one line Link to comment
Castillo Posted May 28, 2012 Author Share Posted May 28, 2012 I've built my own function to split the string by width, but it fails at second line for some reason: Source: function string.split ( text, maxWidth ) local oldlen = 1 local len = 1 local width = 0 local strings = { } for i = 1, text:len ( ) do width = ( width + dxGetTextWidth ( string.char ( text:byte ( i ) ), 1, "default-bold" ) ) if ( width > maxWidth ) then table.insert ( strings, text:sub ( oldlen, len ) ) oldlen = len width = 0 end len = i end if ( #strings == 0 ) then return text else return strings end end Screenshot of the problem: As you can see, there are some letters outside the rectangle. Link to comment
Cadu12 Posted May 28, 2012 Share Posted May 28, 2012 function outputBox( s, nMax ) if type( s ) == 'string' and type( nMax ) == 'number' then local nMaxOld = nMax local nLength = #s if nLength >= nMax then local sNew = '' local nStart = 0 for nCount = 1, math.ceil( nLength / nMax ) do local y = ( originalY + 18 * #messages ) table.insert ( messages, { [ "text" ] = s:sub( nStart + 1, nMax ), [ "y" ] = y, [ "r" ] = r, [ "g" ] = g, [ "b" ] = b, [ "addTime" ] = getTickCount ( ), [ "table" ] = formatTable } ) nStart = nMax nMax = nMax + nMaxOld end local y = ( originalY + 18 * #messages ) table.insert ( messages, { [ "text" ] = sNew:sub( 2, #sNew ), [ "y" ] = y, [ "r" ] = r, [ "g" ] = g, [ "b" ] = b, [ "addTime" ] = getTickCount ( ), [ "table" ] = formatTable } ) end local y = ( originalY + 18 * #messages ) table.insert ( messages, { [ "text" ] = s, [ "y" ] = y, [ "r" ] = r, [ "g" ] = g, [ "b" ] = b, [ "addTime" ] = getTickCount ( ), [ "table" ] = formatTable } ) end end I edited that function, try use function. I can't test for now. outputBox("ASDASDASDASDASDASDDDDDDDDDDDDDAAAAAAASDASDASDASDASDASDASDASDASDASDASASDASDASDASDAS", 45) Link to comment
Castillo Posted May 28, 2012 Author Share Posted May 28, 2012 I don't need that, I need a fix for the function: string.split. Link to comment
50p Posted May 28, 2012 Share Posted May 28, 2012 If you use dxDrawText, why don't you use wordBreak parameter? Link to comment
Castillo Posted May 28, 2012 Author Share Posted May 28, 2012 I've used the wordWrap parameter of dxDrawText, but then if I send another message, it'll appear down the old one. Link to comment
50p Posted May 28, 2012 Share Posted May 28, 2012 Split the string by words. The method you us to split string is OK but it will cut words half way if it's too long or 2 letter words will split and you will end up with 1 letter on 1 line and another on the next line. You can use MTA native split function. Link to comment
AGENT_STEELMEAT Posted May 28, 2012 Share Posted May 28, 2012 (edited) Sad to see that most of the people that try to help on this forum are all idiots. How unfortunate. Anyway - this uses dxDrawText's wordBreak parameter to wrap the text, and the clip parameter to stop it from drawing outside the box. It might need some tweaking to suit your needs, but the basics are there. -- Basic constants local SCREEN_WIDTH, SCREEN_HEIGHT = guiGetScreenSize() local BOX_LEFT, BOX_TOP = (SCREEN_WIDTH/2) - 150, (SCREEN_HEIGHT/2) - 150 local BOX_WIDTH, BOX_HEIGHT = 300, 300 local BOX_COLOR = tocolor(0, 0, 0, 200) local FONT_HEIGHT, EXPIRE_TIME = dxGetFontHeight(1, "default-bold"), 15000 -- Table of all notifications local g_notifications = {} -- Adds a notification to the notification list function addNotification(message, r, g, b) if type(message) ~= "string" then error("Invalid argument(s) to addNotification() [expected string at argument 1]!", 2); end if type(r) ~= "number" then r = 255 g = 255 b = 255 end -- If 5 notifications already exist, remove the oldest one -- If this is the first notification, call addEventHandler if #g_notifications >= 5 then table.remove(g_notifications) elseif #g_notifications <= 0 then addEventHandler("onClientRender", root, drawNotifications) end -- Determine the height of this notification local notificationWidth = dxGetTextWidth(message, 1, "default-bold") local numLines = math.ceil(notificationWidth / BOX_WIDTH) local notificationHeight = (FONT_HEIGHT + 1) * numLines -- Insert the new notification at beginning of table (it will be drawn at the top of the box) table.insert(g_notifications, 1, {message, tocolor(r, g, b), getTickCount(), notificationHeight}) end -- Draws the notifications function drawNotifications() -- Draw the base rectangle dxDrawRectangle(BOX_LEFT, BOX_TOP, BOX_WIDTH, BOX_HEIGHT, BOX_COLOR) -- Track the top of the notification and the current tick count local notificationTop = BOX_TOP + 2 local thisTick = getTickCount() for i, notification in ipairs(g_notifications) do -- Remove this notification if it is expired -- If there are no more notifications, call removeEventHandler if thisTick - notification[3] >= EXPIRE_TIME then table.remove(g_notifications, i) if #g_notifications <= 0 then removeEventHandler("onClientRender", root, drawNotifications) return end else -- Draw this notification, and increment notificationTop so we can draw the next one under it dxDrawText(notification[1], BOX_LEFT, notificationTop, BOX_LEFT + BOX_WIDTH, BOX_TOP + BOX_HEIGHT, notification[2], 1, "default-bold", "left", "top", true, true) notificationTop = notificationTop + notification[4] + 2 end end end GET ON MY LEVEL. Edited May 28, 2012 by Guest Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now