HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Breaking the TextTag Limit

01-13-2009, 09:18 AM#1
Pyrogasm
So I thought of a way to break the 99 texttag limit today. Since they're pseudo-handles they can essentially be manipulated any which way by GetLocalPlayer() if-blocks without risk of a desynch. What this lead me to think about was using a texttag locally for each player that you want to show it for. So instead of using five whole texttag to display "Aweseome!" to Player 1, "Press the right arrow key" to Player 2" and "Watch as the duel commences" to Players 3, 4, and 5 the way texttags are normally done, you could display all of those messages using only a single texttag.

The limit is, of course, that the maximum number of messages you are able to display is 99*<number of players in the map>, and still no player can see more than 99 texttags at any given time. However, take a map that uses texttags to show unit taunts for the opposing team (such as in Rising_Dusk's AotZ), the description for an item currently being tempered at a player's altar, and for a few spells on the map that show text for the casting player as an example.

Because all of the taunts on the map are only shown for half of the players, the number of texttag taunts increases from a cap of 99 to a cap of 198 (though still 99 for each player). Whereas all of the item tempering would take up 12 texttags, using this system you would only need 1 texttag. And for the spells that use texttags; assume the mapmaker has judged there to be a maximum of 15 different texttags from spells at any given time. Thus, the number of texttags required for the bare minimum of the map has been reduced from 27 to 3, and the cap for the number of unit-saying texttags has increased from 72 to 162.


Maybe none of what I said makes any sense to you, in which case you should take a look at the code and see if that gets my idea across. At any rate, I thought this up and started writing a system to handle this; I haven't finished yet, nor have I even syntax checked the part I have written, but I think the barebones are there and enough to make the system understandable.

Collapse JASS:
library MultiTags initializer Init
    globals
        //Max texttags from this system is USED_TEXTTAG_AMOUNT*<Players in map>
        //Max shown for any one player at any time is still USED_TEXTTAG_AMOUNT, though
        private constant integer USED_TEXTTAG_AMOUNT = 99
        private constant real    TIMER_UPDATE_PERIOD = 0.10
    endglobals

    globals
        public texttag array TT
        private timer PTimer = null
        private integer PCount = 0
        keyword MultiTag
        private keyword TagSeparator
        private MultiTag array PTags
        private TagSeparator array Separators

        private player LocalPlayer
    endglobals

    private function NewParent takes integer PId, MultiTag MT returns TagSeparator
        local integer J = 0

        loop
            if not(Separators[J].Used[PId]) then
                set Separators[J].Used[PId] = true
                set Separators[J].References[PId] = MT
                return Separators[J]
            endif
            set J = J+1
            exitwhen J > USED_TEXTTAG_AMOUNT
        endloop

        debug call BJDebugMsg("MultiTags Warning: Could not allocate new parent for Player("+I2S(PId)+")! You've surpassed the new limit... Returning -1")
        return -1
    endfunction

    private function Periodic takes nothing returns nothing
        
    endfunction

    private struct TagSeparator
        integer Index = 0
        boolean array Used[12]
        MultiTag array References[12]

        static method create takes integer Index returns nothing
            local TagSeparator TS = TagSeparator.allocate()
            local integer J = 0

            set TS.Index = Index
            loop
                set TS.Used[J] = false
                set TS.References[12] = 0
                set J = J+1
                exitwhen J > 11
            endloop

            return TS
        endmethod
    endstruct

    struct MultiTag
        string Text = ""
        real Height = 0.00
        real XCoord = 0.00
        real YCoord = 0.00
        integer Red = 0
        integer Green = 0
        integer Blue = 0
        integer Alpha = 0
        real LifeSpan = 0.00

        private TagSeparator array Parents[12]
        readonly boolean array ShowForPlayer[12]
        private real XOff = 0.00
        private real YOff = 0.00

        method ShowForPlayer takes integer forPlayer, boolean Show returns nothing
            local integer PId = GetPlayerId(forPlayer)

            if Show then
                if not(.ShowForPlayer[PId]) then
                    if .Parents[PId] < 0 then
                        set .Parents[PId] = NewParent(PId, this)
                        if .Parents[PId] < 0 then
                            return
                        endif
                    endif

                    set .ShowForPlayer[PId] = true
                    if LocalPlayer == forPlayer then
                        call SetTextTagText(TT[.Parents[PId].Index], .Text, .Height)
                        call SetTextTagPos(TT[.Parents[PId].Index], .XCoord, .YCoord, .Height)
                        call SetTextTagColor(TT[.Parents[PId].Index], .Red, .Green, .Blue, .Alpha)
                    endif
                    set LocalText = null
                endif
            elseif .ShowForPlayer[PId] then
                if LocalPlayer == forPlayer then
                    call SetTextTagText(TT[.Parents[PId].Index], "", 0.00)
                endif
            endif
        endmethod

        static method createForPlayer takes player forPlayer, string Text, real Height, real X, real Y, integer R, integer G, integer B, integer A returns MultiTag
            local MultiTag MT = MultiTag.allocate()
            local integer J = 0

            loop
                if Player(J) == forPlayer then
                    set MT.Parents[J] == NewParent(GetPlayerId(forPlayer), MT)
                    set ShowForPlayer[J] = true
                else
                    set MT.Parents[J] = -1
                    set ShowForPlayer[J] = false
                endif

                set J = J+1
                exitwhen J > 11
            endloop

            set MT.Text = Text
            set MT.Height = Height
            set MT.XCoord = X
            set MT.YCoord = Y
            set MT.Red = R
            set MT.Green = G
            set MT.Blue = B
            set MT.Alpha = A

            return MT
        endmethod

        method onDestroy takes nothing returns nothing
            local integer J = 0

            loop
                if .ShowForPlayer[J] and LocalPlayer == Player(J) then
                    call SetTextTagText(TT[.Parents[J].Index], "", 0.00)
                endif
                    
                set J = J+1
                exitwhen J > 11
            endloop
        endmethod
    endstruct

    private function Init takes nothing returns nothing
        local integer J = 0
        loop
            exitwhen J >= USED_TEXTTAG_AMOUNT
            set TT[J] = CreateTextTag()
            set Separators[J] = TagSeparator.create(J)
            set J = J+1
        endloop

        set PTimer = CreateTimer()
        set LocalPlayer = GetLocalPlayer()
    endfunction
endlibrary
One other thing I just thought of right is this: what if you figured out which texttags could be seen on the screen by each player, and then showed only the relevant ones when necessary. That way the other tags would be there to be seen if a player moved the camera there, but not unless he/she did so. These two in conjunction might drastically increase the 99 texttag cap.
01-13-2009, 10:21 AM#2
DioD
Actually you can directly set any "local" data to texttags and dont need any system for this.
01-13-2009, 12:40 PM#3
Toadcop
yes you can do whatever you want localy with a textag... lightnings ubersplats and images. i mean you can even create them localy.

but anyway every player can't have more than 99 tts
01-14-2009, 02:01 AM#4
Pyrogasm
Goddamn, so I can create 99 local texttags for player 1, and then I can create another 99 local texttags for player 2 without issues?

But if I created 50 global texttags then I could only create 49 more locally for each player?
01-14-2009, 12:11 PM#5
Anitarf
Pretty much.
01-14-2009, 11:00 PM#6
Pyrogasm
Well, I guess I could adapt this system, but it seems pretty pointless now...
01-14-2009, 11:04 PM#7
Vexorian
Wasn't the limit for alive texttags anyway? I think that it was not for visible texttags (So, if you call the fade native on a texttag it doesn't count towards the limit anymore)