Name | Type | is_array | initial_value |
LichKing | unit | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
// ========================================================================================
// Spell: Shimmering Portal
// Created: July 4 2009 by Dark Dragon
// Modified: July 19 2009 by Dark Dragon
//
// Other: Converted Frozen Throne portal from campaign
// Credits: (Blizzard)
//
// *** Installation Instructions ***
//
// *** This instructions are only if you dont want to use externals ***
// *** If you dont know what they are then that means you will use them ***
// *** Just skip this part and read 'Readme' above in Portal category ***
//
// Requires: Jass NewGen Pack or better to say JassHelper to compile! Compiled with JH (0.9.G.3) and WC 1.24 (Beta)
//
// - 1. Go to object editor (F6) hotkey and go to abilities section tab.
// - 2. Below there find spell Shimmering Portal and right click, select copy.
// - 3. Copy unit 'Portal' from units tab. Copy this trigger
// - 4. Since you copied all now use hotkey (Ctrl + O) to open your map or click on File -> Open Map... and select your map
// - 5. Your map will load, when done go to Object Editor, Abilities tab and press hotkey (Ctrl + V) or click on any ability then Right click and select paste, when done you should see your portal spell pasted. Now go to Trigger Editor (Here) of course in your map and click any of your categories or triggers and right click on it, press paste your code (triggers) should appear soon.
// - 6. Press on floppy icon to save your map or press (Ctrl + S)
// - 7. If you are given any of jass errors that means you are most likely not using NGWE Editor! You are requied to use JNGP Editor (Check spells description at hiveworkshop.com) there i pasted the link to Jass NewGen Pack!
// - 8. Check this code below (user setup part) and edit it as you want. You will see function GetHandleId below just after globals remove that novjass and endnovjass lines
// - 9. Give Shimmering Portal to your unit and enjoy!
//
// ~Dark Dragon
// ========================================================================================
// ---------------------------------------------------------------------------------------
// *** You can remove this lines after first time you saved your map, but not needed ***
// ---------------------------------------------------------------------------------------
// *** Shimmering portal main library ***
library ShimmeringPortal initializer Init
// ===========================================================================
// *** User setup is below here ***
// ===========================================================================
globals
// *** Spells rawcode ***
// Default: SPrt
private constant integer ABILPORT_RAWCODE = 'SPrt'
// *** Portal (unit) rawcode ***
// Default: port
private constant integer PORTAL_RAWCODE = 'port'
// *** Model file on enter ***
// Default: Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl
private constant string EFFECT_ON_ENTER = "Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl"
// *** Model file on exit ***
// Default: Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl
private constant string EFFECT_ON_EXIT = "Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl"
// *** Sound file on birth ***
private constant string SOUND_BIRTH = "Sound\\Ambient\\DoodadEffects\\ShimmeringPortalBirth.wav"
// *** Sound file on death ***
private constant string SOUND_DEATH = "Sound\\Ambient\\DoodadEffects\\ShimmeringPortalDeath.wav"
// *** Sound file on enter ***
private constant string SOUND_ENTER = "Sound\\Ambient\\DoodadEffects\\ShimmeringPortalEnterence.wav"
// *** How far away first portal is created from caster position ***
// Default: 200
private constant real PORT_OFFSET = 200.
// *** Portal birth animation length ***
// Default: 6
private constant real PORTAL_BIRTH_TIME = 6.
// *** Portal death animation length ***
// Default: 5.77
private constant real PORTAL_DEATH_TIME = 5.77
// *** Portals width ***
// Default: 380
private constant real PORTAL_WIDTH = 380.
// *** Portals height ***
// Default: 120
private constant real PORTAL_HEIGHT = 120.
// *** Visibility AoE ***
// Default: 512
private constant real FOG_OF_WAR_AREA = 512.
// *** Should flying units be able to pass through portal ***
// Default: false
private constant boolean ALLOW_FLYING_UNITS = false
// *** Do pan camera to unit whihc is teleported? ***
// Default: true
private constant boolean DO_PAN_CAMERA = true
// *** This is order offset in coordinates ***
// *** When unit is teleported how much he will walk ***
// Default: 200
private constant real ORDER_OFFSET = 200.
// *** How much time must pass until same unit can be teleported again ***
// Default: 3
private constant real PORT_TIMEOUT = 3.
// *** Do not edit this vars here edit them below ***
// {
private real array PortalChannelDuration[8191]
private real array PortalDuration[8191]
// }
endglobals
// ----------------------------------------------------
// *** User Level setup ***
private function Setup takes nothing returns nothing
// *** Max level of spell ***
//! set MaxLevel = 3
// *** Portal channel duration per level ***
// Default: 6, 5.7, 5.4
set PortalChannelDuration[1] = 6.0
set PortalChannelDuration[2] = 5.7
set PortalChannelDuration[3] = 5.4
// *** Portal duration per level ***
// Default: 20, 25, 35
set PortalDuration[1] = 20.
set PortalDuration[2] = 25.
set PortalDuration[3] = 35.
endfunction
// ==============================================================================================
// *** DO NOT EDIT BELOW UNLESS YOU KNOW JASS ***
// ==============================================================================================
// *** Keywords ***
private keyword ConvRect
// *** Portal globals ***
globals
private constant real PI_HALF = 1.5708
private constant real TIMER_DELAY = 0.05
// *** Data on caster ***
private integer array SpellPort [8191]
// *** Main timer ***
private timer Tim = null
// *** Code port ***
private code PortAll = null
// *** Checks is unit ported ***
private boolean array Ported[8191]
// *** Timers data ***
private integer array TimerData[8191]
endglobals
// *** Structs data ***
private struct portal
// *** Members ***
unit array port[2]
fogmodifier array fg[2]
sound array snd[2]
rect array rct[2]
real array x[2]
real array y[2]
integer i
filterfunc filt
group grp
real rad
real dur
integer lvl
// *** Portals instances ***
static portal array Port[8191]
// *** N Portals ***
static integer NPorts = 0
// *** temp portal ***
static portal Temp = 0
// *** Constr ***
static method create takes unit u, location l, integer lvl returns portal
local portal this = portal.allocate()
local real x1 = GetUnitX(u)
local real y1 = GetUnitY(u)
local real x2 = GetLocationX(l)
local real y2 = GetLocationY(l)
local real rad = Atan2(y2-y1, x2-x1)
local real dx = Cos(rad)
local real dy = Sin(rad)
local real dist = SquareRoot( Pow(x2-x1, 2.) + Pow(y2-y1, 2.) )
local player p = GetOwningPlayer(u)
local real x
local real y
// *** Assign members ***
set x = x1 + PORT_OFFSET * dx
set y = y1 + PORT_OFFSET * dy
set this.port[0] = CreateUnit(p, PORTAL_RAWCODE, x, y, rad*bj_RADTODEG)
set this.fg[0] = CreateFogModifierRadius(p, FOG_OF_WAR_VISIBLE, x, y, FOG_OF_WAR_AREA, true, false)
set this.rct[0] = ConvRect.evaluate(x, y, rad-PI_HALF, (this), 0)
set x = x1 + dist * dx
set y = y1 + dist * dy
set this.port[1] = CreateUnit(p, PORTAL_RAWCODE, x, y, (rad-bj_PI)*bj_RADTODEG)
set this.fg[1] = CreateFogModifierRadius(p, FOG_OF_WAR_VISIBLE, x, y, FOG_OF_WAR_AREA, true, false)
set this.rct[1] = ConvRect.evaluate(x, y, rad-PI_HALF, (this), 1)
set this.dur = PortalDuration[lvl]
set this.rad = rad-PI_HALF
set this.filt = Filter(PortAll)
set this.grp = CreateGroup()
set this.lvl = lvl
// *** Start fog modifiers ***
call FogModifierStart(this.fg[0])
call FogModifierStart(this.fg[1])
// *** Portals anim speed ***
call SetUnitTimeScale(this.port[0], PORTAL_BIRTH_TIME / PortalChannelDuration[lvl])
call SetUnitTimeScale(this.port[1], PORTAL_BIRTH_TIME / PortalChannelDuration[lvl])
// *** Set birth animation ***
call SetUnitAnimation(this.port[0], "birth")
call SetUnitAnimation(this.port[1], "birth")
// *** Portals abils ***
call UnitRemoveAbility(this.port[0], 'Amov')
call UnitRemoveAbility(this.port[1], 'Amov')
// *** Portals selectable ***
call ShowUnit(this.port[0], false)
call ShowUnit(this.port[1], false)
call ShowUnit(this.port[0], true)
call ShowUnit(this.port[1], true)
return (this)
endmethod
// *** Destr ***
method onDestroy takes nothing returns nothing
// *** Memory clear ***
call FogModifierStop(this.fg[0])
call FogModifierStop(this.fg[1])
call DestroyFogModifier(this.fg[0])
call DestroyFogModifier(this.fg[1])
call KillUnit(this.port[0])
call KillUnit(this.port[1])
call StopSound(this.snd[0], true, true)
call StopSound(this.snd[1], true, true)
call RemoveRect(this.rct[0])
call RemoveRect(this.rct[1])
call DestroyGroup(this.grp)
call DestroyFilter(this.filt)
// *** Null vars ***
set this.grp = null
set this.filt = null
set this.fg[0] = null
set this.fg[1] = null
set this.snd[0] = null
set this.snd[1] = null
set this.rct[0] = null
set this.rct[1] = null
set this.port[0] = null
set this.port[1] = null
endmethod
// *** Stores sounds ***
public method SetSounds takes sound s1, sound s2 returns nothing
set this.snd[0] = s1
set this.snd[1] = s2
endmethod
endstruct
// ------------------------------------------------------------------------
// *** Custom Functions ***
// ------------------------------------------------------------------------
// *** Id Converted Index ***
private function HtoI takes handle h returns integer
return GetHandleId(h) - 1048576
endfunction
// *** Returns minx ***
private constant function Minx takes real a, real b, real c, real d returns real
if (a < b and a < c and a < d) then
return a
elseif (b < c and b < d) then
return b
elseif (c < d) then
return c
endif
return d
endfunction
// *** Returns maxx ***
private constant function Maxx takes real a, real b, real c, real d returns real
if (a > b and a > c and a > d) then
return a
elseif (b > c and b > d) then
return b
elseif (c > d) then
return c
endif
return d
endfunction
// *** Converts rect ***
private function ConvRect takes real cx, real cy, real radians, portal p, integer index returns rect
local real rad = Atan(PORTAL_HEIGHT/PORTAL_WIDTH)
local real dist = SquareRoot( PORTAL_WIDTH*PORTAL_WIDTH + PORTAL_HEIGHT*PORTAL_HEIGHT ) * 0.5
local real array x
local real array y
set x[0] = cx + dist * Cos(radians+rad)
set y[0] = cy + dist * Sin(radians+rad)
set x[1] = cx + dist * Cos(radians-rad)
set y[1] = cy + dist * Sin(radians-rad)
set x[2] = cx - dist * Cos(radians+rad)
set y[2] = cy - dist * Sin(radians+rad)
set x[3] = cx - dist * Cos(radians-rad)
set y[3] = cy - dist * Sin(radians-rad)
set p.x[index] = x[2]
set p.y[index] = y[2]
return Rect(Minx(x[0], x[1], x[2], x[3]), Minx(y[0], y[1], y[2], y[3]), Maxx(x[0], x[1], x[2], x[3]), Maxx(y[0], y[1], y[2], y[3]))
endfunction
// *** Plays portal sound ***
private function PlayPortal takes string id, real x, real y returns sound
local sound s = null
if (id == "birth") then
set s = CreateSound( SOUND_BIRTH, false, true, true, 10, 10, "DefaultEAXON" )
call SetSoundVolume(s, 127)
//call SetSoundParamsFromLabel( s, "ShimmeringPortalBirth" )
elseif (id == "death") then
set s = CreateSound( SOUND_DEATH, false, true, true, 10, 10, "DefaultEAXON" )
call SetSoundVolume(s, 127)
call SetSoundDuration( s, 8529 )
//call SetSoundParamsFromLabel( s, "ShimmeringPortalDeath" )
elseif (id == "enter") then
set s = CreateSound( SOUND_ENTER, false, true, true, 10, 10, "DefaultEAXON" )
call SetSoundVolume(s, 127)
//call SetSoundParamsFromLabel( s, "EnterShimmeringPortal" )
call SetSoundDuration( s, 1829 )
endif
call SetSoundPosition(s, x, y, 0.)
call StartSound(s)
call KillSoundWhenDone(s)
set bj_lastPlayedSound = s
set s = null
return (bj_lastPlayedSound)
endfunction
// *** Checks is unit in an line ***
// *** Arguments: whichUnit, bottom x, bottom y, length, height and angle in radians
private function IsUnitOnLine takes unit u, real bx, real by, real length, real height, real radians returns boolean
// *** Locals ***
local real ux = GetUnitX(u)
local real uy = GetUnitY(u)
local real rad = Atan2(uy-by, ux-bx)
local real hyp
// *** Unit is not on line ***
if (rad < radians or rad > radians+PI_HALF) then
return false
endif
// *** Set remaining locals ***
set hyp = (ux-bx)*(ux-bx) + (uy-by)*(uy-by)
set rad = rad - radians
if (rad < 0.) then
set rad = -rad
endif
return (hyp * Cos(rad) <= length*length) and (hyp * Sin(rad) <= height*height)
endfunction
// *** Resets ported unit ***
private function ResetPorted takes nothing returns nothing
local timer t = GetExpiredTimer()
// *** Make unit teleportable again ***
set Ported[TimerData[HtoI(t)]] = false
// *** Mem clr ***
call PauseTimer(t)
call DestroyTimer(t)
set t = null
endfunction
// *** Filter port (MAIN: Picks and teleports units) ***
private function PortFilter takes nothing returns nothing
// *** Locals ***
local unit f = GetFilterUnit()
local portal p = portal.Temp
local boolean fly = true
local timer t
local real x
local real y
local real rad
// *** Check flying ***
if (not ALLOW_FLYING_UNITS) then
set fly = not IsUnitType(f, UNIT_TYPE_FLYING)
endif
// *** Check is valid unit ***
if (fly and IsUnitOnLine(f, p.x[p.i], p.y[p.i], PORTAL_WIDTH, PORTAL_HEIGHT, p.rad) and not IsUnitType(f, UNIT_TYPE_STRUCTURE) and GetWidgetLife(f) > 0.405 and not Ported[HtoI(f)] and GetUnitTypeId(f) != PORTAL_RAWCODE) then
// *** Port unit ***
set Ported[HtoI(f)] = true
// *** Clear selection ***
call SelectUnit(f, false)
// *** Move it and add effects ***
set x = GetUnitX(f)
set y = GetUnitY(f)
call DestroyEffect( AddSpecialEffect(EFFECT_ON_ENTER, x, y) )
// *** Sound play ***
call PlayPortal("enter", x, y)
// *** New x, y ***
set x = GetRandomReal(GetRectMinX(p.rct[1-p.i]), GetRectMaxX(p.rct[1-p.i]))
set y = GetRandomReal(GetRectMinY(p.rct[1-p.i]), GetRectMaxY(p.rct[1-p.i]))
set rad = GetUnitFacing(f)*bj_DEGTORAD
// *** Main move ***
call SetUnitPosition(f, x, y)
// *** Now do pan camera if wanted ***
if (DO_PAN_CAMERA) then
if (GetLocalPlayer() == GetOwningPlayer(f)) then
call SetCameraPosition(x, y)
endif
endif
// *** Effect on exit ***
call DestroyEffect( AddSpecialEffect(EFFECT_ON_EXIT, x, y) )
// *** Move order ***
call IssuePointOrder(f, "move", x + ORDER_OFFSET * Cos(rad), y + ORDER_OFFSET * Sin(rad))
// *** Now call port timeout ***
set t = CreateTimer()
set TimerData[HtoI(t)] = HtoI(f)
call TimerStart(t, PORT_TIMEOUT, false, function ResetPorted)
// *** Null locals ***
set t = null
endif
// *** mem clr ***
set f = null
endfunction
// *** Portal main teleport function ***
private function PortalTeleActions takes nothing returns nothing
// *** Locals ***
local integer i = 0
local portal p
// *** Loop through portals ***
loop
// *** Get enum portal ***
set p = portal.Port[i]
// *** Pick all units in port 0 and port them ***
set portal.Temp = p
set p.i = 0
call GroupEnumUnitsInRect(p.grp, p.rct[0], p.filt)
// *** Pick all units in port 0 and port them ***
set p.i = 1
call GroupEnumUnitsInRect(p.grp, p.rct[1], p.filt)
// *** Decrease duration ***
set p.dur = p.dur - TIMER_DELAY
// *** Check is portal out of time ***
if (p.dur <= 0.) then
// *** Death sounds ***
call PlayPortal("death", GetUnitX(p.port[0]), GetUnitY(p.port[0]))
call PlayPortal("death", GetUnitX(p.port[1]), GetUnitY(p.port[1]))
// *** Destroy ***
call p.destroy()
// *** Decrease counter ***
set portal.NPorts = portal.NPorts - 1
// *** Swap and decrease current loop ***
set portal.Port[i] = portal.Port[portal.NPorts]
set i = i - 1
endif
set i = i + 1
exitwhen (i >= portal.NPorts)
endloop
// *** Free timer if this is the last one ***
if (portal.NPorts == 0) then
call PauseTimer(Tim)
call DestroyTimer(Tim)
set Tim = null
endif
endfunction
// *** Main condition ***
private constant function Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABILPORT_RAWCODE
endfunction
// *** Main actions ***
private function Actions takes nothing returns nothing
// *** Locals ***
local eventid id = GetTriggerEventId()
local unit u = GetTriggerUnit()
local location l
local real rad
local portal p
// *** Is cast? ***
if (id == EVENT_PLAYER_UNIT_SPELL_EFFECT) then
// *** Locals load ***
set l = GetSpellTargetLoc()
set p = portal.create(u, l, GetUnitAbilityLevel(u, ABILPORT_RAWCODE))
// *** Store sounds ***
call p.SetSounds( PlayPortal("birth", GetUnitX(p.port[0]), GetUnitY(p.port[0])), PlayPortal("birth", GetUnitX(p.port[1]), GetUnitY(p.port[1])) )
// *** Store values ***
set SpellPort[HtoI(u)] = p
// *** Clear mem ***
call RemoveLocation(l)
set l = null
elseif (id == EVENT_PLAYER_UNIT_SPELL_FINISH) then
// *** Spell finished ***
set p = SpellPort[HtoI(u)]
set SpellPort[HtoI(u)] = portal(0)
// *** Add timeout ***
call UnitApplyTimedLife(p.port[0], 'BTLF', PortalDuration[p.lvl])
call UnitApplyTimedLife(p.port[1], 'BTLF', PortalDuration[p.lvl])
// *** Load timer if needed ***
if (portal.NPorts == 0) then
set Tim = CreateTimer()
call TimerStart(Tim, TIMER_DELAY, true, function PortalTeleActions)
endif
// *** Store timer ***
set portal.Port[portal.NPorts] = p
set portal.NPorts = portal.NPorts + 1
elseif (id == EVENT_PLAYER_UNIT_SPELL_ENDCAST and SpellPort[HtoI(u)] != null) then
// *** Play death sound ***
set p = SpellPort[HtoI(u)]
call PlayPortal("death", GetUnitX(p.port[0]), GetUnitY(p.port[0]))
call PlayPortal("death", GetUnitX(p.port[1]), GetUnitY(p.port[1]))
// *** Spell was stoped channeling ***
call p.destroy()
endif
// *** Clear mem ***
set u = null
endfunction
// *** Dummy filter ***
private constant function DummyFilter takes nothing returns boolean
return true
endfunction
// *** Init function ***
private function Init takes nothing returns nothing
// *** Main trigger load ***
local trigger t = CreateTrigger()
local filterfunc ff = Filter(function DummyFilter)
local integer i = 0
// *** Events register ***
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, ff)
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_ENDCAST, ff)
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_FINISH, ff)
set i = i + 1
exitwhen (i == bj_MAX_PLAYER_SLOTS)
endloop
// *** Add condition / action ***
call TriggerAddCondition(t, Condition(function Conditions))
call TriggerAddAction(t, function Actions)
// *** Preloader ***
call Preload(SOUND_BIRTH)
call Preload(SOUND_DEATH)
call Preload(SOUND_ENTER)
call RemoveUnit(CreateUnit(Player(15), PORTAL_RAWCODE, 0., 0., 0.))
// *** Set our code here ***
set PortAll = function PortFilter
// *** User setup ***
call Setup()
call DestroyFilter(ff)
set ff = null
endfunction
endlibrary