🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
TimedHandles (optionally, the spells can be configured to not require it)
- KelThuzad for the icons of Prolonged Life, Smiting Zeal and Reverse Damage
- Blizzard Entertainment for the icon of Seed of Life
- Anitarf for SpellEvent, Stack, DamageEvent and DamageModifiers
- Rising_Dusk for GroupUtils and IntuitiveBuffSystem
- grim001 for AutoIndex and AbilityPreload
- Captain_Griffen for LightLeaklessDamageDetect
- TriggerHappy187 for TimedHandles
- Vexorian for JassHelper, Table and TimerUtils
- Pipedream for Grimoire
- Pitzermike and MindWorX for JassNewGenPack
25/12/2009 - Version 1.0.0
- initial release
28/12/2009 - Version 1.0.1
- multiple bugfixes to all abilities
- Prolonged life now restores to exactly the amount specified in the settings, not to the amount specified plus the units current life
- multiple Reverse Damage instances on the same unit stack (correctly) now, and dont overwrite each other.
- multiple instances of Prolonged Life on the same unit overwrite each other now. The instance with the highest level now stays on the unit.
- all spells based on buffs correctly terminate now if the unit was killed by KillUnit() (or some other way of killing a unit without damaging it).
25/01/2011 - Version 1.1.0
- made TimedHandles an optional requirement
- moved array setup functions into one function
- removed periodic checks for buffs, ProlongedLife and ReverseDamage will now leak a spell instance (which also is an instance of DamageModifier) when the user removes or kills a unit with an active instance of the spell.
- SeedOfLife now has more calibration options eg. a chance to trigger or healing a fraction of the damage dealt to the target of the spell.
- more/better documentation
- few more minor changes
28/01/2011 - Version 1.2.0
- Seed of Life, Prolonged Life and Reverse Damage are now the same spell, configured differently.
- Smiting Zeal now supports enforcing the mana cost. It will not trigger if the caster cant pay the additional cost, if you configured it accordingly.
- Reverse Damage now has a minimum damage, damage dealt to the target of this spell must be greater than or equal to 20.
08/02/2011 - Version 1.2.1
- fixed a bug with how chances are handled, the spells should actually work now.
And here are the spells:
Seed of Life
Infuses the target with the seed of life. Units around it get healed whenever the target takes damage.
Lasts 7 seconds.
Level 1 - Units in a 200 radius get healed by 15 HP. Level 2 - Units in a 275 radius get healed by 20 HP. Level 3 - Units in a 350 radius get healed by 25 HP.
globals
private constant integer AID = 'A001' // ability triggering this. Any unit targeting ability is fine. Used Bloodlust
private constant integer BUFF_PLACER_AID = 'A004' // Ability placing BID on the unit this ability is added to. Based off of Slow Aura (Tornado).
private constant integer BID = 'B000' // buff placed by BUFF_PLACER_AID on the target unit
private constant string FX = "Abilities\\Spells\\Human\\Heal\\HealTarget.mdl" // displayed on the target unit when the effect of this ability is triggered.
private constant string FX_ATTPT = "origin"
private constant real FX_DURATION = 1.833 // 0 or less only plays the death animation // ignored if TimedHandles is not present in the map
private constant string TARGET_FX = "" // displayed on the target of this spell
private constant string TARGET_FX_ATTPT = "" // where to display the effect on the target of this spell
private constant integer PRIORITY = 0 // when to trigger the effects of an instance of this spell when a unit receives damage // refer to DamageModifiers documentation
private real array DURATION // how long does the buff last?
private real array AOE // Heals all units around the damaged target in this area
private real array CHANCE // Chance to trigger this ability // 1.0 = 100% // 0.0 = 0%
private integer array MAX_HEALINGS // heal at most this many times // zero or less for no limit
endglobals
// how long does the buff last?
private function Duration takes integer level returns real
return DURATION[level]
endfunction
// Heals all units around the damaged target in this area
private function Aoe takes integer level returns real
return AOE[level]
endfunction
// Chance to trigger this ability // 1.0 = 100% // 0.0 = 0%
private function Chance takes integer level returns real
return CHANCE[level]
endfunction
// heal at most this many times // zero or less for no limit
private function Max_Healings takes integer level returns integer
return MAX_HEALINGS[level]
endfunction
private function SetUpSpellData takes nothing returns nothing
// how long does the buff last?
set DURATION[1]=7
set DURATION[2]=7
set DURATION[3]=7
// Heals all units around the damaged target in this area
set AOE[1]=200
set AOE[2]=275
set AOE[3]=350
// Chance to trigger this ability // 1.0 = 100% // 0.0 = 0%
set CHANCE[1]=1
set CHANCE[2]=1
set CHANCE[3]=1
// heal at most this many times // zero or less for no limit
set MAX_HEALINGS[1]=0
set MAX_HEALINGS[2]=0
set MAX_HEALINGS[3]=0
endfunction
// if you want to get the targets current HP, use GetUnitLife(whichUnit)
// damage dealt to a unit with this buff active needs to be greater than what this function returns to be blocked
private function Minimum_Damage takes integer level, unit target returns real
return 0.
endfunction
// how much damage to block
private function Damage_Blocked takes integer level, unit target, real damage returns real
return 0.
endfunction
// how much health to restore after blocking
private function Health_Restored takes integer level, unit target, real damage returns real
return 10.+level*10.
endfunction
// how much health to heal units in the area
private function Aoe_Heal takes integer level, unit target, real damage returns real
return 10.+level*5.
endfunction
// only units matching these criteria will get healed
private function ValidTarget takes unit u, unit caster returns boolean
return IsUnitAlly(u, GetOwningPlayer(caster))/*
*/ and IsUnitType(u, UNIT_TYPE_MECHANICAL)==false/*
*/ and IsUnitType(u, UNIT_TYPE_STRUCTURE)==false/*
*/ and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)==false/*
*/
endfunction
//
globals
private integer BuffType
endglobals
private struct Data extends DamageModifier
unit caster
unit target
effect targetFx
integer level
integer healings=0
static thistype Tmps
static real CurrentDamage
static thistype array Instance
private method onDestroy takes nothing returns nothing
set Instance[GetUnitId(.target)]=0
set .caster=null
set .target=null
if TARGET_FX!="" then
call DestroyEffect(.targetFx)
set .targetFx=null
endif
endmethod
private static method AoeHealEnum takes nothing returns boolean
local unit u=GetFilterUnit()
if u!=.Tmps.target and ValidTarget(u, .Tmps.caster) then
call SetUnitLife(u, GetUnitLife(u)+Aoe_Heal(.Tmps.level, .Tmps.target, .CurrentDamage))
static if LIBRARY_TimedHandles then
if FX_DURATION>0 then
call DestroyEffectTimed(AddSpecialEffectTarget(FX, u, FX_ATTPT), FX_DURATION)
else
call DestroyEffect(AddSpecialEffectTarget(FX, u, FX_ATTPT))
endif
else
call DestroyEffect(AddSpecialEffectTarget(FX, u, FX_ATTPT))
endif
endif
set u=null
return false
endmethod
private method onDamageTaken takes unit origin, real damage returns real
local real blocked=0
if GetRandomReal(0,1)<=Chance(.level) and damage+0.406>=Minimum_Damage(.level, .target) then
if ValidTarget(.target, .caster) then
call SetUnitLife(.target, GetUnitLife(.target)+Health_Restored(.level, .target, damage))
static if LIBRARY_TimedHandles then
if FX_DURATION>0 then
call DestroyEffectTimed(AddSpecialEffectTarget(FX, .target, FX_ATTPT), FX_DURATION)
else
call DestroyEffect(AddSpecialEffectTarget(FX, .target, FX_ATTPT))
endif
else
call DestroyEffect(AddSpecialEffectTarget(FX, .target, FX_ATTPT))
endif
set blocked=Damage_Blocked(.level, .target, damage)
endif
if Aoe(.level)>0. then
set .Tmps=this
set .CurrentDamage=damage
call GroupEnumUnitsInArea(ENUM_GROUP, GetUnitX(.target), GetUnitY(.target), Aoe(.level), Condition(function thistype.AoeHealEnum))
endif
set .healings=.healings+1
if Max_Healings(.level)>0 and .healings>=Max_Healings(.level) then
call UnitRemoveBuff(.target, BuffType)
endif
return -blocked
endif
return 0.
endmethod
static method create takes unit caster, unit target returns thistype
local thistype s=Instance[GetUnitId(target)]
if s==0 then
set s=.allocate(target, PRIORITY)
set s.caster=caster
set s.target=target
if TARGET_FX!="" then
set s.targetFx=AddSpecialEffectTarget(TARGET_FX, target, TARGET_FX_ATTPT)
endif
set s.level=GetUnitAbilityLevel(caster, AID)
set Instance[GetUnitId(target)]=s
else
if s.level<GetUnitAbilityLevel(caster, AID) then
set s.caster=caster
set s.healings=0
set s.level=GetUnitAbilityLevel(caster, AID)
endif
endif
set UnitAddBuff(caster, target, BuffType, Duration(s.level), s.level).data=s
return s
endmethod
private function Init takes nothing returns nothing
call RegisterSpellEffectResponse(AID, CastResponse)
set BuffType=DefineBuffType(BUFF_PLACER_AID, BID, 0, false, true, 0,0,Data.BuffRemoved)
call SetUpSpellData()
endfunction
endlibrary[/code]
Prolonged Life
Prolongs the target units life once over the next 8 seconds.
Level 1 - Restores 10% of the targets maximum health. Level 2 - Restores 20% on the targets maximum health. Level 3 - Restores 30% on the targets maximum health.
globals
private constant integer AID = 'A000' // ability triggering this. Any unit targeting ability is fine. Used Channel
private constant integer BUFF_PLACER_AID = 'A005' // Ability placing BID on the unit this ability is added to. Based off of Slow Aura (Tornado).
private constant integer BID = 'B001' // buff placed by BUFF_PLACER_AID on the target unit
private constant string FX = "Abilities\\Spells\\Items\\AIre\\AIreTarget.mdl" // displayed on the target unit when the effect of this ability is triggered.
private constant string FX_ATTPT = "origin"
private constant real FX_DURATION = 0. // 0 or less only plays the death animation // ignored if TimedHandles is not present in the map
private constant string TARGET_FX = "Abilities\\Spells\\Items\\HealingSalve\\HealingSalveTarget.mdl" // displayed on the target of this spell
private constant string TARGET_FX_ATTPT = "head" // where to display the effect on the target of this spell
private constant integer PRIORITY = 0 // when to trigger the effects of an instance of this spell when a unit receives damage // refer to DamageModifiers documentation
private real array DURATION // how long does the buff last?
private real array AOE // Heals all units around the damaged target in this area
private real array CHANCE // Chance to trigger this ability // 1.0 = 100% // 0.0 = 0%
private integer array MAX_HEALINGS // heal at most this many times // zero or less for no limit
endglobals
// how long does the buff last?
private function Duration takes integer level returns real
return DURATION[level]
endfunction
// Heals all units around the damaged target in this area
private function Aoe takes integer level returns real
return AOE[level]
endfunction
// Chance to trigger this ability // 1.0 = 100% // 0.0 = 0%
private function Chance takes integer level returns real
return CHANCE[level]
endfunction
// heal at most this many times // zero or less for no limit
private function Max_Healings takes integer level returns integer
return MAX_HEALINGS[level]
endfunction
private function SetUpSpellData takes nothing returns nothing
// how long does the buff last?
set DURATION[1]=8
set DURATION[2]=8
set DURATION[3]=8
// Heals all units around the damaged target in this area
set AOE[1]=0
set AOE[2]=0
set AOE[3]=0
// Chance to trigger this ability // 1.0 = 100% // 0.0 = 0%
set CHANCE[1]=1
set CHANCE[2]=1
set CHANCE[3]=1
// heal at most this many times // zero or less for no limit
set MAX_HEALINGS[1]=1
set MAX_HEALINGS[2]=1
set MAX_HEALINGS[3]=1
endfunction
// if you want to get the targets current HP, use GetUnitLife(whichUnit)
// damage dealt to a unit with this buff active needs to be greater than what this function returns to be blocked
private function Minimum_Damage takes integer level, unit target returns real
return GetUnitLife(target)
endfunction
// how much damage to block
private function Damage_Blocked takes integer level, unit target, real damage returns real
return damage
endfunction
// how much health to restore after blocking
private function Health_Restored takes integer level, unit target, real damage returns real
return GetUnitLife(target)*0.1*level
endfunction
// how much health to heal units in the area
private function Aoe_Heal takes integer level, unit target, real damage returns real
return 0.
endfunction
// only units matching these criteria will get healed
private function ValidTarget takes unit u, unit caster returns boolean
return IsUnitAlly(u, GetOwningPlayer(caster))/*
*/ and IsUnitType(u, UNIT_TYPE_MECHANICAL)==false/*
*/ and IsUnitType(u, UNIT_TYPE_STRUCTURE)==false/*
*/ and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)==false/*
*/
endfunction
//
globals
private integer BuffType
endglobals
private struct Data extends DamageModifier
unit caster
unit target
effect targetFx
integer level
integer healings=0
static thistype Tmps
static real CurrentDamage
static thistype array Instance
private method onDestroy takes nothing returns nothing
set Instance[GetUnitId(.target)]=0
set .caster=null
set .target=null
if TARGET_FX!="" then
call DestroyEffect(.targetFx)
set .targetFx=null
endif
endmethod
private static method AoeHealEnum takes nothing returns boolean
local unit u=GetFilterUnit()
if u!=.Tmps.target and ValidTarget(u, .Tmps.caster) then
call SetUnitLife(u, GetUnitLife(u)+Aoe_Heal(.Tmps.level, .Tmps.target, .CurrentDamage))
static if LIBRARY_TimedHandles then
if FX_DURATION>0 then
call DestroyEffectTimed(AddSpecialEffectTarget(FX, u, FX_ATTPT), FX_DURATION)
else
call DestroyEffect(AddSpecialEffectTarget(FX, u, FX_ATTPT))
endif
else
call DestroyEffect(AddSpecialEffectTarget(FX, u, FX_ATTPT))
endif
endif
set u=null
return false
endmethod
private method onDamageTaken takes unit origin, real damage returns real
local real blocked=0
if GetRandomReal(0,1)<=Chance(.level) and damage+0.406>=Minimum_Damage(.level, .target) then
if ValidTarget(.target, .caster) then
call SetUnitLife(.target, GetUnitLife(.target)+Health_Restored(.level, .target, damage))
static if LIBRARY_TimedHandles then
if FX_DURATION>0 then
call DestroyEffectTimed(AddSpecialEffectTarget(FX, .target, FX_ATTPT), FX_DURATION)
else
call DestroyEffect(AddSpecialEffectTarget(FX, .target, FX_ATTPT))
endif
else
call DestroyEffect(AddSpecialEffectTarget(FX, .target, FX_ATTPT))
endif
set blocked=Damage_Blocked(.level, .target, damage)
endif
if Aoe(.level)>0. then
set .Tmps=this
set .CurrentDamage=damage
call GroupEnumUnitsInArea(ENUM_GROUP, GetUnitX(.target), GetUnitY(.target), Aoe(.level), Condition(function thistype.AoeHealEnum))
endif
set .healings=.healings+1
if Max_Healings(.level)>0 and .healings>=Max_Healings(.level) then
call UnitRemoveBuff(.target, BuffType)
endif
return -blocked
endif
return 0.
endmethod
static method create takes unit caster, unit target returns thistype
local thistype s=Instance[GetUnitId(target)]
if s==0 then
set s=.allocate(target, PRIORITY)
set s.caster=caster
set s.target=target
if TARGET_FX!="" then
set s.targetFx=AddSpecialEffectTarget(TARGET_FX, target, TARGET_FX_ATTPT)
endif
set s.level=GetUnitAbilityLevel(caster, AID)
set Instance[GetUnitId(target)]=s
else
if s.level<GetUnitAbilityLevel(caster, AID) then
set s.caster=caster
set s.healings=0
set s.level=GetUnitAbilityLevel(caster, AID)
endif
endif
set UnitAddBuff(caster, target, BuffType, Duration(s.level), s.level).data=s
return s
endmethod
private function Init takes nothing returns nothing
call RegisterSpellEffectResponse(AID, CastResponse)
set BuffType=DefineBuffType(BUFF_PLACER_AID, BID, 0, false, true, 0,0,Data.BuffRemoved)
call SetUpSpellData()
endfunction
endlibrary[/code]
Smiting Zeal
Every time the hero casts a spell, all unit surrounding the target point get damaged. Drains 20 additional Mana Points with every cast.
Level 1 - Damages for 2 times the hero's intelligence. Level 2 - Damages for 3 times the hero's intelligence. Level 3 - Damages for 4 times the hero's intelligence.
globals
private constant integer AID = 'A002' // any passive ability should do fine, preferably one that doesnt place a buff.
private constant string DAMAGE_FX = "Abilities\\Spells\\Human\\Feedback\\SpellBreakerAttack.mdl" // effect displayed when a unit gets damaged by this ability
private constant string DAMAGE_FX_ATTPT = "overhead" // where to display the effect
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_MAGIC // what type of damage is dealt to enemy units surrounding the caster (magic, physical, pure, ...)
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC // what type of damage is dealt to enemy units surrounding the caster (magic, physical, pure, ...)
private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS // sound played when a unit is damaged by this ability, WHOKNOWS or null for no sound.
private real array AOE // enemy units within this radius get damaged
private real array MANA_COST // this ability drains this much additional mana from the caster, values >0 but <1 are values relative to the maximum mana of the caster
private constant boolean ENFORCE_MANA_COST = false // if true, the effects of this ability will only be triggered if the hero has enough mana,
// if false, it will be triggered whether or not the caster has enough mana, and if he doesnt,
// it will subtract the remaining mana points
endglobals
private function Aoe takes integer level returns real
return AOE[level]
endfunction
private function Mana_Cost takes integer level returns real
return MANA_COST[level]
endfunction
private function Damage takes unit caster, integer level returns real
return GetHeroInt(caster, true)*(1.+level)
endfunction
private function SetUpSpellData takes nothing returns nothing
set AOE[1]=300.
set AOE[2]=375.
set AOE[3]=450.
set MANA_COST[1]=20.
set MANA_COST[2]=20.
set MANA_COST[3]=20.
endfunction
private function ValidateTarget takes unit u, unit caster returns boolean
return IsUnitEnemy(u, GetOwningPlayer(caster))/*
*/ and IsUnitType(u, UNIT_TYPE_DEAD)==false/*
*/ and IsUnitType(u, UNIT_TYPE_STRUCTURE)==false/*
*/ and IsUnitType(u, UNIT_TYPE_MECHANICAL)==false/*
*/ and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)==false/*
*/ and IsUnitVisible(u, GetOwningPlayer(caster))/*
*/
endfunction
//
globals
private boolexpr DamageFilter
private real tmpdam
endglobals
private function DamageFilterFunc takes nothing returns boolean
local unit u=GetFilterUnit()
if ValidateTarget(u, SpellEvent.CastingUnit) then
call UnitDamageTarget(SpellEvent.CastingUnit, u, tmpdam, true, true, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(DAMAGE_FX, u, DAMAGE_FX_ATTPT))
endif
set u=null
return false
endfunction
private function CastResponse takes nothing returns nothing
local integer level = GetUnitAbilityLevel(SpellEvent.CastingUnit, AID)
local real cost=0
if level>0 then
if Mana_Cost(level)>=1 then
set cost=Mana_Cost(level)
elseif Mana_Cost(level)>0 then
set cost=Mana_Cost(level)*GetUnitState(SpellEvent.CastingUnit, UNIT_STATE_MANA)
endif
if not ENFORCE_MANA_COST or GetUnitState(SpellEvent.CastingUnit, UNIT_STATE_MANA)>=cost then
call SetUnitState(SpellEvent.CastingUnit, UNIT_STATE_MANA, RMaxBJ(GetUnitState(SpellEvent.CastingUnit, UNIT_STATE_MANA)-Mana_Cost(level), 0))
set tmpdam=Damage(SpellEvent.CastingUnit, level)
call GroupEnumUnitsInArea(ENUM_GROUP, GetUnitX(SpellEvent.CastingUnit), GetUnitY(SpellEvent.CastingUnit), Aoe(level), DamageFilter)
endif
endif
endfunction
private function Init takes nothing returns nothing
call RegisterSpellEffectResponse(0, CastResponse)
set DamageFilter=Condition(function DamageFilterFunc)
call SetUpSpellData()
endfunction
endlibrary[/code]
Reverse Damage
Surrounds the target unit with a shield which reverses the next damage greater than 20 within 5 seconds the unit would receive and instead heals the unit for the same amount.
Maximum reversed damage is 100.
globals
private constant integer AID = 'A003' // ability triggering this. Any unit targeting ability is fine. Used Bloodlust
private constant integer BUFF_PLACER_AID = 'A006' // Ability placing BID on the unit this ability is added to. Based off of Slow Aura (Tornado).
private constant integer BID = 'B002' // buff placed by BUFF_PLACER_AID on the target unit
private constant string FX = "Abilities\\Spells\\Undead\\ReplenishHealth\\ReplenishHealthCasterOverhead.mdl" // displayed on the target unit when the effect of this ability is triggered.
private constant string FX_ATTPT = "head"
private constant real FX_DURATION = 0. // 0 or less only plays the death animation // ignored if TimedHandles is not present in the map
private constant string TARGET_FX = "Abilities\\Spells\\Items\\HealingSalve\\HealingSalveTarget.mdl" // displayed on the target of this spell
private constant string TARGET_FX_ATTPT = "head" // where to display the effect on the target of this spell
private constant integer PRIORITY = 0 // when to trigger the effects of an instance of this spell when a unit receives damage // refer to DamageModifiers documentation
private real array DURATION // how long does the buff last?
private real array AOE // Heals all units around the damaged target in this area
private real array CHANCE // Chance to trigger this ability // 1.0 = 100% // 0.0 = 0%
private integer array MAX_HEALINGS // heal at most this many times // zero or less for no limit
endglobals
// how long does the buff last?
private function Duration takes integer level returns real
return DURATION[level]
endfunction
// Heals all units around the damaged target in this area
private function Aoe takes integer level returns real
return AOE[level]
endfunction
// Chance to trigger this ability // 1.0 = 100% // 0.0 = 0%
private function Chance takes integer level returns real
return CHANCE[level]
endfunction
// heal at most this many times // zero or less for no limit
private function Max_Healings takes integer level returns integer
return MAX_HEALINGS[level]
endfunction
private function SetUpSpellData takes nothing returns nothing
// how long does the buff last?
set DURATION[1]=5
set DURATION[2]=5
set DURATION[3]=5
// Heals all units around the damaged target in this area
set AOE[1]=0
set AOE[2]=0
set AOE[3]=0
// Chance to trigger this ability // 1.0 = 100% // 0.0 = 0%
set CHANCE[1]=1
set CHANCE[2]=1
set CHANCE[3]=1
// heal at most this many times // zero or less for no limit
set MAX_HEALINGS[1]=1
set MAX_HEALINGS[2]=1
set MAX_HEALINGS[3]=1
endfunction
// if you want to get the targets current HP, use GetUnitLife(whichUnit)
// damage dealt to a unit with this buff active needs to be greater than what this function returns to be blocked
private function Minimum_Damage takes integer level, unit target returns real
return 20.
endfunction
// how much damage to block
private function Damage_Blocked takes integer level, unit target, real damage returns real
return RMinBJ(damage, 100.)
endfunction
// how much health to restore after blocking
private function Health_Restored takes integer level, unit target, real damage returns real
return RMinBJ(damage, 100.)
endfunction
// how much health to heal units in the area
private function Aoe_Heal takes integer level, unit target, real damage returns real
return 0.
endfunction
// only units matching these criteria will get healed
private function ValidTarget takes unit u, unit caster returns boolean
return IsUnitAlly(u, GetOwningPlayer(caster))/*
*/ and IsUnitType(u, UNIT_TYPE_MECHANICAL)==false/*
*/ and IsUnitType(u, UNIT_TYPE_STRUCTURE)==false/*
*/ and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)==false/*
*/
endfunction
//
globals
private integer BuffType
endglobals
private struct Data extends DamageModifier
unit caster
unit target
effect targetFx
integer level
integer healings=0
static thistype Tmps
static real CurrentDamage
static thistype array Instance
private method onDestroy takes nothing returns nothing
set Instance[GetUnitId(.target)]=0
set .caster=null
set .target=null
if TARGET_FX!="" then
call DestroyEffect(.targetFx)
set .targetFx=null
endif
endmethod
private static method AoeHealEnum takes nothing returns boolean
local unit u=GetFilterUnit()
if u!=.Tmps.target and ValidTarget(u, .Tmps.caster) then
call SetUnitLife(u, GetUnitLife(u)+Aoe_Heal(.Tmps.level, .Tmps.target, .CurrentDamage))
static if LIBRARY_TimedHandles then
if FX_DURATION>0 then
call DestroyEffectTimed(AddSpecialEffectTarget(FX, u, FX_ATTPT), FX_DURATION)
else
call DestroyEffect(AddSpecialEffectTarget(FX, u, FX_ATTPT))
endif
else
call DestroyEffect(AddSpecialEffectTarget(FX, u, FX_ATTPT))
endif
endif
set u=null
return false
endmethod
private method onDamageTaken takes unit origin, real damage returns real
local real blocked=0
if GetRandomReal(0,1)<=Chance(.level) and damage+0.406>=Minimum_Damage(.level, .target) then
if ValidTarget(.target, .caster) then
call SetUnitLife(.target, GetUnitLife(.target)+Health_Restored(.level, .target, damage))
static if LIBRARY_TimedHandles then
if FX_DURATION>0 then
call DestroyEffectTimed(AddSpecialEffectTarget(FX, .target, FX_ATTPT), FX_DURATION)
else
call DestroyEffect(AddSpecialEffectTarget(FX, .target, FX_ATTPT))
endif
else
call DestroyEffect(AddSpecialEffectTarget(FX, .target, FX_ATTPT))
endif
set blocked=Damage_Blocked(.level, .target, damage)
endif
if Aoe(.level)>0. then
set .Tmps=this
set .CurrentDamage=damage
call GroupEnumUnitsInArea(ENUM_GROUP, GetUnitX(.target), GetUnitY(.target), Aoe(.level), Condition(function thistype.AoeHealEnum))
endif
set .healings=.healings+1
if Max_Healings(.level)>0 and .healings>=Max_Healings(.level) then
call UnitRemoveBuff(.target, BuffType)
endif
return -blocked
endif
return 0.
endmethod
static method create takes unit caster, unit target returns thistype
local thistype s=Instance[GetUnitId(target)]
if s==0 then
set s=.allocate(target, PRIORITY)
set s.caster=caster
set s.target=target
if TARGET_FX!="" then
set s.targetFx=AddSpecialEffectTarget(TARGET_FX, target, TARGET_FX_ATTPT)
endif
set s.level=GetUnitAbilityLevel(caster, AID)
set Instance[GetUnitId(target)]=s
else
if s.level<GetUnitAbilityLevel(caster, AID) then
set s.caster=caster
set s.healings=0
set s.level=GetUnitAbilityLevel(caster, AID)
endif
endif
set UnitAddBuff(caster, target, BuffType, Duration(s.level), s.level).data=s
return s
endmethod
22:39, 24th Dec 2009
TriggerHappy:
Review for Spell
First of all, thanks for using TimedHanldes =)
In SmitingZeal you could be using static ifs for the attribute, but
that is most likely overkill to get rid of a simple BJ.
In...
Prolonged Life's tooltip is unclear... It does not nescescarilly imply that it actually only fires when the unit would take a fatal blow and may lead people to thinking it heals them over 8 seconds.
Should be more like
Blocks a fatal blow once in the next 8 seconds by restoring health.
Meh @ tooltip. Find me a good excuse to update this other than an unclear tooltip.
@Requirements: http://www.hiveworkshop.com/forums/1376294-post26.html
So yes, i do, in fact, expect everyone who implements these spells to import a number of dependencies. And this is not going to change. Welcome to a world of sane programming.
This is good, really good. I don't get it why people complain about requirements, they're used by almost every single spell (although some might prefer AIDS or UnitIndexer over AutoIndex but whatever).
In 3 create methods you can always store in ability level but I guess one call more or less wouldn't make it worse.
Sane programming and Warcraft III are totally unrelated. Most spells do not use these systems or use alternative versions. Maybe all your spells do but it can quickly become a mess if people start using spells from alternative authors.
What the fuck.
I cant comprehend how this is relevenat AT ALL.
Youve made your point, ive made mine. Im not going to change my mind and your complaining also wont change a thing for anyone else. Either they use one of these spells, or they dont.
I wish you a happy reinventing the wheel. May you go insane over reimplementing TimedHandles or GroupUtils for the hundredth time.
I can't see much wrong with coding. The only things I can suggest is using a custom destroy method (instead of onDestroy) since your destroy is controlled. (unless I misread the code) GetOwningPlayer(u) can also be GetTriggerPlayer(), but that doesn't really make much of a difference. lol. ;P
Well to be tested ability its always tested in game. And once i load the map i can't start it. First i download and tried to test in game before i open editor. I have newgen 5e version. I wanted to test the abilities in game to see what they can do, but i couldn't
I still cant reproduce your problem, so im afraid i cant really do anything about it. All i can tell you is that it works for me when i start it from WC3s menu or from the editor using the "Test Map".
🔨 Downloads and Uploads have been fixed! If you still have trouble downloading or uploading assets to or from Hive, please reach out to us in the Site Discussion board.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.