Moderator
M
Moderator
07:51, 14th Apr 2010
TriggerHappy:
Coding was fine, so was the spell.
TriggerHappy:
Coding was fine, so was the spell.
Crow Attack
Crows start flying out of the caster and the caster dissapears. Then these crows start flying into the target location. When they arrive, the crows should start flying into the center of the targeted point, and the caster reappears.
library CrowAttack requires TimerUtils, SimError, xefx, xedamage, optional BoundSentinel
//-----------------------------------------------------------------------------------------------
// Crow Attack v1.00 by scorpion182
// requires: TimerUtils, SimError, xe, BoundSentinel by vexorian
//
//
//
//
//-----------------------------------------------------------------------------------------------
//-----------------------CALIBRATION SECTION-----------------------------------------------------
globals
private constant integer SPELL_ID = 'A000' // spell rawcode
private constant real CROW_SCALE = 1. //crow scaling value
private constant string CROW_PATH = "units\\critters\\Vulture\\Vulture.mdl" //crow path
private constant string CASTER_ART = "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"
private constant integer RED = 0 //coloring in RGB
private constant integer GREEN = 0
private constant integer BLUE = 0
private constant integer ALPHA = 255
private constant real CASTING_TIME = 1. //spell casting time
private constant integer MAX_CROW = 25 //maximum crow instance
private constant real FINISH_DIST = 80. //finish point min distance
private constant real MIN_DIST = 300. //minimum casting distance
private constant real CROW_H = 100. //crow movement height
private constant real SPEED = 600. * XE_ANIMATION_PERIOD //crow movement speed
private constant string ERROR_MSG = "Inside Minimum Range." //error message
private constant string DAMAGE_FX = "" //effect on-damage, because it's used xe_animation_period (0.025) it would be lag
private constant string DAMAGE_ATTCH = "origin" //damage effect attachment point
endglobals
private constant function GetCrowCount takes integer lvl returns integer
return 12 + lvl * 0 //how many crows?
endfunction
private constant function GetCollision takes integer lvl returns real
return 125. + lvl * 0 //crow collision size to give damage
endfunction
private constant function GetAoE takes integer lvl returns real
return 200. + lvl * 0 //crow aoe summon
endfunction
private constant function GetDamage takes integer lvl returns real
return 10. + lvl * 0 //does 10 damage per second each crow
endfunction
//damage filter
private function DamageOptions takes xedamage spellDamage returns nothing
set spellDamage.dtype = DAMAGE_TYPE_UNIVERSAL
set spellDamage.atype = ATTACK_TYPE_NORMAL
set spellDamage.exception = UNIT_TYPE_STRUCTURE //don't damage building
set spellDamage.visibleOnly = true //only damage visible unit
set spellDamage.damageAllies = false //damage allies if true
set spellDamage.damageTrees = true //damage destructables?
endfunction
//-----------------------END OF CALIBRATION SECTION----------------------------------------------
globals
private xedamage xed
endglobals
private struct data
unit caster
timer t
integer lvl
integer alpha = 255 //caster alpha
integer alph = 255 //crow alpha
real cx
real cy
real tx
real ty
real dur_f
real alpha_dec = 100. / (CASTING_TIME/XE_ANIMATION_PERIOD) //100%/time
xefx array fx [MAX_CROW]
real array distdone [MAX_CROW]
real array distance [MAX_CROW]
integer array status [MAX_CROW]
real array ang [MAX_CROW]
integer crow_count = 0
boolean finish = false
boolean start_create = false
real angle
static method create takes unit c, real cx, real cy, real tx, real ty returns thistype
local thistype this = thistype.allocate()
set .caster = c
set .tx = tx
set .ty = ty
set .cx = cx
set .cy = cy
set .angle=Atan2(ty - cy, tx - cx)
set .lvl = GetUnitAbilityLevel(c, SPELL_ID)
set .t = NewTimer()
call PauseUnit(c, true)
call SetUnitInvulnerable(c, true)
return this
endmethod
private method onDestroy takes nothing returns nothing
local integer i = 0
call DestroyEffect(AddSpecialEffect(CASTER_ART, .tx, .ty))
loop
exitwhen i == GetCrowCount(.lvl)
call .fx[i].hiddenDestroy()
set i = i + 1
endloop
call ReleaseTimer(.t)
call PauseUnit(.caster, false)
call SetUnitInvulnerable(.caster, false)
endmethod
static method onLoop takes nothing returns nothing
local thistype this = thistype (GetTimerData(GetExpiredTimer()))
local integer i = 0
local real a
local real dis
local real x
local real y
local real dx
local real dy
if not .finish then
if .alpha>0 then
set .alpha = .alpha - PercentTo255(.alpha_dec)
call SetUnitVertexColor(.caster, 255, 255, 255, .alpha)
else
if not .start_create then
set .start_create = true
call DestroyEffect(AddSpecialEffect(CASTER_ART, .cx, .cy))
loop
exitwhen i == GetCrowCount(.lvl)
set a = GetRandomReal(0, 2 * bj_PI)
set dis = GetRandomReal(1, GetAoE(.lvl))
set x = cx + dis * Cos (a)
set y = cy + dis * Sin (a)
set .fx[i] = xefx.create(x, y, .angle)
set .fx[i].fxpath = CROW_PATH
set .fx[i].scale = CROW_SCALE
set .fx[i].z = CROW_H
call .fx[i].recolor(RED, GREEN, BLUE, ALPHA)
set dx = tx - .fx[i].x
set dy = ty - .fx[i].y
set .distance[i] = SquareRoot(dx * dx + dy * dy)
set .distdone[i] = 0.
set .status[i] = 1
set i = i +1
endloop
endif
if .crow_count != GetCrowCount(.lvl) then
set i = 0
loop
exitwhen i == GetCrowCount(.lvl)
if .status[i] != 0 then
if .distdone[i] < .distance[i] then
set .distdone[i]=.distdone[i] + SPEED
set .ang[i] = Atan2(ty - .fx[i].y, tx - .fx[i].x)
set .fx[i].x = .fx[i].x + SPEED * Cos(.ang[i])
set .fx[i].y = .fx[i].y + SPEED * Sin(.ang[i])
call xed.damageAOE(.caster,.fx[i].x, .fx[i].y, GetCollision(.lvl), GetDamage(.lvl) * XE_ANIMATION_PERIOD)
else
set .status[i] = 0
set .crow_count = .crow_count + 1
endif
endif
set i = i + 1
endloop
else
set .finish = true
call SetUnitX(.caster, .tx)
call SetUnitY(.caster, .ty)
endif
endif
else
if .alpha <= 255 then
set .alpha = .alpha + PercentTo255(.alpha_dec)
set .alph = .alph - PercentTo255(.alpha_dec)
call SetUnitVertexColor(.caster, 255, 255, 255, .alpha)
set i = 0
loop
exitwhen i == GetCrowCount(.lvl)
call .fx[i].recolor(RED, GREEN, BLUE, .alph)
set i = i + 1
endloop
else
call .destroy()
endif
endif
endmethod
static method SpellEffect takes nothing returns boolean
local thistype this
if GetSpellAbilityId() == SPELL_ID then
set this = thistype.create(GetTriggerUnit(), GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), GetSpellTargetX(), GetSpellTargetY())
call SetTimerData(.t, this)
call TimerStart(.t, XE_ANIMATION_PERIOD, true, function thistype.onLoop)
endif
return false
endmethod
static method CheckMinDistance takes nothing returns boolean
local unit u = GetTriggerUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real dx = x - GetSpellTargetX()
local real dy = y - GetSpellTargetY()
if (GetSpellAbilityId() == SPELL_ID and dx * dx + dy * dy<MIN_DIST * MIN_DIST) then
call SimError(GetOwningPlayer(u), ERROR_MSG)
call PauseUnit(u, true)
call IssueImmediateOrder(u, "stop")
call PauseUnit(u, false)
endif
set u = null
return false
endmethod
static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function thistype.SpellEffect))
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_CHANNEL)
call TriggerAddCondition(t, Condition(function thistype.CheckMinDistance))
//init xedamage
set xed=xedamage.create()
call DamageOptions(xed)
call xed.useSpecialEffect(DAMAGE_FX,DAMAGE_ATTCH)
endmethod
endstruct
endlibrary