• 🏆 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!

[Trigger] Damage of Time Problem

Status
Not open for further replies.
Level 2
Joined
Sep 21, 2012
Messages
6
Hello, my name is The5thelement and I am new here.

I am here because I am having a problem with a Damage over Time trigger.
Here is what I have. Hopefully someone will be able to tell me whats wrong.

Spell Cast
  • Events
    • Unit - A unit Finishes casting an ability
  • Conditions
    • (Ability being cast) Equal to Fireball (Rank 1)
  • Actions
    • Set CastUnit = (Triggering unit)
    • Unit Group - Add (Target unit of ability being cast) to EffectedUnits
Damage Over Time
  • Events
    • Time - Every 1.00 seconds of game time
  • Conditions
  • Actions
    • Unit Group - Pick every unit in EffectedUnits and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • ((Picked unit) has buff Fireball (Rank 1)) Equal to True
          • Then - Actions
            • Unit - Cause CastUnit to damage (Picked unit), dealing 4.00 damage of attack type Spells and damage type Fire
          • Else - Actions
            • Unit Group - Remove (Picked unit) from EffectedUnits
Any help would be appreciated. And if this is the wrong section to post
this please let me know.
 
Level 9
Joined
Jul 10, 2011
Messages
562
the problem will be that no damage is dealt and the reason is what Adiktuz already mentioned....you have to use 'Starts the effect of an ability' instead of 'A unit finishes casting an ability'.

reason? if the unit already finished casting theres no 'target of ability being cast' anymore means it cant refer to it and so theres never a unit in the unit group and so no damage is dealt.
 
Finishes casting fires after the whole casting animation ends... so if you suddenly issue another order to the unit while it is still "casting" that trigger won't fire anymore...

however, I do believe that wc3 saves the Target unit of ability being cast up to the Finishes casting part... so the only problem is that he probably never really "finishes" casting the ability...
 
I just though it did because written in the description of target unit is Channeling/Starts/... casting so I though it works for all ... casting events...

btw, I'm not talking about saving like the way triggering unit preserves the value even after a wait... by saving I mean you can still fetch a target unit for the event A unit finishes casting...
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
This system:
- Allows select number of damage/heal cicles
- Allows select TimeGap between damage/heal cicles
- Allows select if you want to show or hide the damage/heal amount as text
- Allows select if you want to show or hide an special effect on the target
- It's MUI
- Doesn't requires deep jass knowledge requirement, just follow test map example.

1. Create a Trigger
2. Go to Edit -> Convert to Custom Text
3. Delete Everything Inside it
4. Copy the following script there (each script in a different trigger)

JASS:
library SpartDOT

    globals
        hashtable SpartDOTHash = InitHashtable()
    endglobals

    function SpartDOTActions takes nothing returns nothing
        // Required Locals
        local timer t = GetExpiredTimer()
        local integer i = GetHandleId(t)
        local hashtable h = SpartDOTHash
        local unit caster = LoadUnitHandle(h, i, 0)
        local unit target = LoadUnitHandle(h, i, 1)
        local integer times = LoadInteger(h, i, 2)
        local real amount = LoadReal(h, i, 3)
        local integer count = LoadInteger(h, i, 4)+1
        local boolean showtext = LoadBoolean(h, i, 5)
        local boolean showeffect = LoadBoolean(h, i, 6)
        local string s
        local string a
        local real r = GetUnitState(target, UNIT_STATE_LIFE)
        local real rx = GetUnitState(target, UNIT_STATE_MAX_LIFE)
        local texttag tt = null
        
        if showeffect == true then
            set s = LoadStr(h, i, 7)
            set a = LoadStr(h, i, 8)
        endif
        
        // Is Target Alive?
        if r > 0 then         
            if showtext == true then // Want to display damage?
                set tt = CreateTextTag()
                call SetTextTagPermanent(tt, false)
                call SetTextTagPosUnit(tt, target, 0)
                call SetTextTagVelocity(tt, 0, 0.062)
                call SetTextTagLifespan(tt, 1.2)
                call SetTextTagFadepoint(tt, 0.2)
            endif
            // Damage is negative?
            if amount < 0 then
                call SetTextTagColor(tt, 0, 255, 0, 255)
                call SetTextTagText(tt, "+" + SubString(R2S(amount), 1, StringLength(R2S(amount))-4), 0.027)
                set r = r+(amount*-1)
                if r > rx then
                    set r = GetUnitState(target, UNIT_STATE_MAX_LIFE)
                endif
                call SetWidgetLife(target, r)
            else // It's not?
                call SetTextTagColor(tt, 255, 0, 0, 255)
                call SetTextTagText(tt, "-" + SubString(R2S(amount), 0, StringLength(R2S(amount))-4), 0.027)
                call UnitDamageTarget(caster, target, amount, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
            endif
            
            // Display Special Effect?
            if showeffect == true then
                call DestroyEffect(AddSpecialEffectTarget(s, target, a))
            endif
        // Is target Dead?
        else // Stop everything
            set count = times 
        endif

        if count >= times then // The actual Effect Stop
            call PauseTimer(t)
            call FlushChildHashtable(SpartDOTHash, i)
            call DestroyTimer(t)
        else
            call SaveInteger(SpartDOTHash, i, 4, count)
        endif
        
        // Clean Leaks
        set t = null
        set caster = null
        set target = null
        set tt = null
    endfunction

    function SpartDOTSet takes unit caster, unit target, integer times, real time, real amount, boolean ShowText, boolean ShowEffect, string EffectPath, string AttachPoint returns nothing
        local timer t = CreateTimer()
        local integer i = GetHandleId(t)
        local hashtable h = SpartDOTHash
        call TimerStart(t, time, true, function SpartDOTActions)
        call SaveUnitHandle(h, i, 0, caster) // Caster
        call SaveUnitHandle(h, i, 1, target) // target
        call SaveInteger(h, i, 2, times) // Number of Times
        call SaveReal(h, i, 3, amount) // Amount of Damage
        
        if ShowText == true then
            call SaveBoolean(h, i, 5, ShowText) // ShowEffect
        endif
        
        if ShowEffect == true then
            call SaveBoolean(h, i, 6, ShowEffect) // ShowEffect
            call SaveStr(h, i, 7, EffectPath) // Effect Path
            call SaveStr(h, i, 8, AttachPoint) // Effect Attachment Point
        endif

        set t = null
    endfunction

endlibrary


And you're done. Feel free to edit and manipulate the code to suit your needs.


  • Actions
    • -------- To see it Clearly --------
    • Set Caster = Paladin 0001 <gen>
    • Set Target = Paladin 0002 <gen>
    • Set Times = 6
    • Set TimeGap = 1.00
    • Set Damage = ((Real((Strength of Caster (Include bonuses)))) + 100.00)
    • Set ShowText = True
    • Set ShowEffect = True
    • Set EffectPath = Abilities\Spells\Undead\OrbOfDeath\OrbOfDeathMissile.mdl
    • Set AttachPoint = origin
    • Unit - Make Caster face Target over 0.00 seconds
    • Custom script: call SpartDOTSet(udg_Caster, udg_Target, udg_Times, udg_TimeGap, udg_Damage, udg_ShowText, udg_ShowEffect, udg_EffectPath, udg_AttachPoint)
    • -------- --------
    • -------- You can also type values directly without using variables --------
    • -------- --------
    • Set Caster = Paladin 0001 <gen>
    • Set Target = Paladin 0004 <gen>
    • Unit - Make Caster face Target over 0.00 seconds
    • Custom script: call SpartDOTSet(udg_Caster, udg_Target, 5, 1, GetHeroStr(udg_Caster, true)+100, false, true, udg_EffectPath, "origin")
    • -------- --------
    • -------- If "ShowEffect" is false, you can type "null" on EffectPath and AttachPoint --------
    • -------- --------
    • Set Caster = Paladin 0001 <gen>
    • Set Target = Paladin 0006 <gen>
    • Unit - Make Caster face Target over 0.00 seconds
    • Custom script: call SpartDOTSet(udg_Caster, udg_Target, udg_Times, udg_TimeGap, udg_Damage, false, false, null, null)
    • -------- --------
    • -------- You can also use it toHeal instead of Damage using NEGATIVE DAMAGE --------
    • -------- --------
    • Set Damage = -100.00
    • Set EffectPath = Abilities\Spells\Undead\VampiricAura\VampiricAuraTarget.mdl
    • Set AttachPoint = origin
    • Set Target = Paladin 0002 <gen>
    • Unit - Make Caster face Target over 0.00 seconds
    • Custom script: call SpartDOTSet(udg_Caster, udg_Target, udg_Times, udg_TimeGap, udg_Damage, true, udg_ShowEffect, udg_EffectPath, udg_AttachPoint)


NOTE: Feel free to manipulate it however you want to suit your needs.
 

Attachments

  • SpartDOT.w3x
    24.1 KB · Views: 98
Last edited:
Level 20
Joined
Jul 14, 2011
Messages
3,213
hehehehe I don't really care it being mine. I just want to solve his problem and this is the resource I already have, so, share :p You can still share yours.
 
not really... not until I update it I guess... plus you already posted a working solution... :)

anyway, how about my question? because if it doesn't compile in the normal WE, then you'd better just put it inside a library to be put in a trigger rather than on the map header (so that he won't forget that such system exist)
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
@Adiktuz: But i still use globals/endglobals inside the library. There's no problem there?

@mckill20009 I don't know vJASS but this system is pretty easy. How would I use struct index instead of hashtable?
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
structs is just like hanky's dynamic indexing but it's more advanced, you can use a global reference to that struct name, then change the value whenever you like, just like HT...
JASS:
globals
   name one //instance 1
   name two //instance 2
endglobals

struct name
    static method onInit takes nothing returns nothing
        set one = one.create()
        set two = two.create()
        call BJDebugMsg(I2S(one))
        call BJDebugMsg(I2S(two))
    endmethod
endstruct
 
Status
Not open for further replies.
Top