Moderator
M
Moderator
1 Dec 2011
Bribe: Looks pretty solid. This was the winning entry for the Zephyr Illusion contest.
Bribe: Looks pretty solid. This was the winning entry for the Zephyr Illusion contest.
Water Image
Creates number of illusions of the Hero from the water splash to confuse the enemy.
Level 1 - Creates 8 illusions, they deal 15% damage and take 500% damage.
Level 2 - Creates 9 illusions, they deal 18% damage and take 400% damage.
Level 3 - Creates 10 illusions, they deal 21% damage and take 300% damage.
library WaterImage requires xefx, xecast, SpellEffectEvent, T32, SimError optional BoundSentinel
//*------------------------------------------------------------------------------------------
//* _________________________________________________________________________________________
//* water image - v1.01d
//* by scorpion182
//* _________________________________________________________________________________________
//* Requirements:
//*
//* . JassHelper http://www.wc3c.net/
//* . T32 http://www.thehelper.net/
//* . bound sentinel (optional), xe, SimError by Vexorian http://www.wc3c.net/
//* . SpellEffectEvent by Bribe
//* . RegisterPlayerUnitEvent by Magtheridon96
//*------------------------------------------------------------------------------------------
//*-------------CALIBRATION SECTION----------------------------------------------------------
globals
// spell rawcode
private constant integer SPELL_ID = 'A000'
//dummy spell id
private constant integer DUMMY_SPELL_ID = 'A001'
//dummy order id
private constant integer DUMMY_ORDER_ID = 852274
//missile fx path
private constant string MISSILE_FX = "Abilities\\Weapons\\WaterElementalMissile\\WaterElementalMissile.mdl"
//splash fx path
private constant string SPLASH_FX = "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl"
//max bounce
private constant integer MAX_BOUNCE = 5
private constant integer MAX_INSTANCE_MISSILE = 30
//missile speed
private constant real SPEED = 300.
//maximum bounce height
private constant real MAX_HEIGHT = 100.
//missile scale
private constant real MISSILE_SCALE = 1.0
//distance increment
private constant real DISTANCE_INC = SPEED * T32_PERIOD
//error message
private constant string ERROR_MSG = "Another instance is running for this caster."
private constant boolean PRELOAD_FX = true
endglobals
//image count
private constant function GetImageCount takes integer lvl returns integer
return (lvl * 1) + 7
endfunction
//spell area of effect
private constant function GetAoE takes integer lvl returns real
return (lvl * 0) + 500.
endfunction
//*------------------------------------------------------------------------------------------
//*-----------END OF CALIBRATION-------------------------------------------------------------
globals
private xecast cast
private Table activeTable
endglobals
//Parabolic Function by Moyack and Spec
private function ParabolaZ takes real h, real d, real x returns real
return (4 * h / d) * (d - x) * (x / d)
endfunction
globals
private constant real A = 2 * bj_PI
endglobals
private struct data
integer total //image count
integer lvl //level of ability when it cast
real x //x coord of spell target
real y //y coord of spell target
unit caster //caster
unit array illusion[MAX_INSTANCE_MISSILE]
xefx array fx[MAX_INSTANCE_MISSILE]
real array pos[MAX_INSTANCE_MISSILE]
real array distance[MAX_INSTANCE_MISSILE]
integer array n_bounce[MAX_INSTANCE_MISSILE]
real max_h = MAX_HEIGHT
real max_dist = 0
integer counter = 0
static thistype temp = 0
static method create takes unit c, real dis, integer count, integer lvl returns thistype
local data this = thistype.allocate()
local integer i = 0
if (GetLocalPlayer() == GetOwningPlayer(c)) then
call SelectUnit(c, true)
endif
call DestroyEffect(AddSpecialEffect(SPLASH_FX, .x, .y))
set .total = count
set .caster = c
set .lvl = lvl
set .x = GetUnitX(c)
set .y = GetUnitY(c)
set .max_dist = dis
loop
exitwhen i ==.total
set .fx[i] = xefx.create(x, y, i*A/.total)
set .fx[i].fxpath = MISSILE_FX
set .fx[i].scale = MISSILE_SCALE
set .distance[i] = dis
set .pos[i] = dis
set i = i + 1
endloop
return this
endmethod
private method destroy takes nothing returns nothing
local integer i = 0
local integer shuffle = GetRandomInt(0, .total - 1)
set temp = this
loop
exitwhen i ==.total
set cast.level = .lvl
set cast.owningplayer = GetOwningPlayer(.caster)
call cast.castOnTarget(.caster)
call DestroyEffect(AddSpecialEffect(SPLASH_FX, .fx[i].x, .fx[i].y))
call SetUnitX(.illusion[i], .fx[i].x)
call SetUnitY(.illusion[i], .fx[i].y)
call SetUnitFacing(.illusion[i], (.fx[i].xyangle * bj_RADTODEG) - 180.)
if (GetLocalPlayer() == GetOwningPlayer(.illusion[i])) then
call SelectUnit(.illusion[i], true)
endif
//shuffle the caster with the image
if i == shuffle then
call SetUnitX(.caster, GetUnitX(.illusion[i]))
call SetUnitY(.caster, GetUnitY(.illusion[i]))
call SetUnitFacing(.caster, (.fx[i].xyangle * bj_RADTODEG) - 180.)
call RemoveUnit(.illusion[i])
endif
call .fx[i].destroy()
set i = i + 1
endloop
set activeTable[GetHandleId(.caster)] = 0
endmethod
method periodic takes nothing returns nothing
local real x
local real y
local real dx
local real dy
local integer i = 0
loop
exitwhen i ==.total
if (.pos[i] > 0) then
set .fx[i].x =.fx[i].x + DISTANCE_INC * Cos(.fx[i].xyangle)
set .fx[i].y =.fx[i].y + DISTANCE_INC * Sin(.fx[i].xyangle)
set .pos[i] = .pos[i] - DISTANCE_INC
set .fx[i].z = ParabolaZ(.max_h, .distance[i], .pos[i])
else
if .n_bounce[i] <= MAX_BOUNCE then
set .n_bounce[i] = .n_bounce[i] + 1
set x = .fx[i].x + .max_dist * Cos(.fx[i].xyangle)
set y = .fx[i].y + .max_dist * Sin(.fx[i].xyangle)
set dx = x - .fx[i].x
set dy = y - .fx[i].y
set .distance[i] = SquareRoot(dx * dx + dy * dy)
set .pos[i] = .distance[i]
else
call .stopPeriodic()
call .destroy()
exitwhen true
endif
endif
set i = i + 1
endloop
endmethod
implement T32x
static method spellEffect takes nothing returns nothing
local thistype this
local unit c = GetTriggerUnit()
local integer lvl = GetUnitAbilityLevel(c, SPELL_ID)
if activeTable[GetHandleId(c)] == 0 then
set this = thistype.create(c, GetAoE(lvl) / MAX_BOUNCE, GetImageCount(lvl), lvl)
set activeTable[GetHandleId(c)] = this
call .startPeriodic()
else
call SimError(GetOwningPlayer(c), ERROR_MSG)
endif
set c = null
endmethod
static method illusionInit takes nothing returns nothing
local unit s = GetSummonedUnit()
if temp != 0 then
set temp.illusion[temp.counter] = s
set temp.counter = temp.counter + 1
endif
set s = null
endmethod
static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_ID, function thistype.spellEffect)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SUMMON, function thistype.illusionInit)
//xe cast init
set cast = xecast.create()
set cast.abilityid = DUMMY_SPELL_ID
set cast.orderid = DUMMY_ORDER_ID
//table
set activeTable = Table.create()
//preload fx and ability
static if PRELOAD_FX then
set bj_lastCreatedUnit = CreateUnit(Player(15), XE_DUMMY_UNITID, 0, 0, 0)
call UnitAddAbility(bj_lastCreatedUnit, DUMMY_SPELL_ID)
call RemoveUnit(bj_lastCreatedUnit)
call Preload(MISSILE_FX)
call Preload(SPLASH_FX)
endif
endmethod
endstruct
endlibrary