Name | Type | is_array | initial_value |
Creep_Point | location | Yes | |
FW_Angle | real | Yes | |
FW_AoE1 | real | Yes | |
FW_AoE2 | real | Yes | |
FW_Cast | unit | Yes | |
FW_CastLoc | location | Yes | |
FW_Count | real | Yes | |
FW_CurDist | real | Yes | |
FW_Dist | real | Yes | |
FW_Dist1 | real | Yes | |
FW_DMG1 | real | Yes | |
FW_DMG2 | real | Yes | |
FW_DMG3 | real | Yes | |
FW_Dummy | unit | No | |
FW_Int | integer | Yes | |
FW_Loc | location | No | |
FW_Loc1 | location | No | |
FW_Loc2 | location | No | |
FW_Step | integer | Yes | |
FW_TarLoc | location | Yes | |
FWM_Angle | real | Yes | |
FWM_AngleMultiplier | real | Yes | |
FWM_AoE | real | Yes | |
FWM_CastLoc | location | Yes | |
FWM_CurAngle | real | No | |
FWM_CurDist | real | Yes | |
FWM_CurHeight | real | Yes | |
FWM_DD | unit | Yes | |
FWM_Dist | real | Yes | |
FWM_Dmg | real | Yes | |
FWM_Dummy | unit | Yes | |
FWM_Fly | integer | Yes | |
FWM_Formula | real | Yes | |
FWM_Int | integer | Yes | |
FWM_Loc | location | Yes | |
FWM_MaxHeight | real | Yes | |
FWM_Step | integer | Yes | |
FWM_Steps | real | Yes | |
LeakPoint | location | No | |
Loc | location | Yes | |
Temp_Integer | integer | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
Hai ;D
This is my spell 'Fiery Rage v2.5' made for a challenge against calex3 and f0rsAk3n on THW
Good Luck to both of you ;P
I tried to avoid using the object editor because the category was TRIGGERING, and ended up
at only having one dummy spell, which of course is neccesary.
This spell works with 3 steps: -The fireballs flying to the target
-The burning boulders flying
-The fireballs when boulders explode.
I used dummy units, not special effects because of facing and unit size and flying height
possibilities.
This spell kinda includes a little "dummy move" system, which features everything i need for
this spell, not more, not less. It has an indicator for the three steps which is the integer "FWM_Fly"
If this is 0, it will not fly, but calculate a formula for the arcish movement.
If it is 1, it will just raise linear
and if it is two, it will raise and sink in a nice-looking sine arc.
I would like to thank Palaslayer for teaching me GUI and Paladon for his great indexing sys.
Note that I also recycle indexes, to avoid overflow.
This map also contains older versions of the spell, so you can see, how it has developed.
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope FieryRage initializer init
globals
//The Spell ID. Click ctrl+d in object editor to check if your's is the right.
private constant integer SpellID = 'A000'
//The ID of the dummy unit, which has to be imported.
private constant integer DummyID = 'h000'
//Just neccesary, if you modified existing skills.
private constant integer CrowFormID = 'Amrf'
//The SFX attached to the first dummies, which are flying in a hilf circle from the caster to the target.
private constant string Dummy1attach1 = "Abilities\\Weapons\\LordofFlameMissile\\LordofFlameMissile.mdl"
//See above
private constant string Dummy1attach2 = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"
//The SFX attached to the second dummies, which are flying at changing heights, away from the detonation center.
private constant string Dummy2attach1 = "Abilities\\Spells\\Other\\Volcano\\VolcanoMissile.mdl"
//See above
private constant string Dummy2attach2 = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"
//The SFX attached to the third dummies, which are generated out of the second ones.
private constant string Dummy3attach = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl"
//The SFX shown, when the first dummies arrive.
private constant string SFX1 = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
//The SFX shown, when the second dummies arrive.
private constant string SFX2 = "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl"
//See above
private constant string SFX3 = "Abilities\\Spells\\Other\\Volcano\\VolcanoDeath.mdl"
//The SFX which is shown on every unit (with a 10% chance) every TimerInt, when they are near a projectile.
private constant string SpamSFX = "Environment\\SmallBuildingFire\\SmallBuildingFire2.mdl"
//The size of the first SFX, whereas 1. would be the normal size.
private constant real SFX1size = 1.5
//Quite self-explanatory, isn't it?
private constant real TimerInt = .03
//Damage Setup
private constant boolean Attack = false
//Damage Setup
private constant boolean Ranged = false
//Damage Setup
private constant attacktype AttackType = ATTACK_TYPE_NORMAL
//Damage Setup
private constant damagetype DamageType = DAMAGE_TYPE_NORMAL
//Damage Setup
private constant weapontype WeaponType = WEAPON_TYPE_WHOKNOWS
//The steps, the first dummies take to reach their target, so less steps mean more speed.
private constant integer Steps1 = 40
//The steps, the second dummies take to reach their target, so less steps mean more speed.
private constant integer Steps2 = 20
//The steps, the third dummies take to reach their target, so less steps mean more speed.
private constant integer Steps3 = 16
endglobals
//The number of the first dummies. This should be an uneven number, so you have one missile flying in the middle.
//Else it will look awkward.
private function Dummys1 takes integer lev returns integer
return 5
endfunction
//The number of the second dummies.
private function Dummys2 takes integer lev returns integer
return 10
endfunction
//The number of the first dummies. It should be divideable by Dummys2, since every Dummy3 has its origin in a Dummy2.
private function Dummys3 takes integer lev returns integer
return Dummys2(0)*3
endfunction
//The damage done, when the first dummies reach their target.
private function Damage1 takes real dist, integer lev returns real
return lev*100.
endfunction
//The damage done, when the second dummies reach their target.
private function Damage2 takes real dist, integer lev returns real
return lev*25.
endfunction
//The damage done, when the unit is near a projectile.
private function DamagePerSec takes real dist, integer lev returns real
return lev*10.*TimerInt
endfunction
//The Aoe of Damage1.
private function AoE1 takes real dist, integer lev returns real
return dist/2.
endfunction
//The Aoe of Damage2.
private function AoE2 takes real dist, integer lev returns real
return dist/3.
endfunction
//The maximum flying height of the second dummies.
private function Dummy2maxHeight takes real dist, integer lev returns real
return AoE2(dist, 0)
endfunction
//The flying height of the third dummies. I chose a random number to imitate an explosion (scatters flying around).
private function Dummy3maxHeight takes real dist, integer lev returns real
return GetRandomReal(0., 300.)
endfunction
//The AoE of Damage3.
private function DamagePerSecAoe takes real dist, integer lev returns real
return 220.
endfunction
//Ignore the following 5 lines.
globals
private player p
private boolean heightcheck
private real heighttolerance = 20.
endglobals
//Setup continues
//The Filter for units.
private function UnitFilter takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(), p) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) and GetWidgetLife(GetFilterUnit())>.405
endfunction
//End of Setup
globals
private boolexpr b
private group g = CreateGroup()
endglobals
private struct data
unit cast
unit array dum [50]
real dist
real curdist
real aoe1
real aoe2
real aoe3
real dmg1
real dmg2
real dmg3
real cx
real cy
real tx
real ty
real ang
real array dumang [50]
real formula
real maxheight2
real array maxheight3 [50]
integer step
integer dummys1
integer dummys2
integer dummys3
effect e0
effect array e1 [50]
effect array e2 [50]
static data array ar
static timer tim = CreateTimer()
static integer total = 0
static real dam
static unit cas
static real h
static method groupdamage takes nothing returns nothing
local unit u = GetEnumUnit()
if heightcheck then
if GetUnitFlyHeight(u)>data.h-heighttolerance and GetUnitFlyHeight(u)<data.h+heighttolerance then
call UnitDamageTarget(data.cas, u, data.dam, Attack, Ranged, AttackType, DamageType, WeaponType)
if GetRandomInt(1, 10) == 10 then
call DestroyEffect(AddSpecialEffect(SpamSFX, GetUnitX(u), GetUnitY(u)))
endif
call GroupRemoveUnit(g, u)
endif
else
call UnitDamageTarget(data.cas, u, data.dam, Attack, Ranged, AttackType, DamageType, WeaponType)
if GetRandomInt(1, 10) == 10 then
call DestroyEffect(AddSpecialEffect(SpamSFX, GetUnitX(u), GetUnitY(u)))
endif
call GroupRemoveUnit(g, u)
endif
set u = null
endmethod
static method periodic takes nothing returns nothing
local data d
local integer i = 0
local integer ii = 0
local integer iii = 0
local real x = .0
local real y = .0
local unit u
loop
exitwhen i >= d.total
set d = d.ar[i]
if d.step == 0 then
loop
exitwhen ii >= d.dummys1
set ii = ii + 1
set d.dum[ii] = CreateUnit(Player(15), DummyID, d.cx, d.cy, d.ang)
call PauseUnit(d.dum[ii], true)
set d.e1[ii] = AddSpecialEffectTarget(Dummy1attach1 , d.dum[ii], "chest")
set d.e2[ii] = AddSpecialEffectTarget(Dummy1attach2 , d.dum[ii], "origin")
call UnitAddAbility(d.dum[ii], CrowFormID)
endloop
set d.formula = bj_PI/2.
set ii = 0
set d.step = 1
endif
if d.step == 1 then
set d.formula = d.formula + bj_PI/(Steps1*2.)
loop
exitwhen ii >= d.dummys1
set ii = ii + 1
set d.curdist = d.curdist + d.dist/(Steps1*5.)
set x = d.cx+d.curdist*Cos(d.ang+Sin(d.formula)*(bj_PI/2.)*(I2R(ii-(d.dummys1/2+1))/2.))
set y = d.cy+d.curdist*Sin(d.ang+Sin(d.formula)*(bj_PI/2.)*(I2R(ii-(d.dummys1/2+1))/2.))
call SetUnitPosition(d.dum[ii], x, y)
set p = GetOwningPlayer(d.cast)
call GroupEnumUnitsInRange(g, x, y, d.aoe3, b)
set d.dam = d.dmg3
set d.cas = d.cast
set heightcheck = false
call ForGroup(g, function data.groupdamage)
if d.formula >= bj_PI then
set d.step = 2
call DestroyEffect(d.e1[ii])
call DestroyEffect(d.e2[ii])
call RemoveUnit(d.dum[ii])
endif
endloop
set ii = 0
endif
if d.step == 2 then
set p = GetOwningPlayer(d.cast)
call GroupEnumUnitsInRange(g, d.tx, d.ty, d.aoe1, b)
set d.dam = d.dmg1
set d.cas = d.cast
set heightcheck = false
call ForGroup(g, function data.groupdamage)
set u = CreateUnit(Player(15), DummyID, d.tx, d.ty, .0)
call SetUnitScale(u, SFX1size, SFX1size, SFX1size)
set d.e0 = AddSpecialEffectTarget(SFX1, u, "chest")
call UnitApplyTimedLife(u, 'BTLF', 1.)
call PauseUnit(u, true)
set u = null
loop
exitwhen ii >= d.dummys2
set ii = ii + 1
set d.dum[ii] = CreateUnit(Player(15), DummyID, d.tx, d.ty, d.ang)
call PauseUnit(d.dum[ii], true)
set d.e1[ii] = AddSpecialEffectTarget(Dummy2attach1 , d.dum[ii], "chest")
set d.e2[ii] = AddSpecialEffectTarget(Dummy2attach2 , d.dum[ii], "origin")
call UnitAddAbility(d.dum[ii], CrowFormID)
set d.dumang[ii] = bj_PI*2./ii
endloop
set ii = 0
set d.step = 3
set d.formula = 0.
set d.curdist = 0.
endif
if d.step == 3 then
set d.formula = d.formula + bj_PI/Steps2
set d.curdist = d.curdist + d.aoe2/Steps2
loop
exitwhen ii >= d.dummys2
set ii = ii + 1
set x = d.tx+d.curdist*Cos(bj_PI*2./d.dummys2*ii)
set y = d.ty+d.curdist*Sin(bj_PI*2./d.dummys2*ii)
call SetUnitPosition(d.dum[ii], x, y)
call SetUnitFlyHeight(d.dum[ii], d.maxheight2*Sin(d.formula), 0.)
set p = GetOwningPlayer(d.cast)
call GroupEnumUnitsInRange(g, x, y, d.aoe3, b)
set d.dam = d.dmg3
set d.cas = d.cast
set d.h = GetUnitFlyHeight(d.dum[ii])
set heightcheck = true
call ForGroup(g, function data.groupdamage)
endloop
set ii = 0
if d.formula >= bj_PI then
set d.step = 4
endif
endif
if d.step == 4 then
call DestroyEffect(d.e0)
loop
exitwhen ii == d.dummys2
set ii = ii + 1
set x = GetUnitX(d.dum[ii])
set y = GetUnitY(d.dum[ii])
set p = GetOwningPlayer(d.cast)
call GroupEnumUnitsInRange(g, x, y, d.aoe3, b)
set d.dam = d.dmg2
set d.cas = d.cast
set heightcheck = false
call ForGroup(g, function data.groupdamage)
call DestroyEffect(AddSpecialEffect(SFX2, x, y))
call DestroyEffect(AddSpecialEffect(SFX3, x, y))
call DestroyEffect(d.e1[ii])
call DestroyEffect(d.e2[ii])
call RemoveUnit(d.dum[ii])
endloop
set ii = 0
set d.step = 5
endif
if d.step == 5 then
loop
exitwhen ii == d.dummys2
set ii = ii + 1
set x = d.tx+d.aoe2*Cos(bj_PI*2./d.dummys2*ii)
set y = d.ty+d.aoe2*Sin(bj_PI*2./d.dummys2*ii)
loop
exitwhen iii == d.dummys3/d.dummys2
set iii=iii+1
set d.dum[iii] = CreateUnit(Player(15), DummyID, x, y, (ii*(bj_PI*2.)/3.))
call PauseUnit(d.dum[ii], true)
set d.e1[iii] = AddSpecialEffectTarget(Dummy3attach , d.dum[iii], "chest")
call UnitAddAbility(d.dum[iii], CrowFormID)
set d.maxheight3[iii] = Dummy3maxHeight(d.dist, GetUnitAbilityLevel(d.cast, SpellID))
endloop
endloop
set d.formula = 0.
set ii = 0
set iii = 0
set d.step = 6
endif
if d.step == 6 then
set d.formula = d.formula+1./Steps3
loop
exitwhen ii == d.dummys3
set ii = ii + 1
set x = GetUnitX(d.dum[ii])+d.aoe3/20.*Cos(ii*(bj_PI*2.)/3.)
set y = GetUnitY(d.dum[ii])+d.aoe3/20.*Sin(ii*(bj_PI*2.)/3.)
call SetUnitPosition(d.dum[ii], x, y)
call SetUnitFlyHeight(d.dum[ii], d.maxheight3*d.formula, 0.)
set p = GetOwningPlayer(d.cast)
set d.cas = d.cast
set d.dam = d.dmg3
set heightcheck = true
set d.h = GetUnitFlyHeight(d.dum[ii])
call GroupEnumUnitsInRange(g, x, y, d.aoe3, b)
call ForGroup(g, function data.groupdamage)
endloop
set ii = 0
if d.formula >= 1. then
loop
exitwhen ii == d.dummys3
set ii = ii + 1
call DestroyEffect(d.e1[ii])
call RemoveUnit(d.dum[ii])
endloop
set ii = 0
set d.formula = 0
set d.curdist = 0
set d.total = d.total - 1
set d.ar[i] = d.ar[d.total]
call d.destroy()
set i = i - 1
endif
endif
set i = i + 1
endloop
if d.total == 0 then
call PauseTimer(d.tim)
endif
endmethod
static method actions takes nothing returns nothing
local data d = data.allocate()
local integer lev = GetUnitAbilityLevel(GetTriggerUnit(), SpellID)
set d.tx = GetSpellTargetX()
set d.ty = GetSpellTargetY()
set d.cast = GetTriggerUnit()
set d.cx = GetUnitX(d.cast)
set d.cy = GetUnitY(d.cast)
set d.ang = Atan2(d.ty-d.cy, d.tx-d.cx)
set d.dist = SquareRoot(Pow(d.tx-d.cx, 2.)+Pow(d.ty-d.cy,2.))
set d.aoe1 = AoE1(d.dist, lev)
set d.aoe2 = AoE2(d.dist, lev)
set d.aoe3 = DamagePerSecAoe(d.dist, lev)
set d.dmg1 = Damage1(d.dist, lev)
set d.dmg2 = Damage2(d.dist, lev)
set d.dmg3 = DamagePerSec(d.dist, lev)
set d.maxheight2 = Dummy2maxHeight(d.dist, lev)
set d.step = 0
set d.dummys1 = Dummys1(lev)
set d.dummys2 = Dummys2(lev)
set d.dummys3 = Dummys3(lev)
if d.total == 0 then
call TimerStart(d.tim, TimerInt, true, function data.periodic)
endif
set d.ar[d.total] = d
set d.total = d.total + 1
endmethod
endstruct
private function condition takes nothing returns boolean
return GetSpellAbilityId()==SpellID
endfunction
private function noleakfilter takes nothing returns boolean
return true
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
local filterfunc ff = Filter(function noleakfilter)
loop
exitwhen i >= bj_MAX_PLAYER_SLOTS
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, ff)
set i = i + 1
endloop
set i = 0
call TriggerAddAction(t, function data.actions)
call TriggerAddCondition(t, Condition(function condition))
set b = Condition(function UnitFilter)
call DestroyFilter(ff)
set ff = null
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
Fiery Rage v 3.00
This spell was originally made in GUI for a challenge, but i (or better: GUI) failed, so i decided to learn vJass and
finally made this. I tried to add very much modularity.
Credits go to all the people on the hive, especially Hanky who helped me to understand a problem concerning arrays
in structs.
FAQ:
Q: How do I import this spell?
A: First off, you copy the spell in the object editor.
After this, you have to import the Dummy.mdx file with the import manager.
Next to that, you copy the dummy unit from the object editor, and check the model data.
Then you copy "Fiery Rage vJass" into your map.
When you have done this, you check if the rawcodes in the code are still ok.
Go in to object editor, press ctrl+D and compare the rawcodes with the ones in the globals block.
Finally, you can change the values as you want and use it!
Q: Where do I get some nice effects?
A: Well the easiest way in my opinion is to create a trigger and add the action "Create Special Effect at Point".
Now you select the effect you want and copy the string. Put it in the variable, but CAREFUL:
You need a double backslash(\\), where GUI only puts one.
Q: Why do you have only 2 questions?
A: Well, ask more and I'll add them.