HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Charge spell goes over cliffs.

10-23-2007, 02:05 PM#1
Lordy
My charge spell still goes over cliffs.
Using "IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY)" only stops the unit from charging over water.
How do I stop my charging hero from going over cliffs?
10-23-2007, 02:54 PM#2
Vexorian
You'll have to post some code...
10-23-2007, 07:23 PM#3
Pyrogasm
One problem may be that IsTerrainPathable returns false if it is pathable and true if it isn't.

Just stick a "not" in front of it: if not(IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY)) then
10-23-2007, 08:49 PM#4
Lordy
I don't know if reading my code is the fastest way to find my answer, but I now posted it at the bottom of this post. The important part is in the function Phase2Update, which is this line:
Collapse JASS:
    if collidingdestructables > 0 or not IsTerrainPathable(newx+collisionradius*str.maxxvelocity/maxvelocity,newy+collisionradius*str.maxyvelocity/maxvelocity,PATHING_TYPE_WALKABILITY) then        
//hero has crashed into something.
        call End(str) 
the coordinates given to IsTerrainPathable make up the herolocation plus a vector of length collisionradius that is pointed towards the direction of the hero.

Collapse JASS:
scope Rampage

globals
    //public constant integer SpellId = 'A009'
    public constant integer SpellId = 'A04Q'
    public constant integer ShockwaveId = 'h005'
    private constant real moveinterval = 0.02
    private constant real accelmod = 0.01
    private constant real collisionradius = 150.0
    private constant real switchdistance = 400.0
    private constant real minimumrange = switchdistance + 100.0
    private constant real shockahead = 60.0
    private constant real slowmod = 300.0/PointsPerMeter
    private constant real dmgmod = 50.0
    private constant real crashslow = 150.0/PointsPerMeter
    private constant real slowduration = 2.0
    private constant real maxvelocity = 20.0*PointsPerMeter
    private constant string slowmodel = "Abilities\\Spells\\Orc\\StasisTrap\\StasisTotemTarget.mdl"
endglobals

struct Rampage_Struct
    unit hero
    unit shockwave
    timer updatetimer = CreateTimer()
    real runningtime = 0
    real maxxvelocity
    real maxyvelocity
    real targetx
    real targety
    real switchx
    real switchy
    real facing
    real slow
    real dmg
    real vx0
    real vy0
endstruct

private function End takes Rampage_Struct str returns nothing
    call PauseUnit(str.hero,false)
    call FlushHandleLocals(str.updatetimer)
    call PauseTimer(str.updatetimer)
    call DestroyTimer(str.updatetimer)
    call ResetUnitAnimation(str.hero)
    call RemoveUnit(str.shockwave)
    call SetUnitBusy(str.hero,false)
    call Msg("RampageEnd")
endfunction

private function Phase2Collision takes nothing returns nothing
    local unit subject = GetEnumUnit()
    local unit hero = udg_tempunit
    local real subjectx = GetWidgetX(subject)
    local real subjecty = GetWidgetY(subject)
    local integer hi = H2I(hero)
    local string ss = I2S(H2I(subject))
    
    call SetUnitPosition(subject, subjectx, subjecty)
    if GetStoredInteger(MainGamecache,ss,"slowedbymamak") != hi then
        call DestroyEffectWait(AddSpecialEffectTarget(slowmodel, subject, "overhead"), slowduration)
        call SlowUnit(subject,udg_tempreal,slowduration)
        call UnitDamageTargetNew(hero,subject,udg_tempreal2, 2, 0, 0)
        call StoreInteger(MainGamecache,ss,"slowedbymamak",hi)
        call TriggerSleepAction(slowduration)
        if GetStoredInteger(MainGamecache,ss,"slowedbymamak") == hi then
            call StoreInteger(MainGamecache,ss,"slowedbymamak",0)
        endif
    endif
    set hero = null
    set subject = null
endfunction

private function Phase2CollisionWrapper takes nothing returns nothing
    call ExecuteFunc(SCOPE_PRIVATE+"Phase2Collision")
endfunction

private function CollisionCondition takes nothing returns boolean
    if TargetTypeConditionEasy(GetFilterUnit(),udg_tempunit,0,1,0,0,0,0,0,0,0,0,2) then
        call Msg("collider = "+GetUnitName(GetFilterUnit()))
    endif
    return TargetTypeConditionEasy(GetFilterUnit(),udg_tempunit,0,1,0,0,0,0,0,0,0,0,2)
endfunction

private function DestructableCollision takes nothing returns nothing
    set udg_tempint = udg_tempint + 1
endfunction

private function Phase2Update takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local Rampage_Struct str = GetHandleInt(updatetimer,"struct")
    local real herox = GetWidgetX(str.hero)
    local real heroy = GetWidgetY(str.hero)
    local real vmod
    local real xvelocity
    local real yvelocity
    local integer groupsize
    local real newx
    local real newy
    local group collisiongroup = CreateGroup()
    local location newheroloc
    local integer collidingdestructables
    local real dx
    local real dy
    
    set str.runningtime = str.runningtime+moveinterval
    set vmod = (1-Pow(bj_E,-accelmod*str.runningtime))
    set xvelocity = str.vx0+(str.maxxvelocity-str.vx0)*vmod
    set yvelocity = str.vy0+(str.maxyvelocity-str.vy0)*vmod
    set dx = xvelocity*moveinterval
    set dy = yvelocity*moveinterval
    set newx = herox + dx
    set newy = heroy + dy
    set newheroloc = Location(newx,newy)
    
    //call Msg("RampagePhase2Update")
    
    set udg_tempunit = str.hero
    set udg_tempint = 0
    call EnumDestructablesInCircleBJ(collisionradius,newheroloc,function DestructableCollision)
    set collidingdestructables = udg_tempint
    
    if collidingdestructables > 0 or not IsTerrainPathable(newx+collisionradius*str.maxxvelocity/maxvelocity,newy+collisionradius*str.maxyvelocity/maxvelocity,PATHING_TYPE_WALKABILITY) then
        //crash
        call End(str)
        call SlowUnit(str.hero,crashslow,slowduration)
        call DestroyEffectWait(AddSpecialEffectTarget(slowmodel, str.hero, "overhead"), slowduration)
        call Msg("RampageCrash2")
    else
        call SetUnitCor(str.hero, newx, newy)
        call SetUnitCor(str.shockwave, GetWidgetX(str.shockwave) + dx, GetWidgetY(str.shockwave) + dy)
    endif   
    
    set udg_tempunit = str.hero
    set udg_tempreal = str.slow
    set udg_tempreal2 = str.dmg
    call GroupEnumUnitsInRange(collisiongroup,newx,newy,collisionradius,Condition(function CollisionCondition))
    call ForGroup(collisiongroup, function Phase2CollisionWrapper)  
    
    if xvelocity > 0 then
        if newx > str.targetx then
            //rampageend
            call End(str)
        else
            //maybe no phase2
            if yvelocity > 0 then
                if newy > str.targety then
                    //rampageend
                    call End(str)
                else
                    //no phase2
                endif
            else
                if newy < str.targety then
                    //rampageend
                    call End(str)
                else
                    //no phase2
                endif
            endif
        endif
    else
        if newx < str.targetx then
            //rampageend
            call End(str)
        else
            //maybe no phase2
            if yvelocity > 0 then
                if newy > str.targety then
                    //rampageend
                    call End(str)
                else
                    //no phase2
                endif
            else
                if newy < str.targety then
                    //rampageend
                    call End(str)
                else
                    //no phase2
                endif
            endif
        endif
    endif
    
    call DestroyGroup(collisiongroup)
    set collisiongroup = null
    call RemoveLocation(newheroloc)
    set newheroloc = null
    set updatetimer = null
endfunction

private function Phase2Start takes Rampage_Struct str, real herox, real heroy returns nothing
    set str.shockwave = CreateUnit(Player(15), ShockwaveId, herox + shockahead*Cos(str.facing), heroy + shockahead*Sin(str.facing), str.facing*bj_RADTODEG)
    call TimerStart(str.updatetimer, moveinterval, true, function Phase2Update)
    call Msg("RampagePhase2Start")
endfunction

private function Phase1Update takes nothing returns nothing
    local timer updatetimer = GetExpiredTimer()
    local Rampage_Struct str = GetHandleInt(updatetimer,"struct")
    local real herox = GetWidgetX(str.hero)
    local real heroy = GetWidgetY(str.hero)
    local real vmod
    local real xvelocity
    local real yvelocity
    local real newx
    local real newy
    local integer groupsize
    local group collisiongroup = CreateGroup()
    local location newheroloc
    local integer collidingdestructables
    set str.runningtime = str.runningtime+moveinterval
    set vmod = (1-Pow(bj_E,-accelmod*str.runningtime))
    set xvelocity = str.vx0+(str.maxxvelocity-str.vx0)*vmod
    set yvelocity = str.vy0+(str.maxyvelocity-str.vy0)*vmod
    set newx = herox + xvelocity*moveinterval
    set newy = heroy + yvelocity*moveinterval
    set newheroloc = Location(newx,newy)
    
    
    //call Msg("RampageUpdate")
    
    set udg_tempunit = str.hero
    set udg_tempint = 0
    call EnumDestructablesInCircleBJ(collisionradius,newheroloc,function DestructableCollision)
    set collidingdestructables = udg_tempint
    if collidingdestructables == 0 then
        set collisiongroup = CreateGroup()
        call GroupEnumUnitsInRange(collisiongroup,newx,newy,collisionradius,Condition(function CollisionCondition))
        set groupsize = CountUnitsInGroup(collisiongroup)
        call DestroyGroup(collisiongroup)
        set collisiongroup = null
    endif
    if groupsize > 0 or collidingdestructables > 0 or not IsTerrainPathable(newx+collisionradius*str.maxxvelocity/maxvelocity,newy+collisionradius*str.maxyvelocity/maxvelocity,PATHING_TYPE_WALKABILITY) then
        call End(str)
        call SlowUnit(str.hero,crashslow,slowduration)
        call DestroyEffectWait(AddSpecialEffectTarget(slowmodel, str.hero, "overhead"), slowduration)
        call Msg("RampageCrash1")
    else
        call SetUnitCor(str.hero, newx, newy)
        if xvelocity > 0 then
            if newx > str.switchx then
                //phase2
                call Phase2Start(str,herox,heroy)
            else
                //maybe no phase2
                if yvelocity > 0 then
                    if newy > str.switchy then
                        //phase2
                        call Phase2Start(str,herox,heroy)
                    else
                        //no phase2
                    endif
                else
                    if newy < str.switchy then
                        //phase2
                        call Phase2Start(str,herox,heroy)
                    else
                        //no phase2
                    endif
                endif
            endif
        else
            if newx < str.switchx then
                //phase2
                call Phase2Start(str,herox,heroy)
            else
                //maybe no phase2
                if yvelocity > 0 then
                    if newy > str.switchy then
                        //phase2
                        call Phase2Start(str,herox,heroy)
                    else
                        //no phase2
                    endif
                else
                    if newy < str.switchy then
                        //phase2
                        call Phase2Start(str,herox,heroy)
                    else
                        //no phase2
                    endif
                endif
            endif
        endif
    endif   
    

    
    call RemoveLocation(newheroloc)
    set newheroloc = null
    set updatetimer = null
endfunction

public function Starts takes nothing returns nothing
    local Rampage_Struct str = Rampage_Struct.create()
    local player p = GetTriggerPlayer()
    local location targetloc = GetSpellTargetLoc()
    local real herox 
    local real heroy
    local real castdistancesqr
    local real movespeed
    local real wait
    local real levelmod
    local real herolevelmod
    local real cosfacing
    local real sinfacing

    set str.hero = GetTriggerUnit()
    set levelmod = SquareRoot(GetUnitAbilityLevel(str.hero,SpellId))
    set herolevelmod = SquareRoot(I2R(GetHeroLevel(str.hero)))
    set str.dmg = dmgmod * levelmod * herolevelmod
    set str.slow = slowmod * levelmod / herolevelmod
    set movespeed = GetUnitMoveSpeed(str.hero)
    set herox = GetWidgetX(str.hero)
    set heroy = GetWidgetY(str.hero)
    set str.targetx = GetLocationX(targetloc)
    set str.targety = GetLocationY(targetloc)
    set str.facing = Angle(herox, heroy, str.targetx, str.targety)
    set cosfacing = Cos(str.facing)
    set sinfacing = Sin(str.facing)
    set str.vx0 = cosfacing*movespeed
    set str.vy0 = sinfacing*movespeed
    set str.maxxvelocity = cosfacing*maxvelocity*PointsPerMeter
    set str.maxyvelocity = sinfacing*maxvelocity*PointsPerMeter
    set str.switchx = herox + cosfacing*switchdistance
    set str.switchy = heroy + sinfacing*switchdistance
    set castdistancesqr = DistanceSqr(herox,heroy,str.targetx,str.targety)
    
    call SetHandleInt(str.updatetimer,"struct",str)
    
    call SetUnitBusy(str.hero,true)
    call TriggerSleepAction(0)
    call PauseUnit(str.hero, true)
    call SetUnitFacing(str.hero,str.facing*bj_RADTODEG)
    //I DUNNO.
    call SetUnitAnimationByIndex(str.hero,1)
    set wait = GetSmallestAngleAbs(str.facing,GetUnitFacing(str.hero)*bj_DEGTORAD)/turnspeed
    call TriggerSleepAction(wait)
    
    call SetUnitAnimationByIndex(str.hero,3)
    call PlaySoundOnUnitBJ(gg_snd_Shockwave, 100, str.hero)
    call TimerStart(str.updatetimer, moveinterval, true, function Phase1Update)

    call RemoveLocation(targetloc)
    set targetloc = null
    set p = null
    call Msg("RampageStart")
endfunction

public function Cast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local player p = GetTriggerPlayer()
    local real facing 
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local location targetloc = GetSpellTargetLoc()
    local real targetx = GetLocationX(targetloc)
    local real targety = GetLocationY(targetloc)
    local real castdistancesqr = DistanceSqr(herox,heroy,targetx,targety)
    local real mindistancesqr = minimumrange*minimumrange
    
    if castdistancesqr < mindistancesqr then
        call SimError(p,"Cannot cast within minimum range")
        call IssueImmediateOrder(hero,"stop")
    endif
    
    call RemoveLocation(targetloc)
    set targetloc = null
    set hero = null
    set p = null
endfunction
endscope //Rampage
10-23-2007, 10:32 PM#5
The Elite
please use jass tags.
Code:
[jass]    call PolledWait(1.00)[/jass]
Collapse JASS:
    call PolledWait(1.00)