• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[System] [Needs fix] Align Message

Level 7
Joined
Apr 30, 2011
Messages
359
JASS:
//========================================================================================
//      
//      Align Message
//      -*- overcold_ice -*-
//      
//     -[*] Requirements:
//          - JNGP
//          - latest version of JassHelper
//          - Ascii
//              [url]http://www.hiveworkshop.com/forums/jass-resources-412/snippet-ascii-190746/[/url]
//      
//          Provides functions to align text in game messages
//      
//     -[*] API:
//      
//      constant real MSG_X_LEFT        = 0
//      constant real MSG_X_CENTER      = 0.46
//      constant real MSG_X_RIGHT       = 0.67
//          x-coordinate constants used to position the block of game messages horizontally
//      
//      constant real FULL_MSG_Y_TOP    = 0.3
//      constant real FULL_MSG_Y_MIDDLE = 0.15
//      constant real FULL_MSG_Y_BOTTOM = 0
//          y-coordinate constants used to position the block of game messages vertically
//          will only work for messages with full lines (16 lines),
//          except for FULL_MSG_Y_BOTTOM
//      
//      constant real MSG_LINE_HEIGHT   = 0.0675
//          height of a line in message's y-coordinate
//      
//      function GetMessageAlignLeft takes string Message returns string
//      function GetMessageAlignCenter takes string Message returns string
//      function GetMessageAlignRight takes string Message returns string
//      function GetMessageJustify takes string Message returns string
//          used for horizontal alignment
//          will automatically break the lines if it exceed the limit
//      
//      function GetMessageAlignTop takes string Message returns string
//      function GetMessageAlignMiddle takes string Message returns string
//      function GetMessageAlignBottom takes string Message returns string
//          used for vertical alignment
//          returns the original string if it has 16 lines or more
//          will automatically break the lines if it exceed the limit
//      
//      function GetMessageYTop takes string Message returns real
//      function GetMessageYMiddle takes string Message returns real
//      function GetMessageYBottom takes nothing returns real
//          the first two of them will return an exact y-coordinate to position the
//          message block based on string Message
//          the last of them will inline to FULL_MSG_Y_BOTTOM
//      
//========================================================================================
library AlignMessage requires Ascii
    
    //====================================================================================
    //  C A L I B R A T I O N  S E C T I O N
    //====================================================================================
    globals
        //  Configurable
        private constant real UNKNOWN_CHAR_SIZE = 0.010966167
        
        // Constants
                constant real MSG_X_LEFT        = 0
                constant real MSG_X_CENTER      = 0.46
                constant real MSG_X_RIGHT       = 0.76
                
                constant real FULL_MSG_Y_TOP    = 0.3
                constant real FULL_MSG_Y_MIDDLE = 0.15
                constant real FULL_MSG_Y_BOTTOM = 0
                
                constant real MSG_LINE_HEIGHT   = 0.0675
    endglobals
    //====================================================================================
    
    globals
        private real array CharSize
    endglobals
    
    private module Init
        private static method onInit takes nothing returns nothing
            set CharSize ['A'] = 0.015288462
            set CharSize ['B'] = 0.012268519
            set CharSize ['C'] = 0.013802083
            set CharSize ['D'] = 0.015288462
            set CharSize ['E'] = 0.012268519
            set CharSize ['F'] = 0.009287383
            set CharSize ['G'] = 0.015288462
            set CharSize ['H'] = 0.015288462
            set CharSize ['I'] = 0.006172360
            set CharSize ['J'] = 0.006172360
            set CharSize ['K'] = 0.013802083
            set CharSize ['L'] = 0.010801630
            set CharSize ['M'] = 0.019875000
            set CharSize ['N'] = 0.015288462
            set CharSize ['O'] = 0.016843220
            set CharSize ['P'] = 0.012268519
            set CharSize ['Q'] = 0.018402778
            set CharSize ['R'] = 0.013802083
            set CharSize ['S'] = 0.012268519
            set CharSize ['T'] = 0.010801630
            set CharSize ['U'] = 0.015288462
            set CharSize ['V'] = 0.013802083
            set CharSize ['W'] = 0.021603261
            set CharSize ['X'] = 0.015288462
            set CharSize ['Y'] = 0.013802083
            set CharSize ['Z'] = 0.013802083
            
            set CharSize ['a'] = 0.010801630
            set CharSize ['b'] = 0.012268519
            set CharSize ['c'] = 0.010801630
            set CharSize ['d'] = 0.012268519
            set CharSize ['e'] = 0.012268519
            set CharSize ['f'] = 0.007703488
            set CharSize ['g'] = 0.013802083
            set CharSize ['h'] = 0.012268519
            set CharSize ['i'] = 0.004643692
            set CharSize ['j'] = 0.006172360
            set CharSize ['k'] = 0.010801630
            set CharSize ['l'] = 0.004643692
            set CharSize ['m'] = 0.018402778
            set CharSize ['n'] = 0.012268519
            set CharSize ['o'] = 0.012268519
            set CharSize ['p'] = 0.012268519
            set CharSize ['q'] = 0.012268519
            set CharSize ['r'] = 0.007703488
            set CharSize ['s'] = 0.009287383
            set CharSize ['t'] = 0.007703488
            set CharSize ['u'] = 0.012268519
            set CharSize ['v'] = 0.012268519
            set CharSize ['w'] = 0.016843220
            set CharSize ['x'] = 0.012268519
            set CharSize ['y'] = 0.012268519
            set CharSize ['z'] = 0.010801630
            
            set CharSize [' '] = 0.006172360
            set CharSize ['!'] = 0.004643692
            set CharSize ['"'] = 0.006172360
            set CharSize ['#'] = 0.013802083
            set CharSize ['$'] = 0.010801630
            set CharSize ['%'] = 0.015288462
            set CharSize ['&'] = 0.016843220
            set CharSize [ 39] = 0.003095794
            set CharSize ['('] = 0.006172360
            set CharSize [')'] = 0.006172360
            set CharSize ['*'] = 0.009287383
            set CharSize ['+'] = 0.010801630
            set CharSize [','] = 0.004643692
            set CharSize ['-'] = 0.007703488
            set CharSize ['.'] = 0.004643692
            set CharSize ['/'] = 0.009287383
            set CharSize ['0'] = 0.012268519
            set CharSize ['1'] = 0.004643692
            set CharSize ['2'] = 0.012268519
            set CharSize ['3'] = 0.012268519
            set CharSize ['4'] = 0.013802083
            set CharSize ['5'] = 0.012268519
            set CharSize ['6'] = 0.012268519
            set CharSize ['7'] = 0.010801630
            set CharSize ['8'] = 0.012268519
            set CharSize ['9'] = 0.012268519
            set CharSize [':'] = 0.004643692
            set CharSize [';'] = 0.004643692
            set CharSize ['<'] = 0.010801630
            set CharSize ['='] = 0.010801630
            set CharSize ['>'] = 0.010801630
            set CharSize ['?'] = 0.010801630
            set CharSize ['@'] = 0.015288462
            set CharSize ['['] = 0.006172360
            set CharSize [ 92] = 0.007703488
            set CharSize [']'] = 0.006172360
            set CharSize ['^'] = 0.010801630
            set CharSize ['_'] = 0.010801630
            set CharSize ['`'] = 0.007703488
            set CharSize ['{'] = 0.006172360
            set CharSize ['|'] = 0.004643692
            set CharSize ['}'] = 0.006172360
            set CharSize ['~'] = 0.010801630
        endmethod
    endmodule
    
    private struct Implementer
        implement Init
    endstruct
    
    private function IsColorCode takes string s returns boolean
        local integer l = 1
        local integer i = Char2Ascii(StringCase(SubString(s, 0, 1), false))
        
        if i != 99 then
            return false
        endif
        
        loop
            exitwhen l == 9
            
            set i = Char2Ascii(StringCase(SubString(s, l, l + 1), false))
            
            if (i < 48 or i > 57) and (i < 97 or i > 102) then
                return false
            endif
            
            set l = l + 1
        endloop
        
        return true
    endfunction
    
    private function GetStringSize takes string s returns real
        local integer sl = StringLength(s)
        local string  ss = ""
        local integer l  = 0
        local real    r  = 0
        
        loop
            exitwhen l == sl
            
            set ss = SubString(s, l, l + 1)
            
            if ss == "|" then
                set ss = SubString(s, l + 1, l + 2)
                
                if IsColorCode(SubString(s, l + 1, l + 10)) then
                    set l = l + 9
                elseif StringCase(ss, false) == "r" then
                    set l = l + 1
                elseif ss == "|" then
                    set l = l + 1
                    set r = r + CharSize ['|']
                else
                    set r = r + CharSize ['|']
                endif
            elseif CharSize [Char2Ascii(ss)] != 0 then
                set r = r + CharSize [Char2Ascii(ss)]
            else
                set r = r + UNKNOWN_CHAR_SIZE
            endif
            
            set l = l + 1
        endloop
        
        return r
    endfunction
    
    private function GetSpacing takes integer n returns string
        local string r = ""
        
        loop
            exitwhen n == 0
            
            set r = r + " "
            
            set n = n - 1
        endloop
        
        return r
    endfunction
    
    private function GetLineAlignLeft takes string s returns string
        loop
            exitwhen SubString(s, 0, 1) != " "
            
            set s = SubString(s, 1, StringLength(s))
        endloop
        
        return s
    endfunction
    
    private function GetLineAlignCenter takes string s returns string
        return GetSpacing(R2I((1 - GetStringSize(s)) / (2 * CharSize [' ']))) + GetLineAlignLeft(s)
    endfunction
    
    private function GetLineAlignRight takes string s returns string
        return GetSpacing(R2I((1 - GetStringSize(s)) / CharSize [' '])) + GetLineAlignLeft(s)
    endfunction
    
    private function GetLineJustify takes string s returns string
        local integer ns = R2I((1 - GetStringSize(s)) / CharSize [Char2Ascii(" ")])
        local integer sl = StringLength(s) - 1
        local integer sc = R2I(sl / ns)
        local integer l  = 0
        local string  r  = ""
        
        if sc == 0 then
            return s
        endif
        
        loop
            exitwhen l == sl or ns == 0
            
            if ns < sc then
                set sc = ns
            endif
            
            set r = r + SubString(s, l, l + 1) + GetSpacing(sc)
            
            set l = l + 1
        endloop
        
        set r = r + SubString(s, sl, sl + 1)
        
        return r
    endfunction
    
    globals
        private string array Line
        private integer      LineCount
    endglobals
    
    private function BreakString takes string s returns nothing
        local integer sl = StringLength(s)
        local integer ls = 0
        local string  ss = ""
        local real    r  = 0
        local integer l  = 0
        
        set LineCount = 0
        
        loop
            exitwhen l == sl
            
            set ss = SubString(s, l, l + 1)
            
            if ss == "|" then
                set ss = SubString(s, l + 1, l + 2)
                
                if IsColorCode(SubString(s, l + 1, l + 10)) then
                    set l = l + 9
                elseif StringCase(ss, false) == "r" then
                    set l = l + 1
                elseif ss == "|" then
                    set l = l + 1
                    set r = r + CharSize ['|']
                else
                    set r = r + CharSize ['|']
                endif
            elseif StringCase(SubString(s, l, l + 2), false) == "\n" then
                set LineCount = LineCount + 1
                set Line [LineCount] = SubString(s, ls, l)
                set l  = l + 2
                set ls = l
                set r  = 0
            else
                set r = r + GetStringSize(ss)
            endif
            
            if r > 1 then
                set LineCount = LineCount + 1
                set Line [LineCount] = SubString(s, ls, l)
                set ls = l
                set r  = 0
            endif
            
            set l = l + 1
        endloop
    endfunction
    
    private function GetLineBreak takes integer n returns string
        local string r = ""
        
        loop
            exitwhen n == 0
            
            set r = r + "\n"
            
            set n = n - 1
        endloop
        
        return r
    endfunction
    
    //====================================================================================
    //  A P I
    //====================================================================================
    function GetMessageAlignBottom takes string s returns string
        local integer l = 0
        
        call BreakString(s)
        set s = ""
        
        loop
            exitwhen GetLineAlignLeft(Line [LineCount]) != ""
            set LineCount = LineCount - 1
        endloop
        
        loop
            set l = l + 1
            
            if l == LineCount then
                set s = s + Line [l]
                
                exitwhen true
            else
                set s = s + Line [l] + "\n"
            endif
        endloop
        
        return s
    endfunction
    
    function GetMessageAlignMiddle takes string s returns string
        local integer nb = 0
        
        call BreakString(GetMessageAlignBottom(s))
        
        if LineCount >= 16 then
            return s
        endif
        
        set nb = (16 - LineCount) / 2
        
        if nb == 0 then
            return s
        endif
        
        return GetMessageAlignBottom(s) + GetLineBreak(nb)
    endfunction
    
    function GetMessageAlignTop takes string s returns string
        local integer nb = 0
        
        call BreakString(GetMessageAlignBottom(s))
        
        if LineCount >= 16 then
            return s
        endif
        
        set nb = (16 - LineCount)
        
        return GetMessageAlignBottom(s) + GetLineBreak(nb)
    endfunction
    
    //! textmacro AlignMessage___CreateAPI takes FUNC
        function GetMessage$FUNC$ takes string s returns string
            local integer l = 0
            
            call BreakString(s)
            set s = ""
            
            loop
                set l = l + 1
                
                if l == LineCount then
                    set s = s + GetLine$FUNC$(Line [l])
                    
                    exitwhen true
                else
                    set s = s + GetLine$FUNC$(Line [l]) + "\n"
                endif
            endloop
            
            return s
        endfunction
    //! endtextmacro
    
    //! runtextmacro AlignMessage___CreateAPI("AlignLeft")
    //! runtextmacro AlignMessage___CreateAPI("AlignCenter")
    //! runtextmacro AlignMessage___CreateAPI("AlignRight")
    //! runtextmacro AlignMessage___CreateAPI("Justify")
    
    function GetMessageYTop takes string s returns real
        call BreakString(s)
        
        return FULL_MSG_Y_TOP + (16 - LineCount) * MSG_LINE_HEIGHT
    endfunction
    
    function GetMessageYMiddle takes string s returns real
        call BreakString(s)
        
        return FULL_MSG_Y_MIDDLE + (16 - LineCount) * MSG_LINE_HEIGHT / 2
    endfunction
    
    function GetMessageYBottom takes nothing returns real
        return FULL_MSG_Y_BOTTOM
    endfunction
    //====================================================================================
endlibrary
 
Last edited:
Level 7
Joined
Apr 30, 2011
Messages
359
i'll test it when i got time . . . .
are there anything wrong with my script ?_?

aren't using ascii will be the same with using StringHash ?
JASS:
//  assign real
set CharSize ['A'] = 0.02061788
//  get it
. . . . . CharSize[S2A(s)] . . . . .
 
This system is very neatly written, which is nice. However there are a few things to change:

  • There are several characters that are left out. I suppose they are less necessary, but symbols such as "?", "(", ")", apostrophes/quotations, colons, +/-, and the symbols above numbers 1-8. Those are frequently used by maps and could cause some problems with the system.
  • How did you measure the characters? Just curious.
  • Even though it leads to less customizability, you should write the string hash equivalents instead of the functions so it will reduce the required operations. (you can just put a comment next to each one that lists the character it is corresponding to)
  • If I recall correctly, if someone inputs something such as |c and then a symbol afterward other than a-f/0-9, such as "g", your system will bug. It isn't exactly necessary to cover those weird cases, just letting you know. :)
  • That string hash problem would be best fixed with using the ascii library, as mag and bribe have said.

There were probably more things I wanted to mention but I forgot. Anyway, I recommend you give a test map and test the system thoroughly, because these kinds of systems can easily bug out.

Nice job on the neatness though, it definitely looks better than my versions. If you need to take a look at them, they can be found here:
http://www.hiveworkshop.com/forums/1886277-post378.html
http://www.hiveworkshop.com/forums/1889717-post379.html

They work well, but I never formally submitted them since I didn't put enough optimization into it. I just posted it for whoever might need it since there weren't really any equivalent systems that still worked.

Good luck.
 
Level 7
Joined
Apr 30, 2011
Messages
359
i have said to update this when i got time . . .
(which isn't too long enough)

those was discovered by Anitarf, but i'm not pretty sure about it . . .
i'll redo those values, by my own research . . . .

thanks purge, for the GL, and some praises to me :)
heheh~

btw, i'll going to use the message block's width to calculate the char's width . .
JASS:
set CharSize ['A'] = 0.025076923
//  have been tested, from:
//  set CharSize ['A'] = 1.63 / 65
//  1.63 = Game Message Block's width
//  65 = max amount of A in a line

My Research
and purge, do you know more things about char width . . . ?
i need it for my upcoming resource . . .
which needs char width related to multiboard width,
i can research it myself, but if you know something,
that would shorten my time ^_^

edit: Another Discovery

edit: updated . . .
not yet tested the demo map, but please try . . .
(please read the Demo script by yourself ^_^)
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Hm... when I've used % in save/load, I haven't had problems with it, but I will verify that it is used to display variables (which is typical in other languages) ^)^.

edit
so I investigated your problem and it arose because you apparently don't know how to use SubString ;p.


% is fine.


I thought that this was suspicious since I have never had problems with % in the past.
 
Last edited:
Level 7
Joined
Apr 30, 2011
Messages
359
@nes:
i know how to use SubString -_-

updated . . .
fixed all values there, but have a big bug (still)
it broke other scripts :(
i have tried to do things 'not' related to the system, and almost nothing happens when i test it . . .
can someone figure what thing that make this happens ?_?
(i'm guessing that lengthy numbers, what are their limit for decimal?)
 
9 decimal places is the maximum.

Nestharus, it's not overlord, it's overcold :p
I thought his name was overlord for 2 weeks until I reread his name one day ^-^

JASS:
    private function GetSpacing takes integer n returns string
        local string r
        
        loop
            exitwhen n == 0
            
            set r = r + " "
            
            set n = n - 1
        endloop
        
        return r
    endfunction

->

JASS:
    private function GetSpacing takes integer n returns string
        local string r = ""
        loop
            exitwhen n == 0
            set r = r + " "
            set n = n - 1
        endloop
        return r
    endfunction

Because with your function, GetSpacing(0) will stop the thread since the variable is uninitialized.
 
JASS:
            set ss = StringCase(SubString(s, l, l + 1), false)
            
            if ss != "0" or ss != "1" or ss != "2" or ss != "3" or /*
            */ ss != "4" or ss != "5" or ss != "6" or ss != "7" or /*
            */ ss != "8" or ss != "9" or ss != "a" or ss != "b" or /*
            */ ss != "c" or ss != "d" or ss != "e" or ss != "f" then
                return false
            endif

Those should be and instead of or otherwise it won't work. However, you can instead just do:
JASS:
    set i = Char2Ascii(ss)
    if (a > 64 and a < 71) or (a > 96 and a < 103) or (a > 47 and a < 58) then

That will check if it is any character from "a" to "f", from "A" to "F", and from "0" to "9".

Good job so far though, the system is looking great.
 
Level 7
Joined
Apr 30, 2011
Messages
359
huh . . . greatly updated!

but, please check this test map and post what causing this error ~.~
 

Attachments

  • Align Message.w3x
    30.2 KB · Views: 46
Top