Moderator
M
Moderator
16 July 2012
Bribe: Well-coded and as nice effects. Approved 4.4/5.
Bribe: Well-coded and as nice effects. Approved 4.4/5.
Description
Upload Date: 17:38, 6th Apr 2012
Update V 1.10
Update V 1.11
- 11:42 PM 4/8/2012
Update V 1.12
- 11:15 AM 4/11/2012
Update V 1.20
- 5:50 PM 4/12/2012
- 12:15 AM 4/28/2012
Learn
Learn Meteor Swarm [Level 1]
Learn Meteor Swarm [Level 2]
Learn Meteor Swarm [Level 3]
Learn Meteor Swarm [Level 4]
Learn Meteor Swarm [Level 5]
Calls down waves of fiery boulders with random sizes that fall at random points in the target area dealing fire damage to enemy units and buildings in the effective area, except for the first meteor which is always at the centre of the area and deals maximum damage.
Level 1 - Calls 30 meteors that deals 100 to 300 fire damage.
Level 2 - Calls 35 meteors that deals 125 to 350 fire damage.
Level 3 - Calls 40 meteors that deals 150 to 400 fire damage.
Level 4 - Calls 45 meteors that deals 175 to 450 fire damage.
Level 5 - Calls 50 meteors that deals 200 to 500 fire damage.
[Deals 10% of damage only to trees]
NormalMeteor Swarm - [Level 1]
Calls down 30 waves of firey boulders with random sizes that fall at random points in the target area dealing 100 to 300 fire damage to enemy units and buildings in the effective area. The first meteor is always at the centre and deals the maximum damage.
[Deals 10% of damage only to trees]
Meteor Swarm - [Level 2]
Calls down 35 waves of firey boulders with random sizes that fall at random points in the target area dealing 125 to 350 fire damage to enemy units and buildings in the effective area. The first meteor is always at the centre and deals the maximum damage.
[Deals 10% of damage only to trees]
Meteor Swarm - [Level 3]
Calls down 40 waves of firey boulders with random sizes that fall at random points in the target area dealing 150 to 400 fire damage to enemy units and buildings in the effective area. The first meteor is always at the centre and deals the maximum damage.
[Deals 10% of damage only to trees]
Meteor Swarm - [Level 4]
Calls down 45 waves of firey boulders with random sizes that fall at random points in the target area dealing 175 to 450 fire damage to enemy units and buildings in the effective area. The first meteor is always at the centre and deals the maximum damage.
[Deals 10% of damage only to trees]
Meteor Swarm - [Level 5]
Calls down 50 waves of firey boulders with random sizes that fall at random points in the target area dealing 200 to 500 fire damage to enemy units and buildings in the effective area. The first meteor is always at the centre and deals the maximum damage.
[Deals 10% of damage only to trees]
Sevion: for his 'Alloc' module
Magtheridon96: For his very good and detailed review
Adiktuz: Suggested many good ideas
RetroSexual: For his help in providing me with a trueshot aura model with zero height
Bribe
If someone finds he/she didn't get a well earned credit for using a resource(s) he/she made, contact me.
Will add destructible targetsWill add Shake Camera optionWill add a cast-at-bound fail safe function
- Older versions is included in the map for full change preview, its in a category named 'Older Versions'
V 1.00
- Release
- Changed some variable names.
DUMMYID
andABIL_ID
changed frompublic
toprivate
.- Added
static if
toconstant boolean
.- Added
set t = null
in the functionInit_MeteorSwarm
.- Merged actions in condition function and removed
TriggerAddAction(t, function MeteorSwarm_Actions)
.- Renamed both
static method
Start
andfall
tometeorCall
andmeteorFall
.- Renamed
dat
tothis
.- Removed
if/then/else
block fromMatchingUnit
.- method
meteorDamage
now usesbj_lastCreatedGroup
instead of creating and destroying a local or even instead of a global group.- Changed
GetRandomReal(1.0,360.0)
toGetRandomReal(0.0,2*bj_PI)
and so I can remove thebj_DEGTORAD
from bothCos
andSin
functions.- Used one hashtable only.
- method
meteorDamage
andMatchingUnit
are now normal functions outside the struct.- Added the option to let the first falling meteor to deal maximum damage or random instead of random only.
- Added an indicator to show the targeted area. You also have the option to show/hide this indicator.
- You can target destructables now and also you have the option to disable it.
- The spell now will function even if cast outside the boundary.
- Modified the BoundSentinel library; it now use the playable area not the camera bound in case the user changed the camera bound to minimum.
- Added Camera shake option
- Added Unit-Explode-on-Death option if killed by a meteor
- Implemented CTL
- Merged a library with the scope
- Changed the scope name to MeteorSwarm
The spell is pasted below.
- PM me or post for any inquiry/problem(s)/suggestion(s)
- Credit when use.
IMPORTANT: You will need JNGP to customize it to your needs.JASS:// Meteor Swarm Version 1.20 scope MeteorSwarm initializer Init_MeteorSwarm globals private real MIN_X private real MIN_Y private real MAX_X private real MAX_Y private constant real SAFETY_OFFSET = 16.00 private constant integer M_DUMMY_ID = 'e000' private constant integer I_DUMMY_ID = 'b000' private constant integer ABILITY_ID = 'A000' private integer index = 0 private integer array temp_this private constant integer INT_MIN = 3 // Minimum Interval Between Meteors Threshold private constant integer INT_MAX = 32 // Maximum Interval Between Meteors Threshold private constant real SCALE_MIN = 0.80 // Minimum Meteor Scale Threshold private constant real SCALE_MAX = 3.50 // Maximum Meteor Scale Threshold private constant real H_MIN = 750.00 // Minimum Meteor Height Threshold private constant real H_MAX = 1000.00 // Maximum Meteor Height Threshold private constant real INIT_DIST = 1000.00 private constant real STEP = 50.00 private constant real CHECK_DIST = 32.00 private constant integer HT_OFFSET = 4096 private hashtable mht = InitHashtable() // Meteor Hashtable private constant timer shake_timer = CreateTimer() private unit CASTER private real DAMAGE //==================================================================================================== // User-edit data // //==================================================================================================== // Make sure to change the dummy spell text to be appropriate with the following variables. // General Formula: ConstantFactor + AbilityLevel * AbilityLevelFactor + PrevLevelFactor * PrevLevelValue // The following variable can be changed according to the desired results // Number of Meteors Variables: private constant boolean NUM_TABLE = false // true/false to use Table/Formula // Table: private constant integer array nMeteors // set the values in the function named "Spell_Data_Table" // Formula: private constant integer NUM_CF = 25 // changes 'ConstantFactor' private constant integer NUM_LF = 5 // changes 'AbilityLevelFactor' private constant real NUM_PLF = 0 // changes 'PrevLevelFactor' // Minimum Damage Variables: private constant boolean D_MIN_TABLE = false // true/false to use Table/Formula // Table: private constant real array MinDamage // set the values in the function named "Spell_Data_Table" // Formula: private constant real D_MIN_CF = 75.00 // changes 'ConstantFactor' private constant real D_MIN_LF = 25.00 // changes 'AbilityLevelFactor' private constant real D_MIN_PLF = 0 // changes 'PrevLevelFactor' // Maximum Damage Variables: private constant boolean D_MAX_TABLE = false // true/false to use Table/Formula // Table: private constant real array MaxDamage // set the values in the function named "Spell_Data_Table" // Formula: private constant real D_MAX_CF = 250.00 // changes 'ConstantFactor' private constant real D_MAX_LF = 50.00 // changes 'AbilityLevelFactor' private constant real D_MAX_PLF = 0 // changes 'PrevLevelFactor' // Area of Effect (AoE) Variables: // Grand Area of Effect: private constant boolean GR_TABLE = false // true/false to use Table/Formula // Table: private constant real array GrandArea // set the values in the function named "Spell_Data_Table" // Formula: private constant real GR_CF = 750.00 // changes 'ConstantFactor' private constant real GR_LF = 50.00 // changes 'AbilityLevelFactor' private constant real GR_PLF = 0 // changes 'PrevLevelFactor' // Maximum AOE per Meteor: private constant boolean MAXR_TABLE = false // true/false to use Table/Formula // Table: private constant real array LargeArea // set the values in the function named "Spell_Data_Table" // Formula: private constant real MAXR_CF = 150.00 // changes 'ConstantFactor' private constant real MAXR_LF = 10.00 // changes 'AbilityLevelFactor' private constant real MAXR_PLF = 0 // changes 'PrevLevelFactor' // Minimum AOE per Meteor: private constant boolean MINR_TABLE = false // true/false to use Table/Formula // Table: private constant real array SmallArea // set the values in the function named "Spell_Data_Table" // Formula: private constant real MINR_CF = 100.00 // changes 'ConstantFactor' private constant real MINR_LF = 10.00 // changes 'AbilityLevelFactor' private constant real MINR_PLF = 0 // changes 'PrevLevelFactor' // Targets: private constant boolean FRIENDLY = true // true/false to harm enemy/all units private constant boolean GROUND = true // true/false to include/exclude ground units private constant boolean FLYING = false // true/false to include/exclude flying units private constant boolean STRUCTURE = true // true/false to include/exclude structure units private constant boolean DESTRUCTABLES = true // true/false to enable/disable destructables private constant real DESTRUCTABLE_FACTOR = 10.00 // this is the damage dealt to destructables divisor // Flags: private constant boolean INIT_MAX_D = true // true/false to enable/disable maximum damage on first meteor private constant boolean KILLS_EXPLODE = true // true/false to enable/disable unit explosion if killed by a meteor private constant boolean SHOW_INDICATOR = true // true/false to enable/disable cast area of effect indicator private constant boolean ALLOW_CAMERA_SHAKE = true // true/false to enable/disable camera shaking endglobals // Just IGNORE this function (Table) IF you are using a formula (Just fold it) private function Spell_Data_Table takes nothing returns nothing // Number of Meteors Table set nMeteors[1] = 30 set nMeteors[2] = 35 set nMeteors[3] = 40 set nMeteors[4] = 45 set nMeteors[5] = 50 // Minimum Damage Table set MinDamage[1] = 100.00 set MinDamage[2] = 125.00 set MinDamage[3] = 150.00 set MinDamage[4] = 175.00 set MinDamage[5] = 200.00 // Maximum Damage Table set MaxDamage[1] = 300.00 set MaxDamage[2] = 350.00 set MaxDamage[3] = 400.00 set MaxDamage[4] = 450.00 set MaxDamage[5] = 500.00 // Grand Area of Effect set GrandArea[1] = 800.00 set GrandArea[2] = 850.00 set GrandArea[3] = 900.00 set GrandArea[4] = 950.00 set GrandArea[5] = 1000.00 // Maximum Area of Effect per Meteor set LargeArea[1] = 160.00 set LargeArea[2] = 170.00 set LargeArea[3] = 180.00 set LargeArea[4] = 190.00 set LargeArea[5] = 200.00 // Minimum Area of Effect per Meteor set SmallArea[1] = 110.00 set SmallArea[2] = 120.00 set SmallArea[3] = 130.00 set SmallArea[4] = 140.00 set SmallArea[5] = 150.00 //==================================================================================================== // End of User-edit data // //==================================================================================================== endfunction private function MeteorsNumber takes integer al returns integer local integer prevNMet static if NUM_TABLE then return nMeteors[al] else if al == 1 then set prevNMet = 0 else set prevNMet = MeteorsNumber(al - 1) endif return NUM_CF + NUM_LF * al + R2I(NUM_PLF) * prevNMet endif endfunction private function DamageMin takes integer al returns real local real prevMinDmg static if D_MIN_TABLE then return MinDamage[al] else if al == 1 then set prevMinDmg = 0. else set prevMinDmg = DamageMin(al - 1) endif return D_MIN_CF + D_MIN_LF * al + D_MIN_PLF * prevMinDmg endif endfunction private function DamageMax takes integer al returns real local real prevMaxDmg static if D_MAX_TABLE then return MaxDamage[al] else if al == 1 then set prevMaxDmg = 0. else set prevMaxDmg = DamageMax(al - 1) endif return D_MAX_CF + D_MAX_LF * al + D_MAX_PLF * prevMaxDmg endif endfunction private function AreaGrand takes integer al returns real local real prevGrArea static if GR_TABLE then return GrandArea[al] else if al == 1 then set prevGrArea = 0. else set prevGrArea = AreaGrand(al - 1) endif return GR_CF + GR_LF * al + GR_PLF * prevGrArea endif endfunction private function MinAreaPerMeteor takes integer al returns real local real prevMinA static if MINR_TABLE then return SmallArea[al] else if al == 1 then set prevMinA = 0. else set prevMinA = MinAreaPerMeteor(al - 1) endif return MINR_CF + MINR_LF * al + MINR_PLF * prevMinA endif endfunction private function MaxAreaPerMeteor takes integer al returns real local real prevMaxA static if MAXR_TABLE then return LargeArea[al] else if al == 1 then set prevMaxA = 0. else set prevMaxA = MaxAreaPerMeteor(al - 1) endif return MAXR_CF + MAXR_LF * al + MAXR_PLF * prevMaxA endif endfunction private function GetSpellTargetXBounded takes nothing returns real local real x = GetSpellTargetX() if x < MIN_X then return MIN_X + SAFETY_OFFSET elseif x > MAX_X then return MAX_X - SAFETY_OFFSET else return x endif endfunction private function GetSpellTargetYBounded takes nothing returns real local real y = GetSpellTargetY() if y < MIN_Y then return MIN_Y + SAFETY_OFFSET elseif y > MAX_Y then return MAX_Y - SAFETY_OFFSET else return y endif endfunction private function MatchingUnit takes unit u,player owner returns boolean return not( IsUnitType(u,UNIT_TYPE_DEAD) or/* */ IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) or/* */( FRIENDLY and IsUnitAlly(u,owner)) or/* */(not FLYING and IsUnitType(u,UNIT_TYPE_FLYING)) or/* */(not GROUND and IsUnitType(u,UNIT_TYPE_GROUND)) or/* */(not STRUCTURE and IsUnitType(u,UNIT_TYPE_STRUCTURE))) endfunction private function meteorDamageUnits takes player owner,unit caster,real X, real Y,real rad,real damage returns nothing local unit target call GroupEnumUnitsInRange(bj_lastCreatedGroup,X,Y,rad,null) loop set target = FirstOfGroup(bj_lastCreatedGroup) exitwhen target == null if MatchingUnit(target,owner) then static if KILLS_EXPLODE then call SetUnitExploded(target,true) endif call UnitDamageTarget(caster,target,damage,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_FIRE,null) static if KILLS_EXPLODE then call SetUnitExploded(target,false) endif endif call GroupRemoveUnit(bj_lastCreatedGroup,target) endloop endfunction /* this function/filter is not needed for now and is turned off private function matchingDestructable takes nothing returns boolean return GetDestructableTypeId(GetFilterDestructable()) == WHO_KNOWS_WHAT_TYPE endfunction*/ private function meteorDamageDestructables takes nothing returns nothing call UnitDamageTarget(CASTER,GetEnumDestructable(),DAMAGE,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_FIRE,null) endfunction private struct Meteor extends array player owner unit caster unit target_indicator unit meteor real TX real TY real slope real const real face real grandarea real minarea real maxarea real mindamage real maxdamage integer meteors integer ibem // Interval Between Each Meteor integer cfm // Current Falling Meteors static method cameraShake takes thistype this returns nothing local integer i = 0 local real camX = GetCameraTargetPositionX() local real camY = GetCameraTargetPositionY() local real dx = this.TX - camX local real dy = this.TY - camY local real x1 = SquareRoot( dx*dx + dy*dy ) local real x2 local real magnitude loop exitwhen i >= index set this = temp_this[i] set dx = this.TX - camX set dy = this.TY - camY set x2 = SquareRoot( dx*dx + dy*dy ) if x1 > x2 then set x1 = x2 endif set i = i + 1 endloop set magnitude = 20.0 * Pow(bj_E,- 0.001 * x1) // magnitude = 20*e^(-x) call CameraSetSourceNoiseEx(magnitude,1000.,false) call CameraSetTargetNoiseEx(magnitude,1000.,false) if index == 0 then call CameraSetSourceNoise(0, 0) call CameraSetTargetNoise(0, 0) endif endmethod implement CTL local integer i = 0 // Instance Counter index local integer j = 0 // Meteor Counter index local unit u // This Dummy Unit local unit nu // Next Dummy Unit local real x // This Meteor X local real y // This Meteor Y local real z // This Meteor Z local real ix // This Meteor Initial X local real iy // This Meteor Initial Y local real tx // This Meteor Target X local real ty // This Meteor Target Y local real dx // Delta X local real dy // Delta Y local real dv // XY Plane variable local real face // This Meteor Facing local real slope // This Meteor Fall Line Slope local real const // This Meteor Fall Line Constant local real ratio // This Meteor Scaling Ratio local real ntx // Next Target X local real nty // Next Target Y local real nface // Next Facing local real nix // Next Initial X local real niy // Next Initial Y local real niz // Next Initial Z local real rnd_rad // Random Radius local real rnd_ang // Random Angle local real bound // Bound Size of Falling Meteor w.r.t Grand Area local real scale // Next Meteor Scaling local real nratio // Next Meteor Scaling Ratio local real accurate_radius // Accurate Radius local real accurate_damage // Accurate Damage local rect effectrect // effective Rect for destructables implement CTLExpire set this.ibem = this.ibem - 1 if this.ibem <= 0 then set this.ibem = GetRandomInt(INT_MIN,INT_MAX) set this.cfm = this.cfm + 1 if this.cfm <= this.meteors then // launch another meteor set bound = this.grandarea - this.maxarea loop set rnd_rad = GetRandomReal(0.0,bound) set rnd_ang = GetRandomReal(0.0,2.*bj_PI) set ntx = this.TX + rnd_rad*Cos(rnd_ang) set nty = this.TY + rnd_rad*Sin(rnd_ang) exitwhen ntx > MIN_X and ntx < MAX_X and nty > MIN_Y and nty < MAX_Y endloop loop set nface = GetRandomReal(0.0,2.*bj_PI) set nix = ntx - INIT_DIST * Cos(nface) set niy = nty - INIT_DIST * Sin(nface) exitwhen nix > MIN_X and nix < MAX_X and niy > MIN_Y and niy < MAX_Y endloop set niz = GetRandomReal(H_MIN,H_MAX) set nu = CreateUnit(this.owner,M_DUMMY_ID,nix,niy,nface*bj_RADTODEG) call SetUnitPathing(nu,false) set scale = GetRandomReal(SCALE_MIN,SCALE_MAX) set nratio = (scale - SCALE_MIN)/(SCALE_MAX-SCALE_MIN) call SetUnitScale(nu,scale,scale,scale) call SetUnitFlyHeight(nu,niz,0.0) call SaveUnitHandle(mht,this,this.cfm,nu) call SaveBoolean(mht,this,this.cfm,false) call SaveReal(mht, this, this.cfm,ntx) call SaveReal(mht, this,-this.cfm,nty) call SaveReal(mht,-this, this.cfm,nix) call SaveReal(mht,-this,-this.cfm,niy) call SaveReal(mht, this + HT_OFFSET, this.cfm,nface) call SaveReal(mht, this + HT_OFFSET,-this.cfm,nratio) call SaveReal(mht,-this - HT_OFFSET, this.cfm,-niz/INIT_DIST) call SaveReal(mht,-this - HT_OFFSET,-this.cfm,niz) endif endif set j = 1 loop exitwhen j > this.cfm set u = LoadUnitHandle(mht,this,j) if not(LoadBoolean(mht,this,j)) then set tx = LoadReal(mht, this, j) set ty = LoadReal(mht, this,-j) set ix = LoadReal(mht,-this, j) set iy = LoadReal(mht,-this,-j) set x = GetUnitX(u) set y = GetUnitY(u) set dx = tx - x set dy = ty - y set ratio = LoadReal(mht,this + HT_OFFSET,-j) set accurate_radius = ratio * (this.maxarea - this.minarea ) + this.minarea set accurate_damage = ratio * (this.maxdamage - this.mindamage) + this.mindamage if SquareRoot( dx*dx + dy*dy ) < CHECK_DIST or GetUnitFlyHeight(u) < CHECK_DIST then call KillUnit(u) call SaveBoolean(mht,this,j,true) // Shake camera static if ALLOW_CAMERA_SHAKE then call cameraShake(this) endif // Do Damage stuff call meteorDamageUnits(this.owner,this.caster,tx,ty,accurate_radius,accurate_damage) static if DESTRUCTABLES then set CASTER = this.caster set DAMAGE = accurate_damage/DESTRUCTABLE_FACTOR set effectrect = Rect(tx - accurate_radius, ty - accurate_radius, tx + accurate_radius, ty + accurate_radius) call EnumDestructablesInRect(effectrect,null,function meteorDamageDestructables) call RemoveRect(effectrect) endif if IsUnitType(LoadUnitHandle(mht,this,this.meteors),UNIT_TYPE_DEAD) and/* */ LoadUnitHandle(mht,this,this.meteors) != null then set index = index - 1 set temp_this[this] = temp_this[index] call cameraShake(this) static if SHOW_INDICATOR then call RemoveUnit(this.target_indicator) set this.target_indicator = null endif call this.destroy() call FlushChildHashtable(mht, this) call FlushChildHashtable(mht,-this) call FlushChildHashtable(mht, this + HT_OFFSET) call FlushChildHashtable(mht,-this - HT_OFFSET) endif else // Move the meteor set face = LoadReal(mht,this + HT_OFFSET,j) set slope = LoadReal(mht,-this - HT_OFFSET,j) set const = LoadReal(mht,-this - HT_OFFSET,-j) set x = x + STEP * Cos(face) set y = y + STEP * Sin(face) set dx = x - ix set dy = y - iy set dv = SquareRoot( dx*dx + dy*dy ) set z = slope * dv + const call SetUnitX(u,x) call SetUnitY(u,y) call SetUnitFlyHeight(u,z,0.0) endif endif set j = j + 1 endloop implement CTLNull set u = null set nu = null set effectrect = null implement CTLEnd static method meteorCall takes unit caster, real tx, real ty returns nothing local thistype this = create() local integer al = GetUnitAbilityLevel(caster,ABILITY_ID) local unit u // Dummy Unit local real cx // Cast Point X local real cy // Cast Point Y local real ix // First Meteor Initial X local real iy // First Meteor Initial Y local real iz // First Meteor Initial Z local real dx local real dy local real face local real scale local real ratio local real indicator_scale = 9. + I2R(al) set temp_this[index] = this set this.caster = caster set this.owner = GetOwningPlayer(caster) set this.TX = tx set this.TY = ty set cx = GetUnitX(caster) set cy = GetUnitY(caster) set dx = tx - cx set dy = ty - cy set face = Atan2(dy,dx) set ix = tx - INIT_DIST * Cos(face) set iy = ty - INIT_DIST * Sin(face) set iz = GetRandomReal(H_MIN,H_MAX) static if SHOW_INDICATOR then set this.target_indicator = CreateUnit(this.owner,I_DUMMY_ID,tx,ty,0.0) call SetUnitVertexColor(this.target_indicator, 255,255,255,255) call SetUnitTimeScale(this.target_indicator,0.7) call SetUnitScale(this.target_indicator,indicator_scale,indicator_scale,indicator_scale) call SetUnitPathing(this.target_indicator,false) call SetUnitX(this.target_indicator,tx) call SetUnitY(this.target_indicator,ty) endif set u = CreateUnit(this.owner,M_DUMMY_ID,ix,iy,face*bj_RADTODEG) call SetUnitPathing(u,false) static if INIT_MAX_D then set scale = SCALE_MAX else set scale = GetRandomReal(SCALE_MIN,SCALE_MAX) endif set ratio = (scale - SCALE_MIN)/(SCALE_MAX-SCALE_MIN) call SetUnitScale(u,scale,scale,scale) call SetUnitFlyHeight(u,iz,0.0) set this.cfm = 1 set this.ibem = GetRandomInt(INT_MIN,INT_MAX) call SaveUnitHandle(mht,this,1,u) call SaveBoolean(mht,this,1,false) call SaveReal(mht, this, 1,tx) call SaveReal(mht, this,-1,ty) call SaveReal(mht,-this, 1,ix) call SaveReal(mht,-this,-1,iy) call SaveReal(mht, this + HT_OFFSET, 1,face) call SaveReal(mht, this + HT_OFFSET,-1,ratio) call SaveReal(mht,-this - HT_OFFSET, 1,-iz/INIT_DIST) call SaveReal(mht,-this - HT_OFFSET,-1,iz) set this.meteors = MeteorsNumber(al) set this.grandarea = AreaGrand(al) set this.maxarea = MaxAreaPerMeteor(al) set this.minarea = MinAreaPerMeteor(al) set this.maxdamage = DamageMax(al) set this.mindamage = DamageMin(al) set u = null set index = index + 1 endmethod endstruct private function MeteorSwarm_Conditions takes nothing returns boolean if GetSpellAbilityId() == ABILITY_ID then call Meteor.meteorCall(GetTriggerUnit(),GetSpellTargetXBounded(),GetSpellTargetYBounded()) endif return false endfunction private function Init_MeteorSwarm takes nothing returns nothing local trigger t = CreateTrigger() call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition( t, function MeteorSwarm_Conditions ) call RemoveUnit(CreateUnit(Player(12),M_DUMMY_ID,0.,0.,0.)) call RemoveUnit(CreateUnit(Player(12),I_DUMMY_ID,0.,0.,0.)) call Spell_Data_Table() set MIN_X = GetCameraBoundMinX() - 512.000 set MIN_Y = GetCameraBoundMinY() - 256.000 set MAX_X = GetCameraBoundMaxX() + 512.000 set MAX_Y = GetCameraBoundMaxY() + 256.000 set t = null endfunction endscope