- Joined
- May 3, 2008
- Messages
- 3,154
Ok, recently I started to work back at my project and found many of my spells was currently bugged such as having no model or the spells doesn't effect the targeted unit. Here is the list of spells with issues.
1) Arrow Prison Skills
Problem: The skills does damage and work fine, but there should be special effect affected all unit within the spells range when the skills confine the target.
2) Arrow Split
Problem: When the arrow travel for a certain distance, it should split into 12 smaller arrow that hit and damage all enemies. Problem is, when the arrow travel a certain distance it just dissappear.
3) Electric Chain
Problem: When the unit attack enemies for 7 times, the next attack should had unleash a chain lightning against the enemies but it doesn't seems to happen.
4) Lightning Strike
Problem: When this skills was activate, there should be a lightning hitting the targeted area, dealing damage and knockback the enemies. However, the spells doesn't seems to be working now.
5) Stomp of Corruption
Problem: This skill work fine in all way except that it doesn't applied negative buff towards the enemy.
6) Napalm Shock
Problem: This skill work fine, except the dummy unit doesn't applied skill to the targeted unit.
7) Frost Nova
Problem: The skills effect doesn't show properly and doesn't affect enemy units.
8) Phoenix Spirit
Problem: This skills work fine. But for some unknown reason, it applied regeneration aura to enemy unit for a couple of seconds.
I even provide the map for you to test it, so you can know pretty much whats the problem all about.
1) Arrow Prison Skills
Problem: The skills does damage and work fine, but there should be special effect affected all unit within the spells range when the skills confine the target.
JASS:
scope ArrowPrison initializer init
//##################################################################################################################
globals
//******************************
//* Config
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//*
public constant integer ABIL_ID = 'A637'
//*
public constant real HEIGHT_OFFSET = 70
public constant real SPEED = 900
public constant real ARC = 0
//*
public constant string TARGET_FX_PATH = "Abilities\\Spells\\Items\\AIre\\AIreTarget.mdl"
//*
//*
public real array RADIUS
public real array EXPIRE_TIME
public real array ARROW_DAMAGE
public integer array ARROWS
//*
//*
//* Data
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//*
private
private group data__tempGrp = CreateGroup()
//*
//*
//******************************************************************************************************************
endglobals
native UnitAlive takes unit u returns boolean
//##################################################################################################################
struct arrowprison extends projectile
//******************************
//* Arrow Prison Projectile
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//*
//*
readonly integer level
//*
private effect model = null
private static constant string modelpath = "Abilities\\Weapons\\GuardTowerMissile\\GuardTowerMissile.mdl"
private static constant integer unitid = 'dumm'
//*
private group targets = null
//*
//*
method onDestroy takes nothing returns nothing
call DestroyEffect(model)
call ReleaseGroup(targets)
endmethod
//*
//*
method isValidTargetUnit takes unit u returns boolean
return IsUnitEnemy(u, GetOwningPlayer(source)) and /*
*/ not IsUnitInGroup(u, targets) and /*
*/ not IsUnitType(u, UNIT_TYPE_STRUCTURE) and /*
*/ UnitAlive(u) and u!=toUnit
endmethod
method onUnitCollision takes unit u returns nothing
call GroupAddUnit(targets, u)
call UnitDamageTarget(source, u, ARROW_DAMAGE[level], /*
*/ false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, null)
endmethod
//*
//*
static method create takes unit caster, real x, real y, real face, unit target, integer level returns thistype
local thistype m
set m = allocate(CreateUnit(GetOwningPlayer(caster), unitid, x, y, face))
set m.source = caster
set m.target = target
set m.level = level
set m.model = AddSpecialEffectTarget(modelpath, m.toUnit, "origin")
set m.targets = NewGroup()
set m.z = m.z + HEIGHT_OFFSET
set m.activeDestCollision = false
set m.activeUnitCollision = true
set m.activeRotation = true
set m.activePitch = true
return m
endmethod
//*
//*
//******************************************************************************************************************
endstruct
//##################################################################################################################
private struct spelltargetdata
//******************************
//* Spell Target Data
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* Tracks units that are affected by "Arrow Prison". When a unit is affected by two individual instances of
//* ArrowPrison I use "AutoData" to ensure that it will not break the functionality. The aim is to eliminate the
//* bugs associated with units being unpaused by a previous instance of the spell.
//*
//*
implement AutoData
//*
//*
method onDestroy takes nothing returns nothing
if spelltargetdata[me].size <= 1 then //the buffs applied will only be removed if there are no other
call SetUnitTimeScale(me, 1) //instances of "spelltargetdata" that apply to this unit.
call PauseUnit(me, false)
endif
endmethod
//*
//*
static method create takes unit target returns thistype
local thistype m
if spelltargetdata[target] == 0 then //the buffs will only be applied if the target is not already
call SetUnitTimeScale(target, 0) //under the effects of another instance of "spelltargetdata".
call PauseUnit(target, true)
endif
set m = allocate()
set m.me = target
return m
endmethod
//*
//*
//******************************************************************************************************************
endstruct
//##################################################################################################################
private struct spelldata
public unit caster = null
public unit target = null
public integer level
public real x
public real y
public group grp = null
public projectilegroup grpProj
method onDestroy takes nothing returns nothing
call ReleaseGroup(grp)
call grpProj.destroy()
endmethod
static method create takes nothing returns thistype
local thistype m = allocate()
local integer i = 0
local integer n
local real x
local real y
local vector vi
local vector vf
set m.caster = GetTriggerUnit()
set m.target = GetSpellTargetUnit()
set m.x = GetSpellTargetX()
set m.y = GetSpellTargetY()
set m.level = GetUnitAbilityLevel(m.caster, ABIL_ID)-1
set m.grp = NewGroup()
set m.grpProj = projectilegroup.create()
set vf = vector.createTerrainPoint(m.x, m.y)
set vf.z = vf.z + HEIGHT_OFFSET
set n = ARROWS[m.level]
loop
exitwhen i == n
set x = GetUnitX(m.target) + RADIUS[m.level] * Cos((2*bj_PI/n)*i)
set y = GetUnitY(m.target) + RADIUS[m.level] * Sin((2*bj_PI/n)*i)
call m.grpProj.add( arrowprison.create(m.caster, x, y, (360/n)*i - 180, m.target, m.level) )
set vi = vector.createTerrainPoint(x, y)
set vi.z = vi.z + HEIGHT_OFFSET
set m.grpProj.at[i].timescale = 0
call m.grpProj.at[i].doLaunch(vi, vf, SPEED, ARC)
call vi.destroy()
set i = i + 1
endloop
call vf.destroy()
return m
endmethod
endstruct
//##################################################################################################################
private function run_efilter takes nothing returns boolean
local unit t = GetTriggerUnit()
local unit f = GetFilterUnit()
local boolean r
set r = IsUnitEnemy(f, GetOwningPlayer(t)) and /*
*/ not IsUnitType(f, UNIT_TYPE_STRUCTURE) and /*
*/ not IsUnitType(f, UNIT_TYPE_MAGIC_IMMUNE) and /*
*/ UnitAlive(f) and f!=t
if r then
call spelltargetdata.create(f)
endif
set t = null
set f = null
return r
endfunction
//##################################################################################################################
private function run_expireEnum takes nothing returns nothing
call spelltargetdata[GetEnumUnit()].destroy()
endfunction
private function run_expire takes nothing returns nothing
local spelldata d = GetTimerData(GetExpiredTimer())
local integer i = 0
call ForGroup(d.grp, function run_expireEnum)
// Remove any buff that this spell applied to the target units.
loop
exitwhen i == d.grpProj.max
set d.grpProj.at[i].timescale = 1
set i = i + 1
endloop
call d.destroy()
call ReleaseTimer(GetExpiredTimer())
endfunction
//##################################################################################################################
public function checkid takes nothing returns boolean
return GetSpellAbilityId() == ABIL_ID
endfunction
public function run takes nothing returns nothing
local spelldata d = spelldata.create()
local timer t = NewTimer()
call GroupEnumUnitsInRange(d.grp, GetUnitX(d.target), GetUnitY(d.target), /*
*/ RADIUS[d.level], Filter(function run_efilter))
call SetTimerData(t, d)
call TimerStart(t, EXPIRE_TIME[d.level], false, function run_expire)
set t = null
endfunction
//##################################################################################################################
public function init takes nothing returns nothing
local trigger t = CreateSpellTrigger(null)
call TriggerAddCondition(t, Filter(function checkid))
call TriggerAddAction(t, function run)
//--------------------------------------------------------------------------------------------------------------
// Spell Constant Values
//--------------------------------------------------------------------------------------------------------------
set RADIUS[0] = 500
set RADIUS[1] = 500
set RADIUS[2] = 500
//--------------------------------------------------------------------------------------------------------------
set EXPIRE_TIME[0] = 3
set EXPIRE_TIME[1] = 4
set EXPIRE_TIME[2] = 5
//--------------------------------------------------------------------------------------------------------------
set ARROWS[0] = 12
set ARROWS[1] = 12
set ARROWS[2] = 12
//--------------------------------------------------------------------------------------------------------------
set ARROW_DAMAGE[0] = 35
set ARROW_DAMAGE[1] = 45
set ARROW_DAMAGE[2] = 60
//--------------------------------------------------------------------------------------------------------------
set t = null
endfunction
endscope
2) Arrow Split
Problem: When the arrow travel for a certain distance, it should split into 12 smaller arrow that hit and damage all enemies. Problem is, when the arrow travel a certain distance it just dissappear.
JASS:
scope ArrowSplit initializer init
native UnitAlive takes unit u returns boolean
globals
//******************************
//* Config & Setup
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
public constant integer ABIL_ID = 'A62X'
public constant integer DUMM_ID = 'dumm'
//*
//* Projectile Data
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
public constant real SPEED_PRIMARY = 550
public constant real ARC_PRIMARY = 0
//*
public constant real SPEED_SECONDARY = 800
public constant real ARC_SECONDARY = 0
public constant real RANGE_SECONDARY = 700
//*
public constant real HEIGHT_OFFSET = 60
//*
public real array DAMAGE_SECONDARY
public integer array SPLIT_COUNT
//*
//*
//******************************************************************************************************
endglobals
private struct arrowsplit_arrow extends projectile
//******************************
//* Arrow Split Secondary Projectile
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* Duplicate of the "ArrowSplit" projectiles with different actions.
//*
readonly integer level
//*
private effect obj__model = null
private static constant string obj__modelpath = "Abilities\\Weapons\\GuardTowerMissile\\GuardTowerMissile.mdl"
//*
//*
private static constant real obj__speed = SPEED_SECONDARY
private static constant real obj__arc = ARC_SECONDARY
//*
//*
method onDestroy takes nothing returns nothing
call DestroyEffect(obj__model)
endmethod
//*
//*
method isValidTargetUnit takes unit u returns boolean
return IsUnitEnemy(u, GetOwningPlayer(source)) and /*
*/ not IsUnitType(u, UNIT_TYPE_STRUCTURE) and /*
*/ not IsUnitType(u, UNIT_TYPE_FLYING) and /*
*/ UnitAlive(u)
endmethod
method onUnitCollision takes unit u returns nothing
call UnitDamageTarget(source, u, DAMAGE_SECONDARY[level], false, false, /*
*/ ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, null)
call kill( )
endmethod
//*
//*
static method create takes unit source, vector vi, vector vf, integer level returns thistype
local thistype m
local real a = Atan2(vf.y-vi.y, vf.x-vi.x)
set m = allocate(CreateUnit(GetOwningPlayer(source), DUMM_ID, vi.x, vi.y, a*bj_RADTODEG))
set m.obj__model = AddSpecialEffectTarget(obj__modelpath, m.toUnit, "origin")
set m.source = source
set m.level = level
set m.toRemove = true
set m.toKill = false
set m.activeDestCollision = false
call m.doLaunch(vi, vf, obj__speed, obj__arc)
return m
endmethod
//*
//*
//******************************************************************************************************
endstruct
struct arrowsplit extends projectile
//******************************
//* Arrow Split Projectile
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* Primary data structure that represents the initial projectile that is fired when the ability is
//* put into effect. This arrow will split up into several "arrowsplit_arrow" structures.
//*
readonly integer level
//*
private effect obj__model = null
private static constant string obj__modelpath = "Abilities\\Weapons\\GuardTowerMissile\\GuardTowerMissile.mdl"
//*
//*
private static constant real obj__speed = SPEED_PRIMARY
private static constant real obj__arc = ARC_PRIMARY
//*
//*
method onDestroy takes nothing returns nothing
call DestroyEffect(obj__model)
endmethod
//*
//*
method onFinish takes nothing returns nothing
local integer i = 0
local integer n = SPLIT_COUNT[level]
local vector vi
local vector vf
set vi = vector.create(targetX, targetY, targetZ)
loop
exitwhen i == n
// ----
// Once the initial arrow has reached its target, it will explode into several smaller
// arrows that travel outwards and deal damage to enemy units.
set vf = vector.createTerrainPoint(vi.x+RANGE_SECONDARY*Cos((2*bj_PI/n)*i), /*
*/ vi.y+RANGE_SECONDARY*Sin((2*bj_PI/n)*i))
set vf.z = vf.z + HEIGHT_OFFSET
call arrowsplit_arrow.create(source, vi, vf, level)
call vf.destroy( )
set i = i + 1
endloop
call vi.destroy( )
endmethod
//*
//*
static method create takes unit source, vector vi, vector vf, integer level returns thistype
local thistype m
local real a = Atan2(vf.y-vi.y, vf.x-vi.x)
set m = allocate(CreateUnit(GetOwningPlayer(source), DUMM_ID, vi.x, vi.y, a*bj_RADTODEG))
set m.obj__model = AddSpecialEffectTarget(obj__modelpath, m.toUnit, "origin")
set m.source = source
set m.level = level
// Allocate the projectile with a unit using configuration values.
set m.toRemove = true
set m.toKill = false
set m.activeDestCollision = false
set m.activeUnitCollision = false
call m.doLaunch(vi, vf, obj__speed, obj__arc)
// Launch allocated projectile with specified input.
return m
endmethod
//*
//*
//******************************************************************************************************
endstruct
//######################################################################################################
//#
//# SPELL TRIGGER SETUP
//#
//######################################################################################################
public function run takes nothing returns nothing
local unit u = GetTriggerUnit()
local vector vi = vector.createTerrainPoint(GetUnitX(u), GetUnitY(u))
local vector vf = vector.createTerrainPoint(GetSpellTargetX(), GetSpellTargetY())
set vi.z = vi.z + HEIGHT_OFFSET
set vf.z = vf.z + HEIGHT_OFFSET
call arrowsplit.create(u, vi, vf, GetUnitAbilityLevel(u, ABIL_ID))
set u = null
endfunction
public function checkId takes nothing returns boolean
return GetSpellAbilityId()==ABIL_ID
endfunction
//#
//# Initialization
//# ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
public function init takes nothing returns nothing
local trigger t=CreateSpellTrigger(null)
call TriggerAddCondition(t, Filter(function checkId))
call TriggerAddAction(t, function run)
//# ----------------------------------------------------------------------------------------------------
set DAMAGE_SECONDARY[0] = 50
//# ----------------------------------------------------------------------------------------------------
set SPLIT_COUNT[0] = 12
//# ----------------------------------------------------------------------------------------------------
endfunction
//#
//######################################################################################################
endscope
3) Electric Chain
Problem: When the unit attack enemies for 7 times, the next attack should had unleash a chain lightning against the enemies but it doesn't seems to happen.
JASS:
library ElectricChain initializer Init requires SpellIndexer
//*
struct Chain
//*
static constant real COOLDOWN = 0.6 //Prevents spamming "stop"
static unit array Attack
static timer array Tim
static Chain array stack
integer count = 0
boolean dont = false
effect eff = null
player owner = null
timer tim = null
//*
//* Get Attacking Unit's ID
//* ============================================================================
static method RetrieveViaAttacker takes unit u returns Chain
local integer i = 0
loop
if .Attack[i] == u then
exitwhen true
elseif .Attack[i] == null then
set .stack[i] = Chain.allocate()
set .Attack[i] = u
set .Tim[i] = CreateTimer()
set .stack[i].tim = .Tim[i]
set .stack[i].owner = GetOwningPlayer(u)
exitwhen true
endif
set i = i + 1
endloop
return .stack[i]
endmethod
//*
//* Failsafe so player can't spam "Stop"
//* ============================================================================
static method RetrieveViaTimer takes nothing returns nothing
local integer i = 0
local timer t = GetExpiredTimer()
loop
exitwhen .Tim[i] == t
set i = i + 1
endloop
set .stack[i].dont = false
endmethod
//*
//* Main Setup
//* ============================================================================
static method Actions takes unit att,unit trg,unit u returns nothing
local Chain this = .RetrieveViaAttacker(att)
local integer level = GetUnitAbilityLevel(att,'A626')
if IsUnitEnemy(trg,.owner) and not .dont then
if .count == 9 - level then
set .eff = AddSpecialEffectTarget("Abilities\\Spells\\Orc\\LightningShield\\LightningShieldTarget.mdl",att,"weaponleft")
set .count = .count + 1
elseif .count == 10 - level then
set .count = 0
set u = CreateUnit(.owner,'h60W',GetUnitX(att),GetUnitY(att),GetUnitFacing(att))
call UnitAddAbility(u,'A61X')
call SetUnitAbilityLevel(u,'A61X',level)
call IssueTargetOrder(u,"chainlightning",trg)
call UnitApplyTimedLife(u,'BTLF',0.50)
call DestroyEffect(.eff)
else
set .count = .count + 1
endif
endif
set .dont = true
call TimerStart(.tim,COOLDOWN,false,function Chain.RetrieveViaTimer)
endmethod
//*
//* Conditions
//* ============================================================================
static method Conditions takes nothing returns boolean
if GetUnitAbilityLevel(GetAttacker(),'B612') > 0 then
call .Actions(GetAttacker(),GetTriggerUnit(),null)
endif
return false
endmethod
//*
//*
endstruct
//*
//* Setup Initialization
//* ===========================================================================
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_ATTACKED)
call TriggerAddCondition(t,Condition(function Chain.Conditions))
endfunction
endlibrary
4) Lightning Strike
Problem: When this skills was activate, there should be a lightning hitting the targeted area, dealing damage and knockback the enemies. However, the spells doesn't seems to be working now.
JASS:
scope LightningStrike initializer init
native UnitAlive takes unit u returns boolean
//##############################################################################################################
private struct spelldata
//******************************
//* Spell Data
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* Stores relevant data to the spell being put into effect so that it can be referenced associatively.
//*
readonly unit caster = null
readonly real targetx
readonly real targety
readonly integer level
//*
//*
static method create takes nothing returns thistype
local thistype m = allocate()
set m.caster = GetTriggerUnit()
set m.targetx = GetSpellTargetX()
set m.targety = GetSpellTargetY()
set m.level = GetUnitAbilityLevel(m.caster, GetSpellAbilityId())
return m
endmethod
//*
//*
//**************************************************************************************************************
endstruct
globals
//******************************
//* Config
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//*
public constant integer ABIL_ID = 'A621'
//*
public constant real KNOCKBACK_DISTANCE = 325
public constant real KNOCKBACK_DURATION = 1.45
//*
public constant real AREA_OF_EFFECT = 400
//*
//* Temp Data
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
private group temp__grp = CreateGroup()
private spelldata temp__data
//*
//*
//**************************************************************************************************************
endglobals
//##############################################################################################################
private struct strikeknockback extends knockback
//******************************
//* Ability Knockback
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* Controls the knockback when a unit is struck by lightning. Requires the "KnockbackLite" vJass library in
//* order to properly inherit the necessary members. This basically just adds a dust effect to the knock-back.
//*
//* In addition, units that are being knocked back will destroy nearby destructables.
//*
readonly real size
//*
private static timer loop__tmr = CreateTimer()
private static constant real loop__tmrRef = 0.03
//*
private static rect dest__enum = Rect(0, 0, 0, 0)
private static boolexpr dest__enumfilt = null
private static thistype dest__tempdata
//*
private static thistype array loop__stack
private static integer loop__stacksize = 0
private integer loop__stackindex
//*
method onDestroy takes nothing returns nothing
set thistype.loop__stacksize=thistype.loop__stacksize-1
set thistype.loop__stack[loop__stackindex]=thistype.loop__stack[thistype.loop__stacksize]
set thistype.loop__stack[loop__stackindex].loop__stackindex=loop__stackindex
endmethod
//*
//*
private static method loopfunc_enumfilter takes nothing returns boolean
local thistype kb = dest__tempdata
local destructable dest = GetFilterDestructable()
local real x = GetWidgetX(dest)-GetWidgetX(kb.subject)
local real y = GetWidgetY(dest)-GetWidgetY(kb.subject)
if (x*x + y*y) <= (kb.size*kb.size) then
call KillDestructable(dest)
endif
set dest = null
return false
endmethod
private static method loopfunc takes nothing returns nothing
local integer i = loop__stacksize-1
local thistype kb
local real x
local real y
loop
exitwhen i < 0
set kb = loop__stack[i]
if kb != 0 then
set x = GetWidgetX(kb.subject)
set y = GetWidgetY(kb.subject)
set dest__tempdata = kb
call SetRect(dest__enum, x-kb.size/2, y-kb.size/2, x+kb.size/2, y+kb.size/2)
call EnumDestructablesInRect(dest__enum, dest__enumfilt, null)
// -> Insert other knockback specifications...
endif
set i = i-1
endloop
endmethod
//*
//*
static method create takes unit u, real angle, real size returns thistype
local thistype kb = allocate(u, angle, KNOCKBACK_DISTANCE, KNOCKBACK_DURATION)
set kb.size = size
if loop__stacksize == 0 then
call TimerStart(loop__tmr, loop__tmrRef, true, function thistype.loopfunc)
endif
set kb.loop__stackindex = loop__stacksize
set loop__stack[loop__stacksize] = kb // Add the newly initiated instance to the stack.
set loop__stacksize = loop__stacksize+1
return kb
endmethod
//*
//*
private static method onInit takes nothing returns nothing
set dest__enumfilt = Filter(function thistype.loopfunc_enumfilter)
// To avoid unnecessary calls to the native "Filter" we can just save this value in memory.
endmethod
//*
//*
//**************************************************************************************************************
endstruct
//##############################################################################################################
public function startKB takes nothing returns boolean
local unit filt = GetFilterUnit()
local boolean result
set result = IsUnitEnemy(filt, GetOwningPlayer(temp__data.caster)) and /*
*/ not IsUnitType(filt, UNIT_TYPE_STRUCTURE) and /*
*/ not IsUnitType(filt, UNIT_TYPE_FLYING) and /*
*/ not IsUnitType(filt, UNIT_TYPE_MAGIC_IMMUNE) and /*
*/ not IsUnitType(filt, UNIT_TYPE_SNARED) and /*
*/ UnitAlive(filt)
if result then
call strikeknockback.create(filt, Atan2(GetUnitY(filt)-temp__data.targety, /*
*/ GetUnitX(filt)-temp__data.targetx), 250)
endif
set filt = null
return false
endfunction
//##############################################################################################################
public function checkid takes nothing returns boolean
return GetSpellAbilityId() == ABIL_ID
endfunction
public function run takes nothing returns nothing
set temp__data = spelldata.create()
call GroupEnumUnitsInRange(temp__grp, temp__data.targetx, temp__data.targety, /*
*/ AREA_OF_EFFECT, Filter(function startKB))
call temp__data.destroy()
endfunction
//##############################################################################################################
public function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
exitwhen i == 16
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set i = i + 1
endloop
call TriggerAddCondition(t, Filter(function checkid))
call TriggerAddAction(t, function run)
endfunction
endscope
5) Stomp of Corruption
Problem: This skill work fine in all way except that it doesn't applied negative buff towards the enemy.
JASS:
scope StompOfCorruption initializer init
//######################################################################################################
globals
//**************************
//* Config
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//*
public constant integer abilityID = 'A63J'
//*
public constant real knockbackRange = 400
public constant real knockbackLife = 1.5 // -> this means that the knockback
// will last 1.5 seconds.
//*
//*
//******************************************************************************************************
endglobals
//######################################################################################################
public function init takes nothing returns nothing
endfunction
endscope
function Stomp_of_Corruption_Destructible_Utility takes destructable d returns boolean
local real dx=LoadReal(udg_SOC_Hash,0,7)-GetWidgetX(d)
local real dy=LoadReal(udg_SOC_Hash,0,8)-GetWidgetY(d)
if SquareRoot(dx*dx+dy*dy)<=200. then
call KillDestructable(d)
endif
return false
endfunction
function Stomp_of_Corruption_Destructible_Filter takes nothing returns boolean
return Stomp_of_Corruption_Destructible_Utility(GetFilterDestructable())
endfunction
function Stomp_of_Corruption_Do_Knockback takes integer id,unit u,rect r,real max,real dist,real speed,real vX,real vY returns nothing
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local real inc=2.*speed
set vX=x+vX*inc
set vY=y+vY*inc
call MoveRectTo(r,vX,vY)
call SaveReal(udg_SOC_Hash,0,7,vX)
call SaveReal(udg_SOC_Hash,0,8,vY)
call EnumDestructablesInRect(r,Filter(function Stomp_of_Corruption_Destructible_Filter),null)
if (GetRandomInt(0,6)<1) then
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl",x,y))
endif
if (GetRandomInt(0,4)<1) then
call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl",x,y))
endif
call SetUnitX(u,vX)
call SetUnitY(u,vY)
call SaveReal(udg_SOC_Hash,id,1,dist + inc)
call SaveReal(udg_SOC_Hash,id,2,speed)
endfunction
function Stomp_of_Corruption_Knockback_Setup_2 takes nothing returns nothing
local integer id=GetHandleId(GetEnumUnit())
local real max=LoadReal(udg_SOC_Hash,id,0)
local real dist=LoadReal(udg_SOC_Hash,id,1)
if dist>=max-1.5 then
call FlushChildHashtable(udg_SOC_Hash,id)
call GroupRemoveUnit(LoadGroupHandle(udg_SOC_Hash,0,4),GetEnumUnit())
call SaveInteger(udg_SOC_Hash,0,6,LoadInteger(udg_SOC_Hash,0,6)-1)
else
call Stomp_of_Corruption_Do_Knockback(id,GetEnumUnit(),LoadRectHandle(udg_SOC_Hash,0,5),max,dist,7.-(7./max*dist-LoadReal(udg_SOC_Hash,id,2)*0.1),LoadReal(udg_SOC_Hash,id,3),LoadReal(udg_SOC_Hash,id,4))
endif
endfunction
function Stomp_of_Corruption_Knockback_Setup_1 takes nothing returns nothing
call ForGroup(LoadGroupHandle(udg_SOC_Hash,0,4),function Stomp_of_Corruption_Knockback_Setup_2)
if LoadInteger(udg_SOC_Hash,0,6)==0 then
call PauseTimer(GetExpiredTimer())
endif
endfunction
function Stomp_of_Corruption_Filter takes nothing returns boolean
return GetWidgetLife(GetFilterUnit())>0.
endfunction
function Stomp_of_Corruption_Do_Loop takes integer iterations,integer tot,group g,group kb,unit caster,unit dum,unit tar,player p,real damage,integer level returns nothing
local integer id
local integer i=32
local real x
local real y
local real sx=GetUnitX(caster)
local real sy=GetUnitY(caster)
local real pos
loop
exitwhen (i==0)
set i=i-1
set x=sx+(100.*iterations*LoadReal(udg_SOC_Hash,1,i))
set y=sy+(100.*iterations*LoadReal(udg_SOC_Hash,2,i))
call GroupEnumUnitsInRange(g,x,y,150.,Filter(function Stomp_of_Corruption_Filter))
call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl",x,y))
loop
set tar=FirstOfGroup(g)
call GroupRemoveUnit(g,tar)
exitwhen (tar==null)
if (not IsUnitType(tar,UNIT_TYPE_STRUCTURE) and not IsUnitType(tar,UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(tar,UNIT_TYPE_FLYING) and IsUnitEnemy(tar,p)) then
call UnitDamageTarget(caster,tar,damage,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
set id=GetHandleId(tar)
call SaveReal(udg_SOC_Hash,id,0,100.*level)
call SaveReal(udg_SOC_Hash,id,1,0.)
call SaveReal(udg_SOC_Hash,id,2,0.)
if not (IsUnitInGroup(tar,kb)) then
set dum=CreateUnit(p,'n60R',sx,sy,0.)
call UnitApplyTimedLife(dum,'BTLF',1.)
call UnitAddAbility(dum,'A63I')
call SetUnitAbilityLevel(dum,'A63I',level)
call IssueTargetOrder(dum,"innerfire",tar)
call DestroyEffect(AddSpecialEffectTarget("Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl",tar,"overhead"))
set pos=Atan2(GetUnitY(tar)-sy,GetUnitX(tar)-sx)
call SaveReal(udg_SOC_Hash,id,3,Cos(pos))
call SaveReal(udg_SOC_Hash,id,4,Sin(pos))
call GroupAddUnit(kb,tar)
if tot==0 then
call TimerStart(LoadTimerHandle(udg_SOC_Hash,0,3),0.02,true,function Stomp_of_Corruption_Knockback_Setup_1)
endif
set tot=tot+1
endif
endif
endloop
endloop
call SaveInteger(udg_SOC_Hash,0,6,tot)
endfunction
function Stomp_of_Corruption_On_Loop takes nothing returns nothing
local integer i=3
local integer tot=LoadInteger(udg_SOC_Hash,0,0)
local integer iterations
loop
set iterations=LoadInteger(udg_SOC_Hash,i,4)+1
call Stomp_of_Corruption_Do_Loop(iterations,LoadInteger(udg_SOC_Hash,0,6),LoadGroupHandle(udg_SOC_Hash,0,2),LoadGroupHandle(udg_SOC_Hash,0,4),LoadUnitHandle(udg_SOC_Hash,i,0),null,null,LoadPlayerHandle(udg_SOC_Hash,i,1),LoadReal(udg_SOC_Hash,i,2),LoadInteger(udg_SOC_Hash,i,3))
if (iterations>LoadInteger(udg_SOC_Hash,i,5)) then
if (i!=tot) then
call SaveUnitHandle (udg_SOC_Hash,i,0,LoadUnitHandle (udg_SOC_Hash,tot,0))
call SavePlayerHandle (udg_SOC_Hash,i,1,LoadPlayerHandle (udg_SOC_Hash,tot,1))
call SaveReal (udg_SOC_Hash,i,2,LoadReal (udg_SOC_Hash,tot,2))
call SaveInteger (udg_SOC_Hash,i,3,LoadInteger (udg_SOC_Hash,tot,3))
call SaveInteger (udg_SOC_Hash,i,4,LoadInteger (udg_SOC_Hash,tot,4))
call SaveInteger (udg_SOC_Hash,i,5,LoadInteger (udg_SOC_Hash,tot,5))
set i=i-1
else
call PauseTimer(GetExpiredTimer())
endif
call FlushChildHashtable(udg_SOC_Hash,tot)
set tot=tot-1
else
call SaveInteger(udg_SOC_Hash,i,4,iterations)
endif
exitwhen (i>=tot)
set i=i+1
endloop
call SaveInteger(udg_SOC_Hash,0,0,tot)
endfunction
function Stomp_of_Corruption_Actions takes unit u returns nothing
local integer level=GetUnitAbilityLevel(u,'A63J')
local integer tot=LoadInteger(udg_SOC_Hash,0,0) + 1
call SaveUnitHandle (udg_SOC_Hash,tot,0,u)
call SavePlayerHandle (udg_SOC_Hash,tot,1,GetTriggerPlayer())
call SaveReal (udg_SOC_Hash,tot,2,I2R(GetHeroStr(u,false))*1.2)
call SaveInteger (udg_SOC_Hash,tot,3,level)
call SaveInteger (udg_SOC_Hash,tot,4,0)
call SaveInteger (udg_SOC_Hash,tot,5,level + 3)
call SaveInteger(udg_SOC_Hash,0,0,tot)
if (tot==3) then
call TimerStart(LoadTimerHandle(udg_SOC_Hash,0,1),0.03,true,function Stomp_of_Corruption_On_Loop)
endif
endfunction
function Stomp_of_Corruption_Conditions takes nothing returns nothing
if GetSpellAbilityId()=='A63J' then
call Stomp_of_Corruption_Actions(GetTriggerUnit())
endif
endfunction
//===========================================================================
constant function USSOC takes nothing returns boolean
return true
endfunction
function InitTrig_Stomp_of_Corruption takes nothing returns nothing
local integer i=11
local trigger t=CreateTrigger()
local filterfunc FF=Filter(function USSOC)
loop
call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
exitwhen i==0
set i=i-1
endloop
call DestroyBoolExpr(FF)
call TriggerAddAction(t,function Stomp_of_Corruption_Conditions)
set FF=null
set udg_SOC_Hash=InitHashtable()
call SaveInteger (udg_SOC_Hash,0,0,2)
call SaveTimerHandle (udg_SOC_Hash,0,1,CreateTimer())
call SaveGroupHandle (udg_SOC_Hash,0,2,CreateGroup())
call SaveTimerHandle (udg_SOC_Hash,0,3,CreateTimer())
call SaveGroupHandle (udg_SOC_Hash,0,4,CreateGroup())
call SaveRectHandle (udg_SOC_Hash,0,5,Rect(-200.,-200.,200.,200.))
call SaveInteger (udg_SOC_Hash,0,6,0)
loop
call SaveReal (udg_SOC_Hash,1,i,Cos((i+1)*11.25*bj_DEGTORAD))
call SaveReal (udg_SOC_Hash,2,i,Sin((i+1)*11.25*bj_DEGTORAD))
set i =i+1
exitwhen (i==32)
endloop
endfunction
6) Napalm Shock
Problem: This skill work fine, except the dummy unit doesn't applied skill to the targeted unit.
JASS:
scope NapalmShock initializer init
//######################################################################################################
globals
//**********************
//* Config
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//*
public constant integer abilityID = 'A62A'
//*
//*
//******************************************************************************************************
endglobals
//######################################################################################################
public function init takes nothing returns nothing
endfunction
endscope
function Napalm_Shock_Conditions takes nothing returns boolean
return GetSpellAbilityId()=='A62A'
endfunction
function Napalm_Shock_Actions takes nothing returns nothing
local unit caster=GetTriggerUnit()
local unit target=GetSpellTargetUnit()
local unit lastcreated
local real x1=GetUnitX(caster)
local real y1=GetUnitY(caster)
local real x2=GetUnitX(target)
local real y2=GetUnitY(target)
local real x3
local real y3
local real damage=40+(GetUnitAbilityLevel(caster,'A62A')*15)
local integer index=1
local real dx=x2-x1
local real dy=y2-y1
local real distance=SquareRoot(dx*dx+dy*dy)/100
local real angle=bj_RADTODEG*Atan2(y2-y1,x2-x1)
local real e_distance=0.00
call UnitDamageTarget(caster,target,damage,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Other\\Volcano\\VolcanoDeath.mdl",x1,y1))
loop
exitwhen index>R2I(distance)
set x3=x1+(e_distance+100)*Cos(angle*bj_DEGTORAD)
set y3=y1+(e_distance+100)*Sin(angle*bj_DEGTORAD)
set lastcreated=CreateUnit(GetOwningPlayer(caster),'n61G',x3,y3,angle)
set e_distance=e_distance+100
call UnitApplyTimedLife(lastcreated,'BTLF',0.2)
set index=index+1
endloop
set lastcreated=CreateUnit(GetOwningPlayer(caster),'n61E',x2,y2,angle)
call UnitApplyTimedLife(lastcreated,'BTLF',3)
call UnitAddAbility(lastcreated,'A629')
call SetUnitAbilityLevel(lastcreated,'A629',GetUnitAbilityLevel(caster,'A62A'))
call IssueTargetOrder(lastcreated,"shadowstrike",target)
set caster=null
set target=null
set lastcreated=null
set e_distance=0.00
endfunction
//===========================================================================
constant function ISNS takes nothing returns boolean
return true
endfunction
function InitTrig_Napalm_Shock takes nothing returns nothing
local trigger T=CreateTrigger()
local integer TI=0
local filterfunc FF=Filter(function ISNS)
loop
exitwhen (TI>=bj_MAX_PLAYER_SLOTS)
call TriggerRegisterPlayerUnitEvent(T,Player(TI),EVENT_PLAYER_UNIT_SPELL_EFFECT,FF)
set TI=TI+1
endloop
call DestroyBoolExpr(FF)
call TriggerAddAction(T,function Napalm_Shock_Actions)
call TriggerAddCondition(T,Condition(function Napalm_Shock_Conditions))
set FF=null
set T=null
endfunction
7) Frost Nova
Problem: The skills effect doesn't show properly and doesn't affect enemy units.
JASS:
scope FrostNova initializer init
native UnitAlive takes unit u returns boolean
//######################################################################################################
globals
//**************************
//* Config
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//*
public constant integer abilityID = 'A62S'
public constant integer dummyID = 'dumm'
//*
public constant integer novaFrostID = 'A62F'
public constant integer novaEnsnareID = 'A627'
public constant integer novaFXAbilID = 'A628'
public constant integer novaFXUnitID = 'h612'
//*
public constant string novaFrostOrder = "frostnova"
public constant string novaEnsnareOrder = "ensnare"
public constant string novaFXAbilOrder = "breathoffrost"
//*
public constant string novaFXPath = "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl"
//*
public real array areaRadius
//*
//* Temp Data
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
private group TEMP__enum = CreateGroup()
private boolexpr TEMP__enumfilter = null
private unit TEMP__dummy = null
//*
//*
//******************************************************************************************************
endglobals
//######################################################################################################
private struct nova
public unit caster = null
public integer level
private static thistype TEMP__data
private static method freezeAreaFilter takes nothing returns boolean
local unit filt = GetFilterUnit( )
local boolean result = IsUnitEnemy(filt, GetOwningPlayer(TEMP__data.caster)) and /*
*/ not IsUnitType(filt, UNIT_TYPE_STRUCTURE) and /*
*/ UnitAlive(filt)
if result then
call ShowUnit(TEMP__dummy, true)
call SetUnitX(TEMP__dummy, GetUnitX(filt))
call SetUnitY(TEMP__dummy, GetUnitY(filt))
call SetUnitOwner(TEMP__dummy, GetOwningPlayer(TEMP__data.caster), false)
call SetUnitAbilityLevel(TEMP__dummy, novaFrostID, TEMP__data.level+1)
call SetUnitAbilityLevel(TEMP__dummy, novaEnsnareID, TEMP__data.level+1)
call IssueTargetOrder(TEMP__dummy, novaFrostOrder, filt)
call IssueTargetOrder(TEMP__dummy, novaEnsnareOrder, filt)
call ShowUnit(TEMP__dummy, false)
endif
set filt = null
return false
endmethod
//--------------------------------------------------------------------------------------------------
// freezeArea() -> the freeze area method is used to enumerate nearby enemy targets that have been
// validated and perform a set of operations to inflict the effects of the spell.
//--------------------------------------------------------------------------------------------------
method freezeArea takes nothing returns nothing
local integer i
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local real x2
local real y2
local unit u = CreateUnit(Player(15), novaFXUnitID, x, y, 270)
call SetUnitTimeScale(u, 0.25)
call KillUnit(u)
set u = null
call SetUnitX(TEMP__dummy, x)
call SetUnitY(TEMP__dummy, y)
set i = 0
loop
exitwhen i == 20
set x2 = x + 600*Cos(i*(bj_PI)/8)
set y2 = y + 600*Sin(i*(bj_PI)/8)
call IssuePointOrder(TEMP__dummy, novaFXAbilOrder, x2, y2)
set i = i + 1
endloop
set thistype.TEMP__data = this
call GroupEnumUnitsInRange(TEMP__enum, GetUnitX(caster), GetUnitY(caster), areaRadius[level], /*
*/ TEMP__enumfilter)
endmethod
private static method onInit takes nothing returns nothing
set TEMP__enumfilter = Filter(function thistype.freezeAreaFilter)
endmethod
endstruct
//######################################################################################################
public function typeidfilter takes nothing returns boolean
return GetSpellAbilityId( )==abilityID
endfunction
public function runfunc takes nothing returns nothing
local nova n = nova.create()
set n.caster = GetTriggerUnit()
set n.level = GetUnitAbilityLevel(n.caster, abilityID)
call n.freezeArea( )
call n.destroy( )
endfunction
//######################################################################################################
public function init takes nothing returns nothing
local trigger t=CreateSpellTrigger(null)
call TriggerAddCondition(t, Filter(function typeidfilter))
call TriggerAddAction(t, function runfunc)
set t=null
set TEMP__dummy = CreateUnit(Player(12), dummyID, 0, 0, 0) // add the necessary abilities to the
call UnitAddAbility(TEMP__dummy, novaFrostID) // dummy on initialization; they are
call UnitAddAbility(TEMP__dummy, novaEnsnareID) // modified at run-time.
call UnitAddAbility(TEMP__dummy, novaFXAbilID)
call UnitRemoveAbility(TEMP__dummy, 'Amov')
call ShowUnit(TEMP__dummy, false)
//--------------------------------------------------------------------------------------------------
set areaRadius[0] = 550
set areaRadius[1] = 550
set areaRadius[2] = 550
//--------------------------------------------------------------------------------------------------
endfunction
endscope
8) Phoenix Spirit
Problem: This skills work fine. But for some unknown reason, it applied regeneration aura to enemy unit for a couple of seconds.
JASS:
library PhoenixSpirit initializer Init requires SpellIndexer
private struct dat
static constant integer MAIN_SPELL = 'A62G'
static constant integer SUB_SPELL = 'A62K'
static constant integer BIRDS_SPELL = 'A62M'
static constant integer BIRD_ID = 'h610'
static constant integer SUB_ID = 'n61M'
static integer total = 0
static thistype index = 0
static integer mark = 0
static integer runningTot = 0
static timer loopTimer = CreateTimer()
static group safeGroup = CreateGroup()
static group birdGroup = CreateGroup()
static real radius = 0.
static unit trgUnit = null
static unit array birds
static boolean array actBird
player owner = null
integer level = 0
unit hero = null
unit bird = null
static method birdTravel takes nothing returns nothing
local unit u= GetEnumUnit()
local real x= GetUnitX(u)
local real y= GetUnitY(u)
if GetUnitCurrentOrder(u)!=OrderId("selfdestruct") then
call IssuePointOrder(u,"selfdestruct",x,y)
call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\NightElf\\NEDeathSmall\\NEDeathSmall.mdl",x,y))
endif
set u= null
endmethod
static method RandomFilt takes nothing returns boolean
local unit u= GetFilterUnit()
if GetRandomInt(0,bj_groupRandomConsidered)==0 and not IsUnitType(u, UNIT_TYPE_STRUCTURE) and GetWidgetLife(u) > 0. and IsUnitEnemy(u,bj_groupEnumOwningPlayer) and not IsUnitInGroup(u, .safeGroup) then
set bj_groupRandomCurrentPick= u
set bj_groupRandomConsidered= bj_groupRandomConsidered +1
endif
set u= null
return false
endmethod
static method onLoop takes nothing returns nothing
local thistype this= .index
local integer i= 0
local integer j= 0
local unit u
local real array a
if .radius >= 358. then
set .radius = 0.
else
set .radius = .radius + 2.
endif
call ForGroup(.birdGroup,function thistype.birdTravel)
loop
if .hero != null then
set a[0]= GetUnitX(.hero)
set a[1]= GetUnitY(.hero)
loop
set u= .birds[this *5 +i]
if .actBird[this *5 +i] then
set a[4]= 72. *i -.radius
set a[2]= a[0] +200. *Cos(a[4] *bj_DEGTORAD)
set a[3]= a[1] +200. *Sin(a[4] *bj_DEGTORAD)
call SetUnitX(u,a[2])
call SetUnitY(u,a[3])
call SetUnitFacing(u,bj_RADTODEG *Atan2(a[3] -a[1],a[2] -a[0]) -90.)
set bj_groupEnumOwningPlayer= .owner
set bj_groupRandomConsidered= 0
call GroupEnumUnitsInRange(bj_lastCreatedGroup,a[2],a[3],400.,Filter(function thistype.RandomFilt))
if bj_groupRandomConsidered>0 and GetUnitAbilityLevel(.hero, 'B619')>0 then
call GroupAddUnit(.safeGroup,bj_groupRandomCurrentPick)
set .actBird[this *5 +i]= false
call GroupAddUnit(.birdGroup,u)
call IssueTargetOrder(u,"selfdestruct",bj_groupRandomCurrentPick)
call SetUnitAbilityLevel(u,.BIRDS_SPELL,4)
call SetUnitAbilityLevel(u,.SUB_SPELL,.level)
endif
else
set j = j +1
endif
exitwhen i==4
set i = i + 1
endloop
if j==5 then
call UnitRemoveAbility(.hero,'B619')
set .hero= null
endif
set i= 0
set j= 0
endif
exitwhen this==1
set this= this -1
endloop
endmethod
static method onDeathEval takes nothing returns boolean
local unit u
local integer id= GetUnitTypeId(GetTriggerUnit())
if id==.BIRD_ID or id==.SUB_ID then
set u= GetTriggerUnit()
if id==.BIRD_ID then
set .runningTot= .runningTot +1
if .runningTot==5 then
set .runningTot= 0
set .total= .total -1
if .total==0 then
call PauseTimer(.loopTimer)
set .index= 0
endif
endif
call GroupRemoveUnit(birdGroup,u)
endif
call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\NightElf\\EntBirthTarget\\EntBirthTarget.mdl",GetUnitX(u),GetUnitY(u)))
call RemoveUnit(u)
set u= null
endif
return false
endmethod
static method SecondSpellFilter takes nothing returns boolean
local integer i= GetRandomInt(0,2)
local unit u= GetFilterUnit()
local unit d
if GetWidgetLife(u)>0. and IsUnitEnemy(u,bj_groupEnumOwningPlayer) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\GreenDragonMissile\\GreenDragonMissile.mdl",u,"chest"))
call UnitDamageTarget(.trgUnit,u,15. *bj_randDistCount,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
set d= CreateUnit(bj_groupEnumOwningPlayer,SUB_ID,GetUnitX(u),GetUnitY(u),270.)
call UnitApplyTimedLife(d,'BTLF',GetRandomReal(0.8,1.2))
if i==0 then
call SetUnitAbilityLevel(d,'A62H',bj_groupEnumTypeId)
call IssueTargetOrder(d,"curse",u)
elseif i==1 then
call SetUnitAbilityLevel(d,'A62L',bj_groupEnumTypeId)
call IssueTargetOrder(d,"acidbomb",u)
else
call SetUnitAbilityLevel(d,'A62N',bj_groupEnumTypeId)
call IssueTargetOrder(d,"cripple",u)
endif
set d= null
endif
return false
endmethod
static method subActions takes nothing returns nothing
call GroupRemoveUnit(.safeGroup,GetSpellTargetUnit())
set .trgUnit= GetTriggerUnit()
set bj_groupEnumOwningPlayer= GetTriggerPlayer()
set bj_groupEnumTypeId= GetUnitAbilityLevel(.trgUnit,.SUB_SPELL)
set bj_randDistCount= GetUnitAbilityLevel(.trgUnit,'A002')
call GroupEnumUnitsInRange(bj_lastCreatedGroup,GetUnitX(.trgUnit),GetUnitY(.trgUnit),200.,Filter(function thistype.SecondSpellFilter))
endmethod
static method Actions takes unit u returns nothing
local integer i= 0
local real x1= GetUnitX(u)
local real y1= GetUnitY(u)
local real x
local real y
if .total==0 then
call TimerStart(.loopTimer,0.02,true,function thistype.onLoop)
endif
set .total= .total +1
set .index= .index +1
set .index.hero= u
set .index.owner= GetTriggerPlayer()
set .index.level= GetUnitAbilityLevel(u,.MAIN_SPELL)
loop
set x= x1 +200. *Cos(72. *i *bj_DEGTORAD)
set y= y1 +200. *Sin(72. *i *bj_DEGTORAD)
set .birds[.index *5 +i]= CreateUnit(.index.owner,.BIRD_ID,x,y,72. *i +90.)
set .actBird[.index *5 +i]= true
call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\NightElf\\EntBirthTarget\\EntBirthTarget.mdl",x,y))
call SetUnitAbilityLevel(.birds[.index *5 +i],.BIRDS_SPELL,.index.level)
exitwhen i==4
set i= i +1
endloop
endmethod
static method Conditions takes nothing returns boolean
if GetSpellAbilityId() == .MAIN_SPELL then
call .Actions(GetTriggerUnit())
elseif GetSpellAbilityId() == .SUB_SPELL then
call .subActions()
endif
return false
endmethod
endstruct
//*
//* Main Initialization
//* ============================================================================
private function Init takes nothing returns nothing
local trigger t= CreateTrigger()
call TriggerAddCondition(t,Condition(function dat.onDeathEval))
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
call CreateSpellTrigger(function dat.Conditions)
endfunction
//*
//*
//*
endlibrary
I even provide the map for you to test it, so you can know pretty much whats the problem all about.