//===========================================================================
//=**************************************************************************
//=*
//=* Chidori by Ofel
//=* v1.2
//=*
//=* Credits:
//=* + PurgeandFire
//=* + Gwapogi
//=* + Jad
//=* + bowser499
//=*
//=* Requirement:
//=* + Check Walkability system
//=*
//=**************************************************************************
//===========================================================================
//***************************************************************************
//***************************************************************************
//**
//** CONFIGURATION
//**
//***************************************************************************
//***************************************************************************
//***************************************************************************
//*
//* Determines the ability raw code. Press Ctrl + D to show the raw code in
//* Object Editor
//*
//***************************************************************************
constant function C_AbilityId takes nothing returns integer
return 'A000'
endfunction
//***************************************************************************
//*
//* Determines the base order id of the ability mentioned above. This is
//* used to check if the caster is still channeling the ability
//*
//***************************************************************************
constant function C_OrderId takes nothing returns integer
return OrderId("absorb")
endfunction
//***************************************************************************
//*
//* Determines the animation by index when the caster is 'concentrating'.
//* If you change the caster model, you may need to test the animation
//* again until you found the correct one
//*
//***************************************************************************
constant function C_ConcentrateAnimationIndex takes nothing returns integer
return 11
endfunction
//***************************************************************************
//*
//* Determines the animation by index when the caster is 'moving'
//*
//***************************************************************************
constant function C_RunAnimationIndex takes nothing returns integer
return 2
endfunction
//***************************************************************************
//*
//* Determines the animation by index when the caster is going to swing his
//* hand when about to strike the target
//*
//***************************************************************************
constant function C_SwingAnimationIndex takes nothing returns integer
return 13
endfunction
//***************************************************************************
//*
//* Determines the minimum distance where the caster will start swinging
//* his hand to strike the target
//*
//***************************************************************************
constant function C_SwingDistance takes nothing returns real
return 400.00
endfunction
//***************************************************************************
//*
//* Determines the percent of animation speed when the caster is swinging
//*
//***************************************************************************
constant function C_SwingAnimationSpeed takes nothing returns real
return 200.00
endfunction
//***************************************************************************
//*
//* Determines the period time of the spell to 'update' things related to
//* the spell. Include moving the caster, spawning effects, counting timer,
//* damaging target, etc
//*
//***************************************************************************
constant function C_Interval takes nothing returns real
return 0.03125
endfunction
//***************************************************************************
//*
//* Determines the initial move speed of the caster after finish
//* 'concentrating'
//*
//***************************************************************************
constant function C_InitialSpeed takes nothing returns real
return 1.00
endfunction
//***************************************************************************
//*
//* Determines the move speed acceleration of the caster when moving toward
//* the target
//*
//***************************************************************************
constant function C_SpeedAcceleration takes nothing returns real
return 2.00
endfunction
//***************************************************************************
//*
//* Determines the maximum speed of the caster when moving toward target
//*
//***************************************************************************
constant function C_MaxSpeed takes nothing returns real
return 40.00
endfunction
//***************************************************************************
//*
//* Determines the minimum distance where the caster is considered as
//* 'has strike' the target
//*
//***************************************************************************
constant function C_MinDistance takes nothing returns real
return 150.00
endfunction
//***************************************************************************
//*
//* Determines the how long the target will dying after the strike
//*
//***************************************************************************
constant function C_DyingDuration takes nothing returns real
return 10.00
endfunction
//***************************************************************************
//*
//* Determines the effect attached on the caster
//*
//***************************************************************************
constant function C_HandSFXModel takes nothing returns string
return "war3mapImported\\ZapMissile.mdx"
endfunction
//***************************************************************************
//*
//* Determines the attachment point for the effect above
//*
//***************************************************************************
constant function C_HandSFXAttachment takes nothing returns string
return "hand right"
endfunction
//***************************************************************************
//*
//* Determines the effect attached on the caster. Different than the first
//* one, this effect spawns periodicly
//*
//***************************************************************************
constant function C_LoopingSFXModel takes nothing returns string
return "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl"
endfunction
//***************************************************************************
//*
//* Determines the attachment point for the effect above
//*
//***************************************************************************
constant function C_LoopingSFXAttachment takes nothing returns string
return "hand right"
endfunction
//***************************************************************************
//*
//* Determines the spawn interval of the effect above
//*
//***************************************************************************
constant function C_LoopingSFXInterval takes nothing returns real
return 0.09
endfunction
//***************************************************************************
//*
//* Determines the strike effect
//*
//***************************************************************************
constant function C_StrikeSFXModel takes nothing returns string
return "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
endfunction
//***************************************************************************
//*
//* Determines the attachment point for the effect above
//*
//***************************************************************************
constant function C_StrikeSFXAttachment takes nothing returns string
return "origin"
endfunction
//***************************************************************************
//*
//* Determines the dying effect attached on the target that spawns
//* periodicly
//*
//***************************************************************************
constant function C_DyingSFXModel takes nothing returns string
return "Objects\\Spawnmodels\\Other\\HumanBloodCinematicEffect\\HumanBloodCinematicEffect.mdl"
endfunction
//***************************************************************************
//*
//* Determines the attachment point for the effect above
//*
//***************************************************************************
constant function C_DyingSFXAttachment takes nothing returns string
return "chest"
endfunction
//***************************************************************************
//*
//* Determines the attack-type
//*
//***************************************************************************
constant function C_AttackType takes nothing returns attacktype
return ATTACK_TYPE_PIERCE
endfunction
//***************************************************************************
//*
//* Determines the damage-type
//*
//***************************************************************************
constant function C_DamageType takes nothing returns damagetype
return DAMAGE_TYPE_LIGHTNING
endfunction
//***************************************************************************
//*
//* Determines how long the caster will need to 'concentrate'
//*
//***************************************************************************
function C_ConcentrateDuration takes real level returns real
return 2.50 - (level * 0.50)
endfunction
//***************************************************************************
//*
//* Determines the strike damage
//*
//***************************************************************************
function C_StrikeDamage takes real level returns real
return level * 100.00 + 100.00
endfunction
//***************************************************************************
//*
//* Determines the total damage dealt to the target
//*
//***************************************************************************
function C_DyingTotalDamage takes real level returns real
return level * 50.00 + 150.00
endfunction
//***************************************************************************
//***************************************************************************
//**
//** END OF CONFIGURATION
//**
//***************************************************************************
//***************************************************************************
function C_Periodic takes nothing returns nothing
local real x
local real y
local real x2
local real y2
local real angle
local real dist
local integer index = 1
loop
exitwhen index > udg_C_MaxIndex
if (udg_C_Stage[index] == 1) then
if (not IsUnitType(udg_C_Target[index], UNIT_TYPE_DEAD) and udg_C_RealTimer[index] > 0) then
set udg_C_RealTimer2[index] = udg_C_RealTimer2[index] - C_Interval()
if (udg_C_RealTimer2[index] <= 0) then
call DestroyEffect(AddSpecialEffectTarget(C_DyingSFXModel(), udg_C_Target[index], C_DyingSFXAttachment()))
set udg_C_RealTimer2[index] = 1
endif
call UnitDamageTarget(udg_C_Caster[index], udg_C_Target[index], udg_C_DamagePerSecond[udg_C_Level[index]], true, false, C_AttackType(), C_DamageType(), null)
set udg_C_RealTimer[index] = udg_C_RealTimer[index] - C_Interval()
else
set udg_C_Stage[index] = 4
endif
elseif (udg_C_Stage[index] == 2) then
if (not IsUnitType(udg_C_Caster[index], UNIT_TYPE_DEAD) and not IsUnitType(udg_C_Target[index], UNIT_TYPE_DEAD)) then
if (GetUnitCurrentOrder(udg_C_Caster[index]) == C_OrderId()) then
set x = GetUnitX(udg_C_Caster[index])
set y = GetUnitY(udg_C_Caster[index])
set x2 = GetUnitX(udg_C_Target[index]) - x
set y2 = GetUnitY(udg_C_Target[index]) - y
set dist = x2 * x2 + y2 * y2
if (dist > udg_C_Saver[1]) then
if (udg_C_Swinged[index] == false) then
if (dist <= udg_C_Saver[2]) then
call SetUnitAnimationByIndex(udg_C_Caster[index], C_SwingAnimationIndex())
call SetUnitTimeScalePercent(udg_C_Caster[index], C_SwingAnimationSpeed())
set udg_C_Swinged[index] = true
else
call SetUnitAnimationByIndex(udg_C_Caster[index], C_RunAnimationIndex())
endif
endif
set angle = Atan2(y2, x2)
set x = x + udg_C_Speed[index] * Cos(angle)
set y = y + udg_C_Speed[index] * Sin(angle)
set udg_CP_Point = Location(x, y)
call TriggerExecute(gg_trg_Check_Walkability)
if (udg_CP_PointIsWalkable == true) then
call SetUnitX(udg_C_Caster[index], x)
call SetUnitY(udg_C_Caster[index], y)
call SetUnitFacing(udg_C_Caster[index], angle * bj_RADTODEG)
if (udg_C_Speed[index] < C_MaxSpeed()) then
set udg_C_Speed[index] = udg_C_Speed[index] + C_SpeedAcceleration()
else
set udg_C_Speed[index] = C_MaxSpeed()
endif
else
call DestroyEffect(udg_C_Model[index])
call IssueImmediateOrder(udg_C_Caster[index], "stop")
set udg_C_Stage[index] = 4
endif
else
call DestroyEffect(AddSpecialEffectTarget(C_StrikeSFXModel(), udg_C_Target[index], C_StrikeSFXAttachment()))
call UnitDamageTarget(udg_C_Caster[index], udg_C_Target[index], C_StrikeDamage(udg_C_Level[index]), true, false, C_AttackType(), C_DamageType(), null)
call DestroyEffect(udg_C_Model[index])
call SetUnitTimeScalePercent(udg_C_Caster[index], 100)
call IssueImmediateOrder(udg_C_Caster[index], "stop")
if (not IsUnitType(udg_C_Target[index], UNIT_TYPE_DEAD)) then
set udg_C_RealTimer[index] = C_DyingDuration()
set udg_C_RealTimer2[index] = 0
set udg_C_Stage[index] = 1
else
set udg_C_Stage[index] = 4
endif
endif
else
call DestroyEffect(udg_C_Model[index])
set udg_C_Stage[index] = 4
endif
else
call DestroyEffect(udg_C_Model[index])
call IssueImmediateOrder(udg_C_Caster[index], "stop")
set udg_C_Stage[index] = 4
endif
elseif (udg_C_Stage[index] == 3) then
if (not IsUnitType(udg_C_Caster[index], UNIT_TYPE_DEAD) and not IsUnitType(udg_C_Target[index], UNIT_TYPE_DEAD)) then
set x = GetUnitX(udg_C_Caster[index])
set y = GetUnitY(udg_C_Caster[index])
if (GetUnitCurrentOrder(udg_C_Caster[index]) == C_OrderId() and x == udg_C_CasterX[index] and y == udg_C_CasterY[index]) then
if (udg_C_RealTimer[index] > 0) then
set udg_C_RealTimer2[index] = udg_C_RealTimer2[index] - C_Interval()
if (udg_C_RealTimer2[index] <= 0) then
call DestroyEffect(AddSpecialEffectTarget(C_LoopingSFXModel(), udg_C_Caster[index], C_LoopingSFXAttachment()))
set udg_C_RealTimer2[index] = C_LoopingSFXInterval()
endif
set udg_C_RealTimer[index] = udg_C_RealTimer[index] - C_Interval()
else
set udg_C_Speed[index] = C_InitialSpeed()
set udg_C_Swinged[index] = false
set udg_C_Stage[index] = 2
endif
else
call DestroyEffect(udg_C_Model[index])
set udg_C_Stage[index] = 4
endif
else
call DestroyEffect(udg_C_Model[index])
call IssueImmediateOrder(udg_C_Caster[index], "stop")
set udg_C_Stage[index] = 4
endif
elseif (udg_C_Stage[index] == 4) then
set udg_C_Caster[index] = udg_C_Caster[udg_C_MaxIndex]
set udg_C_CasterX[index] = udg_C_CasterX[udg_C_MaxIndex]
set udg_C_CasterY[index] = udg_C_CasterY[udg_C_MaxIndex]
set udg_C_Level[index] = udg_C_Level[udg_C_MaxIndex]
set udg_C_Model[index] = udg_C_Model[udg_C_MaxIndex]
set udg_C_RealTimer[index] = udg_C_RealTimer[udg_C_MaxIndex]
set udg_C_RealTimer2[index] = udg_C_RealTimer2[udg_C_MaxIndex]
set udg_C_Speed[index] = udg_C_Speed[udg_C_MaxIndex]
set udg_C_Stage[index] = udg_C_Stage[udg_C_MaxIndex]
set udg_C_Swinged[index] = udg_C_Swinged[udg_C_MaxIndex]
set udg_C_Target[index] = udg_C_Target[udg_C_MaxIndex]
set index = index - 1
set udg_C_MaxIndex = udg_C_MaxIndex - 1
if (udg_C_MaxIndex == 0) then
call PauseTimer(udg_C_Timer)
endif
endif
set index = index + 1
endloop
endfunction
function C_Cast takes nothing returns boolean
local integer index
if (GetSpellAbilityId() == C_AbilityId()) then
set udg_C_Caster[0] = GetTriggerUnit()
if (udg_C_MaxIndex == 0) then
call TimerStart(udg_C_Timer, C_Interval(), true, function C_Periodic)
else
set index = 1
loop
exitwhen index > udg_C_MaxIndex
if (udg_C_Caster[index] == udg_C_Caster[0] and udg_C_Stage[index] != 1) then
call DestroyEffect(udg_C_Model[index])
set udg_C_Stage[index] = 4
endif
set index = index + 1
endloop
endif
set udg_C_MaxIndex = udg_C_MaxIndex + 1
set udg_C_Caster[udg_C_MaxIndex] = udg_C_Caster[0]
set udg_C_Target[udg_C_MaxIndex] = GetSpellTargetUnit()
set udg_C_Level[udg_C_MaxIndex] = GetUnitAbilityLevel(udg_C_Caster[udg_C_MaxIndex], C_AbilityId())
set udg_C_CasterX[udg_C_MaxIndex] = GetUnitX(udg_C_Caster[udg_C_MaxIndex])
set udg_C_CasterY[udg_C_MaxIndex] = GetUnitY(udg_C_Caster[udg_C_MaxIndex])
set udg_C_Model[udg_C_MaxIndex] = AddSpecialEffectTarget(C_HandSFXModel(), udg_C_Caster[udg_C_MaxIndex], C_HandSFXAttachment())
set udg_C_RealTimer[udg_C_MaxIndex] = C_ConcentrateDuration(udg_C_Level[udg_C_MaxIndex])
set udg_C_RealTimer2[udg_C_MaxIndex] = 0
call SetUnitAnimationByIndex(udg_C_Caster[udg_C_MaxIndex], C_ConcentrateAnimationIndex())
set udg_C_Stage[udg_C_MaxIndex] = 3
endif
return false
endfunction
//===========================================================================
function InitTrig_Chidori takes nothing returns nothing
set gg_trg_Chidori = CreateTrigger()
if (udg_C_Timer == null) then
set udg_C_Timer = CreateTimer()
endif
call TriggerRegisterAnyUnitEventBJ(gg_trg_Chidori, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(gg_trg_Chidori, Filter(function C_Cast))
set udg_C_Saver[1] = C_MinDistance() * C_MinDistance()
set udg_C_Saver[2] = C_SwingDistance() * C_SwingDistance()
set udg_C_DamagePerSecond[1] = C_DyingTotalDamage(1) * C_Interval()
set udg_C_DamagePerSecond[2] = C_DyingTotalDamage(2) * C_Interval()
set udg_C_DamagePerSecond[3] = C_DyingTotalDamage(3) * C_Interval()
endfunction