Flare
Stops copies me!
- Reaction score
- 662
My second vJASS spell. [DEL]This version is working, but it isn't VERY customizable (the only thing that would be very customizable would be mana cap).[/DEL]
[DEL](By very customizable, I mean you can't adjust it to suit a particular hero stat, or the ability's level. This will be added in one of the next few releases, if I get around to it)[/DEL]
Technical details:
Made in vJASS
Requires NewGen World Editor
Requires Cohadar's ABC Struct Attachment system
MUI
Lagless
Leakless to my knowledge
Importing instructions
Tooltip/Description
The hero creates an orb of mana, which absorbs mana from surrounding enemies. When the caster stops channelling, the orb becomes unstable and detonates, dealing damage based on amount of mana stored.
Size of the orb increases as current mana increases.
Also, mana will NOT be drained from enemies once the orb is maxed out.
NOTE: If you cast this spell in the centre of the group of peasants, the orb will reach maximum size INCREDIBLY fast (2 seconds max)
Screenshots (re-uploaded screenshots with ImageShack)
Spell code
Updates
[DEL](By very customizable, I mean you can't adjust it to suit a particular hero stat, or the ability's level. This will be added in one of the next few releases, if I get around to it)[/DEL]
Technical details:
Made in vJASS
Requires NewGen World Editor
Requires Cohadar's ABC Struct Attachment system
MUI
Lagless
Leakless to my knowledge
Importing instructions
Code:
Copy the Mana Bomb spell, and the Mana Bomb Dummy and Explode Dummy units into your map
Copy the ABC and ManaBomb triggers into your map
In Object Editor, press Ctrl-D to display the rawcodes of the units.
If they are different from the ones displayed at the top of the Mana Bomb code, change them (SPELLID = Mana Bomb rawcode, DUMMYID = Mana Bomb Dummy rawcode, EXPLODEDUMMYID = Explode Dummy rawcode)
Add the Mana Bomb ability to a Hero
Save your map, and test.
Tooltip/Description
The hero creates an orb of mana, which absorbs mana from surrounding enemies. When the caster stops channelling, the orb becomes unstable and detonates, dealing damage based on amount of mana stored.
Size of the orb increases as current mana increases.
Also, mana will NOT be drained from enemies once the orb is maxed out.
NOTE: If you cast this spell in the centre of the group of peasants, the orb will reach maximum size INCREDIBLY fast (2 seconds max)
Screenshots (re-uploaded screenshots with ImageShack)
Spell code
JASS:
//Mana Bomb (by Flare)
//Constructed using vJASS and Cohadar's ABC struct attachment system
//If you use this, give me credits!
//Globals, configurables ETC
//For the time being, all the details here will be relatively constant (functions containing calculation formulas will be added later)
//------------------------------------------------------------------------------------\\
scope ManaBomb
globals
//Ability and dummy ID's
private constant integer SPELLID = 039;A000039;
private constant integer DUMMYID = 039;n000039;
//The character string used by the mana bar
private constant string MBSTRING = "039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;039;"
//Length of the mana bar
private constant integer STRINGLENGTH = 30
//Mana bar size
private constant real TEXTSIZE = TextTagSize2Height (8.)
//Mana bar z offset
private constant real ZOFFSET = 150
//Colour used for current amount of mana
private constant string BLUESTRING = "|c000201FF"
//Color used for empty portion of mana bar
private constant string BLACKSTRING = "|c00000000"
//String for explosion effect
private constant string EXPLODEFX = "Objects\\Spawnmodels\\NightElf\\NEDeathMedium\\NEDeath.mdl"
//Timer interval
private constant real TIMERINTERVAL = 0.03
//Mana limit (base and skill level multiplier)
//No longer used
private constant real BASEMANAMAX = 500
private constant real LEVELMULTIPLIER = 250
//Percent of mana dealt in damage (from 0.00 to 1.00)
//No longer used
private constant real MANA2DAMAGEPERCENT = 0.75
//Rate of mana storing per second (and mana stored per timer interval)
//No longer used
private constant real MANASTORE = 75
private constant real STORERATE = MANASTORE * TIMERINTERVAL
//Rate of mana drain from enemies
//No longer used
private constant real MANADRAIN = 15
private constant real DRAINRATE = MANADRAIN*TIMERINTERVAL
//Area of effect
private constant real DRAINAOE = 700
//No longer used
private constant real BLASTAOE = 400
//Explode dummy scale value
//175 is -roughly- the size of the Night Elf death explosion.
private constant real EXPLODERSCALE = BLASTAOE/175.
//Scaling value
//End scale size of the dummy will be BASESCALER + MANA2SCALE*a.currentmana
private constant real BASESCALER = 1.5
private constant real MANA2SCALE = 0.003
//Explosion speed scaler
private constant real EXPLODESPEED = .75
//End damage SFX string
private constant string DAMAGEFX = "Abilities\\Spells\\Items\\AIvi\\AIviTarget.mdl"
//Required by the spell. DO NOT TOUCH!
private unit gcaster
private real gdamage
private real gm1
private real gm2
private real gdif
private real gcurrentmana
private real gmaxmana
private real gdrain
endglobals
//Formulas for variable stuff
//------------------------------------------------------------------------------------\\
//946609
//Mana stored per second
private function VariableStore takes unit u returns real
local real base = 5.
local real level = I2R (GetUnitAbilityLevel (u, SPELLID))
local real multiplier = 10.
return base + level*multiplier
endfunction
//Mana drained per second
private function VariableDrain takes unit u returns real
local real base = 2.5
local real level = I2R (GetUnitAbilityLevel (u, SPELLID))
local real multiplier = 5.
return base + level*multiplier
endfunction
//Variable mana limit
private function VariableMaxMana takes unit u returns real
local real base = 250.
local real level = I2R (GetUnitAbilityLevel (u, SPELLID))
local real multiplier = 250.
return base + level*multiplier
endfunction
private function VariableMana2Damage takes unit u returns real
local real base = 0.25
local real level = I2R (GetUnitAbilityLevel (u, SPELLID))
local real multiplier = 0.25
return base + level*multiplier
endfunction
private function VariableAOE takes real cmana, real mmana returns real
local real percentscale = (cmana + 1)/(mmana + 1)
local real maxaoe = 400
return percentscale * maxaoe
endfunction
//END OF GLOBALS. DO NOT EDIT BELOW HERE
//------------------------------------------------------------------------------------\\
//Struct data
//------------------------------------------------------------------------------------\\
private struct Bombdata
unit caster
unit bomb
real maxmana
real currentmana
texttag manabar
group damagegroup
real damagepercent
real damage
real aoe
trigger stopcast
timer mbtimer
group draingroup
real bombscale
integer mbstringcount
real elapsedtime
real mana2damage
real drainrate
real storerate
private method onDestroy takes nothing returns nothing
call ClearTriggerStructA (.stopcast)
call DestroyTrigger (.stopcast)
call ClearTimerStructA (.mbtimer)
call DestroyTimer (.mbtimer)
endmethod
endstruct
//End group conditions and actions
//------------------------------------------------------------------------------------\\
private function FilterCondition takes nothing returns boolean
return IsUnitEnemy (GetFilterUnit (), GetOwningPlayer (gcaster)) and GetWidgetLife (GetFilterUnit ()) > 0.405
endfunction
private function EndGroupActions takes nothing returns nothing
local unit u = GetEnumUnit ()
call UnitDamageTarget (gcaster, u, gdamage, true, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
call DestroyEffect (AddSpecialEffectTarget (DAMAGEFX, u, "origin"))
set u = null
endfunction
//Drain group actions
//This utilizes the same filter as the end group
//------------------------------------------------------------------------------------\\
private function DrainGroupActions takes nothing returns nothing
local unit u = GetEnumUnit ()
if gcurrentmana < gmaxmana then
set gm1 = GetUnitState (u, UNIT_STATE_MANA)
call SetUnitState (u, UNIT_STATE_MANA, gm1 - gdrain)
set gm2 = GetUnitState (u, UNIT_STATE_MANA)
set gdif = gdif + (gm1 - gm2)
endif
set u = null
endfunction
//Stopcast condition and actions
//------------------------------------------------------------------------------------\\
private function StopCondition takes nothing returns boolean
return GetSpellAbilityId () == SPELLID
endfunction
private function StopActions takes nothing returns nothing
local Bombdata a = GetTriggerStructA (GetTriggeringTrigger ())
local real x = GetUnitX (a.bomb)
local real y = GetUnitY (a.bomb)
local real aoe = VariableAOE (a.currentmana, a.maxmana)
set a.damage = a.currentmana * a.mana2damage
set gcaster = a.caster
set gdamage = a.damage
set a.damagegroup = CreateGroup ()
call GroupEnumUnitsInRange (a.damagegroup, x, y, aoe, Condition (function FilterCondition))
call ForGroup (a.damagegroup, function EndGroupActions)
call DestroyTextTag (a.manabar)
call RemoveUnit (a.bomb)
call DestroyEffect (AddSpecialEffect (EXPLODEFX, x, y))
set a.elapsedtime = 0
set a.currentmana = 0
set a.maxmana = 0
call a.destroy ()
endfunction
//Timer actions
//------------------------------------------------------------------------------------\\
private function TimerActions takes nothing returns nothing
local timer t = GetExpiredTimer ()
local Bombdata a = GetTimerStructA (t)
local real x = GetUnitX (a.bomb)
local real y = GetUnitY (a.bomb)
local real stringcount = ((a.currentmana + 1)/(a.maxmana + 1)) * I2R (STRINGLENGTH)
set a.draingroup = CreateGroup ()
set a.elapsedtime = a.elapsedtime + TIMERINTERVAL
set gdif = 0
set gcaster = a.caster
set gcurrentmana = a.currentmana
set gmaxmana = a.maxmana
set gdrain = a.drainrate
call GroupEnumUnitsInRange (a.draingroup, x, y, DRAINAOE, Condition (function FilterCondition))
call ForGroup (a.draingroup, function DrainGroupActions)
call DestroyGroup (a.draingroup)
set a.currentmana = a.currentmana + gdif
set a.currentmana = a.currentmana + a.storerate
set a.mbstringcount = R2I (stringcount)
if a.currentmana > a.maxmana then
set a.currentmana = a.maxmana
set a.mbstringcount = STRINGLENGTH
endif
call SetTextTagText (a.manabar, BLUESTRING + SubString (MBSTRING, 1, a.mbstringcount) +"|r" + BLACKSTRING + SubString (MBSTRING, a.mbstringcount, STRINGLENGTH), TEXTSIZE)
set a.bombscale = BASESCALER + (MANA2SCALE * a.currentmana)
call SetUnitScale (a.bomb, a.bombscale, a.bombscale, a.bombscale)
set t = null
endfunction
//Primary trigger condition and actions
//------------------------------------------------------------------------------------\\
private function MBCond takes nothing returns boolean
return GetSpellAbilityId () == SPELLID
endfunction
private function MBActions takes nothing returns nothing
local Bombdata a = Bombdata.create ()
local location loc = GetSpellTargetLoc ()
local real tx = GetLocationX (loc)
local real ty = GetLocationY (loc)
local real level
set a.caster = GetTriggerUnit ()
set level = I2R (GetUnitAbilityLevel (a.caster, SPELLID))
set a.bomb = CreateUnit (GetOwningPlayer (a.caster), DUMMYID, tx, ty, 0)
call SetUnitPathing (a.bomb, false)
set a.mbtimer = CreateTimer ()
set a.stopcast = CreateTrigger ()
set a.maxmana = VariableMaxMana (a.caster)
set a.drainrate = VariableDrain (a.caster) * TIMERINTERVAL
set a.storerate = VariableStore (a.caster) * TIMERINTERVAL
set a.mana2damage = VariableMana2Damage (a.caster)
set a.currentmana = 50.
set a.manabar = CreateTextTag ()
set a.bombscale = BASESCALER + (MANA2SCALE * a.currentmana)
set a.mbstringcount = R2I ((a.currentmana + 1)/(a.maxmana + 1) * I2R (STRINGLENGTH))
call SetTextTagPos (a.manabar, tx, ty, ZOFFSET)
call SetTextTagText (a.manabar, BLUESTRING + SubString (MBSTRING, 1, a.mbstringcount) +"|r" + BLACKSTRING + SubString (MBSTRING, a.mbstringcount + 1, STRINGLENGTH), TEXTSIZE)
call SetTextTagVisibility (a.manabar, false)
if GetLocalPlayer () == GetOwningPlayer (a.caster) then
call SetTextTagVisibility (a.manabar, true)
endif
call RemoveLocation (loc)
call SetUnitScale (a.bomb, a.bombscale, a.bombscale, a.bombscale)
set loc = null
call SetTimerStructA (a.mbtimer, a)
call TimerStart (a.mbtimer, TIMERINTERVAL, true, function TimerActions)
call SetTriggerStructA (a.stopcast, a)
call TriggerRegisterUnitEvent (a.stopcast, a.caster, EVENT_UNIT_SPELL_ENDCAST)
call TriggerAddCondition (a.stopcast, Condition (function StopCondition))
call TriggerAddAction (a.stopcast, function StopActions)
endfunction
//Trigger initialization
//------------------------------------------------------------------------------------\\
function InitTrig_ManaBomb takes nothing returns nothing
local trigger ManaBomb = CreateTrigger ()
call TriggerRegisterAnyUnitEventBJ (ManaBomb, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition (ManaBomb, Condition (function MBCond))
call TriggerAddAction (ManaBomb, function MBActions)
endfunction
endscope
Updates
Code:
v1 - First release
v2 - Fixed the Divide by zero error (I think)
v3 - Fixed the slow text tag fill that Purgeanfire reported
v4 - Removed the immediate stop order on 100% charge (was only used for testing)
v5 - Made the text tag visible to the caster's owner only
v6 - Made the struct private. Replaced Wisp Detonate explosion with Night Elf structure death. Added variable formulas for damage, % mana to damage rate, drain/store rates, end explosion scaling size
v7/8/9 - Made the onDestroy method private. Replaced dummy unit effect with normal special effect. Fixed mana bar extending itself.