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)
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?
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?