Name | Type | is_array | initial_value |
scope MythicalScroll initializer Init_MythicalScroll
//////////// START OF CONF PART ////////////
globals
private constant integer SPELL_PORTAL = 'A000'
private constant integer SPELL_TELEPORT = 'A001'
private constant real INTERVAL_PORTAL = 0.5
private constant string EFFECT_PORTAL_PATH = "Eldritch Scroll.mdx"
private constant real EFFECT_PORTAL_SIZE = 1
private constant real EFFECT_PORTAL_HEIGHT = 0
private constant real RADIUS = 300
private constant string EFFECT_SCROLL_PATH = "Boomer Scroll SD.mdl"
private constant real EFFECT_SCROLL_SIZE = 1
private constant real EFFECT_SCROLL_HEIGHT = 0
private constant string EFFECT_TELEPORT_START_PATH = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"
private constant string EFFECT_TELEPORT_ARRIVE_PATH = "Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl"
private constant real FLY_DURATION_SCROLL = 1
private constant real INTERVAL_SCROLL = 0.01
private constant string ERROR_MESSAGE_TEXT = "[Error] - The Portal does not exist anymore."
private constant string ERROR_MESSAGE_COLOR = "ff0000"
private group G = CreateGroup()
endglobals
private function getDurationMax takes real lvl returns real
return 7 + (2 * lvl)
endfunction
//////////// END OF CONF PART ////////////
private keyword Portal
private function randomRadian takes nothing returns real
return GetRandomReal(0, 6.283185)
endfunction
private function distancePoints takes real X, real Y, real X1, real Y1 returns real
return SquareRoot(((Y1-Y)*(Y1-Y))+((X1-X)*(X1-X)))
endfunction
private function createSfx takes string Path, real X, real Y, real A, real Scale, real Height returns effect
set bj_lastCreatedEffect = AddSpecialEffect(Path, X, Y)
call BlzSetSpecialEffectZ(bj_lastCreatedEffect, Height)
if Scale != 1 then
call BlzSetSpecialEffectScale(bj_lastCreatedEffect, Scale)
endif
call BlzSetSpecialEffectYaw(bj_lastCreatedEffect, A)
return bj_lastCreatedEffect
endfunction
private function effectPoint takes string Path, real X, real Y returns nothing
local effect sfx = AddSpecialEffect(Path, X, Y)
call DestroyEffect(sfx)
set sfx = null
endfunction
private function moveSfx takes effect Sfx, real X, real Y, real A returns nothing
call BlzSetSpecialEffectX(Sfx, X)
call BlzSetSpecialEffectY(Sfx, Y)
call BlzSetSpecialEffectYaw(Sfx, A)
endfunction
private function addSpell takes unit U, integer Id returns nothing
call UnitAddAbility(U, Id)
call UnitMakeAbilityPermanent(U, true, Id)
endfunction
private function removeSpell takes unit U, integer Id returns nothing
call UnitMakeAbilityPermanent(U, false, Id)
call UnitRemoveAbility(U, Id)
endfunction
private function colorTxt takes string Message, string ColorCode returns string
if ColorCode == "" or ColorCode == null then
return Message
else
return "|cff" + ColorCode + Message + "|r"
endif
endfunction
private function nullFilter takes nothing returns boolean
return true
endfunction
private struct Scroll
static Scroll array S
static integer ST = 0
static timer T = null
unit caster
real x
real y
real dx
real dy
real dist
real angle
real duration
effect sfx
player p
Portal pt
private method onDestroy takes nothing returns nothing
call DestroyEffect(.sfx)
set .caster = null
set .p = null
set .sfx = null
endmethod
private method scrollTeleport takes nothing returns nothing
local unit U2
local real X1
local real Y1
local real Dist
local real A
call GroupEnumUnitsInRange(G, .x, .y, RADIUS, Condition(function nullFilter))
loop
set U2 = FirstOfGroup(G)
exitwhen U2 == null
call GroupRemoveUnit(G, U2)
if IsUnitAlly(U2, .p) then
set X1 = GetUnitX(U2)
set Y1 = GetUnitY(U2)
set Dist = distancePoints(.x, .y, X1, Y1)
set A = Atan2(Y1-.y, X1-.x)
call effectPoint(EFFECT_TELEPORT_START_PATH, X1, Y1)
call SetUnitPosition(U2, (pt.x + (Cos(A) * Dist)), (pt.y + (Sin(A) * Dist)))
call effectPoint(EFFECT_TELEPORT_ARRIVE_PATH, GetUnitX(U2), GetUnitY(U2))
endif
endloop
endmethod
private method moveScroll takes nothing returns nothing
set .duration = .duration + INTERVAL_SCROLL
if .dist > 0 then
set .x = .x + .dx
set .y = .y + .dy
call moveSfx(.sfx, .x, .y, .angle)
endif
endmethod
static method update takes nothing returns nothing
local Scroll s
local integer I = 0
loop
set I = I + 1
set s = .S[I]
call s.moveScroll()
if s.duration >= FLY_DURATION_SCROLL then
call s.scrollTeleport()
call s.destroy()
set .S[I] = .S[.ST]
set .ST = .ST - 1
set I = I - 1
endif
exitwhen I >= .ST
endloop
if .ST <= 0 then
call PauseTimer(.T)
set .ST = 0
endif
endmethod
static method addScroll takes unit U, real X, real Y, real A, real Distance, player P, Portal PT returns nothing
local Scroll s = Scroll.allocate()
local real dist = Distance / FLY_DURATION_SCROLL * INTERVAL_SCROLL
set s.caster = U
set s.x = X
set s.y = Y
set s.dx = Cos(A) * dist
set s.dy = Sin(A) * dist
set s.dist = dist
set s.angle = A
set s.duration = 0
set s.sfx = createSfx(EFFECT_SCROLL_PATH, X, Y, A, EFFECT_SCROLL_SIZE, EFFECT_SCROLL_HEIGHT)
set s.p = P
set s.pt = PT
set .ST = .ST + 1
set .S[.ST] = s
if .ST == 1 then
call TimerStart(.T, INTERVAL_SCROLL, true, function Scroll.update)
endif
endmethod
endstruct
private struct Portal
static Portal array P
static integer PT = 0
static timer T = null
unit caster
real x
real y
player p
real duration
real durationMax
real lvl
effect sfx
boolean done
private method swapSpells takes boolean showTeleportSpell returns nothing
if showTeleportSpell then
call BlzUnitHideAbility(.caster, SPELL_PORTAL, showTeleportSpell)
call addSpell(.caster, SPELL_TELEPORT)
call SetUnitAbilityLevel(.caster, SPELL_TELEPORT, R2I(.lvl))
else
call removeSpell(.caster, SPELL_TELEPORT)
call BlzUnitHideAbility(.caster, SPELL_PORTAL, showTeleportSpell)
endif
endmethod
private method onDestroy takes nothing returns nothing
call .swapSpells(false)
set .done = true
call DestroyEffect(.sfx)
set .caster = null
set .sfx = null
set .p = null
endmethod
static method update takes nothing returns nothing
local Portal p
local integer I = 0
loop
set I = I + 1
set p = .P[I]
set p.duration = p.duration + INTERVAL_PORTAL
if p.duration >= p.durationMax then
call p.destroy()
set .P[I] = .P[.PT]
set .PT = .PT - 1
set I = I - 1
endif
exitwhen I >= .PT
endloop
if .PT <= 0 then
call PauseTimer(.T)
set .PT = 0
endif
endmethod
static method getByCaster takes unit U returns Portal
local Portal p
local Portal portalToReturn = 0
local integer I = 1
loop
exitwhen I > .PT
set p = .P[I]
if p.caster == U then
set I = .PT
set portalToReturn = p
endif
set I = I + 1
endloop
return portalToReturn
endmethod
static method addPortal takes unit U, real X, real Y, real lvl returns nothing
local Portal p
local boolean found = false
local integer I = 1
loop
exitwhen I > .PT
set p = .P[I]
if p.caster == U then
set I = .PT
set found = true
set p.duration = 0
set p.x = X
set p.y = Y
call BlzSetSpecialEffectX(p.sfx, X)
call BlzSetSpecialEffectY(p.sfx, Y)
if p.lvl != lvl then
set p.lvl = lvl
set p.durationMax = getDurationMax(lvl)
endif
endif
set I = I + 1
endloop
if not(found) then
set p = Portal.allocate()
set p.caster = U
set p.x = X
set p.y = Y
set p.p = GetOwningPlayer(U)
set p.duration = 0
set p.durationMax = getDurationMax(lvl)
set p.lvl = lvl
set p.sfx = createSfx(EFFECT_PORTAL_PATH, X, Y, randomRadian(), EFFECT_PORTAL_SIZE, EFFECT_SCROLL_HEIGHT)
call p.swapSpells(true)
set .PT = .PT + 1
set .P[.PT] = p
if .PT == 1 then
call TimerStart(.T, INTERVAL_PORTAL, true, function Portal.update)
endif
endif
endmethod
endstruct
function Trig_MythicalScrollTeleport_Conditions takes nothing returns boolean
return GetSpellAbilityId() == SPELL_TELEPORT
endfunction
function Trig_MythicalScrollTeleport_Actions takes nothing returns nothing
local unit U = GetTriggerUnit()
local real XCaster = GetUnitX(U)
local real YCaster = GetUnitY(U)
local real XTarget = GetSpellTargetX()
local real YTarget = GetSpellTargetY()
local player P = GetOwningPlayer(U)
local Portal PT = Portal.getByCaster(U)
local real A = Atan2(YTarget-YCaster, XTarget-XCaster)
local real distance = distancePoints(XCaster, YCaster, XTarget, YTarget)
if PT != 0 then
call Scroll.addScroll(U, XCaster, YCaster, A, distance, P, PT)
else
call DisplayTextToPlayer(P, 0, 0, colorTxt(ERROR_MESSAGE_TEXT, ERROR_MESSAGE_COLOR))
endif
set U = null
set P = null
endfunction
function Trig_MythicalScrollPortal_Conditions takes nothing returns boolean
return GetSpellAbilityId() == SPELL_PORTAL
endfunction
function Trig_MythicalScrollPortal_Actions takes nothing returns nothing
local unit U = GetTriggerUnit()
local real XTarget = GetSpellTargetX()
local real YTarget = GetSpellTargetY()
local real lvl = GetUnitAbilityLevel(U, GetSpellAbilityId())
call Portal.addPortal(U, XTarget, YTarget, lvl)
set U = null
endfunction
//===========================================================================
function Init_MythicalScroll takes nothing returns nothing
local trigger T = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( T, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( T, Condition( function Trig_MythicalScrollPortal_Conditions ) )
call TriggerAddAction( T, function Trig_MythicalScrollPortal_Actions )
set T = null
set T = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( T, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( T, Condition( function Trig_MythicalScrollTeleport_Conditions ) )
call TriggerAddAction( T, function Trig_MythicalScrollTeleport_Actions )
set T = null
set Scroll.T = CreateTimer()
set Portal.T = CreateTimer()
call Preload(EFFECT_TELEPORT_START_PATH)
call Preload(EFFECT_TELEPORT_ARRIVE_PATH)
call Preload(EFFECT_SCROLL_PATH)
call Preload(EFFECT_PORTAL_PATH)
endfunction
endscope