Vexorian's Caster System/ Spell Template help

lllidan

New Member
Reaction score
22
Okay I'm very unexperienced when to comes to JASS. I even have problems when I'm using a JASS spell template that nearly does everything for you. SO that's why I'm here.

I was using Vexorian's Caster System (13.4) and his Alternative Spell Templates System (4.0). I made an ability based off Storm Bolt that is supposed to stun and reduce armor against the target unit multiple times (using the Illidan (evil) missile). I set the damage for all levels (it's a 3 level spell) to 0 seeing as the system does the damage in the code.

I based the spell on the SpellCast template as follows: (bold part is my spell)

Code:
//===================================================================================================
// SpellCast Template Setup
// 
function SpellCastTemplateSetup takes nothing returns nothing
 local integer D //An integer variable we use later to save the Damage Options so we give them to the templates
 local integer s //An integer variable we use later to save the rawcodes of spells to save some time

 //===================================================================================================
 // Template Info:
 //
 // Template Name Id = "SpellCastTemplate"
 //
 // This spell was going to be called UniversalTemplate, This template just extracts all the juice
 // from the caster system, make whatever you need, Channeling Spells, Channeling Spells like 
 // flamestrike, Use missiles, make it do the job as much times as you want, for the effect it can
 // cast up to N spells and do damage and damage per second.
 // 
 //
 // integer "Times"              Is the number of times that the casting / damage wave will happen on the
 //                              target point. Use 0 if you want them to be infinite (so it stops only when
 //                              the spell is channeling and the unit stops casting)
 //
 // real    "Timer"              The period of time between each new casting / damage wave.
 //
 // integer "instantStart"       Is 1 when you want it to instantly start the spells, instead of waiting
 //                              for the timer to expire, this is ignore when "ChannelType" is 2
 //
 // integer "ChannelType"        Is 0 if you want the spell to be instant and ignore any channeling stuff.
 //                              Is 1 if you want the hero to be channeling the spell else the template stops
 //                              Is 2 if you want a spell like flamestrike that has to be succesfully channeled
 //                              before starting.
 //
 // integer "maxtargets"         Is the maximum number of targets affected by damage and targeteable spells
 // real    "area"               Is the area of effect for damage and targeteable spells.
 //
 // integer "DamageOptions"      Caster System Damage Options in saveable form, used to determine which units
 //                              can be affected by damage and targeteable spells, if the damage factor is 0
 //                              The unit is not affected by the target spells nor damage, otherwise the value is
 //                              only important for damage.
 //
 // integer "spellN"             is the number of spells to cast
 // integer "spell1type"         Is the type of the spell to cast #1
 //                              (1 if it is a point spell to cast at the target point,
 //                              0 if it is a unit targeteable spell)
 // integer "spell1id"           Is the rawcode of the spell to cast #1
 // integer "spell1OrderId"      Is the orderid of the spell to cast #1
 // integer "spell1RecDelay"     Is the recycle delay for the caster that casts spell #1 (0 if it is instant)
 // integer "spell1FromSource"   Is 1 when you want the caster to be located at the source point
 // integer "spell1CasterHeight" Is the height of the caster that casts spell #1
 //
 // (The same options work for every spell to cast, just change the number, so when spellN is 2 you can also
 // use spell2id , spell2OrderId , spell2RecDelay, spell2FromSource, spell2CasterHeight.
 //
 // real    "dmg"                Is the damage done to units  (0 if you don't want any, negative for healing)
 // real    "dmgps"              Is the periodic damage done to units  (0 if you don't want any, negative for healing)
 // real    "dmgpsPeriod"        Is the period of time for the periodic damage
 // real    "dmgpsDur"           Is the duration for the periodic damage.
 //
 // integer "SourceIsUnit"       Is 1 when you want the source point to be the position of the unit, otherwise
 //                              it is the target point (The source point is considered when SpellXFromSource is 1
 //
 // integer "UseMissile"         Is 1 when you want to use a missile (spell must be targeteable for this option)
 //                              Wil automatically set "SourceIsUnit" to 1
 // real    "MissileArc"         Is the arc of the missile when "UseMissile" is 1
 // real    "MissileSpeed"       Is the speed of the missile when "UseMissile" is 1
 // real    "MissileScale"       Is the scale of the missile
 // integer "MissileColor"       Contains the Color of the missile in 0xAARRGGBB form
 //                              ( RR is red, GG is green, BB is blue, and AA is alpha
 //                              (all in hex representation from 00 to FF)

 //===================================================================================================
 // SpellCast template Defaults:
 //
    call SetTemplateDefaultInt( "SpellCastTemplate","Times"     ,1)            //Default number of times=1
    call SetTemplateDefaultReal("SpellCastTemplate","Timer"     ,1)            //Default timer is 1
    call SetTemplateDefaultInt( "SpellCastTemplate","spellN"    ,1)            //Default number of spells is 1
    call SetTemplateDefaultInt( "SpellCastTemplate","maxtargets",100)          //Default max targets is 100
    call SetTemplateDefaultReal("SpellCastTemplate","MissileScale",1)          //Default missile scale is 1
    call SetTemplateDefaultReal("SpellCastTemplate","MissileSpeed",800)        //Default missile speed is 800
    call SetTemplateDefaultReal("SpellCastTemplate","MissileLHeight",60)       //Default missile launch height is 60
    call SetTemplateDefaultReal("SpellCastTemplate","MissileIHeight",60)       //Default missile impact height is 60
    call SetTemplateDefaultReal("SpellCastTemplate","MissileArc"  ,0.15)       //Default missile arc is 0.15
    call SetTemplateDefaultInt( "SpellCastTemplate","MissileColor",0xFFFFFFFF) //Default missile color is 255·255·255·255



//===================================================================================================
 [B]// Demon Fury ('A02T')
 //
 set s=SetSpellTemplate('A02T',"SpellCastTemplate")

    call SetAbilityDataInt( s,"ChannelType",0,0)     //The channeling type is 0, so it is a single target spell.
    call SetAbilityDataReal(s,"dmg"       ,1,30)     //Level 1: 30 damage
    call SetAbilityDataReal(s,"dmg"       ,2,40)     //Level 2: 40 damage
    call SetAbilityDataReal(s,"dmg"       ,3,50)     //Level 3: 50 damage    
    call SetAbilityDataInt( s,"Times"      ,1,2)     //Level 1: repeat twice
    call SetAbilityDataInt( s,"Times"      ,2,3)     //Level 2: repeat 3 times
    call SetAbilityDataInt( s,"Times"      ,3,4)     //Level 3: repeat 4 times
    call SetAbilityDataInt( s,"UseMissile"  ,0,1)    //Use Missile
    call SetTemplateDefaultReal("SpellCastTemplate","MissileScale",2)
    call SetAbilityDataInt( s,"instantStart",0,1)    //do it immediatelly

    call SetAbilityDataInt( s,"spellN",0,1) //Number of spells  to cast is 1 for all levels

    call SetAbilityDataInt( s,"spell1id"      ,0,'A02S')                    //Edited Frost Armor, gives a negative armor bonus.
    call SetAbilityDataInt( s,"spell1OrderId" ,0,OrderId("frostarmor"))     //Order is frostarmor
    call SetAbilityDataReal(s,"spell1RecDelay",0,1) //Recycle Delay is 1 second
    call SetAbilityDataInt( s,"spell1type"    ,0,0) //The spell to cast is unit targeteable[/B]


 //===================================================================================================
 // Ability Preloading
 //
 // Next is unrelated to the templates system, just avoids the first time cast lag, here you 
 // should preload any ability used as auxiliar ability for the template, just to avoid first
 // time cast lag.
 //
    call PreloadAbility('A02T') //Demon Fury
endfunction

//===================================================================================================
// SpellCast template code:
//
function SpellCast_Missile takes player ow, integer s, integer l, real x1, real y1, real x2, real y2 returns nothing
 local integer rgb=GetAbilityDataInt(s,l,"MissileColor")
 local integer Y=rgb+IntegerTertiaryOp(rgb<0,0x80000000,0)
 local integer Z
 local integer r
 local integer g
 local integer b
 local real sc=GetAbilityDataReal(s,l,"MissileScale")
    set Z=Y/0x100
    set b=Y-(Z*0x100)
    set Y=Z/0x100
    set g=Z-(Y*0x100)
    set Z=Y/0x100
    set r=Y-(Z*0x100)
    if (rgb<0) then
        set Z=Z+128
    endif
    call ProjectileLaunchEx(ow,GetAbilityEffectById(s,EFFECT_TYPE_MISSILE,0),sc,r,g,b,Z,GetAbilityDataReal(s,l,"MissileSpeed"),GetAbilityDataReal(s,l,"MissileArc"),x1,y1,GetAbilityDataReal(s,l,"MissileLHeight"),x2,y2,GetAbilityDataReal(s,l,"MissileIHeight"))
endfunction

function SpellCast_Do takes unit u, integer s, integer l, real x, real y, real px, real py returns nothing
 local integer n=GetAbilityDataInt(s,l,"spellN")
 local integer array ts   //targetted spell id
 local real array tsr     //targeted spell recycle delay
 local boolean array tsfp //targeted spell cast from point
 local integer array tso  //targeted spell orderid
 local real array tsz     //targeted spell caster height
 local integer tn=0
 local integer i=1
 local integer t
 local string k
 local real dmg=GetAbilityDataReal(s,l,"dmg")
 local real dmgps=GetAbilityDataReal(s,l,"dmgps")
 local real period
 local real dur
 local real cx
 local real cy
 local real z
 local integer dop
 local player ow=GetOwningPlayer(u)
 local group g=CreateGroup()
 local unit p
 local string fx
 local string fxa=GetAbilityEffectById(s,EFFECT_TYPE_TARGET,1)

    if (dmgps!=0) then
        set period=GetAbilityDataReal(s,l,"dmgpsPeriod")
        set dur=GetAbilityDataReal(s,l,"dmgpsDur")
    endif

    if (GetAbilityDataInt(s,l,"UseMissile")==1) then
        call SpellCast_Missile(ow,s,l,px,py,x,y)
    endif
    set fx=GetAbilityEffectById(s,EFFECT_TYPE_AREA_EFFECT,0)
    if ((fx!=null) and (fx!="")) then
        call DestroyEffect( AddSpellEffectById(s,EFFECT_TYPE_AREA_EFFECT,x,y) )
    endif
    set fx=GetAbilityEffectById(s,EFFECT_TYPE_TARGET,0)
    loop
        exitwhen (i>n)
        set k="spell"+I2S(i)
        set t=GetAbilityDataInt(s,l,k+"type")
        if (t==0) then //Targetted Spell
            set tn=tn+1
            set ts[tn]=GetAbilityDataInt(s,l,k+"id")
            set tsr[tn]=GetAbilityDataReal(s,l,k+"RecDelay")
            set tso[tn]=GetAbilityDataInt(s,l,k+"OrderId")
            set tsfp[tn]=(GetAbilityDataInt(s,l,k+"FromSource")==1)
            set tsz[tn]=GetAbilityDataReal(s,l,k+"CasterHeight")

        elseif (t==1) then

            if (GetAbilityDataInt(s,l,k+"FromSource")==1) then
                set cx=px
                set cy=py
            else
                set cx=x
                set cy=y
            endif
            set z=GetAbilityDataReal(s,l,k+"CasterHeight")
            call CasterCastAbilityPointEx(ow,cx,cy,z,  GetAbilityDataInt(s,l,k+"id") ,l, I2S( GetAbilityDataInt(s,l,k+"OrderId") )  , x, y, GetAbilityDataReal(s,l,k+"RecDelay") )

        endif
        set i=i+1
    endloop
    set dop=LoadDamageOptions( GetAbilityDataInt(s,l,"DamageOptions") )
    set n=GetAbilityDataInt(s,l,"maxtargets")
    call GroupEnumUnitsInRange(g,x,y,GetAbilityDataReal(s,l,"area"),null)
    if (IsDamageOptionIncluded(dop,DamageTrees())) then
        call DamageTreesInCircle(x,y,GetAbilityDataReal(s,l,"area"))
    endif
    loop
        set p=FirstOfGroup(g)
        exitwhen ((n<=0) or (p==null) )
        call GroupRemoveUnit(g,p)
        set z=GetDamageFactorByOptions(u,p,dop)
        if (z!=0) then
            set n=n-1
            if (dmg!=0) then
                call UnitDamageTarget(u,p,z*dmg,true,false,null,null,null) 
            endif
            if (dmgps!=0) then
                call UnitDamageUnitTimed(u,dmgps*z,period,dur,p,fx,fxa,null,null)
            else
                if ((fx!="") and (fx!=null)) then
                    call DestroyEffect( AddSpecialEffectTarget(fx,p,fxa) )
                endif
            endif
            set i=1
            loop
                exitwhen (i>tn)
                if (tsfp[i]) then
                    set cx=px
                    set cy=py
                else
                    set cx=GetUnitX(p)
                    set cy=GetUnitY(p)
                endif
                call CasterCastAbilityEx(ow,cx,cy,tsz[i],ts[i],l,I2S(tso[i]),p,tsr[i])
                set i=i+1
            endloop            

        endif
    endloop
    call DestroyGroup(g)


 set ow=null
 set g=null
 set p=null
endfunction

function SpellCast_Doer takes nothing returns nothing
 local trigger t=GetTriggeringTrigger()
 local string k=GetAttachmentTable(t)
 local eventid e=GetTriggerEventId()
 local integer s=GetTableInt(k,"s")
 local integer l=GetTableInt(k,"l")
 local integer n
 local real px
 local real py
 local unit u

    if (e==EVENT_UNIT_SPELL_FINISH) then
        call SetTableBoolean(k,"ignoreEndCast",true)
        set n=GetAbilityDataInt(s,l,"Times")
        if (n<=0) then
            set n=0x0FFFFFFF
        endif
        call SetTableInt(k,"n", n )        
        call TriggerRegisterTimerEvent(t, GetAbilityDataReal(s,l,"Timer")  , true)
    elseif ((e==EVENT_UNIT_SPELL_ENDCAST) or (e==EVENT_UNIT_DEATH) )then
        if ( not(GetTableBoolean(k,"ignoreEndCast")) or (e==EVENT_UNIT_DEATH)) then
            call CS_KillTrigger(t)
        endif
    else
        set n=GetTableInt(k,"n")
        if (n<=0) then
            call CS_KillTrigger(t)
        else
            call SetTableInt(k,"n",n-1)
            set u=GetTableUnit(k,"u")
            if (GetTableBoolean(k,"SourceIsUnit")) then
                set px=GetUnitX(u)
                set py=GetUnitY(u)
            else
                set px=GetTableReal(k,"px")
                set py=GetTableReal(k,"py")
            endif
            call SpellCast_Do(u,s,l,GetTableReal(k,"x") , GetTableReal(k,"y") ,px,py )
           set u=null
        endif
    endif

 set e=null
 set t=null
endfunction

function SpellCastTemplate takes nothing returns nothing
 local unit u=GetTriggerUnit()
 local unit uu
 local integer s=GetSpellAbilityId()
 local integer l=GetUnitAbilityLevel( u,s)
 local integer n
 local trigger t= CreateTrigger()
 local string k=GetAttachmentTable(t)
 local integer ty=GetAbilityDataInt(s,l,"ChannelType")
 local location loc=GetSpellTargetLoc() //Will always hate blizzard for not having GetSpellTargetX/Y and forcing me to use locations
 local real x=GetLocationX(loc)
 local real y=GetLocationY(loc)

    if ((x==0) and (y==0)) then
        set uu=GetSpellTargetUnit()
        if (uu!=null) then
            set x=GetUnitX(uu)
            set y=GetUnitY(uu)
        endif
       set uu=null
    endif

    if ((GetAbilityDataInt(s,l,"SourceIsUnit")==1) or (GetAbilityDataInt(s,l,"UseMissile")==1))  then
        call SetTableBoolean(k,"SourceIsUnit",true)
    else
        call SetTableReal(k,"px",x)
        call SetTableReal(k,"py",y)
    endif
    call SetTableReal(k,"x",x)
    call SetTableReal(k,"y",y)
    call SetTableInt(k,"s",s)
    call SetTableInt(k,"l",l)
    call SetTableObject(k,"u",u)

    call TriggerAddAction(t,function SpellCast_Doer)

    call TriggerRegisterUnitEvent(t,u,EVENT_UNIT_DEATH)
    if (ty>=1) then //do stuff till channel ends
        call TriggerRegisterUnitEvent(t,u,EVENT_UNIT_SPELL_ENDCAST)
    endif
    if (ty>=2) then //Wait till channel ends succesfully then do stuff
        call TriggerRegisterUnitEvent(t,u,EVENT_UNIT_SPELL_FINISH)
    else
        set n=GetAbilityDataInt(s,l,"Times")
        if (n<=0) then
            set n=0x0FFFFFFF
        endif
        call SetTableInt(k,"n", n )        
        call TriggerRegisterTimerEvent(t, GetAbilityDataReal(s,l,"Timer")  , true)
        if (GetAbilityDataInt(s,l,"instantStart")==1) then
            call TriggerExecute(t)
        endif
    endif

    call RemoveLocation(loc)
 set loc=null

 set u=null
 set t=null
endfunction

function InitTrig_SpellCast_Template_Copy takes nothing returns nothing
    call ExecuteFunc("SpellCastTemplateSetup")
//Must use ExecuteFunc to prevent the Map init thread from getting too long and crash.
endfunction

The repeat for each level, and the missile data works fine, but the damage has no effect at all, and the caster unit doesn't cast the FrostArmor spell. I made sure the rawcodes of the spell were right, too. Any Ideas?
 

SFilip

Gone but not forgotten
Reaction score
634
have you implemented the caster system correctly (newest version according to its readme, not just copy paste the one inside the spell factory)?
have you changed the raw codes ('A02T' and 'A02S')?
 

lllidan

New Member
Reaction score
22
Yes the raw codes are correct but no it seems I dont' have the latest version. I'll try updating it and see if it works then. So there's nothing wrong with the way the code is written?
 
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