//TESH.scrollpos=4
//TESH.alwaysfold=0
//*******************************************************************************
//* Paladon presents *
//* Judgement Strike *
//* vJass *
//*******************************************************************************
// Notes: *
// This is my first Jass / vJass spell. *
// This spell is dedicated to Eccho, Eleandor, Hanky and Dynasti who helped me *
// to get my JNGP working properly. *
// This spell is created due to a Spellchallenge between Dynasti and me. *
// *
// A great additional credit goes to Dynasti who taught me the usage of structs.*
// *
// Requirements: *
// -> JassNewGenPack *
// -> A single-target based spell *
// To import this spell, just copy the 'Judgement Strike' trigger into your *
// very own map and adjust the following values in the 'Settings'. *
//********************************SETTINGS***************************************
scope JudgementStrike initializer GetStarted
globals
private constant integer SpellID = 'A000' // Returns the rawcode of the spell. To get a spell's rawcode, press Ctrl+D in the Object Editor.
private constant real Speed = 20.00 // Returns the speed of the flying unit.
private constant real ImpactDamagePerLvl = 75.00 // Returns the impact damage dealt in the AoE and to the target per level.
private constant real DmgByDisPercentPerLvl = 0.08 // Returns the percentage amount per level of the distance which is dealt in direct damage to the target upon impact. 0.08 means 8% per level.
private constant real ImpactAoE = 300.00 // Returns the size of the area in which the impact damage is dealt.
private constant attacktype AttackType = ATTACK_TYPE_NORMAL // Returns the attack type in which the damage is dealt. There's actually no need to adjust this value.
private constant damagetype DamageType = DAMAGE_TYPE_NORMAL // Returns the damage type in which the damage is dealt. There's actually no need to adjust this value.
private constant weapontype WeaponType = WEAPON_TYPE_ROCK_HEAVY_BASH // Returns the weapon type with which the damage is dealt. There's actually no need to adjust this value, replace it with 'null' to remove the corresponding sound.
private constant string ThrowEffect = "Abilities\\Spells\\Undead\\OrbOfDeath\\OrbOfDeathMissile.mdl" // Returns the path of the special effect attached to the flying unit's chest.
private constant string FirstImpactEffect = "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl" // Returns the path of the first special effect displayed upon impact.
private constant string SecondImpactEffect = "Objects\\Spawnmodels\\Human\\HumanLargeDeathExplode\\HumanLargeDeathExplode.mdl" // Returns the path of the second special effect displayed upon impact.
private constant string AoeTargetEffect = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl" // Returns the path of the special effect attached to the targets of the impact damage.
private constant boolean Pause = false // Returns whether the flying unit should be paused.
endglobals
//********************************END OF THE SETTINGS**************************
//**Do not modify anything below this line unless you know what you are doing**
//*****************************************************************************
globals
private group grp = CreateGroup()
private boolexpr Filter = null
private real RectMaxX
private real RectMinX
private real RectMaxY
private real RectMinY
private unit tt
private unit tu
private player to
endglobals
private struct Spell
unit c
unit t
real md
real cd = 0
real x
real y
real cos
real sin
integer l
static Spell array indx
static integer counter = 0
static timer time = CreateTimer()
static method JSFlying takes nothing returns nothing
local Spell d
local integer i = 0
local real hight
loop
exitwhen i >= Spell.counter
set d = Spell.indx[i]
if d.cd < d.md then
set d.x = GetUnitX(d.t) + Speed * d.cos
set d.y = GetUnitY(d.t) + Speed * d.sin
if d.x < RectMaxX and d.x > RectMinX and d.y < RectMaxY and d.y > RectMinY then
set d.cd = d.cd + Speed
set hight = (-(((d.md-(d.md-d.cd))*2)/d.md-1)*(((d.md-(d.md-d.cd))*2)/d.md-1)+1)*(d.md/1.
call SetUnitFlyHeight(d.t,hight + GetUnitDefaultFlyHeight(d.t), 0.0)
call SetUnitX(d.t,d.x)
call SetUnitY(d.t,d.y)
call DestroyEffect(AddSpecialEffectTarget(ThrowEffect,d.t,"chest"))
else
set d.cd = d.md
endif
else
set tt = d.t
set to = GetOwningPlayer(d.c)
call DestroyEffect(AddSpecialEffect(FirstImpactEffect,d.x,d.y))
call DestroyEffect(AddSpecialEffect(SecondImpactEffect,d.x,d.y))
call UnitDamageTarget(d.c,d.t,(d.md*d.l*DmgByDisPercentPerLvl),true,true,AttackType,DamageType,WeaponType)
call GroupEnumUnitsInRange(grp,d.x,d.y,ImpactAoE,Filter)
loop
set tu = FirstOfGroup(grp)
exitwhen tu == null
call UnitDamageTarget(d.c,tu,ImpactDamagePerLvl*d.l,true,true,AttackType,DamageType,null)
call DestroyEffect(AddSpecialEffectTarget(AoeTargetEffect,tu,"chest"))
call GroupRemoveUnit(grp,tu)
endloop
if Pause == true then
call PauseUnit(d.t,false)
endif
call SetUnitFlyHeight(d.t,GetUnitDefaultFlyHeight(d.t),0.0)
set d.c = null
set d.t = null
call d.destroy()
set Spell.counter = Spell.counter - 1
set Spell.indx[i] = d.indx[Spell.counter]
set i = i - 1
endif
set i = i + 1
endloop
if Spell.counter == 0 then
call PauseTimer(Spell.time)
endif
endmethod
static method GetValues takes unit c, unit t, real a, real md, integer l returns nothing
local Spell d = Spell.allocate()
set d.c = c
set d.t = t
set d.x = GetUnitX(t)
set d.y = GetUnitY(t)
set d.md = md
set d.cos = Cos(a)
set d.sin = Sin(a)
set d.l = l
if Spell.counter == 0 then
call TimerStart(Spell.time,0.02,true, function Spell.JSFlying)
endif
set Spell.indx[Spell.counter] = d
set Spell.counter = Spell.counter + 1
endmethod
endstruct
private function GetFilter takes nothing returns boolean
return GetWidgetLife(GetFilterUnit()) > 0 and IsUnitEnemy(GetFilterUnit(),to) and IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING) == false
endfunction
private function JSCondition takes nothing returns boolean
return GetSpellAbilityId() == SpellID
endfunction
private function JSInput takes nothing returns nothing
local unit c = GetTriggerUnit()
local unit t = GetSpellTargetUnit()
local real xc = GetUnitX(c)
local real xt = GetUnitX(t)
local real yc = GetUnitY(c)
local real yt = GetUnitY(t)
call Spell.GetValues(c,t,Atan2((yc-yt),(xc-xt)),(SquareRoot((xt-xc)*(xt-xc)+(yt-yc)*(yt-yc)))*2,GetUnitAbilityLevel(c,SpellID))
call UnitAddAbility(t,'Amrf')
call UnitRemoveAbility(t,'Amrf')
if Pause == true then
call PauseUnit(t,true)
endif
set c = null
set t = null
endfunction
private function GetStarted takes nothing returns nothing
local trigger JStrike = CreateTrigger()
local integer i = 0
set RectMaxX = GetRectMaxX(bj_mapInitialPlayableArea)
set RectMinX = GetRectMinX(bj_mapInitialPlayableArea)
set RectMaxY = GetRectMaxY(bj_mapInitialPlayableArea)
set RectMinY = GetRectMinY(bj_mapInitialPlayableArea)
set Filter = Condition(function GetFilter)
loop
call TriggerRegisterPlayerUnitEvent(JStrike, Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(JStrike, Condition(function JSCondition))
call TriggerAddAction(JStrike, function JSInput)
call Preload(FirstImpactEffect)
call Preload(SecondImpactEffect)
call Preload(AoeTargetEffect)
call Preload(ThrowEffect)
call PreloadStart()
endfunction
endscope