Spell Request

Devalut

TH.net Regular
Reaction score
7
Basically I was trying to look into a triggered damage Dot (based on the casters intelligence) that spreads to another unit if the effected unit dies.
If you play league of legends, there is a hero name Malazhar, and he has the exact ability. Heres a description of the spell:

Malzahar infects his target's mind with cruel visions of their own demise, dealing magic damage over 4 seconds. If the target dies while afflicted by the visions, they pass the curse on to a nearby enemy unit, refreshing the duration and restoring mana to Malzahar

I tried replicating this over a hashtable heal spell, which failed horribly...
This is basically what I'm looking for.
- Set damage & mana that's based upon the stat intelligence (for the caster)
- Damage dealt by the caster ( so the affected unit doesn't run away from
the dummy)

+rep
------------------------------------------------------------------------------------------------

Found it!
(well, semi made it and found it.)
Credits to maker of the life leak, as i completly Frankenstein-ed his spell
http://www.hiveworkshop.com/forums/spells-569/hashtables-life-leak-v0-02-a-167208/

Heres the triggers (for those looking for something like this!)

MV Ini
Events
Map initialization
Conditions
Actions
Hashtable - Create a hashtable
Set MV_Hash = (Last created hashtable)
Set MV_Abilty = Mark of the Void

MV Cast
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to MV_Abilty
((Triggering unit) is A Hero) Equal to True
Actions
Set Caster = (Triggering unit)
Set Target = (Target unit of ability being cast)
Set Points[1] = (Position of Caster)
Unit - Create 1 Dummy Unit for (Owner of Caster) at Points[1] facing Default building facing degrees
Hashtable - Save 4.00 as 0 of (Key (Last created unit)) in MV_Hash
Hashtable - Save 0.05 as (Key Decay) of (Key (Last created unit)) in MV_Hash
Hashtable - Save (((20.00 + (80.00 x (Real((Level of (Triggering unit)))))) + 0.00) / 4.00) as 1 of (Key (Last created unit)) in MV_Hash
Floating Text - Create floating text that reads (String((Integer(((Load 1 of (Key (Last created unit)) from MV_Hash) x 4.00))))) at Points[1] with Z offset 0.00, using font size 10.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
Floating Text - Change (Last created floating text): Disable suspend state
Floating Text - Change (Last created floating text): Disable permanence
Floating Text - Change the lifespan of (Last created floating text) to 2.00 seconds
Floating Text - Change the fading age of (Last created floating text) to 0.25 seconds
Hashtable - Save Handle OfCaster as 2 of (Key (Last created unit)) in MV_Hash
Hashtable - Save Handle OfTarget as 3 of (Key (Last created unit)) in MV_Hash
If ((LifeLeaks is empty) Equal to True) then do (Trigger - Turn on MV Loop <gen>) else do (Do nothing)
Unit Group - Add (Last created unit) to LifeLeaks
Custom script: call RemoveLocation(udg_Points[1])

MV Loop
Events
Time - Every 0.05 seconds of game time
Conditions
Actions
Unit Group - Pick every unit in LifeLeaks and do (Actions)
Loop - Actions
Set Caster = (Load 2 of (Key (Picked unit)) in MV_Hash)
Set Target = (Load 3 of (Key (Picked unit)) in MV_Hash)
Set Points[1] = (Position of Caster)
Set Real[1] = (Load 1 of (Key (Picked unit)) from MV_Hash)
Set Real[3] = (Load 0 of (Key (Picked unit)) from MV_Hash)
Set Real[3] = (Real[3] - 0.05)
Set Real[4] = (Load (Key Decay) of (Key (Picked unit)) from MV_Hash)
Set Real[4] = (Real[4] - 0.05)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Or - Any (Conditions) are true
Conditions
Real[3] Equal to 0.00
(Caster is dead) Equal to True
(Target is dead) Equal to True
Then - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Target is dead) Equal to True
Then - Actions
Unit - Set mana of Caster to ((Mana of Caster) + (Real((Intelligence of Caster (Include bonuses)))))
Special Effect - Create a special effect attached to the chest of Caster using Abilities\Spells\Undead\ReplenishMana\SpiritTouchTarget.mdl
Special Effect - Destroy (Last created special effect)
Set T_Point = (Position of Target)
Set T_Group = (Units within 500.00 of T_Point matching ((((Matching unit) is A structure) Equal to False) and (((((Matching unit) is alive) Equal to True) and (((Matching unit) is Magic Immune) Equal to False)) and (((Matching unit) belongs to an enemy of (Owner of Caster)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Number of units in T_Group) Equal to 0
Then - Actions
Else - Actions
Unit Group - Pick every unit in (Random 1 units from T_Group) and do (Actions)
Loop - Actions
Set Target = (Picked unit)
Special Effect - Create a special effect at T_Point using Abilities\Spells\Items\AIso\AIsoTarget.mdl
Special Effect - Destroy (Last created special effect)
Unit - Create 1 Dummy Unit for (Owner of Caster) at T_Point facing Default building facing degrees
Unit - Add MV_Abilty to (Last created unit)
Unit - Order (Last created unit) to Undead Necromancer - Cripple (Picked unit)
Hashtable - Save 4.00 as 0 of (Key (Last created unit)) in MV_Hash
Hashtable - Save 0.05 as (Key Decay) of (Key (Last created unit)) in MV_Hash
Hashtable - Save (((20.00 + (80.00 x (Real((Level of Caster))))) + 0.00) / 4.00) as 1 of (Key (Last created unit)) in MV_Hash
Hashtable - Save Handle OfCaster as 2 of (Key (Last created unit)) in MV_Hash
Hashtable - Save Handle OfTarget as 3 of (Key (Last created unit)) in MV_Hash
If ((LifeLeaks is empty) Equal to True) then do (Trigger - Turn on MV Loop <gen>) else do (Do nothing)
Unit Group - Add (Last created unit) to LifeLeaks
Custom script: call RemoveLocation(udg_T_Point)
Else - Actions
Hashtable - Clear all child hashtables of child (Key (Picked unit)) in MV_Hash
Unit Group - Remove (Picked unit) from LifeLeaks
Unit - Remove (Picked unit) from the game
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Real[4] Equal to 0.00
Then - Actions
Set Real[4] = 1.00
Unit - Cause Caster to damage Target, dealing Real[1] damage of attack type Spells and damage type Universal
Special Effect - Create a special effect attached to the chest of Target using Abilities\Spells\Undead\CarrionSwarm\CarrionSwarmDamage.mdl
Special Effect - Destroy (Last created special effect)
Else - Actions
Hashtable - Save Real[3] as 0 of (Key (Picked unit)) in MV_Hash
Hashtable - Save Real[4] as (Key Decay) of (Key (Picked unit)) in MV_Hash
Custom script: call RemoveLocation(udg_Points[1])
If ((LifeLeaks is empty) Equal to True) then do (Trigger - Turn off (This trigger)) else do (Do nothing)

Now I stink at triggering, so if someone could also check for leaks or possible ways to fix this would be appreciated!
 

WolfieeifloW

WEHZ Helper
Reaction score
372
I tried to do it.
Probably crappy code, but at least a base for someone to start off of.
JASS:
library Infection requires TimerUtils
    
    globals
        private constant integer INFECTION = &#039;A000&#039;   //Rawcode of the ability
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_NORMAL   //Attack type of the spell
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC   //Damage type of the spell
        
        //DO NOT TOUCH THE GROUP BELOW
        group GROUP = CreateGroup() //DO NOT TOUCH THIS
        //SKIP DOWN TO &quot;CONFIGURABLE FUNCTIONS&quot;
    endglobals
    
    private function Conditions takes nothing returns boolean
        return IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false
    endfunction
    
    struct Infection
        unit caster
        unit target
        integer ran
        timer t
        
        //CONFIGURABLE FUNCTIONS
        //Damage that the spell deals
        method Damage takes integer level, unit caster returns real
            return level * I2R(GetHeroInt(caster, true))
        endmethod
        
        //Duration of the spell
        static method Duration takes nothing returns integer
            return 4
        endmethod
        
        //Radius to pick another unit if the current target dies
        static method Radius takes nothing returns real
            return 300.
        endmethod
        //DO NOT TOUCH BELOW HERE UNLESS YOU KNOW WHAT YOU&#039;RE DOING        
        method onDestroy takes nothing returns nothing
            call ReleaseTimer(.t)
        endmethod
        
        static method Callback takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            
            if (GetUnitState(.target, UNIT_STATE_LIFE) &gt; 0.405) then
                if (.ran &lt; thistype.Duration()) then
                    call UnitDamageTarget(.caster, .target, Damage(GetUnitAbilityLevel(.caster, INFECTION), .caster), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE_WHOKNOWS)
                elseif (.ran &gt;= thistype.Duration()) then
                    call .destroy()
                endif
            elseif (GetUnitState(.target, UNIT_STATE_LIFE) &lt;= 0.405) then
                call GroupEnumUnitsInRange(GROUP, GetUnitX(.target), GetUnitY(.target), thistype.Radius(), Filter(Conditions))
                set .target = GroupPickRandomUnit(GROUP)
                set .ran = 0
            endif
        endmethod
        
        static method onCast takes nothing returns boolean
            local thistype this = thistype.create()
            
            set .caster = GetTriggerUnit()
            set .target = GetSpellTargetUnit()
            set .t = NewTimer()
            call SetTimerData(.t, this)
            call TimerStart(.t, 1., true, function thistype.Callback)
            return false
        endmethod
        
        private static method onInit takes nothing returns nothing
            local trigger trig = CreateTrigger()
            local integer index = 0
            
            loop
                call TriggerRegisterPlayerUnitEvent(trig, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
                set index = index + 1
                exitwhen index == bj_MAX_PLAYER_SLOTS
            endloop
            call TriggerAddCondition(trig, Condition(function thistype.onCast))
            set trig = null
        endmethod
        
    endstruct
    
endlibrary
 

Devalut

TH.net Regular
Reaction score
7
Ive never used jass spells before...
I would prefer GUI, simply because of the editing purposes.
sorry WolfieeifloW.... rep+ for you input though :(
 

DarkKnightML

New Member
Reaction score
1
I have a death knight hero in one of my maps that uses a strength over time dot, which looks like this

<The spell itself>
Code:
Plague Strike
    Events
        Unit - A unit Starts the effect of an ability
    Conditions
        (Ability being cast) Equal to Plague Strike DK
    Actions
        Set PlayerNumber = (Player number of (Owner of (Triggering unit)))
        Set Blood_Plague_Caster = (Triggering unit)
        Set UTA[PlayerNumber] = (Target unit of ability being cast)
        Set GlobalInteger[PlayerNumber] = 0
        Set Counter[1] = PlayerNumber
        Set Plague_Strike_Damage = ((50.00 x (Real((Level of Plague Strike DK for Blood_Plague_Caster)))) + ((0.10 + (0.10 x (Real((Level of Plague Strike DK for Blood_Plague_Caster))))) x (Real((Strength of Blood_Plague_Caster (Include bonuses))))))
        Set Blood_Plague = ((Real((Strength of Blood_Plague_Caster (Include bonuses)))) x (0.30 + (0.10 x (Real((Level of Plague Strike DK for Blood_Plague_Caster))))))
        Unit - Cause Blood_Plague_Caster to damage UTA[PlayerNumber], dealing Plague_Strike_Damage damage of attack type Spells and damage type Normal
        Unit Group - Add (Target unit of ability being cast) to Infected_Units[1]
        Countdown Timer - Start Timer[3] as a One-shot timer that will expire in 3.00 seconds

The DoT
Code:
Blood Plague DoT
    Events
        Time - Timer[3] expires
    Conditions
    Actions
        Set UGA[1] = (Units of type Death Knight)
        Unit Group - Pick every unit in Infected_Units[1] and do (Actions)
            Loop - Actions
                Set Counter[1] = Counter[1]
                -------- Counter[1] Tells Which player Casted the Spell. If you Use The Counter Variable for other Triggers, Count Up EX: Counter[2], Counter[3] --------
                Set PlayerNumber = Counter[1]
                Set Infected_Unit[1] = (Picked unit)
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        (Infected_Unit[1] is dead) Equal to False
                    Then - Actions
                        Set GlobalInteger[PlayerNumber] = (GlobalInteger[PlayerNumber] + 1)
                        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            If - Conditions
                                GlobalInteger[PlayerNumber] Less than or equal to 6
                            Then - Actions
                                Unit - Cause Blood_Plague_Caster to damage Infected_Unit[1], dealing Blood_Plague damage of attack type Spells and damage type Magic
                                Countdown Timer - Start Timer[3] as a One-shot timer that will expire in 3.00 seconds
                            Else - Actions
                                Set GlobalInteger[PlayerNumber] = 0
                                Unit Group - Remove Infected_Unit[1] from Infected_Units[1]
                    Else - Actions
                        Set GlobalInteger[PlayerNumber] = 0
                        Unit Group - Remove Infected_Unit[1] from Infected_Units[1]
 

Devalut

TH.net Regular
Reaction score
7
Thanks I'll check it out!
rep+

Edit: Seems to be for a single unit cast...
 

Dirac

22710180
Reaction score
147
You're missing the part where you check when the unit dies and apply the effect to a random nearby unit, this is why it would be so much easier to do this spell with JASS. Wolfie's solution is good, but lacks accuracy when it comes to detecting if the target is dead or not, since any source of damage other than the ability may kill the unit too. I'm sorry i'm unable to help you, but it's because i hate coding in GUI, did it a long time ago now i hate it so much. Get the Jass NewGen Pack v1.5 posted at the front page on this forums and if Wolfie's solution isn't good enough i'll be glad to code it.

EDIT: when you mean "single unit cast" you mean that it can only work with one unit at the time? another reason to go for JASS, i'm not saying it aint doable in GUI, but it would be a huge pain and it would certainly slow down the speed of your map a lot
 

WolfieeifloW

WEHZ Helper
Reaction score
372
Yeah, I know my code doesn't cut it, but it's just a base for someone else that can code it.

It check's the unit's life, so it does check if the unit's dead;
Probably just not in the right fashion.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top