XeNiM666
I lurk for pizza
- Reaction score
- 138
Ultrablast
by XeNiM666
by XeNiM666
I got nothing to do here so here's another spell with a stupid name. Can't think of any good name for this spell.
GUI/JASS/vJASS : vJASS
MUI/MPI : MUI
Leakless : Yes. Inform me if not
Lagless : Lags when spammed
Description : Channels for 2 seconds to cocentrate all of his magical power and release a wave of pure magic that deals pure magic damage depending on the caster's current mana when he started channeling.
Screenshots :
Code : Please critique my coding...
JASS:
//****************************************************************************************//
//****************************************************************************************//
// //
// ULTRABLAST //
// by XeNiM666 //
// //
//****************************************************************************************//
//****************************************************************************************//
// //
// REQUIRES: //
// 1. A vJASS preprocessor ( Jass NewGen Pack ) //
// 2. Jesus4Lyf's Key Timers 2.0 ( KT2 ) ( Included ) //
// 3. Jesus4Lyf's GTriggers ( GT ) ( Included ) //
// 4. A dummy with Vexorian's dummy.mdx model //
// //
//****************************************************************************************//
//****************************************************************************************//
// //
// HOW TO IMPLEMENT: //
// 1. Create a trigger //
// 2. Convert it to custom text //
// 3. Delete the text inside //
// 4. Copy all the text here and copy it to the trigger you created //
// 5. Copy the Universal Dummy unit in this map //
// 7. Copy the Ultrablast Dummy unit in this map //
// 8. Copy the Ultrablast ability in this map //
// //
//****************************************************************************************//
//****************************************************************************************//
scope Ultrablast initializer onInit
globals
// THE RAW CODE OF THE SPELL
private constant integer SPELL_ID = 039;A000039;
// THE ORDER STRING OF THE SPELL
private constant string SPELL_ORDER_ID = "carrionswarm"
// THE CASTING TIME OF THE SPELL
private constant real SPELL_CASTING_TIME = 2.00
// THE PERIOD OF THE TIMER USED...
private constant real TIMER_PERIOD = 0.03125
// THE RAW CODE OF THE ULTRABLAST DUMMY
private constant integer BEAM_DUMMY_ID = 039;h001039;
// THE RAW CODE OF THE DUMMY USED
// IT MUST HAVE THE "dummy.mdx" AS THE MODEL
private constant integer DUMMY_ID = 039;h000039;
// THE MODEL USED AS THE BEAM
private constant string BEAM_MODEL = "war3mapImported\\StarfallTarget2.mdx"
// THE ATTACHMENT POINT OF THE MODEL ABOVE FOR THE DUMMY_ID
private constant string BEAM_MODEL_ATTACH = "origin"
// THE HEIGHT OF THE BEAM SO IT DOES'NT LOOK WIERD
private constant real BEAM_MODEL_HEIGHT = 100.00
// THE MODEL USED AS THE ORB
private constant string ORB_MODEL = "war3mapImported\\StarfallTarget2.mdx"
// THE NUMBER OF ORBS SPINNING WHILE CASTING
private constant integer NUMBER_OF_ORBS = 6
// THE STARTING DISTANCE OF THE ORBS WHEN IT FIRST STARTED CASTING
private constant real ORB_DISTANCE_FROM_CASTER = 300.00
// THE SPEED OF THE ORBS IN ANGLE PER SECOND
private constant real ORB_SPEED_APS = 270.00
// THE SPEED OF THE BEAM IN WC3 UNITS PER SECOND
private constant real BEAM_SPEED = 2000.00
// THE INTERVAL OF THE RELEASE OF EACH BEAM
private constant real BEAMS_INTERVAL = 0.10
// THE TOTAL NUMBER OF BEAMS
private constant integer NUMBER_OF_BEAMS = 20
// THE INITIAL AOE OF THE SPELL
private constant real INITIAL_AOE = 50.00
endglobals
// CHECKS WHAT UNITS WILL BE DAMAGED
// REQUIRES A LITTLE KNOWLEDGE OF JASS
private function Conditions takes nothing returns boolean
return GetWidgetLife( GetFilterUnit() ) > 0.408 and IsUnitType( GetFilterUnit(), UNIT_TYPE_STRUCTURE ) == false and IsUnitType( GetFilterUnit(), UNIT_TYPE_FLYING ) == false and GetUnitAbilityLevel( GetFilterUnit(), 039;Aloc039; ) == 0
endfunction
// HOW FAR THE BEAM WILL TRAVEL
private function Distance takes integer lvl returns real
return 1250.00 + ( lvl * 250.00 )
endfunction
// THE FINAL AOE OF THE SPELL
private function Final_AOE takes integer lvl returns real
return 300.00 + ( lvl * 50.00 )
endfunction
//**************************************************************************************//
//**************************************************************************************//
// DO NOT TOUCH UNLESS YOU KNOW WHAT YOU'RE DOING //
//**************************************************************************************//
//**************************************************************************************//
globals
private group GROUP = CreateGroup()
endglobals
private struct Beam
unit caster
real cx
real cy
unit beam
effect ef
real cos
real sin
real dis
// CHECKS HOW FAR THE BEAM HAS TRAVELED
real d = 0.00
real aoe
real dmg
group hit = CreateGroup()
static method Move takes nothing returns boolean
local Beam b = KT_GetData()
local unit u = null
local real r = BEAM_SPEED * TIMER_PERIOD
local real x = GetUnitX( b.beam ) + r * b.cos
local real y = GetUnitY( b.beam ) + r * b.sin
call SetUnitPosition( b.beam, x, y )
call GroupEnumUnitsInRange( GROUP, x, y, b.aoe, Condition( function Conditions ) )
loop
set u = FirstOfGroup( GROUP )
exitwhen u == null
if IsUnitEnemy( u, GetOwningPlayer( b.caster ) ) == true and IsUnitInGroup( u, b.hit ) == false then
call UnitDamageTarget( b.caster, u, b.dmg, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
call GroupAddUnit( b.hit, u )
endif
call GroupRemoveUnit( GROUP, u )
endloop
set b.d = b.d + r
if b.d >= b.dis then
call b.destroy()
return true
endif
return false
endmethod
method onDestroy takes nothing returns nothing
call GroupClear( .hit )
call DestroyGroup( .hit )
set .hit = null
call DestroyEffect( .ef )
set .ef = null
call RemoveUnit( .beam )
set .beam = null
set .caster = null
endmethod
static method create takes unit caster, real sin, real cos, real aoe, real dmg returns Beam
local Beam b = Beam.allocate()
local real scale = aoe / 35.00
// AND YES, 35.00 IS NOT A CONFIGURABLE...
set b.caster = caster
set b.cx = GetUnitX( b.caster )
set b.cy = GetUnitY( b.caster )
set b.cos = cos
set b.sin = sin
set b.aoe = aoe
set b.dmg = dmg
set b.beam = CreateUnit( GetOwningPlayer( b.caster ), DUMMY_ID, b.cx, b.cy, 270.00 )
set b.ef = AddSpecialEffectTarget( BEAM_MODEL, b.beam, BEAM_MODEL_ATTACH )
call SetUnitScale( b.beam, scale, scale, scale )
call SetUnitFlyHeight( b.beam, BEAM_MODEL_HEIGHT, 0.00 )
set b.dis = Distance( GetUnitAbilityLevel( b.caster, SPELL_ID ) )
call SetUnitState( b.caster, UNIT_STATE_MANA, GetUnitState( b.caster, UNIT_STATE_MANA ) - b.dmg )
call KT_Add( function Beam.Move, b, TIMER_PERIOD )
return b
endmethod
endstruct
private struct Cast
unit caster
real cx
real cy
integer order
real tx
real ty
real ang
real cos
real sin
real caoe // caoe FOR CURRENT AOE
real faoe // faoe FOR FINAL AOE
real dmg
static method Release takes nothing returns boolean
local Cast c = KT_GetData()
local Beam b
if c.caoe <= c.faoe then
// debug call BJDebugMsg( R2S( c.caoe ) )
set b = Beam.create( c.caster, c.sin, c.cos, c.caoe, c.dmg )
set c.caoe = c.caoe + ( ( c.faoe - INITIAL_AOE ) / NUMBER_OF_BEAMS )
else
call c.destroy()
return true
endif
return false
endmethod
static method Wait takes nothing returns boolean
local Cast c = KT_GetData()
local unit dummy = null
if GetUnitCurrentOrder( c.caster ) == c.order then
// CREATES THE BEAM AS AN EFFECT
set dummy = CreateUnit( GetOwningPlayer( c.caster ), BEAM_DUMMY_ID, c.cx, c.cy, bj_RADTODEG * c.ang )
call UnitApplyTimedLife( dummy, 039;BTLF039;, 3.00 )
set dummy = null
set c.dmg = GetUnitState( c.caster, UNIT_STATE_MANA ) / NUMBER_OF_BEAMS
call KT_Add( function Cast.Release, c, BEAMS_INTERVAL )
else
call c.destroy()
endif
return true
endmethod
method onDestroy takes nothing returns nothing
set .caster = null
endmethod
endstruct
private struct Channel
unit caster
real cx
real cy
integer order
unit orb
effect eff
real d
real a
static method Spin takes nothing returns boolean
local Channel c = KT_GetData()
local real a = ORB_SPEED_APS * TIMER_PERIOD
local real d = ( ORB_DISTANCE_FROM_CASTER / SPELL_CASTING_TIME ) * TIMER_PERIOD
local real x
local real y
if GetUnitCurrentOrder( c.caster ) == c.order then
set c.a = c.a + a
set c.d = c.d - d
if c.d > 0.00 then
set x = c.cx + c.d * Cos( c.a * bj_DEGTORAD )
set y = c.cy + c.d * Sin( c.a * bj_DEGTORAD )
call SetUnitPosition( c.orb, x, y )
else
call c.destroy()
return true
endif
else
call c.destroy()
return true
endif
return false
endmethod
method onDestroy takes nothing returns nothing
call DestroyEffect( .eff )
set .eff = null
call RemoveUnit( .orb )
set .orb = null
set .caster = null
endmethod
static method create takes unit caster, real x, real y, real ang returns Channel
local Channel c = Channel.allocate()
set c.caster = caster
set c.cx = GetUnitX( c.caster )
set c.cy = GetUnitY( c.caster )
set c.orb = CreateUnit( GetOwningPlayer( c.caster ), DUMMY_ID, x, y, ang )
set c.eff = AddSpecialEffectTarget( ORB_MODEL, c.orb, BEAM_MODEL_ATTACH )
call SetUnitFlyHeight( c.orb, BEAM_MODEL_HEIGHT, 0.00 )
set c.d = ORB_DISTANCE_FROM_CASTER
set c.a = ang
set c.order = OrderId( SPELL_ORDER_ID )
call KT_Add( function Channel.Spin, c, TIMER_PERIOD )
return c
endmethod
endstruct
private function U_Actions takes nothing returns boolean
local Cast c = Cast.create()
local Channel ch
local unit caster = GetTriggerUnit()
local real cx = GetUnitX( caster )
local real cy = GetUnitY( caster )
local integer i = 0
local real ang
local real x
local real y
local location t = GetSpellTargetLoc()
loop
set i = i + 1
set ang = ( 360.00 / NUMBER_OF_ORBS ) * i
set x = cx + ORB_DISTANCE_FROM_CASTER * Cos( ang * bj_DEGTORAD )
set y = cy + ORB_DISTANCE_FROM_CASTER * Sin( ang * bj_DEGTORAD )
set ch = Channel.create( caster, x, y, ang )
exitwhen i >= NUMBER_OF_ORBS
endloop
set c.caster = caster
set c.cx = GetUnitX( c.caster )
set c.cy = GetUnitY( c.caster )
set c.tx = GetLocationX( t )
set c.ty = GetLocationY( t )
set c.ang = Atan2( c.ty - c.cy, c.tx - c.cx )
set c.cos = Cos( c.ang )
set c.sin = Sin( c.ang )
set c.order = OrderId( SPELL_ORDER_ID )
set c.caoe = INITIAL_AOE
set c.faoe = Final_AOE( GetUnitAbilityLevel( c.caster , SPELL_ID ) )
call KT_Add( function Cast.Wait, c, SPELL_CASTING_TIME )
call RemoveLocation( t )
set t = null
set caster = null
return false
endfunction
//===========================================================================
private function onInit takes nothing returns nothing
call GT_AddStartsEffectAction( function U_Actions, SPELL_ID )
// PRELOADING <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite1" alt=":)" title="Smile :)" loading="lazy" data-shortname=":)" />
call RemoveUnit( CreateUnit( Player( 15 ), DUMMY_ID, 0.00, 0.00, 0.00 ) )
call RemoveUnit( CreateUnit( Player( 15 ), BEAM_DUMMY_ID, 0.00, 0.00, 0.00 ) )
call Preload( BEAM_MODEL )
call Preload( ORB_MODEL )
call PreloadStart()
endfunction
endscope
// ENJOY! <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite1" alt=":)" title="Smile :)" loading="lazy" data-shortname=":)" />
Changelog :
1.0 - Initial Release
1.1 - Fixed a bug where when you test it it returns to wc3's main screen. ( Thanks Weep )
1.2 - Made a few values configurable.
Enjoy!