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

Guarded Attack v1.0

Guarded Attack
Made by KhaosMachine

Tooltip

(Q)Guarded Attack - [Level 1/2/3/4]

The hero becomes invisible last for 8/10/12/14/16 seconds but his attack is reduced by 25/20/15/10/5%.

Cooldown: 30 seconds
Manacost: 80

vJASS code

JASS:
/*

Guerded Attack v 1.0 made by 'KhaosMachine'

Original idea by 'En_Tropy'

IF YOU WANT TO IMPORT THIS SPELL INTO YOUR MAP YOU HAVE TO COPY THE NEXT THINGS:

*********************************************************************************

TRIGGER EDITOR:
    FOLDERS: NONE
    TRIGGERS: Guarded Attack

OBJECT EDITOR:
    UNITS:      Dummy ('u000')

    ABILITIES:  Guarded Attack  ('A000')
                Guarded Attack  ('A001')
                Invisibility    ('A002')
                
    BUFFS:      Guarded Attack  ('B001')
                

*********************************************************************************

THEN YOU HAVE TO CONFIGURE THE SPELL:

    OBVIOUSLY THINGS:
    
        ABILITY_ID = RAWCODE OF THE SPELL
        REDUCE_ABILITY_ID = RAWCODE OF THE SLOW SPELL
        BUFF_ID = RAWCODE OF THE REDUCE ABILITY ABILITY BUFF
        REDUCE_ABILITY_ORDER = STRING ORDER OF THE REDUCE ABILITY
        ABILITY_INVISIBLE_ID = RAWCODE OF THE INVISIBILITY ABILITY
        DUMMY_ID = RAWCODE OF THE DUMMY
*/

scope guardedAttack initializer init

/****************************************************/*************************************************************
|***                                                      ***|
|**                                                        **|
|*                                                          *|
|====>        ¡¡¡START OF THE CONFIGURATION!!!          <====|
|*                                                          *|
|**                                                        **|
|***                                                      ***|
|************************************************************/

globals
    private constant integer    ABILITY_ID             = 'A000'         //HERO ABILITY ID
    private constant integer    REDUCE_ABILITY_ID      = 'A001'         //REDUCE DAMAGE ABILITY ID
    private constant integer    BUFF_ID                = 'B001'         //REDUCE DAMAGE BUFF ID
    private constant string     REDUCE_ABILITY_ORDER   = "innerfire"    //REDUCE DAMAGE ABILITY ORDER
    private constant integer    ABILITY_INVISIBLE_ID   = 'A002'         //PERMANENT INVISIBILITY ID
    private constant integer    DUMMY_ID               = 'u000'         //DUMMY UNIT ID
    private real                FPS                    = 32             //FRAMES PER SECOND
endglobals

private constant function DURATION takes integer level returns real
    return 6. + 2. * level//SPELL DURATION
endfunction

/****************************************************/*************************************************************
|***                                                      ***|
|**                                                        **|
|*                                                          *|
|====>          ¡¡¡END OF THE CONFIGURATION!!!          <====|
|*                                                          *|
|**                                                        **|
|***                                                      ***|
|************************************************************/

private struct DATA
    unit target
    real duration
endstruct

globals
    private constant timer TIMER = CreateTimer()
    private DATA array ARRAY
    private integer TOTAL = 0
endglobals

private function action takes nothing returns nothing
    local DATA D
    local boolean DESTROY_DATA
    local integer i = 0
    loop
    exitwhen i >= TOTAL
        set D = ARRAY[i]
        set D.duration = D.duration - FPS
        set DESTROY_DATA = D.duration <= 0
        if DESTROY_DATA then
            call IssueImmediateOrder(D.target, "stop")
            call UnitRemoveAbility(D.target, ABILITY_INVISIBLE_ID)
            call UnitRemoveAbility(D.target, BUFF_ID)
            set ARRAY[i] = ARRAY[TOTAL - 1]
            set TOTAL = TOTAL - 1
            call D.destroy()
        endif
        set i = i + 1
    endloop
    if TOTAL == 0 then
        call PauseTimer(TIMER)
    endif
endfunction

private function run takes nothing returns boolean
    local DATA D
    local unit caster
    local unit dummy
    local integer level
    if GetSpellAbilityId() == ABILITY_ID then
        set D = DATA.create()
        set caster = GetTriggerUnit()
        set level = GetUnitAbilityLevel(caster, ABILITY_ID)
        call UnitAddAbility(caster, ABILITY_INVISIBLE_ID)
        set D.target = caster
        set D.duration = DURATION(level)
        set dummy = CreateUnit(GetOwningPlayer(caster), DUMMY_ID, GetUnitX(caster), GetUnitY(caster), 0)
        call UnitAddAbility(dummy, REDUCE_ABILITY_ID)
        call SetUnitAbilityLevel(dummy, REDUCE_ABILITY_ID, level)
        call IssueTargetOrder(dummy, REDUCE_ABILITY_ORDER, caster)
        call UnitApplyTimedLife(dummy, 'BTLF', 0.5)
        if TOTAL == 0 then
            call TimerStart(TIMER, FPS, true, function action)
        endif
        set TOTAL = TOTAL + 1
        set ARRAY[TOTAL - 1] = D
        set caster = null
        set dummy = null
    endif
    return false
endfunction

private function init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer i = 0
    local unit d
    loop
        call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        set i = i + 1
        exitwhen i == bj_MAX_PLAYER_SLOTS
    endloop
    call TriggerAddCondition(t, Condition(function run))
    set FPS = 1 / FPS
    set d = CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE), DUMMY_ID, 0, 0, 0)
    call UnitAddAbility(d, ABILITY_ID)
    call UnitAddAbility(d, BUFF_ID)
    call UnitAddAbility(d, REDUCE_ABILITY_ID)
    call UnitAddAbility(d, ABILITY_INVISIBLE_ID)
    call RemoveUnit(d)
    set d = null
    set t = null
endfunction

endscope

Credits and some info

Credits:
  • KhaosMachine for the SPELL

I made this spell because I love make spells, haha :p. This is my fourth vJASS spell, sorry for the errors or bug

Keywords:
guarded, guarded attack, khaosmachine,spell, vjass.
Contents

Guarded Attack (Map)

Reviews
17:17, 17th Jul 2012 Magtheridon96: Well done. ARRAY -> stack TOTAL -> total DATA -> Data DESTOY_DATA -> destroyData You need to null the target member of the struct before you destroy the instance. set ARRAY[i] = ARRAY[TOTAL - 1]...

Moderator

M

Moderator

17:17, 17th Jul 2012
Magtheridon96: Well done.

  • ARRAY -> stack
  • TOTAL -> total
  • DATA -> Data
  • DESTOY_DATA -> destroyData
  • You need to null the target member of the struct before you destroy the instance.
  • JASS:
    set ARRAY[i] = ARRAY[TOTAL - 1]
    set TOTAL = TOTAL - 1
    You can switch these lines and then use TOTAL as the index of the array.
    You can do something similar here too:
    JASS:
    set TOTAL = TOTAL + 1
    set ARRAY[TOTAL - 1] = D
  • GetOwningPlayer(caster) -> GetTriggerPlayer()
  • You don't need to inline TriggerRegisterAnyUnitEventBJ, it's a good BJ.
  • JASS:
    set DESTROY_DATA = D.duration <= 0
    if DESTROY_DATA then
    ->
    if D.duration <= 0 then
  • This should probably be useful for you.

Anyway, 3.8/5.
Useful.
 
Level 9
Joined
Dec 3, 2010
Messages
162

JASS:
scope guardedAttack initializer init
Scope name should be in CamelCase. Refer to this for more information.

You could use this for registering spell events. I'd recommend using it.

JASS:
private struct DATA
Similar to the above, naming should be CamelCase for Struct name. You could also code everything inside your Struct, instead of using functions. I see that you're storing Struct instances inside a global array and then retrieving it. Instead of doing that, you could simply create a linked list of all instances and loop through it every timer period. You can simply use resources like T32 or CTL for timers dealing with instances.

My Rating: 3/5

The code could be improved. The spell is kind of simple in my opinion. But it could be useful as well.
 
Level 1
Joined
Sep 8, 2012
Messages
5
The spell works fine! but when i add any units to your map and try to run the map it gets stuck on validatin :S and when i delete the unit i added and run it, it works? wtf and i cant move this spell to my map
 
Top