Need Help with my first Jass code (using HandleVars)

Trithilon-V2

New Member
Reaction score
20
Guyz...I read a few jass and vjass tutorials and a lot of jass scripts and i am starting to get a hang of if.
I finally learnt a little bit of jass and made my first jass spell.
As you all know Jass is almost the same as gui (apart from functions and locals) without CSCache or HandleVars.
Any trigger that has to do certain actions after some time and to be MUI at the same time needs one of the two systems above.
However i cant seem to use them properly....
can you guyz please tell me how to fix this?
JASS:
function RecordDamage takes nothing returns nothing
  local unit target=GetTriggerUnit()
  local unit caster=GetEventDamageSource()
  local real damage=GetHandleReal(caster,"damage")
  call SetUnitLifeBJ(target,(GetUnitStateSwap(UNIT_STATE_LIFE,target) + (GetEventDamage())))
  set damage=damage+GetEventDamage()
  call SetHandleReal(caster,"damage",damage) 
  call BJDebugMsg("Damage Taken from "+GetUnitName(GetEventDamageSource())+" to "+GetUnitName(GetTriggerUnit())+" = "+R2S(damage))
  set caster=null
endfunction

function DealDamage takes nothing returns nothing
    local timer t=GetExpiredTimer()
    local unit target=GetHandleUnit(t,"target")
    local unit caster=GetHandleUnit(t,"caster")
    local real damage=GetHandleReal(caster,"damage")
    call BJDebugMsg("The Caster over here is = "+(GetUnitName(caster))+" and the damage recorded is "+R2S(damage))
    call UnitDamageTargetBJ( caster, target, damage, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL )
    call SetHandleReal(caster,"damage",0)
    call SetHandleHandle(t,"caster",null)
    call SetHandleHandle(t,"target",null)
endfunction

function Trig_Test_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    local real damage=0
    local trigger damagedetect=CreateTrigger()
    local unit caster=GetTriggerUnit()
    local unit target=GetSpellTargetUnit()
    call TriggerRegisterUnitEvent(damagedetect,target,EVENT_UNIT_DAMAGED)
    call TriggerAddAction(damagedetect,function RecordDamage)
    call BJDebugMsg("The Caster is = "+GetUnitName(GetTriggerUnit())+" and the Target is "+GetUnitName(GetSpellTargetUnit()))
    call TimerStart(t, 10, false,function DealDamage)
    call SetHandleReal(caster,"damage",damage)
    call SetHandleHandle(t,"caster",caster)
    call SetHandleHandle(t,"target",target)
    call SetHandleHandle(t,"trigger1",damagedetect)
    call SetHandleHandle(t,"trigger2",GetTriggeringTrigger())
    call SetHandleHandle(damagedetect,"AttachCaster",caster)
endfunction

//===========================================================================
function InitTrig_Test_Copy takes nothing returns nothing
    local trigger trig=CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( trig, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction( trig, function Trig_Test_Actions )
endfunction

Its working...just the fact that the local trigger keeps firing even after the timer has expired.This leads to multiple instances of Event - Unit Takes Damage.
And if i try to destroy the local trigger after the timer expires...the trigger wont fire off again.
Btw i am using Newgen 5a and Warcraft TFT ver 1.20e.
 

quraji

zap
Reaction score
144
You never stop the timer, did you expect it to stop on it's own? You need something like this in your timer callback function (DealDamage):

Code:
if ConditionToStopTimer == true then
    call PauseTimer(t)*
    call DestroyTimer(t)
endif

*Always pause repeating timers before you destroy them, or it could cause a bug (you don't need to do this with non-repeating timers).

Hope that helps :)
 

quraji

zap
Reaction score
144
Ah, I see. I didn't really give it a good look before. The reason is because the trigger exists even after the timer expires and still registers the damage event, as you've noticed. The solution is to destroy the trigger. Do this by adding this line in the action:

Code:
call DestroyTrigger(GetTriggeringTrigger())

That should fix it :)
 

Trithilon-V2

New Member
Reaction score
20
Works like a charm......
But i think My spell might not be coded in the way it should have been....
By which i mean to make it mui and not overwrite the values attached to the caster if the caster casts the same spell again.
can you just go through it?
I doubt this is how you make a spell truly mui.
JASS:
//===============================================================================
// Declare and Set the Custom Values required Here //
//              Editing is Suggested               //
//==========================================================================
constant function DP_BaseDuration takes nothing returns real
return 10.0 //This is the Base Duration
endfunction

constant function DP_DurationPerLevel takes nothing returns real
return 0.0 //Duration Increment Per DP_Level of Ability 
endfunction

constant function DP_DeathPenaltyEffectString takes nothing returns string
  return "Abilities\\Spells\\Other\\HowlOfTerror\\HowlTarget.mdl" // Effect Model File
endfunction

constant function DP_EffectAttachmentPoint takes nothing returns string
  return "overhead" // Effect Attachment Point Location
endfunction

constant function DP_DeathPenaltyAbility_No1 takes nothing returns integer
return 'A000' // AbilityId of the first Ability
endfunction

constant function DP_DeathPenaltyAbility_No2 takes nothing returns integer
return 'A001' // AbilityId of the second Ability
endfunction

constant function DP_BasePercentDamage takes nothing returns real
return 0.50 // The % of Total Recorded Used as base and at starting value
endfunction

constant function DP_PercentDamagePerLevel takes nothing returns real
return 0.10 // The % value in Total Damage for increment per level
endfunction
//=========================================================================
//=== End Constants --- No Editing Suggested Ahead of this point============//
//==============================================================================
function DP_Heal takes nothing returns nothing //Heals the Unit after 0.0 seconds
local string address = GetHandleString(GetExpiredTimer(),"DP_Address")
local unit u = GetHandleUnit(GetExpiredTimer(),("DP_Unit"+address))
local real damage = GetHandleReal(GetExpiredTimer(),("DP_Damage"+address))
call SetUnitState(u,UNIT_STATE_LIFE,(GetUnitState(u,UNIT_STATE_LIFE) + (damage)))
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
set u = null
endfunction

function DP_DestroyEffectOnTime takes real r returns nothing //Destroys an effect after a given amount of time
local effect e = bj_lastCreatedEffect
call TriggerSleepAction(r) // Cannot be less than 0.25 secs
call DestroyEffect(e)
endfunction

 function DP_FilterVision takes unit u returns nothing // Makes the Floating Text Invisible to players who cant see the unit 
    if (GetLocalPlayer() == GetOwningPlayer(u)) then
       call SetTextTagVisibility(bj_lastCreatedTextTag, true)
    else
       call SetTextTagVisibility(bj_lastCreatedTextTag, false)
    endif
endfunction

function DP_GetDuration takes integer i returns real // Calculates the total duration for a spell cast
local real r = (DP_BaseDuration()+(DP_DurationPerLevel()*R2I(i)))
return r
endfunction

function DP_GetTotalPercentDamage takes integer i returns real // Calculates the total percentage based on the values declared in the constant functions
local real r = ((DP_BasePercentDamage())+(DP_PercentDamagePerLevel()*R2I(i)))
return r
endfunction

function DP_GetTotalDamage takes real r, integer i returns real //Calculates and returns the real value of the total damage
local real f=(DP_GetTotalPercentDamage(i)*R2I(i))
local real d = r*f
return d
endfunction

function DP_GetUniqueId takes string s, trigger t returns string // Returns a Unique String for each Cast
 local integer i=GetTriggerExecCount(t)
 set s = s+"x"+I2S(i) 
 return s
endfunction

function DP_GetUniqueIdI takes string s, integer i returns string // Returns a Unique String for each Cast 
 set s = s+"x"+I2S(i) 
 return s
endfunction
  
function DP_RecordDamage takes nothing returns nothing // Records the Value of the Total Damage taken from the caster and shows Floating Text.
  local trigger ct = GetTriggeringTrigger()
  local unit target=GetTriggerUnit()
  local unit caster=GetEventDamageSource()
  local integer execno = GetHandleInt(GetTriggeringTrigger(),"DP_Exec No.")
  local string address = DP_GetUniqueIdI("",execno)
  local timer healtimer = CreateTimer()
  local integer instances
  local real damage=GetHandleReal(caster,("DP_Damage"+address))
  local real totheal = 0
if GetHandleUnit(caster,("DP_Caster"+address)) == GetEventDamageSource() then
  set instances = GetHandleInt(target,"DP_Instances")
  if GetUnitState(GetTriggerUnit(),UNIT_STATE_LIFE) == GetUnitState(GetTriggerUnit(),UNIT_STATE_MAX_LIFE) then
      call SetHandleString(healtimer,("DP_Address"),address)
      call SetHandleHandle(healtimer,("DP_Unit"+address),target)
      set totheal = (I2R(instances))
      set totheal = (GetEventDamage()/totheal)
      call SetHandleReal(healtimer,("DP_Damage"+address),totheal)
      call TimerStart(healtimer, 0.0, false,function DP_Heal)
else
      set totheal = (I2R(instances))
      set totheal = (GetEventDamage()/totheal)
      call SetUnitState(GetTriggerUnit(),UNIT_STATE_LIFE,(GetUnitState(GetTriggerUnit(),UNIT_STATE_LIFE)) + (totheal))
endif

if GetEventDamage() > 0.0 then
  call CreateTextTagUnitBJ("+"+I2S(instances*(R2I(DP_GetTotalDamage(GetEventDamage(),(GetHandleInt(caster,"DP_Level"+address)))))), target, 0, 10.00, 0.00, 0.00, 100, 0 )
  call DP_FilterVision(caster)
  call SetTextTagVelocityBJ( bj_lastCreatedTextTag, 130, 80 )
  call SetTextTagPermanent( bj_lastCreatedTextTag, false )
  call SetTextTagLifespan( bj_lastCreatedTextTag, 2.5 )
  call SetTextTagFadepoint( bj_lastCreatedTextTag, 1.50 )
  set damage=damage+GetEventDamage()
  call SetHandleReal(caster,("DP_Damage"+address),damage)
endif  
    set caster=null
    set target=null
else
  set caster=null
  set target=null
  call PauseTimer(healtimer)
  call DestroyTimer(healtimer)
endif  
endfunction
 
function DP_DealDamage takes nothing returns nothing // Deals Damage after the Timer has Expired
    local timer t=GetExpiredTimer()
    local integer execno = GetHandleInt(t,"DP_Exec No.")
    local integer instances
    local string address = DP_GetUniqueIdI("",execno)
    local unit target=GetHandleUnit(t,("DP_Target"+address))
    local unit caster=GetHandleUnit(t,("DP_Caster"+address))
    local real damage=GetHandleReal(caster,("DP_Damage"+address))
    local real totaldmg = (DP_GetTotalDamage(damage,(GetHandleInt(caster,"DP_Level"+address))))
    set instances = GetHandleInt(target,"DP_Instances")
    call DisableTrigger(GetHandleTrigger(t,"DP_DamageDetectionTrigger"+address))
    set instances = instances - 1
    call SetHandleInt(target,"DP_Instances",instances)
    call UnitDamageTarget( caster, target, totaldmg,true,false,ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL,WEAPON_TYPE_WHOKNOWS )
    call CreateTextTagUnitBJ(I2S(R2I(totaldmg))+"!", target, 0, 11.00, 50, 50, 50, 0 )
    call DP_FilterVision(caster)
    call SetTextTagVelocityBJ( bj_lastCreatedTextTag, 120, 90 )
    call SetTextTagPermanent( bj_lastCreatedTextTag, false )
    call SetTextTagLifespan( bj_lastCreatedTextTag, 3 )
    call SetTextTagFadepoint( bj_lastCreatedTextTag, 1.50 )
    call SetHandleReal(caster,("DP_Damage"+address),0)
    call SetHandleHandle(caster,("DP_Caster"+address),null)
    call SetHandleHandle(caster,("DP_Target"+address),null)
    call SetHandleHandle(t,("DP_Caster"+address),null)
    call SetHandleHandle(t,("DP_Target"+address),null)
    call DestroyEffect(GetHandleFX(t,"DP_Effect"+address))
    call PauseTimer(t)
    call DestroyTimer(t)
    call DestroyTrigger(GetHandleTrigger(t,"DP_DamageDetectionTrigger"+address))
endfunction

function DP_Actions takes nothing returns nothing // Assigns and Allocates variable locations and drives the entire trigger script
    local timer t = CreateTimer()
    local real damage=0
    local trigger damagedetect=CreateTrigger()
    local unit caster=GetTriggerUnit()
    local integer instances
    local unit target=GetSpellTargetUnit()
    local integer TrigExecutionCount
    local effect eff = AddSpecialEffectTarget(DP_DeathPenaltyEffectString(),target,DP_EffectAttachmentPoint())
    local integer level = GetUnitAbilityLevel(GetTriggerUnit(),GetSpellAbilityId())
if (GetTriggerExecCount(GetTriggeringTrigger())) == 1 then
    call SetHandleInt(GetTriggeringTrigger(),"DP_Executions",1) // Initializes the trigger Execution count Variable
endif    
    call TriggerRegisterUnitEvent(damagedetect,target,EVENT_UNIT_DAMAGED)
    call TriggerAddAction(damagedetect,function DP_RecordDamage)
    call TimerStart(t, DP_GetDuration(level), false,function DP_DealDamage)
    call SetHandleReal(caster,DP_GetUniqueId("DP_Damage",GetTriggeringTrigger()),damage) //Store DP_Damage Value in DP_Caster
    call SetHandleInt(caster,DP_GetUniqueId("DP_Level",GetTriggeringTrigger()),level)
    call SetHandleHandle(t,"DP_MainTrigger",GetTriggeringTrigger()) // Store Main Trigger in Timer
    call SetHandleHandle(t,DP_GetUniqueId("DP_Caster",GetTriggeringTrigger()),caster)//
    call SetHandleHandle(t,DP_GetUniqueId("DP_Effect",GetTriggeringTrigger()),eff)
    call SetHandleHandle(t,DP_GetUniqueId("DP_Target",GetTriggeringTrigger()),target)
    call SetHandleHandle(caster,DP_GetUniqueId("DP_Caster",GetTriggeringTrigger()),caster)
    call SetHandleHandle(caster,DP_GetUniqueId("DP_Target",GetTriggeringTrigger()),target)
    call SetHandleHandle(t,DP_GetUniqueId("DP_DamageDetectionTrigger",GetTriggeringTrigger()),damagedetect)
    call SetHandleInt(damagedetect,"DP_Exec no.",GetTriggerExecCount(GetTriggeringTrigger()))
    set instances = GetHandleInt(target,"DP_Instances")
    set instances = instances + 1
    call SetHandleInt(target,"DP_Instances",instances)
    call SetHandleInt(t,"DP_Exec no.",GetTriggerExecCount(GetTriggeringTrigger()))
endfunction

function DP_Conditions takes nothing returns boolean // Checks if the Ability being cast is = the Ability declared in the constant functions
  if GetSpellAbilityId() == DP_DeathPenaltyAbility_No1() then
    return true
    endif
    if GetSpellAbilityId() == DP_DeathPenaltyAbility_No2() then
    return true
    endif
  return false
endfunction

//===========================================================================
function InitTrig_Death_Penalty takes nothing returns nothing
    local trigger DP_Main=CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( DP_Main, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(DP_Main, Condition(function DP_Conditions))
    call TriggerAddAction( DP_Main, function DP_Actions )
endfunction


P.S :- Releasing the spell after this check
 

quraji

zap
Reaction score
144
I can't do an in-depth look at the moment, but as long as you're only attaching to the timer you should be fine.

I noticed also this function:

JASS:
function DP_DestroyEffectOnTime takes real r returns nothing //Destroys an effect after a given amount of time
local effect e = bj_lastCreatedEffect
call TriggerSleepAction(r) // Cannot be less than 0.25 secs
call DestroyEffect(e)
endfunction


Be aware this will cause a wait in any function that calls this. You should use a timer and a callback to destroy effects after a time.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top