GrapesOfWath
Sound Reviewer
- Joined
- Mar 31, 2012
- Messages
- 281
Hi guys. Another dev on a map of mine re-created a spell from hive to make it more lightweight. The spell is an AoE ground target spell that basically creates a black hole that damages units and pulls them towards the middle. The spell works great, but it's bugged to where if a unit gets hit by it and survives, that unit is likely to just start spinning randomly later on in the game. This seems to mainly happen if the unit is in a tight space and is trying to leave said tight space. Here's the script:
what do I do here? thanks in advance
JASS:
scope SpellSucc
globals
private constant integer voidPortalMaxIndex = 10
private constant integer ID = 'Avpt'
private constant string MODEL = "war3mapImported\\Void Rift II Orange.mdx"
private constant real DURATION = 5.00
private constant real TICKRATE = 0.03
private constant real DAMAGE = 100
private constant real AOE = 350
private constant real VELOCITY_CENTER = 40
private constant real VELOCITY_ROTATION = 275
private constant boolean CHECK_PATHING = false
private constant boolean ALWAYS_PULL_CENTER = true
private constant boolean PAUSE_UNITS = false
private constant boolean DISABLE_MOVEMENT = true
private constant boolean MOVE_DEAD_UNITS = false
private constant boolean DELETE_CORPSES = false
private constant real CORPSE_DELETE_RADIUS = 100.00
endglobals
private struct VoidPortal
static integer currentIndex = 0
static VoidPortal array all
integer index
unit caster
group affectedUnits = CreateGroup()
location targetLoc
effect sfx
real timerDuration
static method GetIndex takes nothing returns integer
local integer i
if VoidPortal.currentIndex >= voidPortalMaxIndex then
set VoidPortal.currentIndex = 1
set i = 0
else
set i = VoidPortal.currentIndex
set VoidPortal.currentIndex = VoidPortal.currentIndex + 1
endif
return i
endmethod
static method create takes nothing returns VoidPortal
local VoidPortal t = VoidPortal.allocate()
set t.index = GetIndex()
set VoidPortal.all[t.index] = t
return t
endmethod
method destroy takes nothing returns nothing
local unit u
loop
set u = FirstOfGroup(this.affectedUnits)
exitwhen u == null
if DISABLE_MOVEMENT then
call SetUnitPropWindow(u,GetUnitDefaultPropWindow(u))
call SetUnitMoveSpeed(u,GetUnitDefaultMoveSpeed(u))
endif
if PAUSE_UNITS then
call PauseUnit(u,false)
endif
call GroupRemoveUnit(this.affectedUnits,u)
endloop
call DestroyGroup(this.affectedUnits)
set this.affectedUnits = null
call RemoveLocation(targetLoc)
set targetLoc = null
set caster = null
call DestroyEffect(sfx)
set sfx = null
set VoidPortal.all[index] = 0
set u = null
call this.deallocate()
endmethod
endstruct
private function CheckUnitConditions takes unit filter, VoidPortal t returns boolean
local location locFilter = GetUnitLoc(filter)
local boolean isEnemy = IsUnitEnemy(filter, GetOwningPlayer(t.caster))
local boolean isNotMagicImmune = not IsUnitType(filter,UNIT_TYPE_MAGIC_IMMUNE)
local boolean isNotAsh = not IsUnitType(filter,UNIT_TYPE_SAPPER)
if GetUnitTypeId(filter) == 'e008' then
set filter = null
return false
endif
call RemoveLocation(locFilter)
set locFilter = null
if isEnemy and isNotMagicImmune and isNotAsh and (GetUnitState(filter, UNIT_STATE_LIFE) > 0.405 or MOVE_DEAD_UNITS) and not BlzIsUnitInvulnerable(filter) then
set filter = null
return true
else
set filter = null
return false
endif
return filter != t.caster
endfunction
private function MovementLoop takes VoidPortal t returns nothing
local group unitsInRange = CreateGroup()
local group unitsInRangeAll = CreateGroup()
local unit f
local location locEnum
local real angle //angle to center
local real angle2 //angle to center -90, clockwise rotation
local real destx
local real desty
if t.timerDuration <= 0 then
call t.destroy()
else
set unitsInRangeAll = GetUnitsInRangeOfLocAll(AOE,t.targetLoc)
loop
set f = FirstOfGroup(unitsInRangeAll)
exitwhen (f == null)
if CheckUnitConditions(f,t) then
call GroupAddUnit(unitsInRange,f)
endif
call GroupRemoveUnit(unitsInRangeAll,f)
endloop
set f = null
loop
set f = FirstOfGroup(unitsInRange)
exitwhen (f == null)
call GroupRemoveUnit(unitsInRange,f)
//move units
set locEnum = GetUnitLoc(f)
call UnitDamageTarget(t.caster, f, (DAMAGE * TICKRATE * GetUnitAbilityLevel(t.caster,ID))/DURATION,true,true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_DEATH,WEAPON_TYPE_WHOKNOWS)
if DELETE_CORPSES and DistanceBetweenPoints(t.targetLoc, locEnum) < CORPSE_DELETE_RADIUS and IsUnitDeadBJ(f) then
call RemoveUnit(f)
endif
set angle = AngleBetweenPoints(locEnum, t.targetLoc)
set angle2 = angle+90
if angle2 > 360 then
set angle2 = angle2 - 360
endif
set destx = (GetUnitX(f) + (TICKRATE * VELOCITY_CENTER) * Cos(angle * bj_DEGTORAD))
set desty = (GetUnitY(f) + (TICKRATE * VELOCITY_CENTER) * Sin(angle * bj_DEGTORAD))
set destx = (destx + (TICKRATE * VELOCITY_ROTATION) * Cos(angle2 * bj_DEGTORAD))
set desty = (desty + (TICKRATE * VELOCITY_ROTATION) * Sin(angle2 * bj_DEGTORAD))
//dont move these units
if (not (IsUnitType(f, UNIT_TYPE_STRUCTURE)) or not (IsUnitType(f, UNIT_TYPE_ANCIENT))) then
if DISABLE_MOVEMENT then
call SetUnitFacing(f,angle)
call SetUnitPropWindow(f, 0)
endif
if PAUSE_UNITS then
call PauseUnit(f, true)
endif
call GroupAddUnit(t.affectedUnits,f)
if CHECK_PATHING then
if IsTerrainWalkable(destx,desty) or IsUnitDeadBJ(f) then
call SetUnitX(f,destx)
call SetUnitY(f,desty)
elseif ALWAYS_PULL_CENTER then
call SetUnitX(f,GetUnitX(f) + (TICKRATE * VELOCITY_CENTER) * Cos(angle * bj_DEGTORAD))
call SetUnitY(f,GetUnitY(f) + (TICKRATE * VELOCITY_CENTER) * Sin(angle * bj_DEGTORAD))
endif
else
call SetUnitX(f,destx)
call SetUnitY(f,desty)
endif
endif
call RemoveLocation(locEnum)
set locEnum = null
endloop
call DestroyGroup(unitsInRange)
set unitsInRange = null
call DestroyGroup(unitsInRangeAll)
set unitsInRangeAll = null
set t.timerDuration = t.timerDuration - TICKRATE
endif
endfunction
private function isSpellID takes nothing returns boolean
return GetSpellAbilityId() == ID
endfunction
private function timerExpired takes nothing returns nothing
local integer i = 0
loop
exitwhen i == voidPortalMaxIndex
if (VoidPortal.all[i] != 0) then
call MovementLoop(VoidPortal.all[i])
endif
set i = i+1
endloop
endfunction
function KillTrees takes nothing returns nothing
if ( GetDestructableTypeId(GetEnumDestructable()) == 'ATtr' ) then
call KillDestructable( GetEnumDestructable())
endif
endfunction
private function SuccActions takes nothing returns nothing
local VoidPortal t = VoidPortal.create()
set t.caster = GetTriggerUnit()
set t.targetLoc = GetSpellTargetLoc()
set t.timerDuration = DURATION
set t.sfx = AddSpecialEffectLocBJ(t.targetLoc, MODEL)
call BlzSetSpecialEffectScale( t.sfx, 1.45 )
call BlzSetSpecialEffectHeight(t.sfx,GetLocationZ(t.targetLoc))
set udg_TmpPoint6 = GetSpellTargetLoc()
if ( GetUnitAbilityLevelSwapped(GetSpellAbilityId(), GetTriggerUnit()) >= 3 )then
call EnumDestructablesInCircleBJ( 350.00, udg_TmpPoint6, function KillTrees )
call RemoveLocation(udg_TmpPoint6)
endif
endfunction
//===========================================================================
function InitTrig_VoidPortal takes nothing returns nothing
local trigger t = CreateTrigger()
set gg_trg_VoidPortal = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ(gg_trg_VoidPortal,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(gg_trg_VoidPortal, Condition(function isSpellID))
call TriggerAddAction( gg_trg_VoidPortal, function SuccActions )
call TriggerRegisterTimerEvent(t,TICKRATE,true)
call TriggerAddAction(t,function timerExpired)
endfunction
endscope
what do I do here? thanks in advance