HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Hydra Bugs

02-18-2006, 02:44 PM#1
FireFreak
the hydra anyhow has a bug. the fireballs get stuck on the doodads in the water or just the water itself and stay there forever, as well a the heads that send them out.
02-18-2006, 03:40 PM#2
Vexorian
After many attempts at making hydras shot to water and water doodads I was unable to reproduce the bug?

Anything special? Patch you are using? OS? or something?
02-18-2006, 09:12 PM#3
ShadowDragon
Bug on Hydra: When shooting at a flying monster, the missiles will get to the position of the monster (underneath it, as flying height is lower) and then disappear, doing no damage.
02-18-2006, 09:41 PM#4
Mc !
Have you made it in that huge green dragon then it wouldn't work coz the dragon is immune to magic I think
02-19-2006, 12:20 PM#5
FireFreak
Quote:
Originally Posted by Vexorian
After many attempts at making hydras shot to water and water doodads I was unable to reproduce the bug?

Anything special? Patch you are using? OS? or something?

i don'd use anything special, despite SP2 and have the newest patch.
i was able to reproduce it, but only after i casted blood man (?).
here is the replay (i hope it helps)

btw the hydra attacks plague clouds (see replay)
Attached Files
File type: zipReplay.zip (35.1 KB)
02-19-2006, 04:16 PM#6
Vexorian
The bug seems to not be related to water or doodads but it is probably the 'timer set to null' bug that sometimes happens when you use return bug too much. Because from what I was able to see you were really unable to reproduce it after many tries, it is a very random bug

Disease cloud: Simply give the 'Locust' ability to disease cloud units.
02-19-2006, 04:34 PM#7
ShadowDragon
Quote:
Originally Posted by Mc !
Have you made it in that huge green dragon then it wouldn't work coz the dragon is immune to magic I think

Yeah, you're right. Still a bug, in that either it shouldn't attack magic immunes, or should damage them. Also, the missiles exploding far below the dragon looks weird.
02-19-2006, 05:37 PM#8
Vexorian
Not a bug you can just change the damage option to not detect spell immunes nor impact on them. Same with flying units
02-19-2006, 07:49 PM#9
Vexorian
Ok FireFreak seems you are lucky at finding that bug. I was unable to but I think this might fix the bug, could you please try yourself before I upload to the attachment?

Collapse JASS:
//********************************************************************************************************
//*                                 A JESP Spell by Vexorian
//* Codename: Hydra
//* ¯¯¯¯¯¯¯¯
//* Requirements:
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯
//* - The "Hydra" ability
//* - The "Hydra head" unit
//* - The Caster System ( [url]http://wc3campaigns.net/vexorian/[/url] )
//* - This Trigger (MAKE SURE TO change the rawcodes in the trigger to the correct ones of your map)
//*
//* Object Editor fields
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* - Unit's First Attack Art - Projectile : Determines the missile effect
//*
//********************************************************************************************************

//===================================================================================================
// Hydra Spell Configuration:
//
//

////
// Important Stuff (Must make sure you change these to correct values)
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// _SpellId : Must match the rawcode of the Hydra Ability
// _UnitId  : Must match the rawcode of the Hydra Head unit, note that you can use different
//            units depending on head index and level.
//
constant function Hydra_SpellId takes nothing returns integer
    return 'A002'
endfunction
constant function Hydra_UnitId takes integer index, integer level returns integer
    return 'o000'
endfunction
constant function Hydra_AttackAnimationPoint takes integer index, integer level returns real
    return 0.5
endfunction

////
// Eye Candy Options
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// _Area           : Spawn distance between the spell cast point and each head
// _FirstSpawnAngle: The angle between the first head and the spell point
// _Animation      : Animation suffix for the different heeads, by index and level
// _Scale          : Model Scale of each head
// _MissileScale   : Model Scale of the missiles by head index and level
//
constant function Hydra_Area takes real level returns real
    return 50+0*level
endfunction
constant function Hydra_FirstSpawnAngle takes integer level returns integer
   return 90
endfunction
constant function Hydra_UnitAnimation takes integer index, integer level returns string
    if (index==3) then
        return "third"
    endif
    if (index==2) then
        return "second"
    endif
 return "first"
endfunction
constant function Hydra_Scale takes integer index, real level returns real
    return 1.0+0.0*level
endfunction
constant function Hydra_MissileScale takes real index, real level returns real
    return 0.5
endfunction
constant function Hydra_MissileHeight takes integer index, integer level returns integer
    if (index==1) then
        return 45
    endif
 return 35
endfunction


////
// Balance Options
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// _Cycle          : Delay in seconds before spitting a new fire bolt
// _Duration       : Total duration of the spell
// _Number         : Number of heads per level
// _BoltSpeed      : Movement speed of the missiles
// _BoltMaxDist    : Maximum distance for missiles' movement
// _BoltImpactDist : Collision Size of each missile
// _ZCollision     : The Collision Size of the missile in the Z axis
//                   (minimum bolt and target flying height difference to allow a hit)
// _Damage         : Damage done by each missile
//
function Hydra_Cycle takes real level returns real
    return 0.4 - 0.05*level
endfunction
constant function Hydra_Duration takes real level returns real
return 1000.0
    return 20+4*level
endfunction
constant function Hydra_Number takes integer level returns integer
    return 3+0*level
endfunction
constant function Hydra_BoltSpeed takes real level returns real
    return 750+0*level
endfunction
constant function Hydra_BoltMaxDist takes real level returns real
    return 2000+0*level
endfunction
constant function Hydra_ImpactDist takes real level returns real
    return 35+0*level
endfunction
constant function Hydra_ZCollision takes real level returns real
    return 60.0
endfunction
function Hydra_Damage takes real level returns real
return 1.1
    return GetRandomReal( 22+3*level , 45+6*level)
    //First is the minimum value, second the maximum, so the result is random
    //Hint : to use random values on other functions make sure to remove the
    //constant preffix
endfunction


////
// Detect Options
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Determine the kind of units that can be detected by the heads
//
function Hydra_DetectOptions  takes integer level returns integer
    return DamageOnlyEnemies() + DamageOnlyVisibles()
    //Visible Enemies only
endfunction

////
// Explode Options
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Determine the kind of units that make fireballs explode when they hit them
//
function Hydra_ExplodeOptions  takes integer level returns integer
    return DamageOnlyEnemies()
    //Hit enemies only
endfunction

////
// Damage Options
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Determine the kind of damage the fireballs cause
//
function Hydra_DamageOptions takes integer level returns integer
    return DamageTypes(ATTACK_TYPE_NORMAL,DAMAGE_TYPE_FIRE)
    //Do normal (spell) fire (magical) damage
endfunction



//===========================================================================

function Hydra_Hit takes nothing returns nothing
 local unit m=GetTriggerCollisionMissile()
 local string mk=GetAttachmentTable(m)
 local string k=I2S(GetTableInt("[Hydra]",mk))
 local unit u
 local integer l
 local unit t=GetTriggerUnit()

    if (t==null) then
        call SetTableInt(k,"fireballs",GetTableInt(k,"fireballs")-1)
        call GroupAddUnit(GetTableGroup(k,"g"),GetTableUnit(k,mk))
    else
        set u=GetTableUnit(k,"u")
        set l=GetTableInt(k,"l")
        if (( RAbsBJ(GetUnitFlyHeight(m)-GetUnitFlyHeight(t) )<=Hydra_ZCollision(l) ) and (GetDamageFactorByOptions(u,t,Hydra_ExplodeOptions(l))!=0)) then
            call CollisionMissile_Destroy(m)
            call DamageUnitByOptions(u,t, Hydra_Damage(l), Hydra_DamageOptions(l))
        endif
        set u=null
        set t=null
    endif
    
 
 set m=null
endfunction


function Hydra_Bolt takes nothing returns nothing
 local timer t=GetExpiredTimer()
 local string kt=GetAttachmentTable(t)
 local integer ki=GetTableInt("[Hydra]",kt)
 local string k=I2S(ki)
 local unit hy=GetTableUnit(k,kt)
 local unit m
 local integer i=GetTableInt(k,GetAttachmentTable(hy))
 local integer l=GetTableInt(k,"l")
 local real s
    call DestroyTimer(t)
    

    set m = CollisionMissile_Create(GetAbilityEffectById(GetUnitTypeId(hy),EFFECT_TYPE_MISSILE,0),GetUnitX(hy),GetUnitY(hy),GetUnitFacing(hy),Hydra_BoltSpeed(l),0,Hydra_BoltMaxDist(l),Hydra_MissileHeight(i,l),true,Hydra_ImpactDist(l),function Hydra_Hit)

    set kt=GetAttachmentTable(m)
    call SetTableInt("[Hydra]",kt,ki)
    call SetTableObject(k,kt,hy)
    set s=Hydra_MissileScale(i,l)
    call SetUnitScale(m,s,s,s)

 set m=null
 set hy=null
 set t=null
endfunction

function Hydra_AttackAnim takes unit u, unit hy, real x, real y, real f, integer l, integer ki, string k, integer i returns nothing
 local integer s=Hydra_SpellId()
 local timer t=CreateTimer()
 local string kt=GetAttachmentTable(t)
 
 local string suf=Hydra_UnitAnimation(i,l)
 
    call SetTableInt("[Hydra]",kt,ki)
    call SetTableObject(k,kt,hy)
    call SetUnitFacing(hy,f)
    call SetUnitAnimation(hy,"attack "+suf)
    call QueueUnitAnimation(hy,"stand "+suf)
    call SetTableInt(k,"fireballs",GetTableInt(k,"fireballs")+1)
    call TimerStart(t,Hydra_AttackAnimationPoint(i,l),false,function Hydra_Bolt)


 set t=null
endfunction

function Hydra_End takes nothing returns nothing
 local timer t=GetExpiredTimer()
   call SetTableBoolean(I2S(GetTableInt("[Hydra]",GetAttachmentTable(t))),"end",true)
   call DestroyTimer(t)
 set t=null
endfunction



function Hydra_OnCycle takes nothing returns nothing
    call ExecuteFunc("Hydra_Attack")
endfunction

function Hydra_GetTarget takes unit ret, group log, integer l, unit u, real x, real y, real z returns unit
 local real f=Hydra_BoltMaxDist(l)
 local real are = f/32
 local real fl
 local group g=CreateGroup()
 local unit rep=null
 local unit p
    if (ret!=null)and(IsUnitInRangeXY(ret,x,y,f)) then
        call GroupAddUnit(g,ret)
    endif
    set ret=null
    set fl=Hydra_ZCollision(l)
    loop
        exitwhen(ret!=null)
        loop
            set p=FirstOfGroup(g)
            exitwhen (p==null) or (ret!=null)
            call GroupRemoveUnit(g,p)       
            if( ( RAbsBJ(GetUnitFlyHeight(p) - z)<=fl) and (GetDamageFactorByOptions(u,p,Hydra_DetectOptions(l))!=0) and ((rep==null) or not(IsUnitInGroup(p,log)) ) )then
                if (IsUnitInGroup(p,log)) then
                    set rep=p
                else
                    set ret=p
                endif
            endif
        endloop
        exitwhen (are>f)
        call GroupEnumUnitsInRange(g,x,y,are,null)
        set are=are+are
    endloop
    if (ret==null) then
        set ret=rep
    endif

 set rep=null
 return ret
endfunction

function Hydra_Attack takes nothing returns nothing
 local timer t=GetExpiredTimer()
 local integer ki=GetTableInt("[Hydra]",GetAttachmentTable(t))
 local integer i
 local string k=I2S(ki)
 local string hk
 local group g=GetTableGroup(k,"g")
 local integer l=GetTableInt(k,"l")
 local integer n
 local group targets = GetTableGroup(k,"targets")

 local unit u=GetTableUnit(k,"u")
 local unit tr
 local unit hy
 local real x
 local real y
 local real f
 local boolean first
 local string tarfield

    if (GetTableBoolean(k,"end")) then
        loop
            exitwhen (GetTableInt(k,"fireballs")<=0)
            call TriggerSleepAction(0)
        endloop

        call GroupAddUnit(g,null)
        loop
            set hy=FirstOfGroup(g)
            exitwhen (hy==null)
            call GroupRemoveUnit(g,hy)
            //set suf=Hydra_UnitAnimation(GetTableInt(k,GetAttachmentTable(hy) ),l)
            call ExplodeUnitBJ(hy)
            //call SetUnitAnimation(hy,"death "+suf)
        endloop
        call DestroyGroup(g)
        call DestroyGroup(targets)

        call DestroyTimer(t)
        set n=GetTableInt("[Hydra]","n")
        if (n<=1) then
            call ClearTable("[Hydra]")
        else
            call SetTableInt("[Hydra]","n",n-1)
        endif
        call DestroyTable(k)
    else
        set first=true
        loop
            set hy=FirstOfGroup(g)
            exitwhen (hy==null)
            call GroupRemoveUnit(g,hy)
            if (not first) then
                call TriggerSleepAction(0)
            endif
            set x=GetUnitX(hy)
            set y=GetUnitY(hy)
            set hk=GetAttachmentTable(hy)
            set tarfield="target"+hk
            set tr=GetTableUnit(k,tarfield)
            call GroupRemoveUnit(targets,tr)
            set i=GetTableInt(k,hk)
            set tr=Hydra_GetTarget(tr,targets,l,u,x,y,Hydra_MissileHeight(i,l))
            if (tr!=null) then
                set f=Atan2BJ(GetUnitY(tr)-y,GetUnitX(tr)-x)
                call Hydra_AttackAnim(u,hy,x,y,f,l,ki,k,i)
                call GroupAddUnit(targets,tr)
                call SetTableObject(k,tarfield,tr)
            else
                call GroupAddUnit(g,hy)
                exitwhen true
            endif
            
            set first=false            
        endloop
    
        set tr=null
        call TimerStart(t,Hydra_Cycle(l),false,function Hydra_OnCycle)
    endif
  
 set g=null
 set t=null
 set u=null
 set targets=null
endfunction

function Hydra_DoIt takes timer t, timer end returns nothing
 local unit u=GetTriggerUnit()
 local integer s=GetSpellAbilityId()
 local integer l=GetUnitAbilityLevel(u,s)
 local unit hy
 local integer n=Hydra_Number(l)
 local integer a=0
 local location loc=GetSpellTargetLoc()
 local real x=GetLocationX(loc)
 local real y=GetLocationY(loc)
 local real xu
 local real yu
 local real d=Hydra_Area(l)

 local real h
 local group g=CreateGroup()

 local string suf
 local integer ki=NewTableIndex()
 local string k=I2S(ki)
 local string hk
 local real grad = Hydra_FirstSpawnAngle(l) * bj_DEGTORAD

    call RemoveLocation(loc)
 
    call SetTableInt("[Hydra]","n",GetTableInt("[Hydra]","n")+1)
    call SetTableObject(k,"u",u)
    call SetTableObject(k,"g",g)
    call SetTableObject(k,"end",end)
    call SetTableObject(k,"targets",CreateGroup())
    call SetTableReal(k,"x",x)
    call SetTableReal(k,"y",y)
    call SetTableInt(k,"l",l)
    call SetTableInt("[Hydra]",GetAttachmentTable(t),ki)
    call SetTableInt("[Hydra]",GetAttachmentTable(end),ki)

    
    
    loop
        exitwhen a==n

        set yu=Hydra_Area(l)*Sin(grad)
        set xu=Hydra_Area(l)*Cos(grad)
        set hy=CreateUnit(GetOwningPlayer(u),Hydra_UnitId(a+1,l),x+xu,y+yu,270)
        set h=Hydra_Scale(a+1,l)
        call SetUnitScale(hy,h,h,h)
        set suf=Hydra_UnitAnimation(a+1,l)
        call UnitAddAbility(hy,'Aloc')
        set hk=GetAttachmentTable(hy)
        call SetTableInt(k,hk,a+1)
        call SetTableInt("[Hydra]",hk,ki)
        call SetUnitAnimation(hy,"birth "+suf)
        call QueueUnitAnimation(hy,"stand "+suf)
        call GroupAddUnit(g,hy)
        set a=a+1
        if (a<n) then
            call TriggerSleepAction(0)
        endif
        set grad= grad  + (2*bj_PI)/n
    endloop
    call TimerStart(t,Hydra_Cycle(l),false,function Hydra_OnCycle )
    call TimerStart(end,Hydra_Duration(l),false,function Hydra_End)
 set loc=null
 set u=null
 set g=null

endfunction

function Hydra_Actions takes nothing returns nothing
    call Hydra_DoIt(CreateTimer(),CreateTimer())
endfunction

//===========================================================================
function InitTrig_Hydra takes nothing returns nothing
    call OnAbilityEffect(Hydra_SpellId(),"Hydra_Actions")
endfunction
ShadowDragon: This new version has a fix that dissallows fireballs to hit units that have flying heights that are too different to the ball's flying height, also hydras won't try to attack them
02-21-2006, 03:47 PM#10
FireFreak
i tried it again and couldn't experience it again, even by trying in 50 times.
what did u chance (aka how to fix it)?
i saw this bug not the first time when using the hadle vars for missilemovement and casting a spell very often.
02-21-2006, 06:11 PM#11
Vexorian
Well FireFreak it seems that together we discovered a fix to the not set to null timer nightmare, congratulations