HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Spawn/Despawn Unit Script

08-18-2008, 12:09 PM#1
fX_
SPAWNS/DESPAWNS UNITS
with animations + sounds (subsequent or collateral to fading in/out)

Collapse JASS:
//SPAWN/DESPAWN//
//what this does:
//spawns (fades in/out) a unit, plays a spawning animation (with an animation-start sound and animation-end sound)
//then issues an order after spawning.
//
//you can make the unit movable/unmovable (paused/unpaused) while spawning and, seperately, while animating.

//call SpawnUnit(integer intSpawnDespawn, boolean pausedSpawn, boolean pausedAnim, unit spawn, real spawnDuration, integer red, integer green, integer blue, integer alpha, sound start, sound end, string animStr, integer animInt, real speedAnim, real animDuration, string order, real xTarget, real yTarget, unit target)
//
//* integer PosSpawnNegDespawn: set to 1 if u are spawning a unit; -1 if u are despawning it.
//*boolean pausedSpawn: true if you want the spawned unit to be paused while it fades in/out.
//                      if this is false the unit will get to its animation-playing bit immediately
//                      (it'll fade (in/out) whle playing animation)
//*boolean pausedAnim: true if you want the spawned unit to be paused while it performs its animations
//*unit spawn: the unit to be spawned/despawned
//*real spawnDuration: duration of interval over w/c unit will be faded in/faded out
//*integer red: if spawning a unit, set this to the desired color of the unit to be spawned;
//              if despawning a unit, set this to the CURRENT color of the unit to be despawned.
//*integer green: ^ of green
//*integer blue: ^ of blue
//*integer alpha: ^ of alpha
//*sound start: sound played on unit once it starts to perform its animation
//*sound end: sound played on unit after it plays its animation
//*string animstr: string of animation to be played
//                 set this to "stand" if you dont want any anims to be played.
//                 set this to "null" if you want to play an animation by index (SetUnitAnimationByIndex)
//*string animint: integer index of animation to be played
//*real speedanim: animation speed...
//*real animduration: duration of interval over w/c animation will be played
//*string order: order issued to the unit after it performs its animation.
//               (set animation duration to 0.00 and pausedSpawn to false to get an insta-ordered, fading in unit)
//               (set to "null") to issue no order
//*real xTarget: x coordinate of target point of order.
//*real yTarget: y coordinate of target point of order.
//              set this AND xTarget to 0.00 if you wish to issue an immediate order
//*unit target: target of order.
//              set this to "null" if you wish to use issue a point or immediate order



library SpawnUnit
globals
    private timer gTIMER = CreateTimer()
    private integer gINT_CountData = 0
    private Data array gDATA
    private constant real gR_DurationTimer = 0.10
endglobals

struct Data
    integer intDataIndex
    integer intSpawnDespawn
    boolean boolPausedSpawn
    boolean boolPausedAnim
    boolean boolSpawnOn
    boolean boolAnimOn
    integer intCountInterval
    integer intCountMaxInterval
    unit uSpawn
    integer intRedCount
    integer intGreenCount
    integer intBlueCount
    integer intAlphaCount
    integer intRedInc
    integer intGreenInc
    integer intBlueInc
    integer intAlphaInc
    sound sndStart
    sound sndEnd
    string strAnim
    integer intAnim
    real rSpeedAnim
    integer intCountIntervalAnim
    integer intCountMaxIntervalAnim
    string strOrder
    real rXTarget
    real rYTarget
    unit uTarget
    
    static method Create takes integer intSpawnDespawn, boolean pausedSpawn, boolean pausedAnim, unit spawn, real spawnDuration, integer red, integer green, integer blue, integer alpha, sound start, sound end, string animStr, integer animInt, real speedAnim, real animDuration, string order, real xTarget, real yTarget, unit target returns Data
        local Data NewData = Data.allocate()
        set NewData.intDataIndex = gINT_CountData
        set NewData.intSpawnDespawn = intSpawnDespawn
        set NewData.boolPausedSpawn = pausedSpawn
        set NewData.boolPausedAnim = pausedAnim
        set NewData.intCountInterval = 0
        set NewData.intCountMaxInterval = R2I(spawnDuration/gR_DurationTimer)
        set NewData.uSpawn = spawn
        if intSpawnDespawn == -1 then
            set NewData.intRedCount = red
            set NewData.intGreenCount = green
            set NewData.intBlueCount = blue
            set NewData.intAlphaCount = alpha
        else
            set NewData.intRedCount = 0
            set NewData.intGreenCount = 0
            set NewData.intBlueCount = 0
            set NewData.intAlphaCount = 0
        endif
        set NewData.intRedInc = intSpawnDespawn * red/NewData.intCountMaxInterval
        set NewData.intGreenInc = intSpawnDespawn * green/NewData.intCountMaxInterval
        set NewData.intBlueInc = intSpawnDespawn * blue/NewData.intCountMaxInterval
        set NewData.intAlphaInc = intSpawnDespawn * alpha/NewData.intCountMaxInterval
        set NewData.sndStart = start
        set NewData.sndEnd = end
        set NewData.strAnim = animStr
        set NewData.intAnim = animInt
        set NewData.rSpeedAnim = speedAnim
        set NewData.intCountMaxIntervalAnim = R2I(animDuration/gR_DurationTimer)
        set NewData.strOrder = order
        set NewData.rXTarget = xTarget
        set NewData.rYTarget = yTarget
        set NewData.uTarget = target
        set NewData.boolSpawnOn = TRUE
        if pausedSpawn == TRUE then
            call PauseUnit(spawn, TRUE)
            set NewData.boolAnimOn = FALSE
        else
            set NewData.boolAnimOn = TRUE
        endif
        return NewData
    endmethod
    
    method Destroy takes nothing returns nothing
        set this.uSpawn = null
        set this.sndStart = null
        set this.sndEnd = null
        set this.strAnim = null
        set this.strOrder = null
        set this.uTarget = null
        set gDATA[gINT_CountData].intDataIndex = gDATA[this.intDataIndex].intDataIndex
        set gDATA[this.intDataIndex] = gDATA[gINT_CountData]
        set gDATA[gINT_CountData] = 0
        set gINT_CountData = gINT_CountData - 1
        if gINT_CountData == 0 then
            call PauseTimer(gTIMER)
        endif
    endmethod
    
    method Order takes nothing returns nothing
        if this.uTarget != null then
            call IssueTargetOrder(this.uSpawn, this.strOrder, this.uTarget)
        elseif this.rXTarget != 0.00 and this.rYTarget != 0.00 then
            call IssuePointOrder(this.uSpawn, this.strOrder, this.rXTarget, this.rYTarget)
        elseif this.strOrder != null then
            call IssueImmediateOrder(this.uSpawn, this.strOrder)
        endif
    endmethod
    
    method Spawn takes nothing returns nothing
        set this.intCountInterval = this.intCountInterval + 1
        if this.intCountInterval <= this.intCountMaxInterval then
            set this.intRedCount = this.intRedCount + this.intRedInc
            set this.intGreenCount = this.intGreenCount + this.intGreenInc
            set this.intBlueCount = this.intBlueCount + this.intBlueInc
            set this.intAlphaCount = this.intAlphaCount + this.intAlphaInc
            call SetUnitVertexColor(this.uSpawn, this.intRedCount, this.intGreenCount, this.intBlueCount, this.intAlphaCount)
        else
            if this.boolPausedSpawn == TRUE then
                call PauseUnit(this.uSpawn, FALSE)
                set this.boolAnimOn = TRUE
            endif
            set this.boolSpawnOn = FALSE
        endif
    endmethod
    
    method Animation takes nothing returns nothing
        set this.intCountIntervalAnim = this.intCountIntervalAnim + 1
        if this.intCountIntervalAnim == 1 then
            if this.boolPausedAnim == TRUE then
                call PauseUnit(this.uSpawn, TRUE)
            endif
            call AttachSoundToUnit(this.sndStart, this.uSpawn)
            call SetSoundVolume(this.sndStart, 127)
            call StartSound(this.sndStart)
            call SetUnitTimeScale(this.uSpawn, this.rSpeedAnim)
            if this.strAnim != null then
                call SetUnitAnimation(this.uSpawn, this.strAnim)
            else
                call SetUnitAnimationByIndex(this.uSpawn, this.intAnim)
            endif
        elseif this.intCountIntervalAnim > this.intCountMaxIntervalAnim then
            set this.boolAnimOn = FALSE
            call AttachSoundToUnit(this.sndEnd, this.uSpawn)
            call SetSoundVolume(this.sndEnd, 127)
            call StartSound(this.sndEnd)
            call SetUnitTimeScale(this.uSpawn, 1.00)
            call SetUnitAnimation(this.uSpawn, "stand")
            if this.boolPausedAnim == TRUE then
                call PauseUnit(this.uSpawn, FALSE)
            endif
        endif
    endmethod
    
    method Execute takes nothing returns nothing
        if this.boolSpawnOn == TRUE then
            call this.Spawn()
        endif
            
        if this.boolAnimOn == TRUE then
            call this.Animation()
        endif
        
        if GetUnitState(this.uSpawn, UNIT_STATE_LIFE) <= 0 or (this.boolSpawnOn == FALSE and this.boolAnimOn == FALSE) then
            call this.Order()
            if this.intSpawnDespawn == -1 then
                call RemoveUnit(this.uSpawn)
            endif
            call this.Destroy()
        endif
    endmethod
endstruct

private function Callback1 takes nothing returns nothing
    local integer INT_CountData = 0
    loop
        set INT_CountData = INT_CountData + 1
        exitwhen INT_CountData > gINT_CountData
        call gDATA[INT_CountData].Execute()
    endloop
endfunction

function SpawnUnit takes integer intSpawnDespawn, boolean pausedSpawn, boolean pausedAnim, unit spawn, real spawnDuration, integer red, integer green, integer blue, integer alpha, sound start, sound end, string animStr, integer animInt, real speedAnim, real animDuration, string order, real xTarget, real yTarget, unit target returns nothing
    set gINT_CountData = gINT_CountData + 1
    if intSpawnDespawn == 1 then
        call SetUnitVertexColor(spawn, 0, 0, 0, 0)
    endif
    set gDATA[gINT_CountData] = Data.Create(intSpawnDespawn, pausedSpawn, pausedAnim, spawn, spawnDuration, red, green, blue, alpha, start, end, animStr, animInt, speedAnim, animDuration, order, xTarget, yTarget, target)
    if gINT_CountData == 1 then
        call TimerStart(gTIMER, gR_DurationTimer, TRUE, function Callback1)
    endif
endfunction
endlibrary
08-18-2008, 01:31 PM#2
Anitarf
You could reduce the argument list of the create function dramatically if you used ARGB. It would still be pretty bloated, though, perhaps it would be cleaner if you had a separate struct for spawning type which you'd only define once and it would hold all the parameters and then it's id would be the only parameter used when actually spawning units.
08-18-2008, 02:45 PM#3
fX_
ya i considered its length when i was testing it in an application
08-18-2008, 04:41 PM#4
Blubb-Tec
thats a too sick number of parameters. I agree to what Anitarf said, use ARGB, and make a custom struct e.g. SpawnUnitStruct, which holds default(null)-values for all the params, then the user can set the params he wants to change himself. Then add a method spawn takes nothing returns nothing and a method despawn takes nothing returns nothing and have the unit to be (de-)spawned as a member of the struct. You might also want have a method spawnXY takes integer unitid, real x, real y, player owner returns nothing which creates the unit for the user, and automatically sets the member value to the newly created unit. Oh, and maybe add a member which defines the "duration" of the unit, I mean after how many seconds it will be faded out automatically again. And I'd like it if that feature would also be able to clean up when the unit is faded out again, like killing/removing the unit and destroying the struct.
08-19-2008, 03:49 AM#5
fX_
what i break it down?

function SpawnUnit -spawndespawn

function AppendAnimation

function AppendOrder

???

but then whenever id like to apply all 3 id have to make 3 calls
08-19-2008, 11:23 AM#6
Blubb-Tec
mhh I'll give a little(lame) example.

Collapse JASS:
struct DisplayTwoStrings
     string s1 = ""
     string s2 = ""
     string color = "|cFF0000"  // red is default
     method DisplayForPlayer takes player p returns nothing
           if .color != "" then
                call DisplayTextToPlayer(p, 0., 0., .color+.s1+.s2+"|r")
           else
                call DisplayTextToPlayer(p, 0., 0., .s1+.s2)
           endif
     endmethod

if you would simply call the DisplayForPlayer method after creation, it would display an empty message to the player. But we use it like this:

Collapse JASS:
function someFunc takes nothing returns nothing
     local DisplayTwoStrings dts = DisplayTwoStrings.create()
     // we set the struct's variables ourselves:
     set dts.s1 = "hello "
     set dts.s2 = "world!"
     call dts.DisplayForPlayer(Player(0))
     // notice: the above message will be red, because red ist default-value
     // now we change the color to blue
     set dts.color = "|cFF0000FF"
     set dts.s1 = "bye bye "
     call dts.DisplayForPlayer(Player(0))  // this message will be blue
     call dts.destroy()
endfunction

The user sets the values for the struct's variables himself, and then calls a method of the struct that uses the structs parameters. That way, if the user only wants to set a few params, he doesn't have to set them all(as shown in the example). Also you can set default-values for certain parameters, like the example above will print all text-messages in red by default.