- Joined
- Jun 7, 2007
- Messages
- 196
First this works ok, but it starts to lag after some casts so there seems to be leaks, can someone point them out?
Also is there a way to make it run more smoothly with more projectiles flying at a time without using structs?
(I know it targets dead units atm. forgot to add that to the filter list.)
Bouncing Projectile
Also is there a way to make it run more smoothly with more projectiles flying at a time without using structs?
(I know it targets dead units atm. forgot to add that to the filter list.)
Bouncing Projectile
JASS:
//===========================================================================
library Common initializer Init
//===========================================================================
globals
boolexpr noFilter
real PlayableAreaMinX
real PlayableAreaMaxX
real PlayableAreaMinY
real PlayableAreaMaxY
endglobals
//===========================================================================
function ReturnTrue takes nothing returns boolean
return true
endfunction
//===========================================================================
private function Init takes nothing returns nothing
set noFilter = Condition(function ReturnTrue)
set PlayableAreaMinX = GetRectMinX(bj_mapInitialPlayableArea)
set PlayableAreaMaxX = GetRectMaxX(bj_mapInitialPlayableArea)
set PlayableAreaMinY = GetRectMinY(bj_mapInitialPlayableArea)
set PlayableAreaMaxY = GetRectMaxY(bj_mapInitialPlayableArea)
endfunction
//===========================================================================
function PolarProjectionX takes real x, real dist, real angle returns real
return ( x + ( dist * Cos( angle * bj_DEGTORAD ) ) )
endfunction
//===========================================================================
function PolarProjectionY takes real y, real dist, real angle returns real
return ( y + ( dist * Sin( angle * bj_DEGTORAD ) ) )
endfunction
//===========================================================================
function DistanceBetweenCoordinates takes real x1, real y1, real x2, real y2 returns real
return ( SquareRoot( ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ) ) )
endfunction
//===========================================================================
function AngleBetweenCoordinates takes real x1, real y1, real x2, real y2 returns real
return ( bj_RADTODEG * Atan2(y2 - y1, x2 - x1) )
endfunction
//===========================================================================
function FixAngle takes real angle returns real
if (angle < 0) then
return 180 + ( 180 - angle * -1 )
endif
return angle
endfunction
//===========================================================================
function CopyGroup takes group g returns group
set bj_groupAddGroupDest=CreateGroup()
call ForGroup(g, function GroupAddGroupEnum)
return bj_groupAddGroupDest
endfunction
//===========================================================================
endlibrary
//===========================================================================
//===========================================================================
library BouncingProjectile initializer Init requires Common
//===========================================================================
globals
private hashtable HASH = InitHashtable()
private group GROUP = CreateGroup()
private timer TIMER = CreateTimer()
private constant string EFFECT_PATH = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl"
endglobals
//===========================================================================
function FilterFunc takes unit u, unit u2 returns boolean
return (GetUnitTypeId(u2) != 'udum') and (IsUnitEnemy(u2, GetOwningPlayer(u))) and (not(IsUnitType(u2, UNIT_TYPE_FLYING)))
endfunction
//===========================================================================
function Loop takes nothing returns nothing
local unit u
local unit u2
local unit caster
local boolean bounceX
local boolean bounceY
local integer cliff
local integer lifespan
local real x
local real y
local real x2
local real y2
local real angle
local real speed
local group g = CopyGroup(GROUP)
local group g2
loop
set u = FirstOfGroup(g)
exitwhen (u == null)
call GroupRemoveUnit(g, u)
set x = GetUnitX(u)
set y = GetUnitY(u)
set caster = LoadUnitHandle(HASH, StringHash("Caster"), GetHandleId(u))
set cliff = LoadInteger(HASH, StringHash("Cliff"), GetHandleId(u))
set lifespan = LoadInteger(HASH, StringHash("Lifespan"), GetHandleId(u))
set angle = LoadReal(HASH, StringHash("Angle"), GetHandleId(u))
set speed = LoadReal(HASH, StringHash("Speed"), GetHandleId(u))
set bounceX = false
set bounceY = false
set x2 = PolarProjectionX(x, speed, angle)
set y2 = PolarProjectionY(y, speed, angle)
if (GetTerrainCliffLevel(x2, y) > cliff) or (x2 <= PlayableAreaMinX) or (x2 >= PlayableAreaMaxX) then
set bounceX = true
endif
if (GetTerrainCliffLevel(x, y2) > cliff) or (y2 <= PlayableAreaMinY) or (y2 >= PlayableAreaMaxY) then
set bounceY = true
endif
if (bounceX) or (bounceY) then
if (bounceX) and (bounceY) then
set angle = 180 + angle
elseif (bounceX) then
set angle = 180 + ( 360 - angle )
else
set angle = 360 - angle
endif
set x2 = PolarProjectionX(x, speed, angle)
set y2 = PolarProjectionY(y, speed, angle)
endif
call SaveReal(HASH, StringHash("Angle"), GetHandleId(u), angle)
call SaveInteger(HASH, StringHash("Cliff"), GetHandleId(u), GetTerrainCliffLevel(x2, y2))
call SetUnitPosition(u, x2, y2)
set g2 = CreateGroup()
call GroupEnumUnitsInRange(g2, x2, y2, 100.000, noFilter)
loop
set u2 = FirstOfGroup(g2)
exitwhen (u2 == null)
call GroupRemoveUnit(g2, u2)
if (FilterFunc(u, u2)) then
call DestroyEffect(AddSpecialEffectTarget(EFFECT_PATH, u2, "origin"))
call UnitDamageTarget(caster, u2, 10.000, false, true, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
endif
endloop
call DestroyGroup(g2)
set g2 = null
call SaveInteger(HASH, StringHash("Lifespan"), GetHandleId(u), lifespan - 1)
if (lifespan <= 0) then
call FlushChildHashtable(HASH, GetHandleId(u))
call KillUnit(u)
call GroupRemoveUnit(GROUP, u)
if (FirstOfGroup(GROUP) == null) then
call PauseTimer(TIMER)
endif
endif
set u = null
set caster = null
endloop
call DestroyGroup(g)
set g = null
endfunction
//===========================================================================
function Start takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit u2
local player pl = GetOwningPlayer(u)
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real x2 = GetSpellTargetX()
local real y2 = GetSpellTargetY()
local real angle = FixAngle( AngleBetweenCoordinates(x, y, x2, y2) )
if (GetSpellAbilityId() == 'A000') then
set x2 = PolarProjectionX(x, 50, angle)
set y2 = PolarProjectionY(y, 50, angle)
set u2 = CreateUnit(pl, 'udum', x2, y2, angle)
call SaveUnitHandle(HASH, StringHash("Caster"), GetHandleId(u2), u)
call SaveInteger(HASH, StringHash("Cliff"), GetHandleId(u2), GetTerrainCliffLevel(x2, y2))
call SaveInteger(HASH, StringHash("Lifespan"), GetHandleId(u2), 250)
call SaveReal(HASH, StringHash("Angle"), GetHandleId(u2), angle)
call SaveReal(HASH, StringHash("Speed"), GetHandleId(u2), 25.000)
if (FirstOfGroup(GROUP) == null) then
call TimerStart(TIMER, 0.05, true, function Loop)
endif
call GroupAddUnit(GROUP, u2)
endif
set u = null
set u2 = null
set pl = null
endfunction
//===========================================================================
function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction( t, function Start)
set t = null
endfunction
//===========================================================================
endlibrary
//===========================================================================