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

[JASS] My First Jass Spell

Status
Not open for further replies.
the effect was fixed already?

for degrees to radians multiply the degree-angle by bj_DEGTORAD...

Note: if your spell is a targeted one, use this to get angle in radians, and much more accurate since unit facing only returns some angles
JASS:
Atan2(GetSpellTargetY() - GetUnitY(GetTriggerUnit()) , GetSpellTargetX() - GetUnitX(GetTriggerUnit()))
 
Level 10
Joined
Sep 3, 2009
Messages
458
the effect was fixed already?

for degrees to radians multiply the degree-angle by bj_DEGTORAD...

Note: if your spell is a targeted one, use this to get angle in radians, and much more accurate since unit facing only returns some angles
JASS:
Atan2(GetSpellTargetY() - GetUnitY(GetTriggerUnit()) , GetSpellTargetX() - GetUnitX(GetTriggerUnit()))

Ok the bj_DEGTORAD worked XD thanks

oh here's my new improved code. For some reason damage still isn't working. It still doesn't damage enemy unit's, uhm help? ehehe

JASS:
llibrary AttackSystem initializer init
    globals
        constant real ATTACK_AREA = 300
        constant real ATTACK_DAMAGE = 100
        constant real ATTACK_THRUST = 100
        
        constant string ATTACK_SFX = "Abilities\\Spells\\Other\\Monsoon\\MonsoonBoltTarget.mdl"
        
        constant string ATTACK_ORDER_ID = "holdposition"
    endglobals
    
    struct Attack
        private unit caster = null
        private real x
        private real y
        private real angle
        
        private static group enumGroup = CreateGroup()
        private static thistype temp
        
        private static method enumGroupFilter takes nothing returns boolean
            if IsUnitEnemy(GetFilterUnit(), GetOwningPlayer( temp.caster )) then
                call UnitDamageTarget( temp.caster, GetFilterUnit(), ATTACK_DAMAGE, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null)
            endif
            return false
        endmethod
        static method cast takes nothing returns thistype
            local thistype temp = allocate()
            
            set temp.caster = GetTriggerUnit()
            set temp.angle = (GetUnitFacing(temp.caster)*bj_DEGTORAD)
            set temp.x = (GetUnitX(temp.caster) + ATTACK_THRUST * Cos(temp.angle))
            set temp.y = (GetUnitY(temp.caster) + ATTACK_THRUST * Sin(temp.angle))
            
            call DestroyEffect(AddSpecialEffect(ATTACK_SFX, temp.x, temp.y))
            call GroupEnumUnitsInRange(enumGroup, temp.x, temp.y, ATTACK_AREA, Filter( function thistype.enumGroupFilter))
        
            call temp.destroy()
            return 0
        endmethod
    endstruct
    
    //==============================================================================================================
    private function condition takes nothing returns boolean
        return ( GetIssuedOrderIdBJ() == String2OrderIdBJ(ATTACK_ORDER_ID) )
    endfunction
    
    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)
        call TriggerAddCondition(t, Filter(function condition))
        call TriggerAddAction(t, function Attack.cast)
    endfunction
endlibrary
 
first this...

local thistype temp = allocate()

you already have a static variable name temp so just do

set temp = allocate()

-----------------------------------------------------------

I think it will solve it, because cast uses the local thistype temp rather than the static thistype temp meaning the temp in the enumGroupFilter has no value (because the temp in the enumGroupFilter is the static thistype temp)...
 
Level 10
Joined
Sep 3, 2009
Messages
458
^^...

be sure not to have a static thistype and a local thistype having the same name...

for better understanding, read the vJASS OOP tut... ^_^
you will learn there how to use structs effectively...

lol I kind of get why Berb named the local thistype nova, instead of temp ehehe.

I've been reading also the vJass OOP (actually it's open right now on another tab) although learning from someone who knows is better. Besides half of the time I don't even understand what the manual is saying XD

Also I have a question, can if statements go like this

if a==b and cast == true and
 
yeah, that's why... basically you dont give two variables the same name inside the same code... ^_^
and as Berb said, you can just directly use temp, rather than making a local thistype...

that happened to me too while I'm reading it, especially the struct inheriting... I only managed to understand it because of TRD... ^_^

yup, you can have multiple "and" in an if statement
 
Level 10
Joined
Sep 3, 2009
Messages
458
yeah, that's why... basically you dont give two variables the same name inside the same code... ^_^
and as Berb said, you can just directly use temp, rather than making a local thistype...

that happened to me too while I'm reading it, especially the struct inheriting... I only managed to understand it because of TRD... ^_^

yup, you can have multiple "and" in an if statement

Ehehe I'll try to remember that

Lol. Oh who's TRD? is that his username?

yeah I did it and it worked.

Also I saw berb use these

/**/

what does these two do?
 
Ehehe I'll try to remember that

Lol. Oh who's TRD? is that his username?

yeah I did it and it worked.

Also I saw berb use these

/**/

what does these two do?

The_Reborn_Devil

/**/ -> it enables you to have ENTER spaces in the code

JASS:
//here, if he hadn't put the /* */, this would return a compile error
//because he "cut" the parameters
//rather than typing the parameters in a straight line, he "cut" it
//to increase readability
call UnitDamageTarget(temp.caster, GetFilterUnit(), ICE_NOVA_DAMAGE, false, false, /*
                    */ ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null)
//that is easier to read than
call UnitDamageTarget(temp.caster, GetFilterUnit(), ICE_NOVA_DAMAGE, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null)
 
Level 10
Joined
Sep 3, 2009
Messages
458
The_Reborn_Devil

/**/ -> it enables you to have ENTER spaces in the code

JASS:
//here, if he hadn't put the /* */, this would return a compile error
//because he "cut" the parameters
//rather than typing the parameters in a straight line, he "cut" it
//to increase readability
call UnitDamageTarget(temp.caster, GetFilterUnit(), ICE_NOVA_DAMAGE, false, false, /*
                    */ ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null)
//that is easier to read than
call UnitDamageTarget(temp.caster, GetFilterUnit(), ICE_NOVA_DAMAGE, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null)

wow cool! So technically it adds a space yet it doesn't interfere with the code? That's pretty useful for organizing code eh ehehe
 
Level 10
Joined
Sep 3, 2009
Messages
458
Hey I finished my system now but I can't compile it. It says that there's a missing end block. I don't know how to fix it.

JASS:
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Move System v.0.1 by neku99
// 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// A simple Move System for my map. Enables you to move/dash units and also pause them at will
// (some features are not yet implemented and somethings are not yet done)
//==================================================
// Speed Conversions
//==================================================
// I use this conversions to calculate speed
//
//      1 second = 1   meter
//      1 second = 50  units
//   0.01 second = 0.5 units
// So no distance per interval is calcualted:
//
// BASESPEED / SPEEDSCALE = distance per interval
//
//      522 / 100         = 5.22 
//
//==================================================
// Configurables
//==================================================
// -speed
// -more to come
//
//==================================================
// Globals
//==================================================
//
//
//
//==================================================
// Parameters and Usage
//==================================================
// You can simply use damage with one function call:
//
// call Damage.create( PARAMETERS )
//
// Here are the parameters on their proper order
// (Parameters with the prefix "!" are not yet implemented)
//
// unit u  = the unit to be moved
// real x = the x coordinate of the unit
// real y = the y coordinate of the unit
// real bs = the base speed of the move (used to determine distance per interval)
// real ss = the speed scale of the move (used to determine distance per interval)
//
//END+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

library MoveEngine
    globals
        private constant real MOVE_SPEED_SCALE = 100
        private constant real TICK = 0.01
        
        private timer MOVE_TIMER = CreateTimer()
        private integer TOTAL = 0
        private integer array MOVE_ARRAY[8190]
        
    endglobals
    
    struct Move
       
        private unit u  //unit to be moved 
        private real ux //unit x
        private real uy //unit y
        private real tx //target x
        private real ty //target y
        private real a  //angle
        private real bs //base speed
        private real dpi//distance per interval/TICK
        private real md //mas distance 
       
        private static thistype data
       
        private static method GetDPI takes nothing returns real
           set data.dpi = data.bs/MOVE_SPEED_SCALE
           return data.dpi
        endmethod
       
        private static method Loop takes nothing returns nothing
           local integer i = 1
           loop
              exitwhen i > TOTAL
              if data.md > 0.00 then
                 set data.ux = (data.ux + data.dpi * Cos(data.a))
                 set data.uy = (data.uy + data.dpi * Sin(data.a))
                 set data.md = data.md - data.dpi
              else
                 set MOVE_ARRAY[i] = MOVE_ARRAY[TOTAL]
                 set TOTAL = TOTAL - 1
                 set i = i - 1
                 call data.destroy()
                 
              if TOTAL == 0 then
                 call PauseTimer(MOVE_TIMER)
              endif
            endloop
        endmethod
        
        static method create takes unit u, real md, real bs, real a returns thistype
            set TOTAL = TOTAL + 1
            set data.allocate()
            set data.u   = u
            set data.md  = md
            set data.bs  = bs
            set data.a   = (a*bj_DEGTORAD)
            set data.dpi = GetDPI()
        
            if TOTAL == 1 then
                call TimerStart( MOVE_TIMER, TICK, true, function Move.Loop)
            endif
            return data
        endmethod
    endstruct
endlibrary
 
you forgot one endif... (after the else)

and, your trigger wont loop...

JASS:
loop
              exitwhen i > TOTAL
              //add this line
              set data = MOVE_ARRAY[i]
              if data.md > 0.00 then
                 set data.ux = (data.ux + data.dpi * Cos(data.a))
                 set data.uy = (data.uy + data.dpi * Sin(data.a))
                 set data.md = data.md - data.dpi
              else
                 set MOVE_ARRAY[i] = MOVE_ARRAY[TOTAL]
                 set TOTAL = TOTAL - 1
                 set i = i - 1
                 call data.destroy()
           //put endif here....
              if TOTAL == 0 then
                 call PauseTimer(MOVE_TIMER)
              endif
              //add this here
              set i = i + 1
            endloop

            static method create
                 //add this line
                 set MOVE_ARRAY[TOTAL] = data
 
yeah, you dont move the unit... ^_^


the i is used as a loop index like how GUI uses Integer A... at the end of each loop we increase i by 1 to move to the next index... and then when i becomes > TOTAL, the loop stops...

rather than doing this every loop

data.dpi * Cos(data.a)

just save it in a struct member at the create method...
 
Level 10
Joined
Sep 3, 2009
Messages
458
yeah, you dont move the unit... ^_^


the i is used as a loop index like how GUI uses Integer A... at the end of each loop we increase i by 1 to move to the next index... and then when i becomes > TOTAL, the loop stops...

rather than doing this every loop

data.dpi * Cos(data.a)

just save it in a struct member at the create method...

ehehe I'll figure it out eventually. And also for some reason It's not MUI. Whenever I call the function move it overwrites the existing move. I dunno why -_-' maybe it's in the indexing? Do I have to like set the struct instance to the struct MOVE_ARRAY[] something like that?
 
Level 10
Joined
Sep 3, 2009
Messages
458
Ok do I put the

MOVE_ARRAY[TOTAL] = data before or after the TOTAL = TOTAL + 1

Ok what I did was put I put it after the TOTAL = TOTAL +1

Then what happened was when I put

MOVE_ARRAY[TOTAL] = data

It didn't move and my other system the attack system that calls the Move.create() function didn't fire as well.

then I did

data = MOVE_ARRAY[TOTAL]

It didn't move but the attack system worked.

lol more bugs. Ima try renaming the thistypes for the structs.

EDIT: Also on the data = MOVE_ARRAY[TOTAL] I notice that it moves a little but I don't think it loops and it still overwrites the move. T.T
 
Ok do I put the

MOVE_ARRAY[TOTAL] = data before or after the TOTAL = TOTAL + 1

Ok what I did was put I put it after the TOTAL = TOTAL +1

Then what happened was when I put

MOVE_ARRAY[TOTAL] = data

It didn't move and my other system the attack system that calls the Move.create() function didn't fire as well.

then I did

data = MOVE_ARRAY[TOTAL]

It didn't move but the attack system worked.

lol more bugs. Ima try renaming the thistypes for the structs.

EDIT: Also on the data = MOVE_ARRAY[TOTAL] I notice that it moves a little but I don't think it loops and it still overwrites the move. T.T


post the new code... somehow I think you haven't read the other commented parts... ^_^
 
Level 10
Joined
Sep 3, 2009
Messages
458
Ok I kinda forgot to add some stuff from your nova systems indexing so I kinda fixed it.

So technically its MUI now. The moves don't overwrite now but they still just move once and then stop moving. which I don't know how to fix

JASS:
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Move System v.0.1 by neku99
// 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// A simple Move System for my map. Enables you to move/dash units and also pause them at will
// (some features are not yet implemented
//==================================================
// Speed Conversions
//==================================================
// I use this conversions to calculate speed
//
//      1 second = 1   meter
//      1 second = 50  units
//   0.01 second = 0.5 units
// So no distance per interval is calcualted:
//
// BASESPEED / SPEEDSCALE = distance per interval
//
//      522 / 100         = 5.22 
//
//==================================================
// Configurables
//==================================================
// -speed
// -more to come
//
//==================================================
// Globals
//==================================================
//
//
//
//==================================================
// Parameters and Usage
//==================================================
// You can simply use damage with one function call:
//
// call Damage.create( PARAMETERS )
//
// Here are the parameters on their proper order
// (Parameters with the prefix "!" are not yet implemented)
//
// unit u  = the unit to be moved
// real x = the x coordinate of the unit
// real y = the y coordinate of the unit
// real bs = the base speed of the move (used to determine distance per interval)
// real ss = the speed scale of the move (used to determine distance per interval)
//
//END+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

library MoveEngine
    globals
        private constant real MOVE_SPEED_SCALE = 100
        private constant real TICK = 0.01
        
        private timer MOVE_TIMER = CreateTimer()
        private integer TOTAL = 0
        private integer array MOVE_ARRAY[8190]
        
    endglobals
    
    struct Move
       
        private unit u  //unit to be moved 
        private real ux //unit x
        private real uy //unit y
        private real tx //target x
        private real ty //target y
        private real a  //angle
        private real bs //base speed
        private real dpi//distance per interval/TICK
        private real md //mas distance 
       
        private static thistype data
       
        private static method GetDPI takes nothing returns real
           set data.dpi = data.bs/MOVE_SPEED_SCALE
           return data.dpi
        endmethod
       
        private static method Loop takes nothing returns nothing
           local integer i = 1
           loop
              exitwhen i > TOTAL
              set data = MOVE_ARRAY[i]
              if data.md > 0.00 then
                 call SetUnitX( data.u, data.ux)
                 call SetUnitY( data.u, data.uy)
                 set data.md = data.md - data.dpi
              else
                 set MOVE_ARRAY[i] = MOVE_ARRAY[TOTAL]
                 set TOTAL = TOTAL - 1
                 set i = i - 1
                 call data.destroy()
              endif
                 
              if TOTAL == 0 then
                 call PauseTimer(MOVE_TIMER)
              endif
              
              set i = i + 1
              
            endloop
        endmethod
        
        static method create takes unit u, real md, real bs, real a returns thistype
            set TOTAL = TOTAL + 1 
            set data = allocate()
            set data.u   = u
            set data.md  = md
            set data.bs  = bs
            set data.a   = (a*bj_DEGTORAD)
            set data.dpi = GetDPI()
            
            set data.ux = (GetUnitX(data.u) + data.dpi * Cos(data.a))
            set data.uy = (GetUnitY(data.u) + data.dpi * Sin(data.a))
            set MOVE_ARRAY[TOTAL] = data        
            if TOTAL == 1 then
                call TimerStart( MOVE_TIMER, TICK, true, function Move.Loop)
            endif
            return data
        endmethod
    endstruct
endlibrary
 
because ux,uy is set wrongly

JASS:
//on the create trigger change this
set data.ux = (GetUnitX(data.u) + data.dpi * Cos(data.a))
set data.uy = (GetUnitY(data.u) + data.dpi * Sin(data.a))

//to this

set data.ux = data.dpi * Cos(data.a)
set data.uy = data.dpi * Sin(data.a)

//then on the loop change this

call SetUnitX( data.u, data.ux)
call SetUnitY( data.u, data.uy)

//to this:

call SetUnitX( data.u, GetUnitX(data.u) + data.ux)
call SetUnitY( data.u, GetUnitY(data.u) + data.uy)

but you may also want to check if the X,Y are still inside the map bounds... you can check the nova system for that... ^_^
 
Level 10
Joined
Sep 3, 2009
Messages
458
Yeah I kinda figured that part was a bit funny looking XD thanks!

And I guess the map bounds thing was what you where talking about when you told me about dash spells. It's so that units don't go out of map bounds? Right?

Dang still can't rep you T.T
 
Yeah I kinda figured that part was a bit funny looking XD thanks!

And I guess the map bounds thing was what you where talking about when you told me about dash spells. It's so that units don't go out of map bounds? Right?

Dang still can't rep you T.T

right because SetUnit blahblah can make your unit go out of the map... ^_^
 
Level 10
Joined
Sep 3, 2009
Messages
458
So I just need to set the MaxX and MaxY to the map bounds? and check if the unit's x and y are equal to it then I just stop the move?

And if you put like Library blaha initializer init

does the init part run automatically?

can yah explain how the map bound check goes >.>

EDIT: I get it now if the unit is within the values of MIN and MAX I should stop it right?
 
So I just need to set the MaxX and MaxY to the map bounds? and check if the unit's x and y are equal to it then I just stop the move?

And if you put like Library blaha initializer init

does the init part run automatically?

can yah explain how the map bound check goes >.>

EDIT: I get it now if the unit is within the values of MIN and MAX I should stop it right?

yup init would run on map init

.... you create 4 real variables,

MaxX, MaxY,MinY, MinX

then on the init, you set them to the map's bounds

set MaxX = GetRectMaxX(bj_mapblahblah) -> in the function list look for GetPlayableMapRect and copy the bj_mablahblah there... do this for the other 3 variables

then before you move the unit, check if X is between MinX and MaxX and do the same for Y

first its better to create a local real variable TempD
JASS:
set TempD = GetUnitX(data.u) + data.ux
if MinX <= TempD and TempD <= MaxX then
    call SetUnitX( data.u, TempD)
endif
set TempD = GetUnitY(data.u) + data.uy
if MinY <= TempD and TempD <= MaxY then
    call SetUnitY( data.u, TempD)
endif

so if the next X or Y value is out of bounds, it will not move on that part...
 
Status
Not open for further replies.
Top