scope test initializer int
globals
//================================================================
//= ----- Object of Spells Ability ----- =
//================================================================
// 1. Spells ID
private constant integer SPELL_ID = 'A000'
// 2. Dummy ID and total dummy
private constant integer DUMMY = 'h000'
private constant integer MAX_DUMMY = 8
// 3. Effects on caster
private constant string EFFECT = "Abilities\\Spells\\Human\\Resurrect\\ResurrectCaster.mdl"
private constant string POINT_EFFECT = "origin"
private constant string EFFECT2 = "Abilities\\Spells\\Human\\Resurrect\\ResurrectTarget.mdl"
private constant string POINT_EFFECT2 = "origin"
// 4. Effect on target
private constant string EFFECT3 = "Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl"
private constant string POINT_EFFECT3 = "origin"
// 5. Damage of per dummy deal each target
// DAMAGE = INIT_DAMAGE + Level_Ability*PER_DAMAGE
private constant real INIT_DAMAGE = 10
private constant real PER_DAMAGE = 10
//----------------------------------------------------------------
private constant string INIT_SOUND = "Abilities\\Spells\\Human\\Defend\\DefendCaster.wav"
private constant string DUMMY_SOUND = "Abilities\\Weapons\\AvengerMissile\\DestroyerMissile.wav"
private constant integer BORN_TIME = 4
private constant integer MOVE_TIME = 16
private constant real AOE = 400
private constant real MAX_HEIGHT = 600
private constant real MAX_ANGLE = 3*bj_PI
private constant real RADIUS = 400
private constant real HEIGHT_TARGET = 50
//================================================================
private constant real PI_P2 = bj_PI/2
private constant real PI_2 = 2*bj_PI
private constant real AOE_P2 = AOE/2
private constant real AOE_P3 = AOE/3
private constant real AOE_5P6 = 5*AOE/6
private constant integer MOVE_TIME2 = 2*MOVE_TIME
private constant integer MOVE_TIME4 = 4*MOVE_TIME
private constant integer MOVE_TIME5 = 5*MOVE_TIME
private constant integer MOVE_TIME6 = 6*MOVE_TIME
private integer SOUND_VOLUME = 127
private constant real TICK_TIME = 0.03125
private boolean bool = true
private real array SIN1[MOVE_TIME]
private real array SIN2[MOVE_TIME]
private real array SIN3[MOVE_TIME2]
private real temp
endglobals
private struct data
unit caster
real xc
real yc
integer level
unit target
real xt
real yt
real zt
boolean fly
unit array dummy[MAX_DUMMY]
real array x[MAX_DUMMY]
real array y[MAX_DUMMY]
real array z[MAX_DUMMY]
real array facing[MAX_DUMMY]
integer array tick[MAX_DUMMY]
real array rand[MAX_DUMMY]
real distance
real angle
integer tack
integer i
integer max
real temp
real DAMAGE
endstruct
private function AddEvent takes trigger trig, playerunitevent whichEvent returns nothing
local integer index = 0
loop
call TriggerRegisterPlayerUnitEvent(trig, Player(index), whichEvent, null)
set index = index + 1
exitwhen index == bj_MAX_PLAYER_SLOTS
endloop
endfunction
private function PlaySoundEx takes unit u, string path returns nothing
local sound s = CreateSound(path, false, true, true, 12700, 12700, "DefaultEAXON")
call SetSoundVolume(s, SOUND_VOLUME)
set SOUND_VOLUME = 127
call SetSoundChannel(s, 5)
call SetSoundPitch(s, 1.00001)
call SetSoundDistances(s, 600, 10000)
call SetSoundDistanceCutoff(s, 3000)
call SetSoundConeAngles(s, 0, 0, 127)
call AttachSoundToUnit(s, u)
call StartSound(s)
if HaveSavedBoolean(ht, 0x906120, StringHash(path)) then
call KillSoundWhenDone(s)
else
call SaveBoolean(ht, 0x906120, StringHash(path), true)
endif
set s = null
endfunction
private function update takes nothing returns nothing
local data this = getRT()
set this.xc = GetUnitX(this.caster)
set this.yc = GetUnitY(this.caster)
set this.i = 1
loop
exitwhen this.i > this.max
exitwhen this.i > MAX_DUMMY
if this.tick[this.i] == BORN_TIME then
set this.max = this.max + 1
endif
if this.tick[this.i] == 0 then
// --- Create ---
set this.dummy[this.i] = CreateUnit(GetOwningPlayer(this.caster), DUMMY, this.xc, this.yc, 270)
call PlaySoundEx(this.caster, INIT_SOUND)
elseif this.tick[this.i] < MOVE_TIME then
// --- Jump 1 ---
set this.distance = AOE_P3 - SIN2[MOVE_TIME - this.tick[this.i]]*AOE_P3
set this.temp = this.xc + this.distance*Cos(this.facing[this.i])
call SetUnitX(this.dummy[this.i], this.temp)
set this.temp = this.yc + this.distance*Sin(this.facing[this.i])
call SetUnitY(this.dummy[this.i], this.temp)
set this.temp = SIN1[this.tick[this.i]]*AOE_P3
call SetUnitFlyHeight(this.dummy[this.i], this.temp, 0)
elseif this.tick[this.i] == MOVE_TIME then
// --- End jump 1 and initializer jump 2 ---
set this.x[this.i] = this.xc + AOE_P3*Cos(this.facing[this.i])
set this.y[this.i] = this.yc + AOE_P3*Sin(this.facing[this.i])
call SetUnitX(this.dummy[this.i], this.x[this.i])
call SetUnitY(this.dummy[this.i], this.y[this.i])
call SetUnitFlyHeight(this.dummy[this.i], 0, 0)
set this.facing[this.i] = this.facing[this.i] + bj_PI
elseif this.tick[this.i] < MOVE_TIME2 then
// --- Jump 2 ---
set this.tack = this.tick[this.i] - MOVE_TIME
set this.distance = SIN2[this.tack]*AOE_5P6
set this.temp = this.x[this.i] + this.distance*Cos(this.facing[this.i])
call SetUnitX(this.dummy[this.i], this.temp)
set this.temp = this.y[this.i] + this.distance*Sin(this.facing[this.i])
call SetUnitY(this.dummy[this.i], this.temp)
set this.temp = SIN1[this.tack]*AOE_5P6
call SetUnitFlyHeight(this.dummy[this.i], this.temp, 0)
elseif this.tick[this.i] == MOVE_TIME2 then
// --- End jump 2 and initializer fly dummy ---
set this.x[this.i] = this.x[this.i] + AOE_5P6*Cos(this.facing[this.i])
set this.y[this.i] = this.y[this.i] + AOE_5P6*Sin(this.facing[this.i])
call SetUnitX(this.dummy[this.i], this.x[this.i])
call SetUnitY(this.dummy[this.i], this.y[this.i])
call SetUnitFlyHeight(this.dummy[this.i], 0, 0)
set this.facing[this.i] = this.facing[this.i] + bj_PI
elseif this.tick[this.i] < MOVE_TIME4 then
// --- Fly dummy ---
set this.tack = this.tick[this.i] - MOVE_TIME2
set this.distance = SIN3[this.tack]*MAX_HEIGHT
set this.angle = SIN3[this.tack]*MAX_ANGLE
set this.temp = this.xc + AOE_P2*Cos(this.facing[this.i] - this.angle)
call SetUnitX(this.dummy[this.i], this.temp)
set this.temp = this.yc + AOE_P2*Sin(this.facing[this.i] - this.angle)
call SetUnitY(this.dummy[this.i], this.temp)
call SetUnitFlyHeight(this.dummy[this.i], this.distance, 0)
elseif this.tick[this.i] == MOVE_TIME4 then
// --- End fly dummy and initializer stand dummy ---
set this.x[this.i] = this.xc + AOE_P2*Cos(this.facing[this.i] - MAX_ANGLE)
set this.y[this.i] = this.yc + AOE_P2*Sin(this.facing[this.i] - MAX_ANGLE)
set this.z[this.i] = MAX_HEIGHT
set this.rand[this.i] = GetRandomInt(1, 360)*bj_PI/180
call SetUnitX(this.dummy[this.i], this.x[this.i])
call SetUnitY(this.dummy[this.i], this.y[this.i])
call SetUnitFlyHeight(this.dummy[this.i], MAX_HEIGHT, 0)
elseif this.tick[this.i] < MOVE_TIME5 then
// --- Stand dummy ---
set this.x[this.i] = this.xc + AOE_P2*Cos(this.facing[this.i] - MAX_ANGLE)
set this.y[this.i] = this.yc + AOE_P2*Sin(this.facing[this.i] - MAX_ANGLE)
call SetUnitX(this.dummy[this.i], this.x[this.i])
call SetUnitY(this.dummy[this.i], this.y[this.i])
elseif this.tick[this.i] == MOVE_TIME5 then
// --- End stand dummy and initializer fall dummy ---
set this.x[this.i] = this.xc + AOE_P2*Cos(this.facing[this.i] - MAX_ANGLE)
set this.y[this.i] = this.yc + AOE_P2*Sin(this.facing[this.i] - MAX_ANGLE)
call SetUnitX(this.dummy[this.i], this.x[this.i])
call SetUnitY(this.dummy[this.i], this.y[this.i])
call PlaySoundEx(this.dummy[this.i], DUMMY_SOUND)
elseif this.tick[this.i] < MOVE_TIME6 then
// --- Fall dummy ---
set this.tack = this.tick[this.i] - MOVE_TIME5
set this.xt = GetUnitX(this.target)
set this.yt = GetUnitY(this.target)
if this.fly then
set this.zt = GetUnitFlyHeight(this.target)
else
set this.zt = GetUnitFlyHeight(this.target) + HEIGHT_TARGET
endif
set this.distance = SIN2[this.tack]*SquareRoot((this.xt - this.x[this.i])*(this.xt - this.x[this.i]) + (this.yt - this.y[this.i])*(this.yt - this.y[this.i]))
set this.angle = Atan2(this.yt - this.y[this.i], this.xt - this.x[this.i])
set this.temp = this.x[this.i] + this.distance*Cos(this.angle)
set this.temp = this.temp + SIN1[this.tack]*RADIUS*Cos(this.rand[this.i])*Cos(this.angle - PI_P2)
call SetUnitX(this.dummy[this.i], this.temp)
set this.temp = this.y[this.i] + this.distance*Sin(this.angle)
set this.temp = this.temp + SIN1[this.tack]*RADIUS*Cos(this.rand[this.i])*Sin(this.angle - PI_P2)
call SetUnitY(this.dummy[this.i], this.temp)
set this.temp = this.z[this.i] + SIN2[this.tack]*(this.zt - this.z[this.i])
call SetUnitFlyHeight(this.dummy[this.i], this.temp, 0)
elseif this.tick[this.i] == MOVE_TIME6 then
// --- Damage target ---
call RemoveUnit(this.dummy[this.i])
if IsUnitEnemy(this.target, GetOwningPlayer(this.caster)) and GetUnitState(this.target, UNIT_STATE_LIFE) > 0 and not IsUnitType(this.target, UNIT_TYPE_STRUCTURE) then
call DestroyEffect(AddSpecialEffectTarget(EFFECT3, this.target, POINT_EFFECT3))
call UnitDamageTargetBJ(this.caster, this.target, this.DAMAGE, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
endif
set this.dummy[this.i] = null
if this.i == MAX_DUMMY then
set this.caster = null
set this.target = null
call breakRT()
call this.destroy()
return
endif
endif
set this.tick[this.i] = this.tick[this.i] + 1
set this.i = this.i + 1
endloop
endfunction
private function f takes nothing returns nothing
local real fa
local integer i = 1
local data this = data.create()
set this.caster = GetTriggerUnit()
set this.target = GetSpellTargetUnit()
set this.fly = IsUnitType(this.target, UNIT_TYPE_FLYING)
set this.level = GetUnitAbilityLevel(this.caster, SPELL_ID)
set this.DAMAGE = INIT_DAMAGE + this.level*PER_DAMAGE
set this.max = 1
set fa = GetUnitFacing(this.caster)
loop
exitwhen i > MAX_DUMMY
set this.tick[i] = 0
set this.facing[i] = fa + (PI_2*(i - 1))/MAX_DUMMY
set i = i + 1
endloop
if bool then
set i = 1
loop
exitwhen i > MOVE_TIME
set SIN1[i] = Sin((i*bj_PI)/MOVE_TIME)
set SIN2[i] = Sin((i*PI_P2)/MOVE_TIME)
set i = i + 1
endloop
set i = 1
loop
exitwhen i > MOVE_TIME2
set SIN3[i] = Sin((i*PI_P2)/MOVE_TIME2)
set i = i + 1
endloop
set bool = false
endif
call DestroyEffect(AddSpecialEffectTarget(EFFECT, this.caster, POINT_EFFECT))
call DestroyEffect(AddSpecialEffectTarget(EFFECT2, this.caster, POINT_EFFECT2))
call addRT(this, TICK_TIME, true, function update)
endfunction
private function c takes nothing returns boolean
return GetSpellAbilityId() == SPELL_ID
endfunction
//===========================================================================
private function int takes nothing returns nothing
local trigger t = CreateTrigger()
call AddEvent(t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition(t, Condition( function c ) )
call TriggerAddAction(t, function f )
endfunction
endscope