• 💀 Happy Halloween! 💀 It's time to vote for the best terrain! Check out the entries to Hive's HD Terrain Contest #2 - Vampire Folklore.❗️Poll closes on November 14, 2023. 🔗Click here to cast your vote!
  • 🏆 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!
  • 🏆 HD Level Design Contest #1 is OPEN! Contestants must create a maze with at least one entry point, and at least one exit point. The map should be made in HD mode, and should not be openable in SD. Only custom models from Hive's HD model and texture sections are allowed. The only exceptions are DNC models and omnilights. This is mainly a visual and design oriented contest, not technical. The UI and video walkthrough rules are there to give everyone an equal shot at victory by standardizing how viewers see the terrain. 🔗Click here to enter!

vJASS Charge 1.00

  • Like
Reactions: QuantumMatter
A Simple Charge Spell made in vJASS, Highly Customizable.
Yeah, it's not an original spell, but i used this as training for vJASS coding. Since i made it highly customizable and easy to import i thought that sharing it would've helped someone, maybe.

It uses Silvenon's Knockback Function, Vexorian's Handle Timers Function and Captain Griffen's Attach Timer Function.

IT USES vJASS SYNTAX, SO IT REQUIRES JASS NEW GEN PACK TO BE MODIFIED

Since this is my first spell i've surely messed something up, so any comment is very appreciated.


1.00
- Minor changes, Final Release (hopefully :D)

0.95
- Modified the path checker function, now it works even in the (very unlikely to happen) case of a wall in the middle of an area covered by items (so now you will understand why i put all thoose items in the right part of the map) Thanks to Mooglefrooglian for the tip

0.92
- Modified the initTrig function (Thanks to Thanatos for the tips)

0.91
- Now it uses coordinates instead of locations
- Merged Some triggers, others left for readability
- Made a tinier map (no point for a 128x128 testing map)

- 0.9
First Release




JASS:
// **************************************************************************
// ** **
// ** Charge **
// ** ————————————— **
// ** **
// ** A simple Charge Spell **
// ** **
// ** By: Majin **
// ** 
// ** **
// **************************************************************************

library ChargeExec requires Knockback

    struct ChargeLoop
        private real ChargeTargetx
        private real ChargeTargety
        private real ChargeEndx
        private real ChargeEndy
        private real ChargeLocx
        private real ChargeLocy
        private real ChargeNextx
        private real ChargeNexty
        private unit ChargeTarget
        private unit ChargeCaster
        private real ChargeAngle
        private real ChargeDistance
        private effect ChargeEffect
        private timer ChargeTimer
        private boolean ChargeCond = false
        private integer SpellLvl
        
        //START OF CONFIGURATION METHODS
        
        //With this method you can set the "acceleration rate" (Physicists  Forgive me) of the charge.
        //You can use any kind of numeric function (for example this.ChargeDistance * 2.00 will double
        //The speed at every loop)
        private method ChangeDistance takes nothing returns real
            return this.ChargeDistance + 1.00
        endmethod
        //END OF CONFIGURATION METHODS
        
        //START OF CUSTOMIZABLE METHODS
        
        //This method sets the conditions when to activate the AlmostCharge method. In particular
        //You may be interested in changing the distance at where the condition is true. 
        //In this Example it will be activated when the Caster is 16x times the Charge Speed Far away
        //From the target
        private method AlmostChargeCond takes nothing returns boolean
            return ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx,  this.ChargeEndy) < ( this.ChargeDistance * 16.00 )) and this.ChargeCond == false)
        endmethod
        
        //Actions to take when the Charge is almost completed. In this example the caster will play
        //The slam animation (Being a Blademaster, it will jump in the air while attacking)
        private method AlmostCharge takes nothing returns nothing
            set this.ChargeCond = true
            call SetUnitTimeScale( this.ChargeCaster, 2.00 )
            call SetUnitAnimation( this.ChargeCaster, "slam" )
            call QueueUnitAnimation( this.ChargeCaster, "stand")
        endmethod
        
        //Actions to take when the Caster reaches its target and the charge is completed. 
        //In this example the target unit will be stunned and you will see a Thunderclap effect on the ground
        private method CompleteCharge takes nothing returns nothing
            local effect tempEffect
            local unit dummy
            local real angle=GetAngle(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy)
            
            set this.ChargeLocx = this.ChargeNextx
            set this.ChargeLocy = this.ChargeNexty
            set this.ChargeNextx = PolarProjectionx(this.ChargeLocx, this.ChargeDistance, this.ChargeAngle)
            set this.ChargeNexty = PolarProjectiony(this.ChargeLocy, this.ChargeDistance, this.ChargeAngle)
            
            set tempEffect = AddSpecialEffect( WALKEFFECT, this.ChargeLocx, this.ChargeLocy )
            call DestroyEffect( tempEffect )
            
            call SetUnitX( this.ChargeCaster, this.ChargeEndx )
            call SetUnitY( this.ChargeCaster, this.ChargeEndy )
            
            set dummy = CreateUnit( GetOwningPlayer(this.ChargeCaster), DUMMYID, this.ChargeLocx, this.ChargeLocy, 0 )
            call UnitAddAbility( dummy, DUMMYSPELLID )
            call SetUnitAbilityLevel(dummy, DUMMYSPELLID, this.SpellLvl)
            call IssueTargetOrder( dummy, SPELLORDERID, this.ChargeTarget )
            call UnitApplyTimedLife( dummy, 'BTLF', 1.00)
            
            set tempEffect = AddSpecialEffect( ENDINGEFFECT, this.ChargeLocx, this.ChargeLocy )
            call DestroyEffect( tempEffect )
            
            call UnitDamageTarget( this.ChargeCaster, this.ChargeTarget, CHARGEDAMAGE*this.SpellLvl, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
            call PauseUnit( this.ChargeCaster, false )
            //This is the Knockback effect, see the Knock Trigger for more customization options
            call KnockbackEx(this.ChargeTarget, KNOCKDISTANCE*this.SpellLvl, angle, KNOCKDURATION, KnockTree(), KNOCKPLAYEFFECT, KNOCKEFFECT, KNOCKATTACH)
            call IssueTargetOrder( this.ChargeCaster, "attack", this.ChargeTarget )
            
            set tempEffect = null
            set dummy = null
        endmethod

        //What to do during the charge, the unit is moved, an effect is placed on the ground and
        //the charging speed is increased
        private method ContinueCharge takes nothing returns nothing
            local effect tempEffect
            set tempEffect = AddSpecialEffect( WALKEFFECT, this.ChargeLocx, this.ChargeLocy )
            call DestroyEffect( tempEffect )
            
            call SetUnitX(this.ChargeCaster, this.ChargeNextx)
            call SetUnitY(this.ChargeCaster, this.ChargeNexty)
            
            call SetUnitFacing(this.ChargeCaster, bj_RADTODEG * GetAngle(this.ChargeNextx, this.ChargeNexty, this.ChargeTargetx, this.ChargeTargety))
            
            set this.ChargeLocx = this.ChargeNextx
            set this.ChargeLocy = this.ChargeNexty
            set this.ChargeNextx = PolarProjectionx(this.ChargeLocx, this.ChargeDistance, this.ChargeAngle)
            set this.ChargeNexty = PolarProjectiony(this.ChargeLocy, this.ChargeDistance, this.ChargeAngle)
                        
            if (this.ChargeDistance <= MAXSPEED) then
                set this.ChargeDistance = this.ChangeDistance()
            endif
            
            set tempEffect = null
        endmethod
        
        //END OF CUSTOMIZABLE METHODS
        
        //START OF OTHER METHODS
        //This is the main method executed during the charge
        public static method ChargeActions takes nothing returns nothing
            local ChargeLoop l=GetTimerInt(GetExpiredTimer())
            
            set l.ChargeTargetx = GetUnitX(l.ChargeTarget)
            set l.ChargeTargety = GetUnitY(l.ChargeTarget)
            set l.ChargeEndx = PolarProjectionx(l.ChargeTargetx, 100.00, GetAngle(l.ChargeTargetx, l.ChargeTargety, l.ChargeLocx, l.ChargeLocy))
            set l.ChargeEndy = PolarProjectiony(l.ChargeTargety, 100.00, GetAngle(l.ChargeTargetx, l.ChargeTargety, l.ChargeLocx, l.ChargeLocy))
            
            set l.ChargeAngle = GetAngle(l.ChargeLocx, l.ChargeLocy, l.ChargeEndx, l.ChargeEndy)
            if ( l.AlmostChargeCond() ) then
            //What to do when the caster is about to reach the target
                call l.AlmostCharge()
            endif
            //If the Target gets too far away (by teleportation, for example) then stops the Charge
            if ( GetDistance(l.ChargeLocx, l.ChargeLocy, l.ChargeEndx, l.ChargeEndy) >= MAXDISTANCE and (MAXDISTANCE != 0.00) ) then
                call l.StopCharge()
            endif
            if ( l.ChargeConditions() ) then
            //If the unit hasn't reached the target yet, then execute this
                call l.ContinueCharge()
                call TimerAttach(l.ChargeTimer,0.03,l,function ChargeLoop.ChargeActions)
            else
                if ( l.ChargeCompleted() ) then
            //What to do if the charge is succesfully completed
                    call l.CompleteCharge()
                endif
                call l.StopCharge()
            endif
        endmethod
        
        //Actions to take once the Charge is being stopped (either because it wasn't possible to complete
        //the charge or because the caster reached its target)
        private method StopCharge takes nothing returns nothing
            set this.ChargeCond = false
            call SetUnitPathing(this.ChargeCaster, true)
            call PauseUnit(this.ChargeCaster, false)
            call SetUnitAnimation(this.ChargeCaster, "stand")
            call SetUnitTimeScale(this.ChargeCaster, 1.00)
            call DestroyEffect(this.ChargeEffect)
            call this.destroy()
        endmethod
        
        private method ChargeCompleted takes nothing returns boolean
            if ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) <= this.ChargeDistance*1.10)  and IsPointWalkable(this.ChargeNextx, this.ChargeNexty)) then
                if ((IsTerrainPathable(this.ChargeNextx, this.ChargeNexty, PATHING_TYPE_WALKABILITY) == false ) and ( (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false )) then
                    if(((GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false)) then
                        return true
                    endif
                endif
            endif
                return false
        endmethod

        private method ChargeConditions takes nothing returns boolean
            if ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) > this.ChargeDistance*1.10)  and IsPointWalkable(this.ChargeNextx, this.ChargeNexty)) then
                if ((IsTerrainPathable(this.ChargeNextx, this.ChargeNexty, PATHING_TYPE_WALKABILITY) == false ) and ( (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false )) then 
                    if(((GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false)) then
                        return true
                    endif
                endif
            endif
                return false
        endmethod
        
        private method onDestroy takes nothing returns nothing
            call ReleaseTimer(this.ChargeTimer)
            set this.ChargeTarget = null
            set this.ChargeCaster = null
            set this.ChargeEffect = null
        endmethod
        
        static method create takes real pChargeTargetx, real pChargeTargety, real pChargeEndx, real pChargeEndy, real pChargeLocx, real pChargeLocy, real pChargeNextx, real pChargeNexty, unit pChargeTarget, unit pChargeCaster, real pChargeAngle, real pChargeDistance, effect pChargeEffect, timer pChargeTimer returns ChargeLoop
            local ChargeLoop l = ChargeLoop.allocate()
            set l.ChargeTargetx = pChargeTargetx
            set l.ChargeTargety = pChargeTargety
            set l.ChargeEndx = pChargeEndx
            set l.ChargeEndy = pChargeEndy
            set l.ChargeLocx = pChargeLocx
            set l.ChargeLocy = pChargeLocy
            set l.ChargeNextx = pChargeNextx
            set l.ChargeNexty = pChargeNexty
            set l.ChargeTarget = pChargeTarget
            set l.ChargeCaster = pChargeCaster
            set l.ChargeAngle = pChargeAngle
            set l.ChargeDistance = pChargeDistance
            set l.ChargeEffect = pChargeEffect
            set l.ChargeTimer = pChargeTimer
            set l.SpellLvl = GetUnitAbilityLevel(l.ChargeCaster, SPELLID) 
            return l
        endmethod
        
        //END OF OTHER METHODS
    endstruct
endlibrary

//TRIGGER OF THE CHARGE SPELL
scope Charge initializer InitTrig
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == SPELLID
    endfunction

    private function CheckActions takes nothing returns nothing
        local real ChargeLocx = GetUnitX(GetTriggerUnit())
        local real ChargeLocy = GetUnitY(GetTriggerUnit())
        local real ChargeEndx = GetUnitX(GetSpellTargetUnit())
        local real ChargeEndy = GetUnitY(GetSpellTargetUnit())
        
        if ( GetDistance(ChargeLocx, ChargeLocy, ChargeEndx, ChargeEndy) <= (MINDISTANCE) ) then
            call DisplayTextToPlayer( GetOwningPlayer(GetTriggerUnit()), 0, 0, "|cffFFCC00Target is too close!|r" )
            call PlaySound( "Sound\\Interface\\Error.wav" )
            call IssueImmediateOrder( GetTriggerUnit(), "stop" )
        endif
    endfunction
    
    private function InitActions takes nothing returns nothing
        local timer ChargeTimer = NewTimer()
        local effect ChargeEffect
        local unit ChargeCaster = GetTriggerUnit()
        local unit ChargeTarget = GetSpellTargetUnit()
        local real ChargeDistance = STARTSPEED
        local real ChargeLocx = GetUnitX(ChargeCaster)
        local real ChargeLocy = GetUnitY(ChargeCaster)
        local real ChargeTargetx = GetUnitX(ChargeTarget)
        local real ChargeTargety = GetUnitY(ChargeTarget)
        local real ChargeEndx = PolarProjectionx(ChargeTargetx, 100.00, GetAngle(ChargeTargetx, ChargeTargety, ChargeLocx, ChargeLocy))
        local real ChargeEndy = PolarProjectiony(ChargeTargety, 100.00, GetAngle(ChargeTargetx, ChargeTargety, ChargeLocx, ChargeLocy))
        local real ChargeAngle = GetAngle(ChargeLocx, ChargeLocy, ChargeEndx, ChargeEndy)
        local real ChargeNextx = PolarProjectionx(ChargeLocx, ChargeDistance, ChargeAngle)
        local real ChargeNexty = PolarProjectiony(ChargeLocy, ChargeDistance, ChargeAngle)
        local ChargeLoop stru
        
        set ChargeEffect = AddSpecialEffectTarget(ATTACHEDEFFECT, ChargeCaster, "chest" )
        
        set stru = ChargeLoop.create(ChargeTargetx, ChargeTargety, ChargeEndx, ChargeEndy, ChargeLocx, ChargeLocy, ChargeNextx, ChargeNexty, ChargeTarget, ChargeCaster, ChargeAngle, ChargeDistance, ChargeEffect, ChargeTimer)
        call SetUnitPathing(ChargeCaster, false)
        call SetUnitTimeScale(ChargeCaster, 3)
        call IssueImmediateOrder(ChargeCaster, "stop" )
        call PauseUnit(ChargeCaster, true)
        call SetUnitAnimationByIndex(ChargeCaster,6)
        call TimerAttach(ChargeTimer,0,stru,function ChargeLoop.ChargeActions)
        
        set ChargeTimer = null
        set ChargeEffect = null
        set ChargeCaster = null
        set ChargeTarget = null
    endfunction

    private function AntiLeak takes nothing returns boolean
        return true
    endfunction

    private function InitTrig takes nothing returns nothing
        local trigger ChargeCheck = CreateTrigger()
        local trigger ChargeInit = CreateTrigger()
        local filterfunc f = Filter(function AntiLeak)
        local integer i = 0
        loop
            exitwhen i == 16
            call TriggerRegisterPlayerUnitEvent(ChargeCheck,Player(i),EVENT_PLAYER_UNIT_SPELL_CAST,f)
            call TriggerRegisterPlayerUnitEvent(ChargeInit,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,f)
            set i = i + 1
        endloop
        call TriggerAddCondition(ChargeCheck, Condition(function Conditions))
        call TriggerAddAction(ChargeCheck, function CheckActions)
        call TriggerAddCondition(ChargeInit, Condition(function Conditions))
        call TriggerAddAction(ChargeInit, function InitActions)
        set ChargeCheck = null
        set ChargeInit = null
        set f = null
    endfunction
endscope


Keywords:
Charge, vJASS, Script, Run, Blademaster, Animation, Timers, Pathchecker, Knockback, Stun, Path, Checker, Path Checker, Math, Kill, Knock, Back, Charge
Contents

Charge Spell (Map)

Reviews
18:06, 21st Sep 2009 The_Reborn_Devil: Triggering looks nice and I couldn't find any leaks. I really like the effects (especially the running part). Anyway, spell approved. I give this spell the rating useful. It's almost recommended...

Moderator

M

Moderator

18:06, 21st Sep 2009
The_Reborn_Devil:

Triggering looks nice and I couldn't find any leaks.
I really like the effects (especially the running part).

Anyway, spell approved.
I give this spell the rating useful.
It's almost recommended though, something like 3.8/5.
There were some other small things, but it's not that important.
 
Level 9
Joined
Aug 2, 2008
Messages
219
from what i´ve seen it looks quite good, but haven´t checked for leaks yet...
one thing i complain about is that you used some BJ (mainly for mathematical calculations), but you could have inlined them. There is also another faw, some of your functions are heavy actions blocks which are hard2read, so you could add some free lines to them. For now i give you a 3/5 because of the BJ´s and a lack of creativity.
Ehmn and why did you rename the triggers for the libraries, it´s a bit confusing.

~TNT
 
Level 7
Joined
Mar 24, 2008
Messages
184
Ehmn and why did you rename the triggers for the libraries, it´s a bit confusing.

Sorry?

Anyways, not that i was expecting big things from this spell. Also the only BJs function i used are distance between points and PolarProjection, i always thought the important thing was to avoid swapped versions of normal functions, thoose are inefficient, other BJs should work as fine as if you defined your own function and used in your map. Well, i could be wrong ofc...

Anyways, Thanks for your comment :)
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
the unit will pass through other units
Umm that is one failure :p no offense...

Umm, as TNT said, Polar projections are bad, and even angle between points...

Umm, three triggers in Jass? It's Jass and thus I won't be wanting to copy more then one trigger (systems are exceptions...) and so make the three charge triggers one...

Gd job...
 
Level 7
Joined
Mar 24, 2008
Messages
184
Umm that is one failure :p no offense...

Umm, as TNT said, Polar projections are bad, and even angle between points...

Umm, three triggers in Jass? It's Jass and thus I won't be wanting to copy more then one trigger (systems are exceptions...) and so make the three charge triggers one...

Gd job...

Yeah, i've realized that now, i'm modifying it so it'll use coords instead of locations, i'll also make that change...actually it was planned but i was just too tired today and i wanted to upload it as it was :p

Oh and the move through units while charging is intentional


EDIT:

Spell Updated, now it uses coords instead of locations, and i've merged some triggers, the others are left for more readability
 
Last edited:
Level 17
Joined
Mar 17, 2009
Messages
1,349
Believe me, whoever doesn't know Jass won't know how to read both ways :p and that who knows, can read anything :p

And since the pass through units is intentional, here's a nice idea so that it seems professional... everytime the unit passes through another, create a "magic-like" special effect :) what do you think about that?

EDIT:
and maybe you could minorly damage that who the unit goes through ;)
 
Level 7
Joined
Mar 24, 2008
Messages
184
Believe me, whoever doesn't know Jass won't know how to read both ways :p and that who knows, can read anything :p

Yes but there's a difference between being able to read anything, and the difficulty of reading something.

What would you think of a book written in the Language you know best but on a single very long page? How easily would you find things on such a book?

I don't think there's the need of merging everything on a single trigger...i like thinking of thoose as if they were java classes, each one provides a single functionality (and i even merged all the libraries, except the knockback one, in a single trigger) or packages in the worst case (providing a set of functionalities), and i think it's fine as it is now.

And since the pass through units is intentional, here's a nice idea so that it seems professional... everytime the unit passes through another, create a "magic-like" special effect :) what do you think about that?

EDIT:
and maybe you could minorly damage that who the unit goes through ;)

I think that there are already too many effects, adding more would mean that some effect will go unnoticed or either it'll be too much.

This spell is meant to be simple but highly customizable, i like to think that if someone would do such a Spell (which does what you are saying, let's call it..."Meteor Strike" or "Cometary Collision", whatev...) using mine as base, would be able to do it without any problem if he has basic JASS (not even vJASS) knowledge (for example, he could put in the ContinueCharge method this functionality, picking all the units near the Caster unit, slightly Knocking them away and damaging them).

Also, i'm going to use this spell on a map of mine (with some changes) and the idea under this spell was to a sort of Blink for non-mages unit, that's why i added this functionality. If you don't want it then you could just modify the "IsPointWalkable" function according to your needs.

Notice that buildings, trees and other obstacles will still interrupt the charge
 
Level 9
Joined
Aug 2, 2008
Messages
219
Ok some code changes made but there are still some things...
Why did you merge the triggers for the libraries ? It´s good to have for each library a different trigger, what you really should merge are your three triggers. (Just put the configuration part on top).

And whats the deal with your InitTrig in the Charge trigger ? Don´t make i public, use initializer instead and get rid of the last BJ´s :p
JASS:
scope Charge initializer InitTrig

    //   [Your Stuff Here]
    
    private function AntiLeak takes nothing returns boolean
        return true
    endfunction    
    
    private function InitTrig takes nothing returns nothing
        local trigger ChargeCheck = CreateTrigger()
        local trigger ChargeInit = CreateTrigger()
        local filterfunc f = Filter(function AntiLeak)
        local integer i = 0
        loop
            exitwhen i == 16
            call TriggerRegisterPlayerUnitEvent(ChargeCheck,Player(i),EVENT_PLAYER_UNIT_SPELL_CAST,f)
            call TriggerRegisterPlayerUnitEvent(ChargeInit,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,f)
            set i = i + 1
        endloop
        call TriggerAddCondition(ChargeCheck, Condition(function Conditions))
        call TriggerAddAction(ChargeCheck, function CheckActions)
        call TriggerAddCondition(ChargeInit, Condition(function Conditions))
        call TriggerAddAction(ChargeInit, function InitActions)
        set ChargeCheck = null
        set ChargeInit = null
        set f = null
    endfunction

endscope
You can c´n´p this.


Btw how could you compile Slivenons Knockback ? Everytime i try my JNGP says: Error at Memory 0xFFFFFFFF. Could not be read. (0xFFFFFFFF = -1 in Decimal System) So i always wonder...
 
Level 7
Joined
Mar 24, 2008
Messages
184
Maybe because you are using a new version of JNGP, i'm still using the one compatible with 1.21 (i had some problems with wc3 1.22, the new JNGP and some maps so i went back to 1.21, then i never updated again since i stopped making maps for some time). I'll see if i can find some other reason

Anyways, i still don't see the point in merging the triggers, i think it's better to have configuration and code on two separate triggers, i can merge the trigger and the struct part, but i'm not going to merge config.

EDIT: Modified the init trig and merged with ChargeExec, but that's all. I'm not going to merge config and exec, because it's pointless and doesn't improve efficiency, it just reduces readability.

EDIT 2: I downloaded the last JNGP and War3 patch, and my map works fine

EDIT 3: Modified the path checker function :)
 
Last edited:
Level 15
Joined
Jul 6, 2009
Messages
889
JASS:
        private method AlmostCharge takes nothing returns nothing
            set this.ChargeCond = true
            call SetUnitTimeScale( this.ChargeCaster, 2.00 )
            call SetUnitAnimation( this.ChargeCaster, "slam" )
            call QueueUnitAnimation( this.ChargeCaster, "stand")
        endmethod
Configurable "slam" and "Stand" and 2.00?

JASS:
    private function CheckActions takes nothing returns nothing
        local real ChargeLocx = GetUnitX(GetTriggerUnit())
        local real ChargeLocy = GetUnitY(GetTriggerUnit())
        local real ChargeEndx = GetUnitX(GetSpellTargetUnit())
        local real ChargeEndy = GetUnitY(GetSpellTargetUnit())
        local sound s
        
        if ( GetDistance(ChargeLocx, ChargeLocy, ChargeEndx, ChargeEndy) <= (MINDISTANCE) ) then
            call DisplayTextToPlayer( GetOwningPlayer(GetTriggerUnit()), 0, 0, "|cffFFCC00Target is too close!|r" )
            set s = CreateSound("Sound\\Interface\\Error.wav", false, false, true, 12700, 12700, "")
            call StartSound(s)
            call KillSoundWhenDone(s)
            set s = null
            call IssueImmediateOrder( GetTriggerUnit(), "stop" )
        endif
    endfunction
SimError is there for a reason, oh well. Also, Configurable message in your configs trigger? "Target is too close!" make configurable?

Also, I hate the pausing of the unit, it is annoying.
 
Level 7
Joined
Mar 24, 2008
Messages
184
1) The whole method is supposed to be changed (how many units, not counting custom models, will you make jump by using that code? i'll tell you: two! the blademaster and Grom Hellscream), it's even written it's a customizable method and it's even written it's an example.

2) You are right about the message instead, i'm also leaking the string by not recycling it, still, i didn't want to use too many 3rd part libraries in the spell. Anyways...are you using SimError in your map? Great, go ahead...delete those 5 lines and write a call to SimError...is it so difficult?

3) You cannot play a unit walk animation if it's not paused
 
Level 7
Joined
Mar 24, 2008
Messages
184
Have you tried it?

Try to remove the PauseUnit from the code of my charge (it's just before the SetUnitAnimationByIndex, which is what i'm using since the first release, a simple SetUnitAnimation(unit, "walk") doesn't work, there's a post i made about that) and look how the blademaster will act. My mistake about the Walk animation on non paused units, i remember there was something that made the blademaster not play the animation but well...looks like it wasn't the pause.
Still, not pausing the unit will cause the charging unit act weird (it will attempt to attack other units in its way), and it will not jump at the end of the charge

Also, i don't see what's the problem with the paused unit. It's because of the buffs?
 
Last edited:
Level 15
Joined
Jul 6, 2009
Messages
889
I hate pausing, it is annoying in-game.

You can add Cargo Hold ability to prevent the caster attacking during the charge. Or Soul Burn it or something.

As for the attack at the end, you can always reset animation beforehand and then play it, or you can pause, play animation, unpause instantly.

(I haven't tried, you can test around with that).
 
Level 7
Joined
Mar 24, 2008
Messages
184
And i should also disable abilities for the unit as he'd be able to cast while charging. I find all this unnecessarily complicated, also i don't mind units being paused (and so do other people, as you can see).

If you, or someone else, need a charge spell for your map where for some reason you don't want your units to be paused, feel free to modify my script since i'm not going to do that :) i should modify the error message instead, maybe using SimErr is not a bad idea
 
Level 2
Joined
Jun 14, 2012
Messages
18
Is there anyone here still?

Hello everyone, I know this thread is old as ever, but I am new to this and I hope I'm not bothering anyone (if there is still somebody following), I'm having a hard time figuring out what's what...
What I don't understand is, who is casting what, because it is kinda unclear in the tutorial... There is the Charge spell, the Permawalk, two dummys and a Hero... who should have which?
Plus, even though I don't understand any of it, it tells me I need to create other triggers... And, ummm... am I supposed to activate the triggers in the library? Cause, it keeps telling me it has like a gazillion compilation errors...

P.S. I tried the spell on your map: AMAZING!! which is why I don't want to give up on it...
 
Level 7
Joined
Mar 24, 2008
Messages
184
Hi and thank you :) I haven't been doing spells for W3 since a lot of time (recently i've helped someone to modify this very spell, but that's all) so i don't remember much of what i've done. Let's see what i can do for you:

First of all it would be nice to know if you use JassNewGenPack or the normal map editor. You need a vJASS compiler in order to save a map with my spell.
That said, the Dummy called Pathchecker should have the Permawalk spell, while the other will have the "Charge Stun", the hero will have the charge spell.
You could just copy/paste them from my map (first the spells, then the units). But if you haven't got newgenpack it'll be impossible for you to use this spell.

I suggest you to do some research on vJASS
 
Level 2
Joined
Jun 14, 2012
Messages
18
Hi and thank you :) I haven't been doing spells for W3 since a lot of time (recently i've helped someone to modify this very spell, but that's all) so i don't remember much of what i've done. Let's see what i can do for you:

First of all it would be nice to know if you use JassNewGenPack or the normal map editor. You need a vJASS compiler in order to save a map with my spell.
That said, the Dummy called Pathchecker should have the Permawalk spell, while the other will have the "Charge Stun", the hero will have the charge spell.
You could just copy/paste them from my map (first the spells, then the units). But if you haven't got newgenpack it'll be impossible for you to use this spell.

I suggest you to do some research on vJASS

Oh, I see, but I have to go through the trigger line by line to make sure they're configured the right way? (Which, by the way, I don't know how to do)
I have the NewGenPack but when I use that World Editor, I have a hard time finding my map in the game, or even in the directory... They just go "hidden". And whenever I save, it tells me, for example, within the Library Trigger, I have like 1088 compile errors, and sometimes it's stuff like, "Expected end of line: //TESH.alwaysfold=0", which for me is kinda Chinese...
 

Bribe

Code Moderator
Level 49
Joined
Sep 26, 2009
Messages
9,404
This is an old vJass spell, and it's possible that JassHelper forbade it from working correctly after a certain update. This hotfix will patch that particular issue:

vJASS:
// **************************************************************************
// ** **
// ** Charge **
// ** ————————————— **
// ** **
// ** A simple Charge Spell **
// ** **
// ** By: Majin **
// ** 
// ** **
// **************************************************************************

library ChargeExec requires Knockback

    struct ChargeLoop
        private real ChargeTargetx
        private real ChargeTargety
        private real ChargeEndx
        private real ChargeEndy
        private real ChargeLocx
        private real ChargeLocy
        private real ChargeNextx
        private real ChargeNexty
        private unit ChargeTarget
        private unit ChargeCaster
        private real ChargeAngle
        private real ChargeDistance
        private effect ChargeEffect
        private timer ChargeTimer
        private boolean ChargeCond = false
        private integer SpellLvl
        
        //START OF CONFIGURATION METHODS
        
        //With this method you can set the "acceleration rate" (Physicists  Forgive me) of the charge.
        //You can use any kind of numeric function (for example this.ChargeDistance * 2.00 will double
        //The speed at every loop)
        private method ChangeDistance takes nothing returns real
            return this.ChargeDistance + 1.00
        endmethod
        //END OF CONFIGURATION METHODS
        
        //START OF CUSTOMIZABLE METHODS
        
        //This method sets the conditions when to activate the AlmostCharge method. In particular
        //You may be interested in changing the distance at where the condition is true. 
        //In this Example it will be activated when the Caster is 16x times the Charge Speed Far away
        //From the target
        private method AlmostChargeCond takes nothing returns boolean
            return ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx,  this.ChargeEndy) < ( this.ChargeDistance * 16.00 )) and this.ChargeCond == false)
        endmethod
        
        //Actions to take when the Charge is almost completed. In this example the caster will play
        //The slam animation (Being a Blademaster, it will jump in the air while attacking)
        private method AlmostCharge takes nothing returns nothing
            set this.ChargeCond = true
            call SetUnitTimeScale( this.ChargeCaster, 2.00 )
            call SetUnitAnimation( this.ChargeCaster, "slam" )
            call QueueUnitAnimation( this.ChargeCaster, "stand")
        endmethod
        
        //Actions to take when the Caster reaches its target and the charge is completed. 
        //In this example the target unit will be stunned and you will see a Thunderclap effect on the ground
        private method CompleteCharge takes nothing returns nothing
            local effect tempEffect
            local unit dummy
            local real angle=GetAngle(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy)
            
            set this.ChargeLocx = this.ChargeNextx
            set this.ChargeLocy = this.ChargeNexty
            set this.ChargeNextx = PolarProjectionx(this.ChargeLocx, this.ChargeDistance, this.ChargeAngle)
            set this.ChargeNexty = PolarProjectiony(this.ChargeLocy, this.ChargeDistance, this.ChargeAngle)
            
            set tempEffect = AddSpecialEffect( WALKEFFECT, this.ChargeLocx, this.ChargeLocy )
            call DestroyEffect( tempEffect )
            
            call SetUnitX( this.ChargeCaster, this.ChargeEndx )
            call SetUnitY( this.ChargeCaster, this.ChargeEndy )
            
            set dummy = CreateUnit( GetOwningPlayer(this.ChargeCaster), DUMMYID, this.ChargeLocx, this.ChargeLocy, 0 )
            call UnitAddAbility( dummy, DUMMYSPELLID )
            call SetUnitAbilityLevel(dummy, DUMMYSPELLID, this.SpellLvl)
            call IssueTargetOrder( dummy, SPELLORDERID, this.ChargeTarget )
            call UnitApplyTimedLife( dummy, 'BTLF', 1.00)
            
            set tempEffect = AddSpecialEffect( ENDINGEFFECT, this.ChargeLocx, this.ChargeLocy )
            call DestroyEffect( tempEffect )
            
            call UnitDamageTarget( this.ChargeCaster, this.ChargeTarget, CHARGEDAMAGE*this.SpellLvl, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
            call PauseUnit( this.ChargeCaster, false )
            //This is the Knockback effect, see the Knock Trigger for more customization options
            call KnockbackEx(this.ChargeTarget, KNOCKDISTANCE*this.SpellLvl, angle, KNOCKDURATION, KnockTree(), KNOCKPLAYEFFECT, KNOCKEFFECT, KNOCKATTACH)
            call IssueTargetOrder( this.ChargeCaster, "attack", this.ChargeTarget )
            
            set tempEffect = null
            set dummy = null
        endmethod

        //What to do during the charge, the unit is moved, an effect is placed on the ground and
        //the charging speed is increased
        private method ContinueCharge takes nothing returns nothing
            local effect tempEffect
            set tempEffect = AddSpecialEffect( WALKEFFECT, this.ChargeLocx, this.ChargeLocy )
            call DestroyEffect( tempEffect )
            
            call SetUnitX(this.ChargeCaster, this.ChargeNextx)
            call SetUnitY(this.ChargeCaster, this.ChargeNexty)
            
            call SetUnitFacing(this.ChargeCaster, bj_RADTODEG * GetAngle(this.ChargeNextx, this.ChargeNexty, this.ChargeTargetx, this.ChargeTargety))
            
            set this.ChargeLocx = this.ChargeNextx
            set this.ChargeLocy = this.ChargeNexty
            set this.ChargeNextx = PolarProjectionx(this.ChargeLocx, this.ChargeDistance, this.ChargeAngle)
            set this.ChargeNexty = PolarProjectiony(this.ChargeLocy, this.ChargeDistance, this.ChargeAngle)
                        
            if (this.ChargeDistance <= MAXSPEED) then
                set this.ChargeDistance = this.ChangeDistance()
            endif
            
            set tempEffect = null
        endmethod
        
        //END OF CUSTOMIZABLE METHODS
        
        //START OF OTHER METHODS
        //This is the main method executed during the charge
        public static method ChargeActions takes nothing returns nothing
            local ChargeLoop l=GetTimerInt(GetExpiredTimer())
            
            set l.ChargeTargetx = GetUnitX(l.ChargeTarget)
            set l.ChargeTargety = GetUnitY(l.ChargeTarget)
            set l.ChargeEndx = PolarProjectionx(l.ChargeTargetx, 100.00, GetAngle(l.ChargeTargetx, l.ChargeTargety, l.ChargeLocx, l.ChargeLocy))
            set l.ChargeEndy = PolarProjectiony(l.ChargeTargety, 100.00, GetAngle(l.ChargeTargetx, l.ChargeTargety, l.ChargeLocx, l.ChargeLocy))
            
            set l.ChargeAngle = GetAngle(l.ChargeLocx, l.ChargeLocy, l.ChargeEndx, l.ChargeEndy)
            if ( l.AlmostChargeCond() ) then
            //What to do when the caster is about to reach the target
                call l.AlmostCharge()
            endif
            //If the Target gets too far away (by teleportation, for example) then stops the Charge
            if ( GetDistance(l.ChargeLocx, l.ChargeLocy, l.ChargeEndx, l.ChargeEndy) >= MAXDISTANCE and (MAXDISTANCE != 0.00) ) then
                call l.StopCharge()
            endif
            if ( l.ChargeConditions() ) then
            //If the unit hasn't reached the target yet, then execute this
                call l.ContinueCharge()
                call TimerAttach(l.ChargeTimer,0.03,l,function ChargeLoop.ChargeActions)
            else
                if ( l.ChargeCompleted() ) then
            //What to do if the charge is succesfully completed
                    call l.CompleteCharge()
                endif
                call l.StopCharge()
            endif
        endmethod
        
        //Actions to take once the Charge is being stopped (either because it wasn't possible to complete
        //the charge or because the caster reached its target)
        private method StopCharge takes nothing returns nothing
            set this.ChargeCond = false
            call SetUnitPathing(this.ChargeCaster, true)
            call PauseUnit(this.ChargeCaster, false)
            call SetUnitAnimation(this.ChargeCaster, "stand")
            call SetUnitTimeScale(this.ChargeCaster, 1.00)
            call DestroyEffect(this.ChargeEffect)
            call this.destroy()
        endmethod
        
        private method ChargeCompleted takes nothing returns boolean
            if ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) <= this.ChargeDistance*1.10)  and IsPointWalkable(this.ChargeNextx, this.ChargeNexty)) then
                if ((IsTerrainPathable(this.ChargeNextx, this.ChargeNexty, PATHING_TYPE_WALKABILITY) == false ) and ( (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false )) then
                    if(((GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false)) then
                        return true
                    endif
                endif
            endif
                return false
        endmethod

        private method ChargeConditions takes nothing returns boolean
            if ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) > this.ChargeDistance*1.10)  and IsPointWalkable(this.ChargeNextx, this.ChargeNexty)) then
                if ((IsTerrainPathable(this.ChargeNextx, this.ChargeNexty, PATHING_TYPE_WALKABILITY) == false ) and ( (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false )) then 
                    if(((GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false)) then
                        return true
                    endif
                endif
            endif
                return false
        endmethod
        
        private method onDestroy takes nothing returns nothing
            call ReleaseTimer(this.ChargeTimer)
            set this.ChargeTarget = null
            set this.ChargeCaster = null
            set this.ChargeEffect = null
        endmethod
        
        static method create takes real pChargeTargetx, real pChargeTargety, real pChargeEndx, real pChargeEndy, real pChargeLocx, real pChargeLocy, real pChargeNextx, real pChargeNexty, unit pChargeTarget, unit pChargeCaster, real pChargeAngle, real pChargeDistance, effect pChargeEffect, timer pChargeTimer returns ChargeLoop
            local ChargeLoop l = ChargeLoop.allocate()
            set l.ChargeTargetx = pChargeTargetx
            set l.ChargeTargety = pChargeTargety
            set l.ChargeEndx = pChargeEndx
            set l.ChargeEndy = pChargeEndy
            set l.ChargeLocx = pChargeLocx
            set l.ChargeLocy = pChargeLocy
            set l.ChargeNextx = pChargeNextx
            set l.ChargeNexty = pChargeNexty
            set l.ChargeTarget = pChargeTarget
            set l.ChargeCaster = pChargeCaster
            set l.ChargeAngle = pChargeAngle
            set l.ChargeDistance = pChargeDistance
            set l.ChargeEffect = pChargeEffect
            set l.ChargeTimer = pChargeTimer
            set l.SpellLvl = GetUnitAbilityLevel(l.ChargeCaster, SPELLID) 
            return l
        endmethod
        
        //END OF OTHER METHODS
    endstruct
endlibrary

//TRIGGER OF THE CHARGE SPELL
scope Charge initializer Init
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == SPELLID
    endfunction

    private function CheckActions takes nothing returns nothing
        local real ChargeLocx = GetUnitX(GetTriggerUnit())
        local real ChargeLocy = GetUnitY(GetTriggerUnit())
        local real ChargeEndx = GetUnitX(GetSpellTargetUnit())
        local real ChargeEndy = GetUnitY(GetSpellTargetUnit())
        
        if ( GetDistance(ChargeLocx, ChargeLocy, ChargeEndx, ChargeEndy) <= (MINDISTANCE) ) then
            call DisplayTextToPlayer( GetOwningPlayer(GetTriggerUnit()), 0, 0, "|cffFFCC00Target is too close!|r" )
            call PlaySound( "Sound\\Interface\\Error.wav" )
            call IssueImmediateOrder( GetTriggerUnit(), "stop" )
        endif
    endfunction
    
    private function InitActions takes nothing returns nothing
        local timer ChargeTimer = NewTimer()
        local effect ChargeEffect
        local unit ChargeCaster = GetTriggerUnit()
        local unit ChargeTarget = GetSpellTargetUnit()
        local real ChargeDistance = STARTSPEED
        local real ChargeLocx = GetUnitX(ChargeCaster)
        local real ChargeLocy = GetUnitY(ChargeCaster)
        local real ChargeTargetx = GetUnitX(ChargeTarget)
        local real ChargeTargety = GetUnitY(ChargeTarget)
        local real ChargeEndx = PolarProjectionx(ChargeTargetx, 100.00, GetAngle(ChargeTargetx, ChargeTargety, ChargeLocx, ChargeLocy))
        local real ChargeEndy = PolarProjectiony(ChargeTargety, 100.00, GetAngle(ChargeTargetx, ChargeTargety, ChargeLocx, ChargeLocy))
        local real ChargeAngle = GetAngle(ChargeLocx, ChargeLocy, ChargeEndx, ChargeEndy)
        local real ChargeNextx = PolarProjectionx(ChargeLocx, ChargeDistance, ChargeAngle)
        local real ChargeNexty = PolarProjectiony(ChargeLocy, ChargeDistance, ChargeAngle)
        local ChargeLoop stru
        
        set ChargeEffect = AddSpecialEffectTarget(ATTACHEDEFFECT, ChargeCaster, "chest" )
        
        set stru = ChargeLoop.create(ChargeTargetx, ChargeTargety, ChargeEndx, ChargeEndy, ChargeLocx, ChargeLocy, ChargeNextx, ChargeNexty, ChargeTarget, ChargeCaster, ChargeAngle, ChargeDistance, ChargeEffect, ChargeTimer)
        call SetUnitPathing(ChargeCaster, false)
        call SetUnitTimeScale(ChargeCaster, 3)
        call IssueImmediateOrder(ChargeCaster, "stop" )
        call PauseUnit(ChargeCaster, true)
        call SetUnitAnimationByIndex(ChargeCaster,6)
        call TimerAttach(ChargeTimer,0,stru,function ChargeLoop.ChargeActions)
        
        set ChargeTimer = null
        set ChargeEffect = null
        set ChargeCaster = null
        set ChargeTarget = null
    endfunction

    private function AntiLeak takes nothing returns boolean
        return true
    endfunction

    private function Init takes nothing returns nothing
        local trigger ChargeCheck = CreateTrigger()
        local trigger ChargeInit = CreateTrigger()
        local filterfunc f = Filter(function AntiLeak)
        local integer i = 0
        loop
            exitwhen i == 16
            call TriggerRegisterPlayerUnitEvent(ChargeCheck,Player(i),EVENT_PLAYER_UNIT_SPELL_CAST,f)
            call TriggerRegisterPlayerUnitEvent(ChargeInit,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,f)
            set i = i + 1
        endloop
        call TriggerAddCondition(ChargeCheck, Condition(function Conditions))
        call TriggerAddAction(ChargeCheck, function CheckActions)
        call TriggerAddCondition(ChargeInit, Condition(function Conditions))
        call TriggerAddAction(ChargeInit, function InitActions)
        set ChargeCheck = null
        set ChargeInit = null
        set f = null
    endfunction
endscope
 
Level 36
Joined
Feb 27, 2007
Messages
4,785
I'm not sure it will exactly work how you want. In order to do that, you'll have to disable the pathability checks entirely, since that's what's 'failing' when the spell stops by an obstacle like that. This will mean that the spell can be used into water, into a group of trees, and off/up cliffs.
JASS:
//REPLACE THESE TWO FUNCTIONS:
        private method ChargeCompleted takes nothing returns boolean
            if ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) <= this.ChargeDistance*1.10)  and IsPointWalkable(this.ChargeNextx, this.ChargeNexty)) then
                if ((IsTerrainPathable(this.ChargeNextx, this.ChargeNexty, PATHING_TYPE_WALKABILITY) == false ) and ( (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false )) then
                    if(((GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false)) then
                        return true
                    endif
                endif
            endif
                return false
        endmethod

        private method ChargeConditions takes nothing returns boolean
            if ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) > this.ChargeDistance*1.10)  and IsPointWalkable(this.ChargeNextx, this.ChargeNexty)) then
                if ((IsTerrainPathable(this.ChargeNextx, this.ChargeNexty, PATHING_TYPE_WALKABILITY) == false ) and ( (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false )) then
                    if(((GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false)) then
                        return true
                    endif
                endif
            endif
                return false
        endmethod


//WITH THESE VERSIONS:
        private method ChargeCompleted takes nothing returns boolean
            if (GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) <= this.ChargeDistance*1.10) then
                if (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false then
                    if (GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false then
                        return true
                    endif
                endif
            endif
                return false
        endmethod

        private method ChargeConditions takes nothing returns boolean
            if (GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) > this.ChargeDistance*1.10) then
                if (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false then
                    if (GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false then
                        return true
                    endif
                endif
            endif
                return false
        endmethod
 
Last edited:
Level 9
Joined
May 25, 2021
Messages
283
I'm not sure it will exactly work how you want. In order to do that, you'll have to disable the pathability checks entirely, since that's what's 'failing' when the spell stops by an obstacle like that. This will mean that the spell can be used into water, into a group of trees, and off/up cliffs.
JASS:
//REPLACE THESE TWO FUNCTIONS:
        private method ChargeCompleted takes nothing returns boolean
            if ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) <= this.ChargeDistance*1.10)  and IsPointWalkable(this.ChargeNextx, this.ChargeNexty)) then
                if ((IsTerrainPathable(this.ChargeNextx, this.ChargeNexty, PATHING_TYPE_WALKABILITY) == false ) and ( (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false )) then
                    if(((GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false)) then
                        return true
                    endif
                endif
            endif
                return false
        endmethod

        private method ChargeConditions takes nothing returns boolean
            if ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) > this.ChargeDistance*1.10)  and IsPointWalkable(this.ChargeNextx, this.ChargeNexty)) then
                if ((IsTerrainPathable(this.ChargeNextx, this.ChargeNexty, PATHING_TYPE_WALKABILITY) == false ) and ( (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false )) then
                    if(((GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false)) then
                        return true
                    endif
                endif
            endif
                return false
        endmethod


//WITH THESE VERSIONS:
        private method ChargeCompleted takes nothing returns boolean
            if (GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) <= this.ChargeDistance*1.10) then
                if (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false then
                    if (GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false then
                        return true
                    endif
                endif
            endif
                return false
        endmethod

        private method ChargeConditions takes nothing returns boolean
            if (GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) > this.ChargeDistance*1.10) then
                if (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false then
                    if (GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false then
                        return true
                    endif
                endif
            endif
                return false
        endmethod[/jass]
Thank you for your prompt reply!
 

Bribe

Code Moderator
Level 49
Joined
Sep 26, 2009
Messages
9,404
Wow, how can I do that?
Blizzard has taken the very confusing decision to make JassHelper 'disabled' by default, meaning that every new map that uses a vJass resource has to manually enable JassHelper. Please see this thread if you want to know where to find the Enable JassHelper option.
 
Top