Name | Type | is_array | initial_value |
Creep_Point | location | Yes | |
Temp_Integer | integer | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
Readme:
This pack contains three spells of mine (my first three vJass spells):
1.: Blink Strike (A simple Blink Strike With AoE damage
2.: Armageddon (Summons a bucnh of several random SFX in a certain AoE dealing damage)
3.: A charge (finally learned how to use structs [thanks to Anachron {direct help}, Dynasti {tutorial}
and Paladon {direct help}]. The caster has always the same speed, not like in my
previous versions. (I can show you on demand)
Simply import the triggers and the spells and make sure that the rawcodes still are correct
(ctrl+D ind Object Editor and look at spells, then compare to the one in the code)
Change values in setup sections to whatever pleases you.
Further credits go to THW for many tutorials (can#t list all the people sry)
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Conditions takes nothing returns boolean
return GetWidgetLife(GetTriggerUnit()) < 200
endfunction
function Trig_heal_Actions takes nothing returns nothing
call SetWidgetLife(GetTriggerUnit(), 19231)
endfunction
constant function NoLeakFilter takes nothing returns boolean
return true
endfunction
//===========================================================================
function InitTrig_heal takes nothing returns nothing
local trigger t = CreateTrigger()
local filterfunc ff = Filter(function NoLeakFilter)
call TriggerAddAction( t, function Trig_heal_Actions )
call TriggerRegisterPlayerUnitEvent(t, Player(0), EVENT_PLAYER_UNIT_ATTACKED, ff)
call TriggerAddCondition(t, Condition(function Conditions))
call DestroyFilter(ff)
set ff = null
endfunction
//TESH.scrollpos=18
//TESH.alwaysfold=0
scope RealisticCharge initializer Start
globals
//!*******************************SETTINGS*************************!\\
//! general settings
private constant integer SpellID = 'A000'
//^The spell's rawcode
private constant real TimerInterval = 0.02
//^The interval used by the timer. I suggest leaving it at 0.02
private constant integer Speed = 30
//^The speed, with which the caster charges
private constant string ChargeSFX = "Environment\\LargeBuildingFire\\LargeBuildingFire1.mdl"
//^The SFX occuring every (TimerInterval) seconds at the caster's position
private constant string TargetSFX = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl"
//^The SFX created upon impact
private constant string CastAttach = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"
//^The attachment created at the AttachPt
private constant string AttachPt = "weapon"
//^The point where the attachment is created.
private constant string CastAnim = "slam"
//^The animation played every "AnimInterval"
private constant real AnimInterval = 0.4
//^The Interval in which the animation is played.
private constant boolean PathingCheck = false
//^Determines whether the caster should stop, when he has reached an unpathable point
private constant boolean DestroyTrees = true
//^This sets if trees are destroyed.
private constant real TreesAoE = 200.
//^Sets the radius in which trees are destroyed.
endglobals
private function Damage takes integer level returns integer
return (level*100)
//^The damage dealt upon impact. If you don't want the level to influence the damage,
//^simply return the wanted damage
endfunction
//!*******************************SETTINGS END*********************!\\
globals
private boolexpr b
endglobals
//Filter for leakless Event
private constant function NoLeakFilter takes nothing returns boolean
return true
endfunction
//The condition ;D
private function condition takes nothing returns boolean
return GetSpellAbilityId() == SpellID
endfunction
private function KillTrees takes nothing returns nothing
call KillDestructable(GetEnumDestructable())
endfunction
//Main Struct
private struct Spell
//Needed variables
private unit caster //The casting unit
private unit target //The target ;P
private real x //The X-Coordinate, which determines the new position of the caster
private real y //The Y-Coordinate, which determines the new position of the caster
private real x1 //The X-Coordinate, which determines the start position of the caster
private real y1 //The Y-Coordinate, which determines the start position of the caster
private real x2 //The X-Coordinate, which determines the position of the target
private real y2 //The Y-Coordinate, which determines the position of the target
private integer steps //This will be the number of single moves I have to do
private integer level //The level for damage calculation reasons
private integer curstep //The counter, which step is currently being run
private integer animstep//Tells the game when the animation should be played
private effect attach //The attachment
private boolean finished//Neccesary, for not damaging target, if unit stopped, because of unpathable terrain.
private rect r //Needed for tree destroy
//Neccesary struct variables
private static Spell array indx
private static integer counter = 0
private static timer time = CreateTimer()
//The "real" actions done every Interval
static method Execution takes nothing returns nothing
local Spell d
local integer i = 0
loop
exitwhen i >= Spell.counter
set d = Spell.indx[i]
//Counting the curstep one up, so it will stop when it has reached steps
set d.curstep = d.curstep + 1
if d.curstep < d.steps then
//Setting new X and Y to old X/Y + (distance between cast and target X/Y) / steps
set d.x = d.x + ((d.x2 - d.x1) / d.steps)
set d.y = d.y + ((d.y2 - d.y1) / d.steps)
if DestroyTrees == true then
set d.r = Rect(d.x - TreesAoE, d.y - TreesAoE, d.x + TreesAoE, d.y + TreesAoE)
call EnumDestructablesInRect(d.r, b, function KillTrees)
call RemoveRect(d.r)
set d.r = null
endif
if PathingCheck == true then
if IsTerrainPathable(d.x, d.y, PATHING_TYPE_WALKABILITY) == false then
call SetUnitX(d.caster, d.x)
call SetUnitY(d.caster, d.y)
//SFX
call DestroyEffect(AddSpecialEffect(ChargeSFX, d.x, d.y))
if d.animstep < R2I(AnimInterval / TimerInterval) then
set d.animstep = d.animstep + 1
else
set d.animstep = 0
call SetUnitAnimation(d.caster, CastAnim)
endif
else
set d.curstep = d.steps
set d.finished = false
endif
else
call SetUnitX(d.caster, d.x)
call SetUnitY(d.caster, d.y)
//SFX
call DestroyEffect(AddSpecialEffect(ChargeSFX, d.x, d.y))
if d.animstep < R2I(AnimInterval / TimerInterval) then
set d.animstep = d.animstep + 1
else
set d.animstep = 0
call SetUnitAnimation(d.caster, CastAnim)
endif
endif
else
//Damaging the target, unpausing units, giving them pathing
if d.finished == true then
call UnitDamageTarget(d.caster, d.target, Damage(d.level), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNKNOWN, null)
call DestroyEffect(AddSpecialEffect(TargetSFX, d.x, d.y))
endif
call SetUnitPathing(d.caster, true)
call PauseUnit(d.caster, false)
call PauseUnit(d.target, false)
call DestroyEffect(d.attach)
call SetUnitAnimation(d.caster, "walk")
//Struct actions
set d.curstep = 0
set d.animstep = 0
call d.destroy()
set d.counter = d.counter - 1
set d.indx[i] = d.indx[d.counter]
set i = i - 1
endif
set i = i + 1
endloop
set i = 0
//Pause Timer if no instance is running
if Spell.counter == 0 then
call PauseTimer(Spell.time)
endif
endmethod
//Setting variables at spellcast
static method Set takes unit c, unit t, integer l returns nothing
local Spell d = Spell.allocate()
//Obvious settings ;P
set d.caster = c
set d.target = t
set d.x1 = GetUnitX(c)
set d.y1 = GetUnitY(c)
set d.x2 = GetUnitX(t)
set d.y2 = GetUnitY(t)
set d.x = d.x1
set d.y = d.y1
set d.level = l
set d.finished = true //Standard settubg is true, so it damages the target.
//Now I calculate how many steps it takes, by dividing distance between start and end point through speed
set d.steps = R2I((SquareRoot((Pow((d.x2-d.x1), 2.00)+Pow((d.y2-d.y1), 2.00)))) / Speed)
//Pathing and Pausing
call SetUnitPathing(c, false)
call PauseUnit(c, true)
call PauseUnit(t, true)
call SetUnitFacing(c, bj_RADTODEG * Atan2(d.y2 - d.y1, d.x2 - d.x1))
call SetUnitAnimation(c, CastAnim)
set d.attach = AddSpecialEffectTarget(CastAttach, c, "weapon")
//Starting Timer if no instance is already running
if Spell.counter == 0 then
call TimerStart(Spell.time,TimerInterval,true, function Spell.Execution)
endif
set Spell.indx[Spell.counter] = d
set Spell.counter = Spell.counter + 1
endmethod
endstruct
//Function that initializes the actions
private function VInput takes nothing returns nothing
call Spell.Set(GetTriggerUnit(),GetSpellTargetUnit(),GetUnitAbilityLevel(GetTriggerUnit(),SpellID))
endfunction
private function Start takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
local filterfunc ff = Filter(function NoLeakFilter)
//No leaks through TriggerRegisterAnyUnitEventBJ
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, ff)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
set i = 0
call TriggerAddCondition(t, Condition(function condition))
call TriggerAddAction(t, function VInput)
call DestroyFilter(ff)
call Preload(ChargeSFX)
call Preload(TargetSFX)
call PreloadStart()
set ff = null
set b = Condition(function NoLeakFilter)
endfunction
endscope
//TESH.scrollpos=5
//TESH.alwaysfold=0
//====================================================================================================\\
//=====================================================SETUP==========================================\\
//====================================================================================================\\
scope BlinkStrike initializer Init
globals
private constant integer SpellID = 'A001'
private constant string CasterEffect = "Abilities\\Spells\\Undead\\ReplenishMana\\ReplenishManaCasterOverhead.mdl"
private constant string TargetEffect = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl"
private constant real ImpactDamagePerLvl = 100
private constant real GroupDamagePerLvl = 50
private constant real GroupAoE = 300
endglobals
private function UnitsAoE takes unit target returns boolean
return (GetWidgetLife(target) > 0.405) and (IsUnitType(target, UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) == false) and (IsUnitType(target, UNIT_TYPE_MECHANICAL) == false) and (IsUnitEnemy(target, GetTriggerPlayer()) == true)
endfunction
//====================================================================================================\\
//====================================================SETUP END=======================================\\
//====================================================================================================\\
globals
private boolexpr b
endglobals
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == SpellID
endfunction
private function Targets takes nothing returns boolean
return UnitsAoE(GetFilterUnit())
endfunction
private function GroupDamage takes nothing returns nothing
call UnitDamageTarget(GetTriggerUnit(), GetEnumUnit(), GroupDamagePerLvl, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS)
endfunction
private function Actions takes nothing returns nothing
local unit c = GetSpellAbilityUnit()
local unit t = GetSpellTargetUnit()
local real x = GetUnitX(c)
local real y = GetUnitY(c)
local group g = CreateGroup()
call DestroyEffect(AddSpecialEffect(CasterEffect,x,y))
set x = GetUnitX(t)
set y = GetUnitY(t)
call SetUnitX(c, x)
call SetUnitY(c, y)
call DestroyEffect(AddSpecialEffect(TargetEffect,x,y))
if IsUnitEnemy(t, GetTriggerPlayer()) then
call UnitDamageTarget(c, t, I2R(GetUnitAbilityLevel(c,SpellID))*ImpactDamagePerLvl, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS)
else
endif
call GroupEnumUnitsInRange(g, x, y, GroupAoE, b)
call ForGroup(g, function GroupDamage)
set c = null
set t = null
endfunction
private constant 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
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, ff)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
set i = 0
set b = Condition(function Targets)
call TriggerAddCondition( t, Condition( function Conditions ) )
call TriggerAddAction( t, function Actions )
call Preload(CasterEffect)
call Preload(TargetEffect)
call PreloadStart()
call DestroyFilter(ff)
set ff = null
endfunction
endscope
//TESH.scrollpos=16
//TESH.alwaysfold=0
//====================================================================================================\\
//=====================================================SETUP==========================================\\
//====================================================================================================\\
scope Armageddon initializer Init
globals
private constant integer SpellID = 'A002'
private constant string CasterEffect = "Abilities\\Spells\\Other\\ImmolationRed\\ImmolationRedTarget.mdl"
private constant string TargetEffect = "Environment\\LargeBuildingFire\\LargeBuildingFire1.mdl"
private constant real GroupAoE = 300
private constant integer EffectsPerLvl = 3
private constant real AoE = 1200
private string array Effect [2]
endglobals
private function GroupDamageSetup takes integer l returns real
return I2R(l * 100)
endfunction
private function UnitsAoE takes unit target returns boolean
return (GetWidgetLife(target) > 0.405) and (IsUnitType(target, UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) == false) and (IsUnitType(target, UNIT_TYPE_MECHANICAL) == false) and (IsUnitEnemy(target, GetTriggerPlayer()) == true)
endfunction
private function ReturnStrings takes nothing returns nothing
set Effect[1] = "Abilities\\Spells\\Demon\\RainOfFire\\RainOfFireTarget.mdl"
set Effect[2] = "Units\\Demon\\Infernal\\InfernalBirth.mdl"
set Effect[3] = "Units\\Demon\\Infernal\\InfernalBirth.mdl"
endfunction
//====================================================================================================\\
//====================================================SETUP END=======================================\\
//====================================================================================================\\
globals
private boolexpr b
endglobals
private function Targets takes nothing returns boolean
return UnitsAoE(GetFilterUnit())
endfunction
private function GroupDamage takes nothing returns nothing
call UnitDamageTarget(GetTriggerUnit(), GetEnumUnit(), GroupDamageSetup(GetUnitAbilityLevel(GetTriggerUnit(), SpellID)), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(AddSpecialEffectTarget(TargetEffect, GetEnumUnit(), "chest"))
endfunction
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == SpellID
endfunction
private function Actions takes nothing returns nothing
local unit c = GetTriggerUnit()
local real X1 = GetUnitX(c)
local real X2
local real Y1 = GetUnitY(c)
local real Y2
local group g = CreateGroup()
local integer i = 0
local integer r = 0
local integer e = (GetUnitAbilityLevel(c, SpellID)*EffectsPerLvl)
call DestroyEffect(AddSpecialEffect(CasterEffect, X1, Y1))
loop
exitwhen i == e
set i = i + 1
set X2 = GetRandomReal((X1 - (AoE/2)), (X1 + (AoE/2)))
set Y2 = GetRandomReal((Y1 - (AoE/2)), (Y1 + (AoE/2)))
set r = GetRandomInt(1, 3)
call DestroyEffect(AddSpecialEffect(Effect[r], X2, Y2))
call GroupEnumUnitsInRange(g, X2, Y2, GroupAoE, b)
call ForGroup(g, function GroupDamage)
endloop
set i = 0
set c = null
set r = 0
set e = 0
endfunction
private constant 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
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, ff)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
set i = 0
set b = Condition(function Targets)
call ReturnStrings()
set i = 0
call TriggerAddCondition( t, Condition( function Conditions ) )
call TriggerAddAction( t, function Actions )
call Preload(CasterEffect)
call Preload(TargetEffect)
call PreloadStart()
call DestroyFilter(ff)
set ff = null
endfunction
endscope