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

[JASS] Destructable -EVENT_ATTACKED-

Status
Not open for further replies.
Level 24
Joined
Aug 1, 2013
Messages
4,658
Make an ability based of Channel or Eat Tree or stuff like that and you will be able to cast it on destructables.
With channel there is one problem that the destructables have to be selectable to be targeted.

In any case, that is the only way how you can use events for when a unit interacts with a destructable.
You would have to replace the attacks with customized spells to make it look the same and then destroy the destructable with triggers.

Another method would be to not use destructables and use units (probably buildings) to replace them.
 
Level 16
Joined
Sep 29, 2008
Messages
366
use function GetOrderTargetDestructable() in conjuntion with the event EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER.

wierd trigger sample:


JASS:
function TCondition takes nothing returns boolean
 return GetDestructableTypeId(GetOrderTargetDestructable())==YOUR_DESTRUCTABLE_TYPE_ID
//Also you can check GetOrderTargetDestructable()==YOUR_DESTRUCTABLE
endfunction

function TActions takes nothing returns nothing
   local unit u = GetTriggerUnit()
   local destructable d = GetOrderTargetDestructable()

  if (condition) then //Code to check if unit is allowed to attack the destructable if not then 
     call IssueInmediateOrder (u,"stop")
  endif

 set u = null //clean local var
 set d = null

endfunction


function InitAttackedDestructableTrigger takes nothing returns nothing
 local trigger DestructableTrigger = CreateTrigger( )
 local integer index = 0

 loop
  exitwhen index> bj_MAX_PLAYER_SLOTS
   call TriggerRegisterPlayerUnitEvent(DestructableTrigger, Player(index),EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, null )
  set index = index + 1
 endloop 
 
 call TriggerAddCondition(DestructableTrigger, Condition(function TCondition))
 call TriggerAddAction(DestructableTrigger, function TActions)

 set DestructableTrigger = null //local var clean
endfunction

There could have better ways to attach actions to a destructable, but this one is very usefull for me. I hope It helps you.
edit: I posted another response. fixed now - Forget to add triggeractions to DestructableTrigger (fixed)
So another usefull function is GetTriggerDestructable()
 
Last edited:
Level 24
Joined
Aug 1, 2013
Messages
4,658
There are two ways to do this... and neither are really working 100% glitchless.

One way which already has been said is to pause the unit, order it and unpause it, which basically has a weird result.
Or you add a very small delay, which is also mentioned before... however in a not really nice way.

In the second way, you would have to create a new timer, store the unit and order on the timer, start the timer and order the unit when the timer expires... this is a pain to do every single time and you will 100% forget something now and then.

However, I prefer that way and have written a nice thing that makes me be able to delay the order of the 3 most used IssueOrder functions.
It uses TimerUtils and a small library that I wrote that makes a unique index for it.
(How I make a new index in that library is discussable and I should have made that in textmacros so you can have one for each thing that you desire but who the hell cares.)
JASS:
library TimerIndex uses TimerUtils
//*********************************************************************
//* TimerIndex 1.0
//* ----------
//*
//*  This library creates a unique index for the TimerData of timerUtils.
//*  A timer that is created with an index must also be released as an indexed timer.
//*
    
    globals
        integer udg_NextTimerIndex = 0
        boolean array udg_TimerIndex_Occupied
    endglobals
    
    function ReleaseIndexedTimer takes timer t returns nothing
        set udg_TimerIndex_Occupied[GetTimerData(t)] = false
        call ReleaseTimer(t)
    endfunction
    function NewIndexedTimer takes nothing returns timer
        loop
            set udg_NextTimerIndex = udg_NextTimerIndex + 1
            if udg_NextTimerIndex > 8190 then
                set udg_NextTimerIndex = 1
            endif
            
            exitwhen not udg_TimerIndex_Occupied[udg_NextTimerIndex]
        endloop
        
        set udg_TimerIndex_Occupied[udg_NextTimerIndex] = true
        return NewTimerEx(udg_NextTimerIndex)
    endfunction
    
endlibrary
JASS:
library DelayedOrder uses TimerIndex
    
    globals
        
        unit array      udg_DelayedOrder_WhichUnit
        integer array   udg_DelayedOrder_OrderId
        real array      udg_DelayedOrder_TargetPoint_X
        real array      udg_DelayedOrder_TargetPoint_Y
        widget array    udg_DelayedOrder_TargetWidget
        
    endglobals
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    function IssueImmediateOrderByIdCallback takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer id = GetTimerData(t)
        call ReleaseIndexedTimer(t)
        
        call IssueImmediateOrderById(udg_DelayedOrder_WhichUnit[id], udg_DelayedOrder_OrderId[id])
        set udg_DelayedOrder_WhichUnit[id] = null
        set udg_DelayedOrder_OrderId[id] = 0
    endfunction
    function IssueImmediateOrderByIdDelayed takes unit whichUnit, integer order, real delay returns nothing
        local timer t = NewIndexedTimer()
        local integer id = GetTimerData(t)
        
        set udg_DelayedOrder_WhichUnit[id] = whichUnit
        set udg_DelayedOrder_OrderId[id] = order
        
        call TimerStart(t, delay, false, function IssueImmediateOrderByIdCallback)
        set t = null
    endfunction
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    function IssuePointOrderByIdCallback takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer id = GetTimerData(t)
        call ReleaseIndexedTimer(t)
        
        call IssuePointOrderById(udg_DelayedOrder_WhichUnit[id], udg_DelayedOrder_OrderId[id], udg_DelayedOrder_TargetPoint_X[id], udg_DelayedOrder_TargetPoint_Y[id])
        set udg_DelayedOrder_WhichUnit[id] = null
        set udg_DelayedOrder_OrderId[id] = 0
        set udg_DelayedOrder_TargetPoint_X[id] = 0.
        set udg_DelayedOrder_TargetPoint_Y[id] = 0.
    endfunction
    function IssuePointOrderByIdDelayed takes unit whichUnit, integer order, real x, real y, real delay returns nothing
        local timer t = NewIndexedTimer()
        local integer id = GetTimerData(t)
        
        set udg_DelayedOrder_WhichUnit[id] = whichUnit
        set udg_DelayedOrder_OrderId[id] = order
        set udg_DelayedOrder_TargetPoint_X[id] = x
        set udg_DelayedOrder_TargetPoint_Y[id] = y
        
        call TimerStart(t, delay, false, function IssuePointOrderByIdCallback)
        set t = null
    endfunction
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    function IssueTargetOrderByIdCallback takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer id = GetTimerData(t)
        call ReleaseIndexedTimer(t)
        
        call IssueTargetOrderById(udg_DelayedOrder_WhichUnit[id], udg_DelayedOrder_OrderId[id], udg_DelayedOrder_TargetWidget[id])
        set udg_DelayedOrder_WhichUnit[id] = null
        set udg_DelayedOrder_OrderId[id] = 0
        set udg_DelayedOrder_TargetWidget[id] = null
    endfunction
    function IssueTargetOrderByIdDelayed takes unit whichUnit, integer order, widget targetWidget, real delay returns nothing
        local timer t = NewIndexedTimer()
        local integer id = GetTimerData(t)
        
        set udg_DelayedOrder_WhichUnit[id] = whichUnit
        set udg_DelayedOrder_OrderId[id] = order
        set udg_DelayedOrder_TargetWidget[id] = targetWidget
        
        call TimerStart(t, delay, false, function IssueTargetOrderByIdCallback)
        set t = null
    endfunction
    
endlibrary

The basic difference is that you change
IssueImmediateOrderById
into
IssueImmediateOrderByIdDelayed
(You add "Delayed" to the function call.)

and
(myUnit, myOrder)
into
(myUnit, myOrder, 12.34)
(You add a real variable at the end defining the duration of the timer. This is recommended to not use a value below 0.)

Be aware that this uses the integer value of your order.
To convert the string to the integer, you use OrderId("stop") (where stop is your order string).

You can however just write another snippet that takes all order strings that you want to have as integer variables and generate their values at map initialization.
This is something that I use often.
JASS:
globals
    
    integer ORDER_STOP
    integer ORDER_ATTACK
    integer ORDER_MOVE
    integer ORDER_SMART
    
endglobals

//===========================================================================
function InitTrig_OrderIds takes nothing returns nothing
    
    set ORDER_STOP = OrderId("stop")
    set ORDER_ATTACK = OrderId("attack")
    set ORDER_MOVE = OrderId("move")
    set ORDER_SMART = OrderId("smart")
    
endfunction
Ofcourse, you can add your own stuff in here.
(Be aware that you don't break OP limit with these things so having a timer started at init and set the orders when that timer expires will help a lot... however, be sure that you initialize them before you try to use them.)

One last thing though... "Post Quick Reply"... Quick my ass.
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
DSG means that you get a slightly delay which is in some cases enough to complete the order which is kind of not what you want...
Or when you try to move the unit, he will still move for 0.15 seconds every time you right click... which means that if you spamm it, your unit will just walk "normally".
 
Status
Not open for further replies.
Top