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

Shadow Warp and Aura of Death

Status
Not open for further replies.
Level 10
Joined
Apr 22, 2010
Messages
421
Alright so i want to make two abilities called shadow warp and aura of death. How?

Shadow Warp- 100 mp(+15 per lv) (has 10 levels)
Teleports a target unit 200(+50 per lv) units towards the hero.

Aura of Death- 300 mp(+75 per lv) (has 5 levels)
After 3 seconds of channeling, the hero teleports to a target location(range of 500, +100 per lv) and deals 300(+100 per lv) damage per second to units in a radius of 300 for 5(+1 per lv) seconds.

So, any help? (Aura of death was inspired by Fiddlestick's Ultimate in League of Legends)
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
shadow warp
Use triggers with some trig. You may wish to make it so it can not teleport units passed the hero (as not defined in your problem specification) so cap distance teleported to the minimum of distance between target to hero and the level distance.

Basically all it does is move targeted unit to a position offset related to the angle between the caster and the target.

Aura of Death
Base it on blink. Use triggers to deal the damage over a period of time at the target location. There should even be such a spell already in the spell section.
 
Level 16
Joined
May 1, 2008
Messages
1,605
Moin moin =)

I only can give the aura of death, because 1) I love fiddlestick's ultimate^^ (but at the moment I like Caitlyn more =P) and 2) I don't understand the other spell exactly =S

JASS:
library AuraOfDeath initializer init requires TimerUtils
    
    globals
        private constant    integer S_ID = 'A000'   // Spell Id (rawcode)
        private constant    integer D_ID = 'dum0'   // the dummy in the object editor
        
        private constant    attacktype A = ATTACK_TYPE_NORMAL
        private constant    damagetype D = DAMAGE_TYPE_NORMAL
        private constant    weapontype W = WEAPON_TYPE_WHOKNOWS
        
        private constant    real D_TIME = 1. // Every D_TIME the spell deals damage
        private constant    real C_TIME = 3. // The spell need C_TIME channle tiem
        
        private constant    string D_SFX = "Abilities\\Spells\\Undead\\CarrionSwarm\\CarrionSwarmDamage.mdl"   // An aditional effect
        private constant    real   SFX_AMOUNT = 18. // Aditional effect amount
        
        private constant    boolean SFX_BOOLEAN = true // show the aditional effect?
        private constant    boolean DUM_BOOLEAN = true // show the dummy from the object editor?
        
        // Don't change the constants below
        
        private constant real L_TIME = 0.04
        private constant group G = CreateGroup()
    endglobals
    
    private function damage takes integer level returns real
        return 250. + 75. * level
    endfunction
    
    private function area takes integer level returns real
        return 300.
    endfunction
    
    private function duration takes integer level returns real
        return 4. + 1. * level
    endfunction
    
    // Configuration ends here \\
    
    private struct AuraOfDeath
        static thistype TEMP
        unit    caster = null
        unit    dummy  = null
        real    x = 0.
        real    y = 0.
        real    c = 0. //Counter
        real    d = 0.
        real    a = 0.
        real    t = 0. // timer
        real    dur = 0.
        boolean b = true
        
        private static method filter takes nothing returns boolean
            local thistype this = TEMP
            local unit u = GetFilterUnit()
            
            if GetWidgetLife(u) > 0.405 and IsUnitEnemy(u,GetOwningPlayer(.caster)) and IsUnitType(u,UNIT_TYPE_STRUCTURE) == false and IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) == false then
                call UnitDamageTarget(.caster,u,.d,true,false,A,D,W)
            endif
            return false
        endmethod
        
        private static method Loop takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype this = GetTimerData(t)
            local integer i = 0
            local real x
            local real y
            
            if DUM_BOOLEAN == true then
                call SetUnitX(.dummy,GetUnitX(.caster))
                call SetUnitY(.dummy,GetUnitY(.caster))
            endif
            
            if .b == true then
                set .c = .c + L_TIME
                if .c >= C_TIME then
                    set .b = false
                    set .c = 0.
                    call SetUnitX(.caster,.x)
                    call SetUnitY(.caster,.y)
                    call PauseUnit(.caster,false)
                    if DUM_BOOLEAN == true then
                        set .dummy = CreateUnit(GetOwningPlayer(.caster),D_ID,GetUnitX(.caster),GetUnitY(.caster),0.)
                    endif
                    
                    set TEMP = this
                    call GroupEnumUnitsInRange(G,GetUnitX(.caster),GetUnitY(.caster),.a,Condition(function AuraOfDeath.filter))
            
                    if SFX_BOOLEAN == true then
                        loop
                            exitwhen i == SFX_AMOUNT
                            set x = GetUnitX(.caster) + .a / 3 * Cos(360 / SFX_AMOUNT * i * bj_DEGTORAD)
                            set y = GetUnitY(.caster) + .a / 3 * Sin(360 / SFX_AMOUNT * i * bj_DEGTORAD)
                            call DestroyEffect(AddSpecialEffect(D_SFX,x,y))
                            set i = i + 1
                        endloop
                        set i = 0
                        loop
                            exitwhen i == SFX_AMOUNT
                            set x = GetUnitX(.caster) + .a / 2 * Cos(360 / SFX_AMOUNT * i * bj_DEGTORAD)
                            set y = GetUnitY(.caster) + .a / 2 * Sin(360 / SFX_AMOUNT * i * bj_DEGTORAD)
                            call DestroyEffect(AddSpecialEffect(D_SFX,x,y))
                            set i = i + 1
                        endloop
                    endif
                endif
            
            elseif .b == false then
                set .c = .c + L_TIME
                set .t = .t + L_TIME
                        
                if .c >= D_TIME then
                    set .c = 0.
                    
                    if SFX_BOOLEAN == true then
                        loop
                            exitwhen i == SFX_AMOUNT
                            set x = GetUnitX(.caster) + .a / 3 * Cos(360 / SFX_AMOUNT * i * bj_DEGTORAD)
                            set y = GetUnitY(.caster) + .a / 3 * Sin(360 / SFX_AMOUNT * i * bj_DEGTORAD)
                            call DestroyEffect(AddSpecialEffect(D_SFX,x,y))
                            set i = i + 1
                        endloop
                        set i = 0
                        loop
                            exitwhen i == SFX_AMOUNT
                            set x = GetUnitX(.caster) + .a / 2 * Cos(360 / SFX_AMOUNT * i * bj_DEGTORAD)
                            set y = GetUnitY(.caster) + .a / 2 * Sin(360 / SFX_AMOUNT * i * bj_DEGTORAD)
                            call DestroyEffect(AddSpecialEffect(D_SFX,x,y))
                            set i = i + 1
                        endloop
                    endif
                    set TEMP = this
                    call GroupEnumUnitsInRange(G,GetUnitX(.caster),GetUnitY(.caster),.a,Condition(function AuraOfDeath.filter))
                endif
                
                if .t >= .dur then
                    call RemoveUnit(.dummy)
                    call .destroy()
                    call ReleaseTimer(t)
                endif
            endif
            set t = null
        endmethod

        static method create takes unit caster, real x, real y returns thistype
            local thistype this = .allocate()
            local timer t = NewTimer()
            local integer i = 0
            
            set .caster = caster
            set .x = GetSpellTargetX()
            set .y = GetSpellTargetY()
            set .d = damage(GetUnitAbilityLevel(.caster,S_ID))
            set .dur = duration(GetUnitAbilityLevel(.caster,S_ID))
            set .a = area(GetUnitAbilityLevel(.caster,S_ID))
            
            call PauseUnit(.caster,true)
            call SetTimerData(t,this)
            call TimerStart(t,L_TIME,true,function AuraOfDeath.Loop)
            set t = null
            return this
        endmethod
    endstruct
        
    private function cast takes nothing returns boolean
        if GetSpellAbilityId() == S_ID then
            call AuraOfDeath.create(GetTriggerUnit(),GetSpellTargetX(),GetSpellTargetY())
        endif
        return false
    endfunction
    
    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i = 0
        
        loop
            exitwhen i == 16
            call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
            set i = i + 1
        endloop
        call TriggerAddCondition(t,Condition(function cast))
        call Preload(D_SFX)
        
        set t = null
    endfunction
endlibrary

PROBLEM: I don't know why the dummy isn't moving to the caster point, maybe you set the dummy boolean to false, until I found a solution =O

Greetings and Peace
Dr. Boom
 

Attachments

  • this2.w3x
    24.8 KB · Views: 121
Level 2
Joined
Feb 8, 2011
Messages
31
PROBLEM: I don't know why the dummy isn't moving to the caster point, maybe you set the dummy boolean to false, until I found a solution =O

I had a similar problem once. In the test map, your dummy unit has 0 movement speed. SetUnitX and SetUnitY only visibly move the specified unit if the unit has movement speed (or maybe it was if the unit's movement type isn't None, I'm not sure).

On a side note, you could use static ifs every time you check the booleans "SFX_BOOLEAN" and "DUM_BOOLEAN". You could also use one timer for the spell since it runs in such short intervals instead of using TimerUtils.
 
Level 10
Joined
Apr 22, 2010
Messages
421
@Dr.Boom: Is there a way to create this spell using Warcraft Triggers?, if not, then can u tell me how to implant jass codes? Oh yea, shadow warp works like this: 1.u cast it(targets a single unit) 2. The unit is teleported 200 area(idk the measurment for distance in wc) closer to ur hero.

P.S. Fiddlestick rocks, but he is also wayyyy OPed. I also like Mordekaiser. You can add me as your buddy there, my name is: Vetreis (yes there is a cap)

Also, i tested ur map, but why dosent the aura effect move with the hero?
 
Level 16
Joined
May 1, 2008
Messages
1,605
Moin moin =)

Ok I will add you =) Edit: The account doesn't exist =D

=== How to implant the spell ===
1) You create a new trigger, name it AuraOfDeath and convert it to custom text (under edit)
2) Now you copy my code from the side and past it into the created trigger.
3) Now you just need to copy the ability and the dummy from the object editor into your map.

4) After copy the ability and the dummy into your map, you need to check the rawcodes of both "Press Ctrl + D", there you see the codes and you have to change them in the spell.

=== How to fix the Dummy ===
Thanks to Stranger: You need to set the movementtype of the dummy to "Foot" and the movementspeed to "1", then it works

=== About the other spell ===
I see what I can do =)

Greetings and Peace
Dr. Boom
 
Level 2
Joined
Feb 8, 2011
Messages
31
Sorry Dr. Boom. I didn't realize you were going to work on the other spell.

Well solomon, I assume this is what you wanted. It teleports the target unit towards the caster, and the unit won't go past the caster.

Shadow Warp:
 

Attachments

  • Shadow_Warp.w3x
    22.2 KB · Views: 112

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
Dr. Boom, you need to learn to code better..

JASS:
library AuraOfDeath initializer init requires TimerUtils
    
    globals
        private constant    integer S_ID = 'A000'   // Spell Id (rawcode)
        private constant    integer D_ID = 'dum0'   // the dummy in the object editor
        
        private constant    attacktype A = ATTACK_TYPE_NORMAL
        private constant    damagetype D = DAMAGE_TYPE_NORMAL
        private constant    weapontype W = WEAPON_TYPE_WHOKNOWS
        
        private constant    real D_TIME = 1. // Every D_TIME the spell deals damage
        private constant    real C_TIME = 3. // The spell need C_TIME channle tiem
        
        private constant    string D_SFX = "Abilities\\Spells\\Undead\\CarrionSwarm\\CarrionSwarmDamage.mdl"   // An aditional effect
        private constant    real   SFX_AMOUNT = 18. // Aditional effect amount
        
        private constant    boolean SFX_BOOLEAN = true // show the aditional effect?
        private constant    boolean DUM_BOOLEAN = true // show the dummy from the object editor?
        
        // Don't change the constants below
        
        private constant real L_TIME = 0.04
        private constant group G = CreateGroup()
        
        private constant real ANGLE = 360 / SFX_AMOUNT * bj_DEGTORAD
    endglobals
    
    private function damage takes integer level returns real
        return 250. + 75. * level
    endfunction
    
    private function area takes integer level returns real
        return 300.
    endfunction
    
    private function duration takes integer level returns real
        return 4. + level
    endfunction
    
    // Configuration ends here \\
    
    private struct AuraOfDeath
        static thistype TEMP
        unit    caster = null
        unit    dummy  = null
        real    x = 0.
        real    y = 0.
        real    c = 0. //Counter
        real    d = 0.
        real    a = 0.
        real    t = 0. // timer
        real    dur = 0.
        boolean b = true
        
        private static method filter takes nothing returns boolean
            local thistype this = TEMP
            local unit u = GetFilterUnit()
            
            if GetWidgetLife(u) > 0.405 and IsUnitEnemy(u,GetOwningPlayer(.caster)) and IsUnitType(u,UNIT_TYPE_STRUCTURE) == false and IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) == false then
                call UnitDamageTarget(.caster,u,.d,true,false,A,D,W)
            endif
            set u = null
            return false
        endmethod
        
        private method areaEffect takes nothing returns nothing
            local real x = .x
            local real y = .y
            local real sin
            local real cos
            local real ha = .a/2
            local real ta = .a/3
            local integer i = 0
            set .c = 0. // this should not really be here but it is duplicated otherwise
            if SFX_BOOLEAN == true then
                loop
                    set sin = Sin(ANGLE * i)
                    set cos = Cos(ANGLE * i)
                    call DestroyEffect(AddSpecialEffect(D_SFX,x + ta * cos,y + ta * sin))
                    call DestroyEffect(AddSpecialEffect(D_SFX,x + ha * cos,y + ha * sin))
                    set i = i + 1
                    exitwhen i == SFX_AMOUNT
                endloop
            endif
            set TEMP = this
            call GroupEnumUnitsInRange(G,x,y,.a,Condition(function AuraOfDeath.filter))
        endmethod
        
        private static method Loop takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype this = GetTimerData(t)
            local integer i = 0
//            local real x = GetUnitX(.caster)
//            local real y = GetUnitY(.caster)
            
//            if DUM_BOOLEAN == true then
//                call SetUnitX(.dummy,x)
//                call SetUnitY(.dummy,y)
//            endif
            
            if .b then
                set .c = .c + L_TIME
                if .c >= C_TIME then
                    set .b = false
                    
                    call SetUnitX(.caster,.x)
                    call SetUnitY(.caster,.y)
                    call PauseUnit(.caster,false)
//                    if DUM_BOOLEAN == true then
//                        set .dummy = CreateUnit(GetOwningPlayer(.caster),D_ID,x,y,0.)
//                    endif

                    call .areaEffect()
                endif
            
            else
                set .c = .c + L_TIME
                set .t = .t + L_TIME
                        
                if .c >= D_TIME then
                    call .areaEffect()
                endif
                
                if .t >= .dur then
                    call KillUnit(.dummy)
                    //call RemoveUnit(.dummy) // THIS LEAKS
                    call .destroy()
                    call ReleaseTimer(t)
                endif
            endif
            set t = null
        endmethod

        static method create takes unit caster, real x, real y returns thistype
            local thistype this = .allocate()
            local timer t = NewTimer()
            local integer i = 0
            local integer level = GetUnitAbilityLevel(caster,S_ID);
            
            set .caster = caster
            set .x = GetSpellTargetX()
            set .y = GetSpellTargetY()
            set .d = damage(level)
            set .dur = duration(level)
            set .a = area(level)
            
            call PauseUnit(caster,true)
            call SetTimerData(t,this)
            call TimerStart(t,L_TIME,true,function AuraOfDeath.Loop)
            set t = null
            return this
        endmethod
    endstruct
        
    private function cast takes nothing returns boolean
        if GetSpellAbilityId() == S_ID then
            call AuraOfDeath.create(GetTriggerUnit(),GetSpellTargetX(),GetSpellTargetY())
        endif
        return false
    endfunction
    
    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i = 0
        
        loop
            exitwhen i == 16
            call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
            set i = i + 1
        endloop
        call TriggerAddCondition(t,Condition(function cast))
        call Preload(D_SFX)
        
        set t = null
    endfunction
endlibrary

I do not understand what the dummy is meant to do so the involved code has been commented out. Take note of all the optimizations that were present. The code may have a typo or atmost a minor bug as I have not been able to test it but you should be clarly able to see the optimizations that you could have done. The code is still far from perfect as you could probably change its design for even less redundency.
 
Level 16
Joined
May 1, 2008
Messages
1,605
First of all let me say, that I NEED nothing except eat - drink and die ok? (just for the board)

So far so good, I make this only for fun, I make (high calculate) 1 code in a month,
if I help someone maybe 2. And I think it's a good moment to say that, if I see, what creepy shit gets approved in the spell section, I think my way of coding is more then just good y...

Also I get help from dudes here, with owned high skill and when I ask, how to improve my codes and they don't say such things like that, I think my codes are fine and good. Thing is I really have problems to understand English and if I try to learn something in a tutorial here, it sounds like crazy Chinese stuff ± . ±

That you have ultra high skills with this, isn't a secret, but I'm not trying to win a price with my codes so.. =)
[But when you say I can improve it a lot more even after your changes, would you be so fine and can send a whole fixed code via pm to me please? =) ]

Thanks - Greetings - Peace
Dr. Boom
 
Status
Not open for further replies.
Top