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

[JASS] I could use feed back/suggestions on two automated workers systems i am working ont

Status
Not open for further replies.
Level 7
Joined
Jan 28, 2012
Messages
266
These systems are for a city building game I am working on.
I would like people to review the triggering test the map and supply suggestions(better yet fixes:grin:) for things I can improve.

a couple things I know could use fixing/improvement are:
A better method for the crops in the farming system.
A solution for a bug which happens when two units moving opposite directions go toe to toe with each other and sit in each other's way.
I am pretty positive wc3's pathing is causing this problem
and any other suggestions


  • Farm Give
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Recieve orders {852186
      • (Unit-type of (Target unit of ability being cast)) Equal to Granery
    • Actions
      • Custom script: local unit u
      • Set U = (Target unit of ability being cast)
      • Set u = (Triggering unit)
      • Set I = (Custom value of U)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (u is in GW[I]) Equal to True
        • Then - Actions
          • For each (Integer A) from 1 to 6, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Item level of (Item carried by U in slot A)) Equal to 0
                • Then - Actions
                  • Hero - Give (Item carried by u in slot A) to U
                  • Custom script: call AddUnitAnimationProperties(udg_u,"gold",false)
                • Else - Actions
          • Set int[0] = (Number of units in GrainHarvest[I])
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • int[0] Greater than 0
            • Then - Actions
              • Custom script: call IssueImmediateOrderById(GetTriggerUnit(),851972)
              • Custom script: set udg_int[1] = 6-UnitInventoryCount(udg_u)
              • -------- --------
              • Custom script: if udg_int[1]> udg_int[0] then
              • Custom script: set udg_int[1] = udg_int[0]
              • Custom script: endif
              • For each (Integer A) from 1 to int[1], do (Actions)
                • Loop - Actions
                  • Custom script: loop
                  • Custom script: set u = FirstOfGroup(udg_GrainHarvest[udg_I])
                  • Custom script: call GroupRemoveUnit(udg_GrainHarvest[udg_I],u)
                  • Custom script: exitwhen u != null
                  • Custom script: endloop
                  • Custom script: call IssueTargetNextOrder(udg_u,852018,u)
              • Custom script: call IssueTargetNextOrder(udg_u,852186,udg_U)
              • Custom script: set u = null
            • Else - Actions
              • Set int[0] = (Number of units in GrainPlanting[I])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • int[0] Greater than 0
                • Then - Actions
                  • Custom script: call IssueImmediateOrderById(GetTriggerUnit(),851972)
                  • -------- --------
                  • Custom script: if 6 > udg_int[0] then
                  • Custom script: set udg_int[1] = udg_int[0]
                  • Custom script: else
                  • Custom script: set udg_int[1] = 6
                  • Custom script: endif
                  • For each (Integer A) from 1 to int[1], do (Actions)
                    • Loop - Actions
                      • Custom script: loop
                      • Custom script: set u = FirstOfGroup(udg_GrainPlanting[udg_I])
                      • Custom script: call GroupRemoveUnit(udg_GrainPlanting[udg_I],u)
                      • Custom script: exitwhen u != null
                      • Custom script: endloop
                      • Custom script: call IssueTargetNextOrder(udg_u,852600,u)
                  • Custom script: call IssueTargetNextOrder(udg_u,852186,udg_U)
                  • Custom script: set u = null
                • Else - Actions
                  • Custom script: call IssueImmediateOrderById(GetTriggerUnit(),851972)
                  • Custom script: set u = GroupPickRandomUnit(udg_GrainFields[udg_I])
                  • Custom script: call IssuePointNextOrder(udg_u,851983,GetUnitX(u),GetUnitY(u))
                  • Custom script: set u = GroupPickRandomUnit(udg_GrainFields[udg_I])
                  • Custom script: call IssuePointNextOrder(udg_u,851983,GetUnitX(u),GetUnitY(u))
                  • -------- blah blah blah --------
                  • Custom script: call IssueTargetNextOrder(udg_u,852186,udg_U)
                  • Custom script: set u = null
        • Else - Actions
JASS:
function Reap_Filter takes nothing returns boolean
  
   if GetUnitTypeId(GetFilterUnit()) == 'h000' then

     call GroupAddUnit(udg_GrainPlanting[udg_I],GetFilterUnit())
     call GroupAddUnit(udg_GrainNotPlanted[udg_I],GetFilterUnit())
     
   endif
   return false
endfunction

function Trig_Reap_Conditions takes nothing returns boolean
    local unit uMe 
    local unit UCrop = GetSpellTargetUnit()

    set udg_I = GetUnitUserData(UCrop)
    if GetSpellAbilityId() == 'A009' and IsUnitInGroup(UCrop,udg_GrainHarvestable[udg_I]) then
       set uMe = GetTriggerUnit()
       if GetUnitTypeId(UCrop) == 'h002' then
          call UnitAddItemById(uMe,'I000')
       endif
       call AddUnitAnimationProperties(uMe,"gold",true)
       call GroupRemoveUnit(udg_GrainHarvest[udg_I],UCrop)
       call GroupRemoveUnit(udg_GrainHarvestable[udg_I],UCrop)
       call RemoveUnit(UCrop)
       call GroupEnumUnitsInRange(udg_TempGroup,GetUnitX(UCrop),GetUnitY(UCrop),30,Filter(function Reap_Filter))
       set uMe = null
    endif
    set UCrop = null
    return false
endfunction


//===========================================================================
function InitTrig_Farm_Reap takes nothing returns nothing
    set gg_trg_Farm_Reap = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Farm_Reap, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Farm_Reap, Condition( function Trig_Reap_Conditions ) )
endfunction
JASS:
function Trig_Farm_Harvest_Conditions takes nothing returns boolean
    local unit u
    local unit U 
    local integer i
    
     
    if  GetSpellAbilityId() == 'A002'  then
       set U = GetSpellTargetUnit()            
       set i = GetUnitUserData(U)
         
       if IsUnitInGroup(U,udg_GrainNotPlanted[i]) then
       
          if CountUnitsInGroup(udg_gG) == 0  then
              call EnableTrigger( gg_trg_gG )       
          endif
       
          set udg_UnitIndexerEnabled = false
          
          if GetUnitAcquireRange(U) == 10.00 then
             set u = CreateUnit(GetTriggerPlayer(),'h002',GetUnitX(U),GetUnitY(U),0)
          endif

          call SetUnitUserData(u,i)
          set udg_UnitIndexerEnabled = true
          call SetUnitScale(u,.01,.01,.01)
          call GroupAddUnit(udg_gG,u)
          call GroupRemoveUnit(udg_GrainPlanting[i],U)
          call GroupRemoveUnit(udg_GrainNotPlanted[i],U)
          set u = null
          set U = null
      else
          call IssueImmediateOrderById(GetTriggerUnit(),851972)  

      endif    

    endif
    
    return false
endfunction




//===========================================================================
function InitTrig_Farm_Harvest takes nothing returns nothing
    set gg_trg_Farm_Harvest = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Farm_Harvest, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Farm_Harvest, Condition( function Trig_Farm_Harvest_Conditions ) )
    
endfunction
  • gG
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in gG) Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
          • Unit Group - Pick every unit in gG and do (Actions)
            • Loop - Actions
              • Custom script: local unit u = GetEnumUnit()
              • Custom script: local real p = GetUnitManaPercent( u)
              • Custom script: local integer i =GetUnitUserData(u)
              • Custom script: if not IsUnitType(u,UNIT_TYPE_DEAD) then
              • Custom script: if p ==100 then
              • Custom script: call GroupAddUnit(udg_GrainHarvest[i],u)
              • Custom script: call GroupAddUnit(udg_GrainHarvestable[i],u)
              • Custom script: call GroupRemoveUnit(udg_gG,u)
              • Custom script: endif
              • Custom script: call SetUnitScalePercent( u,p, p, p )
              • Custom script: else
              • Custom script: call GroupRemoveUnit(udg_gG,u)
              • Custom script: endif
              • Custom script: set u = null
  • Mill Give
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Recieve orders {852186
      • (Unit-type of (Target unit of ability being cast)) Equal to Mill
    • Actions
      • Custom script: local group G
      • Custom script: local unit u = null
      • Custom script: local unit Chosen = null
      • Custom script: local real d
      • Custom script: local real d2
      • Custom script: local real x
      • Custom script: local real y
      • Custom script: local item flour
      • Set u = (Triggering unit)
      • Set U = (Target unit of ability being cast)
      • Set Item = (Item carried by u of type Wheat)
      • Custom script: set udg_int[0] = GetUnitUserData(udg_u)
      • Custom script: set y = GetUnitY(udg_U)
      • Custom script: set x = GetUnitX(udg_U)
      • Custom script: if udg_Item != null then
      • Custom script: call IssueTargetNextOrder(udg_u,852185,udg_MillU[udg_int[0]])
      • Hero - Drop Item from u
      • Custom script: set flour = CreateItem('I001',x,y)
      • Custom script: call SetItemCharges(flour,GetItemCharges(udg_Item))
      • Custom script: call UnitAddItem(udg_u,flour)
      • Item - Remove Item
      • Custom script: set flour = null
      • Custom script: endif
      • -------- --------
      • Custom script: set udg_int[1] = LoadInteger(udg_Storage,GetUnitUserData(udg_MillU[udg_int[0]]),'I000')
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • int[1] Not equal to 0
        • Then - Actions
          • Custom script: set Chosen = udg_MillU[udg_int[0]]
        • Else - Actions
      • -------- -------------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
        • Then - Actions
          • Custom script: set G = GetUnitsOfPlayerAndTypeId(GetTriggerPlayer(), 'h001')
          • -------- -------------- --------
          • Custom script: loop
          • -------- -------------- --------
          • Custom script: set u = FirstOfGroup(G)
          • Custom script: exitwhen u == null
          • Custom script: set udg_int[1] = LoadInteger(udg_Storage,GetUnitUserData(u), 'I000')
          • -------- -------------- --------
          • Custom script: if udg_int[1] != 0 then
          • -------- -------------- --------
          • Custom script: if Chosen == null then
          • -------- -------------- --------
          • Custom script: set Chosen = u
          • Custom script: set d2 = (Pow(x-GetUnitX(u),2) +Pow(y-GetUnitY(u),2))/1000.0000
          • -------- -------------- --------
          • Custom script: else
          • -------- -------------- --------
          • Custom script: set d = (Pow(x-GetUnitX(u),2) +Pow(y-GetUnitY(u),2))/1000.0000
          • -------- -------------- --------
          • Custom script: if d < d2 then
          • -------- -------------- --------
          • Custom script: set Chosen = u
          • Custom script: set d2 = d
          • -------- -------------- --------
          • Custom script: endif
          • -------- -------------- --------
          • Custom script: endif
          • -------- -------------- --------
          • Custom script: if d2 < 1000 then
          • -------- -------------- --------
          • Custom script: exitwhen true
          • Custom script: endif
          • -------- -------------- --------
          • Custom script: endif
          • Custom script: call GroupRemoveUnit(G,u)
          • -------- -------------- --------
          • Custom script: endloop
          • -------- -------------- --------
          • -------- -------------- --------
          • Custom script: if Chosen != null then
          • Custom script: set udg_MillU[udg_int[0]] = Chosen
          • -------- -------------- --------
          • Custom script: call IssueTargetNextOrder(udg_u,852665,Chosen)
          • -------- -------------- --------
          • Custom script: else
          • -------- -------------- --------
          • Custom script: call IssueImmediateNextOrder(udg_u,852663)
          • -------- -------------- --------
          • -------- -------------- --------
          • Custom script: endif
          • -------- -------------- --------
        • Else - Actions
      • Custom script: call IssueTargetNextOrder(udg_u,852186,udg_U)
  • Mill Take
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Unit-type of (Target unit of ability being cast)) Equal to Granery
      • (Ability being cast) Equal to Take {852665
    • Actions
      • Set u = (Triggering unit)
      • Set U = (Target unit of ability being cast)
      • Custom script: set udg_int[0] = GetUnitUserData(udg_U)
      • Custom script: set udg_int[1] = LoadInteger(udg_Storage,udg_int[0],'I000')
      • Custom script: if 8 < udg_int[1] then
      • Custom script: set udg_int[2] = 8
      • Custom script: else
      • Custom script: if udg_int[1] == 0 then
      • Custom script: return
      • Custom script: endif
      • Custom script: set udg_int[2] = udg_int[1]
      • Custom script: endif
      • Custom script: call AddUnitAnimationProperties(udg_u,"gold",true)
      • For each (Integer A) from 1 to int[2], do (Actions)
        • Loop - Actions
          • Hero - Create Wheat and give it to u
      • Custom script: call SaveInteger(udg_Storage,udg_int[0],'I000',udg_int[1]-udg_int[2])
  • Mill Give2
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Unit-type of (Target unit of ability being cast)) Equal to Granery
      • (Ability being cast) Equal to Give2 {852185
    • Actions
      • Set u = (Triggering unit)
      • Set U = (Target unit of ability being cast)
      • Set Item = (Item carried by u of type Flour)
      • Custom script: if udg_Item != null then
      • Hero - Drop Item from u
      • Hero - Give Item to U
      • Custom script: endif
      • Custom script: call AddUnitAnimationProperties(udg_u,"gold",false)
JASS:
//=========================================================================================================================
//                                              Section 1 Introduction 
//                                                  also entitled
//                                       so I have NextOrder, what does it do?
//=========================================================================================================================  
//    NextOrder is a system designed to emulate the user given shift orders i.e waypoints, however it has a lot more 
//    functionality, you can insert and replace orders, and  most importantly  give "waypoint" orders using triggers
//
//    Q: Can I give patrol orders?
//    A: Yes, but they will behave like a regular patrol order until the player interrupts the unit.
//
//    Q: Why did you create this system
//    A: I wanted to make a city building map, with automated workers doing complex tasks like, farming, smithing, 
//        etc.. And this was the only way I could think of to do it.
//
//=========================================================================================================================
//                                                 Section 2 list of Commands
//                                                      also entitled
//                                          I now know what it does, how do I use it?
//=========================================================================================================================
// IssueImmediateNextOrder takes unit u, integer order returns boolean
//                :can be used to issue train orders, and cast abilities like warstomp, returns false if the NextOrder
//                  was issued as a normal order
//=========================================================================================================================
// IssueImmediateNextOrderBJ takes unit u, string order returns boolean
//                :almost Identical to IssueImmediateNextOrder but you don't have to
//                  look up the integer id's
//=========================================================================================================================
// IssueTargetNextOrder takes unit u, integer order returns boolean
//                :can be used to cast abilities like firebolt heal, returns false if the NextOrder
//                  was issued as a normal order
//=========================================================================================================================
// IssueTargetNextOrderBJ takes unit u, string order returns boolean
//                :almost Identical to IssueTargetNextOrder but you don't have to
//                  look up the integer id's
//=========================================================================================================================
// IssuePointNextOrder takes unit u, integer order returns boolean
//                :can be used to issue move,attackmove orders, and cast abilities like blizzard, 
//                  returns false if the NextOrder was issued as a normal order
//=========================================================================================================================
// IssuePointNextOrderBJ takes unit u, string order returns boolean
//                :almost Identical to IssuePointNextOrder but you don't have to
//                  look up the integer id's
//=========================================================================================================================
//                            Advanced Orders Guide
//=========================================================================================================================
// Insert(Immediate,Point,Target)NextOrder takes +, integer insert, boolean fromstart returns boolean
//                : puts an Order into the middle of the units queue of orders, it can be measured
//                   from start or from the current order, based off of the bool fromstart.
//=========================================================================================================================
// ReplaceWith(Immediate,Point,Target)NextOrder takes +, integer whichone, boolean fromstart returns boolean
//                : replaces an order with a new order, the order that you want to replace can be 
//                   measured from start
//=========================================================================================================================
// RemoveNextOrder takes untit u, integer whichone returns boolean
//                : Removes an order from a units queue, returns wether it was sucessful or not
//=========================================================================================================================
// IssueRepeatOrder takes unit u, integer from, integer howmany returns boolean
//                : repeats from an order you specify to this order, use a negitive value for
//                   endless looping.
//=========================================================================================================================
// IssueRepeatTillCondition Order takes unit u, integer from, boolexpr cond returns boolean
//                : repeats from an order you specify to this order, use a negitive value for
//                   endless looping.
//===============================================================================================
//
//
function NextOrder_allocate takes nothing returns integer
    // allocate it
    local integer this
    if udg_NextOrder_instanceRecycle == 0 then
        set udg_NextOrder_instanceCount = udg_NextOrder_instanceCount + 1
        set this = udg_NextOrder_instanceCount
    else
        set this = udg_NextOrder_instanceRecycle
        set udg_NextOrder_instanceRecycle = udg_NextOrder_recycleNext[this]
    endif
    // add it to the list
    set udg_NextOrder_next[this] = 0
    set udg_NextOrder_prev[this] = udg_NextOrder_prev[0]
    set udg_NextOrder_next[udg_NextOrder_prev[0]] = this
    set udg_NextOrder_prev[0] = this
    // return the new instance
    return this
endfunction

// deallocate:
function NextOrder_deallocate takes integer this returns nothing
    // deallocate it
    if this == 0 then
    else
       set udg_NextOrder_recycleNext[this] = udg_NextOrder_instanceRecycle
       set udg_NextOrder_instanceRecycle = this
       // remove it from the list
       set udg_NextOrder_next[udg_NextOrder_prev[this]] = udg_NextOrder_next[this]
       set udg_NextOrder_prev[udg_NextOrder_next[this]] = udg_NextOrder_prev[this]
       set udg_NextOrder_index[GetUnitUserData(udg_NextOrder_U[this])] = 0
       set udg_NextOrder_U[this] = null// nulling the unit
       
    endif
endfunction

function IssueImmediateNextOrder takes unit u, integer order returns boolean
    local integer index
    local integer int
    if GetUnitCurrentOrder(u) == 0 then
        call IssueImmediateOrderById(u,order)
        set u = null
        return false   
    endif

    set index = udg_NextOrder_index[GetUnitUserData(u)]
    if index == 0 then
       set index = NextOrder_allocate()
       set udg_NextOrder_Last[index] = 0
       set udg_NextOrder_Current[index]=0
       set udg_NextOrder_U[index]=u
       set udg_NextOrder_index[GetUnitUserData(u)] = index
    endif

    set int = udg_NextOrder_Last[index]*5
    call SaveInteger(udg_NextOrder,index,int,1)//the kind of order it is
    call SaveInteger(udg_NextOrder,index,int+1,order)//what the order id is
    set udg_NextOrder_Last[index] = udg_NextOrder_Last[index]+1

    set u = null
    return true
endfunction

function IssueImmediateNextOrderBJ takes unit u, string order returns boolean
    local integer id = OrderId(order)
    if id != 0 then
        return IssueImmediateNextOrder(u,id)
    endif

    set id = UnitId(order)
    if id != 0 then
        return IssueImmediateNextOrder(u,id)
    endif

    set u = null
    return false// unrecognized order
endfunction

function IssueTargetNextOrder takes unit u , integer order,  widget target returns boolean//issues a regular order if the units current order is nothing
    local integer index
    local integer int
    if GetUnitCurrentOrder(u) == 0 then
        call IssueTargetOrderById(u,order,target)
        set u = null
        set target = null
        return false   
    endif

    set index = udg_NextOrder_index[GetUnitUserData(u)]

    if index == 0 then
       set index = NextOrder_allocate()
       set udg_NextOrder_Last[index] = 0
       set udg_NextOrder_Current[index]=0
       set udg_NextOrder_U[index]=u
       set udg_NextOrder_index[GetUnitUserData(u)] = index
    endif

    set int = udg_NextOrder_Last[index]*5
    call SaveInteger(udg_NextOrder,index,int,2)//the kind of order it is
    call SaveInteger(udg_NextOrder,index,int+1,order)//what the order id is   
    call SaveWidgetHandle(udg_NextOrder,index,int+2,target)
    set udg_NextOrder_Last[index] = udg_NextOrder_Last[index]+1

    set u = null
    set target =null
    return true
endfunction

function IssueTargetNextOrderBJ takes unit u, string order, widget target returns boolean//for people who don't want to bother with
    return IssueTargetNextOrder(u,OrderId(order),target)                             // doing a little research on orderId's
endfunction


function IssuePointNextOrder takes unit u, integer order, real x, real y returns boolean
    local integer index
    local integer int
    if GetUnitCurrentOrder(u) == 0 then
        call IssuePointOrderById(u,order,x,y)
        set u = null
        return false   
    endif

    set index = udg_NextOrder_index[GetUnitUserData(u)]
    if index == 0 then
       set index = NextOrder_allocate()
       set udg_NextOrder_Last[index] = 0
       set udg_NextOrder_Current[index]=0
       set udg_NextOrder_U[index]=u
       set udg_NextOrder_index[GetUnitUserData(u)] = index
    endif

    set int = udg_NextOrder_Last[index]*5
    call SaveInteger(udg_NextOrder,index,int,3)//the kind of order it is
    call SaveInteger(udg_NextOrder,index,int+1,order)//what the order id is
    call SaveReal(udg_NextOrder,index,int+2,x)//saving the x coord
    call SaveReal(udg_NextOrder,index,int+3,y)//saving the y coord
    set udg_NextOrder_Last[index] = udg_NextOrder_Last[index]+1

    set u = null//preventing handle leaks
    return true//the order was issued as a next order

endfunction

function IssuePointNextOrderBJ takes unit u, string order, real x, real y returns boolean
    return IssuePointNextOrder(u,OrderId(order),x,y)  
endfunction


//=========================================================================================================================
//                                          Advanced NextOrders
//=========================================================================================================================

function RemoveNextOrder takes unit u, integer whichone returns boolean
    local integer index = udg_NextOrder_index[GetUnitUserData(u)]
    local integer order
    local integer current
    local integer int
    local integer prev

    if whichone < 0 or whichone > udg_NextOrder_Last[index] then
        set u = null
        return false
    endif

    set current = whichone+1
    set int = whichone*5

    loop 
        set order = LoadInteger(udg_NextOrder,index,current*5)
        set prev = int
        set int = prev+5

       if order == 1 then

           call SaveInteger(udg_NextOrder,index,prev,LoadInteger(udg_NextOrder,index,int))
           call SaveInteger(udg_NextOrder,index,prev+1,LoadInteger(udg_NextOrder,index,int+1))

       elseif order == 2 then

           call SaveInteger(udg_NextOrder,index,prev,LoadInteger(udg_NextOrder,index,int))
           call SaveInteger(udg_NextOrder,index,prev+1,LoadInteger(udg_NextOrder,index,int+1))
           call SaveWidgetHandle(udg_NextOrder,index,prev+2,LoadWidgetHandle(udg_NextOrder,index,int+2))

       elseif order == 3 then

           call SaveInteger(udg_NextOrder,index,prev,LoadInteger(udg_NextOrder,index,int))
           call SaveInteger(udg_NextOrder,index,prev+1,LoadInteger(udg_NextOrder,index,int+1))
           call SaveReal(udg_NextOrder,index,prev+2,LoadReal(udg_NextOrder,index,int+2))
           call SaveReal(udg_NextOrder,index,prev+3,LoadReal(udg_NextOrder,index,int+3))

       endif
       exitwhen current == udg_NextOrder_Last[index]
       set current = current +1
    endloop

    set udg_NextOrder_Last[index] = udg_NextOrder_Last[index]-1
    set u = null
    return true
endfunction
//==================================================================================================================
//                                   Replace Orders
//==================================================================================================================

function ReplaceWithImediateNextOrder takes unit u, integer order, integer whichone, boolean fromstart returns boolean
    local integer index = udg_NextOrder_index[GetUnitUserData(u)]
    local integer order
    local integer current
    local integer int 

    if not fromstart then
        set whichone = whichone+udg_NextOrder_Last[index]
    endif

    if whichone <0 or whichone > udg_NextOrder_Last[index] then
        set u = null
        return false
    endif

    if HaveSavedHandle(udg_NextOrder,index,int+3) then
       call RemoveSavedHandle(udg_NextOrder,index,int+3)
    endif

    call SaveInteger(udg_NextOrder,index,int,1)
    call SaveInteger(udg_NextOrder,index,int+1,order)

    set u = null
    return true
endfunction

function ReplaceWithTargetNextOrder takes unit u, integer order, widget t, integer whichone, boolean fromstart returns boolean
    local integer index = udg_NextOrder_index[GetUnitUserData(u)]
    local integer order
    local integer current
    local integer int 

    if not fromstart then
        set whichone = whichone+udg_NextOrder_Last[index]
    endif

    if whichone <0 or whichone > udg_NextOrder_Last[index] then
        set t = null
        set u = null
        return false
    endif

    call SaveInteger(udg_NextOrder,index,int,1)
    call SaveInteger(udg_NextOrder,index,int+1,order)
    call SaveWidgetHandle(udg_NextOrder,index,int+2,t)

    set t = null
    set u = null
    return true
endfunction

function ReplaceWithPointNextOrder takes unit u, integer order, real x, real y, integer whichone, boolean fromstart returns boolean
    local integer index = udg_NextOrder_index[GetUnitUserData(u)]
    local integer order
    local integer current
    local integer int 

    if not fromstart then
        set whichone = whichone+udg_NextOrder_Last[index]
    endif

    if whichone <0 or whichone > udg_NextOrder_Last[index] then
        set u = null
        return false
    endif

    call SaveInteger(udg_NextOrder,index,int,1)
    call SaveInteger(udg_NextOrder,index,int+1,order)
    call SaveReal(udg_NextOrder,index,int+2,x)
    call SaveReal(udg_NextOrder,index,int+2,x)

    set u = null
    return true
endfunction
//==================================================================================================================
//                                   Insert Orders
//==================================================================================================================
function InsertImmediateNextOrder takes unit u, integer order, integer insert, boolean fromstart returns boolean
    local integer index = udg_NextOrder_index[GetUnitUserData(u)]
    local integer current
    local integer int
   
    if not fromstart then
        set insert = udg_NextOrder_Last[index] + insert
    endif

    if insert < 0 or insert > udg_NextOrder_Last[index] then
        set u = null
        return false
    endif

    set int = udg_NextOrder_Last[index]*5 //tinas sanchilas
    set order = 0

    loop
        if order == 1 then
            call SaveInteger(udg_NextOrder,index,int+5,1)
            call SaveInteger(udg_NextOrder,index,int+6,LoadInteger(udg_NextOrder,index,int+1))
        elseif order == 2 then
            call SaveInteger(udg_NextOrder,index,int+5,2)
            call SaveInteger(udg_NextOrder,index,int+6,LoadInteger(udg_NextOrder,index,int+1))
            call SaveWidgetHandle(udg_NextOrder,index,int+7,LoadWidgetHandle(udg_NextOrder,index,int+2))
            call RemoveSavedHandle(udg_NextOrder,index,int+2)
        elseif order == 3 then
            call SaveInteger(udg_NextOrder,index,int+5,3)
            call SaveInteger(udg_NextOrder,index,int+6,LoadInteger(udg_NextOrder,index,int+1))
            call SaveReal(udg_NextOrder,index,int+7,LoadReal(udg_NextOrder,index,int+2))
            call SaveReal(udg_NextOrder,index,int+8,LoadReal(udg_NextOrder,index,int+3))
        endif
        exitwhen current == insert
        set current = current-1
        set int = int-5
    endloop

    set int = insert*5
    call SaveInteger(udg_NextOrder,index,int,1)
    call SaveInteger(udg_NextOrder,index,int+1,order)

    set udg_NextOrder_Last[index] = udg_NextOrder_Last[index]+1

    set u = null
    return true
endfunction

function InsertTargetNextOrder takes unit u, integer order, widget t, integer insert, boolean fromstart returns boolean
    local integer index = udg_NextOrder_index[GetUnitUserData(u)]
    local integer current
    local integer int
   
    if not fromstart then
        set insert = udg_NextOrder_Last[index] + insert
    endif

    if insert < 0 or insert > udg_NextOrder_Last[index] then
        set u = null
        return false
    endif

    set int = udg_NextOrder_Last[index]*5
    set order = 0

    loop
        if order == 1 then
            call SaveInteger(udg_NextOrder,index,int+5,1)
            call SaveInteger(udg_NextOrder,index,int+6,LoadInteger(udg_NextOrder,index,int+1))
        elseif order == 2 then
            call SaveInteger(udg_NextOrder,index,int+5,2)
            call SaveInteger(udg_NextOrder,index,int+6,LoadInteger(udg_NextOrder,index,int+1))
            call SaveWidgetHandle(udg_NextOrder,index,int+7,LoadWidgetHandle(udg_NextOrder,index,int+2))
            call RemoveSavedHandle(udg_NextOrder,index,int+2)
        elseif order == 3 then
            call SaveInteger(udg_NextOrder,index,int+5,3)
            call SaveInteger(udg_NextOrder,index,int+6,LoadInteger(udg_NextOrder,index,int+1))
            call SaveReal(udg_NextOrder,index,int+7,LoadReal(udg_NextOrder,index,int+2))
            call SaveReal(udg_NextOrder,index,int+8,LoadReal(udg_NextOrder,index,int+3))
        endif
        exitwhen current == insert
        set current = current-1
        set int = int-5
    endloop

    set int = insert*5     
    call SaveInteger(udg_NextOrder,index,int,1)
    call SaveInteger(udg_NextOrder,index,int+1,order)
    call SaveWidgetHandle(udg_NextOrder,index,int+2,t)

    set udg_NextOrder_Last[index] = udg_NextOrder_Last[index]+1

    set t = null
    set u = null
    return true
endfunction

function InsertPointNextOrder takes unit u, integer order, real x, real y, integer insert, boolean fromstart returns boolean
    local integer index = udg_NextOrder_index[GetUnitUserData(u)]
    local integer current
    local integer int
    local integer order

    if not fromstart then
        set insert = udg_NextOrder_Last[index] + insert
    endif

    if insert < 0 or insert > udg_NextOrder_Last[index] then
        set u = null
        return false
    endif

    set int = udg_NextOrder_Last[index]*5
    set order = LoadInteger(udg_NextOrder,index,int)

    loop
        if order == 1 then
            call SaveInteger(udg_NextOrder,index,int+5,1)
            call SaveInteger(udg_NextOrder,index,int+6,LoadInteger(udg_NextOrder,index,int+1))
        elseif order == 2 then
            call SaveInteger(udg_NextOrder,index,int+5,2)
            call SaveInteger(udg_NextOrder,index,int+6,LoadInteger(udg_NextOrder,index,int+1))
            call SaveWidgetHandle(udg_NextOrder,index,int+7,LoadWidgetHandle(udg_NextOrder,index,int+2))
            call RemoveSavedHandle(udg_NextOrder,index,int+2)
        elseif order == 3 then
            call SaveInteger(udg_NextOrder,index,int+5,3)
            call SaveInteger(udg_NextOrder,index,int+6,LoadInteger(udg_NextOrder,index,int+1))
            call SaveReal(udg_NextOrder,index,int+7,LoadReal(udg_NextOrder,index,int+2))
            call SaveReal(udg_NextOrder,index,int+8,LoadReal(udg_NextOrder,index,int+3))
        endif
        exitwhen current == insert
        set current = current-1
        set int = int-5
    endloop

    set int = insert*5     
    call SaveInteger(udg_NextOrder,index,int,1)
    call SaveInteger(udg_NextOrder,index,int+1,order)
    call SaveReal(udg_NextOrder,index,int+2,x)
    call SaveReal(udg_NextOrder,index,int+3,y)

    set udg_NextOrder_Last[index] = udg_NextOrder_Last[index]+1

    set u = null
    return true
endfunction
JASS:
function NextOrderLoop takes nothing returns boolean
    local integer this = udg_NextOrder_next[0]
    local integer current
    local integer order
    local integer int
   
    if this != 0 then
 
        loop 
        
            if IsUnitType(udg_NextOrder_U[this],UNIT_TYPE_DEAD) then
                call NextOrder_deallocate(this)
                call FlushChildHashtable(udg_NextOrder,this)

            else

               if GetUnitCurrentOrder(udg_NextOrder_U[this]) == 0  then
                   set current= udg_NextOrder_Current[this]
                   set int    = current*5
                   set order  = LoadInteger(udg_NextOrder,this, int)

                    if     order == 1 then
                        call IssueImmediateOrderById(udg_NextOrder_U[this],LoadInteger(udg_NextOrder,this,int+1))
                    elseif order == 2 then
                        call IssueTargetOrderById(udg_NextOrder_U[this],LoadInteger(udg_NextOrder,this,int+1),LoadWidgetHandle(udg_NextOrder,this,int+2))
                        call RemoveSavedHandle(udg_NextOrder,this,int+2) 
                    elseif order == 3 then
                         call IssuePointOrderById(udg_NextOrder_U[this],LoadInteger(udg_NextOrder,this,int+1),LoadReal(udg_NextOrder,this,int+2),LoadReal(udg_NextOrder,this,int+3))          
                    endif
                    set udg_NextOrder_Current[this] = udg_NextOrder_Current[this]+1
                    if udg_NextOrder_Current[this] == udg_NextOrder_Last[this] then
                        call NextOrder_deallocate(this)
                        call FlushChildHashtable(udg_NextOrder,this)
                    endif
                endif
            endif

            set this  = udg_NextOrder_next[this]
            exitwhen this == 0     
        endloop

    endif
    return false
endfunction
//===========================================================================
function InitTrig_NextOrder takes nothing returns nothing
    set gg_trg_NextOrder = CreateTrigger(  )
    set udg_NextOrder = InitHashtable()
    call  TriggerRegisterTimerEvent(gg_trg_NextOrder,0.02000000,true)
    call TriggerAddCondition(gg_trg_NextOrder,Condition(function NextOrderLoop))
endfunction
 

Attachments

  • WorkerGrain(primitveNextOrder).w3x
    53.4 KB · Views: 34
Level 7
Joined
Jan 28, 2012
Messages
266
Bump also update

JASS:
function Trig_Mill_Give2 takes unit U returns nothing
    local unit u = GetTriggerUnit()
    local item ite = UnitItemInSlot(u, GetInventoryIndexOfItemTypeBJ(u, 'I001')-1)

    call DisplayTextToPlayer(Player(0),0,0,"working")
    if ite != null then
        call DisplayTextToPlayer(Player(0),0,0,"RemovingItem")
        call UnitRemoveItem( u, ite )
        call UnitAddItem( U, ite )
    else
        call DisplayTextToPlayer(Player(0),0,0,"Not Working")
    endif

    call AddUnitAnimationProperties(u,"gold",false)
    set u = null
    set ite = null
    set U = null
endfunction

function Trig_Mill_Grab takes unit U returns nothing
    local unit u = GetTriggerUnit()
    local integer a = 0
    local integer I2    
    local integer index = GetUnitUserData(U)
    local integer I1 = LoadInteger(udg_Storage,index,'I000')


    if  8 < I1 then
        set I2 = 8
    elseif I1 == 0 then
        return
    else
        set I2 = I1
    endif

    call AddUnitAnimationProperties(u,"gold",true)

    loop
        exitwhen a == I2
        call UnitAddItemById( u,'I000' )
        set a = a + 1
    endloop

    call SaveInteger(udg_Storage,index,'I000',I1-I2)
    set U = null
    set u = null
endfunction

function Trig_Mill_Grind takes unit U returns nothing
    local unit Chosen = null
    local unit me = GetTriggerUnit()
    local item flour
    local real x = GetUnitY(U)
    local real y = GetUnitX(U)
    local integer index = GetUnitUserData(me)
    local boolean NoR = true

    set udg_Item = GetItemOfTypeFromUnitBJ(me, 'I000') 

    if udg_Item != null then
        set NoR = false
        call IssueTargetNextOrder(me,852185,udg_MillU[index])
        call UnitRemoveItem(  me,udg_Item )
        set flour = CreateItem('I001',x,y)
        call SetItemCharges(flour,GetItemCharges(udg_Item))
        call UnitAddItem(me,flour)
        call RemoveItem( udg_Item )
        set flour = null
    endif

    set Chosen = SearchForMaterial(GetTriggerPlayer(), 'h001',x,y,'I000', 0, true, 1000 )

    if Chosen != null then
        set udg_MillU[index] = Chosen
        call IssueTargetNextOrder(me,852665,Chosen)
    elseif NoR then
        call IssueImmediateNextOrder(me,852663)
    endif
    
    call IssueTargetNextOrder(me,852186,U)
    set Chosen = null
    set me = null
    set U = null
endfunction


function Trig_Mill_Conditions takes nothing returns boolean
    local unit U = GetSpellTargetUnit()
    local integer id = GetUnitTypeId(U)
    local integer Spell = GetSpellAbilityId()

    if Spell == 'A00A' and id == 'h003' then
        call Trig_Mill_Grind(U)
    elseif Spell == 'A003' and id == 'h001' then
        call Trig_Mill_Grab(U)
    elseif Spell == 'A005' and id == 'h001' then
        call Trig_Mill_Give2(U)
    endif

    set U = null
    return false
endfunction

//===========================================================================
function InitTrig_Mill_Give takes nothing returns nothing
    set gg_trg_Mill_Give = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Mill_Give, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Mill_Give, Condition( function Trig_Mill_Conditions ) )
endfunction
JASS:
//=============================================================================================
//               Reaping
//=============================================================================================
function Reap_Filter takes nothing returns boolean
  
    if GetUnitTypeId(GetFilterUnit()) == 'h000' then
        call GroupAddUnit(udg_GrainPlanting[udg_I],GetFilterUnit())
        call GroupAddUnit(udg_GrainNotPlanted[udg_I],GetFilterUnit())   
    endif
    return false
endfunction

function Trig_Reap takes nothing returns nothing
    local unit uMe 
    local unit UCrop = GetSpellTargetUnit()

    set udg_I = GetUnitUserData(UCrop)
    if IsUnitInGroup(UCrop,udg_GrainHarvestable[udg_I]) then
        set uMe = GetTriggerUnit()
        if GetUnitTypeId(UCrop) == 'h002' then
            call UnitAddItemById(uMe,'I000')
        endif
        call AddUnitAnimationProperties(uMe,"gold",true)
        call GroupRemoveUnit(udg_GrainHarvest[udg_I],UCrop)
        call GroupRemoveUnit(udg_GrainHarvestable[udg_I],UCrop)
        call RemoveUnit(UCrop)
        call GroupEnumUnitsInRange(udg_TempGroup,GetUnitX(UCrop),GetUnitY(UCrop),30,Filter(function Reap_Filter))
        set uMe = null
    endif
    set UCrop = null
endfunction
//========================================================================================================
//                Growing
//========================================================================================================
function Growing_Loop takes nothing returns nothing
    local unit u = GetEnumUnit()
    local real p = GetUnitManaPercent( u)
    local integer i =GetUnitUserData(u)

    if not IsUnitType(u,UNIT_TYPE_DEAD)  then // checking to see if unit is dead
        if p ==100 then                         // checking to see how much mana it has
            call GroupAddUnit(udg_GrainHarvest[i],u) // adding it to auto harvest group
            call GroupAddUnit(udg_GrainHarvestable[i],u) // making it harvestable
            //\\//\\//call GroupRemoveUnit(udg_gG,u)     // making it stop growing
        endif
        call SetUnitScalePercent( u,p, p, p )   // making it get bigger
    else
        call GroupEnumUnitsInRange(udg_TempGroup,GetUnitX(u),GetUnitY(u),30,Filter(function Reap_Filter))
        call GroupRemoveUnit(udg_gG,u)
        call RemoveUnit(u)
    endif

    set u = null
endfunction


function Trig_gG_Actions takes nothing returns nothing
    if  CountUnitsInGroup(udg_gG) == 0 then
        call DisableTrigger( gg_trg_Farming )
    else
        call ForGroup(udg_gG,function Growing_Loop)
    endif
endfunction
//===========================================================================
//              Planting
//===========================================================================
function Trig_Plant takes nothing returns nothing
    local unit u
    local unit U = GetSpellTargetUnit()  
    local integer i = GetUnitUserData(U)
    
       
    if CountUnitsInGroup(udg_gG) == 0  then
        call EnableTrigger( gg_trg_Farming )       
    endif
       
    set udg_UnitIndexerEnabled = false
          
    if GetUnitAcquireRange(U) == 10.00 then
        set u = CreateUnit(GetTriggerPlayer(),'h002',GetUnitX(U),GetUnitY(U),0)
    endif

    call SetUnitUserData(u,i)
    set udg_UnitIndexerEnabled = true
    call SetUnitScale(u,.01,.01,.01)
    call GroupAddUnit(udg_gG,u)
    call GroupRemoveUnit(udg_GrainPlanting[i],U)
    call GroupRemoveUnit(udg_GrainNotPlanted[i],U)

    set u = null
    set U = null
endfunction
//===================================================================================
//            Giver
//===================================================================================

function Trig_Farm_Give takes nothing returns nothing
    local unit u
    local unit U = GetSpellTargetUnit()
    local unit me = GetTriggerUnit()
    local integer i = GetUnitUserData(U)
    local integer Li = 0
    local integer n1
    local integer n2

    if IsUnitInGroup( me, udg_GW[i]) == true then
        loop
            exitwhen Li > 5
            if GetItemLevel(UnitItemInSlot(me, Li)) == 0   then
                call UnitAddItemSwapped( UnitItemInSlot(me, Li), U )
                call AddUnitAnimationProperties(me,"gold",false)
            endif
            set Li = Li + 1
        endloop

        call IssueImmediateOrderById(me,851972)  
        set n1 = CountUnitsInGroup(udg_GrainHarvest[i])
        if n1 > 0 then
            set n2 = 6-UnitInventoryCount(me)             
            if n2> n1 then
                set n2 = n1
            endif

            set Li = 1
            loop
                exitwhen Li > n2
                loop
                    set u = FirstOfGroup(udg_GrainHarvest[i])
                    call GroupRemoveUnit(udg_GrainHarvest[i],u)
                    exitwhen u != null
                endloop
                call IssueTargetNextOrder(me,852018,u)
                set Li = Li +1
            endloop
            call IssueTargetNextOrder(me,852186,U)
        else
            set n1 = CountUnitsInGroup(udg_GrainPlanting[i])
            if n1 > 0 then
                     
                if 6 > n1 then
                    set n2 = n1
                else
                    set n2 = 6
                endif

                set Li = 1
                loop
                    exitwhen Li > n2

                    loop
                        set u = FirstOfGroup(udg_GrainPlanting[i])
                        call GroupRemoveUnit(udg_GrainPlanting[i],u)
                        exitwhen u != null
                    endloop

                    call IssueTargetNextOrder(me,852600,u)
                    set Li = Li+1
                endloop
                call IssueTargetNextOrder(me,852186,U)
            else
                set u = GroupPickRandomUnit(udg_GrainFields[i])
                call IssuePointNextOrder(me,851983,GetUnitX(u),GetUnitY(u))
                set u = GroupPickRandomUnit(udg_GrainFields[i])
                call IssuePointNextOrder(me,851983,GetUnitX(u),GetUnitY(u))
                call IssueTargetNextOrder(me,852186,U)
            endif
        endif
    endif
    set u = null
    set me = null
    set U = null
endfunction
//===================================================================================
//              Hub
//===================================================================================
function Trig_Farming_Conditions takes nothing returns boolean
    local integer Spell = GetSpellAbilityId()

    if Spell == 'A002' then
        call Trig_Plant()
    elseif Spell == 'A009' then
        call Trig_Reap()
    elseif GetUnitTypeId(GetSpellTargetUnit()) == 'h001' and Spell == 'A00A' then
        call Trig_Farm_Give()
    endif

    return false
endfunction

//===========================================================================
function InitTrig_Farming takes nothing returns nothing
    local trigger T = CreateTrigger(  )

    call TriggerRegisterAnyUnitEventBJ( T, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( T, Condition( function Trig_Farming_Conditions ) )
    set T = null

    set gg_trg_Farming = CreateTrigger(  )
    call DisableTrigger( gg_trg_Farming )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Farming, 1.00 )
    call TriggerAddCondition( gg_trg_Farming, Condition(function Trig_gG_Actions ))
endfunction
 

Attachments

  • WorkerSys 0.0.0.1.3.w3x
    53.2 KB · Views: 84
Level 5
Joined
Sep 19, 2006
Messages
152
Grammar Freak: Should be want my....


Off Topic: thanks for posting, it wasn't the most useful 72 character post, but still thanks for replying.

On Topic: hmm I just realize that I haven't finished the last three function in NextOrder.

I suppose, technically, it should be "Want my honest-to-God suggestion."

Otherwise, yes, the postings are correct: you (the original poster) should consider writing your entire trigger in Jass in order to avoid that mottled look.
 

Cokemonkey11

Spell Reviewer
Level 30
Joined
May 9, 2006
Messages
3,537
JASS:
function InitTrig_Farming takes nothing returns nothing
    local trigger T = CreateTrigger(  )

    call TriggerRegisterAnyUnitEventBJ( T, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( T, Condition( function Trig_Farming_Conditions ) )
    set T = null

    set gg_trg_Farming = CreateTrigger(  )
    call DisableTrigger( gg_trg_Farming )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Farming, 1.00 )
    call TriggerAddCondition( gg_trg_Farming, Condition(function Trig_gG_Actions ))
endfunction

Not many people have good comments about the code itself because you're doing a nice job. What I would recommend doing is learning vJass because it seems you have a pretty decent grasp of jass and could benefit from it based on the code I've seen.

You should also look into inlining BJ functions - for example you could use TriggerRegisterTimerEvent() in this case.

One last thing - look into JESP (and I think there is a newer) standards to practice making your code maintainable.

Cheers and good luck.
 
Level 7
Joined
Jan 28, 2012
Messages
266
question wouldn't putting set bj_wantDestroyGroup = true
in front of say
set n1 CountUnitsInGroup( udg_GrainPlanting[i]) destroy udg_GrainPlanting?

I could use a link or example for a better method of counting units in a group, with out destroying the group.
as the way i would do it would be ForGroup(somegroup, function Count) where function count is just a counter
 

Cokemonkey11

Spell Reviewer
Level 30
Joined
May 9, 2006
Messages
3,537
question wouldn't putting set bj_wantDestroyGroup = true
in front of say
set n1 CountUnitsInGroup( udg_GrainPlanting[i]) destroy udg_GrainPlanting?

I could use a link or example for a better method of counting units in a group, with out destroying the group.
as the way i would do it would be ForGroup(somegroup, function Count) where function count is just a counter


bj_wantDestroyGroup only destroys the next group initialized in a BJ function (those functions immediately set it back to false IIRC)

If you want to learn about better group enumeration, read about FirstOfGroup() loops, which apparently is the most efficient method since the 1.24 patch. Let me know if you want more info on that.

Edit: About your farming loop:

use better variable names. U for GetSpellTargetUnit is so much worse than targetU. targetUserData is much better than i.

boolean expressions evaluate wholistically. So, for example you could change:
IsUnitGroup(me,udg_GW)==true
into
IsUnitGroup(me,udg_GW)

and you'll get the same effect.

call UnitAddItemSwapped( UnitItemInSlot(me, Li), U )

can be inlined with UnitAddItem()
 
Last edited:
Status
Not open for further replies.
Top