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

Fire Form

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
Fire Form - Transforms the Fire Spirits body, channeling his magic to turn himself into a flame, he then travels to the targeted point very fast, but depletes his mana as he travels.


In a later version I will add damage, but for now, its not included.

My first vJass spell using structs that actually works.

Credits to thehelper.net for the help they provided.

Requires:
Key Timers 2
Jass NewGen Pack


Made off of a combination of Storm Spirit's ult (I've always loved that ult) and a superhero show that I cannot remember the name of.


Code
JASS:
scope FireForm initializer onInit

    globals
    
	private constant integer    SPELL_ID    =   'A000'
	private constant integer    DUMMY_ID    =   'h000'
        
        // OFFSET is distance travelled per cycle
        // KT_PERIOD is the period you use for KT_Add
        //Manaperunit is the mana per unit moved.
        private constant real       OFFSET      =   20
        private constant real       KT_PERIOD   =   00.03
        private constant real       Manaperunit = .25
        
    endglobals
    
    // I'm assuming that the struct declared
    // below is for the sole use of FireForm
    // so I made it private. The members are
    // public by default, you don't need to 
    // declare them as such.

    private struct casterObject
    
	unit caster
        unit dummy
        
	real offsetX
	real offsetY
        real direction
        
        real distDelta
        real distTarget
        
    endstruct
    
    private function userFunc takes nothing returns boolean
        local casterObject  obj     =   casterObject(KT_GetData())
        local boolean       stop    =   (obj.distDelta >= obj.distTarget)
        
        // If the distance travelled is equivalent or more than the
        // target distance then stop repeating
                
        if stop then
        
            // 1. Show the caster.
            // 2. Select the caster. (It gets unselected when hidden.)
            // 3. Move it to the position of the dummy.

            call ShowUnit(obj.caster, true)
            call SelectUnit(obj.caster, true)
            call SetUnitX(obj.caster, GetUnitX(obj.dummy))
            call SetUnitY(obj.caster, GetUnitY(obj.dummy))
            
            // 4. Cleanup.
            call RemoveUnit(obj.dummy)
            
            set obj.caster  =   null
            set obj.dummy   =   null
            
            call obj.destroy()
            
        else
        
            // 1. Move the dummy unit.
            // This works because the increase in the offsets is sequential.
            // There is no need to call cos and sin repeatedly.
            // Nobody believes me though.
            //2. Removing mana equal to the offset * .25
            if ( GetUnitState(obj.caster, UNIT_STATE_MANA) < 1) then
                set obj.distDelta = obj.distTarget
            else
            
            call SetUnitX(obj.dummy, GetUnitX(obj.dummy) + obj.offsetX)
            call SetUnitY(obj.dummy, GetUnitY(obj.dummy) + obj.offsetY)
            call SetUnitState(obj.caster, UNIT_STATE_MANA, RMaxBJ(0, GetUnitState(obj.caster, UNIT_STATE_MANA) - (OFFSET * Manaperunit)))
            
            // 2. Update distDelta so it correctly holds the distance travelled
            //    by the dummy unit.
            set obj.distDelta = obj.distDelta + OFFSET
            
        endif
        endif
        return stop
    endfunction

    private function onEffect takes nothing returns boolean
	local casterObject  obj     =   casterObject(0)
        local real          x       =   0
        local real          y       =   0
        local real          angle   =   0
        local boolean       cond    =   (GetSpellAbilityId() == SPELL_ID)
        
        // If the spell detected was SPELL_ID then the actions below
        // would be executed, else it would just exit, returning false.
        
        if cond then
        
            // 1. Prepare the needed data.
            set x               =   GetUnitX(GetTriggerUnit())
            set y               =   GetUnitY(GetTriggerUnit())
            set angle           =   Atan2(GetSpellTargetY() - y, GetSpellTargetX() - x)
            // Atan2 returns angle in radians, no conversion required.
            
            // 2. Instantiate.
            set obj             =   casterObject.create()
            
            set obj.caster      =   GetTriggerUnit()
            set obj.dummy       =   CreateUnit(GetOwningPlayer(obj.caster), DUMMY_ID, x, y, angle*bj_RADTODEG)
            // angle*bj_RADTODEG makes the dummy looks toward the cast point.
            
            // 3. Determine the offsets of both x and y coordinates.
            // The angle is constant so the offset increase per iteration
            // will be constant.
            set obj.offsetX     =   OFFSET*Cos(angle)
            set obj.offsetY     =   OFFSET*Sin(angle)
            
            set x               =   GetSpellTargetX() - x
            set y               =   GetSpellTargetY() - y
            
            // 4. Determine the required distance to traverse. Store the
            //    distance travelled.
            set obj.distDelta   =   0
            set obj.distTarget  =   SquareRoot(x*x+y*y)
            
            // ============= Debug messages ============
            debug call BJDebugMsg("====================")
            debug call BJDebugMsg("caster:"+GetUnitName(obj.caster))
            debug call BJDebugMsg("dummy:"+GetUnitName(obj.dummy))
            debug call BJDebugMsg("x offset:"+R2S(obj.offsetX))
            debug call BJDebugMsg("y offset:"+R2S(obj.offsetY))
            debug call BJDebugMsg("distance delta:"+R2S(obj.distDelta))
            debug call BJDebugMsg("distance required:"+R2S(obj.distTarget))
            debug call BJDebugMsg("====================")
            // =========================================
            
            // 5. Hide the casting unit.
            call ShowUnit(obj.caster, false)
            call PauseUnit(obj.dummy, true)
            call KT_Add(function userFunc, obj, KT_PERIOD)
            
        endif
        
        return false
    endfunction

    private function onInit takes nothing returns nothing
	local trigger t = CreateTrigger()
	call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
	call TriggerAddCondition(t,Condition(function onEffect))
    endfunction

endscope

By the way, to delete the DEBUG things, simply go to where it says, "debug call BJDebugMsg and delete that block of code.

Keywords:
vJass, Storm, Spirit, Ultimate, Fire, Ball, Explosion, Damage, Mana, Decay
Contents

Fire Form (Map)

Reviews
12th Dec 2015 IcemanBo: Too long time as NeedsFix. Rejected. 16:05, 4th Mar 2011 Bribe: call SelectUnit(obj.caster, true) You know this will select that unit for every single player? Your indentation is terrible and...

Moderator

M

Moderator

12th Dec 2015
IcemanBo: Too long time as NeedsFix. Rejected.

16:05, 4th Mar 2011
Bribe:

call SelectUnit(obj.caster, true)

You know this will select that unit for every single player?

Your indentation is terrible and KeyTimers2 is worse. casterObject? Just name it Data and save everyone file size in their map.

This is highly lacking. It doesn't do anything unique.

00.03 -> this is just silly formatting. 00 is usually an "octal" (base 8) indicator and throws off the readability. Just run it off of Timer32, or even a struct-timer-loop, it's much faster.

Status: Rejected until update
 
Level 9
Joined
Dec 3, 2010
Messages
162
I've seen this somewhere...
Just don't remember where.

DotA Storm Spirit's ultimate? If you read the description, you would have known.

Also, vJass is damn unnecessary for a easy spell like this.

Nope. vJASS is much more efficient than GUI. This trigger involves periodic functions, which I find it enough of a reason to use vJASS.

I can't help but rate this 1/5.
Also vote for rejection.

Just because it's in vJASS?

And here begins the commenting:

JASS:
    globals
    
    private constant integer    SPELL_ID    =   'A000'
    private constant integer    DUMMY_ID    =   'h000'
        
        // OFFSET is distance travelled per cycle
        // KT_PERIOD is the period you use for KT_Add
        //Manaperunit is the mana per unit moved.
        private constant real       OFFSET      =   20
        private constant real       KT_PERIOD   =   00.03
        private constant real       Manaperunit = .25
        
    endglobals
I realized you like to do this. The code isn't inline. Looks kind of disturbing. Make it like:

JASS:
    globals
    
        private constant integer    SPELL_ID    =   'A000'
        private constant integer    DUMMY_ID    =   'h000'
        
        // OFFSET is distance travelled per cycle
        // KT_PERIOD is the period you use for KT_Add
        //Manaperunit is the mana per unit moved.
        private constant real       OFFSET      =   20
        private constant real       KT_PERIOD   =   00.03
        private constant real       Manaperunit = .25
        
    endglobals
Something like this.

JASS:
private struct casterObject
    
unit caster
    unit dummy
        
real offsetX
real offsetY
    real direction
        
    real distDelta
    real distTarget
        
endstruct
Again, similar story as the above post.

JASS:
// do practice indenting and leaving lines/spaces when necessary, just for the readability
private function onInit takes nothing returns nothing
    local trigger t = CreateTrigger()

    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t,Condition(function onEffect))
endfunction

JASS:
    private function onEffect takes nothing returns boolean
        local casterObject  obj     =   casterObject(0) // not necessary, could just do local casterObject obj
        local real          x       =   0  // do not need
        local real          y       =   0  // to initialize these
        local real          angle   =   0 // values
        local boolean       cond    =   (GetSpellAbilityId() == SPELL_ID) // eliminate this to use 1 less variable
        
        if cond then // directly use GetSpellAbilityId() == SPELL_ID here
        
            // 1. Prepare the needed data.
            set x               =   GetUnitX(GetTriggerUnit()) // set triggering unit 
            set y               =   GetUnitY(GetTriggerUnit()) // to a variable
            set angle           =   Atan2(GetSpellTargetY() - y, GetSpellTargetX() - x)
            // Atan2 returns angle in radians, no conversion required.
            
            // 2. Instantiate.
            set obj             =   casterObject.create() // do this first, so that you can refer the triggering unit as obj.caster
            
            set obj.caster      =   GetTriggerUnit()
            set obj.dummy       =   CreateUnit(GetOwningPlayer(obj.caster), DUMMY_ID, x, y, angle*bj_RADTODEG)
            // angle*bj_RADTODEG makes the dummy looks toward the cast point.
            
            // 3. Determine the offsets of both x and y coordinates.
            // The angle is constant so the offset increase per iteration
            // will be constant.
            set obj.offsetX     =   OFFSET*Cos(angle)
            set obj.offsetY     =   OFFSET*Sin(angle)
            
            set x               =   GetSpellTargetX() - x
            set y               =   GetSpellTargetY() - y
            
            // 4. Determine the required distance to traverse. Store the
            //    distance travelled.
            set obj.distDelta   =   0
            set obj.distTarget  =   SquareRoot(x*x+y*y)
            
            // you could use a static if here to enable or disable this
            // ============= Debug messages ============
            debug call BJDebugMsg("====================")
            debug call BJDebugMsg("caster:"+GetUnitName(obj.caster))
            debug call BJDebugMsg("dummy:"+GetUnitName(obj.dummy))
            debug call BJDebugMsg("x offset:"+R2S(obj.offsetX))
            debug call BJDebugMsg("y offset:"+R2S(obj.offsetY))
            debug call BJDebugMsg("distance delta:"+R2S(obj.distDelta))
            debug call BJDebugMsg("distance required:"+R2S(obj.distTarget))
            debug call BJDebugMsg("====================")
            // =========================================
            
            // 5. Hide the casting unit.
            call ShowUnit(obj.caster, false)
            call PauseUnit(obj.dummy, true)
            call KT_Add(function userFunc, obj, KT_PERIOD)
            
        endif
        
        return false
    endfunction

JASS:
private function userFunc takes nothing returns boolean
        local casterObject  obj     =   casterObject(KT_GetData()) // wouldn't it be simpler to just do local casterObject obj = KT_GetData()

I think that's all. However, it can still definitely be improved. For example, use methods instead of function. And use T32 instead of KT. You could also use allocate() and deallocate() directly.
 
iAyanami said:
DotA Storm Spirit's ultimate? If you read the description, you would have known.
First of all, I don't play DotA.
I'm pretty sure I've seen this spell suploaded earlier to somewhere, but can't remember where.

iAyanami said:
Nope. vJASS is much more efficient than GUI. This trigger involves periodic functions, which I find it enough of a reason to use vJASS.
I were referring for Jass, though.
This is extremely easy to be done in either GUI or Jass.
vJass is less efficient than Jass and you know the reason.
vJass is for those who are lazy enough to not write the whole code by themself, or research the jass libraries granted by Blizzard.

As you probably have seen most of vJass things are rip-offs of other peoples, there is not much done by the "creator" infact.

iAyanami said:
Just because it's in vJASS?
Nope.
Because this~ Bleh I already explained that.
OffGraphic said:
Also, vJass is damn unnecessary for a easy spell like this.
Also this lacks eye-candy.
 
Level 15
Joined
Jul 6, 2009
Messages
889
^ Really now people?

Anyways, the spell is indeed lacking.

  • There is no learn tooltip for the ability.
  • The ability has only one level. Examples should have three, just some unwritten standard to keep be consistent with default hero abilities.
  • The ability is in the wrong button position. It should be in (0,2). Once again for keeping to convention.

  • The spell has no transition to the fire form. It's instant. It's exceedingly awkward to just see Blood Mage -> Some red fireball.
  • Does the ability even damage the enemies? I can't find the part of code that does.

  • Debugging code shouldn't be left in the public release, we don't need to see remnants of your debugging.
  • <Insert more code comments>
 
Last edited:
Level 6
Joined
Aug 20, 2009
Messages
95
First of all, I don't play DotA.
I'm pretty sure I've seen this spell suploaded earlier to somewhere, but can't remember where.

I were referring for Jass, though.
This is extremely easy to be done in either GUI or Jass.
vJass is less efficient than Jass and you know the reason.
vJass is for those who are lazy enough to not write the whole code by themself, or research the jass libraries granted by Blizzard.

Can JASS do this all in one trigger?

Didn't think so.


As you probably have seen most of vJass things are rip-offs of other peoples, there is not much done by the "creator" infact.


Nope.
Because this~ Bleh I already explained that.

Go troll elsewhere.

And by the way, This is my first spell, ever. Thanks for being an asshole and voting 1/5.
 
Yes, Jass can do this in one trigger.
vJass wouldn't be possible if there wasn't Jass, and I'm not trolling.
To be honest, I'm not even ~close to trolling and you should behave a ~lot better or I'll make sure you will get reported, just a friendly notice.

You should've learnt more pure Jass instead of vJass.

EDIT: Quotes are used to QUOTE other people, not to edit what they've wrote.
EDIT 2: Oh yes, I already forgot where you can learn to be a Hiver.
This you can learn from here.
 
Level 9
Joined
Dec 3, 2010
Messages
162
Yes, Jass can do this in one trigger.
vJass wouldn't be possible if there wasn't Jass, and I'm not trolling.
To be honest, I'm not even ~close to trolling and you should behave a ~lot better or I'll make sure you will get reported, just a friendly notice.

You should've learnt more pure Jass instead of vJass.

EDIT: Quotes are used to QUOTE other people, not to edit what they've wrote.
EDIT 2: Oh yes, I already forgot where you can learn to be a Hiver.
This you can learn from here.

Yes, vJASS is JASS. All vJASS scripts will be converted to JASS after being compiled. However, that's not a valid reason to criticize other people's work.

vJASS is basically, you could say, a system, which includes more features than your plain JASS. Of course, you could use these features in JASS, except you would need to re-write them from scratch. Since a lot of the systems out there uses vJASS, I don't see why vJASS is bad, even if it could be coded in JASS. Then why don't you go ahead and criticize all spells and systems that were made in vJASS, because really, they could have been made in plain JASS.

And seriously, lets stick to commenting the codes and the spell itself rather than arguing over if it's JASS or vJASS.
 
If there was something to discuss about this useless Spell, then perhaps.
If it had even a single bit of what is mentioned above it could be called a Spell, now it is just a useless Spell.

Also I do not critisize anything more than what I should. Also discussing about how vJass is more usefull than the other scripting methods is useless~ As you already pointed out that vJass = Jass, but just done in a few functions instead of thousands.

Speaking of vJass, Jass and GUI differences, faults and other is like speaking of what religion is a lie, does God exist or does he not, is there a soul or is there not~ One thing goes for all of them; Something is a lie and it will not be discovered by humankind as long the subject is kept on the lie-side.

And there the subject changes once again, I will state this my last argument to this thread
Also if we are just to reply each others replies we can do that on either Visitor Messages or Private Messages.

Final statement about this spell;;
Useless piece of nothing~ Improve it 95% and we'll call it a spell.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
off-topic: illegalpie are you NeuroToxin from theHelper.net?

No offense illegalpie, but you have to complete the spells first before you submit them lol. Good luck dude, hope you don't lose hope.

@iAyanami
I initialized it because I didn't know where it was supposed to be used. Also the b boolean was supposed to be used with another condition. The indent is fucked up because of the text editor I was using. I fixed that but I guess he wasn't able to se the updated script I posted.
 
Top