• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[vJASS] LifeSteal

Level 9
Joined
Jun 21, 2012
Messages
432
JASS:
library LifeSteal/*
*******************************************************************************************************
*
*   ***************************************************************************************************
*   */ uses /*
*       */ ANY DamageEvent /*
*       */ ANY UnitIndexer /*
*   ***************************************************************************************************
*
*   LifeSteal
*   ¯¯¯¯¯¯¯¯¯
*   v0.1.1.1
*   by Trigger edge
*
*   Add custom life steal for all attack types.
*  
*   API:
*   ¯¯¯
*   struct LifeSteal extends array
*        public string positiveFx
*        public string negativeFx
*        public boolean block
*       
*       static method operator [] takes unit u returns thistype
*       method operator percent takes nothing returns real
*       method operator percent= takes real r returns nothing
*
*******************************************************************************************************/
   
    //CONFIGURATION
    //=================================================================================
    globals
        private constant string DEFAULT_FX = "Abilities\\Spells\\Undead\\VampiricAura\\VampiricAuraTarget.mdl"
    endglobals
    //=================================================================================
   
    globals
        private timer delayTimer=CreateTimer()
        private group stack=CreateGroup()
    endglobals
   
    struct LifeSteal extends array
        private real unitPercent
        private real amount
       
        public string positiveFx
        public string negativeFx
        public boolean block

        static method operator [] takes unit u returns thistype
            return GetUnitId(u)
        endmethod
       
        method operator percent takes nothing returns real
            return .unitPercent
        endmethod
       
        method operator percent= takes real r returns nothing
            set .unitPercent=.unitPercent+r
        endmethod
       
        private static method beforeDmg takes nothing returns nothing
            local thistype this=0
            local unit u=null
            loop
                set u=FirstOfGroup(stack)
                exitwhen(null==u)
                call GroupRemoveUnit(stack,u)
                set this=GetUnitId(u)
                if(not .block)then
                    if(0<.amount)then
                        if(null==.positiveFx)then
                            set .positiveFx=DEFAULT_FX
                        endif
                        call DestroyEffect(AddSpecialEffectTarget(.positiveFx,u,"chest"))
                    else
                        if(null==.negativeFx)then
                            set .negativeFx=DEFAULT_FX
                        endif
                        call DestroyEffect(AddSpecialEffectTarget(.negativeFx,u,"chest"))
                    endif
                    call SetWidgetLife(u,.amount+GetWidgetLife(u))
                    set .amount=0
                else
                    set .block=false
                endif
            endloop
        endmethod

        private static method onHit takes nothing returns nothing
            local thistype this=Damage.sourceId
            if(0!=.percent)then
                set .amount=.amount+(Damage.amount*.percent/100)
                call GroupAddUnit(stack,Damage.source)
                call TimerStart(delayTimer,0,false,function thistype.beforeDmg)
            endif
        endmethod

        private static method onInit takes nothing returns nothing
            call RegisterDamageEvent(function thistype.onHit)
        endmethod
    endstruct
endlibrary

You need config the onInit method for your Damage Event snippet:
JASS:
private static method onInit takes nothing returns nothing
    call RegisterDamageEvent(function thistype.onHit)
endmethod
 
Level 39
Joined
Feb 27, 2007
Messages
5,014
This lifesteal will proc on damage from spell casts and other trigger-based damage. That's kind of a big deal, and AFAIK you'll have to use this with a DDS that can differentiate using the runed bracers trick.

Yes you have the note at the end, but that also doesn't show that you'll have to change references to Damage.source and the unit indexer get call in the [] method operator. IMO the best solution would be to put these few configurable bits into textmacroes at the top of the script so they can easily be edited without touching the main code.
 

AGD

AGD

Level 16
Joined
Mar 29, 2016
Messages
688
This
JASS:
*   */ uses /*
*       */ ANY <--
will pop up a syntax error

As mentioned by Pyrogasm, users should not be obliged touch the main code. I think it would be better to just pick a definite damage detection system and unit indexer.

Correct me if I missed something but is the timer really needed? It would be straightforward to just directly do
JASS:
private static method onDamage takes nothing returns nothing
    local thistype this = thistype[Damage.source]
    //.. Perform lifesteal operations =)
endmethod

private static method onInit takes nothing returns nothing
    call AddDamageHandler(function thistype.onDamage)
endmethod


A LifeSteal snippet that is as configurable (or more configurable) as blizzard's default lifesteals would be nice because currently, a unit can only have 1 type of lifesteal. A lifesteal snippet must atleast able to add as many lifesteal instance to a single unit. Here's some features that might be handy to have in this library:
- Add multiple lifesteal instances per unit (as I said above)
- Categorize lifesteals into stacking and non-stacking (stacking means the ability to works together with other lifesteals)
- Can be configured if a spell damage (or code damage) can trigger lifesteal or not, you can easily do this with looking_for_help's PDDS for example
- Configure allowed targets (Even just the common ones such as enemy, organic, structure, etc.)

Imo, a good lifesteal library must be able to do all of the things the default lifesteal abilities can do and at the same time, do things that the default lifesteal can't do. Because if it can't even beat the default lifesteals' functionality, it might as well make more sense to use them (object editor lifesteals) over a scripted one. When this can be updated to support the said features, this would be a useful addition I think.
 
The main reason this section (or rather our community) are not producing any GOOD Attack Modifier (or Damage Modifier, Physical) is that we currently don't have a working or an accepted Attack Indexer ;)

Let me explain it to you.

For example, I have Item X that grants me Lifesteal using the library LifeSteal. If I try to attack a unit, 9000 units away from me at a missile speed of 900 (that will take 10 seconds or something to reach), without the item, that won't "lifesteal" on damage, right? Now what if the missile was on air and I picked up the Item X, how can we ensure that the attack missile, that was still on air, will not proc the "lifesteal" when it hits the unit?

That's what Attack Indexer is for.

IF there will be an Attack Indexer that will work (contact Nestharus for algorithm details, though I really hate his idea even though it is the only idea we can think of), it can produce anything that is related to Attack Modifying, some are:
- Custom Orb Effects
- Custom Critical Strike, Evasion
- Custom Return Damage
- Custom Cleave, Splash and Bounce
- Custom Attack Barrier
- and more.
 

AGD

AGD

Level 16
Joined
Mar 29, 2016
Messages
688
Though what Almia said is good to consider, It doesn't seem to me to be a requirement for approval (i.e., modifying only the damage of the attacks that are launched when the attack modifier is present on the unit rather than just modifying the damage when the modifier is currently present on the unit). It is actually good - gives it a realistic background but I think is not a mandatory fix.

I would sent this to graveyard for now due to the reasons stated in my post above. Feel free to notify this thread for updates.

Graveyarded
 
Top