Ayanami
칼리
- Reaction score
- 288
Introduction
Made a gravity themed spell pack, out of pure boredom
Requirements
- Damage
- Timer32
- GTrigger
- GroupUtils
The spells:
Details
- The spells are vJASS
- They should be leak-less and lag-less
- It is MUI, meaning can be cast many times at the same instance
Implementation
Spells
Inversion Field
Description:
Creates an inverse gravity field at the target point. The inverse field causes enemy units to be trapped within the gravity matrix. The gravity field rejects any allied units, causing them to be forced outside of the field. Due to the gravitational differences between the 2 mediums, no units can enter or leave the field at any time and any damage taken from different mediums are reduced. Target area of 500 at all levels. Lasts 4 seconds.
Level 1 - Field area of 500. Reduces damage taken by 80%.
Level 2 - Field area of 450. Reduces damage taken by 70%.
Level 3 - Field area of 400. Reduces damage taken by 60%.
Level 4 - Field area of 350. Reduces damage taken by 50%.
Cast Range: 600
Target Type: Point Area
Cooldown: 22/20/18/16 seconds
Screenshot:
Code:
Gravity Matrix
Description:
Constantly generates an unstable gravity field in an area of 1000. In this unstable gravitized zone, all damage loses its power if the damage source is further away from the hero. Further away the damage source is, less damage this unit takes, with a maximum reduction at above 1000 distance. The blocked damage is converted into energy, and absorbed. For every 100 mana absorbed, an automatic gravity force is unleashed, dealing 100 damage to all units within 500 range. Insufficient mana results in a reset in mana counter.
Level 1 - Maximum reduction of 17%.
Level 2 - Maximum reduction of 28%.
Level 3 - Maximum reduction of 39%.
Level 4 - Maximum reduction of 50%.
Passive
Screenshot:
Code:
Gravity Flux
Description:
Creates a heavy gravity current at target point. The sudden change in gravity causes a leakage of nearby enemy units' mana. The mana materializes in a ball form, which then travels towards the target point. Upon arrival at the target point, the volatile energy balls violently explodes, unleashing a devastating gravity force, dealing damage equal to the total mana absrobed to all units within the area. Damage is distributed evenly among all enemy units. Area of 400 at all levels.
Level 1 - 50 mana absorption.
Level 2 - 75 mana absorption.
Level 3 - 100 mana absorption.
Level 4 - 125 mana absorption.
Cast Range: 700
Target Type: Point
Cooldown: 12 seconds
Screenshot:
Code:
Graviton Acceleration
Description:
Causes a huge amount of gravitons to accelerate towards the target point, creating a black hole. The black hole causes all enemy units within 600 range to have their mana drained periodically and dragged towards the target point. The less mana enemies have, the stronger the dragging force. At 0 mana, enemies cannot resist the dragging force and is pulled towards the center and receives damage instead of mana drain. Lasts 5 seconds.
Level 1 - 20 mana per second.
Level 2 - 30 mana per second.
Level 3 - 40 mana per second.
Cast Range: 300
Target Type: Point
Cooldown: 75 seconds
Screenshot:
Code:
Credits
Changelogs
Feedback will be appreciated.
Made a gravity themed spell pack, out of pure boredom
Requirements
- Damage
- Timer32
- GTrigger
- GroupUtils
The spells:
- Inversion Field [Active]
- Gravity Matrix [Passive]
- Gravity Flux [Active]
- Graviton Acceleration [Active]
Details
- The spells are vJASS
- They should be leak-less and lag-less
- It is MUI, meaning can be cast many times at the same instance
Implementation
JASS:
//==============================================================================
// GRAVITY SPELLPACK v1.2
// BY Ayanami
//==============================================================================
//==============================================================================
// REQUIREMENTS
//==============================================================================
// - JNGP
// - Damage
// * Event
// * AIDS
// - Timer32
// - GTrigger
// - GroupUtils
//==============================================================================
//==============================================================================
// IMPLEMENTATION
//==============================================================================
// 1) Copy the whole "Required Systems" Trigger folder
// 2) Save the map, it will take a bit longer than usual
// 3) Close the map and re-open it, then disable or delete the trigger "Objects"
// 4) Go to the Import Manager and export all resources, then import into map
// 5) Copy all 4 abilities under "Night Elf"
// 6) Copy the whole "Gravity Spellpack" Trigger folder
//==============================================================================
Spells
Inversion Field
Description:
Creates an inverse gravity field at the target point. The inverse field causes enemy units to be trapped within the gravity matrix. The gravity field rejects any allied units, causing them to be forced outside of the field. Due to the gravitational differences between the 2 mediums, no units can enter or leave the field at any time and any damage taken from different mediums are reduced. Target area of 500 at all levels. Lasts 4 seconds.
Level 1 - Field area of 500. Reduces damage taken by 80%.
Level 2 - Field area of 450. Reduces damage taken by 70%.
Level 3 - Field area of 400. Reduces damage taken by 60%.
Level 4 - Field area of 350. Reduces damage taken by 50%.
Cast Range: 600
Target Type: Point Area
Cooldown: 22/20/18/16 seconds
Screenshot:

Code:
JASS:
scope InversionField // requires Damage, Timer32, GTrigger, GroupUtils
//===========================================================================
// CONFIGURABLES
//===========================================================================
globals
private constant integer ABILID = 'ABIF' // raw code of ability "Inversion Field"
private constant integer ABILDUMID = 'AIF0' // raw code of ability "Inversion Field (Buff)"
private constant integer BUFFID = 'BIF0' // raw code of buff "Inversion Field"
private constant integer PRELOADID = 'prel' // raw code of unit "Preloader"
private constant string WALLART = "Abilities\\Spells\\Undead\\DarkSummoning\\DarkSummonMissile.mdl" // model used as field wall
private constant string DAMAGEART = "Abilities\\Weapons\\WingedSerpentMissile\\WingedSerpentMissile.mdl" // model used when damaged
private constant string DAMAGEATTACH = "chest" // attachment point of model
private constant real THICKNESS = 100.0 // thickness of the field wall
private constant boolean GFBOOLEAN = true // set to true if Gravity Flux will be used
private constant boolean GABOOLEAN = true // set to true if Graviton Acceleration will be used
endglobals
private function GetCastArea takes integer level returns real
return 500.0 // area of cast
endfunction
private function GetArea takes integer level returns real
return 550.0 - (50.0 * level) // area of field
endfunction
private function GetDuration takes integer level returns real
return 4.0 // duration of spell
endfunction
private function GetReduction takes integer level returns real
return 0.9 - (0.1 * level) // reduction in damage taken where, 1.0 == 100%
endfunction
private function GetWallCount takes integer level returns integer
return 30 - (3 * level) // number of effect created
endfunction
//===========================================================================
// END CONFIGURABLES
//===========================================================================
// Do not touch below unless you know what you're doing
native UnitAlive takes unit id returns boolean
private struct Data
real duration
real aoe
real castaoe
real x
real y
integer level
group tgroup
static thistype tempData
static unit tempCaster
static hashtable Hash = InitHashtable()
private static method staticCheck takes unit u returns boolean
local boolean check = true
static if GFBOOLEAN then
set check = GetUnitTypeId(u) != GravityFlux_DUMMYID
endif
static if GABOOLEAN then
if not check then
set check = not IsUnitInGroup(u, GravitonAcceleration_Checkgroup)
endif
endif
return check
endmethod
private static method groupFilter takes nothing returns boolean
local thistype this = tempData
local unit u = GetFilterUnit()
local real a
local real dx
local real dy
if IsUnitEnemy(u, GetOwningPlayer(tempCaster)) and UnitAlive(u) then
if GetUnitAbilityLevel(u, ABILDUMID) == 0 then
call UnitAddAbility(u, ABILDUMID)
endif
call SetUnitAbilityLevel(u, ABILDUMID, this.level)
set u = null
return true
else
set dx = GetUnitX(u) - this.x
set dy = GetUnitY(u) - this.y
if dx * dx + dy * dy < this.aoe * this.aoe then
set a = Atan2(dy, dx)
set dx = this.x + (this.aoe + THICKNESS) * Cos(a)
set dy = this.y + (this.aoe + THICKNESS) * Sin(a)
call SetUnitX(u, dx)
call SetUnitY(u, dy)
endif
set u = null
endif
return false
endmethod
private static method groupFunc takes nothing returns nothing
local thistype this = tempData
local unit u = GetEnumUnit()
local real dx = GetUnitX(u) - this.x
local real dy = GetUnitY(u) - this.y
local real a
if GetUnitAbilityLevel(u, ABILDUMID) == 0 then
call UnitAddAbility(u, ABILDUMID)
call SetUnitAbilityLevel(u, ABILDUMID, this.level)
endif
if SquareRoot(dx * dx + dy * dy) > this.aoe - THICKNESS and thistype.staticCheck(u) then
set a = Atan2(dy, dx)
set dx = this.x + (this.aoe - THICKNESS - 50) * Cos(a)
set dy = this.y + (this.aoe - THICKNESS - 50) * Sin(a)
call SetUnitX(u, dx)
call SetUnitY(u, dy)
endif
set u = null
endmethod
private static method groupAction takes nothing returns boolean
local thistype this = tempData
local unit u = GetFilterUnit()
local real dx
local real dy
local real a
if not IsUnitInGroup(u, this.tgroup) and thistype.staticCheck(u) then
set a = Atan2(GetUnitY(u) - this.y, GetUnitX(u) - this.x)
set dx = this.x + (this.aoe + THICKNESS + 50) * Cos(a)
set dy = this.y + (this.aoe + THICKNESS + 50) * Sin(a)
call SetUnitX(u, dx)
call SetUnitY(u, dy)
endif
set u = null
return false
endmethod
private static method removeGroup takes nothing returns nothing
call UnitRemoveAbility(GetEnumUnit(), ABILDUMID)
call UnitRemoveAbility(GetEnumUnit(), BUFFID)
endmethod
private method periodic takes nothing returns nothing
local integer i
local real dx
local real dy
if this.duration <= 0 then
set i = LoadInteger(Hash, this, StringHash("count"))
loop
exitwhen i < 0
call DestroyEffect(LoadEffectHandle(Hash, this, i))
set i = i - 1
endloop
call ForGroup(this.tgroup, function thistype.removeGroup)
call ReleaseGroup(this.tgroup)
call FlushChildHashtable(Hash, this)
call this.stopPeriodic()
call this.deallocate()
else
set tempData = this
call ForGroup(this.tgroup, function thistype.groupFunc)
call GroupEnumUnitsInArea(ENUM_GROUP, this.x, this.y, this.aoe + THICKNESS, Filter(function thistype.groupAction))
set this.duration = this.duration - T32_PERIOD
endif
endmethod
implement T32x
static method actions takes nothing returns nothing
local thistype this = thistype.allocate()
local unit u = GetTriggerUnit()
local integer i
local integer count
local real a
local real x
local real y
set this.level = GetUnitAbilityLevel(u, ABILID)
set this.duration = GetDuration(this.level)
set this.aoe = GetArea(this.level)
set this.castaoe = GetCastArea(this.level)
set this.x = GetSpellTargetX()
set this.y = GetSpellTargetY()
set this.tgroup = NewGroup()
set tempCaster = u
set tempData = this
call GroupEnumUnitsInArea(this.tgroup, this.x, this.y, this.castaoe, Filter(function thistype.groupFilter))
set count = GetWallCount(this.level)
set i = 0
loop
exitwhen i == count
set a = ((bj_PI * 2) / count) * i
set x = this.x + this.aoe * Cos(a)
set y = this.y + this.aoe * Sin(a)
call SaveEffectHandle(Hash, this, i, AddSpecialEffect(WALLART, x, y))
set i = i + 1
endloop
call SaveInteger(Hash, this, StringHash("count"), i - 1)
call this.startPeriodic()
set u = null
endmethod
private static method damageReduction takes nothing returns boolean
local unit u = GetEventDamageSource()
local unit t = GetTriggerUnit()
local integer sourcelevel = GetUnitAbilityLevel(u, ABILDUMID)
local integer targetlevel = GetUnitAbilityLevel(t, ABILDUMID)
if sourcelevel > 0 and targetlevel > 0 then
elseif sourcelevel > 0 then
call Damage_Block(GetEventDamage() * GetReduction(sourcelevel))
call DestroyEffect(AddSpecialEffectTarget(DAMAGEART, t, DAMAGEATTACH))
elseif targetlevel > 0 then
call Damage_Block(GetEventDamage() * GetReduction(targetlevel))
call DestroyEffect(AddSpecialEffectTarget(DAMAGEART, t, DAMAGEATTACH))
endif
set u = null
set t = null
return false
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
local unit u = CreateUnit(Player(13), PRELOADID, 0, 0, 0)
call GT_RegisterStartsEffectEvent(t, ABILID)
call TriggerAddAction(t, function thistype.actions)
set t = CreateTrigger()
call Damage_RegisterEvent(t)
call TriggerAddCondition(t, Condition(function thistype.damageReduction))
set t = null
//preload
call UnitAddAbility(u, ABILDUMID)
call RemoveUnit(u)
set u = null
endmethod
endstruct
endscope
Gravity Matrix
Description:
Constantly generates an unstable gravity field in an area of 1000. In this unstable gravitized zone, all damage loses its power if the damage source is further away from the hero. Further away the damage source is, less damage this unit takes, with a maximum reduction at above 1000 distance. The blocked damage is converted into energy, and absorbed. For every 100 mana absorbed, an automatic gravity force is unleashed, dealing 100 damage to all units within 500 range. Insufficient mana results in a reset in mana counter.
Level 1 - Maximum reduction of 17%.
Level 2 - Maximum reduction of 28%.
Level 3 - Maximum reduction of 39%.
Level 4 - Maximum reduction of 50%.
Passive
Screenshot:

Code:
JASS:
scope GravityMatrix initializer OnInit // requires Damage, GTrigger, GroupUtils
//===========================================================================
// CONFIGURABLES
//===========================================================================
globals
private constant integer ABILID = 'ABGM' // raw code of ability "Gravity Matrix"
private constant string DAMAGEART = "Abilities\\Weapons\\WingedSerpentMissile\\WingedSerpentMissile.mdl" // model used when damaged
private constant string DAMAGEATTACH = "chest" // attachment point of model
private constant string MANAART = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl" // model used when damaging enemy units
private constant string MANAATTACH = "origin" // attachment point of model
private constant attacktype ATK = ATTACK_TYPE_NORMAL // attack type of damage
private constant damagetype DMG = DAMAGE_TYPE_MAGIC // damage type of damage
private constant weapontype WEP = WEAPON_TYPE_WHOKNOWS // weapon type of damage
endglobals
private function GetDistance takes integer level returns real
return 1000.0 // distance where damage reduction becomes maximum
endfunction
private function GetReduction takes integer level returns real
return 0.06 + (0.11 * level) // maximum damage reduction where, 1.00 = 100%
endfunction
private function GetManaInterval takes integer level returns real
return 100.0 // every interval of mana where damage is unleashed
endfunction
private function GetArea takes integer level returns real
return 500.0 // area of damage
endfunction
//===========================================================================
// END CONFIGURABLES
//===========================================================================
// Do not touch below unless you know what you're doing
native UnitAlive takes unit id returns boolean
globals
private hashtable Hash = InitHashtable()
private trigger Trig
private unit Tempunit
private real Tempreal
endglobals
private function GroupFunc takes nothing returns boolean
local unit u = GetFilterUnit()
if IsUnitEnemy(u, GetOwningPlayer(Tempunit)) and UnitAlive(u) then
call DisableTrigger(Trig)
call UnitDamageTargetEx(Tempunit, u, Tempreal, true, false, ATK, DMG, WEP)
call DestroyEffect(AddSpecialEffectTarget(MANAART, u, MANAATTACH))
call EnableTrigger(Trig)
endif
set u = null
return false
endfunction
private function Learn takes nothing returns boolean
local unit u = GetTriggerUnit()
if GetUnitAbilityLevel(u, ABILID) == 1 then
call SaveReal(Hash, GetHandleId(u), 0, 0.0)
endif
set u = null
return false
endfunction
private function Actions takes nothing returns boolean
local unit u
local integer i
local integer count
local integer id
local real r
local real x
local real y
local real dist
local real maxdist
set Tempunit = GetTriggerUnit()
set i = GetUnitAbilityLevel(Tempunit, ABILID)
set id = GetHandleId(Tempunit)
set maxdist = GetDistance(i)
if i > 0 then
set u = GetEventDamageSource()
set x = GetUnitX(u) - GetUnitX(Tempunit)
set y = GetUnitY(u) - GetUnitY(Tempunit)
set dist = SquareRoot(x * x + y * y)
if dist > maxdist then
set dist = maxdist
endif
set r = GetEventDamage() * GetReduction(i) * (dist / maxdist)
call Damage_Block(r)
call DestroyEffect(AddSpecialEffectTarget(DAMAGEART, Tempunit, DAMAGEATTACH))
call SetUnitState(Tempunit, UNIT_STATE_MANA, GetUnitState(Tempunit, UNIT_STATE_MANA) + r)
set r = r + LoadReal(Hash, id, 0)
if r >= GetManaInterval(i) then
set count = R2I(r / GetManaInterval(i))
call SaveReal(Hash, id, 0, r - (GetManaInterval(i) * count))
if GetUnitState(Tempunit, UNIT_STATE_MANA) >= GetManaInterval(i) then
set Tempreal = GetManaInterval(i)
loop
exitwhen count == 0
call GroupEnumUnitsInArea(ENUM_GROUP, GetUnitX(Tempunit), GetUnitY(Tempunit), GetArea(i), Filter(function GroupFunc))
call SetUnitState(Tempunit, UNIT_STATE_MANA, GetUnitState(Tempunit, UNIT_STATE_MANA) - GetManaInterval(i))
set count = count - 1
endloop
endif
else
call SaveReal(Hash, id, 0, r)
endif
endif
set u = null
return false
endfunction
private function OnInit takes nothing returns nothing
local trigger t = CreateTrigger()
call GT_RegisterLearnsAbilityEvent(t, ABILID)
call TriggerAddCondition(t, Condition(function Learn))
set Trig = CreateTrigger()
call Damage_RegisterEvent(Trig)
call TriggerAddCondition(Trig, Condition(function Actions))
set t = null
endfunction
endscope
Gravity Flux
Description:
Creates a heavy gravity current at target point. The sudden change in gravity causes a leakage of nearby enemy units' mana. The mana materializes in a ball form, which then travels towards the target point. Upon arrival at the target point, the volatile energy balls violently explodes, unleashing a devastating gravity force, dealing damage equal to the total mana absrobed to all units within the area. Damage is distributed evenly among all enemy units. Area of 400 at all levels.
Level 1 - 50 mana absorption.
Level 2 - 75 mana absorption.
Level 3 - 100 mana absorption.
Level 4 - 125 mana absorption.
Cast Range: 700
Target Type: Point
Cooldown: 12 seconds
Screenshot:

Code:
JASS:
scope GravityFlux // requires Damage, Timer32, GTrigger, GroupUtils
native UnitAlive takes unit id returns boolean
//===========================================================================
// CONFIGURABLES
//===========================================================================
globals
private constant integer ABILID = 'ABGF' // raw code of ability "Gravity Flux"
public constant integer DUMMYID = 'grFl' // raw code of unit "Gravity Flux Dummy"
private constant boolean SELF = true // true if includes mana cost
private constant real TIME = 1.0 // time taken for balls to reach target point
private constant string ART = "Objects\\Spawnmodels\\NightElf\\NEDeathMedium\\NEDeath.mdl" // effect upon enemy damage
private constant string ARTPOINT = "origin" // attachment point of damage effect
private constant string DEATHART = "Objects\\Spawnmodels\\NightElf\\NEDeathMedium\\NEDeath.mdl" // effect upon projectile death
private constant attacktype ATK = ATTACK_TYPE_NORMAL // attack type of damage
private constant damagetype DMG = DAMAGE_TYPE_MAGIC // damage type of damage
private constant weapontype WEP = WEAPON_TYPE_WHOKNOWS // weapon type of damage
endglobals
private function GetMana takes integer level returns real
return 25.0 + (25.0 * level) // mana absorbed from unit
endfunction
private function GetTargetAoe takes integer level returns real
return 400.0 // target area of effect
endfunction
private function GetAoe takes integer level returns real
return 400.0 // area of effect of damage
endfunction
private function FilterTarget takes unit owner, unit target returns boolean
return UnitAlive(target) or IsUnitEnemy(target, GetOwningPlayer(owner)) // targets allowed for damage
endfunction
//===========================================================================
// END CONFIGURABLES
//===========================================================================
private struct Data
real duration
real mana
real x
real y
integer level
integer count = 0
group ballgroup
group damagegroup
unit caster
static Data tempData
static hashtable Hash = InitHashtable()
static unit tempUnit
static real tempX
static real tempY
static real tempReal
static integer tempInt
private static method damageFunc takes nothing returns nothing
local thistype this = tempData
local unit u = GetEnumUnit()
call UnitDamageTargetEx(this.caster, u, this.mana, true, false, ATK, DMG, WEP)
call DestroyEffect(AddSpecialEffectTarget(ART, u, ARTPOINT))
set u = null
endmethod
private static method countFunc takes nothing returns boolean
local thistype this = tempData
local unit u = GetFilterUnit()
if IsUnitEnemy(u, GetOwningPlayer(this.caster)) and UnitAlive(u) then
set this.count = this.count + 1
call GroupAddUnit(this.damagegroup, u)
endif
set u = null
return false
endmethod
private static method groupFunc takes nothing returns nothing
local thistype this = tempData
local unit u = GetEnumUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real a = Atan2(this.y - y, this.x - x)
local real dist = LoadReal(Hash, GetHandleId(u), 0)
set x = x + dist * Cos(a)
set y = y + dist * Sin(a)
call SetUnitPosition(u, x, y)
set u = null
endmethod
private static method filterFunc takes nothing returns boolean
local thistype this = tempData
local unit u = GetFilterUnit()
local real x
local real y
local real mana
local real unitmana
if FilterTarget(this.caster, u) then
set x = GetUnitX(u)
set y = GetUnitY(u)
set mana = GetMana(this.level)
set unitmana = GetUnitState(u, UNIT_STATE_MANA)
if unitmana < mana then
set mana = unitmana
endif
set this.mana = this.mana + mana
set tempUnit = CreateUnit(GetOwningPlayer(this.caster), DUMMYID, x, y, Atan2(this.y - y, this.x - x) * bj_RADTODEG)
call GroupAddUnit(this.ballgroup, tempUnit)
call SetUnitState(u, UNIT_STATE_MANA, unitmana - mana)
set x = x - this.x
set y = y - this.y
call SaveReal(Hash, GetHandleId(tempUnit), 0, (SquareRoot(x * x + y * y) / TIME) * T32_PERIOD)
endif
set u = null
return false
endmethod
private static method GroupFlush takes nothing returns nothing
local unit u = GetEnumUnit()
local thistype this = tempData
call FlushChildHashtable(Hash, GetHandleId(u))
call GroupRemoveUnit(this.ballgroup, u)
call RemoveUnit(u)
set u = null
endmethod
private method periodic takes nothing returns nothing
if this.duration <= 0 then
set tempData = this
call GroupEnumUnitsInArea(ENUM_GROUP, this.x, this.y, GetAoe(this.level), Filter(function thistype.countFunc))
if this.count > 0 then
set this.mana = this.mana / this.count
call ForGroup(this.damagegroup, function thistype.damageFunc)
endif
call DestroyEffect(AddSpecialEffect(DEATHART, this.x, this.y))
call ForGroup(this.ballgroup, function thistype.GroupFlush)
call ReleaseGroup(this.ballgroup)
call this.stopPeriodic()
call this.deallocate()
else
set tempData = this
call ForGroup(this.ballgroup, function thistype.groupFunc)
set this.duration = this.duration - T32_PERIOD
endif
endmethod
implement T32x
private static method create takes unit caster, integer level, real x, real y, real mana returns thistype
local thistype this = thistype.allocate()
set this.duration = TIME
set this.mana = mana
set this.x = x
set this.y = y
set this.level = level
set this.count = 0
set this.ballgroup = NewGroup()
set this.damagegroup = NewGroup()
set this.caster = caster
static if SELF then
set tempX = GetUnitX(this.caster)
set tempY = GetUnitY(this.caster)
set tempUnit = CreateUnit(GetOwningPlayer(this.caster), DUMMYID, tempX, tempY, Atan2(y - tempY, x - tempX) * bj_RADTODEG)
set tempX = tempX - this.x
set tempY = tempY - this.y
call GroupAddUnit(this.ballgroup, tempUnit)
call SaveReal(Hash, GetHandleId(tempUnit), 0, (SquareRoot(tempX * tempX + tempY * tempY) / TIME) * T32_PERIOD)
endif
set tempData = this
call GroupEnumUnitsInArea(ENUM_GROUP, this.x, this.y, GetTargetAoe(this.level), Filter(function thistype.filterFunc))
call this.startPeriodic()
return this
endmethod
private static method manaTimeOut takes nothing returns nothing
local timer t = GetExpiredTimer()
call thistype.create(tempUnit, tempInt, tempX, tempY, tempReal - GetUnitState(tempUnit, UNIT_STATE_MANA))
call PauseTimer(t)
call DestroyTimer(t)
set t = null
endmethod
private static method actions takes nothing returns nothing
local timer t
set tempUnit = GetTriggerUnit()
set tempInt = GetUnitAbilityLevel(tempUnit, ABILID)
set tempX = GetSpellTargetX()
set tempY = GetSpellTargetY()
static if SELF then
set t = CreateTimer()
set tempReal = GetUnitState(tempUnit, UNIT_STATE_MANA)
call TimerStart(t, 0.00, false, function thistype.manaTimeOut)
else
call thistype.create(tempUnit, tempInt, tempX, tempY, 0)
endif
set t = null
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call GT_RegisterStartsEffectEvent(t, ABILID)
call TriggerAddAction(t, function thistype.actions)
set t = null
//preload
call RemoveUnit(CreateUnit(Player(13), DUMMYID, 0, 0, 0))
endmethod
endstruct
endscope
Graviton Acceleration
Description:
Causes a huge amount of gravitons to accelerate towards the target point, creating a black hole. The black hole causes all enemy units within 600 range to have their mana drained periodically and dragged towards the target point. The less mana enemies have, the stronger the dragging force. At 0 mana, enemies cannot resist the dragging force and is pulled towards the center and receives damage instead of mana drain. Lasts 5 seconds.
Level 1 - 20 mana per second.
Level 2 - 30 mana per second.
Level 3 - 40 mana per second.
Cast Range: 300
Target Type: Point
Cooldown: 75 seconds
Screenshot:

Code:
JASS:
scope GravitonAcceleration // requires Damage, Timer32, GTrigger, GroupUtils
//===========================================================================
// CONFIGURABLES
//===========================================================================
globals
private constant integer ABILID = 'ABGA' // raw code of ability "Graviton Acceleration"
private constant integer DUMMYID = 'grAc' // raw code of unit "Graviton Acceleration Dummy"
private constant real MAXSPEED = 200.0 // maximum drag speed
private constant real SPINRATE = 2.0 // number of spins in the center area per second
private constant string LIGHTNING = "DRAM" // lightning effect used, small note that lightning effect
// can generate lag when dealing with mass units
private constant boolean ALLOWLIGHT = true // true if lightning effect is used
private constant attacktype ATK = ATTACK_TYPE_NORMAL // attack type of damage
private constant damagetype DMG = DAMAGE_TYPE_MAGIC // damage type of damage
private constant weapontype WEP = WEAPON_TYPE_WHOKNOWS // weapon type of damage
endglobals
private function GetCenterAoe takes integer level returns real
return 100.0 // radius of center area
endfunction
private function GetAoe takes integer level returns real
return 600.0 // area of effect of spell
endfunction
private function GetAbsorbAmount takes integer level returns real
return 10.0 + (10.0 * level) // amount of mana absorbed per second
endfunction
private function GetDuration takes integer level returns real
return 5.0 // duration of spell
endfunction
//===========================================================================
// END CONFIGURABLES
//===========================================================================
native UnitAlive takes unit id returns boolean
globals
public group Checkgroup = CreateGroup()
endglobals
private struct Data
integer level
real x
real y
real duration
real amount
real angle
real center
real aoe
group track
unit caster
unit dummy
static Data tempData
static hashtable Hash = InitHashtable()
private static method groupFunc takes nothing returns nothing
local thistype this = tempData
local unit u = GetEnumUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real dx = x - this.x
local real dy = y - this.y
local real a
local real mana
local real dist = SquareRoot(dx * dx + dy * dy)
local integer id = GetHandleId(u)
local boolean check
if dist > this.aoe or not UnitAlive(u) then
call DestroyLightning(LoadLightningHandle(Hash, this, id))
call GroupRemoveUnit(this.track, u)
call GroupRemoveUnit(Checkgroup, u)
else
set mana = GetUnitState(u, UNIT_STATE_MANA)
if mana >= this.amount then
call SetUnitState(u, UNIT_STATE_MANA, mana - this.amount)
else
call UnitDamageTargetEx(this.caster, u, this.amount, true, false, ATK, DMG, WEP)
call SetUnitState(u, UNIT_STATE_MANA, 0)
endif
set check = mana >= 1
set a = LoadReal(Hash, id, 0) + (this.angle)
set dx = this.x + this.center * Cos(a)
set dy = this.y + this.center * Sin(a)
call MoveLightningEx(LoadLightningHandle(Hash, this, id), true, dx, dy, 0, x, y, GetUnitFlyHeight(u) + 50.0)
call SaveReal(Hash, id, 0, a)
if dist > this.center then
set a = Atan2(this.y - y, this.x - x)
if check then
set dist = MAXSPEED * T32_PERIOD
else
set dist = MAXSPEED * (1.0 - (mana / GetUnitState(u, UNIT_STATE_MAX_MANA))) * T32_PERIOD
endif
set dx = x + dist * Cos(a)
set dy = y + dist * Sin(a)
endif
if check then
call SetUnitX(u, dx)
call SetUnitY(u, dy)
else
call SetUnitPosition(u, dx, dy)
endif
endif
set u = null
endmethod
private static method filterFunc takes nothing returns boolean
local thistype this = tempData
local unit u = GetFilterUnit()
local real a
local real x
local real y
if IsUnitEnemy(u, GetOwningPlayer(this.caster)) and UnitAlive(u) and not IsUnitInGroup(u, this.track) then
set x = GetUnitX(u)
set y = GetUnitY(u)
set a = Atan2(y - this.y, x - this.x)
static if ALLOWLIGHT then
call SaveLightningHandle(Hash, this, GetHandleId(u), AddLightning(LIGHTNING, true, this.x + this.center + Cos(a), this.y + this.center + Sin(a), x, y))
endif
call SaveReal(Hash, GetHandleId(u), 0, a)
call GroupAddUnit(this.track, u)
call GroupAddUnit(Checkgroup, u)
endif
set u = null
return false
endmethod
private static method groupFlush takes nothing returns nothing
local thistype this = tempData
local unit u = GetEnumUnit()
local integer id = GetHandleId(u)
static if ALLOWLIGHT then
call DestroyLightning(LoadLightningHandle(Hash, this, id))
endif
call GroupRemoveUnit(Checkgroup, u)
set u = null
endmethod
private method periodic takes nothing returns nothing
set tempData = this
if this.duration <= 0 then
call KillUnit(this.dummy)
call ForGroup(this.track, function thistype.groupFlush)
call FlushChildHashtable(Hash, this)
call ReleaseGroup(this.track)
call this.stopPeriodic()
call this.deallocate()
else
call GroupEnumUnitsInArea(ENUM_GROUP, this.x, this.y, this.aoe, Filter(function thistype.filterFunc))
call ForGroup(this.track, function thistype.groupFunc)
set this.duration = this.duration - T32_PERIOD
endif
endmethod
implement T32x
static method actions takes nothing returns nothing
local thistype this = thistype.allocate()
set this.caster = GetTriggerUnit()
set this.level = GetUnitAbilityLevel(this.caster, ABILID)
set this.x = GetSpellTargetX()
set this.y = GetSpellTargetY()
set this.duration = GetDuration(this.level)
set this.amount = GetAbsorbAmount(this.level) * T32_PERIOD
set this.angle = bj_PI * 2 * (T32_PERIOD / SPINRATE)
set this.center = GetCenterAoe(this.level)
set this.aoe = GetAoe(this.level)
set this.track = NewGroup()
set this.dummy = CreateUnit(GetOwningPlayer(this.caster), DUMMYID, this.x, this.y, 0)
call this.startPeriodic()
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call GT_RegisterStartsEffectEvent(t, ABILID)
call TriggerAddAction(t, function thistype.actions)
set t = null
//preload
call RemoveUnit(CreateUnit(Player(13), DUMMYID, 0, 0, 0))
endmethod
endstruct
endscope
Credits
Code:
[B]Jesus4Lyf[/B]
- [URL="http://www.thehelper.net/forums/showthread.php/131287-Damage"]Damage[/URL]
* [URL="http://www.thehelper.net/forums/showthread.php/130752-Advanced-Indexing-Data-Storage"]AIDS[/URL]
* [URL="http://www.thehelper.net/forums/showthread.php/126846-Event"]Event[/URL]
- [URL="http://www.thehelper.net/forums/showthread.php/132538-Timer32"]Timer32[/URL]
- [URL="http://www.thehelper.net/forums/showthread.php/123288-GTrigger-Event-System"]GTrigger[/URL]
[B]Rising_Dusk[/B] - [URL="http://www.wc3c.net/showthread.php?t=104464"]GroupUtils[/URL]
[B]WILL THE ALMIGHTY[/B] - [URL="http://www.hiveworkshop.com/forums/models-530/black-hole-48468/?prev=search%3DBlackhole%26d%3Dicon%26r%3D200"]Graviton Acceleration Model[/URL]
Changelogs
Code:
[B]Version 1.0[/B]
- Initial release
[B]Version 1.1[/B]
[COLOR="red"]Inversion Field[/COLOR]
- Made number of special effects to be configurable
- Optimized trigger
[COLOR="red"]Gravity Matrix[/COLOR]
- Optimized trigger
[COLOR="red"]Gravity Flux[/COLOR]
- Made targets allowed to be configurable
- Optimized trigger
[COLOR="red"]Graviton Acceleration[/COLOR]
- Added a line to preload dummy unit
- Fixed a bug where lightning effects were not destroyed when 2 or more instances of the skill were running
- Optimized trigger
[B]Version 1.2[/B]
- Reworked code using Timer32, GTrigger and GroupUtils, instead of KeyTimers2 and Recycle
Attachments
-
111.1 KB Views: 384
-
140.3 KB Views: 548