Free of type error (Pui related)

Faust

You can change this now in User CP.
Reaction score
123
JASS:
scope Relocation initializer I

private struct Relocation
    //! runtextmacro PUI()
    unit mover
    real x
    real y
    integer xp
    timer clock = CreateTimer()
    integer unitid
    boolean transferFlag
        
    static method Get takes unit whichUnit returns Relocation
        local Relocation dat = Relocation[whichUnit] //check if an instance is already associated with whichUnit
        if dat == 0 then //if not
            set dat = Relocation.allocate() //allocate a new instance
            
            //insert whatever you want to happen when a new instance is created here
            set dat.transferFlag = false
            
            set Relocation[whichUnit] = dat //associate the newly allocate instance with whichUnit
        endif
        return dat
    endmethod
    
    static method Transfer takes unit sourceUnit, unit targetUnit returns Relocation
        local Relocation dat = Relocation.Get(sourceUnit)
        //to make this function safer, you should check if targetUnit has an instance set before starting the transfer.
        set dat.transferFlag = true //anything in onDestroy should not be carried out for a transfering instance.
        
        //by releasing, the instance will be freed from the previous unit, and next in line to be allocated.
        call dat.release()
        set dat = Relocation.allocate()
        
        set dat.transferFlag = false
        
        set Relocation[targetUnit] = dat //transfer complete
        return dat
    endmethod
    
    method onDestroy takes nothing returns nothing
        if not .transferFlag then
            
            //this block will only be called whenever an instance is fully destroyed.
                        //transfered instances will be ignored
            
            call PauseTimer(.clock)
            call ClearTimerStructA(.clock)
            call DestroyTimer(.clock)
        endif
    endmethod


endstruct

private function C2 takes nothing returns boolean
    return GetIssuedOrderId() == 852165
endfunction

private function C3 takes nothing returns boolean
    return GetIssuedOrderId() == 852166 and IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true
endfunction

private function RootHandle takes nothing returns nothing
    local Relocation dat = GetTimerStructA(GetExpiredTimer())
    if GetUnitX(dat.mover) == dat.x and GetUnitY(dat.mover) == dat.y then
     call ReplaceTower(dat.mover, dat.unitid, 'h01C')
     call Relocation.Transfer(dat.mover, bj_lastCreatedUnit)
     set dat.mover = bj_lastCreatedUnit
     call SetHeroXP(bj_lastCreatedUnit, dat.xp, false)
     call PauseTimer(dat.clock)
    endif
    if GetUnitCurrentOrder(dat.mover) != 852165 then
     call PauseTimer(dat.clock)
    endif
endfunction

private function Root takes nothing returns nothing
    local Relocation dat = Relocation[GetTriggerUnit()]
    local location l = GetOrderPointLoc()
    set dat.mover = GetTriggerUnit()
    set dat.x = GetLocationX(l)
    set dat.y = GetLocationY(l)
    set dat.clock = CreateTimer()
    call SetTimerStructA(dat.clock, dat)
    call TimerStart(dat.clock, 0.2, true, function RootHandle)
    call RemoveLocation(l)
    set l = null
endfunction

private function Uproot takes nothing returns nothing
    local Relocation dat = Relocation[GetTriggerUnit()]
    if dat == null then
     call BJDebugMsg("Dat is null")
     set dat = Relocation.create()
     //call SetTimerStructA(dat.clock, dat)
    else
     call BJDebugMsg("dat is not null")
    endif
    set dat.xp = GetHeroXP(GetTriggerUnit())
    call KillDummy(GetTriggerUnit())
    set dat.unitid = GetUnitTypeId(GetTriggerUnit())
    call ReplaceTower(GetTriggerUnit(), 'h02A', 'none')
    call IssueImmediateOrderById(bj_lastCreatedUnit, 852166)
    call Relocation.Transfer(GetTriggerUnit(), bj_lastCreatedUnit)
    //set dat.mover = bj_lastCreatedUnit
endfunction

private function C1 takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'H029'
endfunction

private function EntryUproot takes nothing returns nothing
    local Relocation dat = Relocation[GetTriggerUnit()]
    if dat == null then
     call IssueImmediateOrderById(GetTriggerUnit(), 852166)
    else
    endif
endfunction


//===========================================================================
private function I takes nothing returns nothing
    local trigger t = CreateTrigger()
    local region r = CreateRegion()
    call RegionAddRect(r, bj_mapInitialPlayableArea)
    call TriggerRegisterEnterRegion(t, r, Condition(function C1))
    call TriggerAddAction(t, function EntryUproot)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
    call TriggerAddCondition(t, Condition(function C2))
    call TriggerAddAction(t, function Root)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)
    call TriggerAddCondition(t, Condition(function C3))
    call TriggerAddAction(t, function Uproot)
endfunction

endscope


Now same thing happens, except there is only one red line with that error message :D
 

Builder Bob

Live free or don't
Reaction score
249
JASS:
scope Relocation initializer I

private struct Relocation
    //! runtextmacro PUI()
    unit mover
    real x
    real y
    integer xp
    timer clock = CreateTimer()
    integer unitid
    boolean transferFlag
        
    static method Get takes unit whichUnit returns Relocation
        local Relocation dat = Relocation[whichUnit] //check if an instance is already associated with whichUnit
        if dat == 0 then //if not
            set dat = Relocation.allocate() //allocate a new instance
            
            //insert whatever you want to happen when a new instance is created here
            set dat.transferFlag = false
            
            set Relocation[whichUnit] = dat //associate the newly allocate instance with whichUnit
        endif
        return dat
    endmethod
    
    static method Transfer takes unit sourceUnit, unit targetUnit returns Relocation
        local Relocation dat = Relocation.Get(sourceUnit)
        //to make this function safer, you should check if targetUnit has an instance set before starting the transfer.
        set dat.transferFlag = true //anything in onDestroy should not be carried out for a transfering instance.
        
        //by releasing, the instance will be freed from the previous unit, and next in line to be allocated.
        call dat.release()
        set dat = Relocation.allocate()
        
        set dat.transferFlag = false
        
        set Relocation[targetUnit] = dat //transfer complete
        return dat
    endmethod
    
    method onDestroy takes nothing returns nothing
        if not .transferFlag then
            
            //this block will only be called whenever an instance is fully destroyed.
                        //transfered instances will be ignored
            
            call PauseTimer(.clock)
            call ClearTimerStructA(.clock)
            call DestroyTimer(.clock)
        endif
    endmethod


endstruct

private function C2 takes nothing returns boolean
    return GetIssuedOrderId() == 852165
endfunction

private function C3 takes nothing returns boolean
    return GetIssuedOrderId() == 852166 and IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true
endfunction

private function RootHandle takes nothing returns nothing
    local Relocation dat = GetTimerStructA(GetExpiredTimer())
    if GetUnitX(dat.mover) == dat.x and GetUnitY(dat.mover) == dat.y then
     call ReplaceTower(dat.mover, dat.unitid, 'h01C')
     call Relocation.Transfer(dat.mover, bj_lastCreatedUnit)
     set dat.mover = bj_lastCreatedUnit
     call SetHeroXP(bj_lastCreatedUnit, dat.xp, false)
     call PauseTimer(dat.clock)
    endif
    if GetUnitCurrentOrder(dat.mover) != 852165 then
     call PauseTimer(dat.clock)
    endif
endfunction

private function Root takes nothing returns nothing
    local Relocation dat = Relocation[GetTriggerUnit()]
    local location l = GetOrderPointLoc()
    set dat.mover = GetTriggerUnit()
    set dat.x = GetLocationX(l)
    set dat.y = GetLocationY(l)
    set dat.clock = CreateTimer()
    call SetTimerStructA(dat.clock, dat)
    call TimerStart(dat.clock, 0.2, true, function RootHandle)
    call RemoveLocation(l)
    set l = null
endfunction

private function Uproot takes nothing returns nothing
    local Relocation dat = Relocation[GetTriggerUnit()]
    if dat == null then
     call BJDebugMsg("Dat is null")
     set dat = Relocation.create()
     //call SetTimerStructA(dat.clock, dat)
    else
     call BJDebugMsg("dat is not null")
    endif
    set dat.xp = GetHeroXP(GetTriggerUnit())
    call KillDummy(GetTriggerUnit())
    set dat.unitid = GetUnitTypeId(GetTriggerUnit())
    call ReplaceTower(GetTriggerUnit(), 'h02A', 'none')
    call IssueImmediateOrderById(bj_lastCreatedUnit, 852166)
    call Relocation.Transfer(GetTriggerUnit(), bj_lastCreatedUnit)
    //set dat.mover = bj_lastCreatedUnit
endfunction

private function C1 takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'H029'
endfunction

private function EntryUproot takes nothing returns nothing
    local Relocation dat = Relocation[GetTriggerUnit()]
    if dat == null then
     call IssueImmediateOrderById(GetTriggerUnit(), 852166)
    else
    endif
endfunction


//===========================================================================
private function I takes nothing returns nothing
    local trigger t = CreateTrigger()
    local region r = CreateRegion()
    call RegionAddRect(r, bj_mapInitialPlayableArea)
    call TriggerRegisterEnterRegion(t, r, Condition(function C1))
    call TriggerAddAction(t, function EntryUproot)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
    call TriggerAddCondition(t, Condition(function C2))
    call TriggerAddAction(t, function Root)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)
    call TriggerAddCondition(t, Condition(function C3))
    call TriggerAddAction(t, function Uproot)
endfunction

endscope


Now same thing happens, except there is only one red line with that error message :D

Every place you have:

JASS:
local Relocation dat = Relocation[GetTriggerUnit()]


replace it with:

JASS:
local Relocation dat = Relocation.Get(GetTriggerUnit())


Do not use Relocation[someUnitVariable] outside of Get or Transfer.

I'll check later why the PUI comes if it persists
 

Faust

You can change this now in User CP.
Reaction score
123
JASS:
scope Relocation initializer I

private struct Relocation
    //! runtextmacro PUI()
    unit mover
    real x
    real y
    integer xp
    timer clock = CreateTimer()
    integer unitid
    boolean transferFlag
        
    static method Get takes unit whichUnit returns Relocation
        local Relocation dat = Relocation[whichUnit] //check if an instance is already associated with whichUnit
        if dat == 0 then //if not
            set dat = Relocation.allocate() //allocate a new instance
            
            //insert whatever you want to happen when a new instance is created here
            set dat.transferFlag = false
            
            set Relocation[whichUnit] = dat //associate the newly allocate instance with whichUnit
        endif
        return dat
    endmethod
    
    static method Transfer takes unit sourceUnit, unit targetUnit returns Relocation
        local Relocation dat = Relocation.Get(sourceUnit)
        //to make this function safer, you should check if targetUnit has an instance set before starting the transfer.
        set dat.transferFlag = true //anything in onDestroy should not be carried out for a transfering instance.
        
        //by releasing, the instance will be freed from the previous unit, and next in line to be allocated.
        call dat.release()
        set dat = Relocation.allocate()
        
        set dat.transferFlag = false
        
        set Relocation[targetUnit] = dat //transfer complete
        return dat
    endmethod
    
    method onDestroy takes nothing returns nothing
        if not .transferFlag then
            
            //this block will only be called whenever an instance is fully destroyed.
                        //transfered instances will be ignored
            
            call PauseTimer(.clock)
            call ClearTimerStructA(.clock)
            call DestroyTimer(.clock)
        endif
    endmethod


endstruct

private function C2 takes nothing returns boolean
    return GetIssuedOrderId() == 852165
endfunction

private function C3 takes nothing returns boolean
    return GetIssuedOrderId() == 852166 and IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true
endfunction

private function RootHandle takes nothing returns nothing
    local Relocation dat = GetTimerStructA(GetExpiredTimer())
    if GetUnitX(dat.mover) == dat.x and GetUnitY(dat.mover) == dat.y then
     call ReplaceTower(dat.mover, dat.unitid, 'h01C')
     call Relocation.Transfer(dat.mover, bj_lastCreatedUnit)
     set dat.mover = bj_lastCreatedUnit
     call SetHeroXP(bj_lastCreatedUnit, dat.xp, false)
     call PauseTimer(dat.clock)
    endif
    if GetUnitCurrentOrder(dat.mover) != 852165 then
     call PauseTimer(dat.clock)
    endif
endfunction

private function Root takes nothing returns nothing
    local Relocation dat = Relocation.Get(GetTriggerUnit())
    local location l = GetOrderPointLoc()
    set dat.mover = GetTriggerUnit()
    set dat.x = GetLocationX(l)
    set dat.y = GetLocationY(l)
    set dat.clock = CreateTimer()
    call SetTimerStructA(dat.clock, dat)
    call TimerStart(dat.clock, 0.2, true, function RootHandle)
    call RemoveLocation(l)
    set l = null
endfunction

private function Uproot takes nothing returns nothing
    local Relocation dat = Relocation.Get(GetTriggerUnit())
    if dat == null then
     call BJDebugMsg("Dat is null")
     set dat = Relocation.create()
     //call SetTimerStructA(dat.clock, dat)
    else
     call BJDebugMsg("dat is not null")
    endif
    set dat.xp = GetHeroXP(GetTriggerUnit())
    call KillDummy(GetTriggerUnit())
    set dat.unitid = GetUnitTypeId(GetTriggerUnit())
    call ReplaceTower(GetTriggerUnit(), 'h02A', 'none')
    call IssueImmediateOrderById(bj_lastCreatedUnit, 852166)
    call Relocation.Transfer(GetTriggerUnit(), bj_lastCreatedUnit)
    //set dat.mover = bj_lastCreatedUnit
endfunction

private function C1 takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'H029'
endfunction

private function EntryUproot takes nothing returns nothing
    local Relocation dat = Relocation[GetTriggerUnit()]
    if dat == null then
     call IssueImmediateOrderById(GetTriggerUnit(), 852166)
    else
    endif
endfunction


//===========================================================================
private function I takes nothing returns nothing
    local trigger t = CreateTrigger()
    local region r = CreateRegion()
    call RegionAddRect(r, bj_mapInitialPlayableArea)
    call TriggerRegisterEnterRegion(t, r, Condition(function C1))
    call TriggerAddAction(t, function EntryUproot)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
    call TriggerAddCondition(t, Condition(function C2))
    call TriggerAddAction(t, function Root)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)
    call TriggerAddCondition(t, Condition(function C3))
    call TriggerAddAction(t, function Uproot)
endfunction

endscope


Well, now no error message, but something else...
The hero unit keeps changing to itself. I mean, it gets replaced a few times per second by itself (I know because hero proper names change, and also the animation resets).
 

Builder Bob

Live free or don't
Reaction score
249
JASS:
scope Relocation initializer I

private struct Relocation
    //! runtextmacro PUI()
    unit mover
    real x
    real y
    integer xp
    timer clock = CreateTimer()
    integer unitid
    boolean transferFlag
        
    static method Get takes unit whichUnit returns Relocation
        local Relocation dat = Relocation[whichUnit] //check if an instance is already associated with whichUnit
        if dat == 0 then //if not
            set dat = Relocation.allocate() //allocate a new instance
            
            //insert whatever you want to happen when a new instance is created here
            set dat.transferFlag = false
            
            set Relocation[whichUnit] = dat //associate the newly allocate instance with whichUnit
        endif
        return dat
    endmethod
    
    static method Transfer takes unit sourceUnit, unit targetUnit returns Relocation
        local Relocation dat = Relocation.Get(sourceUnit)
        //to make this function safer, you should check if targetUnit has an instance set before starting the transfer.
        set dat.transferFlag = true //anything in onDestroy should not be carried out for a transfering instance.
        
        //by releasing, the instance will be freed from the previous unit, and next in line to be allocated.
        call dat.release()
        set dat = Relocation.allocate()
        
        set dat.transferFlag = false
        
        set Relocation[targetUnit] = dat //transfer complete
        return dat
    endmethod
    
    method onDestroy takes nothing returns nothing
        if not .transferFlag then
            
            //this block will only be called whenever an instance is fully destroyed.
                        //transfered instances will be ignored
            
            call PauseTimer(.clock)
            call ClearTimerStructA(.clock)
            call DestroyTimer(.clock)
        endif
    endmethod


endstruct

private function C2 takes nothing returns boolean
    return GetIssuedOrderId() == 852165
endfunction

private function C3 takes nothing returns boolean
    return GetIssuedOrderId() == 852166 and IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true
endfunction

private function RootHandle takes nothing returns nothing
    local Relocation dat = GetTimerStructA(GetExpiredTimer())
    if GetUnitX(dat.mover) == dat.x and GetUnitY(dat.mover) == dat.y then
     call ReplaceTower(dat.mover, dat.unitid, 'h01C')
     call Relocation.Transfer(dat.mover, bj_lastCreatedUnit)
     set dat.mover = bj_lastCreatedUnit
     call SetHeroXP(bj_lastCreatedUnit, dat.xp, false)
     call PauseTimer(dat.clock)
    endif
    if GetUnitCurrentOrder(dat.mover) != 852165 then
     call PauseTimer(dat.clock)
    endif
endfunction

private function Root takes nothing returns nothing
    local Relocation dat = Relocation.Get(GetTriggerUnit())
    local location l = GetOrderPointLoc()
    set dat.mover = GetTriggerUnit()
    set dat.x = GetLocationX(l)
    set dat.y = GetLocationY(l)
    set dat.clock = CreateTimer()
    call SetTimerStructA(dat.clock, dat)
    call TimerStart(dat.clock, 0.2, true, function RootHandle)
    call RemoveLocation(l)
    set l = null
endfunction

private function Uproot takes nothing returns nothing
    local Relocation dat = Relocation.Get(GetTriggerUnit())
    if dat == null then
     call BJDebugMsg("Dat is null")
     set dat = Relocation.create()
     //call SetTimerStructA(dat.clock, dat)
    else
     call BJDebugMsg("dat is not null")
    endif
    set dat.xp = GetHeroXP(GetTriggerUnit())
    call KillDummy(GetTriggerUnit())
    set dat.unitid = GetUnitTypeId(GetTriggerUnit())
    call ReplaceTower(GetTriggerUnit(), 'h02A', 'none')
    call IssueImmediateOrderById(bj_lastCreatedUnit, 852166)
    call Relocation.Transfer(GetTriggerUnit(), bj_lastCreatedUnit)
    //set dat.mover = bj_lastCreatedUnit
endfunction

private function C1 takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'H029'
endfunction

private function EntryUproot takes nothing returns nothing
    local Relocation dat = Relocation[GetTriggerUnit()]
    if dat == null then
     call IssueImmediateOrderById(GetTriggerUnit(), 852166)
    else
    endif
endfunction


//===========================================================================
private function I takes nothing returns nothing
    local trigger t = CreateTrigger()
    local region r = CreateRegion()
    call RegionAddRect(r, bj_mapInitialPlayableArea)
    call TriggerRegisterEnterRegion(t, r, Condition(function C1))
    call TriggerAddAction(t, function EntryUproot)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
    call TriggerAddCondition(t, Condition(function C2))
    call TriggerAddAction(t, function Root)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)
    call TriggerAddCondition(t, Condition(function C3))
    call TriggerAddAction(t, function Uproot)
endfunction

endscope


Well, now no error message, but something else...
The hero unit keeps changing to itself. I mean, it gets replaced a few times per second by itself (I know because hero proper names change, and also the animation resets).

I attempted to create a test map with your trigger, but I'm having a very hard time navigating with all those indescriptive names used.

What hero keeps changing itself? Is he the tower being replaced?

What is 'H029', 'h02A', 'h01C' and 'none'?



JASS:
    if dat == null then
     call BJDebugMsg("Dat is null")
     set dat = Relocation.create()
     //call SetTimerStructA(dat.clock, dat)
    else
     call BJDebugMsg("dat is not null")
    endif

This is redundant as it is already done in the method Relocation.Get()

JASS:
private function EntryUproot takes nothing returns nothing
    local Relocation dat = Relocation[GetTriggerUnit()]
    if dat == null then
     call IssueImmediateOrderById(GetTriggerUnit(), 852166)
    else
    endif
endfunction

I don't see what this does really.


I feel like I'm stumbling to help you now. A test map would be very helpful.
 

Faust

You can change this now in User CP.
Reaction score
123
I attempted to create a test map with your trigger, but I'm having a very hard time navigating with all those indescriptive names used.

What hero keeps changing itself? Is he the tower being replaced?

What is 'H029', 'h02A', 'h01C' and 'none'?

I successfully recreated the problem in a testmap, which I'm uploading now.

'none' is just none. That is rawcode of nothing, so ReplaceTower doesn't place anything there (as a moving unit should not have ground texture).

This is redundant as it is already done in the method Relocation.Get()

I got rid of it now.


I don't see what this does really.

You see, whenever a unit enters the game and has root, it automatically is rooted. This also applies when any unit receives the ability, they are automatically rooted.
Since I'm making a maul type game, and the training building will somewhere in the maze, it wouldn't be wise to create a blocking unit when the round is on and creeps are coming through the maze.
 

Faust

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

JASS:
scope Relocation initializer I

private struct Relocation
    //! runtextmacro PUI()
    unit mover
    real x
    real y
    integer xp
    timer clock = CreateTimer()
    integer unitid
    boolean transferFlag
        
    static method Get takes unit whichUnit returns Relocation
        local Relocation dat = Relocation[whichUnit] //check if an instance is already associated with whichUnit
        if dat == 0 then //if not
            set dat = Relocation.allocate() //allocate a new instance
            
            //insert whatever you want to happen when a new instance is created here
            set dat.transferFlag = false
            
            set Relocation[whichUnit] = dat //associate the newly allocate instance with whichUnit
        endif
        return dat
    endmethod
    
    static method Transfer takes unit sourceUnit, unit targetUnit returns Relocation
        local Relocation dat = Relocation.Get(sourceUnit)
        //to make this function safer, you should check if targetUnit has an instance set before starting the transfer.
        set dat.transferFlag = true //anything in onDestroy should not be carried out for a transfering instance.
        
        //by releasing, the instance will be freed from the previous unit, and next in line to be allocated.
        call dat.release()
        set dat = Relocation.allocate()
        
        set dat.transferFlag = false
        
        set Relocation[targetUnit] = dat //transfer complete
        return dat
    endmethod
    
    method onDestroy takes nothing returns nothing
        if not .transferFlag then
            
            //this block will only be called whenever an instance is fully destroyed.
                        //transfered instances will be ignored
            
            call PauseTimer(.clock)
            call ClearTimerStructA(.clock)
            call DestroyTimer(.clock)
        endif
    endmethod


endstruct

private function C2 takes nothing returns boolean
    return GetIssuedOrderId() == 852165
endfunction

private function C3 takes nothing returns boolean
    return GetIssuedOrderId() == 852166 and IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true
endfunction

private function RootHandle takes nothing returns nothing
    local Relocation dat = GetTimerStructA(GetExpiredTimer())
    call BJDebugMsg("RootHandle")
    if GetUnitX(dat.mover) == dat.x and GetUnitY(dat.mover) == dat.y then
     call ReplaceTower(dat.mover, dat.unitid, 'h01C')
     call Relocation.Transfer(dat.mover, bj_lastCreatedUnit)
     set dat.mover = bj_lastCreatedUnit
     call SetHeroXP(bj_lastCreatedUnit, dat.xp, false)
     call PauseTimer(dat.clock)
     call BJDebugMsg("RH 1")
    endif
    if GetUnitCurrentOrder(dat.mover) != 852165 then
     call BJDebugMsg("RH 2")
     call PauseTimer(dat.clock)
    endif
endfunction

private function Root takes nothing returns nothing
    local Relocation dat = Relocation.Get(GetTriggerUnit())
    local location l = GetOrderPointLoc()
    call BJDebugMsg("Root")
    set dat.mover = GetTriggerUnit()
    set dat.x = GetLocationX(l)
    set dat.y = GetLocationY(l)
    set dat.clock = CreateTimer()
    call SetTimerStructA(dat.clock, dat)
    call TimerStart(dat.clock, 0.2, true, function RootHandle)
    call RemoveLocation(l)
    set l = null
endfunction

private function Uproot takes nothing returns nothing
    local Relocation dat = Relocation.Get(GetTriggerUnit())
    call BJDebugMsg("Uproot")
    set dat.xp = GetHeroXP(GetTriggerUnit())
    call KillDummy(GetTriggerUnit())
    set dat.unitid = GetUnitTypeId(GetTriggerUnit())
    call ReplaceTower(GetTriggerUnit(), 'h02A', 'none')
    call IssueImmediateOrderById(bj_lastCreatedUnit, 852166)
    call Relocation.Transfer(GetTriggerUnit(), bj_lastCreatedUnit)
    //set dat.mover = bj_lastCreatedUnit
endfunction

private function C1 takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'H029'
endfunction

private function EntryUproot takes nothing returns nothing
    local Relocation dat = Relocation[GetTriggerUnit()]
    call BJDebugMsg("EntryUproot")
    if dat == null then
     call IssueImmediateOrderById(GetTriggerUnit(), 852166)
    else
    endif
endfunction


//===========================================================================
private function I takes nothing returns nothing
    local trigger t = CreateTrigger()
    local region r = CreateRegion()
    call RegionAddRect(r, bj_mapInitialPlayableArea)
    call TriggerRegisterEnterRegion(t, r, Condition(function C1))
    call TriggerAddAction(t, function EntryUproot)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
    call TriggerAddCondition(t, Condition(function C2))
    call TriggerAddAction(t, function Root)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)
    call TriggerAddCondition(t, Condition(function C3))
    call TriggerAddAction(t, function Uproot)
endfunction

endscope



Don't leave me alone Builder T.T

Added debugmsges, apparently, roothandle doesn't stop.
When the problem is "happening", the following is spammed on my screen:
RootHandle
RH 1
RH 2
EntryUproot
~repeat~
 

Builder Bob

Live free or don't
Reaction score
249
Bump

(---)

Don't leave me alone Builder T.T

Added debugmsges, apparently, roothandle doesn't stop.
When the problem is "happening", the following is spammed on my screen:
RootHandle
RH 1
RH 2
EntryUproot
~repeat~

Sorry that I couldn't help you yesterday. I was checking out the testmap yesterday, and it helped quite a bit. Unfortunately I didn't have enough time to find the whole solution to the problem right away.

It looks like the EntryUproot function causes the problem with an endless stream of root/uproot orders which makes the unit get replaced over and over.

I'm going to see how it can be avoided in a little bit.

By the way, would you be open to use Chaos to change the unit into another instead of replacing it? You'd probably have to make the caravan a hero so it won't crash, but the issue about newly created units triggering the EnterRegion event won't be there anymore.
 

Faust

You can change this now in User CP.
Reaction score
123
I know chaos, it's a wonder tool... But I don't know how much lag it would cause.
And I'm not sure if chaos doesn't trigger entering unit anyway...

And most importantly, there will be many units in that race (I estimate 50), and creating 50 chaos ability, is not very practical.

I was thinking about what could separate the newly trained units from the replaced one, and I think I have an idea. Brb :p


EDIT: It's DEFINITELY not the EntryUproot what causes the problem (at least not only that).

While reading your last post, I came up with 2 ideas
#1, add the ReplaceTower created unit into a unitgroup, and in EntryUproot, check if that unit is in the group.
But I thought it might be too slow, and I don't fancy globals anyway, so I tried
#2, the newly created unit in ReplaceTower is called bj_lastCreatedUnit, and there is no delay.
So why not check for that? if GetTriggerUnit() != bj_lastCreatedUnit then
And it kept doing the same thing

So I was like wtf, I commented out the EntryUproot's IssueImmediate order, so I can uproot the entering unit manually, which I did, and when I wanted to root it down, it STILL kept doing the same thing (replacing the hero unit with hero unit).

I think the problem is in RootHandle, the timer doesn't pause, so it keeps checking if the place where the unit is correct. As it is correct, it gets replaced.

... a few tests ...

Indeed. I fixed it! for now...

I moved the PauseTimer function before ReplaceTower, and woot.

... testing for the original problem ...

No free of type error messages appearing! Grand succes!

Thank you zillion times ! I hope it won't bug up. I'm having problem with unit evading condition though :p
 

Builder Bob

Live free or don't
Reaction score
249
And most importantly, there will be many units in that race (I estimate 50), and creating 50 chaos ability, is not very practical.

I was thinking about what could separate the newly trained units from the replaced one, and I think I have an idea. Brb :p

oh, 50 units. You're right. It does sound like a lot of hassle. I'll wait and see what you find out before going any further.
 

Faust

You can change this now in User CP.
Reaction score
123
Done and thanks (See my previous post)

EDIT: More problems may arise now... As the rooting command can be canceled. Testing ^^

EDIT2: For now, there are no problems whatsoever with that :) AWESOME
 

Builder Bob

Live free or don't
Reaction score
249
Done and thanks (See my previous post)

EDIT: More problems may arise now... As the rooting command can be canceled. Testing ^^

EDIT2: For now, there are no problems whatsoever with that :) AWESOME

Great job! Sound like you're getting quite good with debugging and figuring out where the problem arises.

I hope no more bugs arises.


A few small issues I saw in your code before:
  • The member clock has initial value CreateTimer(). Additionally clock is set to CreateTimer() on every root order.
  • If you order a unit to root repeatedly within .2 seconds, multiple timers will be created for that unit.
This can cause many leaks and bugs as multiple different timers may expire for the same unit.
What I'd suggest as a solution would be to give clock the initial value CreateTimer(), and never destroy it. ClearTimerStructA on destroy, and SetTimerStructA on creation. Both clear and set on transfer.

On root orders you won't have to create any timers or set any timer data.
 

Faust

You can change this now in User CP.
Reaction score
123
JASS:
scope Relocation initializer I

private struct Relocation
    //! runtextmacro PUI()
    unit mover
    real x
    real y
    integer xp
    timer clock = CreateTimer()
    integer unitid
    boolean transferFlag
        
    static method Get takes unit whichUnit returns Relocation
        local Relocation dat = Relocation[whichUnit] //check if an instance is already associated with whichUnit
        if dat == 0 then //if not
            set dat = Relocation.allocate() //allocate a new instance
            
            //insert whatever you want to happen when a new instance is created here
            set dat.transferFlag = false
            
            set Relocation[whichUnit] = dat //associate the newly allocate instance with whichUnit
        endif
        return dat
    endmethod
    
    static method Transfer takes unit sourceUnit, unit targetUnit returns Relocation
        local Relocation dat = Relocation.Get(sourceUnit)
        //to make this function safer, you should check if targetUnit has an instance set before starting the transfer.
        set dat.transferFlag = true //anything in onDestroy should not be carried out for a transfering instance.
        
        //by releasing, the instance will be freed from the previous unit, and next in line to be allocated.
        call dat.release()
        set dat = Relocation.allocate()
        
        set dat.transferFlag = false
        
        set Relocation[targetUnit] = dat //transfer complete
        return dat
    endmethod
    
    method onDestroy takes nothing returns nothing
        if not .transferFlag then
            
            //this block will only be called whenever an instance is fully destroyed.
                        //transfered instances will be ignored
            
            call PauseTimer(.clock)
            call ClearTimerStructA(.clock)
            call DestroyTimer(.clock)
        endif
    endmethod


endstruct

private function C2 takes nothing returns boolean
    return GetIssuedOrderId() == 852165
endfunction

private function C3 takes nothing returns boolean
    return GetIssuedOrderId() == 852166 and IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true
endfunction

private function RootHandle takes nothing returns nothing
    local Relocation dat = GetTimerStructA(GetExpiredTimer())
    call BJDebugMsg("RH running")
    if GetUnitCurrentOrder(dat.mover) != 852165 then
     call PauseTimer(dat.clock)
     //call ClearTimerStructA(dat.clock)
    endif
    if GetUnitX(dat.mover) == dat.x and GetUnitY(dat.mover) == dat.y then
     call PauseTimer(dat.clock)
     call ReplaceTower(dat.mover, dat.unitid, 'h01C')
     call Relocation.Transfer(dat.mover, bj_lastCreatedUnit)
     set dat.mover = bj_lastCreatedUnit
     call SetHeroXP(bj_lastCreatedUnit, dat.xp, false)
     call ClearTimerStructA(dat.clock)
    endif
    
endfunction

private function Root takes nothing returns nothing
    local Relocation dat = Relocation.Get(GetTriggerUnit())
    local location l = GetOrderPointLoc()
    set dat.mover = GetTriggerUnit()
    set dat.x = GetLocationX(l)
    set dat.y = GetLocationY(l)
    set dat.clock = CreateTimer()
    call SetTimerStructA(dat.clock, dat)
    call TimerStart(dat.clock, 0.2, true, function RootHandle)
    call RemoveLocation(l)
    set l = null
endfunction

private function Uproot takes nothing returns nothing
    local Relocation dat = Relocation.Get(GetTriggerUnit())
    set dat.xp = GetHeroXP(GetTriggerUnit())
    call KillDummy(GetTriggerUnit())
    set dat.unitid = GetUnitTypeId(GetTriggerUnit())
    call ReplaceTower(GetTriggerUnit(), 'h02A', 'none')
    call IssueImmediateOrderById(bj_lastCreatedUnit, 852166)
    call Relocation.Transfer(GetTriggerUnit(), bj_lastCreatedUnit)
    //set dat.mover = bj_lastCreatedUnit
endfunction

private function C1 takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'H029'
endfunction

private function EntryUproot takes nothing returns nothing
    if GetTriggerUnit() != bj_lastCreatedUnit then
     call IssueImmediateOrderById(GetTriggerUnit(), 852166)
    else
    endif
endfunction


//===========================================================================
private function I takes nothing returns nothing
    local trigger t = CreateTrigger()
    local region r = CreateRegion()
    call RegionAddRect(r, bj_mapInitialPlayableArea)
    call TriggerRegisterEnterRegion(t, r, Condition(function C1))
    call TriggerAddAction(t, function EntryUproot)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
    call TriggerAddCondition(t, Condition(function C2))
    call TriggerAddAction(t, function Root)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)
    call TriggerAddCondition(t, Condition(function C3))
    call TriggerAddAction(t, function Uproot)
endfunction

endscope


Current code.

If I reorder the unit (no need 0.2 seconds), I mean the unit is moving somewhere to root, and I reorder it to root somewhere else, the RH messages begin to show at a doubled rate.

I tried what you wanted, and now whenever the unit is created to the hero rooted one (the one created in RootHandle), I get an error:

ERROR: ClearTimerStructA[bunchofnumbers] - clear attempt on bad key.

When I combine the two error, the latter shows up a faster rate too of course.

Also, if I don't set dat.clock = CreateTimer() in the Root function, every time I order root I get this:
Warning: SetTimerStructA[bunchofnumber] - index blah collision 1, then 2, then 3, etc.
 

Builder Bob

Live free or don't
Reaction score
249
Clearing and Setting the data on the timers must be done very carefully.

Here's a working map. Ask if you're unsure about any of the changes I made.

JASS:
scope Relocation initializer I

globals
    private constant integer ROOT = 852165
    private constant integer UNROOT = 852166
    private constant integer CARAVANUNIT = 'h002'
    private constant integer HEROUNIT1 = 'H000'
    private constant integer HEROUNIT2 = 'H001'
    private constant integer ADDITIONALUNIT = 'h003'
endglobals

private struct Relocation
    //! runtextmacro PUI()
    unit mover
    real x
    real y
    integer xp
    timer clock
    integer unitid
    boolean transferFlag
        
    static method Get takes unit whichUnit returns Relocation
        local Relocation dat = Relocation[whichUnit]
        if dat == 0 then
            set dat = Relocation.allocate()
            
            set dat.transferFlag = false
            set dat.mover = whichUnit
            if dat.clock == null then
                set dat.clock = CreateTimer()
            endif
            call SetTimerStructA(dat.clock, dat)
            
            set Relocation[whichUnit] = dat
        endif
        return dat
    endmethod
    
    static method Transfer takes unit sourceUnit, unit targetUnit returns Relocation
        local Relocation dat = Relocation.Get(sourceUnit)
        set dat.transferFlag = true
        if dat.clock != null then
        endif
        
        call dat.release()
        set dat = Relocation.allocate()
        
        set dat.transferFlag = false
        set dat.mover = targetUnit
        
        set Relocation[targetUnit] = dat
        return dat
    endmethod
    
    method onDestroy takes nothing returns nothing
        if not .transferFlag then
            call ClearTimerStructA(.clock)
            call PauseTimer(.clock)
        endif
    endmethod


endstruct

private function C2 takes nothing returns boolean
    return GetIssuedOrderId() == ROOT
endfunction

private function C3 takes nothing returns boolean
    return GetIssuedOrderId() == UNROOT and IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true
endfunction

private function RootHandle takes nothing returns nothing
    local Relocation dat = GetTimerStructA(GetExpiredTimer())
    call BJDebugMsg("RH running " + I2S(dat))
    if GetUnitCurrentOrder(dat.mover) != ROOT then
     call PauseTimer(dat.clock)
    endif
    if GetUnitX(dat.mover) == dat.x and GetUnitY(dat.mover) == dat.y then
     call PauseTimer(dat.clock)
     call ReplaceTower(dat.mover, dat.unitid, ADDITIONALUNIT)
     call Relocation.Transfer(dat.mover, bj_lastCreatedUnit)
     set dat.mover = bj_lastCreatedUnit
     call SetHeroXP(bj_lastCreatedUnit, dat.xp, false)
    endif
    
endfunction

private function Root takes nothing returns nothing
    local Relocation dat = Relocation.Get(GetTriggerUnit())
    set dat.x = GetOrderPointX()
    set dat.y = GetOrderPointY()
    call TimerStart(dat.clock, 0.2, true, function RootHandle)
endfunction

private function Uproot takes nothing returns nothing
    local Relocation dat = Relocation.Get(GetTriggerUnit())
    set dat.xp = GetHeroXP(GetTriggerUnit())
    call KillDummy(GetTriggerUnit())
    set dat.unitid = GetUnitTypeId(GetTriggerUnit())
    call ReplaceTower(GetTriggerUnit(), CARAVANUNIT, 'none')
    call Relocation.Transfer(GetTriggerUnit(), bj_lastCreatedUnit)
    call IssueImmediateOrderById(bj_lastCreatedUnit, UNROOT)
    //set dat.mover = bj_lastCreatedUnit
endfunction

private function C1 takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == HEROUNIT1 or GetUnitTypeId(GetFilterUnit()) == HEROUNIT2
endfunction

private function EntryUproot takes nothing returns nothing
    if GetTriggerUnit() != bj_lastCreatedUnit then
     call IssueImmediateOrderById(GetTriggerUnit(), UNROOT)
    else
    endif
endfunction


//===========================================================================
private function I takes nothing returns nothing
    local trigger t = CreateTrigger()
    local region r = CreateRegion()
    call RegionAddRect(r, bj_mapInitialPlayableArea)
    call TriggerRegisterEnterRegion(t, r, Condition(function C1))
    call TriggerAddAction(t, function EntryUproot)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
    call TriggerAddCondition(t, Condition(function C2))
    call TriggerAddAction(t, function Root)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)
    call TriggerAddCondition(t, Condition(function C3))
    call TriggerAddAction(t, function Uproot)
endfunction

endscope
 

Attachments

  • RootRelocation.w3x
    32.6 KB · Views: 143

Faust

You can change this now in User CP.
Reaction score
123
I shit you not, that was the code I made, and then you read my elder test map code, and tried to give instructions thinking about that, and that's why I messed it up. Rotfl.

Thank you again and again!
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +1
  • V-SNES V-SNES:
    Happy Friday!
    +1

      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