• 🏆 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] Variable not being passed correctly?

Status
Not open for further replies.
Level 9
Joined
Aug 27, 2004
Messages
471
Im working on another spell, and this is the first time i have come into this problem. Most of my handles pass fine with Kattanas handler system. But two of my handles seem to have broken, and are always passing "0". I made some text displays to make sure this was the problem, and it is. I just cant fix it, i have tried changing it to pass an integer and convert it into a real (didint work), setting it after locals were declared rather than during, and a whole ton of other stuff.

But it just wont work, and i cant get why! Every other handle passes fine, the real has a value > 0 when its passed... Why doesnt this work?

Alright, this isisint the whole script, cause it doesnt fit :p. So try to ingore the missing parts >.>

Calls the problematic function via timer:
JASS:
function SkyPortion takes real painful, integer spd, real range, integer maxama, location targpos returns nothing
local effect array Effects
local real array XS
local real array YS
local real array FinWait
local location array HitPoint
local timer array TillFor
local real RanX = 0
local real RanY = 0
local real MaxWait = 1.62
local real MinWait = 1.02
local real TargposX = GetLocationX(targpos)
local real TargposY = GetLocationY(targpos)
local real passX = 0
local real passY = 0
local integer CountA = 0
local integer CountB = 0
local integer CountC = 0
call SetHandleReal(GetTriggeringTrigger(), "painfulness", painful)
 loop
  exitwhen(CountA >= maxama)
  set FinWait[CountA] = (GetRandomReal(MinWait, MaxWait))
  set RanX = (GetRandomReal((range / 10), (range)))
  set RanY = (GetRandomReal((range / 10), (range)))
  set HitPoint[CountA] = Location((TargposX + RanX), (TargposY + RanY))
  set Effects[CountA] = AddSpecialEffectLoc("Abilities\\Spells\\Human\\Blizzard\\BlizzardTarget.mdl", HitPoint[CountA])  
  
  set TillFor[CountA] = CreateTimer()
  set passX = GetLocationX(HitPoint[CountA])
  set passY = GetLocationY(HitPoint[CountA])
   
  call SetHandleReal(GetTriggeringTrigger(),"PHX", passX)
  call SetHandleReal(GetTriggeringTrigger(),"PHY", passY)

  call TimerStart(TillFor[CountA], 0.80, false, function SkyDamagePortion)
  call TriggerSleepAction(FinWait[CountA])
  set CountA = (CountA + 1)
 endloop
endfunction

The problematic function:
JASS:
function SkyDamagePortion takes nothing returns nothing
local timer array FrostTimer
local unit array FOGCalleresto
local integer AmQ = GetHandleInt(GetTriggeringTrigger(), "CurrCount")
local real PointHitX = 0
local real PointHitY = 0
local real Range = GetHandleReal(GetTriggeringTrigger(), "Range")
local real Duration = GetHandleReal(GetTriggeringTrigger(), "Sky_Shard_Frost_Duration")
local real Damage = GetHandleReal(GetTriggeringTrigger(), "Sky_Shard_Damage")
local integer Groupies = 0
local integer CountA = 0
local group Radialian
local location FinLocation
local unit FOG
local unit caster = GetHandleUnit(GetTriggeringTrigger(), "casterunit")
local player owner = GetOwningPlayer(GetHandleUnit(GetTriggeringTrigger(), "casterunit"))

set PointHitX = GetHandleReal(GetTriggeringTrigger(), "PHX")
set PointHitY = GetHandleReal(GetTriggeringTrigger(), "PHY")

set FinLocation = Location(PointHitX, PointHitY)
call DisplayTimedTextToForce( GetPlayersAll(), 30, (R2S(PointHitX) + "  " + R2S(PointHitY)))

set Radialian = GetUnitsInRangeOfLocAll(Range, FinLocation)

set Groupies = CountUnitsInGroup(Radialian)
call DisplayTimedTextToForce( GetPlayersAll(), 30, I2S(Groupies))

loop
 exitwhen(Groupies <= 0)
 set Groupies = CountUnitsInGroup(Radialian)

 set FOG = FirstOfGroup(Radialian)
   if(IsUnitAliveBJ(FOG) == true) then
     if(IsUnitEnemy(FOG, owner) == true) then
     call SetUnitLifeBJ(FOG, (GetUnitStateSwap(UNIT_STATE_LIFE, FOG) - Damage))
     call SetUnitMoveSpeed(FOG, (GetUnitDefaultMoveSpeed(FOG)) - 100)
     set FrostTimer[CountA] = CreateTimer()
     set FOGCalleresto[CountA] = FOG
     call SetHandleHandle(GetTriggeringTrigger(), "FogCurrent", FOG)
     call TimerStart(FrostTimer[CountA], Duration, false, function SkyFinishPortion)
     call GroupRemoveUnit(Radialian, FOG)
     endif
   endif
endloop
endfunction

I have tried for four hours to fix this bug, but i just cant seem to get the variable to the other side... Everything else works though... :/.
 
Level 3
Joined
Mar 27, 2004
Messages
70
The problem is that you are using the Trigger to store the variables on, where you should use the timer.
In the SkyPortion function, you should set the variable on the timer rather than the trigger.
And in SkyDamagePortion you should use GetExpiredTimer() instead of GetTriggeringTrigger().

The reason for this is that when a timer expires, it does not remember what trigger started the timer, and therefore GetTriggeringTrigger could be anything (probably null). You need a unique reference handle on both sides, and in this case it is the timer.
 
Level 9
Joined
Aug 27, 2004
Messages
471
o_O

This just keeps getting more complicated!

But let me see if i get this:

When a timer expires it sets its values to null like a good little timer, but by doing so, it forgets what trigger called it, therfore the calling trigger is null. So, I made a call that was

call (null
and
call (GetTriggeringTrigger()

yes? Or something like that. So what you're saying is to turn it from GetTriggeringTrigger to...

call (Timer var
and
call (GetExpiredTimer()

yes? That makes perfect sence in a very strange way.
So i called the timer, and set the game cachce to remember the timer, but the function is called when the timer expires, so if i wanted the same timer, i have to set the call to the timer that just expired?

Ok, i wont make that mistake anymore. So, i always set the handler variable, to whatever is going to be making the call, and then, whatever made the call yes?

But then, doesnt that mean if I use GetExpiredTimer(), but a timer just expired, i will get a different timer? Hmmm quite a conundrum... Well, its always possible to store the timer in the cache... but how to get it out? Hmmm.. tricky... Ill just hope for now that I dont get the wrong timer :).

Thx again kat :). (Excellent system btw)


-Edit: Hahahaha, flawless! Works better than ever, just a few minor ajustments and it'll work like a charm :). Thanks again :D.
 
Level 3
Joined
Mar 27, 2004
Messages
70
Glad to hear that it works.

It's not as complicated as you think it is. Remember: A timer is not destroyed when it expires. It still exists as an object, even if you set periodic to false (non-repeating).
There is still a lot of work for you if you want it perfect, because there are many memory leaks in it.
You need to destroy/remove locations, groups and timers after you are done with them, or they will pile up in memory and cause lag.
 
Status
Not open for further replies.
Top