HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

instant knockback. [ + rep ]

03-16-2009, 09:35 AM#1
XeNiM666
i have a spell that knockbacks every units is front of the caster. but somehow, it knockbacks the unit instantly. It doesnt move.
Heres the code:

Collapse JASS:
scope Bash

    globals
        private constant integer BASH_ABILITY_ID = 'A008'
        
        private constant string BASH_CAST_EFFECT = "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
        private constant string BASH_CAST_ATTACH_1 = "hand,left"
        private constant string BASH_CAST_ATTACH_2 = "hand,right"

        private constant string BASH_SLIDING_EFFECT = "Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl"
        private constant string BASH_SLIDING_ATTACH = "origin"
        
        private constant real MS_SLIDE_REDUCTION = 0.50 // IN PERCENTAGE //
        
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_SIEGE
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
        private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
        
        private constant integer MAXIMUM_PUSHED = 250
    endglobals
        
    private function Damage takes integer lvl returns real
        if lvl == 1 then
            return 120.00 // DAMAGE AT LEVEL 1 //
        elseif lvl == 2 then
            return 200.00 // DAMAGE AT LEVEL 2 //
        elseif lvl == 3 then
            return 320.00 // DAMAGE AT LEVEL 3 //
        elseif lvl == 4 then
            return 400.00 // DAMAGE AT LEVEL 4 //
        endif
        return 490.00 // DAMAGE AT LEVEL 5 //
    endfunction
    
    private function Distance takes integer lvl returns real
        if lvl == 1 then
            return 300.00 // KNOCKBACK DISTANCE AT LEVEL 1 //
        elseif lvl == 2 then
            return 350.00 // KNOCKBACK DISTANCE AT LEVEL 2 //
        elseif lvl == 3 then
            return 400.00 // KNOCKBACK DISTANCE AT LEVEL 3 //
        elseif lvl == 4 then
            return 450.00 // KNOCKBACK DISTANCE AT LEVEL 4 //
        endif
        return 500.00 // KNOCKBACK DISTANCE AT LEVEL 5 //
    endfunction

    private struct Bash
        unit caster
        real cx
        real cy
        integer num                             = 0
        unit array target [ MAXIMUM_PUSHED ]
        real array tx [ MAXIMUM_PUSHED ]
        real array ty [ MAXIMUM_PUSHED ]
        real array n [ MAXIMUM_PUSHED ]
        real array cos [ MAXIMUM_PUSHED ]
        real array sin [ MAXIMUM_PUSHED ]
        real array rate [ MAXIMUM_PUSHED ]
        real array dec [ MAXIMUM_PUSHED ]
        real distance
                
        static method Move takes nothing returns boolean
            local Bash b = TT_GetData()
                        
            local boolean flag = false
            
            local integer i = 0
            local real x
            local real y 
            local real nx
            local real ny
            
            loop
                set i = i + 1
                
                set x = GetUnitX( b.target[ i ] )
                set y = GetUnitY( b.target[ i ] )
                
                call DestroyEffect( AddSpecialEffectTarget( BASH_SLIDING_EFFECT, b.target[ i ], BASH_SLIDING_ATTACH ) )
                
                set nx = x + b.rate * b.cos[ i ]
                set ny = y + b.rate * b.sin[ i ]
                
                call SetUnitPosition( b.target[ i ], nx, ny )
                
                set b.n[ i ] = b.n[ i ] + b.rate
                set b.rate[ i ] = b.rate[ i ] - b.dec[ i ]
                                                           
                if b.rate[ i ] <= 0.00 or b.n[ i ] >= b.distance then
                    call PauseUnit( b.target[ i ], false )
                    set b.target[ i ] = null
                    set b.num = b.num - 1
                endif
                
                exitwhen i >= b.num
            endloop
            
            if b.num <= 0 then
                set flag = true
            endif
            
            return flag        
        endmethod
        
        static method Actions takes nothing returns nothing
            local Bash b = Bash.create()
            
            local real q = 1.00 / TT_PERIOD
            local group g = CreateGroup()
            local unit u = null
            local real angle
            
            local integer lvl
            local real damage

            set b.caster = GetTriggerUnit()
            set b.cx = GetUnitX( b.caster )
            set b.cy = GetUnitY( b.caster )
            
            set lvl = GetUnitAbilityLevel( b.caster, BASH_ABILITY_ID )
            set damage = Damage( lvl ) 
            set b.distance = Distance( lvl )           
            
            set g = UnitsInFront( b.caster, 225.00 )
            
            loop
                set u = FirstOfGroup( g )
                
                if IsUnitEnemy( u, GetOwningPlayer( b.caster ) ) == true and IsUnitType( u, UNIT_TYPE_STRUCTURE ) == false and IsUnitType( u, UNIT_TYPE_FLYING ) == false then
                    set b.num = b.num + 1
                    
                    set b.n[ b.num ] = 0.00
                                    
                    set b.target[ b.num ] = u
                    set b.tx[ b.num ] = GetUnitX( b.target[ b.num ] )
                    set b.ty[ b.num ] = GetUnitY( b.target[ b.num ] )
                
                    set angle = bj_RADTODEG * Atan2( b.ty[ b.num ] - b.cy , b.tx[ b.num ] - b.cx )
                
                    set b.cos[ b.num ] = Cos( angle * bj_DEGTORAD )
                    set b.sin[ b.num ] = Sin( angle * bj_DEGTORAD )
                    
                    set b.rate[ b.num ] = ( 2 * b.distance ) / ( q + 1 )
                    set b.dec[ b.num ] = b.rate[ b.num ] / q
                    
                    call BJDebugMsg( I2S( b.num ) + ", b.rate : " + R2S( b.rate[ b.num ] ) )
                    call BJDebugMsg( I2S( b.num ) + ", b.dec : " + R2S( b.dec[ b.num ] ) )
                    
                    call UnitDamageTarget( b.caster, b.target[ b.num ], damage, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE )
                    call PauseUnit( b.target[ b.num ], true )
                endif

                exitwhen u == null
                
                call GroupRemoveUnit( g, u )
            endloop
                                            
            call DestroyEffect( AddSpecialEffectTarget( BASH_CAST_EFFECT, b.caster, BASH_CAST_ATTACH_1 ) )
            call DestroyEffect( AddSpecialEffectTarget( BASH_CAST_EFFECT, b.caster, BASH_CAST_ATTACH_2 ) )

            call TT_Start( function Bash.Move, b )
            
            call DestroyGroup( g )
            set g = null
        endmethod
                
        static method Check_ID takes nothing returns boolean
            return GetSpellAbilityId() == BASH_ABILITY_ID
        endmethod

    //===========================================================================
       
        static method onInit takes nothing returns nothing
            local trigger B = CreateTrigger(  )
            local integer i = 0
            
            loop 
                exitwhen i > 15
                call TriggerRegisterPlayerUnitEvent( B, Player( i ), EVENT_PLAYER_UNIT_SPELL_EFFECT, Condition( function True ) )
                
                set i = i + 1
            endloop
            
            call TriggerAddCondition( B, Condition( function Bash.Check_ID ) )
            call TriggerAddAction( B, function Bash.Actions )
            
            set B = null
            
            call Preload( BASH_SLIDING_EFFECT )
            call Preload( BASH_CAST_ATTACH_1 )
            call Preload( BASH_CAST_ATTACH_2 )
            call Preload( BASH_CAST_EFFECT )
            call Preload( BASH_SLIDING_ATTACH )
        endmethod
    
    endstruct

endscope

The Debug Messages display the right thing but it knockbacks too fast, almost (actually really)instantly
Also for some reason, the distance it knockbacks increases with every cast of the spell..

Can anyone help? [ + rep ]

EDIT:
I also followed the efficient knockback tutorial in this spell.
03-16-2009, 10:18 AM#2
Viikuna-
b.rate should probably be b.rate[i] in your periodic function.
03-16-2009, 12:56 PM#3
Anitarf
Why bother with arrays, why not have a struct per knockbacked unit instead? Would simplify the code a bit and reduce the chance of such errors.
03-16-2009, 01:01 PM#4
MaD[Lion]
u use a loop, loop is "instant", so ye. u have to use a time delayed method. which isnt loop but timer
03-16-2009, 02:04 PM#5
busterkomo
Collapse JASS:
private function Distance takes integer lvl returns real
        if lvl == 1 then
            return 300.00 // KNOCKBACK DISTANCE AT LEVEL 1 //
        elseif lvl == 2 then
            return 350.00 // KNOCKBACK DISTANCE AT LEVEL 2 //
        elseif lvl == 3 then
            return 400.00 // KNOCKBACK DISTANCE AT LEVEL 3 //
        elseif lvl == 4 then
            return 450.00 // KNOCKBACK DISTANCE AT LEVEL 4 //
        endif
        return 500.00 // KNOCKBACK DISTANCE AT LEVEL 5 //
    endfunction

Can easilly be optimized into:
Collapse JASS:
private function Distance takes integer lvl returns real
return lvl * 50. + 250.
endfunction
The reason for your spell being instant is that it loops are instant (well, basically), therefore, your spell will also execute the distance instantly. You'll need to use timers instead. Also, what exactly is the purpose behind using mass arrays? You're making my eyes bleed. Structs are probably more ideal for a knockback to avoid certain bugs.
03-17-2009, 01:39 PM#6
XeNiM666
actually Viikuna's suggestion worked.

Quote:
Why bother with arrays, why not have a struct per knockbacked unit instead? Would simplify the code a bit and reduce the chance of such errors.
Don't know how to do that... :D:D

Thanks for the suggestion every one! :D
03-17-2009, 04:37 PM#7
Viikuna-
Little mistakes like that are really anoying and really hard to spot, because when you read your own code, you dont only use your eyes but also your memory ( so you see what you want to see ).

Just debug your code properly and use some logic. If knocback is nearly instant, the velocity variable is the first thing you should check.