A "Swap" system, needed ? (From a command in "DotA" ;))

roaaaarrrr

New Member
Reaction score
33
One thing I ran into when we made a swap system for Footmen Frenzy was an issue with items. A lot of maps will start the hero with certain items (tp or something like that) and players were able to abuse this with swap systems. So we basically had to save the exact stats/items/xp/everything in the code to ensure there weren't any unseen/unfair advantages to be gained from swapping.
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Well, I might add the "keep items" feature as a constant, but since you will still need both players' consent to be able to swap, you shouldn't swap with players who have a worse hero than you :p
 

Blackrage

Ultra Cool Member
Reaction score
25
This seems really useful, though I think you should have a constant to see if you want items to switch over, and also a constant if you want the heroes to unlearn all their abilities.
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Sure, I can add that ! :D

And how would I go about making them unlearn their abilities ? :S
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Anyone wanna try this out now ? :S

JASS:
library SwapHeroes initializer Init requires SimError, optional TimerUtils, optional PlayerColors

    globals
        private constant boolean HEROES_ON_INIT = true      // Change this to true, if each player has a 'single' hero at Map Init !
        
        private constant boolean SWAP_NEUTRALS = false      // If you want the players to be able to swap heroes with the &#039;neutral&#039; players (They don&#039;t have to write &quot;-swap ##&quot; back <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite7" alt=":p" title="Stick Out Tongue    :p" loading="lazy" data-shortname=":p" />)
        
        private constant boolean SWAP_ALLIES_ONLY = true    // If you only want the players to be able to swap with their allies !
        
        private constant boolean SWITCH_POSITIONS = true    // If you want the swapped heroes to also swap positions <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin    :D" loading="lazy" data-shortname=":D" />
        private constant boolean SWAP_ITEMS = true
        private constant boolean UNLEARN_ABILITIES = false
        
        private constant boolean REVIVE_IF_DEAD = true      // If you swap with a player, and it&#039;s currently dead, then if this is true it&#039;ll revive the unit also <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin    :D" loading="lazy" data-shortname=":D" />
        private constant boolean ELSE_DONT_SWAP = false
        
        private constant boolean USE_GUI_PLAYER_IDS = false
        
        private constant boolean USE_PLAYERS_COLOR_ON_NAME = true
        
        private constant boolean RETAIN_PLAYER_COLORS = false
        
        private constant boolean ONE_SWAP_ONLY = false
        
        private constant boolean SWAP_TIME_LIMIT = true
        private constant real TIME_LIMIT = 30.
        
        private constant string SWAP_COMMAND = &quot;-swap &quot;
        
        private constant boolean ENABLE_CANCEL_COMMAND = true
        private constant string CANCEL_SWAP_CMD = &quot;-swapcancel&quot;
        
        private constant boolean ENABLE_RESWAP = true
        private constant string RESWAP_COMMAND = &quot;-reswap&quot;
        private constant boolean RESWAP_TIME_LIMIT = true
        private constant real RESWAP_TIME = 10.
        private constant boolean NEED_BOTHS_CONSENT = true
        private constant boolean RESWAP_ONCE_ONLY = true        
    endglobals
    
    native UnitAlive takes unit id returns boolean
    
    globals
        private hashtable TimerHash
    endglobals
    
    static if HEROES_ON_INIT then
    
        globals
            private group ENUM = CreateGroup()
            
            private integer tempInt = 0
        endglobals
        
    endif

    private struct SwapData extends array
        boolean hasSwapped
        
        unit swapUnit
        unit targetUnit
        unit reswapUnit
        
        player swapPlayer
        player targetPlayer
        player reswapPlayer
        
        static if SWAP_TIME_LIMIT then
            timer resetTimer
        endif
        
        static if ENABLE_RESWAP then
            timer reswapTimer
        endif
        
        static if SWAP_TIME_LIMIT then
        
            static method ResetSwapData takes nothing returns nothing
                local thistype this
                
                static if LIBRARY_TimerUtils then
                    set this = GetTimerData( GetExpiredTimer() )
                else
                    set this = LoadInteger( TimerHash, GetHandleId( GetExpiredTimer() ), 1 )
                endif
                
                set this.targetUnit = null
                set this.targetPlayer = null
                
                static if LIBRARY_TimerUtils then
                    call ReleaseTimer( GetExpiredTimer() )
                else
                    call PauseTimer( GetExpiredTimer() )
                    call DestroyTimer( GetExpiredTimer() )
                    
                    set this.resetTimer = null
                endif
                
            endmethod
            
        endif
        
        static if ENABLE_RESWAP then
        
            static method StopReswap takes nothing returns nothing
                local thistype this
                local player pt
                
                static if LIBRARY_TimerUtils then
                    set this = GetTimerData( GetExpiredTimer() )
                else
                    set this = LoadInteger( TimerHash, GetHandleId( GetExpiredTimer() ), 2 )
                endif
                
                set pt = this.reswapPlayer
                
                set this.reswapPlayer = null
                set this.reswapUnit = null
                set SwapData[ GetPlayerId( pt ) ].reswapPlayer = null
                set SwapData[ GetPlayerId( pt ) ].reswapUnit = null
                
                static if LIBRARY_TimerUtils then
                    call ReleaseTimer( GetExpiredTimer() )
                    call ReleaseTimer( SwapData[ GetPlayerId( pt ) ].reswapTimer )
                else
                    call PauseTimer( GetExpiredTimer() )
                    call DestroyTimer( GetExpiredTimer() )
                    
                    set this.reswapTimer = null
                    
                    call PauseTimer( SwapData[ GetPlayerId( pt ) ].reswapTimer )
                    call DestroyTimer( SwapData[ GetPlayerId( pt ) ].reswapTimer )
                    
                    set SwapData[ GetPlayerId( pt ) ].reswapTimer = null
                endif
                
            endmethod
        
        endif
        
    endstruct
        
    private function SwapActions takes nothing returns boolean
        local player p
        local player pt
        local string s = GetEventPlayerChatString()
        local boolean conds
        local unit temp = null
        
        static if SWAP_ITEMS then
            local integer array firstHeros
            local integer array secHeros
            local integer loops = 0
        endif
        
        if SubString( s, 0, StringLength( SWAP_COMMAND ) ) == SWAP_COMMAND then
            set p = GetTriggerPlayer()
            
            static if USE_GUI_PLAYER_IDS then
                set pt = Player( S2I( SubString( s, StringLength( SWAP_COMMAND ), StringLength( s ) ) ) - 1 )
            else
                set pt = Player( S2I( SubString( s, StringLength( SWAP_COMMAND ), StringLength( s ) ) ) )
            endif
            
            static if SWAP_NEUTRALS then
                set conds = GetPlayerId( pt ) &gt;= 16 or GetPlayerId( pt ) &lt; 0 or pt == null or SwapData[ GetPlayerId( pt ) ].swapPlayer != null or pt == p or ( SWAP_ALLIES_ONLY and IsPlayerEnemy( p, pt ) )
            else
                set conds = GetPlayerId( pt ) &gt;= 12 or GetPlayerId( pt ) &lt; 0 or pt == null or SwapData[ GetPlayerId( pt ) ].swapPlayer != null or pt == p or ( SWAP_ALLIES_ONLY and IsPlayerEnemy( p, pt ) )
            endif
            
            // Make sure you type a valid player
            
            if conds then
                call SimError( p, &quot;You need to input a valid player-id !&quot; )
                
                return false
            endif
            
            // And also make sure you yourself have a valid hero to swap before starting <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite2" alt=";)" title="Wink    ;)" loading="lazy" data-shortname=";)" />
            
            if SwapData[ GetPlayerId( p ) ].swapUnit == null then
                call SimError( p, &quot;You need to have a swap hero eligible yourself, before you can use the -swap command !&quot; )
                
                return false
            endif
            
            if SwapData[ GetPlayerId( p ) ].hasSwapped == true and ONE_SWAP_ONLY then
                call SimError( p, &quot;You have already swapped once, and can&#039;t swap again...&quot; )
                
                return false
            endif
            
            if SwapData[ GetPlayerId( pt ) ].hasSwapped == true and ONE_SWAP_ONLY then
                call SimError( p, &quot;The player you wish to swap with has already swapped once, and can&#039;t swap again !&quot; )
                
                return false
            endif
            
            /*if SwapData[ GetPlayerId( pt ) ].targetPlayer != p and ONE_SWAP_ONLY then
                call SimError( p, &quot;The player you wish to swap with has already swapped once, and can&#039;t swap again !&quot; )
                
                return false
            endif*/
            
            if ELSE_DONT_SWAP then
            
                if not UnitAlive( SwapData[ GetPlayerId( p ) ].swapUnit ) then
                    call SimError( p, &quot;Your swap-unit needs to be alive to be allowed to swap !&quot; )
                    
                    return false
                endif
                
                if not UnitAlive( SwapData[ GetPlayerId( pt ) ].swapUnit ) then
                    call SimError( p, &quot;Your swap-player has a dead swap-unit, and you cannot swap then !&quot; )
                    
                    return false
                endif
                
            endif
            
            if SWAP_TIME_LIMIT then
                
                static if LIBRARY_TimerUtils then
                    call ReleaseTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                    call ReleaseTimer( SwapData[ GetPlayerId( pt ) ].resetTimer )
                else
                    call PauseTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                    call DestroyTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                    
                    set SwapData[ GetPlayerId( p ) ].resetTimer = null
                    
                    call PauseTimer( SwapData[ GetPlayerId( pt ) ].resetTimer )
                    call DestroyTimer( SwapData[ GetPlayerId( pt ) ].resetTimer )
                    
                    set SwapData[ GetPlayerId( pt ) ].resetTimer = null
                endif
                
            endif
            
            set SwapData[ GetPlayerId( p ) ].targetPlayer = pt
            set SwapData[ GetPlayerId( p ) ].targetUnit = SwapData[ GetPlayerId( p ) ].swapUnit
            
            // Start switch ! <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin    :D" loading="lazy" data-shortname=":D" />            
            
            if SwapData[ GetPlayerId( pt ) ].targetPlayer == p and SwapData[ GetPlayerId( pt ) ].targetUnit == SwapData[ GetPlayerId( p ) ].swapUnit then
                set temp = SwapData[ GetPlayerId( p ) ].swapUnit
                
                static if SWAP_ITEMS then
                
                    loop
                        set firstHeros[loops] = GetItemTypeId( UnitItemInSlot( temp, loops ) )
                        
                        call RemoveItem( UnitItemInSlot( temp, loops ) )
                        
                        set secHeros[loops] = GetItemTypeId( UnitItemInSlot( SwapData[ GetPlayerId( pt ) ].swapUnit, loops ) )
                        
                        call RemoveItem( UnitItemInSlot( SwapData[ GetPlayerId( pt ) ].swapUnit, loops ) )
                        call UnitAddItemToSlotById( temp, firstHeros[loops], loops )
                        call UnitAddItemToSlotById( temp, secHeros[loops], loops )
                        
                        set loops = loops + 1
                        
                        exitwhen loops &gt;= 6
                    endloop
                    
                endif
                
                static if UNLEARN_ABILITIES then
                    call
                    
                endif
                
                static if RETAIN_PLAYER_COLORS then
                    call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, false )
                else
                    call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, true )
                endif
                
                set SwapData[ GetPlayerId( p ) ].swapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                
                
                static if RETAIN_PLAYER_COLORS then
                    call SetUnitOwner( temp, pt, false )
                else
                    call SetUnitOwner( temp, pt, true )
                endif
                
                set SwapData[ GetPlayerId( pt ) ].swapUnit = temp
                
                static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                    call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have accepted &quot; + GetPlayerNameColored( pt ) + &quot;&#039;s swap request !&quot; )
                    call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has accepted you request to swap heroes !&quot; )
                else
                    call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have accepted &quot; + GetPlayerName( pt ) + &quot;&#039;s swap request !&quot; )
                    call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has accepted you request to swap heroes !&quot; )
                endif
                        
                
                static if SWITCH_POSITIONS then
                    call SetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                    call SetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                    call SetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                    call SetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                endif
                
                static if REVIVE_IF_DEAD then
                
                    if not UnitAlive( SwapData[ GetPlayerId( pt ) ].swapUnit ) then
                        call ReviveHero( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ), true )
                    endif
                    
                    if not UnitAlive( SwapData[ GetPlayerId( p ) ].swapUnit ) then
                        call ReviveHero( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ), true )
                    endif
                    
                endif
                
                set SwapData[ GetPlayerId( p ) ].hasSwapped = true
                set SwapData[ GetPlayerId( pt ) ].hasSwapped = true
                
                static if LIBRARY_TimerUtils then
                    set SwapData[ GetPlayerId( p ) ].reswapTimer = NewTimer()
                    set SwapData[ GetPlayerId( pt ) ].reswapTimer = NewTimer()
                    
                    call SetTimerData( SwapData[ GetPlayerId( p ) ].reswapTimer, SwapData[ GetPlayerId( p ) ] )
                    call SetTimerData( SwapData[ GetPlayerId( pt ) ].reswapTimer, SwapData[ GetPlayerId( pt ) ] )
                else
                    set SwapData[ GetPlayerId( p ) ].reswapTimer = CreateTimer()
                    set SwapData[ GetPlayerId( pt ) ].reswapTimer = CreateTimer()
                    
                    call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( p ) ].reswapTimer ), 2, SwapData[ GetPlayerId( p ) ] )
                    call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( pt ) ].reswapTimer ), 2, SwapData[ GetPlayerId( pt ) ] )
                endif
                
                set SwapData[ GetPlayerId( p ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                set SwapData[ GetPlayerId( pt ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                set SwapData[ GetPlayerId( p ) ].reswapPlayer = pt
                set SwapData[ GetPlayerId( pt ) ].reswapPlayer = p
                
                static if ONE_SWAP_ONLY then
                    set SwapData[ GetPlayerId( p ) ].swapUnit = null
                    set SwapData[ GetPlayerId( pt ) ].swapUnit = null
                endif
                
                call TimerStart( SwapData[ GetPlayerId( p ) ].reswapTimer, RESWAP_TIME, false, function SwapData.StopReswap )
                call TimerStart( SwapData[ GetPlayerId( pt ) ].reswapTimer, RESWAP_TIME, false, function SwapData.StopReswap )
            else
        
                static if SWAP_TIME_LIMIT then
                    
                    static if LIBRARY_TimerUtils then
                        set SwapData[ GetPlayerId( p ) ].resetTimer = NewTimer()
                        
                        call SetTimerData( SwapData[ GetPlayerId( p ) ].resetTimer, SwapData[ GetPlayerId( p ) ] )
                    else
                        set SwapData[ GetPlayerId( p ) ].resetTimer = CreateTimer()
                        
                        call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( p ) ].resetTimer ), 1, SwapData[ GetPlayerId( p ) ] )
                    endif
                    
                    call TimerStart( SwapData[ GetPlayerId( p ) ].resetTimer, TIME_LIMIT, false, function SwapData.ResetSwapData )
                
                endif
                
                static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                    call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have sent a request to &quot; + GetPlayerNameColored( pt ) + &quot;, to swap heroes !&quot; )
                    call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has sent you a swap request ! Will you accept ?&quot; )                    
                else
                    call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have sent a request to &quot; + GetPlayerName( pt ) + &quot;, to swap heroes !&quot; )
                    call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has sent you a swap request ! Will you accept ?&quot; )
                endif
                
            endif
            
        endif
        
        set s = null
        set p = null
        set pt = null
        set temp = null
        
        return false
    endfunction
    
    static if ENABLE_RESWAP then
    
        private function Reswap takes nothing returns boolean
            local player p = GetTriggerPlayer()
            local player pt
            local unit temp = null
            
            static if SWAP_ITEMS then
                local integer array firstHeros
                local integer array secHeros
                local integer loops = 0
            endif
            
            if SwapData[ GetPlayerId( p ) ].reswapPlayer != null and SwapData[ GetPlayerId( p ) ].reswapUnit != null then
                set pt = SwapData[ GetPlayerId( p ) ].reswapPlayer
                
                if not ( UnitAlive( SwapData[ GetPlayerId( p ) ].swapUnit ) and REVIVE_IF_DEAD ) and ELSE_DONT_SWAP then
                    call SimError( p, &quot;Your reswap-hero needs to be alive !&quot; )
                    
                    return false
                endif
                
                if not ( UnitAlive( SwapData[ GetPlayerId( pt ) ].swapUnit ) and REVIVE_IF_DEAD ) and ELSE_DONT_SWAP then
                    call SimError( p, &quot;Your reswap-player&#039;s swap-unit needs to be alive !&quot; )
                    
                    return false
                endif
                
                static if NEED_BOTHS_CONSENT then
                    set SwapData[ GetPlayerId( p ) ].targetPlayer = pt
                    set SwapData[ GetPlayerId( p ) ].targetUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                    
                    if SwapData[ GetPlayerId( pt ) ].targetPlayer == p and SwapData[ GetPlayerId( pt ) ].targetUnit == SwapData[ GetPlayerId( p ) ].swapUnit then
                        set temp = SwapData[ GetPlayerId( p ) ].swapUnit
                        
                        static if SWAP_ITEMS then
                        
                            loop
                                set firstHeros[loops] = GetItemTypeId( UnitItemInSlot( temp, loops ) )
                                
                                call RemoveItem( UnitItemInSlot( temp, loops ) )
                                
                                set secHeros[loops] = GetItemTypeId( UnitItemInSlot( SwapData[ GetPlayerId( pt ) ].swapUnit, loops ) )
                                
                                call RemoveItem( UnitItemInSlot( SwapData[ GetPlayerId( pt ) ].swapUnit, loops ) )
                                call UnitAddItemToSlotById( temp, firstHeros[loops], loops )
                                call UnitAddItemToSlotById( temp, secHeros[loops], loops )
                                
                                set loops = loops + 1
                                
                                exitwhen loops &gt;= 6
                            endloop
                            
                        endif
                        
                        static if RETAIN_PLAYER_COLORS then
                            call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, false )
                        else
                            call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, true )
                        endif
                        
                        set SwapData[ GetPlayerId( p ) ].swapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                        
                        
                        static if RETAIN_PLAYER_COLORS then
                            call SetUnitOwner( temp, pt, false )
                        else
                            call SetUnitOwner( temp, pt, true )
                        endif
                        
                        set SwapData[ GetPlayerId( pt ) ].swapUnit = temp                 
                        
                        static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                            call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have accepted &quot; + GetPlayerNameColored( pt ) + &quot;&#039;s swap request !&quot; )
                            call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has accepted you request to swap heroes !&quot; )
                        else
                            call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have accepted &quot; + GetPlayerName( pt ) + &quot;&#039;s swap request !&quot; )
                            call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has accepted you request to swap heroes !&quot; )
                        endif
                                
                        
                        static if SWITCH_POSITIONS then
                            call SetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                            call SetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                            call SetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                            call SetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                        endif
                        
                        static if REVIVE_IF_DEAD then
                        
                            if not UnitAlive( SwapData[ GetPlayerId( pt ) ].swapUnit ) then
                                call ReviveHero( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ), true )
                            endif
                            
                            if not UnitAlive( SwapData[ GetPlayerId( p ) ].swapUnit ) then
                                call ReviveHero( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ), true )
                            endif
                            
                        endif
                        
                        set SwapData[ GetPlayerId( p ) ].hasSwapped = true
                        set SwapData[ GetPlayerId( pt ) ].hasSwapped = true
                        
                        static if LIBRARY_TimerUtils then
                            set SwapData[ GetPlayerId( p ) ].reswapTimer = NewTimer()
                            set SwapData[ GetPlayerId( pt ) ].reswapTimer = NewTimer()
                            
                            call SetTimerData( SwapData[ GetPlayerId( p ) ].reswapTimer, SwapData[ GetPlayerId( p ) ] )
                            call SetTimerData( SwapData[ GetPlayerId( pt ) ].reswapTimer, SwapData[ GetPlayerId( pt ) ] )
                        else
                            set SwapData[ GetPlayerId( p ) ].reswapTimer = CreateTimer()
                            set SwapData[ GetPlayerId( pt ) ].reswapTimer = CreateTimer()
                            
                            call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( p ) ].reswapTimer ), 2, SwapData[ GetPlayerId( p ) ] )
                            call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( pt ) ].reswapTimer ), 2, SwapData[ GetPlayerId( pt ) ] )
                        endif
                        
                        set SwapData[ GetPlayerId( p ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                        set SwapData[ GetPlayerId( pt ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                        set SwapData[ GetPlayerId( p ) ].reswapPlayer = pt
                        set SwapData[ GetPlayerId( pt ) ].reswapPlayer = p
                        set SwapData[ GetPlayerId( p ) ].swapUnit = null
                        set SwapData[ GetPlayerId( pt ) ].swapUnit = null
                        
                        call TimerStart( SwapData[ GetPlayerId( p ) ].reswapTimer, RESWAP_TIME, false, function SwapData.StopReswap )
                        call TimerStart( SwapData[ GetPlayerId( pt ) ].reswapTimer, RESWAP_TIME, false, function SwapData.StopReswap )
                    else
                
                        static if SWAP_TIME_LIMIT then
                    
                            static if LIBRARY_TimerUtils then
                                set SwapData[ GetPlayerId( p ) ].resetTimer = NewTimer()
                                
                                call SetTimerData( SwapData[ GetPlayerId( p ) ].resetTimer, SwapData[ GetPlayerId( p ) ] )
                            else
                                set SwapData[ GetPlayerId( p ) ].resetTimer = CreateTimer()
                                
                                call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( p ) ].resetTimer ), 1, SwapData[ GetPlayerId( p ) ] )
                            endif
                            
                            call TimerStart( SwapData[ GetPlayerId( p ) ].resetTimer, TIME_LIMIT, false, function SwapData.ResetSwapData )
                        
                        endif
                        
                        static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                            call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have sent a request to &quot; + GetPlayerNameColored( pt ) + &quot;, to swap heroes !&quot; )
                            call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has sent you a swap request ! Will you accept ?&quot; )
                        else
                            call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have sent a request to &quot; + GetPlayerName( pt ) + &quot;, to swap heroes !&quot; )
                            call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has sent you a swap request ! Will you accept ?&quot; )
                        endif
                        
                    endif
                    
                else
                    set temp = SwapData[ GetPlayerId( p ) ].swapUnit
                    
                    static if RETAIN_PLAYER_COLORS then
                        call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, false )
                    else
                        call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, true )
                    endif
                    
                    set SwapData[ GetPlayerId( p ) ].swapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                    
                    
                    static if RETAIN_PLAYER_COLORS then
                        call SetUnitOwner( temp, pt, false )
                    else
                        call SetUnitOwner( temp, pt, true )
                    endif
                    
                    set SwapData[ GetPlayerId( pt ) ].swapUnit = temp
                    
                    static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                        call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have now reswapped your hero from &quot; + GetPlayerNameColored( pt ) + &quot; and given him your hero !&quot; )
                        call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has reswapped his hero from you, and you&#039;ve gotten yours back too !&quot; )
                    else
                        call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have accepted &quot; + GetPlayerName( pt ) + &quot;&#039;s swap request !&quot; )
                        call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has accepted you request to swap heroes !&quot; )
                    endif
                            
                    
                    static if SWITCH_POSITIONS then
                        call SetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                        call SetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                        call SetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                        call SetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                    endif
                    
                    static if REVIVE_IF_DEAD then
                    
                        if not UnitAlive( SwapData[ GetPlayerId( pt ) ].swapUnit ) then
                            call ReviveHero( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ), true )
                        endif
                        
                        if not UnitAlive( SwapData[ GetPlayerId( p ) ].swapUnit ) then
                            call ReviveHero( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ), true )
                        endif
                        
                    endif
                    
                    set SwapData[ GetPlayerId( p ) ].hasSwapped = true
                    set SwapData[ GetPlayerId( pt ) ].hasSwapped = true
                    
                    static if LIBRARY_TimerUtils then
                        set SwapData[ GetPlayerId( p ) ].reswapTimer = NewTimer()
                        set SwapData[ GetPlayerId( pt ) ].reswapTimer = NewTimer()
                        
                        call SetTimerData( SwapData[ GetPlayerId( p ) ].reswapTimer, SwapData[ GetPlayerId( p ) ] )
                        call SetTimerData( SwapData[ GetPlayerId( pt ) ].reswapTimer, SwapData[ GetPlayerId( pt ) ] )
                    else
                        set SwapData[ GetPlayerId( p ) ].reswapTimer = CreateTimer()
                        set SwapData[ GetPlayerId( pt ) ].reswapTimer = CreateTimer()
                        
                        call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( p ) ].reswapTimer ), 2, SwapData[ GetPlayerId( p ) ] )
                        call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( pt ) ].reswapTimer ), 2, SwapData[ GetPlayerId( pt ) ] )
                    endif
                    
                    static if not RESWAP_ONCE_ONLY then
                        set SwapData[ GetPlayerId( p ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                        set SwapData[ GetPlayerId( pt ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                        set SwapData[ GetPlayerId( p ) ].reswapPlayer = pt
                        set SwapData[ GetPlayerId( pt ) ].reswapPlayer = p
                    endif
                    
                    set SwapData[ GetPlayerId( p ) ].targetUnit = null
                    set SwapData[ GetPlayerId( pt ) ].targetUnit = null
                endif
                    
            endif
            
            return false
        endfunction
    
    endif
    
    private function PickInitHeroes takes nothing returns boolean
        local unit u = GetFilterUnit()
        local player p = GetOwningPlayer( u )
        
        if tempInt == 0 and IsUnitType( u, UNIT_TYPE_HERO ) and not IsUnitType( u, UNIT_TYPE_STRUCTURE ) and UnitAlive( u ) and SwapData[ GetPlayerId( p ) ].swapUnit == null then
            set SwapData[ GetPlayerId( p ) ].swapUnit = u
            set tempInt = 1
        endif
        
        set u = null
        set p = null
        
        return false
    endfunction

    private function OnInitHeroes takes nothing returns nothing
        local integer i = 0
        local player p
        
        loop
        
            static if SWAP_NEUTRALS then
                exitwhen i &gt;= 16
            else
                exitwhen i &gt;= 12
            endif
            
            set tempInt = 0
            set p = Player( i )
            
            if SwapData[ GetPlayerId( p ) ].swapUnit != null and GetPlayerController( p ) == MAP_CONTROL_USER and GetPlayerController( p ) == PLAYER_SLOT_STATE_PLAYING then                    
                call GroupEnumUnitsOfPlayer( ENUM, p, Filter( function PickInitHeroes ) )
            endif
            
            set i = i + 1
        endloop
    
        set p = null
    endfunction
    
    static if ENABLE_CANCEL_COMMAND then
    
        private function CancelSwap takes nothing returns boolean
            local player p = GetTriggerPlayer()
            local player pt = SwapData[ GetPlayerId( p ) ].targetPlayer
            
            if TimerGetRemaining( SwapData[ GetPlayerId( p ) ].resetTimer ) &gt; 0 then
                
                static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                    call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have cancelled the request to swap heroes with &quot; + GetPlayerNameColored( pt ) + &quot; !&quot; )
                    call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has cancelled his request to swap heroes with you !&quot; )
                else
                    call DisplayTextToPlayer( pt, 0.0, 0.0, &quot;You have cancelled the request to swap heroes with &quot; + GetPlayerName( pt ) + &quot; !&quot; )
                    call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has cancelled his request to swap heroes with you !&quot; )
                endif
                
                set SwapData[ GetPlayerId( p ) ].targetPlayer = null
                set SwapData[ GetPlayerId( p ) ].targetUnit = null
                
                static if SWAP_TIME_LIMIT then
                
                    static if LIBRARY_TimerUtils then
                        call ReleaseTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                    else
                        call PauseTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                        call DestroyTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                        
                        set SwapData[ GetPlayerId( p ) ].resetTimer = null
                    endif
                    
                endif
        
            endif
        
            return false
        endfunction
        
    endif

    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i = 0
        local player p = null
        
        loop
        
            set p = Player( i )
        
            static if SWAP_NEUTRALS then
                exitwhen i &gt;= 16
                
                if i &gt;= 12 and ( GetPlayerController( p ) == MAP_CONTROL_COMPUTER or GetPlayerController( p ) == MAP_CONTROL_CREEP ) then
                    set SwapData[ GetPlayerId( p ) ].hasSwapped = false
                    set SwapData[ GetPlayerId( p ) ].swapPlayer = p
                endif
                    
            else
                exitwhen i &gt;= 12
            endif
            
            if GetPlayerController( p ) == MAP_CONTROL_USER and GetPlayerSlotState( p ) == PLAYER_SLOT_STATE_PLAYING then
                call TriggerRegisterPlayerChatEvent( t, p, SWAP_COMMAND, false )
                
                set SwapData[ GetPlayerId( p ) ].hasSwapped = false
                set SwapData[ GetPlayerId( p ) ].swapPlayer = p
            endif
            
            set i = i + 1
        endloop
        
        call TriggerAddCondition( t, Condition( function SwapActions ) )
        
        static if ENABLE_CANCEL_COMMAND then
            set t = CreateTrigger()
            set i = 0
            
            loop
                exitwhen i &gt;= 12
                
                set p = Player( i )
                
                if GetPlayerController( p ) == MAP_CONTROL_USER and GetPlayerSlotState( p ) == PLAYER_SLOT_STATE_PLAYING then
                    call TriggerRegisterPlayerChatEvent( t, p, CANCEL_SWAP_CMD, false )
                endif
                
                set i = i + 1
            endloop
            
            call TriggerAddCondition( t, Condition( function CancelSwap ) )
        endif
        
        static if ENABLE_RESWAP then
            set t = CreateTrigger()
            set i = 0
            
            loop
                exitwhen i &gt;= 12
                
                set p = Player( i )
                
                if GetPlayerController( p ) == MAP_CONTROL_USER and GetPlayerSlotState( p ) == PLAYER_SLOT_STATE_PLAYING then
                    call TriggerRegisterPlayerChatEvent( t, p, RESWAP_COMMAND, false )
                endif
                
                set i = i + 1
            endloop
            
            call TriggerAddCondition( t, Condition( function Reswap ) )
        endif
        
        static if HEROES_ON_INIT then
            call OnInitHeroes()
        endif
        
        static if not LIBRARY_TimerUtils then
            
            static if SWAP_TIME_LIMIT then
                set TimerHash = InitHashtable()
            elseif RESWAP_TIME then
                set TimerHash = InitHashtable()
            endif
            
        endif
        
        set p = null
        set t = null
    endfunction
    
endlibrary


Supports swapping items :D (I think :S XD)
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Bump...

Anyone could help me ? :S
Or maybe you'd like to see something added ? :eek:
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Well, not player 1 of team two, but Player 1 (Red)... (Or if you use JASS players, it's Player 2 (Blue) :p)
 

tooltiperror

Super Moderator
Reaction score
231
You should add team switching.

Like, if a player types -swap all then every player switches or something. Or a -random and you switch with a random player.
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Well, I'm not too sure about the "-swap all" command, but the random is a good idea :D
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Ok, so I think I've added the "-swap random" command correctly now :S

I'm really sorry to ask you guys for something so extensive, but is there anyone out there that's willing to test this out VERY thoroughly ? :S
Like test every aspect of it, and also with different variations of the constants used ?

Anyways, here's the updated code :D

JASS:
library SwapHeroes initializer Init requires SimError, optional TimerUtils, optional PlayerColors

    globals
        private constant boolean HEROES_ON_INIT = true      // Change this to true, if each player has a &#039;single&#039; hero at Map Init !
        
        private constant boolean SWAP_NEUTRALS = false      // If you want the players to be able to swap heroes with the &#039;neutral&#039; players (They don&#039;t have to write &quot;-swap ##&quot; back <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite7" alt=":p" title="Stick Out Tongue    :p" loading="lazy" data-shortname=":p" />)
        
        private constant boolean SWAP_ALLIES_ONLY = true    // If you only want the players to be able to swap with their allies !
        
        private constant boolean SWITCH_POSITIONS = true    // If you want the swapped heroes to also swap positions <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin    :D" loading="lazy" data-shortname=":D" />
        private constant boolean SWAP_ITEMS = true
        private constant boolean UNLEARN_ABILITIES = false
        
        private constant boolean REVIVE_IF_DEAD = true      // If you swap with a player, and it&#039;s currently dead, then if this is true it&#039;ll revive the unit also <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin    :D" loading="lazy" data-shortname=":D" />
        private constant boolean ELSE_DONT_SWAP = false
        
        private constant boolean USE_GUI_PLAYER_IDS = false
        
        private constant boolean USE_PLAYERS_COLOR_ON_NAME = true
        
        private constant boolean RETAIN_PLAYER_COLORS = false
        
        private constant boolean ONE_SWAP_ONLY = false
        
        private constant boolean SWAP_TIME_LIMIT = true
        private constant real TIME_LIMIT = 30.
        
        private constant string SWAP_COMMAND = &quot;-swap &quot;
        
        private constant boolean ENABLE_CANCEL_COMMAND = true
        private constant string CANCEL_SWAP_CMD = &quot;-swapcancel&quot;
        
        private constant boolean ENABLE_RESWAP = true
        private constant string RESWAP_COMMAND = &quot;-reswap&quot;
        private constant boolean RESWAP_TIME_LIMIT = true
        private constant real RESWAP_TIME = 10.
        private constant boolean NEED_BOTHS_CONSENT = true
        private constant boolean RESWAP_ONCE_ONLY = true      
        
        private constant boolean ENABLE_RANDOM_SWAP = true
        private constant string RANDOM_SWAP_CMD = &quot;-swap random&quot;
    endglobals
    
    native UnitAlive takes unit id returns boolean
    
    globals
        private hashtable TimerHash
    endglobals
    
    static if HEROES_ON_INIT then
    
        globals
            private group ENUM = CreateGroup()
            
            private integer tempInt = 0
        endglobals
        
    endif

    private struct SwapData extends array
        boolean hasSwapped
        
        unit swapUnit
        unit targetUnit
        unit reswapUnit
        
        player swapPlayer
        player targetPlayer
        player reswapPlayer
        
        static if SWAP_TIME_LIMIT then
            timer resetTimer
        endif
        
        static if ENABLE_RESWAP then
            timer reswapTimer
        endif
        
        static if SWAP_TIME_LIMIT then
        
            static method ResetSwapData takes nothing returns nothing
                local thistype this
                
                static if LIBRARY_TimerUtils then
                    set this = GetTimerData( GetExpiredTimer() )
                else
                    set this = LoadInteger( TimerHash, GetHandleId( GetExpiredTimer() ), 1 )
                endif
                
                set this.targetUnit = null
                set this.targetPlayer = null
                
                static if LIBRARY_TimerUtils then
                    call ReleaseTimer( GetExpiredTimer() )
                else
                    call PauseTimer( GetExpiredTimer() )
                    call DestroyTimer( GetExpiredTimer() )
                    
                    set this.resetTimer = null
                endif
                
            endmethod
            
        endif
        
        static if ENABLE_RESWAP then
        
            static method StopReswap takes nothing returns nothing
                local thistype this
                local player pt
                
                static if LIBRARY_TimerUtils then
                    set this = GetTimerData( GetExpiredTimer() )
                else
                    set this = LoadInteger( TimerHash, GetHandleId( GetExpiredTimer() ), 2 )
                endif
                
                set pt = this.reswapPlayer
                
                set this.reswapPlayer = null
                set this.reswapUnit = null
                set SwapData[ GetPlayerId( pt ) ].reswapPlayer = null
                set SwapData[ GetPlayerId( pt ) ].reswapUnit = null
                
                static if LIBRARY_TimerUtils then
                    call ReleaseTimer( GetExpiredTimer() )
                    call ReleaseTimer( SwapData[ GetPlayerId( pt ) ].reswapTimer )
                else
                    call PauseTimer( GetExpiredTimer() )
                    call DestroyTimer( GetExpiredTimer() )
                    
                    set this.reswapTimer = null
                    
                    call PauseTimer( SwapData[ GetPlayerId( pt ) ].reswapTimer )
                    call DestroyTimer( SwapData[ GetPlayerId( pt ) ].reswapTimer )
                    
                    set SwapData[ GetPlayerId( pt ) ].reswapTimer = null
                endif
                
            endmethod
        
        endif
        
    endstruct
        
    private function SwapActions takes nothing returns boolean
        local player p
        local player pt
        local string s = GetEventPlayerChatString()
        local boolean conds
        local unit temp = null
        
        static if SWAP_ITEMS then
            local integer array firstHeros
            local integer array secHeros
            local integer loops = 0
        endif
        
        if SubString( s, 0, StringLength( SWAP_COMMAND ) ) == SWAP_COMMAND then
            set p = GetTriggerPlayer()
            
            static if USE_GUI_PLAYER_IDS then
                set pt = Player( S2I( SubString( s, StringLength( SWAP_COMMAND ), StringLength( s ) ) ) - 1 )
            else
                set pt = Player( S2I( SubString( s, StringLength( SWAP_COMMAND ), StringLength( s ) ) ) )
            endif
            
            static if SWAP_NEUTRALS then
                set conds = GetPlayerId( pt ) &gt;= 16 or GetPlayerId( pt ) &lt; 0 or pt == null or SwapData[ GetPlayerId( pt ) ].swapPlayer != null or pt == p or ( SWAP_ALLIES_ONLY and IsPlayerEnemy( p, pt ) )
            else
                set conds = GetPlayerId( pt ) &gt;= 12 or GetPlayerId( pt ) &lt; 0 or pt == null or SwapData[ GetPlayerId( pt ) ].swapPlayer != null or pt == p or ( SWAP_ALLIES_ONLY and IsPlayerEnemy( p, pt ) )
            endif
            
            // Make sure you type a valid player
            
            if conds then
                call SimError( p, &quot;You need to input a valid player-id !&quot; )
                
                return false
            endif
            
            // And also make sure you yourself have a valid hero to swap before starting <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite2" alt=";)" title="Wink    ;)" loading="lazy" data-shortname=";)" />
            
            if SwapData[ GetPlayerId( p ) ].swapUnit == null then
                call SimError( p, &quot;You need to have a swap hero eligible yourself, before you can use the -swap command !&quot; )
                
                return false
            endif
            
            if SwapData[ GetPlayerId( p ) ].hasSwapped == true and ONE_SWAP_ONLY then
                call SimError( p, &quot;You have already swapped once, and can&#039;t swap again...&quot; )
                
                return false
            endif
            
            if SwapData[ GetPlayerId( pt ) ].hasSwapped == true and ONE_SWAP_ONLY then
                call SimError( p, &quot;The player you wish to swap with has already swapped once, and can&#039;t swap again !&quot; )
                
                return false
            endif
            
            if SwapData[ GetPlayerId( pt ) ].targetPlayer != p and ONE_SWAP_ONLY then
                call SimError( p, &quot;The player you wish to swap with has already swapped once, and can&#039;t swap again !&quot; )
                
                return false
            endif
            
            if ELSE_DONT_SWAP then
            
                if not UnitAlive( SwapData[ GetPlayerId( p ) ].swapUnit ) then
                    call SimError( p, &quot;Your swap-unit needs to be alive to be allowed to swap !&quot; )
                    
                    return false
                endif
                
                if not UnitAlive( SwapData[ GetPlayerId( pt ) ].swapUnit ) then
                    call SimError( p, &quot;Your swap-player has a dead swap-unit, and you cannot swap then !&quot; )
                    
                    return false
                endif
                
            endif
            
            if SWAP_TIME_LIMIT then
                
                static if LIBRARY_TimerUtils then
                    call ReleaseTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                    call ReleaseTimer( SwapData[ GetPlayerId( pt ) ].resetTimer )
                else
                    call PauseTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                    call DestroyTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                    
                    set SwapData[ GetPlayerId( p ) ].resetTimer = null
                    
                    call PauseTimer( SwapData[ GetPlayerId( pt ) ].resetTimer )
                    call DestroyTimer( SwapData[ GetPlayerId( pt ) ].resetTimer )
                    
                    set SwapData[ GetPlayerId( pt ) ].resetTimer = null
                endif
                
            endif
            
            set SwapData[ GetPlayerId( p ) ].targetPlayer = pt
            set SwapData[ GetPlayerId( p ) ].targetUnit = SwapData[ GetPlayerId( p ) ].swapUnit
            
            // Start switch ! <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin    :D" loading="lazy" data-shortname=":D" />            
            
            if SwapData[ GetPlayerId( pt ) ].targetPlayer == p and SwapData[ GetPlayerId( pt ) ].targetUnit == SwapData[ GetPlayerId( p ) ].swapUnit then
                set temp = SwapData[ GetPlayerId( p ) ].swapUnit
                
                static if SWAP_ITEMS then
                
                    loop
                        set firstHeros[loops] = GetItemTypeId( UnitItemInSlot( temp, loops ) )
                        
                        call RemoveItem( UnitItemInSlot( temp, loops ) )
                        
                        set secHeros[loops] = GetItemTypeId( UnitItemInSlot( SwapData[ GetPlayerId( pt ) ].swapUnit, loops ) )
                        
                        call RemoveItem( UnitItemInSlot( SwapData[ GetPlayerId( pt ) ].swapUnit, loops ) )
                        call UnitAddItemToSlotById( temp, firstHeros[loops], loops )
                        call UnitAddItemToSlotById( temp, secHeros[loops], loops )
                        
                        set loops = loops + 1
                        
                        exitwhen loops &gt;= 6
                    endloop
                    
                endif
                
                static if UNLEARN_ABILITIES then
                    call
                    
                endif
                
                static if RETAIN_PLAYER_COLORS then
                    call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, false )
                else
                    call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, true )
                endif
                
                set SwapData[ GetPlayerId( p ) ].swapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                
                
                static if RETAIN_PLAYER_COLORS then
                    call SetUnitOwner( temp, pt, false )
                else
                    call SetUnitOwner( temp, pt, true )
                endif
                
                set SwapData[ GetPlayerId( pt ) ].swapUnit = temp
                
                static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                    call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have accepted &quot; + GetPlayerNameColored( pt ) + &quot;&#039;s swap request !&quot; )
                    call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has accepted you request to swap heroes !&quot; )
                else
                    call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have accepted &quot; + GetPlayerName( pt ) + &quot;&#039;s swap request !&quot; )
                    call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has accepted you request to swap heroes !&quot; )
                endif
                        
                
                static if SWITCH_POSITIONS then
                    call SetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                    call SetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                    call SetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                    call SetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                endif
                
                static if REVIVE_IF_DEAD then
                
                    if not UnitAlive( SwapData[ GetPlayerId( pt ) ].swapUnit ) then
                        call ReviveHero( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ), true )
                    endif
                    
                    if not UnitAlive( SwapData[ GetPlayerId( p ) ].swapUnit ) then
                        call ReviveHero( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ), true )
                    endif
                    
                endif
                
                set SwapData[ GetPlayerId( p ) ].hasSwapped = true
                set SwapData[ GetPlayerId( pt ) ].hasSwapped = true
                
                static if LIBRARY_TimerUtils then
                    set SwapData[ GetPlayerId( p ) ].reswapTimer = NewTimer()
                    set SwapData[ GetPlayerId( pt ) ].reswapTimer = NewTimer()
                    
                    call SetTimerData( SwapData[ GetPlayerId( p ) ].reswapTimer, SwapData[ GetPlayerId( p ) ] )
                    call SetTimerData( SwapData[ GetPlayerId( pt ) ].reswapTimer, SwapData[ GetPlayerId( pt ) ] )
                else
                    set SwapData[ GetPlayerId( p ) ].reswapTimer = CreateTimer()
                    set SwapData[ GetPlayerId( pt ) ].reswapTimer = CreateTimer()
                    
                    call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( p ) ].reswapTimer ), 2, SwapData[ GetPlayerId( p ) ] )
                    call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( pt ) ].reswapTimer ), 2, SwapData[ GetPlayerId( pt ) ] )
                endif
                
                set SwapData[ GetPlayerId( p ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                set SwapData[ GetPlayerId( pt ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                set SwapData[ GetPlayerId( p ) ].reswapPlayer = pt
                set SwapData[ GetPlayerId( pt ) ].reswapPlayer = p
                
                static if ONE_SWAP_ONLY then
                    set SwapData[ GetPlayerId( p ) ].swapUnit = null
                    set SwapData[ GetPlayerId( pt ) ].swapUnit = null
                endif
                
                call TimerStart( SwapData[ GetPlayerId( p ) ].reswapTimer, RESWAP_TIME, false, function SwapData.StopReswap )
                call TimerStart( SwapData[ GetPlayerId( pt ) ].reswapTimer, RESWAP_TIME, false, function SwapData.StopReswap )
            else
        
                static if SWAP_TIME_LIMIT then
                    
                    static if LIBRARY_TimerUtils then
                        set SwapData[ GetPlayerId( p ) ].resetTimer = NewTimer()
                        
                        call SetTimerData( SwapData[ GetPlayerId( p ) ].resetTimer, SwapData[ GetPlayerId( p ) ] )
                    else
                        set SwapData[ GetPlayerId( p ) ].resetTimer = CreateTimer()
                        
                        call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( p ) ].resetTimer ), 1, SwapData[ GetPlayerId( p ) ] )
                    endif
                    
                    call TimerStart( SwapData[ GetPlayerId( p ) ].resetTimer, TIME_LIMIT, false, function SwapData.ResetSwapData )
                
                endif
                
                static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                    call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have sent a request to &quot; + GetPlayerNameColored( pt ) + &quot;, to swap heroes !&quot; )
                    call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has sent you a swap request ! Will you accept ?&quot; )                    
                else
                    call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have sent a request to &quot; + GetPlayerName( pt ) + &quot;, to swap heroes !&quot; )
                    call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has sent you a swap request ! Will you accept ?&quot; )
                endif
                
            endif
            
        endif
        
        set s = null
        set p = null
        set pt = null
        set temp = null
        
        return false
    endfunction
    
    static if ENABLE_RESWAP then
    
        private function Reswap takes nothing returns boolean
            local player p = GetTriggerPlayer()
            local player pt
            local unit temp = null
            local string s = GetEventPlayerChatString()
            
            static if SWAP_ITEMS then
                local integer array firstHeros
                local integer array secHeros
                local integer loops = 0
            endif
            
            if SwapData[ GetPlayerId( p ) ].reswapPlayer != null and SwapData[ GetPlayerId( p ) ].reswapUnit != null and SubString( s, 0, StringLength( RESWAP_COMMAND ) ) == RESWAP_COMMAND then
                set pt = SwapData[ GetPlayerId( p ) ].reswapPlayer
                
                if not ( UnitAlive( SwapData[ GetPlayerId( p ) ].swapUnit ) and REVIVE_IF_DEAD ) and ELSE_DONT_SWAP then
                    call SimError( p, &quot;Your reswap-hero needs to be alive !&quot; )
                    
                    return false
                endif
                
                if not ( UnitAlive( SwapData[ GetPlayerId( pt ) ].swapUnit ) and REVIVE_IF_DEAD ) and ELSE_DONT_SWAP then
                    call SimError( p, &quot;Your reswap-player&#039;s swap-unit needs to be alive !&quot; )
                    
                    return false
                endif
                
                static if NEED_BOTHS_CONSENT then
                    set SwapData[ GetPlayerId( p ) ].targetPlayer = pt
                    set SwapData[ GetPlayerId( p ) ].targetUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                    
                    if SwapData[ GetPlayerId( pt ) ].targetPlayer == p and SwapData[ GetPlayerId( pt ) ].targetUnit == SwapData[ GetPlayerId( p ) ].swapUnit then
                        set temp = SwapData[ GetPlayerId( p ) ].swapUnit
                        
                        static if SWAP_ITEMS then
                        
                            loop
                                set firstHeros[loops] = GetItemTypeId( UnitItemInSlot( temp, loops ) )
                                
                                call RemoveItem( UnitItemInSlot( temp, loops ) )
                                
                                set secHeros[loops] = GetItemTypeId( UnitItemInSlot( SwapData[ GetPlayerId( pt ) ].swapUnit, loops ) )
                                
                                call RemoveItem( UnitItemInSlot( SwapData[ GetPlayerId( pt ) ].swapUnit, loops ) )
                                call UnitAddItemToSlotById( temp, firstHeros[loops], loops )
                                call UnitAddItemToSlotById( temp, secHeros[loops], loops )
                                
                                set loops = loops + 1
                                
                                exitwhen loops &gt;= 6
                            endloop
                            
                        endif
                        
                        static if RETAIN_PLAYER_COLORS then
                            call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, false )
                        else
                            call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, true )
                        endif
                        
                        set SwapData[ GetPlayerId( p ) ].swapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                        
                        
                        static if RETAIN_PLAYER_COLORS then
                            call SetUnitOwner( temp, pt, false )
                        else
                            call SetUnitOwner( temp, pt, true )
                        endif
                        
                        set SwapData[ GetPlayerId( pt ) ].swapUnit = temp                 
                        
                        static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                            call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have accepted &quot; + GetPlayerNameColored( pt ) + &quot;&#039;s swap request !&quot; )
                            call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has accepted you request to swap heroes !&quot; )
                        else
                            call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have accepted &quot; + GetPlayerName( pt ) + &quot;&#039;s swap request !&quot; )
                            call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has accepted you request to swap heroes !&quot; )
                        endif
                                
                        
                        static if SWITCH_POSITIONS then
                            call SetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                            call SetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                            call SetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                            call SetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                        endif
                        
                        static if REVIVE_IF_DEAD then
                        
                            if not UnitAlive( SwapData[ GetPlayerId( pt ) ].swapUnit ) then
                                call ReviveHero( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ), true )
                            endif
                            
                            if not UnitAlive( SwapData[ GetPlayerId( p ) ].swapUnit ) then
                                call ReviveHero( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ), true )
                            endif
                            
                        endif
                        
                        set SwapData[ GetPlayerId( p ) ].hasSwapped = true
                        set SwapData[ GetPlayerId( pt ) ].hasSwapped = true
                        
                        static if LIBRARY_TimerUtils then
                            set SwapData[ GetPlayerId( p ) ].reswapTimer = NewTimer()
                            set SwapData[ GetPlayerId( pt ) ].reswapTimer = NewTimer()
                            
                            call SetTimerData( SwapData[ GetPlayerId( p ) ].reswapTimer, SwapData[ GetPlayerId( p ) ] )
                            call SetTimerData( SwapData[ GetPlayerId( pt ) ].reswapTimer, SwapData[ GetPlayerId( pt ) ] )
                        else
                            set SwapData[ GetPlayerId( p ) ].reswapTimer = CreateTimer()
                            set SwapData[ GetPlayerId( pt ) ].reswapTimer = CreateTimer()
                            
                            call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( p ) ].reswapTimer ), 2, SwapData[ GetPlayerId( p ) ] )
                            call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( pt ) ].reswapTimer ), 2, SwapData[ GetPlayerId( pt ) ] )
                        endif
                        
                        set SwapData[ GetPlayerId( p ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                        set SwapData[ GetPlayerId( pt ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                        set SwapData[ GetPlayerId( p ) ].reswapPlayer = pt
                        set SwapData[ GetPlayerId( pt ) ].reswapPlayer = p
                        set SwapData[ GetPlayerId( p ) ].swapUnit = null
                        set SwapData[ GetPlayerId( pt ) ].swapUnit = null
                        
                        call TimerStart( SwapData[ GetPlayerId( p ) ].reswapTimer, RESWAP_TIME, false, function SwapData.StopReswap )
                        call TimerStart( SwapData[ GetPlayerId( pt ) ].reswapTimer, RESWAP_TIME, false, function SwapData.StopReswap )
                    else
                
                        static if SWAP_TIME_LIMIT then
                    
                            static if LIBRARY_TimerUtils then
                                set SwapData[ GetPlayerId( p ) ].resetTimer = NewTimer()
                                
                                call SetTimerData( SwapData[ GetPlayerId( p ) ].resetTimer, SwapData[ GetPlayerId( p ) ] )
                            else
                                set SwapData[ GetPlayerId( p ) ].resetTimer = CreateTimer()
                                
                                call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( p ) ].resetTimer ), 1, SwapData[ GetPlayerId( p ) ] )
                            endif
                            
                            call TimerStart( SwapData[ GetPlayerId( p ) ].resetTimer, TIME_LIMIT, false, function SwapData.ResetSwapData )
                        
                        endif
                        
                        static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                            call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have sent a request to &quot; + GetPlayerNameColored( pt ) + &quot;, to swap heroes !&quot; )
                            call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has sent you a swap request ! Will you accept ?&quot; )
                        else
                            call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have sent a request to &quot; + GetPlayerName( pt ) + &quot;, to swap heroes !&quot; )
                            call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has sent you a swap request ! Will you accept ?&quot; )
                        endif
                        
                    endif
                    
                else
                    set temp = SwapData[ GetPlayerId( p ) ].swapUnit
                    
                    static if RETAIN_PLAYER_COLORS then
                        call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, false )
                    else
                        call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, true )
                    endif
                    
                    set SwapData[ GetPlayerId( p ) ].swapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                    
                    
                    static if RETAIN_PLAYER_COLORS then
                        call SetUnitOwner( temp, pt, false )
                    else
                        call SetUnitOwner( temp, pt, true )
                    endif
                    
                    set SwapData[ GetPlayerId( pt ) ].swapUnit = temp
                    
                    static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                        call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have now reswapped your hero from &quot; + GetPlayerNameColored( pt ) + &quot; and given him your hero !&quot; )
                        call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has reswapped his hero from you, and you&#039;ve gotten yours back too !&quot; )
                    else
                        call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have accepted &quot; + GetPlayerName( pt ) + &quot;&#039;s swap request !&quot; )
                        call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has accepted you request to swap heroes !&quot; )
                    endif
                            
                    
                    static if SWITCH_POSITIONS then
                        call SetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                        call SetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                        call SetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                        call SetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                    endif
                    
                    static if REVIVE_IF_DEAD then
                    
                        if not UnitAlive( SwapData[ GetPlayerId( pt ) ].swapUnit ) then
                            call ReviveHero( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ), true )
                        endif
                        
                        if not UnitAlive( SwapData[ GetPlayerId( p ) ].swapUnit ) then
                            call ReviveHero( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ), true )
                        endif
                        
                    endif
                    
                    set SwapData[ GetPlayerId( p ) ].hasSwapped = true
                    set SwapData[ GetPlayerId( pt ) ].hasSwapped = true
                    
                    static if LIBRARY_TimerUtils then
                        set SwapData[ GetPlayerId( p ) ].reswapTimer = NewTimer()
                        set SwapData[ GetPlayerId( pt ) ].reswapTimer = NewTimer()
                        
                        call SetTimerData( SwapData[ GetPlayerId( p ) ].reswapTimer, SwapData[ GetPlayerId( p ) ] )
                        call SetTimerData( SwapData[ GetPlayerId( pt ) ].reswapTimer, SwapData[ GetPlayerId( pt ) ] )
                    else
                        set SwapData[ GetPlayerId( p ) ].reswapTimer = CreateTimer()
                        set SwapData[ GetPlayerId( pt ) ].reswapTimer = CreateTimer()
                        
                        call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( p ) ].reswapTimer ), 2, SwapData[ GetPlayerId( p ) ] )
                        call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( pt ) ].reswapTimer ), 2, SwapData[ GetPlayerId( pt ) ] )
                    endif
                    
                    static if not RESWAP_ONCE_ONLY then
                        set SwapData[ GetPlayerId( p ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                        set SwapData[ GetPlayerId( pt ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                        set SwapData[ GetPlayerId( p ) ].reswapPlayer = pt
                        set SwapData[ GetPlayerId( pt ) ].reswapPlayer = p
                    endif
                    
                    set SwapData[ GetPlayerId( p ) ].targetUnit = null
                    set SwapData[ GetPlayerId( pt ) ].targetUnit = null
                endif
                    
            endif
            
            set p = null
            set pt = null
            set temp = null
            set s = null
            
            return false
        endfunction
    
    endif
    
    static if ENABLE_CANCEL_COMMAND then
    
        private function CancelSwap takes nothing returns boolean
            local player p = GetTriggerPlayer()
            local player pt = SwapData[ GetPlayerId( p ) ].targetPlayer
            local string s = GetEventPlayerChatString()
            
            if TimerGetRemaining( SwapData[ GetPlayerId( p ) ].resetTimer ) &gt; 0 and SubString( s, 0, StringLength( CANCEL_SWAP_CMD ) ) == CANCEL_SWAP_CMD then
                
                static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                    call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have cancelled the request to swap heroes with &quot; + GetPlayerNameColored( pt ) + &quot; !&quot; )
                    call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has cancelled his request to swap heroes with you !&quot; )
                else
                    call DisplayTextToPlayer( pt, 0.0, 0.0, &quot;You have cancelled the request to swap heroes with &quot; + GetPlayerName( pt ) + &quot; !&quot; )
                    call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has cancelled his request to swap heroes with you !&quot; )
                endif
                
                set SwapData[ GetPlayerId( p ) ].targetPlayer = null
                set SwapData[ GetPlayerId( p ) ].targetUnit = null
                
                static if SWAP_TIME_LIMIT then
                
                    static if LIBRARY_TimerUtils then
                        call ReleaseTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                    else
                        call PauseTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                        call DestroyTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                        
                        set SwapData[ GetPlayerId( p ) ].resetTimer = null
                    endif
                    
                endif
        
            endif
            
            set p = null
            set pt = null
            set s = null
        
            return false
        endfunction
        
    endif
    
    static if ENABLE_RANDOM_SWAP then
        
        private function RandomSwap takes nothing returns boolean
            local player p = GetTriggerPlayer()
            local player pt = null
            local string s = GetEventPlayerChatString()
            local integer i = 0
            local unit temp = null
            
            static if SWAP_ITEMS then
                local integer array firstHeros
                local integer array secHeros
                local integer loops = 0
            endif
            
            if SubString( s, 0, StringLength( RANDOM_SWAP_CMD ) ) == RANDOM_SWAP_CMD then
                
                loop
                    set i = GetRandomInt( 0, 11 )
                    
                    if SwapData[ i ].swapPlayer != null and SwapData[ i ].targetPlayer == null and Player( i ) != p then
                        set pt = Player( i )
                        
                        return true
                    endif
                    
                endloop
                
                        
                if pt == null then
                    call SimError( p, &quot;There is no elegible player to swap with !&quot; )
                endif
                
                // And also make sure you yourself have a valid hero to swap before starting <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite2" alt=";)" title="Wink    ;)" loading="lazy" data-shortname=";)" />
                
                if SwapData[ GetPlayerId( p ) ].swapUnit == null then
                    call SimError( p, &quot;You need to have a swap hero eligible yourself, before you can use the -swap command !&quot; )
                    
                    return false
                endif
                
                if SwapData[ GetPlayerId( p ) ].hasSwapped == true and ONE_SWAP_ONLY then
                    call SimError( p, &quot;You have already swapped once, and can&#039;t swap again...&quot; )
                    
                    return false
                endif
                
                if SwapData[ GetPlayerId( pt ) ].hasSwapped == true and ONE_SWAP_ONLY then
                    call SimError( p, &quot;The player you wish to swap with has already swapped once, and can&#039;t swap again !&quot; )
                    
                    return false
                endif
                
                if SwapData[ GetPlayerId( pt ) ].targetPlayer != p and ONE_SWAP_ONLY then
                    call SimError( p, &quot;The player you wish to swap with has already swapped once, and can&#039;t swap again !&quot; )
                    
                    return false
                endif
                
                if ELSE_DONT_SWAP then
                
                    if not UnitAlive( SwapData[ GetPlayerId( p ) ].swapUnit ) then
                        call SimError( p, &quot;Your swap-unit needs to be alive to be allowed to swap !&quot; )
                        
                        return false
                    endif
                    
                    if not UnitAlive( SwapData[ GetPlayerId( pt ) ].swapUnit ) then
                        call SimError( p, &quot;Your swap-player has a dead swap-unit, and you cannot swap then !&quot; )
                        
                        return false
                    endif
                    
                endif
                
                if SWAP_TIME_LIMIT then
                    
                    static if LIBRARY_TimerUtils then
                        call ReleaseTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                        call ReleaseTimer( SwapData[ GetPlayerId( pt ) ].resetTimer )
                    else
                        call PauseTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                        call DestroyTimer( SwapData[ GetPlayerId( p ) ].resetTimer )
                        
                        set SwapData[ GetPlayerId( p ) ].resetTimer = null
                        
                        call PauseTimer( SwapData[ GetPlayerId( pt ) ].resetTimer )
                        call DestroyTimer( SwapData[ GetPlayerId( pt ) ].resetTimer )
                        
                        set SwapData[ GetPlayerId( pt ) ].resetTimer = null
                    endif
                    
                endif
                
                set SwapData[ GetPlayerId( p ) ].targetPlayer = pt
                set SwapData[ GetPlayerId( p ) ].targetUnit = SwapData[ GetPlayerId( p ) ].swapUnit
                
                // Start switch ! <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin    :D" loading="lazy" data-shortname=":D" />            
                
                if SwapData[ GetPlayerId( pt ) ].targetPlayer == p and SwapData[ GetPlayerId( pt ) ].targetUnit == SwapData[ GetPlayerId( p ) ].swapUnit then
                    set temp = SwapData[ GetPlayerId( p ) ].swapUnit
                    
                    static if SWAP_ITEMS then
                    
                        loop
                            set firstHeros[loops] = GetItemTypeId( UnitItemInSlot( temp, loops ) )
                            
                            call RemoveItem( UnitItemInSlot( temp, loops ) )
                            
                            set secHeros[loops] = GetItemTypeId( UnitItemInSlot( SwapData[ GetPlayerId( pt ) ].swapUnit, loops ) )
                            
                            call RemoveItem( UnitItemInSlot( SwapData[ GetPlayerId( pt ) ].swapUnit, loops ) )
                            call UnitAddItemToSlotById( temp, firstHeros[loops], loops )
                            call UnitAddItemToSlotById( temp, secHeros[loops], loops )
                            
                            set loops = loops + 1
                            
                            exitwhen loops &gt;= 6
                        endloop
                        
                    endif
                    
                    static if UNLEARN_ABILITIES then
                        call
                        
                    endif
                    
                    static if RETAIN_PLAYER_COLORS then
                        call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, false )
                    else
                        call SetUnitOwner( SwapData[ GetPlayerId( pt ) ].swapUnit, p, true )
                    endif
                    
                    set SwapData[ GetPlayerId( p ) ].swapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                    
                    
                    static if RETAIN_PLAYER_COLORS then
                        call SetUnitOwner( temp, pt, false )
                    else
                        call SetUnitOwner( temp, pt, true )
                    endif
                    
                    set SwapData[ GetPlayerId( pt ) ].swapUnit = temp
                    
                    static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                        call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have accepted &quot; + GetPlayerNameColored( pt ) + &quot;&#039;s swap request !&quot; )
                        call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has accepted you request to swap heroes !&quot; )
                    else
                        call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have accepted &quot; + GetPlayerName( pt ) + &quot;&#039;s swap request !&quot; )
                        call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has accepted you request to swap heroes !&quot; )
                    endif
                            
                    
                    static if SWITCH_POSITIONS then
                        call SetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                        call SetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                        call SetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ) )
                        call SetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ) )
                    endif
                    
                    static if REVIVE_IF_DEAD then
                    
                        if not UnitAlive( SwapData[ GetPlayerId( pt ) ].swapUnit ) then
                            call ReviveHero( SwapData[ GetPlayerId( pt ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( pt ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( pt ) ].swapUnit ), true )
                        endif
                        
                        if not UnitAlive( SwapData[ GetPlayerId( p ) ].swapUnit ) then
                            call ReviveHero( SwapData[ GetPlayerId( p ) ].swapUnit, GetUnitX( SwapData[ GetPlayerId( p ) ].swapUnit ), GetUnitY( SwapData[ GetPlayerId( p ) ].swapUnit ), true )
                        endif
                        
                    endif
                    
                    set SwapData[ GetPlayerId( p ) ].hasSwapped = true
                    set SwapData[ GetPlayerId( pt ) ].hasSwapped = true
                    
                    static if LIBRARY_TimerUtils then
                        set SwapData[ GetPlayerId( p ) ].reswapTimer = NewTimer()
                        set SwapData[ GetPlayerId( pt ) ].reswapTimer = NewTimer()
                        
                        call SetTimerData( SwapData[ GetPlayerId( p ) ].reswapTimer, SwapData[ GetPlayerId( p ) ] )
                        call SetTimerData( SwapData[ GetPlayerId( pt ) ].reswapTimer, SwapData[ GetPlayerId( pt ) ] )
                    else
                        set SwapData[ GetPlayerId( p ) ].reswapTimer = CreateTimer()
                        set SwapData[ GetPlayerId( pt ) ].reswapTimer = CreateTimer()
                        
                        call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( p ) ].reswapTimer ), 2, SwapData[ GetPlayerId( p ) ] )
                        call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( pt ) ].reswapTimer ), 2, SwapData[ GetPlayerId( pt ) ] )
                    endif
                    
                    set SwapData[ GetPlayerId( p ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                    set SwapData[ GetPlayerId( pt ) ].reswapUnit = SwapData[ GetPlayerId( pt ) ].swapUnit
                    set SwapData[ GetPlayerId( p ) ].reswapPlayer = pt
                    set SwapData[ GetPlayerId( pt ) ].reswapPlayer = p
                    
                    static if ONE_SWAP_ONLY then
                        set SwapData[ GetPlayerId( p ) ].swapUnit = null
                        set SwapData[ GetPlayerId( pt ) ].swapUnit = null
                    endif
                    
                    call TimerStart( SwapData[ GetPlayerId( p ) ].reswapTimer, RESWAP_TIME, false, function SwapData.StopReswap )
                    call TimerStart( SwapData[ GetPlayerId( pt ) ].reswapTimer, RESWAP_TIME, false, function SwapData.StopReswap )
                else
            
                    static if SWAP_TIME_LIMIT then
                        
                        static if LIBRARY_TimerUtils then
                            set SwapData[ GetPlayerId( p ) ].resetTimer = NewTimer()
                            
                            call SetTimerData( SwapData[ GetPlayerId( p ) ].resetTimer, SwapData[ GetPlayerId( p ) ] )
                        else
                            set SwapData[ GetPlayerId( p ) ].resetTimer = CreateTimer()
                            
                            call SaveInteger( TimerHash, GetHandleId( SwapData[ GetPlayerId( p ) ].resetTimer ), 1, SwapData[ GetPlayerId( p ) ] )
                        endif
                        
                        call TimerStart( SwapData[ GetPlayerId( p ) ].resetTimer, TIME_LIMIT, false, function SwapData.ResetSwapData )
                    
                    endif
                    
                    static if USE_PLAYERS_COLOR_ON_NAME and LIBRARY_PlayerColors then
                        call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have sent a request to &quot; + GetPlayerNameColored( pt ) + &quot;, to swap heroes !&quot; )
                        call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerNameColored( p ) + &quot; has sent you a swap request ! Will you accept ?&quot; )                    
                    else
                        call DisplayTextToPlayer( p, 0.0, 0.0, &quot;You have sent a request to &quot; + GetPlayerName( pt ) + &quot;, to swap heroes !&quot; )
                        call DisplayTextToPlayer( pt, 0.0, 0.0, GetPlayerName( p ) + &quot; has sent you a swap request ! Will you accept ?&quot; )
                    endif
                    
                endif
            
            endif
            
            return false
        endfunction
        
    endif
    
    private function PickInitHeroes takes nothing returns boolean
        local unit u = GetFilterUnit()
        local player p = GetOwningPlayer( u )
        
        if tempInt == 0 and IsUnitType( u, UNIT_TYPE_HERO ) and not IsUnitType( u, UNIT_TYPE_STRUCTURE ) and UnitAlive( u ) and SwapData[ GetPlayerId( p ) ].swapUnit == null then
            set SwapData[ GetPlayerId( p ) ].swapUnit = u
            set tempInt = 1
        endif
        
        set u = null
        set p = null
        
        return false
    endfunction

    private function OnInitHeroes takes nothing returns nothing
        local integer i = 0
        local player p
        
        loop
        
            static if SWAP_NEUTRALS then
                exitwhen i &gt;= 16
            else
                exitwhen i &gt;= 12
            endif
            
            set tempInt = 0
            set p = Player( i )
            
            if SwapData[ GetPlayerId( p ) ].swapUnit != null and GetPlayerController( p ) == MAP_CONTROL_USER and GetPlayerController( p ) == PLAYER_SLOT_STATE_PLAYING then                    
                call GroupEnumUnitsOfPlayer( ENUM, p, Filter( function PickInitHeroes ) )
            endif
            
            set i = i + 1
        endloop
    
        set p = null
    endfunction

    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i = 0
        local player p = null
        
        loop
        
            set p = Player( i )
        
            static if SWAP_NEUTRALS then
                exitwhen i &gt;= 16
                
                if i &gt;= 12 and ( GetPlayerController( p ) == MAP_CONTROL_COMPUTER or GetPlayerController( p ) == MAP_CONTROL_CREEP ) then
                    set SwapData[ GetPlayerId( p ) ].hasSwapped = false
                    set SwapData[ GetPlayerId( p ) ].swapPlayer = p
                endif
                    
            else
                exitwhen i &gt;= 12
            endif
            
            if GetPlayerController( p ) == MAP_CONTROL_USER and GetPlayerSlotState( p ) == PLAYER_SLOT_STATE_PLAYING then
                call TriggerRegisterPlayerChatEvent( t, p, SWAP_COMMAND, true )
                
                set SwapData[ GetPlayerId( p ) ].hasSwapped = false
                set SwapData[ GetPlayerId( p ) ].swapPlayer = p
            endif
            
            set i = i + 1
        endloop
        
        call TriggerAddCondition( t, Condition( function SwapActions ) )
        
        static if ENABLE_CANCEL_COMMAND then
            set t = CreateTrigger()
            set i = 0
            
            loop
                exitwhen i &gt;= 12
                
                set p = Player( i )
                
                if GetPlayerController( p ) == MAP_CONTROL_USER and GetPlayerSlotState( p ) == PLAYER_SLOT_STATE_PLAYING then
                    call TriggerRegisterPlayerChatEvent( t, p, CANCEL_SWAP_CMD, true )
                endif
                
                set i = i + 1
            endloop
            
            call TriggerAddCondition( t, Condition( function CancelSwap ) )
        endif
        
        static if ENABLE_RESWAP then
            set t = CreateTrigger()
            set i = 0
            
            loop
                exitwhen i &gt;= 12
                
                set p = Player( i )
                
                if GetPlayerController( p ) == MAP_CONTROL_USER and GetPlayerSlotState( p ) == PLAYER_SLOT_STATE_PLAYING then
                    call TriggerRegisterPlayerChatEvent( t, p, RESWAP_COMMAND, true )
                endif
                
                set i = i + 1
            endloop
            
            call TriggerAddCondition( t, Condition( function Reswap ) )
        endif
        
        static if ENABLE_RANDOM_SWAP then
            set t = CreateTrigger()
            set i = 0
            
            loop
                exitwhen i &gt;= 12
                
                set p = Player( i )
                
                if GetPlayerController( p ) == MAP_CONTROL_USER and GetPlayerSlotState( p ) == PLAYER_SLOT_STATE_PLAYING then
                    call TriggerRegisterPlayerChatEvent( t, p, RANDOM_SWAP_CMD, true )
                endif
                
                set i = i + 1
            endloop
            
            call TriggerAddCondition( t, Condition( function RandomSwap ) )
        endif
        
        static if HEROES_ON_INIT then
            call OnInitHeroes()
        endif
        
        static if not LIBRARY_TimerUtils then
            
            static if SWAP_TIME_LIMIT then
                set TimerHash = InitHashtable()
            elseif RESWAP_TIME then
                set TimerHash = InitHashtable()
            endif
            
        endif
        
        set p = null
        set t = null
    endfunction
    
endlibrary
 

Komaqtion

You can change this now in User CP.
Reaction score
469
One last bump here...

PLEASE can some one test this ?!
I would GREATLY appreciate it ;)

If no one will test it then I will have no other option but to submit this resource, not knowing if it works or not :(
 

SanKakU

Member
Reaction score
21
yeah i guess i'll test it.
so far i noticed you seem to have an insane ammount of tabbing whitespace.
JASS:
world editor is shocked right now trying to replace &quot;    &quot; with &quot;&quot;

hmm...took notepad 4 minutes to do it.
wonder how long it will take me to delete all the line breaks.
1059 lines of code...can't it be smaller? this is madness, imo.

are all the customizable globals commented on? guess not. this is pretty interesting how much you put into it. idk if anyone wants to test everything though...lol...oh well i'll keep looking over it all and if it gets to be too much i'll let you know.

i think NEED_BOTHS_CONSENT should be NEED_CONSENT_OF_BOTH and ELSE_DONT_SWAP should be ELSE_NO_SWAP or ELSE_DO_NOT_SWAP.

i do not understand why you do not have a list feature for swap.
in dota, -swap pulls up a list of swappable units. 5 units, numbers 1-5. but you have option of player number, and your default for use gui player number is false. all that is not good. even still, i think using player number doesn't make a lot of sense. i really liked the list feature better which is in dota. maybe you could add option for swapping with player of a color. like, -swap blue, -swap red, etc.

i feel like you wrote wayyyy too much code and a swap system could be written in about 100 lines maybe. but i could be wrong. i guess i'll try writing my own.

what i think i'm going to go for is making functions which have a lot of fields and just use the functions. i think this is all so simple and you made is so complicated by throwing in so many structs and methods and nonsense. but maybe i'm wrong...
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top