• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[Infrastructure/System(?)] The Utilities Library (JASS)

Level 6
Joined
Apr 16, 2007
Messages
177
An infrastructure Library used in many of my Systems.
REQUIREMENTS:
JassPack NewGen
FEATURES:
  • Can convert integers into hexstrings ( for string coloring ) with Hex2S( integer, ndigits ) ( only ndigits digits of the hex integer will be put into the string )
  • Can color a string according to a percentage ( EG: 100% -> Green, 50% -> brown, 0% -> Red ) with State2Color( real state ) // state is between 0 and 1
  • Comes with four strings to color messages in a coordinated way: RED, GREEN, GREY and GOLD ( just use string = RED + "You have been killed!" )
  • Can create bounty tags ( and the bounty effect ) that just look like the Wc3 ones with CreateBountyText( integer amount, unit target, player getter ): This will display the bounty text above unit target. Bounty text is only visible for getter. Btw, if the amount is negative, color will be changed to red and it will bear a minus sign insted of the + sign.
  • You can also use a color you want with the bounty texts. Just use CreateColoredBountyText( string color, integer amount, unit target, player getter )
  • Comes with StartLocX[ playerId ] / StartLocY[ playerId ] for the start location x and y of Player(playerId)
  • Comes with variables for players, although I don't know if that is really faster than Player( x ): Players[ x ]
  • Comes with the unformatted names for name checking ( is faster than the GetPlayerName() function ): PlayerStartName[ playerId ]
  • Comes with autocolored playernames PlayerName[ playerid ] ( is colored for text output ). Uncolored ones are PlayerNameUncolored[ playerId ]
  • Needs another namechange command, that is: SetPlayerNameSJ( player, name ). This changes PlayerName/PlayerNameUncolored accordingly. PlayerStartName will not be altered!
  • Alternatively to the normal player text colors, you can set a players text colors with SetPlayerColors( integer playerid, integer red, integer green, integer blue ). It won't affect the player's name in the interface, as the normal coloring does not work here. I'm still trying to find a way for fixing this.
  • Has a Leaver handler that fires whenever a player leaves. Displays a message, and changes the players name to GREY+Name+ (LEFT).
  • The message shown on player leave can be altered in the parameters. It will use the message of the parameters ( LEAVER_MESSAGE ), but enter the players name at the position of the "%p" string. If there is no %p, no name will be displayed.
  • The trigger to attach leaver actions to is LEAVER_HANDLER. You can, but needn't create your own one.
  • Has a function to calculate the distance between units. DistanceBetweenUnits( unit a, unit b ), as fast as I could get it. You most probably have your own function here ; )
  • Has a function to register the chat event of any player. Saves me the pain in the neck Chat events normally are. TriggerRegisterAnyPlayerChatEvent( trigger register, string chat, boolean exactmatchonly )
  • Has two functions to create n units, one of them issues a point order - good for spawning. CreateNUnitsAngle( player owner, integer unittype, real x, real y, real angle, integer number ) and CreateNUnitsOrder( player owner, integer unittype, real x, real y, integer number, string order, real targetx, real targety ) . The last one sets the angle towards the direction of the order x/y. Note also that it returns a unit group that you can use, but it is MUI only to some extent. Using
    JASS:
    local group g = CreateNUnitsAngle( Players[0], 'hfoo', 0, 0, 270, 7 ) 
    call CreateNUnitsAngle( Players[1], 'hfoo', 512, 0, 270, 7 )
    // g will now be the units at 512|0, not the ones at 0|0 !!!

    In order to still use g, you'ld need to do the following:
    JASS:
    local group g = CreateGroup()
    call GroupAddGroup( CreateNUnitsAngle( Players[0], 'hfoo', 0, 0, 270, 7 ), g ) 
    call CreateNUnitsAngle( Players[1], 'hfoo', 512, 0, 270, 7 )
    // g will now be the units at 0|0, not the ones at 512|0 !!!
  • The SetPlayerAllianceStateSJ( player one, player two, integer alliancestate ) function does the same like the BJ, just that it allies in both ways, saves all if clauses and lots of function calls.
  • Has a function to retrieve either the closest or the farest unit in a certain range. GetClosestUnitInRange( real x, real y, real radius, boolean closest, boolexpr filter ).
  • Comes with a function to have a player win/loose with a certain message. WinGame( player whichPlayer, boolean win, string message ). Creates the dialogs etc.
  • Comes with the PlayerActive[ playerId ] array that is set to true when the slot is used by either a computer player or an user. Will be automatically set to false when a player leaves, looses or if the slot was not filled at map start.
  • Has MAX_INV_SLOT ( 5, maximum item slot ), MAX_PLAYER_SLOT ( 15, maximum player slot ) and MAX_USER_SLOT ( 11, maximum user slot ) constants for looping through all players, the user players, and an inventory
  • a ReturnHandle variable in order to fix the returnbug handle-leaks ( return location etc ). In the utilities, there is only one function that returns a handle, but that function uses it ; D
  • Has a textmacro for randomized string output. Tiny, yet useful, you can add strings to a stack and use a function to retrieve a random one of them.
    JASS:
    //! runtextmacro RandomString( "Name" )
    for Stack Creation;
    JASS:
    call AddNameString( "Jones" )
    call AddNameString( "Sarah" )
    call AddNameString( "Tim" )
    call GetNameString() // Gets a random 'Name' string; In this case either Jones, Sarah or Tim.
    call AddNameString( "Jones" )
    call AddNameString( "Carol" )
    call GetNameString() // Gets a random 'Name' string; In this case either Jones, Sarah, Carol or Tim. Note that the chance to get 'Jones' is twice as high.
  • Has 2 functions that convert an alphanumerical string into a number and back. NOT TO BE CONFUSED WITH ASCII! However, 'A' will score lower than 'B' and 'AB'. Can be used for alphabetical sorting or for saveload codes or whatever. Non-Alphanumerical characters will not be retrieved when you revert the number to a string; They will simply be left out ( 'Cpt.Davey' will become 'CptDavey' ). The case is ignored. The Char2I function only processes on a substring of the argument, which is chosen by the two min and max parameters.
    JASS:
    call BJDebugMSG( I2Char( Char2I( "Cpt.Da_vEy", 3, 9) ) // shows 'davey'
    If the span is to big, it might get an overflow error! You should always use 6 letters at max.
  • Has a DisplayText( player, text ) function that actually does nothing but call DisplayTimedTextToPlayer( player, 0, 0, 15, text ). JASSHelper 0.9.9.E.0 inlines this so it is as fast as the normal function, but it saves 50% of the time and is easier to read.
  • Has a GetHandleId function, that does but H2I(). I didn't want to use H2I as name becouse it is overused and might get a syntax with a non-scoped H2I.
  • Comes with the SetMultiboardItemValue function.
    JASS:
    call SetMultiboardItemValue( multiboard, row, col, value, iconfilename, width, whichplayer )
    . This sets the (row|col) item's stats. If value is "" ( empty string ), it won't show the text; If iconfilename is "", it won't show the icon, if width is 0 or smaller, it will not alter the item's width at all. If whichplayer is null, it will apply the changes for everyone - elsewise just for whichplayer. If row is -1, it will affect all rows; If col is -1, it will affect all cols. If multiboard is null, it will crash ; D
  • Comes with a handy textmacro for state 2 text conversion. That means, a Text ( like empty, or full ) can be mapped to State A ( like 0%, or 100% ) and then be retrieved with a function. With Empty: 0% and Full 100%, everything that is less than 100% will return Empty, and everything above will return Full. This is nice when you want to output certain states of anything without having to do an enourmous if-cluster whenever you want to use it. The syntax is:
    JASS:
    //! runtextmacro State2Text( "Life" )
    now in any function you can call
    JASS:
    call Text2Life( GREY + "Dead", -1 )
    call Text2Life( State2Color( 0.2) + "Wounded", 0.0 )
    call Text2Life( GREEN + "Ok", 0.6 )
    and then
    JASS:
    call BJDebugMSG( Life2Text( 0.3 ) )
    call BJDebugMSG( Life2Text( -0.1 ) )
    call BJDebugMSG( Life2Text( 0.9 ) )
    will print to the screen:
    Wounded
    Dead
    Ok
    ( with the right coloring )
  • NEW
  • There is a global variable for the GetLocalPlayer() function: LOCAL_PLAYER
  • Perhaps you have remarked Blizzards Multiboard flaw: Only one can be displayed at the same time. When you display another one, the first one will no longer be displayed - and without a huge amount of coding, it is impossible to regain the old multiboard once the new one is destroyed.
    The Utilities library comes with a function that handles this problem:
    JASS:
    call MultiboardDisplaySJ( yourMultiboard, show, player )
    When invoked with true, the function will store the last displayed multiboard of player, and when invoked with false, return it. Works with up to 680 Multiboards per player ( at average. You can also concentrate 8191 on one single player ), but might get a bit slower by that time ; )
I hope it is helpful for someone, I use it mainly for coordination purposes of style ( not using 5 different reds for negative warnings, lol ) and for not having to code the "pain in the neck" functions everytime I use them.

If you should find a bug ( which is really unprobable, I have been using most of these functions for almost half a year now and haven't found anything ), or have a suggestion for a function / constant that should make it into this Library, just post here.

Greetings to all, Davey Jones

JASS:
//----------------------------\\
//           VER B2           \\
//----------------------------\\

// Special thanks: Tom_Kazansky  for his incredible wisdom concerning the creation of texttags ; )
//                 PurplePoot    for his countless tips on what to improve! 

library UtilityParameters
globals
    // parameters
        // for parameter coloring
            // GOLD will be used as the display color for positive bounty created with CreateBountyText()
            // RED will be used as the display color for negative bounty created with CreateBountyText()

    constant string NegativeTag = "|cffff3333"
    constant string PositiveTag = "|cff33cf33"
    constant string NeutralTag = "|cffffcc00"
    constant string InactiveTag = "|cff808080"
    constant string EndTag = "|r"

    constant string RED = "|cffff3333"
    constant string GREEN = "|cff33cf33"
    constant string GOLD = "|cffffcc00"
    constant string GREY = "|cff808080"
    constant string LIGHTGREY = "|cffC0C0C0"
    constant string TURQUOISE = "|cff33BBBB"
    constant string WHITE = "|r"

        // use %p for the name of the player that has left.
    constant string LEAVER_MESSAGE = RED + "%p has left the game!"

endglobals

endlibrary
library Utilities initializer UtilityInit needs UtilityParameters
//! textmacro ChangePlayerState takes PLAYER, STATE, AMOUNT
    call SetPlayerState( $PLAYER$, PLAYER_STATE_$STATE$, GetPlayerState( $PLAYER$, PLAYER_STATE_$STATE$ ) + $AMOUNT$ )
//! endtextmacro

//! textmacro State2Text takes STATE
globals
    integer $STATE$s = 0
    string array $STATE$Name
    real array $STATE$State
endglobals

function Text2$STATE$ takes string text, real state returns nothing
    local real curKey = state
    local string parKey = text
    local integer index = $STATE$s
    local integer curdex = index - 1
    set $STATE$s = $STATE$s + 1
    loop
        exitwhen index < 1
        exitwhen curKey >= $STATE$State[ curdex ]
        set $STATE$State[ index ] = $STATE$State[ curdex ]
        set $STATE$Name[ index ] = $STATE$Name[ curdex ]
        set index = curdex
        set curdex = index - 1
    endloop

    set $STATE$State[ index ] = curKey
    set $STATE$Name[ index ] = parKey
endfunction



function $STATE$2Text takes real state returns string
    local integer index = 0
    loop
        if $STATE$State[ index ] >= state then
            set index = index - 1
            if index < 0 then
                set index = 0
            endif
            exitwhen true
        endif
        exitwhen index >= $STATE$s - 1
        set index = index + 1
    endloop
    return $STATE$Name[ index ]
endfunction
//! endtextmacro


globals
    // Do not change these!
             player array Players
    constant integer NUMPLAYERS = 15
    constant integer MAX_PLAYER_SLOT = 15

    constant integer NUMUSERS = 11
    constant integer MAX_USER_SLOT = 11

    constant integer NUMSLOTS = 5
    constant integer MAX_INV_SLOT = 5

             integer LETTERS = 0

             real array StartLocX
             real array StartLocY

             string array PlayerName
             string array PlayerNameUncolored
             string array PlayerStartName
             string array PlayerColor
             boolean array PlayerActive

             playercolor array DefaultPlayerColor
    private  string array NormalPlayerColor

    constant group GLOBAL_GROUP = CreateGroup()

    constant integer HexBase = 16
             string array Hex
             string array LETTER

    constant string BountyEffectString = "UI\\Feedback\\GoldCredit\\GoldCredit.mdl"
             string BountyColoring = GOLD + "+"
    constant real BountySpeed = 0.71 / 24
    constant real BountyTextSize = 0.023

    constant trigger LEAVER_HANDLER = CreateTrigger()

             handle ReturnHandle
             boolean array PLAYER_ALLIANCE_STATE_PASSIVE
             boolean array PLAYER_ALLIANCE_STATE_HELP_REQUEST
             boolean array PLAYER_ALLIANCE_STATE_HELP_RESPONSE
             boolean array PLAYER_ALLIANCE_STATE_SHARED_XP
             boolean array PLAYER_ALLIANCE_STATE_SHARED_SPELLS
             boolean array PLAYER_ALLIANCE_STATE_ALLIANCE_SHARED_VISION
             boolean array PLAYER_ALLIANCE_STATE_ALLIANCE_SHARED_CONTROL
             boolean array PLAYER_ALLIANCE_STATE_ALLIANCE_SHARED_ADVANCED_CONTROL

    constant boolean AUTOCOLOR_NAMES = true

             string LEAVER_MESSAGE_A
             string LEAVER_MESSAGE_B
             boolean DISPLAY_LEAVER_NAME = false
             player LOCAL_PLAYER
             
    private  multiboardchain array MBChain
endglobals

function DisplayText takes player whichplayer, string text returns nothing
    call DisplayTimedTextToPlayer( whichplayer, 0, 0, 15, text )
endfunction

function Hex2S takes integer hex, integer digits returns string
    local string hexstring = ""
    local integer curDigit

    loop
        exitwhen digits <= 0
        set curDigit = ModuloInteger( hex, HexBase )
        set hex = hex / HexBase
        set hexstring = Hex[ curDigit ] + hexstring
        set digits = digits - 1
    endloop
    return hexstring
endfunction

function DistanceBetweenUnits takes unit a, unit b returns real
    local real deltaX = GetUnitX( a ) - GetUnitX( b )
    local real deltaY = GetUnitY( a ) - GetUnitY( b )
    set a = null
    set b = null
    return SquareRoot( deltaX * deltaX + deltaY * deltaY )
endfunction

function GetHandleId takes handle h returns integer
    return h
    return 0
endfunction

function State2Color takes real state returns string
    local integer hex = R2I( state * 204 )
    if hex > 204 then
        set hex = 204
    elseif hex < 0 then
        set hex = 0
    endif
    return "|cff" + Hex2S( 255 - hex, 2 ) + Hex2S( 51 + hex, 2 ) + "20"
endfunction

function SetPlayerNameSJ takes player whichplayer, string name returns nothing
    local integer playerId = GetPlayerId( whichplayer )
    set PlayerName[ playerId ] = PlayerColor[ playerId ] + name
    set PlayerNameUncolored[ playerId ] = name
    call SetPlayerName( whichplayer, name )
endfunction

function SetPlayerColors takes integer playerid, integer red, integer green, integer blue returns nothing
    set PlayerColor[ playerid ] = "|cff" + Hex2S( red, 2 ) + Hex2S( green, 2 ) + Hex2S( blue, 2 )
    set PlayerName[ playerid ] = PlayerColor[ playerid ] + PlayerNameUncolored[ playerid ]
endfunction

function SetPlayerColorsOld takes integer playerid, integer red, integer green, integer blue returns nothing
    set NormalPlayerColor[ playerid ] = "|cff" + Hex2S( red, 2 ) + Hex2S( green, 2 ) + Hex2S( blue, 2 )
endfunction


private function LeaverHandlerNoName_Actions takes nothing returns nothing
    local player leaver = GetTriggerPlayer( )
    local integer leaverId = GetPlayerId ( leaver )
    local string leaverName = GREY + PlayerName[ leaverId ] + " (LEFT)" + EndTag
    call SetPlayerNameSJ( leaver, leaverName )
    set PlayerActive [ leaverId ] = false
    set PlayerName [ leaverId ] = leaverName
    call DisplayTextToPlayer( GetLocalPlayer(), 0, 0, LEAVER_MESSAGE )
endfunction

private function LeaverHandlerName_Actions takes nothing returns nothing
    local player leaver = GetTriggerPlayer( )
    local integer leaverId = GetPlayerId ( leaver )
    local string leaverName = InactiveTag + PlayerName[ leaverId ] + " (LEFT)" + EndTag
    call SetPlayerNameSJ( leaver, leaverName )
    set PlayerActive [ leaverId ] = false
    set PlayerName [ leaverId ] = leaverName
    call DisplayTextToPlayer( GetLocalPlayer(), 0, 0, LEAVER_MESSAGE_A + PlayerStartName[ leaverId ] + LEAVER_MESSAGE_B )
endfunction

function SetAllianceState takes integer alliancestate, boolean passive, boolean helprequest, boolean helpresponse, boolean sharedxp, boolean sharedspells, boolean sharedvision, boolean sharedcontrol, boolean sharedadvancedcontrol returns nothing
    if alliancestate >= 0 and alliancestate <= 8 then
        set PLAYER_ALLIANCE_STATE_PASSIVE[ alliancestate ] = passive
        set PLAYER_ALLIANCE_STATE_HELP_REQUEST[ alliancestate ] = helprequest
        set PLAYER_ALLIANCE_STATE_HELP_RESPONSE[ alliancestate ] = helpresponse
        set PLAYER_ALLIANCE_STATE_SHARED_XP[ alliancestate ] = sharedxp
        set PLAYER_ALLIANCE_STATE_SHARED_SPELLS[ alliancestate ] = sharedspells
        set PLAYER_ALLIANCE_STATE_ALLIANCE_SHARED_VISION[ alliancestate ] = sharedvision
        set PLAYER_ALLIANCE_STATE_ALLIANCE_SHARED_CONTROL[ alliancestate ] = sharedcontrol
        set PLAYER_ALLIANCE_STATE_ALLIANCE_SHARED_ADVANCED_CONTROL[ alliancestate ] = sharedadvancedcontrol
    endif
endfunction

private function AddLetter takes string char returns nothing
    set LETTER[ LETTERS ] = char
    set LETTERS = LETTERS + 1
endfunction


struct multiboardchain
    player owner
    multiboardchain_member first
    multiboardchain_member last    
    static method create takes player owner returns multiboardchain
        local multiboardchain this = .allocate()
        set .owner = owner
        set .first = 0
        set .last  = 0
        return this
    endmethod
endstruct

struct multiboardchain_member
    multiboard mb
    multiboardchain parent
    multiboardchain_member next
    multiboardchain_member last
    static method create takes multiboard mb, multiboardchain parent returns multiboardchain_member
        local multiboardchain_member this
        local multiboardchain_member curChild = parent.first
                
        if parent.first == 0 then
            set this = .allocate()
            set parent.first = this
        else
            loop
                exitwhen curChild == 0
                if curChild.mb == mb then
                    call curChild.reAppend()
                    return curChild
                endif
                set curChild = curChild.next
            endloop
            set this = .allocate()            
        endif

        set .mb = mb
        set .parent = parent
        set .last = .parent.last
        set .parent.last = this
        set .last.next = this
        set .next = 0
        if LOCAL_PLAYER == .parent.owner then
            if .last != 0 then
                call MultiboardDisplay( .last.mb, false )
            endif
            call MultiboardDisplay( mb, true )
        endif
        return this
    endmethod
    
    // drops the chain member from the chain and fixes the chain
    method drop takes nothing returns nothing
        local boolean isLast = .next == 0 
        local boolean isFirst = .last == 0
        if isLast and isFirst then
            set .parent.last = 0
            set .parent.first = 0
        elseif isLast then
            set .parent.last = .last
            set .last.next = 0 
        elseif isFirst then
            set .parent.first = .next
            set .next.last = 0
        else            
            set .next.last = .last
            set .last.next = .next
        endif
    endmethod
    
    method reAppend takes nothing returns nothing
        // fix chain
        call .drop()
        // append self
        set .last = .parent.last
        set .parent.last = this
        set .last.next = this
        if LOCAL_PLAYER == .parent.owner then
            if .last != 0 then
                call MultiboardDisplay( .last.mb, false )
            endif
            call MultiboardDisplay( .mb, true )
        endif
    endmethod
    
    method onDestroy takes nothing returns nothing
        local boolean view = LOCAL_PLAYER == .parent.owner
        local boolean showLast = ( .next == 0 ) and ( .last != 0 )
        if view then
            call MultiboardDisplay( .mb, false )
            if showLast then
                call MultiboardDisplay( .last.mb, true )
            endif
        endif
        call .drop()
        
        set .mb = null
    endmethod
endstruct

function MultiboardDisplaySJ takes multiboard mb, boolean display, player viewer returns nothing
    local multiboardchain parent 
    local multiboardchain_member curChild
    local boolean view
    
    if viewer == null then
        set viewer = LOCAL_PLAYER
    endif
    
    set view = viewer == LOCAL_PLAYER
    set parent = MBChain[ GetPlayerId( viewer ) ] 
    if display then
        call multiboardchain_member.create( mb, parent )
    else    
        set curChild = parent.last
        loop
            exitwhen curChild == 0
            if curChild.mb == mb then
                call curChild.destroy()
                set view = false
                exitwhen true
            endif
            set curChild = curChild.last
        endloop
        if view then
            call MultiboardDisplay( mb, false )
        endif
    endif
endfunction

private function UtilityInit takes nothing returns nothing
    local integer playerId = 0
    local integer innerIndex = 0
    local integer stringIndex = 0
    local integer stringLen = StringLength( LEAVER_MESSAGE )
    local integer startLocation
    local playercolor curColor
    
    set LOCAL_PLAYER = GetLocalPlayer()

    set Hex[ 0 ] = "0"
    set Hex[ 1 ] = "1"
    set Hex[ 2 ] = "2"
    set Hex[ 3 ] = "3"
    set Hex[ 4 ] = "4"
    set Hex[ 5 ] = "5"
    set Hex[ 6 ] = "6"
    set Hex[ 7 ] = "7"
    set Hex[ 8 ] = "8"
    set Hex[ 9 ] = "9"
    set Hex[ 10 ] = "a"
    set Hex[ 11 ] = "b"
    set Hex[ 12 ] = "c"
    set Hex[ 13 ] = "e"
    set Hex[ 14 ] = "d"
    set Hex[ 15 ] = "f"

    call AddLetter( RED + "UNDEF CHAR" )
    call AddLetter( "0" )
    call AddLetter( "1" )
    call AddLetter( "2" )
    call AddLetter( "3" )
    call AddLetter( "4" )
    call AddLetter( "5" )
    call AddLetter( "6" )
    call AddLetter( "7" )
    call AddLetter( "8" )
    call AddLetter( "9" )
    call AddLetter( "a" )
    call AddLetter( "b" )
    call AddLetter( "c" )
    call AddLetter( "d" )
    call AddLetter( "e" )
    call AddLetter( "f" )
    call AddLetter( "g" )
    call AddLetter( "h" )
    call AddLetter( "i" )
    call AddLetter( "j" )
    call AddLetter( "k" )
    call AddLetter( "l" )
    call AddLetter( "m" )
    call AddLetter( "n" )
    call AddLetter( "o" )
    call AddLetter( "p" )
    call AddLetter( "q" )
    call AddLetter( "r" )
    call AddLetter( "s" )
    call AddLetter( "t" )
    call AddLetter( "u" )
    call AddLetter( "v" )
    call AddLetter( "w" )
    call AddLetter( "x" )
    call AddLetter( "y" )
    call AddLetter( "z" )



    set BountyColoring = GOLD + "+"


    call SetPlayerColorsOld( 0, 255,   3,   3 )
    call SetPlayerColorsOld( 1,   0,  66, 255 )
    call SetPlayerColorsOld( 2,  28, 230, 185 )
    call SetPlayerColorsOld( 3,  84,   0, 129 )
    call SetPlayerColorsOld( 4, 255, 252,   1 )
    call SetPlayerColorsOld( 5, 254, 186,  14 )
    call SetPlayerColorsOld( 6,  32, 192,   0 )
    call SetPlayerColorsOld( 7, 229,  91, 176 )
    call SetPlayerColorsOld( 8, 149, 150, 151 )
    call SetPlayerColorsOld( 9, 126, 191, 241 )
    call SetPlayerColorsOld( 10, 16,  98,  70 )
    call SetPlayerColorsOld( 11, 78,  42,   4 )

    call SetAllianceState( bj_ALLIANCE_ALLIED_ADVUNITS, true,   true,   true,   true,   true,   true,   true,   true )
    call SetAllianceState( bj_ALLIANCE_ALLIED_UNITS,    true,   true,   true,   true,   true,   true,   true,   false )
    call SetAllianceState( bj_ALLIANCE_ALLIED_VISION,   true,   true,   true,   true,   true,   true,   false,  false )
    call SetAllianceState( bj_ALLIANCE_ALLIED,          true,   true,   true,   true,   true,   false,  false,  false )
    call SetAllianceState( bj_ALLIANCE_NEUTRAL_VISION,  true,   false,  false,  false,  false,  true,   false,  false )
    call SetAllianceState( bj_ALLIANCE_NEUTRAL,         false,  false,  false,  false,  false,  false,  false,  false )
    call SetAllianceState( bj_ALLIANCE_UNALLIED_VISION, false,  false,  false,  false,  false,  true,   false,  false )
    call SetAllianceState( bj_ALLIANCE_UNALLIED,        false,   false,  false,  false,  false,  false,  false,  false )


    loop
        exitwhen stringIndex >= stringLen
        if SubString( LEAVER_MESSAGE, stringIndex, stringIndex +2 ) == "%p" then
            set LEAVER_MESSAGE_A = SubString( LEAVER_MESSAGE, 0, stringIndex )
            set LEAVER_MESSAGE_B = SubString( LEAVER_MESSAGE, stringIndex+2, stringLen )
            set DISPLAY_LEAVER_NAME = true
            exitwhen true
        endif
        set stringIndex = stringIndex + 1
    endloop

    set playerId = 0
    loop
        exitwhen playerId > NUMPLAYERS
        set Players [ playerId ] = Player( playerId )
        set PlayerActive [ playerId ] = GetPlayerSlotState( Players[ playerId ] ) == PLAYER_SLOT_STATE_PLAYING
        set PlayerStartName[ playerId ] = GetPlayerName( Players[ playerId ] )    
                
        set curColor = GetPlayerColor( Player( playerId ) )
        set PlayerColor[ playerId ] = NormalPlayerColor[ GetHandleId( curColor ) ]

        set startLocation = GetPlayerStartLocation( Players[ playerId ] )
        set StartLocX [ playerId ] = GetStartLocationX( startLocation )
        set StartLocY [ playerId ] = GetStartLocationY( startLocation )
        
        set MBChain[ playerId ] = multiboardchain.create( Players[ playerId ] )
        
        if PlayerActive[ playerId ] then                                                              
            set PlayerName[ playerId ] = PlayerColor[ playerId ] + PlayerStartName[ playerId ]
            set PlayerNameUncolored[ playerId ] = PlayerStartName[ playerId ]
            call TriggerRegisterPlayerEvent( LEAVER_HANDLER, Players[ playerId ], EVENT_PLAYER_LEAVE )
        else
            set PlayerName[ playerId ] = GREY + "Player " + I2S( playerId + 1 ) + " (N/A)" + WHITE
        endif
    
        set playerId = playerId + 1
    endloop

    if DISPLAY_LEAVER_NAME then
        call TriggerAddAction( LEAVER_HANDLER, function LeaverHandlerName_Actions )
    else
        call TriggerAddAction( LEAVER_HANDLER, function LeaverHandlerNoName_Actions )
    endif

    call SetPlayerNameSJ( Players[ PLAYER_NEUTRAL_AGGRESSIVE ], "Neutral aggressive" )
    call SetPlayerNameSJ( Players[ PLAYER_NEUTRAL_PASSIVE ],    "Neutral passive" )
    call SetPlayerNameSJ( Players[ bj_PLAYER_NEUTRAL_EXTRA ],   "Neutral extra" )
    call SetPlayerNameSJ( Players[ bj_PLAYER_NEUTRAL_VICTIM ],  "Neutral victim" )
endfunction

function CreateColoredBountyText takes string color, integer bounty, unit target, player getter returns nothing
    local texttag bountyText = CreateTextTag()
    local effect bountyArt
    if bounty > 0 then
        call SetTextTagText ( bountyText, color + "+" + I2S( bounty ) + "|r", BountyTextSize )
    elseif bounty < 0 then
        call SetTextTagText ( bountyText, color + I2S( bounty ) + "|r", BountyTextSize )
    else
        call SetTextTagText ( bountyText, "", BountyTextSize )
    endif
    set bountyArt = AddSpecialEffectTarget( BountyEffectString, target, "overhead" )
    call SetTextTagVelocity ( bountyText, 0, BountySpeed )
    call SetTextTagPermanent( bountyText, false )
    call SetTextTagAge ( bountyText, 0 )
    call SetTextTagFadepoint( bountyText, 2 )
    call SetTextTagLifespan ( bountyText, 3 )
    call SetTextTagPosUnit ( bountyText, target, 0 )
    if LOCAL_PLAYER != getter then
        call SetTextTagVisibility( bountyText, false )
    endif
    call DestroyEffect( bountyArt )
    set bountyText = null
    set bountyArt = null
endfunction

function CreateBountyText takes integer bounty, unit target, player getter returns nothing
    local texttag bountyText = CreateTextTag()
    local effect bountyArt
    if bounty > 0 then
        call SetTextTagText ( bountyText, BountyColoring + I2S( bounty ) + "|r", BountyTextSize )
    elseif bounty < 0 then
        call SetTextTagText ( bountyText, RED + I2S( bounty ) + "|r", BountyTextSize )
    else
        call SetTextTagText ( bountyText, "", BountyTextSize )
    endif
    set bountyArt = AddSpecialEffectTarget( BountyEffectString, target, "overhead" )
    call SetTextTagVelocity ( bountyText, 0, BountySpeed )
    call SetTextTagPermanent( bountyText, false )
    call SetTextTagAge ( bountyText, 0 )
    call SetTextTagFadepoint( bountyText, 2 )
    call SetTextTagLifespan ( bountyText, 3 )
    call SetTextTagPosUnit ( bountyText, target, 0 )
    if LOCAL_PLAYER != getter then
        call SetTextTagVisibility( bountyText, false )
    endif
    call DestroyEffect( bountyArt )
    set bountyText = null
    set bountyArt = null
endfunction

function TriggerRegisterAnyPlayerChatEvent takes trigger whichtrigger, string chatmessagetodetect, boolean exactmatchonly returns nothing
    local integer playerId = 0
    loop
        exitwhen playerId > NUMPLAYERS
        call TriggerRegisterPlayerChatEvent( whichtrigger, Players[ playerId ], chatmessagetodetect, exactmatchonly )
        set playerId = playerId + 1
    endloop
endfunction

function CreateNUnits takes player owner, integer unittypeid, real x, real y, integer n returns group      
    call GroupClear( GLOBAL_GROUP )
    loop
        exitwhen n <= 0
        call GroupAddUnit( GLOBAL_GROUP, CreateUnit( owner, unittypeid, x, y, GetRandomReal( 0, 360 ) ) )
        set n = n - 1
    endloop     
    return GLOBAL_GROUP
endfunction

function CreateNUnitsAngle takes player owner, integer unittypeid, real x, real y, real angle, integer n returns group      
    call GroupClear( GLOBAL_GROUP )
    loop
        exitwhen n <= 0
        call GroupAddUnit( GLOBAL_GROUP, CreateUnit( owner, unittypeid, x, y,  angle ) )
        set n = n - 1
    endloop
    return GLOBAL_GROUP
endfunction

function CreateNUnitsOrder takes player owner, integer unittypeid, real x, real y, integer n, string order, real targetx, real targety returns group
    local real angle = Atan2( y-targety, x-targetx )
    local unit loopUnit             
    call GroupClear( GLOBAL_GROUP )
    loop
        exitwhen n <= 0
        set loopUnit = CreateUnit( owner, unittypeid, x, y, angle )
        call GroupAddUnit( GLOBAL_GROUP, loopUnit )
        call IssuePointOrder( loopUnit, order, targetx, targety )
        set n = n - 1
    endloop
    set loopUnit = null
    return GLOBAL_GROUP
endfunction


function SetPlayerAllianceStateSJ takes player sourcePlayer, player otherPlayer, integer allianceState returns nothing
    if (sourcePlayer == otherPlayer) then
        return
    endif
    //this works like the normal BJ, just that it allies in both ways
    if allianceState >= 0 and allianceState <= 8 then
        call SetPlayerAlliance( sourcePlayer, otherPlayer, ALLIANCE_PASSIVE, PLAYER_ALLIANCE_STATE_PASSIVE[ allianceState ] )
        call SetPlayerAlliance( sourcePlayer, otherPlayer, ALLIANCE_HELP_REQUEST, PLAYER_ALLIANCE_STATE_HELP_REQUEST[ allianceState ] )
        call SetPlayerAlliance( sourcePlayer, otherPlayer, ALLIANCE_HELP_RESPONSE, PLAYER_ALLIANCE_STATE_HELP_RESPONSE[ allianceState ] )
        call SetPlayerAlliance( sourcePlayer, otherPlayer, ALLIANCE_SHARED_XP, PLAYER_ALLIANCE_STATE_SHARED_SPELLS[ allianceState ] )
        call SetPlayerAlliance( sourcePlayer, otherPlayer, ALLIANCE_SHARED_SPELLS, PLAYER_ALLIANCE_STATE_SHARED_SPELLS[ allianceState ] )
        call SetPlayerAlliance( sourcePlayer, otherPlayer, ALLIANCE_SHARED_VISION, PLAYER_ALLIANCE_STATE_ALLIANCE_SHARED_CONTROL[ allianceState ] )
        call SetPlayerAlliance( sourcePlayer, otherPlayer, ALLIANCE_SHARED_CONTROL, PLAYER_ALLIANCE_STATE_ALLIANCE_SHARED_CONTROL[ allianceState ] )
        call SetPlayerAlliance( sourcePlayer, otherPlayer, ALLIANCE_SHARED_ADVANCED_CONTROL, PLAYER_ALLIANCE_STATE_ALLIANCE_SHARED_ADVANCED_CONTROL[ allianceState ] )

        call SetPlayerAlliance( otherPlayer, sourcePlayer, ALLIANCE_PASSIVE, PLAYER_ALLIANCE_STATE_PASSIVE[ allianceState ] )
        call SetPlayerAlliance( otherPlayer, sourcePlayer, ALLIANCE_HELP_REQUEST, PLAYER_ALLIANCE_STATE_HELP_REQUEST[ allianceState ] )
        call SetPlayerAlliance( otherPlayer, sourcePlayer, ALLIANCE_HELP_RESPONSE, PLAYER_ALLIANCE_STATE_HELP_RESPONSE[ allianceState ] )
        call SetPlayerAlliance( otherPlayer, sourcePlayer, ALLIANCE_SHARED_XP, PLAYER_ALLIANCE_STATE_SHARED_SPELLS[ allianceState ] )
        call SetPlayerAlliance( otherPlayer, sourcePlayer, ALLIANCE_SHARED_SPELLS, PLAYER_ALLIANCE_STATE_SHARED_SPELLS[ allianceState ] )
        call SetPlayerAlliance( otherPlayer, sourcePlayer, ALLIANCE_SHARED_VISION, PLAYER_ALLIANCE_STATE_ALLIANCE_SHARED_CONTROL[ allianceState ] )
        call SetPlayerAlliance( otherPlayer, sourcePlayer, ALLIANCE_SHARED_CONTROL, PLAYER_ALLIANCE_STATE_ALLIANCE_SHARED_CONTROL[ allianceState ] )
        call SetPlayerAlliance( otherPlayer, sourcePlayer, ALLIANCE_SHARED_ADVANCED_CONTROL, PLAYER_ALLIANCE_STATE_ALLIANCE_SHARED_ADVANCED_CONTROL[ allianceState ] )
    endif
endfunction

function GetClosestUnitInRange takes real x, real y, real radius, boolean closest, boolexpr filter returns unit
    local group g = GLOBAL_GROUP
    local unit curUnit = null
    local unit loopUnit
    local real curDist
    local real dX
    local real dY
    local real loopDist
    call GroupClear( g )
    call GroupEnumUnitsInRange( g, x, y, radius, filter )
    if closest then
        set curDist = radius + 1
    else
        set curDist = 0
    endif
    loop
        set loopUnit = FirstOfGroup( g )
        exitwhen loopUnit == null
        set dX = x - GetUnitX( loopUnit )
        set dY = y - GetUnitY( loopUnit )
        set loopDist = SquareRoot( dX * dX + dY * dY )
        if loopDist < curDist == closest then
            set curDist = loopDist
            set curUnit = loopUnit
        endif
        call GroupRemoveUnit( g, loopUnit )
    endloop
    set ReturnHandle = curUnit
    set filter = null
    set loopUnit = null
    set curUnit = null
    return ReturnHandle
endfunction

function EndMap takes nothing returns nothing
    call EndGame( true )
endfunction

function WinGame takes player whichPlayer, boolean win, string message returns nothing
    local trigger t = CreateTrigger()
    local dialog d = DialogCreate ()
    local player localPlayer = LOCAL_PLAYER

    if win then
        call RemovePlayer ( whichPlayer, PLAYER_GAME_RESULT_VICTORY )
    else
        call RemovePlayer ( whichPlayer, PLAYER_GAME_RESULT_DEFEAT )
    endif

    call DialogSetMessage ( d, message )
    call TriggerRegisterDialogButtonEvent( t, DialogAddButton( d, "Ok", GetLocalizedHotkey("GAMEOVER_CONTINUE") ) )
    call TriggerAddAction ( t, function EndMap )
    if localPlayer == whichPlayer then
        call EnableUserControl( true )
        call EnableUserUI ( false )
    endif

    call DialogDisplay( whichPlayer, d, true )

endfunction

function SetMultiboardItemValue takes multiboard mb, integer row, integer col, string value, string iconfilename, real width, player whichplayer returns nothing
    local multiboarditem curItem
    local boolean showIcon = iconfilename != "" 
    local boolean showValue = value != ""
    local boolean changeWidth = width > 0
    local integer minCol
    local integer maxCol
    local integer minRow
    local integer maxRow
    local integer i
    local integer j
    if col == - 1 then
        set minCol = 0
        set maxCol = MultiboardGetColumnCount( mb )
    else
        set minCol = col
        set maxCol = col + 1
    endif
    if row == -1 then
        set minRow = 0
        set maxRow = MultiboardGetRowCount( mb )
    else
        set minRow = row
        set maxRow = row + 1
    endif
    
    set col = minCol
    
    loop
        exitwhen col >= maxCol
        
        set row = minRow
        loop
            exitwhen row >= maxRow
            set curItem = MultiboardGetItem( mb, row, col )
            if whichplayer == null or whichplayer == LOCAL_PLAYER then
                call MultiboardSetItemStyle( curItem, showValue, showIcon )
                if showIcon then
                    call MultiboardSetItemIcon( curItem, iconfilename )
                endif
                if showValue then
                    call MultiboardSetItemValue( curItem, value )
                endif
                if changeWidth then
                    call MultiboardSetItemWidth( curItem, width )
                endif
            endif
            call MultiboardReleaseItem( curItem ) 
            set row = row + 1
        endloop
        set col = col + 1
    endloop
    
endfunction

function Char2I takes string char, integer min, integer max returns integer
    local integer index
    local string toInt = SubString( char, min, max )
    local integer stringPos = StringLength( toInt ) - 1
    local integer stringValue = 1
    local string curChar
    local integer returnValue = 0

    set char = StringCase( toInt, false )
    loop
        exitwhen stringPos < 0
        set index = 0
        set curChar = SubString( char, stringPos, stringPos + 1 )
        loop
            exitwhen index == LETTERS
            if curChar == LETTER[ index ] then
                set returnValue = returnValue + index * stringValue
                exitwhen true
            endif
            set index = index + 1
        endloop
        set stringValue = stringValue * LETTERS
        set stringPos = stringPos - 1
    endloop
    return returnValue
endfunction

function I2Char takes integer i returns string 
    local string returnString = ""
    local integer curValue
    loop
        exitwhen i == 0
        set curValue = ModuloInteger( i, LETTERS )
        if curValue != 0 then
            set returnString = LETTER[ curValue ] + returnString
        endif
        set i = i / LETTERS
    endloop
    return returnString
endfunction

//! textmacro RandomString takes SCOPE, NAME
globals
    private string array $NAME$
    private integer $NAME$s = -1
endglobals
$SCOPE$ function Get$NAME$String takes nothing returns string
    return $NAME$[GetRandomInt( 0, $NAME$s )]
endfunction
$SCOPE$ function Add$NAME$String takes string toadd returns nothing
    set $NAME$s = $NAME$s + 1
    set $NAME$[ $NAME$s ] = toadd
endfunction
//! endtextmacro    

endlibrary


B2
- Added SetDisplayMultiboardSJ
- Fixed scope problems with RandomString
- Added LOCAL_PLAYER

B1
- Added RandomString
- Added Char2I / I2Char
- Added DisplayText
- Added SetMultiboardItemValue
 

Attachments

  • Utilities.txt
    30.1 KB · Views: 103
Last edited:
Level 40
Joined
Dec 14, 2005
Messages
10,532
Most of the code seems decent from the description, though I haven't had the opportunity to read the script yet.

However, as for the last feature, textmacros are evil. They shouldn't be used very often, and this is a prime example in which they're being abused more so than used.

Additionally, I find the constants to be a bit pointless, seeing as they're not something you'll ever want to (or be able to) change.

Finally, list tags are far more readable than dashes.
 
Level 6
Joined
Apr 16, 2007
Messages
177
Most of the code seems decent from the description, though I haven't had the opportunity to read the script yet.

However, as for the last feature, textmacros are evil. They shouldn't be used very often, and this is a prime example in which they're being abused more so than used.

Additionally, I find the constants to be a bit pointless, seeing as they're not something you'll ever want to (or be able to) change.

Finally, list tags are far more readable than dashes.

>> Most of the code seems decent
Thanks a lot ; )

>>I haven't had the opportunity to read the script yet
If you do, keep out the SetPlayerAllianceStateSJ function. It is actually the code of SetPlayerAllianceStateBJ just that it allies in both ways and is inlined, saving 9-10 function calls and 50% of the ifs.

>>[T]extmacros are evil
But do a great job when I need multiple instances that do not overlap.
EG in my map I use them for three purposes (currently), and it is just a lot easier to type
JASS:
//! runtextmacro State2Text( "Life" )
//! runtextmacro State2Text( "DepotState" )
//! runtextmacro State2Text( "Stash" )
than copy/pasting the whole code three times, and then replacing the name everytime.

>>constants [are] a bit pointless
The constants, at least for me, increase maintainability and readability.
Imagine you have a loop running from 0 to 11, then you first need to look at the rest of the code to get where these numbers are actually coming from.
If you use however from 0 to MAX_USER_SLOT, it is clear that the rest of the loop is user-related.
The color strings really make life easier.
JASS:
RED + "action" + WHITE + "related"
is far more readable than
JASS:
"|cffff3333action|rrelated"
Also, it is just easier to use than copying the |cff... string everytime, and if you want to change the RED used in your (diverse) triggers to a darker red - have fun!
Here you just set RED to, for example, "|ca02020".
With the AUTOCOLOR_NAMES: Well, if a player wants to use PlayerName with the color of the rest of the string, he should set this to false. I'll add an PlayerNameUncolored soon that will make this constant meaningless.
LEAVER_MESSAGE_A and _B are usefull when you want to print "The coward ___ has fled the battlefield!" or "Leaver detected: ____ ", becouse you don't have to go through the xyz lines of code ; )
The other constants are ( normally ) just for use within the library anyway.

>> they're not something you'll ever want to (or be able to) change
That's the point of Constants, allright :p

>>list tags are far more readable than dashes
Will be changed, master ; )

Cheers, Davey

EDIT: It are actually 9-10 Function calls, if not even more (with the passive states). I just didn't see the BJ calls BJs itself, which I had also cleared up ; )
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Textmacros could easily be replaced by gamecache, saving a lot of code.

Constants: fair enough. I was only referring to MAX_PLAYER_SLOT/MAX_USER_SLOT/MAX_INVENTORY_SLOT, though.

As for LEAVER_MESSAGE_A and B, you could always allow for a sort of string parsing system, for example "%p has left the game.", for ease of use.

That's the point of Constants, allright :p
Nah, constants (at least generally) are things that won't change ingame, but are subject to change in the code. There are of course exceptions, usually when function calls are otherwise required.

However, I'd imagine the main reason Jass has most of its constants is because it was being coded as the game was, and thus things weren't always the same.

As for the code:

SetPlayerAllianceStateSJ could be optimized a lot.

CreateNUnits(/Order): Add an option for facing? In the second, you could have them face the direction of the order.

GetClosestUnitInRange should use a global group, shared with anything else in the map.

CreateBountyText should support custom colours, or at least a variant should.
 
Level 6
Joined
Apr 16, 2007
Messages
177
Textmacros could easily be replaced by gamecache, saving a lot of code.

Constants: fair enough. I was only referring to MAX_PLAYER_SLOT/MAX_USER_SLOT/MAX_INVENTORY_SLOT, though.

As for LEAVER_MESSAGE_A and B, you could always allow for a sort of string parsing system, for example "%p has left the game.", for ease of use.

Nah, constants (at least generally) are things that won't change ingame, but are subject to change in the code. There are of course exceptions, usually when function calls are otherwise required.

However, I'd imagine the main reason Jass has most of its constants is because it was being coded as the game was, and thus things weren't always the same.

As for the code:

SetPlayerAllianceStateSJ could be optimized a lot.

CreateNUnits(/Order): Add an option for facing? In the second, you could have them face the direction of the order.

GetClosestUnitInRange should use a global group, shared with anything else in the map.

CreateBountyText should support custom colours, or at least a variant should.

>>Textmacros could easily be replaced by gamecache
I have to admit that my knowledge on GC is really limited. So I need to ask you, how would that feature work with GC? Thanks in advance.

>>CreateNUnits(/Order): Add an option for facing
Will do.

>>Constants: fair enough. I was only referring to MAX_PLAYER_SLOT/MAX_USER_SLOT/MAX_INVENTORY_SLOT, though.
As I said, I use them for making the code easier to understand.

>>CreateBountyText should support custom colours
In fact, it does. It did before with a constant in the non-parameters block, the next uploaded version will use the GOLD string for coloring and the RED string for neg coloring. Would that be fine?

>>SetPlayerAllianceStateSJ could be optimized a lot.
Hm yes a really basic hashtable should do here. I'll work on it, but more than 4 ifs ( avg ) cannot be saved I think. That doesn't sound "a lot" for me :/

>>LEAVER_MESSAGE_A and B you could always allow for a sort of string parsing system
Ummm... I just finished a chomsky-level 0 parsing program for python :D
And Compiler building is really a pain in the neck.
Do you think I should write a regex library for JASS?
Really seems like an interesting idea, but I'm out of time currently. %p will for sure be added.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
In fact, it does. It did before with a constant in the non-parameters block, the next uploaded version will use the GOLD string for coloring and the RED string for neg coloring. Would that be fine?
What I meant was more a CreateBountyTextCustomColored(...,RED,...) sort of thing.

Hm yes a really basic hashtable should do here. I'll work on it, but more than 4 ifs ( avg ) cannot be saved I think. That doesn't sound "a lot" for me :/
Ifs don't need removal. However, the majority of the calls are redundant, and could be consolidated in a way which doesn't clog them inside individual ifs (IE most of them are the same no matter the condition, with the exception of unally, which is easily implemented with a single, outside if).

Ummm... I just finished a chomsky-level 0 parsing program for python :D
And Compiler building is really a pain in the neck.
Do you think I should write a regex library for JASS?
Really seems like an interesting idea, but I'm out of time currently. %p will for sure be added.
A replace() function isn't that hard to code. In fact, I posted one somewhere a bit ago, if you want me to dig it up.

I have to admit that my knowledge on GC is really limited. So I need to ask you, how would that feature work with GC? Thanks in advance.
You would store the info as a type (say, a string, or maybe just a bunch of ints, or whatever you want) under the category name of your 'operator' (ex "Life").
 
Level 6
Joined
Apr 16, 2007
Messages
177
What I meant was more a CreateBountyTextCustomColored(...,RED,...) sort of thing.

Ifs don't need removal. However, the majority of the calls are redundant, and could be consolidated in a way which doesn't clog them inside individual ifs (IE most of them are the same no matter the condition, with the exception of unally, which is easily implemented with a single, outside if).

A replace() function isn't that hard to code. In fact, I posted one somewhere a bit ago, if you want me to dig it up.

You would store the info as a type (say, a string, or maybe just a bunch of ints, or whatever you want) under the category name of your 'operator' (ex "Life").
[all comments concerning ver A2+]
>>CreateBountyTextCustomColored(...,RED,...)
Message understood ; )
CreateColoredBountyText( color, integer, unit, getter ) has been implemented.

>>the majority of the calls are redundant
Too bad I just removed all the ifs (added one for safety issues, though). And no, I don't think the calls are redundant. There is only 16 calls anyway, and doing large checks ( is state xyz == true etc ) shouldn't really improve the efficience anyway.

>> replace()
I actually split the LEAVER_MESSAGE into two strings, one to the left of the %p and one to the right of the %p, and then save them into to globals

>> store the info as a type
And how would I get from 92% the string that is related to 90%?

Thx for your help, Serra

EDIT: I forgot to add the +2 in the splitting function. Bugfixed ver will be uploaded (A3=
 
Last edited:
Level 6
Joined
Apr 16, 2007
Messages
177
Your new AllianceState implementation is fine.

The same way you currently do it.

Anyways, I'll most likely approve this soon, but I need to give it a customary test run first, as with everything.

I actually found two tiny bugs, one that sets player names of empty slots to
the wrong player number ( Player 4 (N/A) for player 5 ), and a memory leak in the GetClosestUnitInRange function ( I forgot to destroy the group ; ) )
Both are fixed in A4. Will upload after I went shopping.

Greetings, Davey

EDIT: Upload done.
 
Last edited:
Level 6
Joined
Apr 16, 2007
Messages
177
The biggest thing that currently needs fixing is that the system doesn't take custom player colour picking into account.

The problem is just that I cannot set the team colors of a unit to something different than any of the preset colors, and that I have no idea if this is even fixable using (only!) code. I don't think so, but if it is, I'll find a way.

A5 now sets the PlayerName[ ] string correctly when you're using SetPlayerColors( id, r, g, b ), so you no longer need to to it yourself.

PS: I had tried out coloring player names in the gameplay interface, and it perfectly worked out for me, but for other players my name displayed like a weird mix of my name and some random literals.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
JASS:
native GetPlayerColor           takes player whichPlayer returns playercolor
    constant playercolor        PLAYER_COLOR_RED                = ConvertPlayerColor(0)
    constant playercolor        PLAYER_COLOR_BLUE               = ConvertPlayerColor(1)
    constant playercolor        PLAYER_COLOR_CYAN               = ConvertPlayerColor(2)
    constant playercolor        PLAYER_COLOR_PURPLE             = ConvertPlayerColor(3)
    constant playercolor        PLAYER_COLOR_YELLOW             = ConvertPlayerColor(4)
    constant playercolor        PLAYER_COLOR_ORANGE             = ConvertPlayerColor(5)
    constant playercolor        PLAYER_COLOR_GREEN              = ConvertPlayerColor(6)
    constant playercolor        PLAYER_COLOR_PINK               = ConvertPlayerColor(7)
    constant playercolor        PLAYER_COLOR_LIGHT_GRAY         = ConvertPlayerColor(8)
    constant playercolor        PLAYER_COLOR_LIGHT_BLUE         = ConvertPlayerColor(9)
    constant playercolor        PLAYER_COLOR_AQUA               = ConvertPlayerColor(10)
    constant playercolor        PLAYER_COLOR_BROWN              = ConvertPlayerColor(11)
 
Level 6
Joined
Apr 16, 2007
Messages
177
JASS:
native GetPlayerColor           takes player whichPlayer returns playercolor
    constant playercolor        PLAYER_COLOR_RED                = ConvertPlayerColor(0)
    constant playercolor        PLAYER_COLOR_BLUE               = ConvertPlayerColor(1)
    constant playercolor        PLAYER_COLOR_CYAN               = ConvertPlayerColor(2)
    constant playercolor        PLAYER_COLOR_PURPLE             = ConvertPlayerColor(3)
    constant playercolor        PLAYER_COLOR_YELLOW             = ConvertPlayerColor(4)
    constant playercolor        PLAYER_COLOR_ORANGE             = ConvertPlayerColor(5)
    constant playercolor        PLAYER_COLOR_GREEN              = ConvertPlayerColor(6)
    constant playercolor        PLAYER_COLOR_PINK               = ConvertPlayerColor(7)
    constant playercolor        PLAYER_COLOR_LIGHT_GRAY         = ConvertPlayerColor(8)
    constant playercolor        PLAYER_COLOR_LIGHT_BLUE         = ConvertPlayerColor(9)
    constant playercolor        PLAYER_COLOR_AQUA               = ConvertPlayerColor(10)
    constant playercolor        PLAYER_COLOR_BROWN              = ConvertPlayerColor(11)

That is not what I meant.
I meant something like
JASS:
local playercolor black = PlayerColor( 0, 0, 0 )
call SetPlayerColor( Players[ 0 ], black )
, allowing you to define your CUSTOM player colors. As I said:
something different than any of the preset colors
. With preset colors, I referred to these you mentioned above.

Thanks for trying to help, though.
 
Level 6
Joined
Apr 16, 2007
Messages
177
Ah, I guess you misunderstood what I meant, and I misunderstood what you thought I meant :p

What I mean is that if Player 1 changes their color to Blue in a game that allows this (before the game starts), this system detects them as Red.

Also, you can set someone's playercolor to black.
>>if Player 1 changes their color to Blue in a game that allows this (before the game starts), this system detects them as Red.

Ahhh. Got it. Will change it.

>>Also, you can set someone's playercolor to black.

That was just a bad example. I meant a CUSTOM player color.

EDIT: Fixed the issue.
 
Last edited:
Level 8
Joined
Oct 3, 2008
Messages
367
I feel that a big bad system that does anything and everything doesn't belong as a resource. Every user should pretty much have their own library that does repetitive tasks the way they like it.

Just my opinion, and would like some more opinions before I take any action.
 
Top