- Joined
- Apr 15, 2011
- Messages
- 123
Hello,
I've finished my first (v)Jass spell and as I'm not that experienced, I'd be glad, if someone could help me, otzimize the code. Thanks (in advance, hopefully)
I've finished my first (v)Jass spell and as I'm not that experienced, I'd be glad, if someone could help me, otzimize the code. Thanks (in advance, hopefully)
Creates a missile, that is attracted by enemy units around it
JASS:
scope SpellHeatSeekingMissile initializer init
globals
private constant real InitialOffset = 100 //the missile's distance from the caster, when summoned
private constant real InitialFlyHeight = 80 //the missile's flying height, when summoned
private constant real InitialSpeed = 30 //the missile's speed, when summoned; in units per 0.03 seconds
private constant real DetectionRadius = 1000 //the radius in which the missile gets attracted by units
private constant real ExpirationRadius = 50 //the radius in which the missile detects uni
private constant real ExplosionRadius = 150 //the radius in which the damage is dealt, when the missile explodes
private constant real Attraction = 200 //this value determines how much the missile is attracted by other units
private constant real Damage = 250 //damage dealt by the missile
private constant real Size = ExplosionRadius / 150 // the visual explosion size
private constant integer OffsetX = 0
private constant integer OffsetY = 1
private constant integer Effect = 2
private constant hashtable hash = InitHashtable()
//--------------------------------------------------\\
private real minX = 0
private real maxX = 0
private real minY = 0
private real maxY = 0
private group Missiles = CreateGroup()
private unit tempUnit
endglobals
private function EnumFilter takes nothing returns boolean
local unit u = GetFilterUnit()
//--------------------------------------------------\\
return GetUnitTypeId(u) != 'n001' and GetUnitState(u, UNIT_STATE_LIFE) > 0 and IsUnitEnemy(u, GetOwningPlayer(tempUnit))
endfunction
private function Cond takes nothing returns boolean
return GetSpellAbilityId() == 'A000'
endfunction
private function Death takes unit u1, real x, real y returns nothing
local effect e = LoadEffectHandle(hash, GetHandleId(u1), Effect)
local unit u2
local group g = CreateGroup()
//--------------------------------------------------\\
call KillUnit(u1)
call DestroyEffect(e)
call SetUnitScale(u1, Size, Size, Size)
call GroupRemoveUnit(Missiles, u1)
call GroupEnumUnitsInRange(g, x, y, ExplosionRadius, function EnumFilter)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
call GroupRemoveUnit(g, u2)
call UnitDamageTarget(u1, u2, Damage, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_FIRE, null)
endloop
call DestroyGroup(g)
set e = null
set g = null
set u1 = null
set u2 = null
endfunction
private function Movement takes nothing returns nothing
local unit u1
local unit u2
local group g1 = CreateGroup()
local group g2
local real x1
local real x2
local real x3
local real y1
local real y2
local real y3
local real ox
local real oy
local real difx
local real dify
local integer id
local boolean explode
//--------------------------------------------------\\
call GroupAddGroup(Missiles, g1)
loop
set u1 = FirstOfGroup(g1)
exitwhen u1 == null
call GroupRemoveUnit(g1, u1)
set id = GetHandleId(u1)
set x1 = GetUnitX(u1)
set y1 = GetUnitY(u1)
set ox = LoadReal(hash, id, OffsetX)
set oy = LoadReal(hash, id, OffsetY)
set tempUnit = u1
set g2 = CreateGroup()
call GroupEnumUnitsInRange(g2, x1, y1, DetectionRadius, function EnumFilter)
loop
set u2 = FirstOfGroup(g2)
exitwhen u2 == null
call GroupRemoveUnit(g2, u2)
set x2 = GetUnitX(u2)
set y2 = GetUnitY(u2)
set difx = x2 - x1
set dify = y2 - y1
if (difx > 5 or difx < -5) and (dify > 5 or dify < -5) then
set ox = ox + (((x2 - x1) * Attraction) / (Pow(x2 - x1, 2) + Pow(y2 - y1, 2)))
set oy = oy + (((y2 - y1) * Attraction) / (Pow(x2 - x1, 2) + Pow(y2 - y1, 2)))
endif
set u2 = null
endloop
call DestroyGroup(g2)
set g2 = null
set x3 = x1 + ox
set y3 = y1 + oy
set explode = false
if minX <= x3 and x3 <= maxX and minY <= y3 and y3 <= maxY then
set g2 = CreateGroup()
call GroupEnumUnitsInRange(g2, x1, y1, ExpirationRadius, function EnumFilter)
loop
set u2 = FirstOfGroup(g2)
exitwhen u2 == null
set explode = true
exitwhen explode == true
endloop
//I might have to do a rectangle detection here as well. When the missile gets too fast it just skips units :S
call DestroyGroup(g2)
set g2 = null
if explode == false then
call SetUnitFacing(u1, Atan2(oy, ox) * bj_RADTODEG)
call SetUnitX(u1, x3)
call SetUnitY(u1, y3)
call SaveReal(hash, id, OffsetX, ox)
call SaveReal(hash, id, OffsetY, oy)
else
call Death(u1, x1, y1)
endif
else
call Death(u1, x1, y1)
endif
set u1 = null
endloop
call DestroyGroup(g1)
set g1 = null
endfunction
private function Cast takes nothing returns nothing
local unit u1 = GetTriggerUnit()
local real r = Atan2(GetSpellTargetY() - GetUnitY(u1), GetSpellTargetX() - GetUnitX(u1))
local unit u2 = CreateUnit(GetTriggerPlayer(), 'n001', GetUnitX(u1) + (InitialOffset * Cos(r)), GetUnitY(u1) + (InitialOffset * Sin(r)), r * bj_RADTODEG)
local integer id = GetHandleId(u2)
//--------------------------------------------------\\
call SetUnitFlyHeight(u2, InitialFlyHeight, 0)
call SetUnitScale(u2, 2, 2, 2)
call GroupAddUnit(Missiles, u2)
call SaveReal(hash, id, OffsetX, InitialSpeed * Cos(r))
call SaveReal(hash, id, OffsetY, InitialSpeed * Sin(r))
call SaveEffectHandle(hash, id, Effect, AddSpecialEffectTarget("Rocket.mdx", u2, "head"))
set u1 = null
set u2 = null
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local timer tmr = CreateTimer()
//--------------------------------------------------\\
set minX = GetRectMinX(bj_mapInitialPlayableArea) //I had some problems here.
set maxX = GetRectMaxX(bj_mapInitialPlayableArea) //It seemed to me like
set minY = GetRectMinY(bj_mapInitialPlayableArea) //bj_mapInitialPlayableArea
set maxY = GetRectMaxY(bj_mapInitialPlayableArea) //is null at map initialization :S
//--------------------------------------------------\\
call TimerStart(tmr, 0.03, true, function Movement)
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, function Cond)
call TriggerAddAction(t, function Cast)
set t = null
set tmr = null
endfunction
endscope
Last edited: