• 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.

Life Drain Neutralise

Status
Not open for further replies.
Level 16
Joined
Mar 27, 2011
Messages
1,349
I'm using the Life Drain ability to allow one unit to channel health into another unit. That works, but I have one problem. The unit is transferring his own life to heal the other unit. How can I nullify the damage done?

Using Bribe's damage detection system, this is what I have done so far:

  • Heal Station
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • DamageEventSource Equal to DamageEventTarget
    • Actions
      • Unit - Set life of DamageEventSource to ((Life of DamageEventSource) + 20.00)
      • Game - Display to (All players) for 1.00 seconds the text: run
Not sure how to properly use the system. Any help please?
 
Level 26
Joined
Aug 18, 2009
Messages
4,099
Why not just use Channel (ANcl) and trigger the healing part?

The damage event occurs before the damage is dealt, so for instance the unit cannot reach max health because SetLife gets truncated and then the damage follows. I am not sure if LifeDrain triggers the damage event at all since this initially is not meant to damage the caster nor a non-ally-targeted ability in that aspect. Does the message appear? For ways to nullify the damage you can search around the forums for "Shield" implementations.
 
Level 16
Joined
Mar 27, 2011
Messages
1,349
Ok, I've triggered it like you suggested but I've encountered another problem. Here are my triggers:

  • Heal Station Detect
    • Events
      • Time - Every 0.75 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in HealingStationGroup and do (Actions)
        • Loop - Actions
          • Set TempUnit = (Picked unit)
          • Set TempPoint = (Position of TempUnit)
          • Set Temp_Unit_Group = (Units within 300.00 of TempPoint)
          • Unit Group - Pick every unit in Temp_Unit_Group and do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Owner of (Picked unit)) is in Players) Equal to True
                  • ((Picked unit) is A structure) Equal to False
                • Then - Actions
                  • Unit - Order TempUnit to Neutral Dark Ranger - Life Drain (Random unit from Temp_Unit_Group)
                • Else - Actions
          • Set TempUnit = No unit
          • Custom script: call RemoveLocation (udg_TempPoint)
      • Custom script: call DestroyGroup (udg_Temp_Unit_Group)
  • Heal Station Effect
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Life Drain (Neutral Hostile)
    • Actions
      • Set HealingStationIndex = (HealingStationIndex + 1)
      • Set HealingStationPoint1[HealingStationIndex] = (Position of (Triggering unit))
      • Set HealingStationUnit[HealingStationIndex] = (Target unit of ability being cast)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • HealingStationIndex Equal to 1
        • Then - Actions
          • Trigger - Turn on Heal Station Loop <gen>
        • Else - Actions
  • Heal Station Loop
    • Events
      • Time - Every 0.25 seconds of game time
    • Conditions
    • Actions
      • For each (Integer HealingStationLoopInteger) from 1 to HealingStationIndex, do (Actions)
        • Loop - Actions
          • Set HealingStationPoint2[HealingStationLoopInteger] = (Position of HealingStationUnit[HealingStationLoopInteger])
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Percentage life of HealingStationUnit[HealingStationLoopInteger]) Less than 100.00
              • (Distance between HealingStationPoint1[HealingStationLoopInteger] and HealingStationPoint2[HealingStationLoopInteger]) Less than or equal to 300.00
            • Then - Actions
              • Unit - Set life of HealingStationUnit[HealingStationLoopInteger] to ((Life of HealingStationUnit[HealingStationLoopInteger]) + 1.00)
              • Custom script: call RemoveLocation( udg_HealingStationPoint2[udg_HealingStationLoopInteger])
            • Else - Actions
              • Set HealingStationUnit[HealingStationLoopInteger] = HealingStationUnit[HealingStationIndex]
              • Set HealingStationUnit[HealingStationIndex] = No unit
              • Custom script: call RemoveLocation( udg_HealingStationPoint1[udg_HealingStationLoopInteger])
              • Set HealingStationPoint1[HealingStationLoopInteger] = HealingStationPoint1[HealingStationIndex]
              • Custom script: set udg_HealingStationPoint1[udg_HealingStationIndex] = null
              • Set HealingStationIndex = (HealingStationIndex - 1)
              • Set HealingStationLoopInteger = (HealingStationLoopInteger - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • HealingStationIndex Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
The problem is that when two units come in range of the Healing Station, the Healing station starts healing a new unit before finishing healing the first unit. So the healing station has the Life Drain graphics on 1 unit, but could actually be healing 2 at the same time.

I need to stop the Healing station picking new units before its done healing its current one. Its ok if the player manually selects a new unit to heal, as long as the old one stops being healed. Not sure how to do it
 
Level 26
Joined
Aug 18, 2009
Messages
4,099
For preventing auto-reordering, you filter the unit checking its current order or you mark it yourself during the channeling. You should actually capture the end of casting (when the order is lost), not only what you did in "Heal Station Loop" there.

For overwriting the last instance, well one option is to simply deallocate the last when you request a new one. In any case you need to assign the instance to the caster to be able to check for it.
 
Level 16
Joined
Mar 27, 2011
Messages
1,349
I dunno, just cant seem to get it to work. I can't seem to remove the Buff from a unit that has been deindexed (I used buffs to "mark" the unit as you suggested). Also, manually using the ability causes a deindex to occur!

Not sure if there is a simple fix or if I have to restart with a new approach...Maybe I can have the healing station neutral passive so theres no manual use of the ability. That might make things easier...?

  • Heal Station Detect
    • Events
      • Time - Every 0.75 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in HealingStationGroup and do (Actions)
        • Loop - Actions
          • Set TempUnit = (Picked unit)
          • Set TempPoint = (Position of TempUnit)
          • Set Temp_Unit_Group = (Units within 300.00 of TempPoint)
          • Unit Group - Pick every unit in Temp_Unit_Group and do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Percentage life of (Picked unit)) Less than 100.00
                  • ((Owner of (Picked unit)) is in Players) Equal to True
                  • ((Picked unit) is A structure) Equal to False
                  • ((Picked unit) is alive) Equal to True
                  • (Current order of TempUnit) Not equal to (Order(drain))
                  • ((Picked unit) has buff Healing (Dummy)) Equal to False
                • Then - Actions
                  • Game - Display to (All players) for 3.00 seconds the text: unit detected
                  • Unit - Order TempUnit to Neutral Dark Ranger - Life Drain (Random unit from Temp_Unit_Group)
                • Else - Actions
          • Set TempUnit = No unit
          • Custom script: call RemoveLocation (udg_TempPoint)
      • Custom script: call DestroyGroup (udg_Temp_Unit_Group)
  • Heal Station Index
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Life Drain (Neutral Hostile)
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Target unit of ability being cast) has buff Healing (Dummy)) Equal to True
        • Then - Actions
          • Unit - Order (Triggering unit) to Stop
        • Else - Actions
          • Unit - Order Dummy Frog 0041 <gen> to Human Sorceress - Slow (Target unit of ability being cast)
          • Game - Display to (All players) for 3.00 seconds the text: Indexed
          • Set HealingStationIndex = (HealingStationIndex + 1)
          • Set HealingStationPoint1[HealingStationIndex] = (Position of (Triggering unit))
          • Set HealingStationUnit[HealingStationIndex] = (Target unit of ability being cast)
          • Set HealingStationCaster[HealingStationIndex] = (Triggering unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • HealingStationIndex Equal to 1
            • Then - Actions
              • Trigger - Turn on Heal Station Loop <gen>
            • Else - Actions
  • Heal Station Deindex
    • Events
      • Unit - A unit Stops casting an ability
    • Conditions
      • (Ability being cast) Equal to Life Drain (Neutral Hostile)
    • Actions
      • Game - Display to (All players) for 3.00 seconds the text: Deindexed
      • For each (Integer HealingStationLoopInteger) from 1 to HealingStationIndex, do (Actions)
        • Loop - Actions
          • Unit - Remove Healing (Dummy) buff from HealingStationUnit[HealingStationLoopInteger]
          • Set HealingStationUnit[HealingStationLoopInteger] = HealingStationUnit[HealingStationIndex]
          • Set HealingStationUnit[HealingStationIndex] = No unit
          • Set HealingStationCaster[HealingStationLoopInteger] = HealingStationCaster[HealingStationIndex]
          • Set HealingStationCaster[HealingStationIndex] = No unit
          • Custom script: call RemoveLocation( udg_HealingStationPoint1[udg_HealingStationLoopInteger])
          • Set HealingStationPoint1[HealingStationLoopInteger] = HealingStationPoint1[HealingStationIndex]
          • Custom script: set udg_HealingStationPoint1[udg_HealingStationIndex] = null
          • Set HealingStationIndex = (HealingStationIndex - 1)
          • Set HealingStationLoopInteger = (HealingStationLoopInteger - 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • HealingStationIndex Equal to 0
            • Then - Actions
              • Trigger - Turn off Heal Station Loop <gen>
            • Else - Actions
  • Heal Station Loop
    • Events
      • Time - Every 0.25 seconds of game time
    • Conditions
    • Actions
      • For each (Integer HealingStationLoopInteger) from 1 to HealingStationIndex, do (Actions)
        • Loop - Actions
          • Set HealingStationPoint2[HealingStationLoopInteger] = (Position of HealingStationUnit[HealingStationLoopInteger])
          • Unit - Set life of HealingStationUnit[HealingStationLoopInteger] to ((Life of HealingStationUnit[HealingStationLoopInteger]) + 1.00)
          • Custom script: call RemoveLocation( udg_HealingStationPoint2[udg_HealingStationLoopInteger])
To clarify: I want a building (Healing Station) to channel health to a nearby allied unit. The Healing Station can only heal 1 unit at a time, and any unit can only be healed by 1 Healing Station at a time. Needs to be MUI because there can be seveal healing stations at a given time.
 
Level 26
Joined
Aug 18, 2009
Messages
4,099
You should not deallocate every instance when the casting stops but only the one connected to the caster. I am seeing that the indexing/deindexing method is off. You simply count up and down like in a LIFO storage but you cannot expect that the instances follow this rule. Ex: Create 3 instances, cancel the first one, then instance 3 gets killed instead.

  • init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set table = (Last created hashtable)
  • start
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Life Restoration
    • Actions
      • Custom script: set udg_targetId = GetHandleId(GetSpellTargetUnit())
      • Set index = (Load 1 of targetId from table)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • index Unequal to 0
        • 'THEN'-Actions
          • Unit - Order attr_caster[index] to Stop
        • 'ELSE'-Actions
      • -------- - --------
      • Set index = alloc_cur
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • alloc_cur Equal to 0
        • 'THEN'-Actions
          • Set alloc_max = (alloc_max + 1)
          • Set index = alloc_max
        • 'ELSE'-Actions
          • Set alloc_cur = alloc_recycled[index]
      • Set alloc_recycled[index] = -1
      • Game - Display to (All players) the text: (alloc + (String(index)))
      • -------- - --------
      • Set allC = (allC + 1)
      • Set all[allC] = index
      • Set attr_allIndex[index] = allC
      • -------- - --------
      • Custom script: set udg_casterId = GetHandleId(GetTriggerUnit())
      • Hashtable - Save index as 0 of casterId in table
      • Set attr_caster[index] = (Triggering unit)
      • Set attr_target[index] = (Target unit of ability being cast)
      • Set casterPt = (Position of attr_caster[index])
      • Set targetPt = (Position of attr_target[index])
      • Bolt - Create a Healing Wave - Primary lightning effect from source casterPt to target targetPt
      • Set attr_bolt[index] = (Last created lightning effect)
      • Custom script: call RemoveLocation(udg_casterPt)
      • Custom script: call RemoveLocation(udg_targetPt)
      • -------- - --------
      • Custom script: set udg_targetId = GetHandleId(GetSpellTargetUnit())
      • Hashtable - Save index as 1 of targetId in table
  • ending
    • Events
      • Unit - A unit Stops casting an ability
    • Conditions
      • (Ability being cast) Equal to Life Restoration
    • Actions
      • Custom script: set udg_casterId = GetHandleId(GetTriggerUnit())
      • Set index = (Load 0 of casterId from table)
      • -------- - --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • index Unequal to 0
          • alloc_recycled[index] Equal to -1
        • 'THEN'-Actions
          • Set alloc_recycled[index] = alloc_cur
          • Set alloc_cur = index
          • Game - Display to (All players) the text: (dealloc + (String(index)))
          • -------- - --------
          • Set all[attr_allIndex[index]] = all[allC]
          • Set attr_allIndex[all[allC]] = attr_allIndex[index]
          • Set allC = (allC - 1)
        • 'ELSE'-Actions
          • Game - Display to (All players) the text: (error: cannot deallocate + (String(index)))
          • Skip remaining actions
      • -------- - --------
      • Hashtable - Save 0 as 0 of casterId in table
      • Bolt - Destroy attr_bolt[index]
      • -------- - --------
      • Custom script: set udg_targetId = GetHandleId(udg_attr_target[udg_index])
      • Hashtable - Save 0 as 1 of targetId in table
  • updateGraphics
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer A) from 1 to allC, do (Actions)
        • Loop - Actions
          • Set iterateList[(Integer A)] = all[(Integer A)]
      • Set iterateListC = allC
      • -------- - --------
      • For each (Integer A) from 1 to iterateListC, do (Actions)
        • Loop - Actions
          • Set index = iterateList[(Integer A)]
          • -------- - --------
          • Set casterPt = (Position of attr_caster[index])
          • Set targetPt = (Position of attr_target[index])
          • Bolt - Move attr_bolt[index] to source casterPt and target targetPt
          • Custom script: call RemoveLocation(udg_casterPt)
          • Custom script: call RemoveLocation(udg_targetPt)
  • healing
    • Events
      • Time - Every 0.25 seconds of game time
    • Conditions
    • Actions
      • For each (Integer A) from 1 to allC, do (Actions)
        • Loop - Actions
          • Set iterateList[(Integer A)] = all[(Integer A)]
      • Set iterateListC = allC
      • -------- - --------
      • For each (Integer A) from 1 to iterateListC, do (Actions)
        • Loop - Actions
          • Set index = iterateList[(Integer A)]
          • -------- - --------
          • Special Effect - Create a special effect attached to the origin of attr_target[index] using Abilities\Spells\Human\HolyBolt\HolyBoltSpecialArt.mdl
          • Special Effect - Destroy (Last created special effect)
          • Unit - Set life of attr_target[index] to ((Leben of attr_target[index]) + 1.00)
And yes, it's all super ugly in GUI. I copied the allocation method from JassHelper. I did not know it by heart. Normally you write this one time, then simply import it/call the functions. Likewise for the data structures.

edit: There is still a mistake in between, fixing...

edit2: done
 
Last edited:
Level 16
Joined
Mar 27, 2011
Messages
1,349
I'm not that good at triggering and this is a bit alien to me but I've managed to copy it. It seems to work thanks, but one picky point. How do I check if a unit is already being healed?

When using this trigger:

  • Heal Station Detect
    • Events
      • Time - Every 0.75 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in HealingStationGroup and do (Actions)
        • Loop - Actions
          • Set TempUnit = (Picked unit)
          • Set TempPoint = (Position of TempUnit)
          • Set Temp_Unit_Group = (Units within 300.00 of TempPoint)
          • Unit Group - Pick every unit in Temp_Unit_Group and do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Percentage life of (Picked unit)) Less than 100.00
                  • ((Owner of (Picked unit)) is in Players) Equal to True
                  • ((Picked unit) is A structure) Equal to False
                  • ((Picked unit) is alive) Equal to True
                  • (Current order of TempUnit) Not equal to (Order(drain))
                • Then - Actions
                  • Game - Display to (All players) for 3.00 seconds the text: unit detected
                  • Unit - Order TempUnit to Neutral Dark Ranger - Life Drain (Random unit from Temp_Unit_Group)
                • Else - Actions
          • Set TempUnit = No unit
          • Custom script: call RemoveLocation (udg_TempPoint)
      • Custom script: call DestroyGroup (udg_Temp_Unit_Group)
The towers keep challenging eachother as to who heals the unit and it keeps switching. Any workaround?
 
Level 16
Joined
Mar 27, 2011
Messages
1,349
Yes, this works as intended, but the problem lies in my detection trigger; "Heal Station Detect". If there are 2 healing towers and 1 unit to be healed, each tower seems to compete to heal the same unit and so one tower starts healing then the other takes over, and so on and so on. It's not a major bug, its merely a small graphical flaw. If there's no easy fix, its no biggy.

If there was a way to check if the unit was currently being healed, I could prevent other towers to not heal a target that's already being healed, but I'm not sure how.
 
Last edited:
Level 26
Joined
Aug 18, 2009
Messages
4,099
I did the marking already above.

  • Heal Station Detect
    • Events
      • Time - Every 0.75 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in HealingStationGroup and do (Actions)
        • Loop - Actions
          • Set TempUnit = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • 'IF'-Conditions
              • (Current order of TempUnit) Unequal to (Order(drain))
            • 'THEN'-Actions
              • Set TempPoint = (Position of TempUnit)
              • Set Temp_Unit_Group = (Units within 300.00 of TempPoint)
              • Custom script: call RemoveLocation(udg_TempPoint)
              • Unit Group - Pick every unit in Temp_Unit_Group and do (Actions)
                • Loop - Actions
                  • Custom script: set udg_targetId = GetHandleId(GetEnumUnit())
                  • Set index = (Load 1 of targetId from table)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • 'IF'-Conditions
                      • index Unequal to 0
                    • 'THEN'-Actions
                      • Unit Group - Remove (Picked unit) from Temp_Unit_Group
                    • 'ELSE'-Actions
              • Set TempUnit2 = (Random unit from Temp_Unit_Group)
              • Custom script: call DestroyGroup(udg_Temp_Unit_Group)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • 'IF'-Conditions
                  • TempUnit2 Unequal to Keine Einheit
                • 'THEN'-Actions
                  • Einheit - Order TempUnit to Neutral Dark Ranger - Life Drain TempUnit2
                • 'ELSE'-Actions
            • 'ELSE'-Actions
Maybe you should do an additional marking already when the order is given though because else multiple healing stations may try to initiate the casting of a new target that simulataneously enters their range. On the other hand there is no direct "unit loses order" event, so checking for that might be a bit of a hassle. An alternative is "begins casting".
 
Status
Not open for further replies.
Top