• 🏆 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] Spell Help Needed

Status
Not open for further replies.
Level 7
Joined
Jul 9, 2008
Messages
253
Hello everybody, so I'm trying to make a spell again. This time it involves a timer, and because I've never used a timer before and have no idea how it actually works. I post you this trigger and hope that you can make it work.

Information about the spell:

Well the spell should just create a dummy and move it forward for now. But it gives a error in line "local unit caster = GetTriggerUnit()" saying it's a "Type missbatch in assignment". Please help me.

Trigger ( JASS ):

JASS:
// Spell ID //

constant function Shadow_Path_ID takes nothing returns integer
    return 'A00R'
endfunction

function Shadow_Path_Expire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit caster = LoadUnitHandle( udg_SP_Hash , GetHandleId( t ) , 1 )        
    local unit dummy = LoadUnitHandle( udg_SP_Hash , GetHandleId( t ) , 2 )
    local real angle = LoadReal( udg_SP_Hash , GetHandleId( t ) , 3 )
    local real cx = GetUnitX( caster )
    local real cy = GetUnitY( caster )
    local real tx = GetUnitX( dummy )
    local real ty = GetUnitY( dummy )
    local real dx = tx - cx
    local real dy = ty - cy
    local real distance = SquareRoot(dx * dx + dy * dy)
    local real dispertime = distance * 0.03
    local real px = tx + dispertime * Cos( angle * bj_DEGTORAD )
    local real py = ty + dispertime * Sin( angle * bj_DEGTORAD )
    //
    call SetUnitX( dummy , px )
    call SetUnitY( dummy , py )
    //
    //call DestroyTimer( t )
    //
    //set t = null
    set caster = null
    set dummy = null
endfunction

function Shadow_Path_Actions takes nothing returns nothing
    local trigger t = CreateTimer()   
    local unit caster = GetTriggerUnit()
    local location loc = GetSpellTargetLoc()
    local player p = GetOwningPlayer( caster )
    local real cx = GetUnitX( caster )
    local real cy = GetUnitY( caster )
    local real tx = GetLocationX( loc )
    local real ty = GetLocationY( loc )
    local unit dummy
    local real facing = bj_RADTODEG * Atan2( ty - cy , tx - cx )
    //
    set dummy = CreateUnit( p , 'h004' , cx , cy , facing )
    call UnitApplyTimedLife( dummy , 'BTLF' , 1. )
    //   
    call SaveUnitHandle( udg_SP_Hash , GetHandleId( t ) , 1 , caster )
    call SaveUnitHandle( udg_SP_Hash , GetHandleId( t ) , 2 , dummy )
    call SaveReal( udg_SP_Hash , GetHandleId( t ) , 3 , facing )
    call TimerStart( t , 0.03 , true , function Shadow_Path_Expire )
    //
    call PolledWait( 1. )
    //
    call DestroyTimer( t )
    //
    call RemoveLocation( loc )
    //
    set caster = null
    set dummy = null
    set p = null
    set loc = null
endfunction

// Spell Condition //

function Trig_Shadow_Path_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == Shadow_Path_ID()
endfunction

//===========================================================================
function InitTrig_Shadow_Path takes nothing returns nothing
    local trigger t = CreateTrigger( )
    local integer i = 0 
    set udg_SP_Hash = InitHashtable()    
    loop
        exitwhen i == 16
        call TriggerRegisterPlayerUnitEvent( t, Player( i ) , EVENT_PLAYER_UNIT_SPELL_EFFECT , null )
        set i = i + 1
    endloop
    call TriggerAddCondition( t , Condition( function Trig_Shadow_Path_Conditions ) )
    call TriggerAddAction( t , function Trig_Shadow_Path_Actions )
    set t = null
endfunction

It's not finished, I just need the moving to work.

Thanks in advance, Quetzalcotl
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
JASS:
local trigger t = CreateTimer()
should be
JASS:
local timer t = CreateTimer()
I also suggest that you use TimerUtils,http://www.wc3c.net/showthread.php?t=101322, or something that can recycle timers.

Other Comments:
There is no real point of having that PolledWait(1.) After you start the timer, just do DestroyTimer or ReleaseTimer when you're done with the timer in the Shadow_Path_Expire function.
Don't use locations for GetSpellTargetLoc, use GetSpellTargetX and GetSpellTargetY instead.
You also don't need to inline TriggerRegisterAnyUnitEventBJ.
For facing, remove bj_RADTODEG. For px and py, remove bj_DEGTORAD.
 
Level 7
Joined
Jul 9, 2008
Messages
253
Okey, so I changed few things, I doesn't cause errors, but it only spawns the unit, 1 second later it disappears and that's it.
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
It would be helpful if you updated your code.

I made a kind of stupid mistake if you followed my advice for destroying/releasing the timer in Shadow_Path_Expire; you'll need a real variable to count how many times that function has run.

Example:
In Shadow_Path_Actions
JASS:
call SaveReal( udg_SP_Hash , GetHandleId( t ) , 4 , 0 )
And in your Shadow_Path_Expire,
JASS:
local real count = = LoadReal( udg_SP_Hash , GetHandleId( t ) , 4) + 0.03
if count >= 1 then
//Do things here as the spell should be finished, like destroying or releasing the timer.
else
//Do things here that considers the spell to be going on.
    call SaveReal( udg_SP_Hash , GetHandleId( t ) , 4 , count ) //Stores the count variable.
endif
 
Level 13
Joined
Jun 23, 2009
Messages
299
Not to be offensive in any way, but I think GetTriggerUnit() > GetSpellAbilityUnit().
I know, but since he said that the problem was in that line (though now we know it wasn't), as strange as that issue was, he could have also tried with GetSpellAbilityUnit() to see if it changed anything. That's what I meant.
YourName said:
GetSpellAbilityUnit() is not any better than GetTriggerUnit(), both will return the same in ability events.
Read above. :razz:

Also:
local real count = LoadReal( udg_SP_Hash , GetHandleId( t ) , 4) + 0.03
Made a typo, watermelon =)
 
Level 7
Joined
Jul 9, 2008
Messages
253
Okey I got good news and bad news, the good news is that there is no error and that it spawns the dummy and kills it after 1 second, the bad news is that dummy doesn't move.

Trigger ATM:

JASS:
// Spell ID //

constant function Shadow_Path_ID takes nothing returns integer
    return 'A00R'
endfunction

function Shadow_Path_Expire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit caster = LoadUnitHandle( udg_SP_Hash , GetHandleId( t ) , 1 )        
    local unit dummy = LoadUnitHandle( udg_SP_Hash , GetHandleId( t ) , 2 )
    local real angle = LoadReal( udg_SP_Hash , GetHandleId( t ) , 3 )
    local real cx = GetUnitX( caster )
    local real cy = GetUnitY( caster )
    local real tx = GetUnitX( dummy )
    local real ty = GetUnitY( dummy )
    local real dx = tx - cx
    local real dy = ty - cy
    local real distance = SquareRoot(dx * dx + dy * dy)
    local real dispertime = distance * 0.03
    local real px = tx + dispertime * Cos( angle * bj_DEGTORAD )
    local real py = ty + dispertime * Sin( angle * bj_DEGTORAD )
    local integer i = 0
    local real count = LoadReal( udg_SP_Hash , GetHandleId( t ) , 4) + 0.03 
    //
    if count >= 1 then
        call KillUnit( dummy )
        call DestroyTimer( t )
    else
        call SetUnitX( dummy , px )
        call SetUnitY( dummy , py )
        call SaveReal( udg_SP_Hash , GetHandleId( t ) , 4 , count ) //Stores the count variable.
    endif
    //
    set i = i + 1
    //
    set t = null
    set caster = null
    set dummy = null
endfunction

function Trig_Shadow_Path_Actions takes nothing returns nothing
    local timer t = CreateTimer()   
    local unit caster = GetTriggerUnit()
    local location loc = GetSpellTargetLoc()
    local player p = GetOwningPlayer( caster )
    local real cx = GetUnitX( caster )
    local real cy = GetUnitY( caster )
    local real tx = GetLocationX( loc )
    local real ty = GetLocationY( loc )
    local unit dummy
    local real facing = bj_RADTODEG * Atan2( ty - cy , tx - cx )
    //
    set dummy = CreateUnit( p , 'h00D' , cx , cy , facing )
    //   
    call SaveUnitHandle( udg_SP_Hash , GetHandleId( t ) , 1 , caster )
    call SaveUnitHandle( udg_SP_Hash , GetHandleId( t ) , 2 , dummy )
    call SaveReal( udg_SP_Hash , GetHandleId( t ) , 3 , facing )
    call SaveReal( udg_SP_Hash , GetHandleId( t ) , 4 , 0 )
    call TimerStart( t , 0.03 , true , function Shadow_Path_Expire )
    //
    call RemoveLocation( loc )
    //
    set caster = null
    set dummy = null
    set p = null
    set loc = null
endfunction

// Spell Condition //

function Trig_Shadow_Path_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == Shadow_Path_ID()
endfunction

//===========================================================================
function InitTrig_Shadow_Path takes nothing returns nothing
    local trigger t = CreateTrigger( )
    local integer i = 0 
    set udg_SP_Hash = InitHashtable()    
    loop
        exitwhen i == 16
        call TriggerRegisterPlayerUnitEvent( t, Player( i ) , EVENT_PLAYER_UNIT_SPELL_EFFECT , null )
        set i = i + 1
    endloop
    call TriggerAddCondition( t , Condition( function Trig_Shadow_Path_Conditions ) )
    call TriggerAddAction( t , function Trig_Shadow_Path_Actions )
    set t = null
endfunction
 
Level 13
Joined
Mar 16, 2008
Messages
941
Well, you create a dummy at the casters position, and move it 0.03*distance to caster, what's 0? Or am I blind?
BJDebugMsg your distance pls :D
JASS:
    local real cx = GetUnitX( caster )
    local real cy = GetUnitY( caster )
    set dummy = CreateUnit( p , 'h00D' , cx , cy , facing )

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

    local real cx = GetUnitX( caster )
    local real cy = GetUnitY( caster )
    local real tx = GetUnitX( dummy )
    local real ty = GetUnitY( dummy )
    local real dx = tx - cx
    local real dy = ty - cy
    local real distance = SquareRoot(dx * dx + dy * dy)
    local real dispertime = distance * 0.03
    local real px = tx + dispertime * Cos( angle * bj_DEGTORAD )
    local real py = ty + dispertime * Sin( angle * bj_DEGTORAD )
    call SetUnitX( dummy , px )
    call SetUnitY( dummy , py )
 
Level 7
Joined
Jul 9, 2008
Messages
253
Okey I'll try, could you help me with a different trigger in the meanwhile? :p

The problem with it is that it gives million errors, starting with the "loop" in Lightning_Shield_Damage.

Trigger:

JASS:
// Spell ID //

constant function Lightning_Shield_ID takes nothing returns integer
    return 'A00T'
endfunction

// Buff ID //

constant function Lightning_Shield_Buff takes nothing returns integer
    return 'B00C'
endfunction

// Damage Constant // 

constant function Lightning_Shield_Damage_Constant takes nothing returns real
    return 10.
endfunction

// Damage Level //

constant function Lightning_Shield_Damage_Level takes nothing returns real
    return 10.
endfunction 

// Area of Effect //

constant function Lightning_Shield_Area takes nothing returns real
    return 150.
endfunction

// Effect //

constant function Lightning_Shield_Effect takes nothing returns string
    return "Abilities\\Spells\\Orc\\LightningShield\\LightningShieldBuff.mdl"
endfunction

// Filter //

function Lightning_Shield_EnemyFilter takes nothing returns boolean
    return IsUnitType( GetFilterUnit() , UNIT_TYPE_MAGIC_IMMUNE ) == false and IsPlayerEnemy( GetOwningPlayer( GetFilterUnit() ) , GetOwningPlayer( GetTriggerUnit() ) ) == true
endfunction

function Lightning_Shield_Damage takes unit whichUnit, real radius, real x, real y, real amount, boolean attack, boolean ranged, attacktype attackType, damagetype damageType, weapontype weaponType, string special returns nothing
    local unit u
    local group g = CreateGroup()
    //
    call GroupEnumUnitsInRange( g , x , y , radius , function Lightning_Shield_EnemyFilter )
    loop
        set u = FirstOfGroup( g )
        exitwhen u == null
        if GetUnitState( u , UNIT_STATE_LIFE ) > 0 then
            call UnitDamageTarget( whichunit , u , amount , attack , ranged , attackType , damageType , weaponType )
            call DestroyEffect( AddSpecialEffectTarget( special , u , "chest" )
        endif
        call GroupRemoveUnit( g , u )
        set u = null
    endloop    
    //
    call DestroyGroup( g )
    set g = null
endfunction

function Trig_Lightning_Shield_Actions takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local real x
    local real y
    local integer level = GetUnitAbilityLevel( Lightning_Shield_ID() , caster )
    local real amount = Lightning_Shield_Damage_Constant() + Lightning_Shield_Damage_Level() * I2R( level )  
    local integer i = 0
    //
    loop
        exitwhen i >= 10
        if GetUnitState( target , UNIT_STATE_LIFE ) > 0 and GetUnitAbilityLevel( target , Lightning_Shield_Buff() ) > 0 then
            set x = GetUnitX( target )
            set y = GetUnitY( target )
            call Lightning_Shield_Damage( caster , Lightning_Shield_Area() , x , y , amount , true , false ,ATTACK_TYPE_NORMAL , DAMAGE_TYPE_UNKNOWN , WEAPON_TYPE_WHOKNOWS , Lightning_Shield_Effect() )  
        endif
        call PolledWait( 1. )
        set i = i + 1
    endloop
    //
    set caster = null
    set target = null
endfunction

// Spell Condition //

function Trig_Lightning_Shield_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == Lightning_Shield_ID()
endfunction

//===========================================================================
function InitTrig_Lightning_Shield takes nothing returns nothing
    local trigger t = CreateTrigger( )
    local integer i = 0
    loop
        exitwhen i == 16
        call TriggerRegisterPlayerUnitEvent( t, Player( i ) , EVENT_PLAYER_UNIT_SPELL_EFFECT , null )
        set i = i + 1
    endloop
    call TriggerAddCondition( t , Condition( function Trig_Lightning_Shield_Conditions ) )
    call TriggerAddAction( t , function Trig_Lightning_Shield_Actions )
    set t = null
endfunction

EDIT: You are completely right, I'm an idiot, the distance is 0 indeed. I'll fix that. Thanks.

EDIT 2: Woho got Shadow Path working :D
 
Status
Not open for further replies.
Top