Moderator
M
Moderator
00:27, 31st Dec 2009
TriggerHappy:
You still need to use a global group. But whatever.
TriggerHappy:
You still need to use a global group. But whatever.
Demon SlashAfter summoning a demon, supporting him with power, the hero slashes through numerous enemys dealing aoe damage.
If the hero hits an obstacle he stops.
library DemonSlash requires RegisterPlayerUnitEvent, T32
// Demon Slash by The_Witcher
// The hero slashes through numerous enemys dealing aoe damage.
// When the hero crashes into an obstacle he stops.
//
// well not much to say look through/edit the setup part for your wishes
//
// The SETUP part
globals
// the rawcode of the ghost/demon appearing behind the caster when channeling
private constant integer DEMON_DUMMY_ID = 'h000'
// the rawcode and the order string of the Demon Slash ability
private constant integer ABILITY_ID = 'A000'
private constant string ORDER_STRING = "absorb"
// the size the dummy will be when fully grown (2 = 200%)
private constant real MAX_SIZE = 2
//the effect created when a unit is hit
private constant string BLOOD_EFFECT = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl"
//the effect created on the weapon of the caster
private constant string WEAPON_EFFECT = "Abilities\\Weapons\\ZigguratMissile\\ZigguratMissile.mdl"
//the effect created on the body of the caster
private constant string BODY_EFFECT = "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilMissile.mdl"
//the effect created when the dummy disappears cause of abort
private constant string ABORT_EFFECT = "Abilities\\Spells\\Undead\\CarrionSwarm\\CarrionSwarmDamage.mdl"
endglobals
private function GetDamage takes integer level returns real
return 120.00 + 50 * (level - 1) //120 on level 1, 170 level 2, 220 level 3, ...
endfunction
private function GetAOE takes integer level returns real
return 100.00 + 20 * level //120 on level 1, 140 level 2, 160 level 3, ...
endfunction
private function GetSlashDistance takes integer level returns real
return 500.0 + 100 * level //600 on level 1, 700 level 2, 800 level 3, ...
endfunction
private function GetSlashSpeed takes integer level returns real
return 700.0 + 100 * level //800 on level 1, 900 level 2, 1000 level 3, ...
endfunction
private function GetChannelTime takes integer level returns real
return 4.00 - level / 2 //3, 5 on level 1, 3 level 2, 2, 5 level 3, ...
endfunction
//==============================================================================
//========================= SETUP END ======================================
//==============================================================================
private struct spell
static group g
static item ite
static unit Temp
static boolexpr BoolExpr
unit u
unit dummy
real v
real d
real vx
real vy
real phase
real temp
integer level
effect bodyFX
effect weaponFX
group damaged
method IsCoordPathable takes real x, real y returns boolean
local real xx
local real yy
call SetItemVisible(.ite, true)
call SetItemPosition(.ite, x, y)
set xx = GetItemX( .ite ) - x
set yy = GetItemY( .ite ) - y
call SetItemVisible(.ite, false)
if xx < 1 and xx > -1 and yy < 1 and yy > -1 then
return true
endif
return false
endmethod
method periodic takes nothing returns nothing
local unit k = null
if .phase == 0 then // phase 1
if GetUnitCurrentOrder(.u) == OrderId(ORDER_STRING) then
call SetUnitVertexColor(.dummy, 255, 255, 255, R2I(.temp / 100 * 255))
call SetUnitScalePercent(.dummy, .temp * MAX_SIZE, .temp * MAX_SIZE, .temp * MAX_SIZE)
set .temp = .temp + 100 / GetChannelTime(.level) * T32_PERIOD
if .temp >= 100 then
set .phase = 1
set .temp = 0
set .weaponFX = AddSpecialEffectTarget(WEAPON_EFFECT, .u, "weapon")
set .bodyFX = AddSpecialEffectTarget(BODY_EFFECT, .u, "chest")
call IssueImmediateOrder(.u,"stop")
call PauseUnit(.u, true)
call SetUnitInvulnerable(.u, true)
call SetUnitAnimation(.u, "attack")
call SetUnitAnimation(.dummy, "attack")
call QueueUnitAnimation(.dummy,"stand")
endif
else
call DestroyEffect(AddSpecialEffect(ABORT_EFFECT, GetUnitX(.dummy), GetUnitY(.dummy)))
call RemoveUnit(.dummy)
call DestroyGroup(.damaged)
call .stopPeriodic()
call .destroy()
endif
else // phase 2
call SetUnitVertexColor(.dummy, 255, 255, 255, R2I((100 - .temp) / 100 * 255))
set .temp = .temp + 400 / GetChannelTime(.level) * T32_PERIOD
if .d > 0 and IsCoordPathable(GetUnitX(.u) + .vx, GetUnitY(.u) + .vy) then
call SetUnitX(.u, GetUnitX(.u) + .vx )
call SetUnitY(.u, GetUnitY(.u) + .vy )
set .d = .d - .v
set .Temp = .u
call GroupEnumUnitsInRange(.g, GetUnitX(.u), GetUnitY(.u), GetAOE(.level), .BoolExpr)
loop
set k = FirstOfGroup(.g)
exitwhen k == null
call GroupRemoveUnit(.g, k)
if not IsUnitInGroup(k, .damaged) then
call GroupAddUnit(.damaged, k)
call UnitDamageTarget( .u, k, GetDamage(.level), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT, k, "chest"))
endif
endloop
else
call PauseUnit(.u, false)
call SetUnitAnimation(.u, "stand")
call SetUnitInvulnerable(.u, false)
call DestroyEffect(.weaponFX)
call DestroyEffect(.bodyFX)
call RemoveUnit(.dummy)
call DestroyGroup(.damaged)
call .stopPeriodic()
call .destroy()
endif
endif
endmethod
implement T32x
private static method create takes unit caster, real tx, real ty returns spell
local spell this = spell.allocate()
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local real r = Atan2(ty - y, tx - x)
set .u = caster
set .level = GetUnitAbilityLevel(.u, ABILITY_ID)
set .v = GetSlashSpeed(.level) * T32_PERIOD
set .vx = .v * Cos(r)
set .vy = .v * Sin(r)
set x = x + 200 * Cos(r - bj_PI)
set y = y + 200 * Sin(r - bj_PI)
set .dummy = CreateUnit(GetOwningPlayer(caster), DEMON_DUMMY_ID, x, y, r * bj_RADTODEG)
call PauseUnit(.dummy, true)
call SetUnitVertexColor(.dummy, 255, 255, 255, 0)
set .phase = 0
set .temp = 0
set .d = GetSlashDistance(.level)
set .damaged = CreateGroup()
call .startPeriodic()
return this
endmethod
private static method cast takes nothing returns nothing
if GetSpellAbilityId() == ABILITY_ID then
call spell.create(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY())
endif
endmethod
private static method AllyFilter takes nothing returns boolean
return ( IsUnitAlly(GetFilterUnit(), GetOwningPlayer(.Temp)) == false ) and not (IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD) or GetUnitTypeId(GetFilterUnit()) == 0 )
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent( EVENT_PLAYER_UNIT_SPELL_CAST, function spell.cast )
set .BoolExpr = Condition(function spell.AllyFilter)
set .ite = CreateItem( 'wolg', 0, 0 )
call SetItemVisible(.ite, false)
set .g = CreateGroup()
endmethod
endstruct
endlibrary
//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com