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

[vJASS] Default Getting the same index "assigned" to an object

Status
Not open for further replies.
Level 5
Joined
Jun 30, 2004
Messages
170
Getting the same index "assigned" to an object

Here's a simple respawning trigger:
JASS:
library RefreshEnemies initializer init requires TimerUtils

private struct Respawn
    unit c
    timer t
    real x
    real y
endstruct

globals
    Respawn array RespawnEnemyGroup
    integer EnemyRefreshCount = 0
endglobals

private function Conditions takes nothing returns boolean
    return GetOwningPlayer(GetDyingUnit()) == Player(11) and RectContainsUnit(gg_rct_W_Battlefields, GetDyingUnit()) == false
endfunction

private function TimerCallback takes nothing returns nothing
    local Respawn data = RespawnEnemyGroup[EnemyRefreshCount]
    local timer t = GetExpiredTimer()
    call PauseTimer(t)
    call SetUnitPosition(data.c, data.x, data.y)
    set RespawnEnemyGroup[EnemyRefreshCount] = RespawnEnemyGroup[EnemyRefreshCount] - 1
    set EnemyRefreshCount = EnemyRefreshCount - 1
    call ReleaseTimer(t)
    call RespawnEnemyGroup[EnemyRefreshCount].destroy()
endfunction

function RemoveEnemyGroup takes unit u returns nothing
    local Respawn data = Respawn.create()
    set EnemyRefreshCount = EnemyRefreshCount + 1
    set RespawnEnemyGroup[EnemyRefreshCount] = data
    set data.c = u
    set data.x = GetUnitX(data.c)
    set data.y = GetUnitY(data.c)
    set data.t = NewTimer()
    call SetUnitPosition(data.c, GetRectCenterX(GetWorldBounds()), GetRectCenterY(GetWorldBounds()))
    call TimerStart(data.t, 60., false, function TimerCallback)
endfunction

//===========================================================================
private function init takes nothing returns nothing
endfunction

endlibrary
What this trigger does is that whenever an enemy unit of a certain type dies, it gets moved to the center of the map (I will change this later), makes a timer that counts down for a minute, then puts the unit back where it disappeared. I probably didn't need a struct to do this, but I really need to practice simple struct usage.

This works great and all, but there's one issue and I knew that this trigger was going to do this when I was making the trigger: the unit that dies is assigned an index in the struct to keep track of it and put it back after a minute. However, I don't know how to identify which index that a particular unit has in the struct array. This causes problems, like so:

Unit A dies and becomes struct index [0]. Timer starts for [0]. Unit B dies and becomes index [1] ten seconds later. But because the index does not change what it is assigned to until timer[0] finishes, when timer[0] does finish we're still at the struct array at [1], causing Unit B to be moved back. Even though Unit A moved first.

How do I go about this the right way? My alternative route is to make this trigger for every unit type, but seriously... that's tedious and I imagine 99% unnecessary. Please tell me that this as easy as it sounds.
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,258
Create a queue structure. Place the structs onto the back of the queue. Every time a timer expires, enqueue from it (remove front) and revive. As long as the revive delay (time from death till it should revive) is the same for all units in the queue it will work fine.

Easiest queue structure I imagine is a simple linked list approach with the front of the queue pointing backwards.
 
Id do something like this...

JASS:
library RefreshEnemies requires TimerUtils

private struct Respawn
    unit c
    real x
    real y
    integer utype

    static method TimerCallback takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local thistype data = GetTimerData(t)
        local unit newunit = CreateUnit(GetOwningPlayer(data.c), data.utype, data.x, data.y, 0)
        call ReleaseTimer(t)
        set t = null
        set newunit = null
    endmethod

    static method RemoveEnemyGroup takes unit u, real x, real y returns thistype
        local thistype data = thistype.create()
        local timer t = NewTimer()
        set data.c = u
        set data.x = x
        set data.y = y
        set data.utype = GetUnitTypeId(data.c)
        call SetTimerData(t, data)        
        call TimerStart(t, 60., false, function thistype.TimerCallback)
        set t = null
        return data
    endmethod
endstruct    

function DyingUnit takes unit u returns nothing
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    call SetUnitPosition(u, GetRectCenterX(GetWorldBounds()), GetRectCenterY(GetWorldBounds()))
    call Respawn.RemoveEnemyGroup(u,x,y)             
endfunction

endlibrary
 
Last edited:
Status
Not open for further replies.
Top