HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Events taking unit variables.

01-15-2005, 07:04 AM#1
EdwardSwolenToe
Q. Is there a way to make unit events take unit variables instead of preplaced units? Ive tried with jass, although either my skills were poor (as they are) or i must do something else.
01-15-2005, 09:32 AM#2
Guest
Quote:
Originally Posted by EdwardSwolenToe
Q. Is there a way to make unit events take unit variables instead of preplaced units? Ive tried with jass, although either my skills were poor (as they are) or i must do something else.

Keep in mind that a unit event takes a unit, not a variable. If you use a unit variable, then whenever the variable changes its pointer to a different unit, the event stays the same regardless.

The event to use is,

call TriggerRegisterUnitEvent(yourTrigger, udg_unit, EVENT_UNIT_DAMAGED )

The above event is commonly used, and it takes the current value of udg_unit, and that value becomes a constant to the event which will not change, UNLESS you find a way to alter the memory location of the unit associated with the event itself.
01-15-2005, 09:50 AM#3
Guest
I think the best solution to this is to create triggers on the fly. If you just keep adding events to an existing trigger, you'll end up with events that you no longer want(like, for the old values of a variable).

I'll give an example. We're going to add a takes damage trigger for a unit that is attacked. This kind of trigger is very handy to check whether a unit takes damage from an attack of another unit.

We have two global variables: a Trigger udg_MyTrigger and a Unit udg_someVeryEvilUnit.

E.g.

Events
A Unit is Attacked
Condition
The AttackingUnit is <someVeryEvilUnit>
Actions
//Usually you want to destroy the old trigger
Custom Script: "DestroyTrigger(udg_MyTrigger)
//Make the new one
Custom Script: "set udg_Mytrigger = MakeMyTrigger(GetTriggerUnit)"


Then use the following Jass code:

Code:
function MTConditions takes nothing returns boolean
    if (GetEventDamageSource() == udg_someVeryEvilUnit) then
        return true
    else
        return false
    endif
endfunction

function MTActions takes nothing returns nothing
    call <Insert here what you want the trigger to do>
endfunction

function MakeMyTrigger takes unit target returns trigger
    local trigger mt = CreateTrigger()                   //Jass only
    call TriggerRegisterUnitEvent(mt, target, EVENT_UNIT_DAMAGED )
    call TriggerAddCondition(mt, Condition(function MTConditions))
    call TriggerAddAction(mt, function MTActions)
    return mt
endfunction

So, for your case, everytime you set the variable to something new, you'll have to rebuild the trigger for the new value. Even if it is for the same variable: as Arcanister mentioned, the value is filled in when the trigger is created, and every bound with the variable itself is removed.
01-15-2005, 09:24 PM#4
Vexorian
Quote:
Originally Posted by arcanister
Keep in mind that a unit event takes a unit, not a variable. If you use a unit variable, then whenever the variable changes its pointer to a different unit, the event stays the same regardless.

The event to use is,

call TriggerRegisterUnitEvent(yourTrigger, udg_unit, EVENT_UNIT_DAMAGED )

The above event is commonly used, and it takes the current value of udg_unit, and that value becomes a constant to the event which will not change, UNLESS you find a way to alter the memory location of the unit associated with the event itself.
The GUI 's trigger - add event action allows that.
01-16-2005, 01:11 PM#5
Shark
well, maybe the problem isn't as complex as it looks (no pun intended).... what kind of trigger are you trying to make ?
01-16-2005, 03:53 PM#6
Guest
In case somebody wants the trigger to initially have the event, then the GUI doesn't allow that. In most cases you have to call the function from somewhere to add the event, even though that makes no difference.
01-24-2005, 03:01 AM#7
EdwardSwolenToe
Ok im not the best jass person, but im not sure how to rebuild the trigger, because using the add event action doesnt get rid of the previous actions.

What im trying to do is create a shield in a way, that whenever the unit is damaged, it is healed by the same amount, therfore 'blocking' damage. I need to know either how to remove events or rebuild the trigger.
01-24-2005, 05:53 AM#8
Guest
A recent spell, Defensive Matrix, in wc3sear.ch does that, go get it. There is a bug, but since the maker didn't response I won't help fix it.
01-24-2005, 07:15 AM#9
EdwardSwolenToe
Hey cool that spell is credited to me :D w00t. I thought that matrix model was useless.

But that would take the easy way out. I need to know how to make this.

Well ive followed the the second one, but im not sure about the function, this is what i have now.

Code:
Trig_Distortion_Shield_Copy_Conditions takes nothing returns boolean
    if ( not ( GetEventDamage() > 0.00 ) ) then
        return false
    endif
    return true
endfunction

function Trig_Distortion_Shield_Copy_Actions takes nothing returns nothing
    call SetUnitLifeBJ( udg_ShieldUnit, ( GetUnitStateSwap(UNIT_STATE_LIFE, udg_ShieldUnit) + ( GetEventDamage() + 3.00 ) ) )
    set udg_ShieldDmg = ( udg_ShieldDmg + RAbsBJ(GetEventDamage()) )
    call DisplayTextToForce( GetPlayersAll(), R2S(GetEventDamage()) )
endfunction

//===========================================================================
function InitTrig_Distortion_Shield_Copy takes nothing returns nothing
function MakeMyTrigger takes unit target returns trigger
    local trigger udg_ShieldTrig = CreateTrigger()
    call TriggerRegisterUnitEvent(Trig_Distortion_Shield_Copy, udg_ShieldUnit, EVENT_UNIT_DAMAGED )
    call TriggerAddCondition( Trig_Distortion_Shield_Copy, Condition( function Trig_Distortion_Shield_Copy_Conditions ) )
    call TriggerAddAction (Trig_Distortion_Shield_Copy, function Trig_Distortion_Shield_Copy_Actions)
    return Trig_Distortion_Shield_Copy
endfunction
01-24-2005, 11:17 PM#10
EdwardSwolenToe
Code:
function Trig_Shield_Cast_Copy_Conditions takes nothing returns boolean
   if ( not ( GetSpellAbilityId() == 'A01P' ) ) then
       return false
   endif
   return true
endfunction

function Damage takes nothing returns nothing

call SetUnitLifeBJ( udg_ShieldUnit, ( GetUnitStateSwap(UNIT_STATE_LIFE, udg_ShieldUnit) + GetEventDamage() ) )
endfunction

function Shield_Actions takes nothing returns nothing

   local unit udg_ShieldUnit
   local trigger udg_ShieldTrig
   
   set udg_ShieldUnit = GetSpellTargetUnit()
   set udg_ShieldTrig = CreateTrigger()
   call TriggerRegisterUnitEvent(udg_ShieldTrig, udg_ShieldUnit, EVENT_UNIT_DAMAGED)
   call TriggerAddAction(udg_ShieldTrig, function Damage)
   call DestroyEffectBJ( udg_ShieldSFX )
   call AddSpecialEffectTargetUnitBJ( "overhead", udg_ShieldUnit, "Abilities\\Spells\\Human\\ManaFlare\\ManaFlareTarget.mdl" )
   set udg_ShieldSFX = GetLastCreatedEffectBJ() 
endfunction

//===========================================================================
function InitTrig_Shield_Cast_Copy takes nothing returns nothing
   set gg_trg_Shield_Cast_Copy = CreateTrigger(  )
   call TriggerRegisterAnyUnitEventBJ( gg_trg_Shield_Cast_Copy, EVENT_PLAYER_UNIT_SPELL_EFFECT )
   call TriggerAddCondition( gg_trg_Shield_Cast_Copy, Condition( function Trig_Shield_Cast_Copy_Conditions ) )
   call TriggerAddAction( gg_trg_Shield_Cast_Copy, function Shield_Actions )
endfunction

My first rather shaky attempt at jass. The Shield_Actions function goes off but it doesnt activate function Damage. In theory its supposed to make a new trigger called udg_ShieldTrig then set the unit for the damage event, then destroy it (ill destory it later i just gotta get it working for now) that way because of unit events taking variables.

It worked as GUI but the only problem is that i couldnt remove events so they would double up if cast on the same unit therfore healing the unit instead of givein it evens.

Anyone with jass experience can tell me what is wrong?
01-25-2005, 07:25 PM#11
Guest
udg_shieldunit was assigned as a local variable, and do NOT transfer between functions.

To transfer local variables between functions, you have to either make use of global variables, or gamecache. In this case, you need to use gamecache. A few gamecache examples I know are the spell Omni Drain, and Defensive Matrix which are both in wc3sear.ch. Defens Matrix is a little harder to read because the maker made a number of dummy call functions.