Steel
Software Engineer
- Reaction score
- 109
Vortex
Demo Map
Note: Code is at the bottom
Note II: This is a submission for the Spells section
Background: I basically designed this for my own map and put some work into it and I figured it may be useful for others. The spell is completely in JASS; GUI people don't worry its so easy to use! I've included many steps and comments to follow to help you to put this in your map. There were a few things that I hadn't ever tried before, so some of the code might be a bit sloppy (Dealing with the trigger addition). I still have a bit of timing issues to work out with the pausing, I had some issues with the spell working when I paused at improper times. Ill be tweaking and updating this. If there are memory leaks let me know I did probably miss some in the handles, I need to work on cleanup.
Spell Notes: This spell is very versitile. There are a lot of things you can edit without touching the actual code of the spell. There are several constant functions that you can modify, what the targets are, the damage, the effects displayed, etc. This makes the spell extremely easy to change even for people who don't know JASS.
What it does: The spell is based around an AoE target (Blizzard). The units are taken from their position and "removed" and put into the caster. When they are stored into the caster the unit take damage over time, but as a result the caster suffers strain from holding the units. Now, this is not like devour, the spell has 2 parts. While the units are stored within the caster, when you want you can cast the spell again and it will "spit out" the units to wherever you target them.
If you plan on using this please read the implementation before asking questions.
Map Custom Script:
Spell: Vortex
Demo Map
Note: Code is at the bottom
Note II: This is a submission for the Spells section
Background: I basically designed this for my own map and put some work into it and I figured it may be useful for others. The spell is completely in JASS; GUI people don't worry its so easy to use! I've included many steps and comments to follow to help you to put this in your map. There were a few things that I hadn't ever tried before, so some of the code might be a bit sloppy (Dealing with the trigger addition). I still have a bit of timing issues to work out with the pausing, I had some issues with the spell working when I paused at improper times. Ill be tweaking and updating this. If there are memory leaks let me know I did probably miss some in the handles, I need to work on cleanup.
Spell Notes: This spell is very versitile. There are a lot of things you can edit without touching the actual code of the spell. There are several constant functions that you can modify, what the targets are, the damage, the effects displayed, etc. This makes the spell extremely easy to change even for people who don't know JASS.
What it does: The spell is based around an AoE target (Blizzard). The units are taken from their position and "removed" and put into the caster. When they are stored into the caster the unit take damage over time, but as a result the caster suffers strain from holding the units. Now, this is not like devour, the spell has 2 parts. While the units are stored within the caster, when you want you can cast the spell again and it will "spit out" the units to wherever you target them.
If you plan on using this please read the implementation before asking questions.
Map Custom Script:
Code:
function H2I takes handle h returns integer
return h
return 0
endfunction
function LocalVars takes nothing returns gamecache
if udg_steelcache == null then
call FlushGameCache(InitGameCache("steelcache.w3v"))
set udg_steelcache = InitGameCache("steelcache.w3v")
endif
return udg_steelcache
endfunction
function SetHandleHandle takes handle subject, string name, handle value returns nothing
if value==null then
call FlushStoredInteger(LocalVars(),I2S(H2I(subject)),name)
else
call StoreInteger(LocalVars(), I2S(H2I(subject)), name, H2I(value))
endif
endfunction
function SetHandleInt takes handle subject, string name, integer value returns nothing
if value==0 then
call FlushStoredInteger(LocalVars(),I2S(H2I(subject)),name)
else
call StoreInteger(LocalVars(), I2S(H2I(subject)), name, value)
endif
endfunction
function SetHandleReal takes handle subject, string name, real value returns nothing
if value==0 then
call FlushStoredReal(LocalVars(), I2S(H2I(subject)), name)
else
call StoreReal(LocalVars(), I2S(H2I(subject)), name, value)
endif
endfunction
function SetHandleString takes handle subject, string name, string value returns nothing
if value==null then
call FlushStoredString(LocalVars(), I2S(H2I(subject)), name)
else
call StoreString(LocalVars(), I2S(H2I(subject)), name, value)
endif
endfunction
function SetHandleBoolean takes handle subject, string name, boolean value returns nothing
if value==false then
call FlushStoredBoolean(LocalVars(), I2S(H2I(subject)), name)
else
call StoreBoolean(LocalVars(), I2S(H2I(subject)), name, true )
endif
endfunction
function GetHandleBoolean takes handle subject, string name returns boolean
return GetStoredBoolean(LocalVars(), I2S(H2I(subject)), name)
endfunction
function GetHandleHandle takes handle subject, string name returns handle
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function GetHandleInt takes handle subject, string name returns integer
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
endfunction
function GetHandleReal takes handle subject, string name returns real
return GetStoredReal(LocalVars(), I2S(H2I(subject)), name)
endfunction
function GetHandleString takes handle subject, string name returns string
return GetStoredString(LocalVars(), I2S(H2I(subject)), name)
endfunction
function GetHandleUnit takes handle subject, string name returns unit
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function GetHandleTimer takes handle subject, string name returns timer
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function GetHandleTrigger takes handle subject, string name returns trigger
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function GetHandleEffect takes handle subject, string name returns effect
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function GetHandleTextTag takes handle subject, string name returns texttag
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function GetHandleTriggerAction takes handle subject, string name returns triggeraction
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function FlushHandleLocals takes handle subject returns nothing
call FlushStoredMission(LocalVars(), I2S(H2I(subject)) )
endfunction
Spell: Vortex
Code:
constant function Vortexabilid takes nothing returns integer
//This is the ability ID
return 'A002'
endfunction
constant function Vortexradius takes nothing returns real
//This is the radius of the spell being cast
return 225.0
endfunction
constant function VortexPretty takes nothing returns boolean
//Make this true if you want the pretty effect
return true
endfunction
constant function VortexPrettyUnit takes nothing returns integer
//This is the Pretty vortex dummy unit, it makes the spell look pretty
return 'h000'
endfunction
constant function Vortexdamage takes nothing returns real
//This value is how much damage the units will received per second multiplied by the level of the spell
//If the units are stored within the caster for 15 seconds with a level 1 spell they will be damaged for
//20*1*15
//The 20 refers to this value
return 20.0
endfunction
//The following are the strings for the model effects
//I put these here so you users would be able to change how the spell graphics look without
//Worrying about damaging the functionality of the rest of the spell
constant function VortexCreationEffect takes nothing returns string
//This is the effect when you first cast the spell
//This is on the location of your target cast
return "Objects\\Spawnmodels\\NightElf\\NECancelDeath\\NECancelDeath.mdl"
endfunction
constant function VortexStorageEffect takes nothing returns string
//This is the effect that binds to your caster
//This basically is a visual effect showing that units have been stored in the caster
//And that your caster is ready to release the units
return "Abilities\\Spells\\NightElf\\Barkskin\\BarkSkinTarget.mdl"
endfunction
constant function VortexDeathEffect takes nothing returns string
//This is the effect when you release the units
return "Objects\\Spawnmodels\\Undead\\UDeathMedium\\UDeath.mdl"
endfunction
//************************************************************************************
//**** DO NOT CHANGE ANYTHING BELOW UNLESS YOU KNOW WHAT YOU ARE DOING ****
//************************************************************************************
function Trig_Vortex_Conditions takes nothing returns boolean
return GetSpellAbilityId() == Vortexabilid()
endfunction
function Vortex_Units takes nothing returns boolean
return (IsUnitEnemy(GetFilterUnit(),bj_groupEnumOwningPlayer))
endfunction
function Vortex_Release takes unit caster, location loc returns nothing
local unit u
local integer i = 1
local effect e
local location casterloc = GetUnitLoc(caster)
local real damage = (Vortexdamage()*GetHandleInt(caster, "lvl"))*GetHandleInt(caster, "duration")
loop
set u = GetHandleUnit(caster, "vortex"+I2S(i))
exitwhen u==null
call SetUnitPosition(u, GetLocationX(loc)+GetRandomReal(1,225),GetLocationY(loc)+GetRandomReal(1,225) )
call ShowUnit(u, true)
call SetHandleHandle(caster, "vortex"+I2S(i), null)
call UnitDamageTarget(caster, u, damage, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS) //Damages our target
set i = i+1
endloop
set e = AddSpecialEffectLoc(VortexDeathEffect(), loc)
call DestroyEffect(GetHandleEffect(caster,"vortexe"))
call SetHandleBoolean(caster, "vortexb", false)
set u = null
call DestroyEffect(e)
set e = null
call RemoveLocation(casterloc)
set casterloc = null
endfunction
function Vortex_Damage takes nothing returns nothing
local unit caster = GetHandleUnit(GetTriggeringTrigger(), "caster")
call SetHandleInt(caster, "duration", GetHandleInt(caster, "duration")+1)
if (GetUnitState(caster, UNIT_STATE_LIFE)) < 6 then
call DestroyTrigger(GetTriggeringTrigger())
call Vortex_Release(caster, GetUnitLoc(caster))
call SetHandleReal(caster, "damage", 0)
endif
call SetUnitState(caster, UNIT_STATE_LIFE, GetUnitState(caster, UNIT_STATE_LIFE)-(GetHandleReal(caster, "damage")+1.5))
call SetHandleReal(caster, "damage", GetHandleReal(caster, "damage")+(GetHandleInt(caster, "lvl")*2.5))
set caster = null
endfunction
function Vortex_Death takes nothing returns nothing
local unit u = GetTriggerUnit()
call FlushHandleLocals(u)
set u = null
endfunction
function Trig_Vortex_Actions takes nothing returns nothing
local unit caster = GetTriggerUnit()
local unit u
local unit v
local location casterloc = GetUnitLoc(caster)
local location targetloc = GetSpellTargetLoc()
local group g = CreateGroup()
local boolexpr b = Condition(function Vortex_Units)
local integer i = 1
local effect e
local trigger t = CreateTrigger()
local trigger death = CreateTrigger()
local real safeduration = 500.0
call SetHandleInt(caster,"lvl", GetUnitAbilityLevel(caster, Vortexabilid()))
set bj_groupEnumOwningPlayer = GetOwningPlayer(caster)
call TriggerRegisterPlayerUnitEvent(death, GetOwningPlayer(caster), EVENT_PLAYER_UNIT_DEATH, null)
call TriggerAddAction(death, function Vortex_Death)
if (GetHandleBoolean(caster, "vortexb")) then
call Vortex_Release(caster, targetloc)
set e = AddSpecialEffectLoc(VortexDeathEffect(), targetloc)
call DestroyEffect(GetHandleEffect(caster,"vortexe"))
call SetHandleBoolean(caster, "vortexb", false)
call DestroyTrigger(GetHandleTrigger(caster, "vortext"))
else
call GroupEnumUnitsInRange(g, GetLocationX(targetloc), GetLocationY(targetloc), 225, b)
call DestroyBoolExpr(b)
set b = null
loop
set u = FirstOfGroup(g)
exitwhen u == null
call SetHandleHandle(caster, "vortex"+I2S(i), u)
if (VortexPretty()) then
set v = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), VortexPrettyUnit(), GetUnitX(u), GetUnitY(u), 0)
call SetHandleHandle(caster, "vortexp"+I2S(i),v)
call IssuePointOrder(v, "move", GetUnitX(caster), GetUnitY(caster))
call UnitApplyTimedLife(v, 'BTLF', (DistanceBetweenPoints(casterloc, GetUnitLoc(u))/500))
endif
call ShowUnitHide(u)
call GroupRemoveUnit(g,u)
set i = i+1
endloop
set e = AddSpecialEffectLoc(VortexCreationEffect(), targetloc)
if (i==1) then
return
endif
call PolledWait(.5)
call SetHandleHandle(t, "caster", caster)
call SetHandleHandle(caster, "vortext", t)
call TriggerRegisterTimerEventPeriodic( t, 1.00 )
call TriggerAddAction(t, function Vortex_Damage)
call PauseUnit(caster, true)
call SetHandleBoolean(caster, "vortexb", true)
call SetHandleBoolean(caster, "vortexa", true)
call PolledWait(.5)
call SetHandleHandle(caster, "vortexe", AddSpecialEffectTarget(VortexStorageEffect(), caster, "overhead"))
endif
if (VortexPretty() and GetHandleBoolean(caster, "vortexb")) then
//call PauseUnit(caster, true)
call PolledWait(1.3)
call PauseUnit(caster, false)
endif
set v = null
set u = null
set caster = null
call RemoveLocation(casterloc)
call RemoveLocation(targetloc)
set casterloc=null
set targetloc=null
call DestroyGroup(g)
set g = null
call DestroyEffect(e)
set e = null
call PolledWait(safeduration)
call FlushHandleLocals(caster)
call DestroyTrigger(t)
set t = null
call DestroyTrigger(death)
set death = null
endfunction
//===========================================================================
function InitTrig_Vortex takes nothing returns nothing
set gg_trg_Vortex = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Vortex, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Vortex, Condition( function Trig_Vortex_Conditions ) )
call TriggerAddAction( gg_trg_Vortex, function Trig_Vortex_Actions )
endfunction