• 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.
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!
  • ✅ The POLL for Hive's Texturing Contest #34 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!
  • ✅ The POLL for Hive's Techtree Contest #20 is OPEN! Vote for the TOP 3 FACTIONS! 🔗Click here to cast your vote!

How to make Orb of Darkness stackable with life-stealing effects?

Hello. I got a problem. I really want orb of darkness to be stackable with life-steal effects. Is there anyway to do it by triggerings or something else? Pls help!
Lifesteal is an Unique Attack Modifier (Orb Effect) and multiple orb effects don't work. However you can use Damage Engine to make a custom lifesteal mechanic which works with Orb of Darkness.
 
Lifesteal is an Unique Attack Modifier (Orb Effect) and multiple orb effects don't work. However you can use Damage Engine to make a custom lifesteal mechanic which works with Orb of Darkness.
Hmm but actually some orb-effects works with life-steal. Like "Envenomed Spears" and "Frost Attack". There must be some easy way to do a triggered "Orb of Darkness"? And I don't know much about Damage Engine :(
 
Hmm but actually some orb-effects works with life-steal. Like "Envenomed Spears" and "Frost Attack". There must be some easy way to do a triggered "Orb of Darkness"? And I don't know much about Damage Engine :(
One way to trigger it is to find an ability that casts a buff when the hero/unit deals damage to an enemy target. Like you mentioned, Frostguard's (the item) slow works with Mask of Death's lifesteal (essentially with all orb effect abilities separately). I'm not sure if you can edit the sword's ability to not slow or if it's hardcoded. The point is if you find an ability that casts a buff when hitting a target, you can simply trigger said target on death to create a unit (skeleton?) for you if the dying unit has that particular buff on it.

If you'd use 1.32+ game versions you'd already have a GUI inbuilt damage detection system and it would be super easy. You could add a buff on the target on damage dealt/hit via trigger or by making a dummy unit cast it through a spell. The latter can have the buff duration in the object editor while the first needs to be triggered.
 
One way to trigger it is to find an ability that casts a buff when the hero/unit deals damage to an enemy target. Like you mentioned, Frostguard's (the item) slow works with Mask of Death's lifesteal (essentially with all orb effect abilities separately). I'm not sure if you can edit the sword's ability to not slow or if it's hardcoded. The point is if you find an ability that casts a buff when hitting a target, you can simply trigger said target on death to create a unit (skeleton?) for you.
If you'd use 1.32+ game versions you'd already have a GUI inbuilt damage detection system and it would be super easy. You could add a buff on the target on damage dealt/hit via trigger or by making a dummy unit cast it through a spell. The latter can have the buff duration in the object editor while the first needs to be triggered.
Well "Envenomed Spears" casts a buff on enemy targets when attacking them and you can also get rid of the slow-effect from it too and it stacks with life-stealing effects so maybe using "Envenomed Spears" ability is a good idéa? Btw I have no idéa how to trigger it and would be happy if someone could make a spellpack map for me.
 
Hmm but actually some orb-effects works with life-steal. Like "Envenomed Spears" and "Frost Attack". There must be some easy way to do a triggered "Orb of Darkness"? And I don't know much about Damage Engine :(
You don't need to know about Damage Engine. Use
  • Game - DamageModifierEvent becomes Equal to 1.00
for events, use
  • IsDamageSpell Equal to False
for conditions and use
  • Unit - Set life of DamageEventSource to ((Life of DamageEventSource) + (DamageEventAmount x LifestealPercentage))
for actions
 
Well "Envenomed Spears" casts a buff on enemy targets when attacking them and you can also get rid of the slow-effect from it too and it stacks with life-stealing effects so maybe using "Envenomed Spears" ability is a good idéa? Btw I have no idéa how to trigger it and would be happy if someone could make a spellpack map for me.
It's quite simple really.
Make a copy of envenomed spears and name it orb of darkness or whatever. Then make a copy of the envenomed spears buff and rename it how you want and add it/replace it in the copy of envenomed spears ability.
Then in the trigger editor do something like this:
Event: A unit dies
Condition: Unit has buff copy of envenomed spears
Action: Create 1 [desired] unit for player [?] at point [position of dying unit]

Don't forget to clean leaks. First, before the create unit action, make a point variable and name it something like OrbOfDarknessDyingUnitPoint (could be much shorter ofc) and set it as OrbOfDarknessDyingUnitPoint=position of dying unit. Then after the unit creation action, remove it via the custom trigger Custom script: call RemoveLocation(udg_Location) where udg_Location would be udg_OrbOfDarknessDyingUnitPoint.
So instead of Action: Create 1 [desired] unit for player [?] at point [position of dying unit], you'll have Action: Create 1 [desired] unit for player [?] at point [OrbOfDarknessDyingUnitPoint].
 
It's quite simple really.
Make a copy of envenomed spears and name it orb of darkness or whatever. Then make a copy of the envenomed spears buff and rename it how you want and add it/replace it in the copy of envenomed spears ability.
Then in the trigger editor do something like this:
Event: A unit dies
Condition: Unit has buff copy of envenomed spears
Action: Create 1 [desired] unit for player [?] at point [position of dying unit]

Don't forget to clean leaks. First, before the create unit action, make a point variable and name it something like OrbOfDarknessDyingUnitPoint (could be much shorter ofc) and set it as OrbOfDarknessDyingUnitPoint=position of dying unit. Then after the unit creation action, remove it via the custom trigger Custom script: call RemoveLocation(udg_Location) where udg_Location would be udg_OrbOfDarknessDyingUnitPoint.
So instead of Action: Create 1 [desired] unit for player [?] at point [position of dying unit], you'll have Action: Create 1 [desired] unit for player [?] at point [OrbOfDarknessDyingUnitPoint].
I did it like this but it doesn't work. No unit is summoned :(
  • Orb of the Valar
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Dying unit) has buff Orb of the Valar ) Equal to True
    • Actions
      • Set VariableSet Summon_Point = (Position of (Dying unit))
      • Unit - Create 1 Weak Gondor Swordsman for (Owner of (Killing unit)) at Summon_Point facing Default building facing degrees
      • Unit - Add classification of Summoned to (Last created unit)
      • Unit - Add a 30.00 second Generic expiration timer to (Last created unit)
      • Custom script: call RemoveLocation( udg_Summon_Point )
 
I did it like this but it doesn't work. No unit is summoned :(
It's great that you did it on your own! Would you mind sharing the map for debugging? If not publicly, via a p.m.? It should work so I'm not sure what the cause is, possibly related to the buff or something.
By the way, does the buff appear on the enemy unit?
 
Well "Envenomed Spears" casts a buff on enemy targets when attacking them and you can also get rid of the slow-effect from it too and it stacks with life-stealing effects so maybe using "Envenomed Spears" ability is a good idéa? Btw I have no idéa how to trigger it and would be happy if someone could make a spellpack map for me.
 

Attachments

OK, so since without a detection system, dying units lose their buff (i.e. the buff can no longer be checked because the unit is dead), a crappy solution is to simply put the condition Killing unit has item of type Orb of Valar. This however is not chance based so, the spawning of the minion will happen every time an enemy dies. To make it happen only on enemies add the condition: Dying unit is an enemy of player (owner of killing unit).

EDIT: To make it chance based you could add another crappy condition: random number between 1 and 2 is 1 then the trigger fires. If it's 2 it doesn't. That means 50/50 chance.

EDIT2: What I meant was...
  • Orb of the Valar
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Killing unit) has an item of type |c00ff8040Orb of the Valar|r) Equal to True
      • ((Dying unit) belongs to an enemy of (Owner of (Killing unit)).) Equal to True
    • Actions
      • Set VariableSet OrbOfValarChanceInteger = (Random integer number between 1 and 2)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • OrbOfValarChanceInteger Equal to 1
        • Then - Actions
          • Set VariableSet Summon_Point = (Position of (Dying unit))
          • Unit - Create 1 Weak Gondor Swordsman for (Owner of (Killing unit)) at Summon_Point facing Default building facing degrees
          • Unit - Add classification of Summoned to (Last created unit)
          • Unit - Add a 30.00 second Generic expiration timer to (Last created unit)
          • Custom script: call RemoveLocation( udg_Summon_Point )
        • Else - Actions
 
Last edited:
Sry I don't understand. I don't want to trigger the life-steal effect pls because I don't want to life-steal effect to be stackable with other orbs like "orb of corruption". There must be a way to make so dying unit with specific buff create a unit for the killing unit if the killing unit has the specific item. I know I have an imported spell in my map that causes an explosion around the dying unit with the specific buff if it dies or if 10 sec has passed. But I don't understand the triggers because it is in JASS...
 
I really want orb of darkness to be stackable with life-steal effects. Is there anyway to do it by triggerings or something else?
You said "Is there anyway to do it by triggerings or something else?" but now you say:
I don't want to trigger the life-steal effect pls because I don't want to life-steal effect to be stackable with other orbs like "orb of corruption"
Without triggering, it is impossible.
Btw I have no idéa how to trigger it and would be happy if someone could make a spellpack map for me.
I uploaded the spellpack.
 
You said "Is there anyway to do it by triggerings or something else?" but now you say:

Without triggering, it is impossible.

I uploaded the spellpack.
Well what I actually mean is that I want a triggered version of "Orb of Darkness" but it seems to be very complicated to do because you have to have something to check if the attacked unit is alive or not and if it has the specific buff and the create the unit for the killing unit if it has the specific item. There should be a way to do it since I have a spell in my map that causes an explosion around a dying unit if it has a specific buff and damages nearby enemies. Here is the JASS triggers of that spell.
JASS:
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library NullBlast initializer Init uses LastOrder, SpellEvent, UnitIndexingUtils, UnitMaxState,/*
                                     */ TimerUtils, xecast, xepreload, TextTag
    
    // This spell ignores the time the hero takes to reach the cast point.
    // Achieving this without potentially breaking, requires some more sophisticated work,
    // since players could potentially abort the casting of the ability after SPELL_CAST has been reached.
    
    private keyword Data // DO NOT CHANGE!
    
    globals
        private constant    real                    TICK                                = 1./32 // interval to check for the buff BLINDNESS_DUMMY_BID
        
        private constant    integer                 LEARN_AID                           = 'A0QA' // Dummy Ability for learning interface
        private constant    integer                 CAST_AID                            = 'A0QC' // Dummy Ability for casting only
        private constant    integer                 DUMMY_AID                           = 'A0QB' // the mana cost of CAST_AID and DUMMY_AID must match // dummy ability for mana cost and cooldown
        private constant    string                  DUMMY_ORDER                         = "berserk"
        private constant    integer                 DUMMY_BID                           = 'B07S' // placed by DUMMY_AID on the caster
        
        private constant    integer                 BLINDNESS_DUMMY_AID                 = 'A0QD' // changes duration of spell and % to miss
        private constant    string                  BLINDNESS_DUMMY_ORDER               = "curse"
        private constant    integer                 BLINDNESS_DUMMY_BID                 = 'B07R' // placed by BLINDNESS_DUMMY_AID on the target unit
        
        private constant    string                  FX                                  = "war3mapImported\\CurseBolt.mdx" // blast effect
        private constant    string                  FX_ATTPT                            = "head"
        private             real            array   COOLDOWN                            // must match the cooldown time given in DUMMY_AID
        private             real            array   DAMAGE                              // damage dealt by the primary blast
        private             real            array   SECONDARY_DAMAGE                    // damage dealt by the secondary blast
        private constant    real                    SECONDARY_DAMAGE_AOE                = 300. // units in this area around the target get damaged when the spell ends
        private constant    boolean                 DAMAGE_FRIENDLY_UNITS               = false
        private constant    boolean                 DEBUFF_FRIENDLY_UNITS               = true
        private constant    attacktype              ATTACK_TYPE                         = ATTACK_TYPE_MAGIC
        private constant    damagetype              DAMAGE_TYPE                         = DAMAGE_TYPE_MAGIC
        private constant    weapontype              WEAPON_TYPE                         = WEAPON_TYPE_WHOKNOWS // sound effect when damaging
        private constant    weapontype              SECONDARY_WEAPON_TYPE               = WEAPON_TYPE_WHOKNOWS // sound effect when damaging through second blast
        private             real            array   STAT_TAKEN                          // max hp or max mana taken away for a period of time by this ability // values less than 1 turn this into a relative loss instead of an absolute
        private constant    unitstate               STAT_MODIFIED                       = UNIT_STATE_MAX_LIFE // either UNIT_STATE_MAX_LIFE or UNIT_STATE_MAX_MANA
        private constant    boolean                 SHOW_TT                             = true // should a texttag be shown
        private constant    string                  TT_PATTERN                          = "&d HP!" // place "&d" where the amount taken away should be (case insensitive)
        private constant    string                  TT_NEGATIVE_HP_BONUS_STRING         = "-"
        private constant    string                  TT_POSITIVE_HP_BONUS_STRING         = "+"
        private constant    string                  TT_COLOR                            = "|cffA00030" // color of the text in the texttag; standard WC3 formatting (|cAARRGGBB)
    endglobals
    
    // Cooldown
    private function SetUpCOOLDOWN takes nothing returns nothing
        set COOLDOWN[1]=12.
        set COOLDOWN[2]=12.
        set COOLDOWN[3]=12.
        set COOLDOWN[4]=12.
    endfunction
    
    private function Cooldown takes integer level returns real
        return COOLDOWN[level]
    endfunction
    
    // Damage
    private function SetUpDAMAGE takes nothing returns nothing
        set DAMAGE[1]=90.
        set DAMAGE[2]=140.
        set DAMAGE[3]=190.
        set DAMAGE[4]=240.
    endfunction
    
    private function Damage takes integer level returns real
        return DAMAGE[level]
    endfunction
    
    // Secondary Damage
    private function SetUpSECONDARY_DAMAGE takes nothing returns nothing
        set SECONDARY_DAMAGE[1]=100.
        set SECONDARY_DAMAGE[2]=125.
        set SECONDARY_DAMAGE[3]=150.
        set SECONDARY_DAMAGE[4]=175.
    endfunction
    
    private function Secondary_Damage takes integer level returns real
        return SECONDARY_DAMAGE[level]
    endfunction
    
    // HP Taken
    private function SetUpSTAT_TAKEN takes nothing returns nothing
        set STAT_TAKEN[1]=90.
        set STAT_TAKEN[2]=140.
        set STAT_TAKEN[3]=190.
        set STAT_TAKEN[4]=240.
    endfunction
    
    private function Stat_Taken takes integer level returns real
        return STAT_TAKEN[level]
    endfunction
    
    // Validate Target
    private function ValidTarget takes unit u, Data s returns boolean
        return     IsUnitType(u, UNIT_TYPE_DEAD)==false/*
            */ and IsUnitType(u, UNIT_TYPE_STRUCTURE)==false/*
            */ and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)==false/*
            */ and (DAMAGE_FRIENDLY_UNITS or IsUnitEnemy(u, GetOwningPlayer(s.caster)))/*
            */ and s.target!=u/*
            */
    endfunction
    
    //
    
    globals
        private integer PatternLength=StringLength(TT_PATTERN)
    endglobals
    
    private struct Data
        unit caster
        unit target
        timer t
        integer level
        real hptaken
        boolean cooldown=true
        boolean inloop=true
        
        static boolean array CooldownActive
        static xecast BlindnessDummy
        
        static boolexpr DamageFilter
        static thistype tmps
        
        private integer i
        
        private static thistype array Structs
        private static timer T=CreateTimer()
        private static integer Count=0
        
        private method onDestroy takes nothing returns nothing
            set .target=null
            set .caster=null
            set .t=null
        endmethod
        
        private method RemoveFromLoop takes nothing returns nothing
            if not .cooldown then
                call .destroy()
            endif
            // clean your struct here
            set .Count=.Count-1
            set .Structs[.i]=.Structs[.Count]
            set .Structs[.i].i=.i
            if .Count==0 then
                call PauseTimer(.T)
            endif
            set .inloop=false
        endmethod
        
        private static method EndCooldown takes nothing returns nothing
        local thistype s=thistype(GetTimerData(GetExpiredTimer()))
            // switch from dummy ability to casting ability
            if GetUnitAbilityLevel(s.caster, LEARN_AID)>0 then
                call UnitRemoveAbility(s.caster, DUMMY_AID)
                call UnitAddAbility(s.caster, CAST_AID)
                call UnitMakeAbilityPermanent(s.caster, true, CAST_AID) // to avoid removal through morphing abilities
                call SetUnitAbilityLevel(s.caster, CAST_AID, GetUnitAbilityLevel(s.caster, LEARN_AID))
            endif
            call ReleaseTimer(s.t) // clean up
            set .CooldownActive[GetUnitId(s.caster)]=false // mark the caster as "not in cooldown"
            set s.cooldown=false
            if GetUnitAbilityLevel(s.target, BLINDNESS_DUMMY_BID)==0 and (not s.inloop) then
                call s.destroy() // if the cooldown is longer than the buff lasts, destroy this instance
            endif
        endmethod
        
        private static method DamageFilterFunc takes nothing returns boolean
        local unit u=GetFilterUnit()
            if ValidTarget(u, .tmps) then
                call UnitDamageTarget(.tmps.caster, u, Secondary_Damage(.tmps.level), true, false, ATTACK_TYPE, DAMAGE_TYPE, SECONDARY_WEAPON_TYPE)
            endif
            set u=null
            return false
        endmethod
        
        private static method Callback takes nothing returns nothing
        local integer i=.Count-1
        local thistype s
            loop
                exitwhen i<0
                set s=.Structs[i]
                if GetUnitAbilityLevel(s.target, BLINDNESS_DUMMY_BID)==0 then
                    //buff got removed/expired
                    set .tmps=s
                    call GroupEnumUnitsInRange(ENUM_GROUP, GetUnitX(s.target), GetUnitY(s.target), SECONDARY_DAMAGE_AOE, .DamageFilter)
                    call AddUnitMaxState(s.target, STAT_MODIFIED, s.hptaken)
                    call s.RemoveFromLoop() // if the buff lasts longer than the cooldown, destroy the instance
                endif
                // do your things here, dont forget to call s.destroy() somewhen
                //
                set i=i-1
            endloop
        endmethod
        
        static method create takes nothing returns thistype
        local thistype s=.allocate()
        local integer i=0
        local string str=""
            
            set s.t=NewTimer()
            set s.caster=SpellEvent.CastingUnit
            set s.target=SpellEvent.TargetUnit
            set s.level=GetUnitAbilityLevel(s.caster, LEARN_AID)
            call AbortOrder(s.caster) // cancel the spell before it goes into cooldown and costs mana
            // apply the blindness
            set .BlindnessDummy.level=s.level
            //set .BlindnessDummy.owningplayer=GetOwningPlayer(s.caster) // comment out this line to allow targeting friendly units
            call .BlindnessDummy.castOnTarget(s.target)
            // some nice FX
            call DestroyEffect(AddSpecialEffectTarget(FX, s.target, FX_ATTPT))
            if DAMAGE_FRIENDLY_UNITS or IsUnitEnemy(s.target, GetOwningPlayer(s.caster)) then
                call UnitDamageTarget(s.caster, s.target, Damage(s.level), true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE) // damage the target
            endif
            // switch from casting ability to dummy ability
            call UnitRemoveAbility(s.caster, CAST_AID)
            call UnitAddAbility(s.caster, DUMMY_AID)
            call UnitMakeAbilityPermanent(s.caster, true, DUMMY_AID)
            call SetUnitAbilityLevel(s.caster, DUMMY_AID, s.level)
            call IssueImmediateOrder(s.caster, DUMMY_ORDER) // apply mana cost and cooldown
            call UnitRemoveAbility(s.caster, DUMMY_BID) // remove the buff placed by DUMMY_AID
            set .CooldownActive[GetUnitId(s.caster)]=true
            call SetTimerData(s.t, s)
            call TimerStart(s.t, Cooldown(s.level), false, function thistype.EndCooldown)
            if DEBUFF_FRIENDLY_UNITS or IsUnitEnemy(s.target, GetOwningPlayer(s.caster)) then
                if Stat_Taken(s.level)>=1. or Stat_Taken(s.level)<=-1. then // absolute max hp loss
                    if GetUnitState(s.target, STAT_MODIFIED)<=Stat_Taken(s.level) then
                        // if the current max hp of the target are smaller than the amount taken away
                        // Reduce the amount taken away so that it leaves the unit with exactly 1 max hp.
                        set s.hptaken=GetUnitState(s.target, STAT_MODIFIED)-1 // store the amount taken away
                        call SetUnitMaxState(s.target, STAT_MODIFIED, 1)
                    else
                        set s.hptaken=Stat_Taken(s.level) // store the amount taken away
                        call AddUnitMaxState(s.target, STAT_MODIFIED, -Stat_Taken(s.level))
                    endif
                else // relative max hp loss
                    if GetUnitState(s.target, STAT_MODIFIED)*(1.-Stat_Taken(s.level))<1. then
                        set s.hptaken=GetUnitState(s.target, STAT_MODIFIED)-1 // store the amount taken away
                        call SetUnitMaxState(s.target, STAT_MODIFIED, 1)
                    else
                        set s.hptaken=Stat_Taken(s.level)*GetUnitState(s.target, STAT_MODIFIED)
                        call AddUnitMaxState(s.target, STAT_MODIFIED, -s.hptaken)
                    endif
                endif
            endif
            
            if SHOW_TT and s.hptaken!=0. then
                loop
                    exitwhen i>=PatternLength
                    if SubString(TT_PATTERN, i, i+1)=="&" and i+1<PatternLength then
                        if SubString(TT_PATTERN, i+1, i+2)=="d" or SubString(TT_PATTERN, i+1, i+2)=="D" then
                            if s.hptaken<0. then
                                set str=str+TT_POSITIVE_HP_BONUS_STRING
                            else
                                set str=str+TT_NEGATIVE_HP_BONUS_STRING
                            endif
                            set str=str+I2S(R2I(RAbsBJ(s.hptaken)))
                            set i=i+1
                        else
                            set str=str+"&"
                        endif
                    else
                        set str=str+SubString(TT_PATTERN, i, i+1)
                    endif
                    set i=i+1
                endloop
                call TextTag_Unit(s.target, str, TT_COLOR)
            endif
            
            // initialize the struct here
            set .Structs[.Count]=s
            set s.i=.Count
            if .Count==0 then
                call TimerStart(.T, TICK, true, function thistype.Callback)
            endif
            set .Count=.Count+1
            return s
        endmethod
        
        private static method onInit takes nothing returns nothing
            set .BlindnessDummy=xecast.create()
            set .BlindnessDummy.abilityid=BLINDNESS_DUMMY_AID
            set .BlindnessDummy.orderstring=BLINDNESS_DUMMY_ORDER
            set .BlindnessDummy.recycledelay=1.0
            
            set .DamageFilter=Condition(function thistype.DamageFilterFunc)
            
            call Preload(FX)
            call PreloadStart()
            call XE_PreloadAbility(CAST_AID)
            call XE_PreloadAbility(DUMMY_AID)
            call XE_PreloadAbility(BLINDNESS_DUMMY_AID)
            
            call SetUpCOOLDOWN()
            call SetUpDAMAGE()
            call SetUpSECONDARY_DAMAGE()
            call SetUpSTAT_TAKEN()
        endmethod
    endstruct
    
    private function Cast takes nothing returns nothing
        call Data.create()
    endfunction
    
    globals
        private integer array LearnedAbilityLevel
    endglobals
    
    private function IsLearnAbility takes nothing returns boolean
        return GetLearnedSkill()==LEARN_AID
    endfunction
    
    private function Learning takes nothing returns nothing
    local unit u=GetLearningUnit()
        if GetLearnedSkillLevel()==1 then
            call UnitAddAbility(u, CAST_AID)
            call UnitMakeAbilityPermanent(u, true, CAST_AID)
        endif
        if Data.CooldownActive[GetUnitId(u)] then
            call SetUnitAbilityLevel(u, DUMMY_AID, GetLearnedSkillLevel())
        else
            call SetUnitAbilityLevel(u, CAST_AID, GetLearnedSkillLevel())
        endif
        set LearnedAbilityLevel[GetUnitId(u)]=GetLearnedSkillLevel()
        set u=null
    endfunction
    
    private function UnlearnedAbility takes nothing returns boolean
        return GetUnitAbilityLevel(GetTriggerUnit(), LEARN_AID)!=LearnedAbilityLevel[GetUnitId(GetTriggerUnit())]
    endfunction
    
    private function ResetAbility takes nothing returns nothing
        call UnitRemoveAbility(GetTriggerUnit(), CAST_AID)
        call UnitRemoveAbility(GetTriggerUnit(), DUMMY_AID)
    endfunction
    
    private function Init takes nothing returns nothing
    local trigger t=CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_HERO_SKILL)
        call TriggerAddCondition(t, Condition(function IsLearnAbility))
        call TriggerAddAction(t, function Learning)
        
        set t=CreateTrigger() // just in case someone uses that damn tome of relearning // untested code
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM)
        call TriggerAddCondition(t, Condition(function UnlearnedAbility))
        call TriggerAddAction(t, function ResetAbility)
        
        call RegisterSpellCastResponse(CAST_AID, Cast) // why trigger on cast? --
        // well, when using SPELL_EFFECT the hero can be interrupted before actually
        // reaching the Cast Point (where SPELL_EFFECT is triggered).
        // This spell ignores the time the hero takes to reach the cast point.
    endfunction
    
endlibrary
 
Since you didn't like the easiest and crappy GUI way in the previous post, maybe you could try something a bit more convoluted. A unit indexer would definitely help but here's an example without:

  • Orb Carrier On
    • Events
      • Unit - A unit Acquires an item
    • Conditions
      • (Owner of (Hero manipulating item)) Equal to Player 1 (Red)
    • Actions
      • Set VariableSet ValarOrbCarrier01 = (Hero manipulating item)
  • Orb Carrier Off
    • Events
      • Unit - A unit Loses an item
    • Conditions
      • (Owner of (Hero manipulating item)) Equal to Player 1 (Red)
    • Actions
      • Set VariableSet ValarOrbCarrier01 = No unit
  • Valar Orb Buff Checker
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet ValarOrbCarrierPoint = (Position of ValarOrbCarrier01)
      • Set VariableSet ValarOrbRangeGroup = (Units within 1500.00 of ValarOrbCarrierPoint matching ((((Matching unit) belongs to an enemy of (Owner of ValarOrbCarrier01).) Equal to True) and (((Matching unit) has buff Acid Bomb) Equal to True)).)
      • Unit Group - Pick every unit in ValarOrbRangeGroup and do (Actions)
        • Loop - Actions
          • Unit Group - Add (Picked unit) to ValarOrbBuffGroup
      • Custom script: call RemoveLocation(udg_ValarOrbCarrierPoint)
      • Unit Group - Pick every unit in ValarOrbBuffGroup and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff Acid Bomb) Equal to False
              • ((Picked unit) is alive) Equal to True
            • Then - Actions
              • Unit Group - Remove (Picked unit) from ValarOrbBuffGroup.
            • Else - Actions
      • Custom script: call DestroyGroup(udg_ValarOrbRangeGroup)
  • Spawn
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Killing unit) Equal to ValarOrbCarrier01
      • ((Dying unit) is in ValarOrbBuffGroup.) Equal to True
    • Actions
      • Unit - Create 1 Footman for (Owner of ValarOrbCarrier01) at (Position of (Dying unit)) facing Default building facing degrees
      • Unit Group - Remove (Dying unit) from ValarOrbBuffGroup.
Have to clean leaks in the last one: set ValarOrbBuffUnit=dying unit. Set ValarOrbVictimPosition=position of dying unit. So on.
Also replace the acid bomb buff I used in the example with your custom one.
 
Since you didn't like the easiest and crappy GUI way in the previous post, maybe you could try something a bit more convoluted. A unit indexer would definitely help but here's an example without:

  • Orb Carrier On
    • Events
      • Unit - A unit Acquires an item
    • Conditions
      • (Owner of (Hero manipulating item)) Equal to Player 1 (Red)
    • Actions
      • Set VariableSet ValarOrbCarrier01 = (Hero manipulating item)
  • Orb Carrier Off
    • Events
      • Unit - A unit Loses an item
    • Conditions
      • (Owner of (Hero manipulating item)) Equal to Player 1 (Red)
    • Actions
      • Set VariableSet ValarOrbCarrier01 = No unit
  • Valar Orb Buff Checker
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet ValarOrbCarrierPoint = (Position of ValarOrbCarrier01)
      • Set VariableSet ValarOrbRangeGroup = (Units within 1500.00 of ValarOrbCarrierPoint matching ((((Matching unit) belongs to an enemy of (Owner of ValarOrbCarrier01).) Equal to True) and (((Matching unit) has buff Acid Bomb) Equal to True)).)
      • Unit Group - Pick every unit in ValarOrbRangeGroup and do (Actions)
        • Loop - Actions
          • Unit Group - Add (Picked unit) to ValarOrbBuffGroup
      • Custom script: call RemoveLocation(udg_ValarOrbCarrierPoint)
      • Unit Group - Pick every unit in ValarOrbBuffGroup and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff Acid Bomb) Equal to False
              • ((Picked unit) is alive) Equal to True
            • Then - Actions
              • Unit Group - Remove (Picked unit) from ValarOrbBuffGroup.
            • Else - Actions
      • Custom script: call DestroyGroup(udg_ValarOrbRangeGroup)
  • Spawn
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Killing unit) Equal to ValarOrbCarrier01
      • ((Dying unit) is in ValarOrbBuffGroup.) Equal to True
    • Actions
      • Unit - Create 1 Footman for (Owner of ValarOrbCarrier01) at (Position of (Dying unit)) facing Default building facing degrees
      • Unit Group - Remove (Dying unit) from ValarOrbBuffGroup.
Have to clean leaks in the last one: set ValarOrbBuffUnit=dying unit. Set ValarOrbVictimPosition=position of dying unit. So on.
Also replace the acid bomb buff I used in the example with your custom one.
But you made the trigger to only be working on Player Red but my map can be played by up to 10 players... Also you didn't tell me what type of Variable you are using...
 
But you made the trigger to only be working on Player Red but my map can be played by up to 10 players... Also you didn't tell me what type of Variable you are using...
Yes. This other example which somewhat takes the buff into consideration needs to be made MUI. But it's easier to use a unit indexer alongside arrays. So, you could just make a player variable with an array and check the owner of the unit acquiring/losing the item: set OrbOfValarPlayer=player number [owner of acquiring/losing item]. Then you can do the same with ValarOrbCarrier[player number of owner of unit].
It's easy to infer what variables I'm using:
ValarOrbCarrier01 - unit
ValarOrbCarrierPoint - point
ValarOrbRangeGroup - unit group


But have you tried the first example? It works well only it doesn't take the buff into consideration. Basically you only need to have the item and to kill a unit to spawn the Gondor swordsman.
 
Yes. This other example which somewhat takes the buff into consideration needs to be made MUI. But it's easier to use a unit indexer alongside arrays. So, you could just make a player variable with an array and check the owner of the unit acquiring/losing the item: set OrbOfValarPlayer=player number [owner of acquiring/losing item]. Then you can do the same with ValarOrbCarrier[player number of owner of unit].
It's easy to infer what variables I'm using:
ValarOrbCarrier01 - unit
ValarOrbCarrierPoint - point
ValarOrbRangeGroup - unit group


But have you tried the first example? It works well only it doesn't take the buff into consideration. Basically you only need to have the item and to kill a unit to spawn the Gondor swordsman.
Well I think the second example is better. Because alot of heroes has aoe spells and if they kill a big group and has the orb-item then it will spawn an unit for each enemy units that was killed by the aoe spell and it will be too overpowered in my opinion so it is better with second example I think that requires the dying unit to have the specific buff before it spawns the unit. I really suck at doing triggers like you maybe have noticed so I don't really get what you mean with player numbers and arrays. Would you mind doing it to me instead?
 
Btw I couldn't choose "Units within 1500.00 of ValarOrbCarrierPoint" for some reason :-/
So I just made it to "Units within 1500.00 of (Position of ValarOrbCarrier01)"
yours.png

mine.png
 
I've uploaded the triggers separately. Hope you can import them in a dummy map and then copy them to your map.
I've also uploaded the example map but it's saved on the latest 2.0.3 and I'm not sure if you can open it or use an older game/editor version.

Here's the trigger text too:
  • Orb Carrier On
    • Events
      • Unit - A unit Acquires an item
    • Conditions
      • ((Hero manipulating item) has an item of type Gem Fragment) Equal to True
    • Actions
      • Game - Display to (All players) the text: GET ITEM
      • Set VariableSet ValarOrbPlayerNumber = (Player number of (Owner of (Hero manipulating item)))
      • Set VariableSet ValarOrbCarrier[ValarOrbPlayerNumber] = (Hero manipulating item)
      • Unit Group - Add ValarOrbCarrier[ValarOrbPlayerNumber] to ValarOrbWielderGroup
  • Orb Carrier Off
    • Events
      • Unit - A unit Loses an item
    • Conditions
      • ((Hero manipulating item) has an item of type Gem Fragment) Equal to True
    • Actions
      • Game - Display to (All players) the text: LOSE ITEM
      • Set VariableSet ValarOrbPlayerNumber = (Player number of (Owner of (Hero manipulating item)))
      • Set VariableSet ValarOrbCarrier[ValarOrbPlayerNumber] = (Hero manipulating item)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (ValarOrbCarrier[ValarOrbPlayerNumber] has (Item carried by ValarOrbCarrier[ValarOrbPlayerNumber] of type Gem Fragment)) Equal to False
        • Then - Actions
          • Game - Display to (All players) the text: LOSE ITEM AGAIN
          • Unit Group - Remove ValarOrbCarrier[ValarOrbPlayerNumber] from ValarOrbWielderGroup.
        • Else - Actions
  • Valar Orb Buff Checker
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in ValarOrbWielderGroup and do (Actions)
        • Loop - Actions
          • Set VariableSet ValarOrbPlayerNumber = (Player number of (Owner of (Picked unit)))
          • Set VariableSet ValarOrbCarrierPointOld = (Position of ValarOrbCarrier[ValarOrbPlayerNumber])
          • Set VariableSet ValarOrbRangeGroup = (Units within 1500.00 of ValarOrbCarrierPointOld matching ((((Matching unit) belongs to an enemy of (Owner of ValarOrbCarrier[ValarOrbPlayerNumber]).) Equal to True) and (((Matching unit) has buff Acid Bomb) Equal to True)).)
          • Unit Group - Pick every unit in ValarOrbRangeGroup and do (Actions)
            • Loop - Actions
              • Unit Group - Add (Picked unit) to ValarOrbBuffGroup
          • Custom script: call RemoveLocation(udg_ValarOrbCarrierPointOld)
          • Custom script: call DestroyGroup(udg_ValarOrbRangeGroup)
      • Game - Display to (All players) the text: (HEROES IN GROUP - + (String((Number of units in ValarOrbWielderGroup))))
      • Unit Group - Pick every unit in ValarOrbBuffGroup and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff Acid Bomb) Equal to False
              • ((Picked unit) is alive) Equal to True
            • Then - Actions
              • Unit Group - Remove (Picked unit) from ValarOrbBuffGroup.
            • Else - Actions
      • Game - Display to (All players) the text: (ENEMIES IN GROUP - + (String((Number of units in ValarOrbBuffGroup))))
  • Spawn
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Killing unit) has an item of type Gem Fragment) Equal to True
      • ((Dying unit) is in ValarOrbBuffGroup.) Equal to True
    • Actions
      • Game - Display to (All players) the text: FOOTMAN SPAWNED
      • Set VariableSet ValarOrbVictimPoint = (Position of (Dying unit))
      • Unit - Create 1 Footman for (Owner of (Killing unit)) at (Position of (Dying unit)) facing Default building facing degrees
      • Custom script: call RemoveLocation(udg_ValarOrbVictimPoint)
  • Buffed Unit Removal on Death
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Dying unit) is in ValarOrbBuffGroup.) Equal to True
    • Actions
      • Game - Display to (All players) the text: BUFFED UNIT DIES
      • Unit Group - Remove (Dying unit) from ValarOrbBuffGroup.
EDIT: moved Custom script: call DestroyGroup(udg_ValarOrbRangeGroup) in the wielder group after the location removal.
Added proper removal of buffed units when dying.
EDIT2: added more to the item drop trigger as to work even if you have more orbs on and drop one.
 

Attachments

Last edited:
Back
Top