HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Storing and Adding Actions

10-04-2007, 02:15 PM#1
Strilanc
I am trying to make a small structure which will handle registering units and triggers for the Unit-takes-damage event. The idea is that whenever there are no damage event units left, the damage trigger is destroyed, recreated, and the 'actions' are added again.

The problem is that it works great... until the trigger is recreated. I've checked, and the code to re-add the actions IS being run. They just aren't being called when damage happens.

What am I doing wrong?

Collapse JASS:
//this is called at startup with functions that want "takes damage" calls
function registerForDamage takes code c returns nothing
  if (numDamageCode > MAX_DAMAGE_CALLBACKS) then
    call showMessage("Critical Map Error: too many callbacks for unit takes damage")
    return
  endif
  set numDamageCode = numDamageCode + 1
  set damageCode[numDamageCode] = Code2I(c)
  call TriggerAddAction(trigDamage, c)
endfunction

//Called for new runners
function addDamageEventUnit takes unit u returns nothing
  if (u != null and IsUnitInGroup(u, damageUnits) == false) then
    call GroupAddUnit(damageUnits, u)
    call TriggerRegisterUnitEvent(trigDamage, u, EVENT_UNIT_DAMAGED)
  endif
endfunction

//Called when runners die
function catchDeath takes nothing returns nothing
  local integer i
  local unit u = GetTriggerUnit()
  if (IsUnitInGroup(u, damageUnits)) then
    call GroupRemoveUnit(damageUnits, u)

    if (CountUnitsInGroup(damageUnits) == 0) then //guaranteed to happen when rounds end
      //recreate the damage trigger
      call DestroyTrigger(trigDamage)
      set trigDamage = CreateTrigger()
      set i = 1
      loop
        exitwhen i > numDamageCode
        call TriggerAddAction(trigDamage, I2Code(damageCode[i])) //<== doesn't work, action never called
        set i = i + 1
      endloop
    endif
  endif
endfunction
10-04-2007, 03:50 PM#2
cohadar
You cannot add more than one unit to the same UNIT_DAMAGE trigger.
10-04-2007, 05:37 PM#3
TaintedReality
It must be something with I2Code/Code2I. Why not just store the actions in a code array in the first place, instead of converting it back and forth?

Quote:
Originally Posted by cohadar
You cannot add more than one unit to the same UNIT_DAMAGE trigger.

What.....?
10-04-2007, 05:49 PM#4
Vexorian
Quote:
It must be something with I2Code/Code2I. Why not just store the actions in a code array in the first place, instead of converting it back and forth?
perhaps for the cause we cannot have code arrays...

I doubt the actions are failing to get added, first check the trigger is actually getting called... For example you can have a debug trigger that shows GetTriggerEvalCount(trigDamage) ...
10-04-2007, 05:51 PM#5
cohadar
Exactly like i said, let me repeat it.
You can NOT add more than one unit to the same UNIT_DAMAGE trigger.
10-04-2007, 06:24 PM#6
Anitarf
Quote:
Originally Posted by cohadar
Exactly like i said, let me repeat it.
You can NOT add more than one unit to the same UNIT_DAMAGE trigger.
What.....?
10-04-2007, 06:30 PM#7
cohadar
prove me wrong.
10-04-2007, 07:35 PM#8
blu_da_noob
If you mean adding more than one UNIT_DAMAGE event to the same trigger for different units, then yes you can. People have been doing it for ages.

So how about we put the onus on you. Triggers can have multiple events and people have used systems with multiple UNIT_DAMAGE events on the same trigger (hundreds of them, in fact). Upload a test map which proves you are right.
10-04-2007, 09:03 PM#9
cohadar
My bad,
had a bug in test map and made some wrong conclusions based on it.
10-04-2007, 10:30 PM#10
Strilanc
GetTriggerEvalCount(trigDamage) is returning the correct amounts, as if the trigger were being destroyed and firing appropriately. Furthermore, "TriggerAddAction" isn't returning null, so that should mean the action was added correctly.

At this point I am COMPLETELY confused.
10-04-2007, 10:55 PM#11
Strilanc
I think I have the problem worked out. If I add a "real" TriggerAddAction call, which is given a code argument of the form "function name", it works. To me, that suggests something is going wrong storing the handle to the code.

I would bet that WC3 tracks code handles much more closely than other types, and cleans it up without me realizing it. That makes my stored integers become incorrect, and the actions would then just get dropped when called.

In any case, I have a workaround: I separated my trigger into events and actions. I only need to destroy the events trigger, so there is no need to store the actions. This is arguably simpler than what I was originally doing.

Collapse JASS:
//called by trigDamageEvents, forwards to trigDamageActions
function catchDamage takes nothing returns nothing
  call ConditionalTriggerExecute(trigDamageActions)
endfunction

//Called when runners die
function catchDeath takes nothing returns nothing
  local integer i
  local unit u = GetTriggerUnit()
  if (IsUnitInGroup(u, damageUnits)) then
    call GroupRemoveUnit(damageUnits, u)

    if (CountUnitsInGroup(damageUnits) == 0) then //guaranteed to happen when rounds end
      //recreate the damage trigger
      call DestroyTrigger(trigDamageEvents)
      set trigDamageEvents = CreateTrigger()
      call TriggerAddAction(trigDamageEvents, function catchDamage) //call middle-man
    endif
  endif
endfunction

//this is called at startup with functions that want "takes damage" calls
function registerForDamage takes code c returns nothing
  call TriggerAddAction(trigDamageActions, c)
endfunction

//Called for new runners
function addDamageEventUnit takes unit u returns nothing
  if (u != null and IsUnitInGroup(u, damageUnits) == false) then
    call GroupAddUnit(damageUnits, u)
    call TriggerRegisterUnitEvent(trigDamageEvents, u, EVENT_UNIT_DAMAGED)
  endif
endfunction
10-04-2007, 11:02 PM#12
Vexorian
Quote:
I would bet that WC3 tracks code handles much more closely than other types, and cleans it up without me realizing it.

you know, this doesn't really make sense, when you consider that code is a constant type...

My bet would be

Collapse JASS:

   function I2Code takes integer i returns code
       return i
       return null
   endfunction

   function I2Code_Fix takes integer i returns code
     local code c=I2Code(i)
        return c
   endfunction


I've seen reals requiring this bridge thing for the return bugger to work correctly, else they really misbehave, so there's a chance the same happens with code.
10-04-2007, 11:05 PM#13
Strilanc
Quote:
Originally Posted by Vexorian
\I've seen reals requiring this bridge thing for the return bugger to work correctly, else they really misbehave, so there's a chance the same happens with code.

That makes more sense, since "function X" always seems to return the same thing.

In any case, the two-trigger work-around works, and it cuts the amount of code down, too.