(Keeps Hive Alive)
Go Back   The Hive Workshop - A Warcraft III Modding Site > Warcraft III Resources > Submissions

Submissions Submit JASS resources! If approved, they will be moved to their proper section.
Please read me first.

Reply
 
LinkBack Thread Tools Display Modes
Old 09-10-2008, 01:55 PM   #1 (permalink)
 
SerraAvenger's Avatar

How may I serve you?
 
Join Date: Apr 2007
Posts: 100

SerraAvenger has little to show at this moment (3)


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

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
    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:
    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.
    //! runtextmacro RandomString( "Name" )
    for Stack Creation;
    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.
    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.
    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:
    //! runtextmacro State2Text( "Life" )
    now in any function you can call
    call Text2Life( GREY + "Dead", -1 )
    call Text2Life( State2Color( 0.2) + "Wounded", 0.0 )
    call Text2Life( GREEN + "Ok", 0.6 )
    and then
    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:
    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
Code


//----------------------------\\
// 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