• 🏆 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] Toss spell not properly landing units

Status
Not open for further replies.
Level 7
Joined
Mar 8, 2009
Messages
360
Again another vJASS spell problem.
My spell is completely working except that a tossed unit is 'floating' above the ground when there is a unit below it when landing.

These are the most important parts of the spell:

JASS:
//Disable pathing so unit should go through units, but it isn't working
//This is set when the spell starts
call SetUnitPathing(sTarget, false)

//**************
// After unit is tossed:

//This turns unit collision on again 
call SetUnitPathing(toss.launchUnit, true)
//Unpause unit
call PauseUnit(toss.launchUnit, false)
//Set unit to closest free spot, (this function works even though the unit floats above the ground)
call SetUnitPosition( toss.launchUnit, GetUnitX(toss.launchUnit), GetUnitY(toss.launchUnit))

Full spell:
JASS:
// Uses:
// -SpellEvent by Anitarf
// -xebasic by Vexorian
// -TimerUtils by Vexorian
// -GroupUtils by Rising Dusk
scope CreepLaunch initializer Init
    globals
        private constant integer SPELLID = 'A01N'
        //How much times the unit is moved untill it's on target location
        private constant integer INTERVALS = 30
        // Max height the unit can reach.
        private constant real MAXHEIGHT = 800.00
        //Effect when unit hits ground
        private constant string EFFECT = "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl"
        //Range to which units can be shooted
        private constant real RANGE = 800.00  
        private constant real AOE = 250.00
        //End of lane coordinates
        private constant real T1X = -480.00
        private constant real T1Y = 770.00
        private constant real T2X = 80.00
        private constant real T2Y = 760.00
    endglobals
    
    //=========================================================================
    
    private struct Data
        unit launchUnit
        unit launcher
        integer remainingIntervals
        real targetx
        real targety
        
        static method create takes unit launcher, unit launchUnit, real targetX, real targetY returns Data
            local Data toss = Data.allocate()
            set toss.launcher = launcher
            set toss.launchUnit = launchUnit
            set toss.remainingIntervals = INTERVALS
            set toss.targetx = targetX
            set toss.targety = targetY
            return toss
        endmethod          
    endstruct
                
    globals
        private constant real a = SquareRoot(MAXHEIGHT) / (INTERVALS/2)
        private boolexpr b2
        private boolexpr b
    endglobals
    
    private function isUnitAlly2 takes nothing returns boolean
        return GetOwningPlayer(GetFilterUnit())==Player(10) or GetOwningPlayer(GetFilterUnit())==Player(11)
    endfunction

    private function Damage takes unit launcher, unit target, player id returns nothing
        local group units = NewGroup()
        local real damage = GetWidgetLife(target)/2        
                
        //Order unit to move to end of path
        if GetPlayerId(id) == 10 then
            call IssuePointOrder( target, "move", T1X, T1Y)
        else
            call IssuePointOrder( target, "move", T2X, T2Y)
        endif
        
        call DestroyEffect(AddSpecialEffect(EFFECT, GetUnitX(target), GetUnitY(target)))
        
        //Damage units around target
        call GroupEnumUnitsInRange(units, GetUnitX(target), GetUnitY(target), AOE, b2)
        loop
            exitwhen FirstOfGroup(units) == null
            call UnitDamageTarget( launcher, FirstOfGroup(units), damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
            call GroupRemoveUnit( units, FirstOfGroup(units))
        endloop
        
        call ReleaseGroup(units)
    endfunction
    
    private function Launch takes nothing returns nothing
        local Data toss = GetTimerData( GetExpiredTimer())
        set toss.remainingIntervals = toss.remainingIntervals - 1        
        
        if toss.remainingIntervals >= 0 then
            call SetUnitPosition( toss.launchUnit, GetUnitX(toss.launchUnit) + ((toss.targetx - GetUnitX(toss.launchUnit)) / toss.remainingIntervals), GetUnitY(toss.launchUnit) + ((toss.targety - GetUnitY(toss.launchUnit)) / toss.remainingIntervals))
            call SetUnitFlyHeight( toss.launchUnit, MAXHEIGHT - (a*(toss.remainingIntervals - (INTERVALS/2)))*(a*(toss.remainingIntervals - (INTERVALS/2))), 0)
        endif                   
              
        if toss.remainingIntervals <= 0 then
            call SetUnitPathing(toss.launchUnit, true)
            call PauseUnit(toss.launchUnit, false)
            call SetUnitPosition( toss.launchUnit, GetUnitX(toss.launchUnit), GetUnitY(toss.launchUnit))
            call Damage(toss.launcher, toss.launchUnit, GetOwningPlayer(toss.launcher))
            call ReleaseTimer(GetExpiredTimer())
            call toss.destroy()            
        endif
    endfunction
           
    private function isUnitAlly takes nothing returns boolean
        return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) and (GetFilterUnit() != GetSpellTargetUnit())
    endfunction
    
    private function Actions takes nothing returns nothing
        local timer t
        local group uG = NewGroup()
        local Data toss
        local unit sTarget = SpellEvent.TargetUnit
        local unit tUnit = SpellEvent.CastingUnit
        local real targetX = GetUnitX(sTarget)
        local real targetY = GetUnitY(sTarget)
        
        call PauseUnit(sTarget, true)
        call SetUnitPathing(sTarget, false)
        
        call UnitAddAbility( sTarget, XE_HEIGHT_ENABLER )
        call UnitRemoveAbility( sTarget, XE_HEIGHT_ENABLER )
        
        call SetUnitPosition( sTarget, GetUnitX(tUnit), GetUnitY(tUnit))
        
        call GroupEnumUnitsInRangeCounted(uG, GetUnitX(tUnit), GetUnitY(tUnit), RANGE, b, 1)
        if FirstOfGroup(uG) != null then
            set targetX = GetUnitX(FirstOfGroup(uG))
            set targetY = GetUnitY(FirstOfGroup(uG))
        endif
        
        set toss = Data.create( SpellEvent.CastingUnit, sTarget, targetX, targetY)
        set t = NewTimer()        
        call SetTimerData( t, toss)
        call TimerStart( t, XE_ANIMATION_PERIOD, true, function Launch)
        
        call ReleaseGroup(uG)
        set sTarget = null
        set tUnit = null
    endfunction    

    private function Init takes nothing returns nothing
        call RegisterSpellEffectResponse(SPELLID, Actions)
        
        set b2 = Condition(function isUnitAlly2)
        set b = Condition(function isUnitAlly)
    endfunction
endscope

thanks in forward
 
Status
Not open for further replies.
Top