• 🏆 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] Problems/plasma field

Status
Not open for further replies.
Level 6
Joined
Apr 16, 2011
Messages
158
hi,
I'm having some problems with my plasma field:
11 local hashtable gc = udg_HashCache
32 undeclared function DisBetweenPts
32 Cannot convert null to real
52 undeclared function KillTimer
69 undeclared variable udg_HashCache

What are the possible problems ?

JASS:
function Trig_Plasma_Field_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A09H'
endfunction

function Trig_Plasma_Field_Targ takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) > 0.405 and not (IsUnitType(GetFilterUnit(),UNIT_TYPE_MAGIC_IMMUNE) and IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL)) and GetUnitAbilityLevel(GetFilterUnit(),'Aloc') == 0
endfunction

function Trig_Plasma_Field_Tick takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local hashtable gc = udg_HashCache
    local integer s = GetHandleId(t)
    local unit u = LoadUnitHandle(gc,s,1)
    local group g = CreateGroup()
    local group hit = LoadGroupHandle(gc,s,2)
    local boolexpr b = LoadBooleanExprHandle(gc,s,3)
    local real c = LoadReal(gc,s,4)
    local integer bc = LoadInteger(gc,s,5)
    local unit p
    local real pd
    if bc == 0 then
        set c = c+32
      else
          set c = c-32
    endif
    call SaveReal(gc,s,4,c)
    call GroupEnumUnitsInRange(g,GetUnitX(u),GetUnitY(u),c,b)
    call GroupRemoveUnit(g,u)
    loop
        exitwhen CountUnitsInGroup(g) == 0
        set p = FirstOfGroup(g)
        set pd = DistBetweenPts(GetUnitX(u),GetUnitY(u),GetUnitX(p),GetUnitY(p))
        if (IsUnitEnemy(p,GetOwningPlayer(u)) and not IsUnitInGroup(p,hit)) and (pd < c+100 and pd > c-100) then
            call GroupAddUnit(hit,p)
            call UnitDamageTarget(u,p,(c/704)*LoadReal(gc,s,10),false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS)
            call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\ChimaeraLightningMissile\\ChimaeraLightningMissile.mdl",p,"origin"))
        endif
        call GroupRemoveUnit(g,p)
        set p = null
    endloop

    if bc == 0 then
        if c > 700 then
            call SaveInteger(gc,s,5,1)
            call GroupClear(hit)
        endif
      else
          if c <= 32 then
              call DestroyEffect(LoadEffectHandle(gc,s,17))
              call DestroyGroup(hit)
              call DestroyBoolExpr(b)
              call KillTimer(t)
              call FlushChildHashtable(gc,s)
          endif
    endif
    call DestroyGroup(g)
    set t = null
    set gc = null
    set u = null
    set g = null
    set hit = null
    set b = null
    set p = null
endfunction

function Trig_Plasma_Field takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local timer t = CreateTimer()
    local hashtable gc = udg_HashCache
    local integer s = GetHandleId(t)
    local group hit = CreateGroup()
    local boolexpr b = Condition(function Trig_Plasma_Field_Targ)
    call DestroyEffect(AddSpecialEffectTarget("Effects\\PlasmaField.mdx",u,"origin"))
    call SaveUnitHandle(gc,s,1,u)
    call SaveGroupHandle(gc,s,2,hit)
    call SaveBooleanExprHandle(gc,s,3,b)
    call SaveEffectHandle(gc,s,17,AddSpecialEffectTarget("Effects\\LightningBall.mdx",u,"origin"))
    call SaveReal(gc,s,10,35+35*I2R(GetUnitAbilityLevel(u,'A09H')))
    call TimerStart(t,.04,true,function Trig_Plasma_Field_Tick)
    set u = null
    set t = null
    set gc = null
    set b = null
    set hit = null
endfunction

function InitTrig_Plasma_Field takes nothing returns nothing
    set gg_trg_Plasma_Field = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Plasma_Field, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Plasma_Field, Condition( function Trig_Plasma_Field_Conditions ) )
    call TriggerAddAction( gg_trg_Plasma_Field, function Trig_Plasma_Field )
endfunction

thanks*
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,199
DistBetweenPts is a function that is not declared at that point in your script.

There are 3 possible causes.
1. You made an error in the name you are trying to call (like a typo). To fix, check the function you are trying to call and make sure it is spelt correctly.
2. The function is declared below where you are trying to call from and as such is not defined at this point in the script. To fix, move the function you are trying to call above the function that is doing the calling in the map script.
3. No such function exists in your script. To fix you will need to declare such a function and its accompanying logic above the calling function.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,199
JASS:
    loop
        set p = FirstOfGroup(g)
        exitwhen p == null
        set pd = DistBetweenPts(GetUnitX(u),GetUnitY(u),GetUnitX(p),GetUnitY(p))
        if (IsUnitEnemy(p,GetOwningPlayer(u)) and not IsUnitInGroup(p,hit)) and (pd < c+100 and pd > c-100) then
            call GroupAddUnit(hit,p)
            call UnitDamageTarget(u,p,(c/704)*LoadReal(gc,s,10),false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS)
            call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\ChimaeraLightningMissile\\ChimaeraLightningMissile.mdl",p,"origin"))
        endif
        call GroupRemoveUnit(g,p)
    endloop
This method of looping is much faster than the one you used. FirstOfGroup(g) returns null when the group is empty.
 
Level 6
Joined
Apr 16, 2011
Messages
158
well
*I replaced the loop but the problems still DistBetweenPts,


to declare HashCache(global variable) can use:
JASS:
function HashCache takes string s returns nothing
    set udg_HashCache = InitHashtable()
endfunction
?

JASS:
function Trig_Plasma_Field_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A09H'
endfunction

function Trig_Plasma_Field_Targ takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) > 0.405 and not (IsUnitType(GetFilterUnit(),UNIT_TYPE_MAGIC_IMMUNE) and IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL)) and GetUnitAbilityLevel(GetFilterUnit(),'Aloc') == 0
endfunction

function Trig_Plasma_Field_Tick takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local hashtable gc = udg_HashCache
    local integer s = GetHandleId(t)
    local unit u = LoadUnitHandle(gc,s,1)
    local group g = CreateGroup()
    local group hit = LoadGroupHandle(gc,s,2)
    local boolexpr b = LoadBooleanExprHandle(gc,s,3)
    local real c = LoadReal(gc,s,4)
    local integer bc = LoadInteger(gc,s,5)
    local unit p
    local real pd
    if bc == 0 then
        set c = c+32
      else
          set c = c-32
    endif
    call SaveReal(gc,s,4,c)
    call GroupEnumUnitsInRange(g,GetUnitX(u),GetUnitY(u),c,b)
    call GroupRemoveUnit(g,u)
    loop
    set p = FirstOfGroup(g)
    exitwhen p == null
    set pd = DistBetweenPts(GetUnitX(u),GetUnitY(u),GetUnitX(p),GetUnitY(p))
    if (IsUnitEnemy(p,GetOwningPlayer(u)) and not IsUnitInGroup(p,hit)) and (pd < c+100 and pd > c-100) then
        call GroupAddUnit(hit,p)
        call UnitDamageTarget(u,p,(c/704)*LoadReal(gc,s,10),false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS)
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\ChimaeraLightningMissile\\ChimaeraLightningMissile.mdl",p,"origin"))
    endif
    call GroupRemoveUnit(g,p)
endloop

    if bc == 0 then
        if c > 700 then
            call SaveInteger(gc,s,5,1)
            call GroupClear(hit)
        endif
      else
          if c <= 32 then
              call DestroyEffect(LoadEffectHandle(gc,s,17))
              call DestroyGroup(hit)
              call DestroyBoolExpr(b)
              call DestroyTimer(t)
              call FlushChildHashtable(gc,s)
          endif
    endif
    call DestroyGroup(g)
    set t = null
    set gc = null
    set u = null
    set g = null
    set hit = null
    set b = null
    set p = null
endfunction

function Trig_Plasma_Field takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local timer t = CreateTimer()
    local hashtable gc = udg_HashCache
    local integer s = GetHandleId(t)
    local group hit = CreateGroup()
    local boolexpr b = Condition(function Trig_Plasma_Field_Targ)
    call DestroyEffect(AddSpecialEffectTarget("Effects\\PlasmaField.mdx",u,"origin"))
    call SaveUnitHandle(gc,s,1,u)
    call SaveGroupHandle(gc,s,2,hit)
    call SaveBooleanExprHandle(gc,s,3,b)
    call SaveEffectHandle(gc,s,17,AddSpecialEffectTarget("Effects\\LightningBall.mdx",u,"origin"))
    call SaveReal(gc,s,10,35+35*I2R(GetUnitAbilityLevel(u,'A09H')))
    call TimerStart(t,.04,true,function Trig_Plasma_Field_Tick)
    set u = null
    set t = null
    set gc = null
    set b = null
    set hit = null
endfunction

function InitTrig_Plasma_Field takes nothing returns nothing
    set gg_trg_Plasma_Field = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Plasma_Field, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Plasma_Field, Condition( function Trig_Plasma_Field_Conditions ) )
    call TriggerAddAction( gg_trg_Plasma_Field, function Trig_Plasma_Field )
endfunction

"DistBetweenPts is a function that is not declared at that point in your script.
how to declare?
"
 
Last edited:
Level 6
Joined
Apr 16, 2011
Messages
158
I know I'm reviving, I left it aside but I decided to try one more time.
****I have put everything right enemy units do not take damage*****
JASS:
function KillTimer takes timer t returns nothing
    call PauseTimer(t)
    call DestroyTimer(t)
endfunction

function KillTrigger takes trigger t returns nothing
    call DisableTrigger(t)
    call DestroyTrigger(t)
endfunction

function ClearUnitTriggers takes unit u returns nothing
    local hashtable gc = udg_HashCache
    local integer s = GetHandleId(u)
    local integer i = LoadInteger(gc,s,StringHash("triggeri"))
    local integer l = 1
    local trigger array t
    if i >= 1 then
    loop
    exitwhen l > i
    set t[l] = LoadTriggerHandle(gc,s,StringHash("trigger"+I2S(l)))
    call FlushChildHashtable(gc,GetHandleId(t[l]))
    call TriggerRemoveAction(t[l],LoadTriggerActionHandle(gc,s,StringHash("triggeraction"+I2S(l))))
    call KillTrigger(t[l])
    set l = l + 1
    set t[l] = null
    endloop
    endif
    set gc = null
endfunction

function fif_AddSpecialEffectTimed takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local hashtable gc = udg_HashCache
    local integer s = GetHandleId(t)
    call DestroyEffect(LoadEffectHandle(gc,s,1))
    call KillTimer(t)
    call FlushChildHashtable(gc,s)
    set t = null
    set gc = null
endfunction

function AddSpecialEffectTimed takes string SFX, real x, real y, real duration returns nothing
    local hashtable gc = udg_HashCache
    local timer t = CreateTimer()
    local integer s = GetHandleId(t)
    local effect e = AddSpecialEffect(SFX,x,y)
    call TimerStart(t,duration,false,function fif_AddSpecialEffectTimed)
    call SaveEffectHandle(gc,s,1,e)
    set gc = null
    set t = null
    set e = null
endfunction

function fif_RemoveUnitEx takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local hashtable gc = udg_HashCache
    local unit u = LoadUnitHandle(gc,GetHandleId(t),1)
    call ClearUnitTriggers(u)
    call FlushChildHashtable(gc,GetHandleId(u))
    call RemoveUnit(u)
    call KillTimer(t)
    call FlushChildHashtable(gc,GetHandleId(t))
    set u = null
    set t = null
    set gc = null
endfunction

function RemoveUnitEx takes unit u returns nothing
    local timer t = CreateTimer()
    local hashtable gc = udg_HashCache
    call SaveUnitHandle(gc,GetHandleId(t),1,u)
    call KillUnit(u)
    call TimerStart(t,.01,false,function fif_RemoveUnitEx)
    set t = null
    set gc = null
endfunction

function DistBetweenPts takes real x, real y, real x2, real y2 returns real
    return SquareRoot((x-x2)*(x-x2)+(y-y2)*(y-y2))
endfunction
And

Plasma Field

JASS:
function Trig_Plasma_Field_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction

function Trig_Plasma_Field_Targ takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) > 0.405 and not (IsUnitType(GetFilterUnit(),UNIT_TYPE_MAGIC_IMMUNE) and IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL)) and GetUnitAbilityLevel(GetFilterUnit(),'Aloc') == 0
endfunction

function Trig_Plasma_Field_Tick takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local hashtable gc = udg_HashCache
    local integer s = GetHandleId(t)
    local unit u = LoadUnitHandle(gc,s,1)
    local group g = CreateGroup()
    local group hit = LoadGroupHandle(gc,s,2)
    local boolexpr b = LoadBooleanExprHandle(gc,s,3)
    local real c = LoadReal(gc,s,4)
    local integer bc = LoadInteger(gc,s,5)
    local unit p
    local real pd
    if bc == 0 then
    set c = c+32
    else
    set c = c-32
    endif
    call SaveReal(gc,s,4,c)
    call GroupEnumUnitsInRange(g,GetUnitX(u),GetUnitY(u),c,b)
    call GroupRemoveUnit(g,u)
    loop
    exitwhen CountUnitsInGroup(g) == 0
    set p = FirstOfGroup(g)
    set pd = DistBetweenPts(GetUnitX(u),GetUnitY(u),GetUnitX(p),GetUnitY(p))
    if (IsUnitEnemy(p,GetOwningPlayer(u)) and not IsUnitInGroup(p,hit)) and (pd < c+100 and pd > c-100) then
    call GroupAddUnit(hit,p)
    call UnitDamageTarget(u,p,(c/704)*LoadReal(gc,s,10),false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS)
    call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\ChimaeraLightningMissile\\ChimaeraLightningMissile.mdl",p,"origin"))
    endif
    call GroupRemoveUnit(g,p)
    set p = null
    endloop
    if bc == 0 then
    if c > 700 then
    call SaveInteger(gc,s,5,1)
    call GroupClear(hit)
    endif
    else
    if c <= 32 then
    call DestroyEffect(LoadEffectHandle(gc,s,17))
    call DestroyGroup(hit)
    call DestroyBoolExpr(b)
    call KillTimer(t)
    call FlushChildHashtable(gc,s)
    endif
    endif
    call DestroyGroup(g)
    set t = null
    set gc = null
    set u = null
    set g = null
    set hit = null
    set b = null
    set p = null
endfunction

function Trig_Plasma_Field takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local timer t = CreateTimer()
    local hashtable gc = udg_HashCache
    local integer s = GetHandleId(t)
    local group hit = CreateGroup()
    local boolexpr b = Condition(function Trig_Plasma_Field_Targ)
    call DestroyEffect(AddSpecialEffectTarget("PlasmaField.mdx",u,"origin"))
    call SaveUnitHandle(gc,s,1,u)
    call SaveGroupHandle(gc,s,2,hit)
    call SaveBooleanExprHandle(gc,s,3,b)
    call SaveReal(gc,s,10,35+35*I2R(GetUnitAbilityLevel(u,'A09H')))
    call TimerStart(t,.04,true,function Trig_Plasma_Field_Tick)
    set u = null
    set t = null
    set gc = null
    set b = null
    set hit = null
endfunction

function InitTrig_Plasma_Field takes nothing returns nothing
    set gg_trg_Plasma_Field = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Plasma_Field, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Plasma_Field, Condition( function Trig_Plasma_Field_Conditions ) )
    call TriggerAddAction( gg_trg_Plasma_Field, function Trig_Plasma_Field )
endfunction
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,199
exitwhen CountUnitsInGroup(g) == 0
CountUnitsInGroup(g) is an O(n) opperation based on group size. Worse is that it is a BJ and not a native so is insanly slow. Instead count the group once and store that count in an integer. It is far faster to decriment an integer than to use CountUnitsInGroup(g).

loop
exitwhen CountUnitsInGroup(g) == 0
set p = FirstOfGroup(g)
set pd = DistBetweenPts(GetUnitX(u),GetUnitY(u),GetUnitX(p),GetUnitY(p))
if (IsUnitEnemy(p,GetOwningPlayer(u)) and not IsUnitInGroup(p,hit)) and (pd < c+100 and pd > c-100) then
call GroupAddUnit(hit,p)
call UnitDamageTarget(u,p,(c/704)*LoadReal(gc,s,10),false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\ChimaeraLightningMissile\\ChimaeraLightningMissile.mdl",p,"origin"))
endif
call GroupRemoveUnit(g,p)
set p = null
endloop

should be...

loop
set p = FirstOfGroup(g)
exitwhen p == null
set pd = DistBetweenPts(GetUnitX(u),GetUnitY(u),GetUnitX(p),GetUnitY(p))
if (IsUnitEnemy(p,GetOwningPlayer(u)) and not IsUnitInGroup(p,hit)) and (pd < c+100 and pd > c-100) then
call GroupAddUnit(hit,p)
call UnitDamageTarget(u,p,(c/704)*LoadReal(gc,s,10),false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\ChimaeraLightningMissile\\ChimaeraLightningMissile.mdl",p,"origin"))
endif
call GroupRemoveUnit(g,p)
endloop
 
Level 6
Joined
Apr 16, 2011
Messages
158
thank Dr Super Good, but even using another loop, the magic still not hurt, I'll leave here a map test, maybe I'm doing something wrong if someone is interested to look I am grateful;
:ogre_icwydt:
 

Attachments

  • Plasma field.w3x
    34.7 KB · Views: 85
Level 7
Joined
Jul 3, 2011
Messages
251
You really should get JassCraft if you haven't already
JASS:
function DistanceBetweenPoints takes location locA, location locB returns real
    local real dx = GetLocationX(locB) - GetLocationX(locA)
    local real dy = GetLocationY(locB) - GetLocationY(locA)
    return SquareRoot(dx * dx + dy * dy)
endfunction
which, asuming you have the x and y for the first and second loc, you would then
JASS:
set x3 = x2 - x
set y3 = y2 - y
set dist = SquareRoot(x3 * x3 + y3 * y3)
and there you have the distance between 2 locs using reals.
 
Level 7
Joined
Jul 3, 2011
Messages
251
You dont need to check the distance for a spell like this, when the lightning expands, just increase a real (the damage) and when you damage a unit, damage it for a real. Likewise for contractions but decrease the real.
 
Status
Not open for further replies.
Top