• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Unit Spawn - Submission

Status
Not open for further replies.
vJASS:
scope Spawn initializer Init

    globals
        hashtable hash = InitHashtable()
        integer creeps = 0
    endglobals

    private function Creeps takes nothing returns nothing
        local integer c = 0
       
        loop
            exitwhen c > 19
            set c = c + 1
            call CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE), ChooseRandomCreep(GetRandomInt(1,10)),0,0,GetRandomReal(0,360))
            set creeps = creeps + 1
        endloop
    endfunction

    private function Alliance takes nothing returns nothing
        local integer p1 = 0
        local integer p2 = 0
       
        loop
            exitwhen p1 > 3
            loop
                exitwhen p2 > 3
                call SetPlayerAllianceStateAllyBJ(Player(p1),Player(p2),true)
                set p2 = p2 + 1
            endloop
            set p2 = 0
            set p1 = p1 + 1
        endloop
    endfunction
   
    private function Barracks takes nothing returns nothing
        local integer p = 0
        local real a = 0
        local location s = GetRectCenter(GetPlayableMapRect())
        local location l
        local unit b
       
        loop
            exitwhen p > 3
            set l = PolarProjectionBJ(s,3000,a)
            set b = CreateUnitAtLoc(Player(p),'hbar',l,bj_UNIT_FACING)
            call SaveUnitHandle(hash,0,GetHandleId(Player(p)),b)
            set a = a + 90
            set p = p + 1
        endloop
       
        call RemoveLocation(l)
        call RemoveLocation(s)
        set b = null
    endfunction
   
    private function CreepCount takes nothing returns boolean
        if creeps > 0 then
            return true
        endif
        return false
    endfunction

    private function Spawn takes nothing returns nothing
        local integer p = 0
        local integer r = 0
        local real x
        local real y
        local unit b
        local unit u
       
        loop
            exitwhen p > 3
            set b = LoadUnitHandle(hash,0,GetHandleId(Player(p)))
            set x = GetUnitX(b)
            set y = GetUnitY(b)
            set r = GetRandomInt(0,1)
            if IsUnitAliveBJ(b) then
                if r > 0 then
                    set u = CreateUnit(Player(p),'hfoo',x,y,bj_UNIT_FACING)
                else
                    set u = CreateUnit(Player(p),'hrif',x,y,bj_UNIT_FACING)
                endif
                call IssuePointOrder(u,"attack",0,0)
            endif
            set p = p + 1
        endloop
       
        set b = null
        set u = null
    endfunction

    private function Owner takes nothing returns boolean
        if (GetOwningPlayer(GetTriggerUnit()) == Player(PLAYER_NEUTRAL_AGGRESSIVE) and IsUnitType(GetTriggerUnit(),UNIT_TYPE_SUMMONED) == false) then
            return true
        endif
        return false
    endfunction

    private function Type takes nothing returns boolean
        return IsUnitType(GetEnumUnit(),UNIT_TYPE_STRUCTURE) == false
    endfunction
   
    private function Kill takes nothing returns nothing
        call ExplodeUnitBJ(GetEnumUnit())
    endfunction

    private function Death takes nothing returns nothing
        local group g
       
        set creeps = creeps - 1
        if creeps == 0 then
            set g = GetUnitsInRectMatching(GetPlayableMapRect(), Condition(function Type))
            call ForGroup(g,function Kill)
            call DisplayTextToForce(GetPlayersAll(),"You won!")
        endif
       
        call DestroyGroup(g)
    endfunction

    private function Init takes nothing returns nothing
        local trigger trg = CreateTrigger()
        call TriggerRegisterTimerEvent(trg, 0.2, false)
        call TriggerAddAction(trg, function Creeps)
        call TriggerAddAction(trg, function Alliance)
        call TriggerAddAction(trg, function Barracks)
       
        set trg = CreateTrigger()
        call TriggerRegisterTimerEvent(trg,2.5,true)
        call TriggerAddCondition(trg, Condition(function CreepCount))
        call TriggerAddAction(trg, function Spawn)
       
        set trg = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(trg,EVENT_PLAYER_UNIT_DEATH)
        call TriggerAddCondition(trg, Condition(function Owner))
        call TriggerAddAction(trg,function Death)
       
        set trg = null
    endfunction

endscope
 

Attachments

  • JASS Class - Spawn.w3x
    25.7 KB · Views: 54

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
The Bj TriggerRegisterAnyUnitEventBJ loops through all players using player events. If you just use the native to detect the death event only for player neutrla hostile, your code would be a bit more efficient.
In general you are using a lot of BJs that could easily replaced.

Your function CreepCount can be done in one line. No need for an if: return creeps > 0

In the Creeps function you both increment c and creeps. Using creeps for the loop would make the function slightly faster.

In your Alliance function you will make player allied with itself. I don't know if this has any consequences. I just wanted to mention it.
 
You could use one shot timers instead of using triggers to run a function; a timer is more leight weight, and can be always used in JASS for such things.
Triggers I believe make only sense as event listeners, or for dynamic code registration. Just as tip, because this timer-trigger thinking is pretty GUI-ish. : )

Have you read the crash course? -- I mean where the differences between array and hashtables are; you're not 'really' using the hashtable power at the moment, and could just use an array variable for the barracks.

hm...
 
vJASS:
scope Spawn initializer Init

    globals
        private group creeps = CreateGroup()
        private group bases = CreateGroup()
        private integer bcount = 4
        private integer ccount = 20
    endglobals

    private function Setup takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer c = 0
        local integer p = 0
        local real a = 0
        local real x
        local real y
        local unit u
      
        loop
            exitwhen c > 19
            set u = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE),ChooseRandomCreep(GetRandomInt(1,10)),0,0,GetRandomReal(0,360))
            call GroupAddUnit(creeps,u)
            if c < 4 then
                loop
                    exitwhen p > 4
                    call SetPlayerAllianceStateBJ(Player(p),Player(c),bj_ALLIANCE_ALLIED)
                    set p = p +1
                endloop
                set x = 0 + 3000 * Cos(a * bj_DEGTORAD)
                set y = 0 + 3000 * Sin(a * bj_DEGTORAD)
                set u = CreateUnit(Player(c),'hbar',x,y,bj_UNIT_FACING)
                call GroupAddUnit(bases,u)
                set a = a + 90
                set p = 0
            endif
            set c = c + 1
        endloop
      
        call DestroyTimer(t)
        set u = null
        set t = null
    endfunction

    private function Spawn takes nothing returns nothing
        local unit u
        local unit b = GetEnumUnit()
        local real x = GetUnitX(b)
        local real y = GetUnitY(b)
        local player p = GetOwningPlayer(b)
        local integer i = GetRandomInt(0,1)
      
        if GetWidgetLife(b) > 0.405 then
            if i == 0 then
                set u = CreateUnit(p,'hfoo',x,y,bj_UNIT_FACING)
            else
                set u = CreateUnit(p,'hrif',x,y,bj_UNIT_FACING)
            endif
            call IssuePointOrder(u,"attack",0,0)
        else
            call GroupRemoveUnit(bases,b)
            set bcount = bcount - 1
        endif
      
        set u = null
        set b = null
        set p = null
    endfunction

    private function Bases takes nothing returns nothing
        local timer t = GetExpiredTimer()
      
        if bcount > 0 then
            call ForGroup(bases,function Spawn)
        else
            call PauseTimer(t)
            call DestroyTimer(t)
        endif
      
        set t = null
    endfunction
  
    private function Explode takes nothing returns nothing
        local unit u = GetEnumUnit()
      
        call SetUnitExploded(u,true)
        call KillUnit(u)
      
        set u = null
    endfunction
  
    private function Victory takes nothing returns nothing
        local group g = CreateGroup()
      
        call GroupEnumUnitsInRect(g,bj_mapInitialPlayableArea,null)
        call ForGroup(g,function Explode)
        call DisplayTextToForce(GetPlayersAll(),"You Won!")
    endfunction
  
    private function CreepDeath takes nothing returns nothing
        local unit u = GetTriggerUnit()
      
        if IsUnitInGroup(u,creeps) then
            call GroupRemoveUnit(creeps,u)
            set ccount = ccount - 1
            if ccount == 0 then
                call Victory()
            endif
        endif
      
        set u = null
    endfunction

    private function Init takes nothing returns nothing
        local timer t = CreateTimer()
        local timer p = CreateTimer()
        local trigger trg = CreateTrigger()
      
        call TriggerRegisterPlayerUnitEvent(trg,Player(PLAYER_NEUTRAL_AGGRESSIVE),EVENT_PLAYER_UNIT_DEATH,null)
        call TriggerAddAction(trg,function CreepDeath)
      
        call TimerStart(t,0.2,false,function Setup)
        call TimerStart(p,2.5,true,function Bases)
    endfunction

endscope
 

Attachments

  • JASS Class - Spawn.w3x
    25.6 KB · Views: 54
Last edited:
Can't test right now, but from code it seems barracks form a diamond form.

When an agent like a timer might be destroyed later, like in an other function, you still always need to null it in the end.
Things that you can always access/can be potentialy always used (that you don't want/need destroy), don't need to be nulled.

Your winning conditions is a bit risky because units might spawn new enemy units with abilities, or so; and the winning condition tells to win exactly then at the moment no enemy is alive anymore.

Footmen and rifle shooters only should be exploded.

local group isnt removed.
 
Status
Not open for further replies.
Top