- Joined
- Jun 18, 2011
- Messages
- 168
Line 87: Not a valid identifier name: "3D"
I am unable to save the map I attached, as well as the map I imported the spell to.
This spell uses TimerUtils, BountSentinel, Vector, and Heights
- private constant boolean 3D = true
I am unable to save the map I attached, as well as the map I imported the spell to.
This spell uses TimerUtils, BountSentinel, Vector, and Heights
JASS:
scope BurningOrbit initializer init
//*************************************************************************************************************//
// Burning Orbit //
// by //
// cedi //
// //
// needs: TimerUtils by Vexorian //
// Bound Sentinel by Vexorian //
// Dummy Model by //
// Vector lib by //
// Heights by cedi //
//*************************************************************************************************************//
//For use, copy the trigger to your map, copy the dummy create a spell and adjust the values below.
globals
//ID of the dummy spell
private constant integer SPELL_ID = 'A000'
//ID of the spell which the splits should have. Beware, only unit target spells or passivs.
private constant integer SPLIT_SPELL = 'A001'
//ID of the spell which they mmain orb should have. BEware, only passivs.
private constant integer MAIN_SPELL = '0000'
//ID of the dummy
private constant integer DUMMY_ID = 'h000'
//How many levels does your spell have?
private constant integer SPELL_LEVEL_COUNT = 4
//How many splits do you want?
private constant integer MAX_SPLITS = 20
//How many moves should the spreed out use?
private constant integer MOVES = 25
//Red part of the color of the main orb ( 0 - 255 )
private constant integer COLOR_RED = 255
//Green part of the color of the main orb ( 0 - 255 )
private constant integer COLOR_GREEN = 255
//Blue part of the color of the main orb ( 0 - 255 )
private constant integer COLOR_BLUE = 255
//Alpha part of the color of the main orb ( 0 - 255 )
private constant integer COLOR_ALPHA = 255
//Red part of the color of the split orb ( 0 - 255 )
private constant integer SPLIT_COLOR_RED = 255
//Green part of the color of the split orb ( 0 - 255 )
private constant integer SPLIT_COLOR_GREEN = 255
//Blue part of the color of the split orb ( 0 - 255 )
private constant integer SPLIT_COLOR_BLUE = 255
//Alpha part of the color of the split orb ( 0 - 255 )
private constant integer SPLIT_COLOR_ALPHA = 255
//The move timer interval
private constant real TIMER_INTERVAL = 0.02
//Max distance of the splits to the main orb.
private constant real MAX_DISTANCE = 300.00
//Min distance of the splits to the main orb.
private constant real MIN_DISTANCE = 100.00
//Max rotation speed of the splits in grad.
private constant real MAX_SPEED = 2.00
//Min rotation speed of the splits in grad.
private constant real MIN_SPEED = 0.50
//Flyheight of the main orb.
private constant real MAIN_FLY_HEIGHT = 500.00
//Maximal cooldown add.
private constant real MAX_COOLDOWN_ADD = 3.00
//Delay between summon and split.
private constant real SPLIT_DELAY = 3.00
//Size of the main orb 1 == 100% size.
private constant real MAIN_SIZE = 3.00
//Size of the splits orb 1 == 100% size.
private constant real SPLIT_SIZE = 1.00
//Model of the splits.
private constant string SPLIT_MODEL = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl"
//Model of the main orb.
private constant string MAIN_MODEL = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"
//Effect when the main orb split up.
private constant string SPLIT_EFFECT = "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl"
//Effect when the main orb comes to gether.
private constant string SPLIT_END_EFFECT = ""
//Order string of the split spell.
private constant string ORDER_STRING = "acidbomb"
//Effect when the main orb appears.
private constant string CREATE_EFFECT = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
//Effect when the main orb disappears.
private constant string REMOVE_EFFECT = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
//Should the main orb get invisible during splitting?
private constant boolean HIDE_MAIN = true
//Is the split spell targeting enemies?
private constant boolean TARGET_ENEMY = true
//Should the splits fly around on 3d?
private constant boolean 3D = true
private vector AXISZ //System
private vector AXISX //System
private vector AXISY //System
private vector TEMPVECTOR2 //System
private real array COOLDOWN //System
private real array DURATION //System
private real array AOE //System
private group TEMPGROUP = CreateGroup() //System
endglobals
//Cooldown of the split spell.
private function SET_COOLDOWN takes nothing returns nothing
set COOLDOWN[1] = 3.00
set COOLDOWN[2] = 3.00
set COOLDOWN[3] = 3.00
set COOLDOWN[4] = 3.00
endfunction
//Duration of the whole spell
private function SET_DURATION takes nothing returns nothing
set DURATION[1] = 12.00
set DURATION[2] = 12.00
set DURATION[3] = 12.00
set DURATION[4] = 12.00
endfunction
//Range of the dummy spell ( the value in the oe should be bigger then this )
private function SET_AOE takes nothing returns nothing
set AOE[1] = 550.00
set AOE[2] = 550.00
set AOE[3] = 550.00
set AOE[4] = 550.00
endfunction
//*************************************************************************************************************//
// !SYSTEM! //
//*************************************************************************************************************//
private keyword SF_Split
private keyword SF_Main
private function IsAliveAndUnitAndNotMagicImmune takes nothing returns boolean
return GetWidgetLife( GetFilterUnit() ) > 0.405 and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false
endfunction
private struct SF_Split
unit split
integer movescounter = 0
real angleZ
real angleX
real angleY
real cd = 0.00
real nextcast = 0.00
boolean reachedLoc = false
boolean goinInit = false
effect sfx
SF_Main root
vector posi
vector tmpposi
vector move
method onDestroy takes nothing returns nothing
call DestroyEffect( .sfx )
call KillUnit( .split )
set .sfx = null
set .split = null
call .posi.destroy()
call .move.destroy()
endmethod
private method GetRandomNextCast takes nothing returns nothing
set .nextcast = COOLDOWN[.root.level] + GetRandomReal( 0.00, MAX_COOLDOWN_ADD )
endmethod
private method Cast takes nothing returns nothing
local unit u
call .GetRandomNextCast()
set .cd = 0.00
call GroupEnumUnitsInRange( TEMPGROUP, GetUnitX( .split ), GetUnitY( .split ), AOE[.root.level], Condition( function IsAliveAndUnitAndNotMagicImmune ) )
loop
set u = FirstOfGroup( TEMPGROUP )
exitwhen u == null
if IsUnitEnemy( u, .root.owner ) == TARGET_ENEMY then
call IssueTargetOrder( .split, ORDER_STRING, u )
set u = null
call GroupClear( TEMPGROUP )
exitwhen true
endif
call GroupRemoveUnit( TEMPGROUP, u )
endloop
endmethod
private method Zangle takes real z returns nothing
local integer i=R2I(z*bj_RADTODEG+90.5)
if(i>=180) then
set i=179
elseif(i<0) then
set i=0
endif
call SetUnitAnimationByIndex(.split, i )
endmethod
private method Turn takes nothing returns nothing
local real z = .posi.z
local real x = .posi.x
local real y = .posi.y
call .posi.rotate( AXISZ, .angleZ )
set x = ( .root.posi.x + .posi.x ) - ( .root.posi.x + x )
set y = ( .root.posi.y + .posi.y ) - ( .root.posi.y + y )
if 3D == true then
call .posi.rotate( AXISX, .angleX )
call .posi.rotate( AXISY, .angleY )
set z = ( .root.posi.z + .posi.z ) - ( .root.posi.z + z )
call .Zangle( Atan(( z / (SquareRoot(x*x + y*y))) ) )
call SetUnitZ( .split, .root.posi.z + .posi.z )
endif
call SetUnitX( .split, .root.posi.x + .posi.x )
call SetUnitY( .split, .root.posi.y + .posi.y )
call SetUnitFacing(.split,Atan2(y, x)*bj_RADTODEG)
endmethod
private method SetPositonReturn takes nothing returns nothing
if .movescounter <= MOVES then
call .tmpposi.add( .move )
call SetUnitX( .split, .tmpposi.x )
call SetUnitY( .split, .tmpposi.y )
call SetUnitZ( .split, .tmpposi.z )
else
call .destroy()
endif
set .movescounter = .movescounter + 1
endmethod
private method SetPositon takes nothing returns nothing
if .movescounter <= MOVES then
call .tmpposi.add( .move )
call SetUnitX( .split, .tmpposi.x )
call SetUnitY( .split, .tmpposi.y )
call SetUnitZ( .split, .tmpposi.z )
else
set .reachedLoc = true
endif
set .movescounter = .movescounter + 1
endmethod
method control takes nothing returns nothing
if .root.splitlifetime <= 0.00 then
call .destroy()
endif
if .root.goin == true then
if .goinInit == false then
set .movescounter = 0
set .goinInit = true
set .tmpposi.x = .root.posi.x + .posi.x
set .tmpposi.y = .root.posi.y + .posi.y
set .tmpposi.z = .root.posi.z + .posi.z
set .move.x = ( .posi.x * -1.00 ) / I2R( MOVES )
set .move.y = ( .posi.y * -1.00 ) / I2R( MOVES )
set .move.z = ( .posi.z * -1.00 ) / I2R( MOVES )
set .movescounter = 0
endif
call .SetPositonReturn()
endif
if .reachedLoc == false then
call .SetPositon()
elseif .root.goin == false then
call .Turn()
set .cd = .cd + TIMER_INTERVAL
if .cd >= .nextcast then
call .Cast()
endif
endif
endmethod
private method GetRamdomAngle takes nothing returns nothing
local integer i = GetRandomInt( 0, 1 )
local real r = GetRandomReal( MIN_SPEED, MAX_SPEED ) * bj_DEGTORAD
if i == 0 then
set .angleZ = r * -1
else
set .angleZ = r
endif
set i = GetRandomInt( 0, 1 )
set r = GetRandomReal( MIN_SPEED, MAX_SPEED ) * bj_DEGTORAD
if i == 0 then
set .angleX = r * -1
else
set .angleX = r
endif
set i = GetRandomInt( 0, 1 )
set r = GetRandomReal( MIN_SPEED, MAX_SPEED ) * bj_DEGTORAD
if i == 0 then
set .angleY = r * -1
else
set .angleY = r
endif
endmethod
private method GetRandomPosi takes nothing returns nothing
local real a = GetRandomReal( 0.00, 360.00 ) * bj_DEGTORAD
local real b = GetRandomReal( 0.00, 180.00 ) * bj_DEGTORAD
local real r = GetRandomReal( MIN_DISTANCE, MAX_DISTANCE )
local real times = I2R( MOVES )
set .posi = vector.create( r*Cos(a)*Cos(b), r*Cos(a)*Sin(b), r*Sin(a) )
set .move = vector.create( .posi.x / times , .posi.y / times, .posi.z / times )
endmethod
static method create takes SF_Main root returns SF_Split
local SF_Split data = SF_Split.allocate()
set data.root = root
call data.GetRandomPosi()
call data.GetRamdomAngle()
set data.split = CreateUnit( root.owner, DUMMY_ID, 0.00, 0.00, GetRandomReal( 0.00, 360.00 ) )
set data.sfx = AddSpecialEffectTarget( SPLIT_MODEL, data.split, "origin" )
call data.GetRandomNextCast()
call UnitAddAbility( data.split, SPLIT_SPELL )
call SetUnitAbilityLevel( data.split, SPLIT_SPELL, data.root.level )
call data.SetPositon()
call SetUnitVertexColor( data.split, SPLIT_COLOR_RED, SPLIT_COLOR_GREEN, SPLIT_COLOR_BLUE, SPLIT_COLOR_ALPHA )
call SetUnitScale( data.split, SPLIT_SIZE, SPLIT_SIZE, SPLIT_SIZE )
set data.tmpposi = vector.create( root.posi.x, root.posi.y, root.posi.z )
return data
endmethod
endstruct
private function Control takes nothing returns nothing
local timer t = GetExpiredTimer()
local SF_Main data = GetTimerData( t )
call data.control()
set t = null
endfunction
private struct SF_Main
unit main = null
unit caster = null
integer level = 1
timer t = null
player owner = null
boolean goin = false
boolean splitupdone = false
boolean end = false
boolean moving = false
real splitlifetime
real delay = SPLIT_DELAY
effect sfx = null
SF_Main data = 0
SF_Split array splits[MAX_SPLITS]
vector posi = 0
vector move = 0
method control takes nothing returns nothing
local integer i = 0
if .splitupdone == false then
set .delay = .delay - TIMER_INTERVAL
if .delay <= 0.00 then
set .splitupdone = true
call DestroyEffect( AddSpecialEffectTarget( SPLIT_EFFECT, .main, "origin" ) )
if HIDE_MAIN then
call SetUnitVertexColor( .main, 255, 255, 255, 0 )
endif
loop
exitwhen i == MAX_SPLITS
set .splits[i] = SF_Split.create( .data )
set i = i + 1
endloop
endif
endif
if .splitlifetime <= 0.00 and .end == false then
set .delay = SPLIT_DELAY
set .end = true
if HIDE_MAIN then
call SetUnitVertexColor( .main, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_ALPHA )
call DestroyEffect( AddSpecialEffectTarget( SPLIT_END_EFFECT, .main, "origin" ) )
set i = 0
loop
exitwhen i == MAX_SPLITS
if .splits[i] != 0 then
call .splits[i].control()
endif
set i = i + 1
endloop
endif
endif
if .end == true then
set .delay = .delay - TIMER_INTERVAL
if .delay <= 0.00 then
call DestroyEffect( AddSpecialEffectTarget( REMOVE_EFFECT, .main, "origin" ) )
call .destroy()
endif
endif
if .moving then
call .posi.add( .move )
call SetUnitX( .main, .posi.x )
call SetUnitY( .main, .posi.y )
endif
if .splitlifetime <= I2R( MOVES ) * TIMER_INTERVAL and .goin == false then
set .goin = true
endif
set i = 0
if .splitupdone and not .end then
set .splitlifetime = .splitlifetime - TIMER_INTERVAL
loop
exitwhen i == MAX_SPLITS
if .splits[i] != 0 then
call .splits[i].control()
endif
set i = i + 1
endloop
endif
endmethod
method onDestroy takes nothing returns nothing
call ReleaseTimer( .t )
call DestroyEffect( .sfx )
call KillUnit( .main )
call .posi.destroy()
if .moving == true then
call .move.destroy()
endif
endmethod
static method create takes unit caster, real x, real y, vector move returns SF_Main
local SF_Main data = SF_Main.allocate()
set data.data = data
set data.t = NewTimer()
call SetTimerData( data.t, data )
set data.caster = caster
set data.owner = GetOwningPlayer( caster )
set data.main = CreateUnit( data.owner, DUMMY_ID, x, y, GetRandomReal( 0.00, 360.00 ) )
set data.sfx = AddSpecialEffectTarget( MAIN_MODEL, data.main, "origin" )
set data.level = GetUnitAbilityLevel( caster, SPELL_ID )
set data.splitlifetime = DURATION[data.level]
call SetUnitFlyHeight( data.main, MAIN_FLY_HEIGHT, 0.00 )
call DestroyEffect( AddSpecialEffectTarget( CREATE_EFFECT, data.main, "origin" ) )
call UnitAddAbility( data.main, MAIN_SPELL )
call SetUnitAbilityLevel( data.main, MAIN_SPELL, data.level )
call SetUnitVertexColor( data.main, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_ALPHA )
call SetUnitScale( data.main, MAIN_SIZE, MAIN_SIZE, MAIN_SIZE )
if move != 0 then
set data.move = move
set data.moving = true
endif
set data.posi = vector.create( x, y, GetUnitZ( data.main ) )
call TimerStart( data.t, TIMER_INTERVAL, true, function Control )
set caster = null
return data
endmethod
endstruct
private function IsSpell takes nothing returns boolean
if GetSpellAbilityId() == SPELL_ID then
call SF_Main.create( GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY(), 0 )
endif
return false
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( t, Condition( function IsSpell ) )
set AXISX = vector.create( 1.00, 0.00, 0.00 )
set AXISY = vector.create( 0.00, 1.00, 0.00 )
set AXISZ = vector.create( 0.00, 0.00, 1.00 )
set TEMPVECTOR2 = vector.create( 0.00, 0.00, 0.00 )
call SET_COOLDOWN()
call SET_DURATION()
call SET_AOE()
set t = null
endfunction
endscope
Attachments
Last edited: