• 🏆 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!

Order tracking, Wanderer, Unit Spawn - Submissions

Status
Not open for further replies.
Level 12
Joined
Jun 15, 2016
Messages
472
These are my solutions to universal missions 1-3.


JASS:
function Trig_Order_Tracking_Actions takes nothing returns nothing
   local string order = OrderId2String(GetIssuedOrderId())
   local string orunit = GetUnitName(GetOrderedUnit())
   local widget target = GetOrderTarget()
   local string sr = orunit + " - " + order
   
   if GetOrderTarget() != null then
       call PingMinimap(GetWidgetX(target), GetWidgetY(target), 2.0)
   endif
   
   call BJDebugMsg(sr)
endfunction

//===========================================================================
function InitTrig_Order_Tracking takes nothing returns nothing
    set gg_trg_Order_Tracking = CreateTrigger(  )
   
   // Initialize some units for the test
   call CreateUnit(Player(0), 'hpea', 100.0, 100.0, 0.0)
   call CreateUnit(Player(0), 'Hjai', 110.0, 120.0, 0.0)
   call CreateUnit(Player(0), 'Hmbr', 120.0, 110.0, 0.0)
   call CreateUnit(Player(1), 'hpea', 1000.0, 1000.0, 0.0)
   
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Order_Tracking, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Order_Tracking, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Order_Tracking, EVENT_PLAYER_UNIT_ISSUED_ORDER )
    call TriggerAddAction( gg_trg_Order_Tracking, function Trig_Order_Tracking_Actions )
endfunction



JASS:
function GryphonAtGoal takes unit u, integer th returns boolean
    local real target_x = LoadReal(udg_Hash,th,1)
    local real target_y = LoadReal(udg_Hash,th,2)
    local real distance_x = target_x - GetUnitX(u)
    local real distance_y = target_y - GetUnitY(u)
    local integer terrain_type = LoadInteger(udg_Hash,th,3)
   
   if (distance_x < 50.0 and distance_x > -50.0) and (distance_y < 50.0 and distance_y > -50.0) then
       call SetTerrainType(target_x,target_y,terrain_type,-1, 1, 0)
       return true
   endif
   
   return false
endfunction

function SetNewTarget takes unit u, integer th returns nothing
   local location original_loc = GetUnitLoc(u)
    local location new_loc
    local real new_x
    local real new_y
   
   // Check if the new location is inside the playable map bounds
   loop
       set new_loc = PolarProjectionBJ(original_loc,GetRandomReal(500,1500),GetRandomReal(0,360))
       exitwhen RectContainsLoc(bj_mapInitialPlayableArea, new_loc)
   endloop
    set new_x = GetLocationX(new_loc)
   set new_y = GetLocationY(new_loc)
   
   call SaveReal(udg_Hash,th,1,new_x)
   call SaveReal(udg_Hash,th,2,new_y)
   call SaveInteger(udg_Hash,th,3,GetTerrainType(new_x,new_y))
   
   call IssuePointOrder(u,"smart",new_x,new_y)
   call SetTerrainType(new_x,new_y,'Nsnw',-1, 1, 0)
   
   call RemoveLocation(original_loc)
   call RemoveLocation(new_loc)
   set original_loc = null
   set new_loc = null
endfunction

function GryphonTimeout takes nothing returns nothing
    local integer timer_handle = GetHandleId(GetExpiredTimer())
    local unit gryphon = LoadUnitHandle(udg_Hash,timer_handle,0)
   
    if GryphonAtGoal(gryphon,timer_handle) then
        call SetNewTarget(gryphon,timer_handle)
    endif
endfunction

function Trig_Wanderer_gryphon_Timer_Actions takes nothing returns nothing
    local timer gryphon_timer = CreateTimer()
    local unit gryphon = CreateUnit(Player(0),'hgry',0,0,0)
    local integer timer_handle = GetHandleId(gryphon_timer)
   
    call SaveUnitHandle(udg_Hash, timer_handle, 0, gryphon)
    call SaveReal(udg_Hash, timer_handle,1,0) // save target x
    call SaveReal(udg_Hash, timer_handle,2,0) // save target y
   
    call TimerStart(gryphon_timer,0.5,true,function GryphonTimeout)
endfunction

//===========================================================================
function InitTrig_Wanderer_gryphon_timer takes nothing returns nothing
   set gg_trg_Wanderer_gryphon_timer = CreateTrigger(  )
   set udg_Hash = InitHashtable()
   call TriggerRegisterPlayerEventEndCinematic( gg_trg_Wanderer_gryphon_timer, Player(0) )
    call TriggerAddAction( gg_trg_Wanderer_gryphon_timer, function Trig_Wanderer_gryphon_Timer_Actions )
endfunction


Just a note about this mission: Perhaps it should include a note to make sure that the gryphon's target is inside the playable map area. Not that big a deal, but still worth the few extra words.

I also made implemented mission 2 with waits just for fun.


JASS:
function CheckDistanceWaits takes unit u returns boolean
   local real desx = LoadReal(udg_Hash,GetHandleId(u),1)
   local real desy = LoadReal(udg_Hash,GetHandleId(u),2)
   local integer dest = LoadInteger(udg_Hash,GetHandleId(u),3)
   local real dix = desx - GetUnitX(u)
   local real diy = desy - GetUnitY(u)

   if (dix < 50.0 and dix > -50.0) and (diy < 50.0 and diy > -50.0) then
       call SetTerrainType(desx,desy,dest,-1, 1, 0)
       return true
   endif
   
   return false
endfunction

function UnitWaitDestinationWaits takes unit u returns nothing
   //call BJDebugMsg("Starting loop, waiting for unit to arrive at target")
   
   loop
       exitwhen CheckDistanceWaits(u)
       
       call TriggerSleepAction(0.25)
   endloop
   
   //call BJDebugMsg("unit at target")
   
endfunction

function SetUnitTargetWaits takes unit u returns nothing
   local location ol = GetUnitLoc(u)
   local location nl
   local real nx
   local real ny
   
   // Check if the new location is inside the playable map bounds
   loop
       set nl = PolarProjectionBJ(ol,GetRandomReal(500,1500),GetRandomReal(0,360))
       exitwhen RectContainsLoc(bj_mapInitialPlayableArea, nl)
   endloop
   set nx = GetLocationX(nl)
   set ny = GetLocationY(nl)
   
   call SaveReal(udg_Hash,GetHandleId(u),1,nx)
   call SaveReal(udg_Hash,GetHandleId(u),2,ny)
   call SaveInteger(udg_Hash,GetHandleId(u),3,GetTerrainType(nx,ny))
   
   call IssuePointOrder(u,"smart",nx,ny)
   call SetTerrainType(nx,ny,'Nsnw',-1, 1, 0)
   
   call RemoveLocation(ol)
   call RemoveLocation(nl)
   set ol = null
   set nl = null
endfunction

function Trig_Wanderer_gryphon_Waits_Actions takes nothing returns nothing
   local unit gry = CreateUnit(Player(0),'hgry',0,0,0)
   
   loop
       exitwhen GetUnitState(gry, UNIT_STATE_LIFE) <= 0
       call SetUnitTargetWaits(gry)
       call UnitWaitDestinationWaits(gry)
   endloop
   
   call BJDebugMsg("Gryphon is dead :<")
   set gry = null
endfunction

//===========================================================================
function InitTrig_Wanderer_gryphon_waits takes nothing returns nothing
   set gg_trg_Wanderer_gryphon_waits = CreateTrigger(  )
   set udg_Hash = InitHashtable()
   call TriggerRegisterPlayerEventEndCinematic( gg_trg_Wanderer_gryphon_waits, Player(0) )
    call TriggerAddAction( gg_trg_Wanderer_gryphon_waits, function Trig_Wanderer_gryphon_Waits_Actions )
endfunction



JASS:
function UnitIsAlive takes nothing returns boolean
   return (GetUnitState(GetEnumUnit(),UNIT_STATE_LIFE) <= 0)
endfunction

function BlastOff takes nothing returns nothing
   local unit u = GetEnumUnit()
   if GetUnitTypeId(u) != 'hbar' then
       call ExplodeUnitBJ(u)
   endif
endfunction

function ThisIsTheEnd takes nothing returns nothing
   local integer index = 0
   local group PlayerUnits = CreateGroup()
   
   call BJDebugMsg("YOU WON!!!")
   loop
       exitwhen index >= 4
       
       call GroupEnumUnitsOfPlayer(PlayerUnits,Player(index),Condition(function UnitIsAlive))
       call ForGroup(PlayerUnits, function BlastOff)
       
       set index = index + 1
   endloop
endfunction

function CreepIsAlive takes nothing returns nothing
   local unit u = GetEnumUnit()
   local group g = LoadGroupHandle(udg_Hash,12,1)
   
   if GetUnitState(u,UNIT_STATE_LIFE) <= 0 then
       call GroupRemoveUnit(g,u)
   endif
endfunction

function GetCreepAmount takes nothing returns integer
   local group g = LoadGroupHandle(udg_Hash,12,1)
   
   call ForGroup(g,function CreepIsAlive)
   
   return CountUnitsInGroup(g)
endfunction

function SpawnUnits takes nothing returns nothing
   local integer index = 0
   local unit barracks
   local unit spawn
   local real x
   local real y
   local integer stype
   local timer t = GetExpiredTimer()
   
   if GetCreepAmount() < 1 then
       call DestroyTimer(t)
       set index = 100
       call ThisIsTheEnd()
   endif
   
   loop
       exitwhen index >= 4
       
       set barracks = LoadUnitHandle(udg_Hash,index,1)
       set x = GetUnitX(barracks)
       set y = GetUnitY(barracks)
       set stype = GetRandomInt(1,2)
       
       if stype == 1 then
           set spawn = CreateUnit(Player(index),'hfoo',x,y,0)
       else
           set spawn = CreateUnit(Player(index),'hrif',x,y,0)
       endif
       
       call IssuePointOrder(spawn,"attack",0,0)
       
       set index = index + 1
   endloop
endfunction

function Trig_Spawn_unit_Actions takes nothing returns nothing
   local integer index = 0
   local integer level
   local location Source = Location(0,0)
   local location loc
   local timer SpawnTimer = CreateTimer()
   local group CreepGroup = CreateGroup()
   local unit u
   set udg_Hash = InitHashtable()
   
   loop
       exitwhen index >= 21
       
       set level = GetRandomInt(1,10)
       set u = CreateUnit(Player(12),ChooseRandomCreep(level),0,0,0)
       call GroupAddUnit(CreepGroup,u)
       
       set index = index + 1
   endloop
   
   call SaveGroupHandle(udg_Hash,12,1,CreepGroup)
   set index = 0
   
   loop
       exitwhen index >= 4
       set loc = PolarProjectionBJ(Source,3000.0,(90.0*index))
       
       set u = CreateUnit(Player(index),'hbar',GetLocationX(loc),GetLocationY(loc),270.0)
       call SaveUnitHandle(udg_Hash,index,1,u)
       
       call RemoveLocation(loc)
       set index = index + 1
   endloop
   
   call RemoveLocation(Source)
   call TimerStart(SpawnTimer,2.5,true,function SpawnUnits)
endfunction

//===========================================================================
function InitTrig_Spawn_unit takes nothing returns nothing
    set gg_trg_Spawn_unit = CreateTrigger(  )
   set udg_Hash = InitHashtable()
    call TriggerAddAction( gg_trg_Spawn_unit, function Trig_Spawn_unit_Actions )
endfunction


P.S.: Do I need to post a test map of all that? Cause all the missions so far are on the same map...
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
It would nice to have a test map, so we can test it ourself. You should upload one test map per mission.

===========================================

Mission 1:
You are missing the part "print the unit's name and the issued order id on screen.", so you need to print both order id and the string.
There is also another native, that can print the name of the order for train/build/upgrade and research orders: GetObjectName

Mission 2:
Apparently for this mission you don't have to check if the target is inside the playable map area. (I asked the same here:Mission Solved - Wanderer - Submission)

You should null local agents.

SetNewTarget:
I would prefer, if you would use coordinates instead of locations and avoid BJs. Being able to use coordinates is one of the big advantages of JASS over GUI, you should use it if you can. You can take a look at the function PolarProjectionBJ if you don't know the trigonometric functions to calculate it.

This would also allow you to use 2*pi instead 360°, but that's only a very small optimization.

Mission 3:
I guess you have ticked "runs on map initialization" in the trigger editor, otherwise that would not do anything. You could also call the function from the init function. No preplaced units means, that you are not allowed to use the map editor to place units there.

CountUnitsInGroup iterates through the group. Together with call ForGroup(g,function CreepIsAlive) these are two group iterations. You can count the units in CreepIsAlive as well.
The general points I mentioned for mission 2 apply here is well (null local agents, avoid locations and BJs).

Especially for mission 3 I need a test map, so I can see if everything works.
 
Last edited:
Level 12
Joined
Jun 15, 2016
Messages
472
Mission 1:
You are missing the part "print the unit's name and the issued order id on screen.", so you need to print both order id and the string.
There is also another native, that can print the name of the order for train/build/upgrade and research orders: GetObjectName

By using this line local string sr = orunit + " - " + order I'm printing the unit and the order, no?
As to GetObjectName, in case the order is a training/research/build order it should replace the order string (not) received from OrderId2String(GetIssuedOrderId())

Mission 2:
Apparently for this mission you don't have to check if the target is inside the playable map area. (I asked the same here:Mission Solved - Wanderer - Submission)

You should null local agents.

SetNewTarget:
I would prefer, if you would use coordinates instead of locations and avoid BJs. Being able to use coordinates is one of the big advantages of JASS over GUI, you should use it if you can. You can take a look at the function PolarProjectionBJ if you don't know the trigonometric functions to calculate it.

This would also allow you to use 2*pi instead 360°, but that's only a very small optimization.

Fair enough. I think checking the target location to be reachable is a more "correct" way of doing things.
As to the BJs PolarProjectionBJ and RectContainsLoc, internally they are leakless and save up a lot of writing at the trade-off of 2 extra function calls each. Is there any other reason not to use them except for the red highlighting in WEX?

Mission 3:
I guess you have ticked "runs on map initialization" in the trigger editor, otherwise that would not do anything. You could also call the function from the init function. No preplaced units means, that you are not allowed to use the map editor to place units there.

CountUnitsInGroup iterates through the group. Together with call ForGroup(g,function CreepIsAlive) these are two group iterations. You can count the units in CreepIsAlive as well.
The general points I mentioned for mission 2 apply here is well (null local agents, avoid locations and BJs).

Yup, runs on map init. Is it less preferable to use this option? I thought about the double iteration because of a basic aversion from global variables (not sure why though...), yeah it's better to run once.

Alright, individual test maps will be set and stuff will be fixed in the following days. Just one more question concerning mission 4:
How taxing is it to save and load values from a hashtable, when compared to other simple operations? I found myself using hashing quite a bit.
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
The mission wants you to print: unit name + order string + order id. You need the string and the id of the order.

Fair enough. I think checking the target location to be reachable is a more "correct" way of doing things.
It's not required, but even better if you have it.

For BJs you always have to decide for yourself, if you want to replace them. If it's just a swap function or something else that only calls one native you should always replace it, but as soon as a function consists of 2 or more other functions it can be worth to use it. If you are coding performance critical code sections (for example periodic trigger + unit group / loop) you should not have any BJ.
In this case the main thing is, that you should use coordinates. If you take a look at PolarProjectionBJ, it only uses the coordinates of the location, so why even create a location, if you can use the coordinates directly?

Yup, runs on map init. Is it less preferable to use this option? I thought about the double iteration because of a basic aversion from global variables (not sure why though...), yeah it's better to run once.
It's just, that you can't see this option in the trigger. If you use "run at map initialization" it runs after all triggers have been initialized. if you put it directly in the initialization, you don't know which triggers have already been initialized, so you need to keep that in mind.
How taxing is it to save and load values from a hashtable, when compared to other simple operations? I found myself using hashing quite a bit.
Loading/Storing in hashtables is slower than getting/setting variables, so using arrays should be faster. I think it's not a big difference and hashtables are very useful, so you should definitely use them. You can attach data to any type (unit, timer, group, unit type, buff type,...) without the need of tons of array variables and an indexing system (unit indexer for example).
 
Level 12
Joined
Jun 15, 2016
Messages
472
Mission one including everything. Missions 2 & 3 will be added later (when I'm not lazy). By the way, when units are spawned they receive an order with the ID 851970, named "defaultstring", any idea whether that's supposed to happen? (it's not in the orders repo)


JASS:
function Trig_Order_Tracking_Actions takes nothing returns nothing
    local integer order = GetIssuedOrderId()
    local string order_string = OrderId2String(order)
    local string ordered_unit = GetUnitName(GetOrderedUnit())
    local widget target = GetOrderTarget()
    local string message_string = ""
  
    if order_string == null then
        set order_string = GetObjectName(order)
    endif
  
    if target != null then
        call PingMinimap(GetWidgetX(target), GetWidgetY(target), 2.0)
    endif
  
    set message_string = ordered_unit + " - " + order_string + "(" + I2S(order) + ")"
  
    call BJDebugMsg(message_string)
endfunction

//===========================================================================
function InitTrig_Order_Tracking takes nothing returns nothing
    set gg_trg_Order_Tracking = CreateTrigger(  )
  
    // Some settings
    call CreateFogModifierRectBJ( true, Player(0), FOG_OF_WAR_VISIBLE, GetPlayableMapRect() )
    call SetPlayerState(Player(0),PLAYER_STATE_RESOURCE_GOLD,15000)
    call SetPlayerState(Player(0),PLAYER_STATE_RESOURCE_LUMBER,15000)
  
    // Initialize some units for the test
    call CreateUnit(Player(0), 'hpea', 100.0, 100.0, 0.0)
    call CreateUnit(Player(0), 'Hjai', 110.0, 120.0, 0.0)
    call CreateUnit(Player(0), 'Hmbr', 120.0, 110.0, 0.0)
    call CreateUnit(Player(1), 'hpea', 1000.0, 1000.0, 0.0)
  
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Order_Tracking, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Order_Tracking, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Order_Tracking, EVENT_PLAYER_UNIT_ISSUED_ORDER )
    call TriggerAddAction( gg_trg_Order_Tracking, function Trig_Order_Tracking_Actions )
endfunction


Not as lazy as I thought... Here is mission 2. The code in the test map is slightly different from the code here, the posted version is the right one. (I did minor changes to prevent a bug where gryphons don't start wandering when spawning multiple gryphons at the same time)


JASS:
function GryphonAtGoal takes unit u, integer th returns boolean
    local real target_x = LoadReal(udg_Hash,th,1)
    local real target_y = LoadReal(udg_Hash,th,2)
    local real distance_x = target_x - GetUnitX(u)
    local real distance_y = target_y - GetUnitY(u)
    local integer terrain_type = LoadInteger(udg_Hash,th,3)
   
   if (distance_x < 50.0 and distance_x > -50.0) and (distance_y < 50.0 and distance_y > -50.0) then
       call SetTerrainType(target_x,target_y,terrain_type,-1, 1, 0)
       return true
   endif
   
   return false
endfunction

function SetNewTarget takes unit u, integer th returns nothing
   local location original_loc = GetUnitLoc(u)
    local location new_loc
    local real new_x
    local real new_y
   
   // Check if the new location is inside the playable map bounds
   loop
       set new_loc = PolarProjectionBJ(original_loc,GetRandomReal(500,1500),GetRandomReal(0,360))
       exitwhen RectContainsLoc(bj_mapInitialPlayableArea, new_loc)
   endloop
    set new_x = GetLocationX(new_loc)
   set new_y = GetLocationY(new_loc)
   
   call SaveReal(udg_Hash,th,1,new_x)
   call SaveReal(udg_Hash,th,2,new_y)
   call SaveInteger(udg_Hash,th,3,GetTerrainType(new_x,new_y))
   
   call IssuePointOrder(u,"smart",new_x,new_y)
   call SetTerrainType(new_x,new_y,'Nsnw',-1, 1, 0)
   
   call RemoveLocation(original_loc)
   call RemoveLocation(new_loc)
   set original_loc = null
   set new_loc = null
endfunction

function GryphonTimeout takes nothing returns nothing
    local integer timer_handle = GetHandleId(GetExpiredTimer())
    local unit gryphon = LoadUnitHandle(udg_Hash,timer_handle,0)
   
    if GryphonAtGoal(gryphon,timer_handle) then
        call SetNewTarget(gryphon,timer_handle)
    endif
endfunction

function Trig_Wanderer_gryphon_Timer_Actions takes nothing returns nothing
    local timer gryphon_timer = CreateTimer()
    local unit gryphon = CreateUnit(Player(0),'hgry',0,0,0)
    local integer timer_handle = GetHandleId(gryphon_timer)
   
    call SaveUnitHandle(udg_Hash, timer_handle, 0, gryphon)

    call SetNewTarget(gryphon,timer_handle)
    call TimerStart(gryphon_timer,0.5,true,function GryphonTimeout)
   
    set gryphon = null
    set gryphon_timer = null
endfunction

//===========================================================================
function InitTrig_Wanderer_gryphon_timer takes nothing returns nothing
   set gg_trg_Wanderer_gryphon_timer = CreateTrigger(  )
   set udg_Hash = InitHashtable()
   call TriggerRegisterPlayerEventEndCinematic( gg_trg_Wanderer_gryphon_timer, Player(0) )
    call TriggerAddAction( gg_trg_Wanderer_gryphon_timer, function Trig_Wanderer_gryphon_Timer_Actions )
endfunction
 

Attachments

  • JASS class 1 - for upload.w3m
    16.7 KB · Views: 60
  • JASS class 2 - for upload.w3m
    17 KB · Views: 71
Last edited:

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
I guess it is normal, because there is nothing in your map that could cause any weird behaviour. There is also "dafault string", if you move items in your inventory or use them.
I find it really weird though, that dropping items on the ground or giving them to other units are no orders at all.

You should null target at the end of the function: set target = null

You solved the first mission.
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
In the GryphonTimeout function you forgot to null gryphon. Unfortunately we have to null all agenst manually.
I would use a faster periodic timer. With 0.5 seconds the gryphon sometimes stood still for a noticeable duration.

You solved the second mission.
 
Level 12
Joined
Jun 15, 2016
Messages
472
Mission 3 solution including test map.


JASS:
function UnitIsAlive takes nothing returns boolean
    return (GetUnitState(GetEnumUnit(),UNIT_STATE_LIFE) <= 0)
endfunction

function BlastOff takes nothing returns nothing
    local unit u = GetEnumUnit()
    if GetUnitTypeId(u) != 'hbar' then
        call ExplodeUnitBJ(u)
    endif
   
    set u = null
endfunction

function ThisIsTheEnd takes nothing returns nothing
    local integer index = 0
    local group PlayerUnits = CreateGroup()
   
    call BJDebugMsg("YOU WON!!!")
    loop
        exitwhen index >= 4
       
        call GroupEnumUnitsOfPlayer(PlayerUnits,Player(index),Condition(function UnitIsAlive))
        call ForGroup(PlayerUnits, function BlastOff)
       
        set index = index + 1
    endloop
   
    call FlushParentHashtable(udg_Hash)
    call DestroyGroup(PlayerUnits)
    set PlayerUnits = null
endfunction

function CreepIsAlive takes nothing returns nothing
    local unit u = GetEnumUnit()
    local group g = LoadGroupHandle(udg_Hash,12,1)
   
    if GetUnitState(u,UNIT_STATE_LIFE) <= 0 then
        call GroupRemoveUnit(g,u)
    else
        call SaveInteger(udg_Hash,12,2,(LoadInteger(udg_Hash,12,2) + 1))
    endif
   
    set u = null
    set g = null
endfunction

function GetCreepAmount takes nothing returns integer
    local group g = LoadGroupHandle(udg_Hash,12,1)
   
    call SaveInteger(udg_Hash,12,2,0)
    call ForGroup(g,function CreepIsAlive)
   
    set g = null
    return LoadInteger(udg_Hash,12,2)
endfunction

function SpawnUnits takes nothing returns nothing
    local integer index = 0
    local unit barracks
    local unit spawn
    local real x
    local real y
    local integer stype
    local timer t = GetExpiredTimer()
   
    if GetCreepAmount() < 1 then
        call DestroyTimer(t)
        set index = 100
        call ThisIsTheEnd()
    endif
   
    loop
        exitwhen index >= 4
       
        set barracks = LoadUnitHandle(udg_Hash,index,1)
        set x = GetUnitX(barracks)
        set y = GetUnitY(barracks)
        set stype = GetRandomInt(1,2)
       
        if stype == 1 then
            set spawn = CreateUnit(Player(index),'hfoo',x,y,0)
        else
            set spawn = CreateUnit(Player(index),'hrif',x,y,0)
        endif
       
        call IssuePointOrder(spawn,"attack",0,0)
       
        set index = index + 1
    endloop
endfunction

function Trig_Spawn_unit_Actions takes nothing returns nothing
    local integer index = 0
    local integer level
    local location Source = Location(0,0)
    local location loc
    local timer SpawnTimer = CreateTimer()
    local group CreepGroup = CreateGroup()
    local unit u
    set udg_Hash = InitHashtable()
   
    loop
        exitwhen index >= 21
       
        set level = GetRandomInt(1,10)
        set u = CreateUnit(Player(12),ChooseRandomCreep(level),0,0,0)
        call GroupAddUnit(CreepGroup,u)
       
        set index = index + 1
    endloop
   
    call SaveGroupHandle(udg_Hash,12,1,CreepGroup)
    set index = 0
   
    loop
        exitwhen index >= 4
        set loc = PolarProjectionBJ(Source,3000.0,(90.0*index))
       
        set u = CreateUnit(Player(index),'hbar',GetLocationX(loc),GetLocationY(loc),270.0)
        call SaveUnitHandle(udg_Hash,index,1,u)
       
        call RemoveLocation(loc)
        set index = index + 1
    endloop
   
    call RemoveLocation(Source)
    call TimerStart(SpawnTimer,2.5,true,function SpawnUnits)
endfunction

//===========================================================================
function InitTrig_Spawn_unit takes nothing returns nothing
    set gg_trg_Spawn_unit = CreateTrigger(  )
    set udg_Hash = InitHashtable()
    call CreateFogModifierRectBJ( true, Player(0), FOG_OF_WAR_VISIBLE, GetPlayableMapRect())
    call Trig_Spawn_unit_Actions()
endfunction


Gotta null em all
 

Attachments

  • JASS class 3 - for upload.w3m
    17.5 KB · Views: 55

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
You are not the first one to make this mistake:
Mission Solved - Unit Spawn - Submission
https://www.hiveworkshop.com/threads/unit-spawn-submission.293798/#post-3161199
From the mission description: "Player 1-4 must be set as allies."

Instead of using ChooseRandomCreep(level), you can use ChooseRandomCreep(-1) it is easier and has a better random distribution (imo).
There is an easier solution:
ChooseRandomCreep(-1)

Using -1 as parameter will choose any level (it will not choose a level that does not exist). It will also change the random distribution I assume. It probably will give every unit the same chance, whereas yours would give every level the same chance, so if there is only 1 level 10 creep and 100 level 1 creeps, the specific level 10 creep will have a much higher chance than a specific level 1 creep.
That's not something you need to change, but it's good to know, that -1 also works. If you look at the GUI equivalent it is explained there, but when only using JASS there is unfortunately no way to know this.

A unit is actually considered dead, if hp <= 0.405.

I think you missed this part: "Each 2.5 seconds a footman, or a rifleman (randomly) must be created at each living base and receive an attack order towards the enemy location (0/0).
In case the base is dead/destroyed, the periodic creation must not continue for this certain base."
 
Level 12
Joined
Jun 15, 2016
Messages
472
Changes to mission 3 have been made accordingly.


JASS:
native UnitAlive takes unit u returns boolean

function BlastOff takes nothing returns nothing
    local unit u = GetEnumUnit()
    if GetUnitTypeId(u) != 'hbar' and UnitAlive(u) then
        call ExplodeUnitBJ(u)
    endif
   
    set u = null
endfunction

function ThisIsTheEnd takes nothing returns nothing
    local integer index = 0
    local group PlayerUnits = CreateGroup()
   
    call BJDebugMsg("YOU WON!!!")
    loop
        exitwhen index >= 4
       
        call GroupEnumUnitsOfPlayer(PlayerUnits,Player(index),null)
        call ForGroup(PlayerUnits, function BlastOff)
       
        set index = index + 1
    endloop
   
    call FlushParentHashtable(udg_Hash)
    call DestroyGroup(PlayerUnits)
    set PlayerUnits = null
endfunction

//===========================================================================

function CreepIsAlive takes nothing returns nothing
    local unit u = GetEnumUnit()
    local group g = LoadGroupHandle(udg_Hash,12,1)
   
    if not UnitAlive(u) then
        call GroupRemoveUnit(g,u)
    else
        call SaveInteger(udg_Hash,12,2,(LoadInteger(udg_Hash,12,2) + 1))
    endif
   
    set u = null
    set g = null
endfunction

function GetCreepAmount takes nothing returns integer
    local group g = LoadGroupHandle(udg_Hash,12,1)
   
    call SaveInteger(udg_Hash,12,2,0)
    call ForGroup(g,function CreepIsAlive)
   
    set g = null
    return LoadInteger(udg_Hash,12,2)
endfunction

function SpawnUnits takes nothing returns nothing
    local integer index = 0
    local unit barracks
    local unit spawn
    local real x
    local real y
    local integer stype
    local timer t = GetExpiredTimer()
   
    if GetCreepAmount() < 1 then
        call DestroyTimer(t)
        set index = 100
        call ThisIsTheEnd()
    endif
   
    loop
        exitwhen index >= 4
       
        set barracks = LoadUnitHandle(udg_Hash,index,1)
       
        if barracks != null and UnitAlive(barracks) then
            set x = GetUnitX(barracks)
            set y = GetUnitY(barracks)
            set stype = GetRandomInt(1,2)
       
            if stype == 1 then
                set spawn = CreateUnit(Player(index),'hfoo',x,y,0)
            else
                set spawn = CreateUnit(Player(index),'hrif',x,y,0)
            endif
       
            call IssuePointOrder(spawn,"attack",0,0)
        endif
       
        set index = index + 1
    endloop
   
    set t = null
    set barracks = null
    set spawn = null
endfunction

function Trig_Spawn_unit_Actions takes nothing returns nothing
    local integer index = 0
    local location Source = Location(0,0)
    local location loc
    local timer SpawnTimer = CreateTimer()
    local group CreepGroup = CreateGroup()
    local unit u
    set udg_Hash = InitHashtable()
   
    loop
        exitwhen index >= 21
       
        set u = CreateUnit(Player(12),ChooseRandomCreep(-1),0,0,0)
        call GroupAddUnit(CreepGroup,u)
       
        set index = index + 1
    endloop
   
    call SaveGroupHandle(udg_Hash,12,1,CreepGroup)
    set index = 0
   
    loop
        exitwhen index >= 4
        set loc = PolarProjectionBJ(Source,3000.0,(90.0*index))
       
        set u = CreateUnit(Player(index),'hbar',GetLocationX(loc),GetLocationY(loc),270.0)
        call SaveUnitHandle(udg_Hash,index,1,u)
       
        call RemoveLocation(loc)
        set index = index + 1
    endloop
   
    call RemoveLocation(Source)
    call TimerStart(SpawnTimer,2.5,true,function SpawnUnits)
   
    set Source = null
    set loc = null
    set SpawnTimer = null
    set CreepGroup = null
endfunction

//===========================================================================
function InitTrig_Spawn_unit takes nothing returns nothing
    local integer Sslot = 0
    local integer Tslot = 0
   
    set gg_trg_Spawn_unit = CreateTrigger(  )
    set udg_Hash = InitHashtable()
    call CreateFogModifierRectBJ( true, Player(0), FOG_OF_WAR_VISIBLE, GetPlayableMapRect())
   
    loop
        exitwhen Sslot >= 4
        set Tslot = 0
        loop
            exitwhen Tslot >= 4
            call SetPlayerAllianceStateAllyBJ(Player(Sslot),Player(Tslot),true)
            set Tslot = Tslot + 1
        endloop
        set Sslot = Sslot + 1
    endloop
   
    // to test dead barracks
    // call CreateUnit(Player(0),'hmtt',2000.0,2000.0,0)
    // call CreateUnit(Player(0),'hmtt',-2000.0,2000.0,0)
    // call CreateUnit(Player(0),'hmtt',-2000.0,-2000.0,0)
    // call CreateUnit(Player(0),'hmtt',2000.0,-2000.0,0)
   
    call Trig_Spawn_unit_Actions()
endfunction


you can use ChooseRandomCreep(-1) it is easier and has a better random distribution (imo).
That's a nice trick, thanks.
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
It's still no square. You would have to change
JASS:
set loc = PolarProjectionBJ(Source,3000.0,(90.0*index))
to
JASS:
set loc = PolarProjectionBJ(Source,3000.0,(90.0*index + 45))
You can change it if you want, but you don't have to. I am sure you are capable of adding "+ 45", so I do not ask you to change it in order to solve the mission.

Changes have been made, mission is solved.
 
Level 12
Joined
Jun 15, 2016
Messages
472
It's a quadrangle with two equal, perpendicular diagonals that intersect one another at the middle. Seems like a square rotated 45 degrees to the default game view to me.

But I digress. Thank you very much :D
 
Status
Not open for further replies.
Top