• 🏆 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, Problem with groupflying and an endless loop

Status
Not open for further replies.
Level 13
Joined
Mar 16, 2008
Messages
941
Hi, I have a problem with a spell.

So what does it do?
First you have to target your target (no, really?). Your hero will jump to the middle of the distance between you and your target. The ground deforms under his jump energy, in compensation the ground under your target will raise up fast, throwing all enemys on it in the air. While landing (all timed, so it's not really while landing ith's while the end of the timer :razz:) they take the earth with them, ripping the "hill" down to earth and creating a huge deformation, a hole.
In this hole 10 seconds every 1 second cyrcles of impale (I hope that's the right name, at least it's the order) attack the enemys and then the hole will raise up to normal height.

So nearly all works, but my enemys don't fly in the air and the impale cyrcles don't stop after 10 seconds, they are never ending :sad:

EDIT:It's now ending, my fault saving an int with SetHandleReal, but the units still don't fly

I've hidden the text because this are 300 lines :razz:

JASS:
function Parabula takes real H, real T, real x returns real
    return ((4*H)/-(T*T))*(x*x) + ((4*H)/T)*x
endfunction

function Jump_High takes nothing returns real
    return 500.0
endfunction

function Jump_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction

function Jump_Enemys takes nothing returns boolean
    return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(bj_ghoul[501])) == true and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false
endfunction


function Jump_Damage takes nothing returns nothing
    local timer tform = GetExpiredTimer()
    
    local unit caster = GetHandleUnit(tform, "caster")
    local unit dummy = null
    
    local player owner = GetOwningPlayer(caster)
    
    local real tx = GetHandleReal(caster, "tx")
    local real ty = GetHandleReal(caster, "ty")
    local real rx = 0.0
    local real ry = 0.0
    local real angle = 0.0
    local real distance = 400.0
    
    local integer loopindex = GetHandleInt(tform, "loopindex") + 1
    local integer spawnindex = 0
    local integer level = GetUnitAbilityLevel(caster, 'A000')
    
    loop
        set spawnindex = spawnindex + 1
        set angle = 12 * spawnindex
        set rx = tx + distance * Cos(angle * bj_DEGTORAD)
        set ry = ty + distance * Sin(angle * bj_DEGTORAD)
        set dummy = CreateUnit(owner, 'o001', tx, ty, 0.0)
        call UnitApplyTimedLife(dummy, 'BTLF', 1.0)
        call SetUnitAbilityLevel(dummy, 'A001', level)
        call IssuePointOrder(dummy, "impale", rx, ry)
        exitwhen spawnindex >= 30
    endloop 

    if (loopindex >= 10) then
        call PauseTimer(tform)
        call FlushHandleLocals(tform)
        call DestroyTimer(tform)
        set tform = null
        
        call TerrainDeformCrater(tx, ty, 500, -600, 2000, true)
    else
        call SetHandleIntl(tform, "loopindex", loopindex)
    endif
    
    set caster = null
    set dummy = null
endfunction

function Jump_Deform_Last takes nothing returns nothing
    local timer tdeform = GetExpiredTimer()
    local timer tform = CreateTimer()
    
    local unit caster = GetHandleUnit(tdeform, "caster")
    
    local real tx = GetHandleReal(caster, "tx")
    local real ty = GetHandleReal(caster, "ty")
    
    call TerrainDeformCrater(tx, ty, 500, 600, 200, true) 

    call SetHandleHandle(tform, "caster", caster)
    call TimerStart(tform, 1.0, true, function Jump_Damage)
    
    call FlushHandleLocals(tdeform)
    call DestroyTimer(tdeform)
    set tdeform = null
    
    set caster = null
endfunction

function Jump_Land takes nothing returns nothing
    local timer tland = GetExpiredTimer()
    local timer tdeform = CreateTimer()
    
    local unit caster = GetHandleUnit(tland, "caster")
    
    local real cx = GetHandleReal(caster, "cx")
    local real cy = GetHandleReal(caster, "cy")
    local real tx = GetHandleReal(caster, "tx")
    local real ty = GetHandleReal(caster, "ty")
    
    call TerrainDeformCrater(cx, cy, 200, -400, 100, true)
    call TerrainDeformCrater(tx, ty, 200, 400, 100, true) 

    call SetHandleHandle(tdeform, "caster", caster)
    call TimerStart(tdeform, 0.1, false, function Jump_Deform_Last)
    
    call FlushHandleLocals(tland)
    call DestroyTimer(tland)
    set tland = null
    
    set caster = null
endfunction
    
function Jump_Victim_Fly takes nothing returns nothing
    local timer tfly = GetExpiredTimer()
    local timer tland = null
    
    local group enemys = GetHandleGroup(tfly, "enemys")
    local group tempenemys = enemys
    local unit enemy = null
    local unit caster = null
    local real ez = 0.0
    local real z = 0.0
    
    local integer loopindex = GetHandleInt(tfly, "loopindex") + 1
    loop
        set enemy = FirstOfGroup(tempenemys)
        exitwhen enemy == null
        set ez = GetUnitZ(enemy)
        set z = Parabula(Jump_High(), 1.96, I2R(loopindex)/56.0)
    
        call SetUnitZ(enemy, z)
        
        call GroupRemoveUnit(tempenemys, enemy)
    endloop
    
    if (loopindex >= 56) then
        set caster = GetHandleUnit(tfly, "caster")
        call PauseTimer(tfly)
        call FlushHandleLocals(tfly)
        call DestroyTimer(tfly)
        set tfly = null
        
        set tland = CreateTimer()
        call SetHandleHandle(tland, "caster", caster)
        call TimerStart(tland, 0.0, false, function Jump_Land)
        
        call DestroyGroup(enemys)
        set enemys = null
    else
        call SetHandleInt(tfly, "loopindex", loopindex)
    endif
        
    call DestroyGroup(tempenemys)
    set tempenemys = null
    set enemy = null
    set caster = null
endfunction
 
function Jump_Victim_Fly_Start takes nothing returns nothing
    local timer tflystart = GetExpiredTimer()
    local timer tfly = CreateTimer()
    
    local real tx = GetHandleReal(tflystart, "tx")
    local real ty = GetHandleReal(tflystart, "ty")
    local location targetloc = Location(tx, ty)
    
    local unit caster = GetHandleUnit(tflystart, "caster")
    local group enemys = null

    set bj_ghoul[501] = caster
    set enemys = GetUnitsInRangeOfLocMatching(200, targetloc, Condition(function Jump_Enemys))
    
    call RemoveLocation(targetloc)
    set targetloc = null
    
    call SetHandleHandle(tfly, "caster", caster)
    call SetHandleHandle(tfly, "enemys", enemys)
    call SetHandleReal(caster, "tx", tx)
    call SetHandleReal(caster, "ty", ty)
    call TimerStart(tfly, 0.035, true, function Jump_Victim_Fly)
    
    set caster = null
endfunction
    
function Jump_Deform takes nothing returns nothing
    local timer tdeform = GetExpiredTimer()
    local timer tflystart = CreateTimer()
    local unit caster = GetHandleUnit(tdeform, "caster")
    
    local real cx = GetUnitX(caster)
    local real cy = GetUnitY(caster)
    local real tx = GetHandleReal(tdeform, "tx")
    local real ty = GetHandleReal(tdeform, "ty")
    
    call TerrainDeformCrater(cx, cy, 200, 400, 100, true)
    call TerrainDeformCrater(tx, ty, 200, -400, 100, true)
    
    call SetHandleHandle(tflystart, "caster", caster)
    call SetHandleReal(tflystart, "tx", tx)
    call SetHandleReal(tflystart, "ty", ty)
    call SetHandleReal(caster, "cx", cx)
    call SetHandleReal(caster, "cy", cy)
    call TimerStart(tflystart, 0.0, false, function Jump_Victim_Fly_Start)
    
    call FlushHandleLocals(tdeform)
    call DestroyTimer(tdeform)
    set tdeform = null 
    
    set caster = null                              
endfunction

function Jump_Move_Up takes nothing returns nothing
    local timer tup = GetExpiredTimer()
    local unit caster = GetHandleUnit(tup, "caster")
    
    local integer loopindex = GetHandleInt(tup, "highindex") + 1

    local real cz = GetUnitZ(caster)
    local real z = Parabula(Jump_High(), 0.98, I2R(loopindex)/28.0)
    
    call SetUnitZ(caster, z)
    
    if (loopindex >= 28) then
        call PauseTimer(tup)
        call FlushHandleLocals(tup)
        call DestroyTimer(tup)
        set tup = null
    else
        call SetHandleInt(tup, "highindex", loopindex)
    endif
    
    set caster = null
endfunction

function Jump_Move_Forward takes nothing returns nothing
    local timer tforward = GetExpiredTimer()
    
    local unit caster = GetHandleUnit(tforward, "caster")
    
    local real range = GetHandleReal(tforward, "range")
    local real angle = GetHandleReal(tforward, "angle")
    local real cx = GetUnitX(caster)
    local real cy = GetUnitY(caster)
    local real xforward = cx + (range / 28) * Cos(angle * bj_DEGTORAD)
    local real yforward = cy + (range / 28) * Sin(angle * bj_DEGTORAD)
    
    local integer loopindex = GetHandleInt(tforward, "forwardindex") + 1

    call SetUnitX(caster, xforward)
    call SetUnitY(caster, yforward)
    
    if (loopindex >= 28) then
        call PauseTimer(tforward)
        call FlushHandleLocals(tforward)
        call DestroyTimer(tforward)
        set tforward = null
    else
        call SetHandleInt(tforward, "forwardindex", loopindex)
    endif

    set caster = null
endfunction

function Jump_Actions takes nothing returns nothing
    local timer tup = CreateTimer()
    local timer tforward = CreateTimer()
    local timer tdeform = CreateTimer()
    
    local unit caster = GetSpellAbilityUnit()
    local unit target = GetSpellTargetUnit()
    local real cx = GetUnitX(caster)
    local real cy = GetUnitY(caster)
    local real tx = GetUnitX(target)
    local real ty = GetUnitY(target)
    
    local real dx = tx - cx
    local real dy = ty - cy
    local real range = SquareRoot(dx * dx + dy * dy)/2
    local real angle = Atan2(dy,dx) * bj_DEGTORAD * 3600

    call SetHandleHandle(tup, "caster", caster)
    call TimerStart(tup, 0.035, true, function Jump_Move_Up)
    
    call SetHandleHandle(tforward, "caster", caster)
    call SetHandleReal(tforward, "range", range)
    call SetHandleReal(tforward, "angle", angle)
    call TimerStart(tforward, 0.035, true, function Jump_Move_Forward)
    
    call SetHandleHandle(tdeform, "caster", caster)
    call SetHandleReal(tdeform, "tx", tx)
    call SetHandleReal(tdeform, "ty", ty)
    call TimerStart(tdeform, 0.98, false, function Jump_Deform)
    
    set caster = null
    set target = null
endfunction

// ==================================================
function InitTrig_Jump takes nothing returns nothing
    set gg_trg_Jump = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Jump, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Jump, Condition( function Jump_Conditions ) )
    call TriggerAddAction( gg_trg_Jump, function Jump_Actions )
endfunction

I hope anyone out there can help me :ugly:
 
Level 9
Joined
Mar 25, 2005
Messages
252
You need to use the flying trick to be able to set the fly height of a non-flying unit. Flying trick means that you add 'Amrf' to a unit and then remove it. Replace your Jump_Victim_Fly_Start function with this code below and I think it should work.
JASS:
function Jump_Victim_Flying_Trick takes nothing returns nothing
	call UnitAddAbility(GetEnumUnit(), 'Amrf')
	call UnitRemoveAbility(GetEnumUnit(), 'Amrf')
endfunction
function Jump_Victim_Fly_Start takes nothing returns nothing
    local timer tflystart = GetExpiredTimer()
    local timer tfly = CreateTimer()

    local real tx = GetHandleReal(tflystart, "tx")
    local real ty = GetHandleReal(tflystart, "ty")

    local unit caster = GetHandleUnit(tflystart, "caster")
    local group enemys = CreateGroup()

    set bj_ghoul[501] = caster
	
	// I replaced your GetUnitsInRangeOfLocMatching call with this one.
	// This does exactly the same but is more efficient and you dont have
	// to use a location.
	call GroupEnumUnitsInRange(enemys, tx, ty, 200, Condition(function Jump_Enemys))
	
	call ForGroup(enemys, function Jump_Victim_Flying_Trick)

    call SetHandleHandle(tfly, "caster", caster)
    call SetHandleHandle(tfly, "enemys", enemys)
    call SetHandleReal(caster, "tx", tx)
    call SetHandleReal(caster, "ty", ty)
    call TimerStart(tfly, 0.035, true, function Jump_Victim_Fly)

    set caster = null
endfunction
 
Level 13
Joined
Mar 16, 2008
Messages
941
1) DAMN THX, sry I have to say it like that, but I found no group functions with coordinates in JassCraft, thx a lot :D

2)Oh sry I have forgotten to show you my script header. SetUnitZ is a workaround someone made on inwarcraft.de:

JASS:
function GetFloorHeight takes real x, real y returns real
    local location whichUnitLocation = Location( x, y )
    local real z = GetLocationZ( whichUnitLocation )
    call RemoveLocation( whichUnitLocation )
    set whichUnitLocation = null
    return z
endfunction

function GetUnitZ takes unit whichUnit returns real
    local real z = ( GetFloorHeight( GetUnitX( whichUnit ), GetUnitY( whichUnit ) ) + GetUnitFlyHeight( whichUnit ) )
    set whichUnit = null
    return z
endfunction

function SetUnitZ takes unit whichUnit, real z returns nothing
    local boolean whichUnitHasNotAmrf = ( GetUnitAbilityLevel( whichUnit, 'Amrf' ) <= 0 )
    if ( whichUnitHasNotAmrf ) then
        call UnitAddAbility( whichUnit, 'Amrf' )
    endif
    call SetUnitFlyHeight( whichUnit, z - GetFloorHeight( GetUnitX( whichUnit ), GetUnitY( whichUnit ) ), 0.00 )
    if ( whichUnitHasNotAmrf ) then
        call UnitRemoveAbility( whichUnit, 'Amrf' )
    endif    
    set whichUnit = null
endfunction
:)

Oh and a second thing, found out that set tempenemys = enemys doesn't create a group, for sure it doesn't, but which function creates a new group with the units of another one?
 
Level 9
Joined
Mar 25, 2005
Messages
252
Ok try this
JASS:
function Jump_Victim_Fly takes nothing returns nothing
    local timer tfly = GetExpiredTimer()
    local timer tland = null

    local group enemys = GetHandleGroup(tfly, "enemys")
    local group tempenemys = CreateGroup()
    local unit enemy = null
    local unit caster = null
    local real ez = 0.0
    local real z = 0.0
    local integer loopindex = SetHandleInt(tfly, "loopindex") + 1
	
	set bj_groupAddGroupDest = tempenemys
	call ForGroup(enemys, function GroupAddGroupEnum)
	
    loop
        set enemy = FirstOfGroup(tempenemys)
        exitwhen enemy == null
        set ez = GetUnitZ(enemy)
        set z = Parabula(Jump_High(), 1.96, I2R(loopindex)/56.0)

        call SetUnitZ(enemy, z)

        call GroupRemoveUnit(tempenemys, enemy)
    endloop

    if (loopindex >= 56) then
        set caster = GetHandleUnit(tfly, "caster")
        call PauseTimer(tfly)
        call FlushHandleLocals(tfly)
        call DestroyTimer(tfly)
        set tfly = null

        set tland = CreateTimer()
        call SetHandleHandle(tland, "caster", caster)
        call TimerStart(tland, 0.0, false, function Jump_Land)

        call DestroyGroup(enemys)
        set enemys = null
    else
        call SetHandleInt(tfly, "loopindex", loopindex)
    endif

    call DestroyGroup(tempenemys)
    set tempenemys = null
    set enemy = null
    set caster = null
endfunction

Previously you were simply destroying the original "enemys" group the first time the timer expired.
This version makes a copy of the original group and loops through that copy and then destroys that copy instead of the original one.

Btw in those GetUnitZ and SetUnitZ functions you don't need to null whichUnit since it is an argument.
 
Status
Not open for further replies.
Top