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

vJass Problem

Status
Not open for further replies.
Level 14
Joined
Nov 23, 2008
Messages
512
hey i tryed to create my first vJass spell but i don't know any more. i hope everybody knows BTanks and the Earth Robot. the tank has a ability called "Dustwave". i want to create this spell. here is my current code: (short)
JASS:
library Dustwave initializer Init
    globals
        private constant integer speed = 1050
        private constant integer spellID = 'A000'
        private constant real refresh = 0.1
        private constant real distance = 800
        private integer total = 0
        private timer time = CreateTimer()
    endglobals

private struct information
    unit u
    real distancedone
endstruct

globals
    information array units
endglobals
    
function check takes nothing returns boolean
    return GetSpellAbilityId() == spellID
endfunction

function Initdustwave takes nothing returns nothing
    set total = total + 1
endfunction
    
function Initdustwaveloop takes nothing returns nothing
    local information dat
    local real x1 = GetUnitX(dat.u)
    local real y1 = GetUnitY(dat.u)
    local real x2 //formula..
    local real y2 //formula..
    set dat.distancedone = dat.distancedone + speed/10
endfunction
    
private function getcaster takes unit u returns information
    local integer i
    local information dat
    loop
        exitwhen i > total
        set dat = units[i]
        if dat.u == u then
            return dat
        endif
        set i = i+1
    endloop
    set u = null
    return 0
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerAddAction(t, function Initdustwave)
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition(t, Condition(function check))
    set t = null
endfunction
endlibrary

it may have leaks!

plz help me. and if you don't know the spell i can make a gui version.
 
Your spell is not even functional, you never create any struct instances yet use them?

I suggest reading a tutorial on structs, or practicing with something more simple before using them on something more advanced such as this.

As for your current code..

  • Spells should be scopes, not libraries.
  • Your functions should all be private.
  • You can use a single global block like this;
    JASS:
        private keyword information
        globals
            private constant integer speed = 1050
            private constant integer spellID = 'A000'
            private constant real refresh = 0.1
            private constant real distance = 800
            private integer total = 0
            private timer time = CreateTimer()
            information array units
        endglobals
  • It's more efficient to use only a condition thread instead of an action/condition.
    That way you save a function call and the game doesn't have to internally check the conditions, then run the actions. Example..
    JASS:
    private function Actions takes nothing returns boolean
        if YOUR_CONDITION then
            // actions
        endif
        return false
    endfunction
    
    private function onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterSomeEvent(t)
        call TriggerAddCondition(t, Condition(function Actions))
    endfunction

I have never played battle tanks and I don't know how the spell looks visually, so I can't help you there but hopefully you will take in these tips.
 
Ok here it is

ok i solved your problem!
my suggestion is to read the jasshelper manual (included in the JNGP folder)

i learned much from that...

here is the working, leakless, mui, full documentated... code, working in the map from your previous post:

JASS:
scope Dustwave initializer Init
globals
    // Setup part       Adjust the variables so they fit your map
    
    private constant integer spellID = 'AOsh'  //The rawcode of the ability for this spell
    private constant real interval = 0.1       //The time after a new effect is created
    private constant integer amount = 10       //This is how many effects will be created (amount * interval = spell duration)
    private constant real distance = 800       //The distance the caster will travel
    private constant string sfx = "Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl"
                                               //sfx is the special effect which is created each interval
    //Setup part ends here
    private integer total = 0
    private timer time = CreateTimer()         // these variables are the core of the system
    private integer array units                // a timer for the loop, a integer for counting how many instances are running
endglobals                                     // and a integer array for storing the active instances (structs are integers)

private struct information
    unit u
    real distancedone = 0                      // our struct which holds the information of our instance
    real xx                                    // u will be the caster, distancedone explains itself
    real x                                     // xx are the x coordinates the effects travel each interval
    real yy                                    // yy are the y coordinates the effects travel each interval
    real y                                     // and x and y are our changing coordinates
endstruct

private function DustwaveLoop takes nothing returns nothing
    local integer i = 0
    local information dat
    loop
        exitwhen i >= total                                    //the function loops through all active instances
        set dat = units[i]                                     // the correct struct is picked
        set dat.x = dat.x + dat.xx
        set dat.y = dat.y + dat.yy                             // the coordinates are actualized
        set dat.distancedone = dat.distancedone + distance/amount  // the distancedone is increased
        call DestroyEffect(AddSpecialEffect(sfx,dat.x,dat.y))   // the sfx is created
        if dat.distancedone >= distance then
            call SetUnitPosition(dat.u,dat.x,dat.y)            // if the effects have travelled the whole distance
            call SetUnitAnimation(dat.u,"birth")               // the caster is moved and plays his birth animation
        endif
        if dat.distancedone >= distance or GetWidgetLife(dat.u) <= 0.405 then
            set total = total - 1
            set units[i] = units[total]                         // and if the caster dies or the distance is travelled
            call dat.destroy()                                  // the active struct is destroyed and its array recycled
        endif
        set i = i + 1                                           // the next loop gets prepared
    endloop
    if total == 0 then
        call PauseTimer(time)                                   // when there are no active instances the timer gets paused
    endif
endfunction
    
private function check takes nothing returns boolean
    local information dat
    local unit u = GetTriggerUnit()
    local real angle = Atan2(GetSpellTargetY() - GetUnitY(u), GetSpellTargetX() - GetUnitX(u)) // this gets the correct angle
    if GetSpellAbilityId() == spellID then                 // if the casted spell is our spell then we go on
        set dat = information.create()                           // a new struct instance is created
        set units[total] = dat 
        set total = total + 1                                    // and stored in our system
        
        set dat.u = u
        set dat.xx = distance/10 * Cos(angle)
        set dat.yy = distance/10 * Sin(angle)                    // then the struct variables are adjusted
        set dat.x = GetUnitX(u)
        set dat.y = GetUnitY(u)
        
        if total == 1 then
           call TimerStart(time,interval,true,function DustwaveLoop)  // and if this is our first instance: timer start
        endif
    endif
    set u = null                                                 // removing leaks
    return false                                                 // return false (its the condition of the trigger)
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_CAST )  // well we initialize our trigger
    call TriggerAddCondition(t, Condition(function check))
endfunction
endscope
 
Level 4
Joined
Apr 16, 2009
Messages
85
you should change private integer array units to private information array units or your spell will stop working when jasshelper finally gets its long needed type safety (you could also use typecasts but thats really ugly)
 
Status
Not open for further replies.
Top