- Joined
- Sep 25, 2005
- Messages
- 71
Ahoy there. So, I've been trying to create a "shotgun" sort of effect basically that fires off a cone made of a relatively high count of semi-random arrows. Single casts are fine, but simultaneous counts lag hard. I was wondering if someone could recognize something that would cause this problem in my code? I mean, it's not a big deal ultimately since it functions, but lagging with multiple uses seems bad.
I've tried reducing the move interval (didn't change anything) and the actual arrow count (helps, but the problem still persists with enough simultaneous casts.
Am I just going to have to deal with never having a few "shotgun" effects on map/same screen to reduce the lag?
I've tried reducing the move interval (didn't change anything) and the actual arrow count (helps, but the problem still persists with enough simultaneous casts.
Am I just going to have to deal with never having a few "shotgun" effects on map/same screen to reduce the lag?
JASS:
scope Arrowblast initializer init
globals
private constant integer ABIL_ID = 'A00P'
private constant integer DUMMY_ID = 'o00A'
private constant integer ARROW_NUMBER = 20
private constant real ANGLE_VARIATION = 7.5
private constant real CAST_RANGE = 700.
private constant real COLLISION_SIZE = 94.
private constant real DAMAGE_AMOUNT = 5.
private constant real DAMAGE_PER_LEVEL = 0.
private constant real RANGE_VARIATION = 128.
private constant real MOVESPEED = 22.
private constant real MOVESPEED_RANDOM = 6.
private constant real MOVE_INTERVAL = 0.0125
private constant real ARROW_Z_DEFAULT = 56.
private constant real ARROW_Z_RANDOM = 38.
private constant string HIT_FX = "Objects\\Spawnmodels\\Critters\\Albatross\\CritterBloodAlbatross.mdl"
private constant string HIT_ATTACH_POINT = "chest"
endglobals
struct Arrowblast
unit Caster
unit array Arrow[ARROW_NUMBER]
real TargetX
real TargetY
real array Distance[ARROW_NUMBER]
real array MaxDist[ARROW_NUMBER]
real array ArrowZ[ARROW_NUMBER]
group array Hit[ARROW_NUMBER]
group ArrowEnum = CreateGroup()
timer Mover
integer ArrowsMaxed
private static method math takes real y2, real y1, real x2, real x1 returns real
local real output = bj_RADTODEG*Atan2(y2 - y1, x2 - x1)
return output
endmethod
private static method distancebetween takes real x2, real x1, real y2, real y1 returns real
local real x = x2 - x1
local real y = y2 - y1
return SquareRoot(x*x+y*y)
endmethod
private static method move takes unit u, real speed, real angle returns nothing
local real x
local real y
set x = GetUnitX(u) + speed * Cos(angle * bj_DEGTORAD)
set y = GetUnitY(u) + speed * Sin(angle * bj_DEGTORAD)
call SetUnitBoundedX(u, x)
call SetUnitBoundedY(u, y)
endmethod
private static method validtarget takes unit caster, unit enemy, real z, real collisionsize returns boolean
if IsUnitEnemy(enemy, GetOwningPlayer(caster)) == true /*
*/and GetWidgetLife(enemy) > 0.405 == true /*
*/and GetUnitFlyHeight(enemy) > z+collisionsize == false /*
*/and GetUnitFlyHeight(enemy) < z-collisionsize == false /*
*/and IsUnitType(enemy,UNIT_TYPE_MAGIC_IMMUNE) == false /*
*/and IsUnitType(enemy,UNIT_TYPE_STRUCTURE) == false /*
*/and IsUnitType(enemy, UNIT_TYPE_MECHANICAL) == false then
return true
endif
return false
endmethod
private static method arrowmove takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = LoadInteger(hash, 0, GetHandleId(t) )
local effect e
local location l
local unit u
local integer i = 0
local real randomdist
loop
exitwhen i == ARROW_NUMBER
set l = Location(GetUnitX(.Arrow[i]), GetUnitY(.Arrow[i]) )
if GetLocationZ(l) >= .ArrowZ[i] then
call KillUnit(.Arrow[i])
set .ArrowsMaxed = .ArrowsMaxed + 1
set .Arrow[i] = null
endif
if .Distance[i] >= .MaxDist[i] and .Arrow[i] != null then
call KillUnit(.Arrow[i])
set .ArrowsMaxed = .ArrowsMaxed + 1
set .Arrow[i] = null
else
set randomdist = GetRandomReal(-MOVESPEED_RANDOM,MOVESPEED_RANDOM)
call thistype.move(.Arrow[i], MOVESPEED+randomdist, GetUnitFacing(.Arrow[i]) )
call GroupEnumUnitsInRange(.ArrowEnum, GetUnitX(.Arrow[i]), GetUnitY(.Arrow[i]), COLLISION_SIZE, null)
loop
set u = FirstOfGroup(.ArrowEnum)
exitwhen u == null
if not IsUnitInGroup(u, .Hit[i]) and thistype.validtarget(.Caster, u, .ArrowZ[i], COLLISION_SIZE) and .Arrow[i] != null then
call UnitDamageTarget(.Caster, u, DAMAGE_AMOUNT + DAMAGE_PER_LEVEL * GetUnitAbilityLevel(.Caster, ABIL_ID), false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_FIRE, null)
call GroupAddUnit(.Hit[i], u)
set e = AddSpecialEffect(HIT_FX, GetUnitX(.Arrow[i]), GetUnitY(.Arrow[i]) )
call DestroyEffect(e)
call KillUnit(.Arrow[i])
set .ArrowsMaxed = .ArrowsMaxed + 1
set .Arrow[i] = null
endif
call GroupRemoveUnit(.ArrowEnum, u)
endloop
call SetUnitFlyHeight(.Arrow[i], .ArrowZ[i] - GetLocationZ(l), 0. )
set .Distance[i] = .Distance[i] + MOVESPEED+randomdist
endif
set i = i + 1
endloop
call RemoveLocation(l)
set t = null
set e = null
set l = null
set u = null
if .ArrowsMaxed == ARROW_NUMBER then
call .destroy()
endif
endmethod
static method create takes unit caster, real targetx, real targety returns Arrowblast
local thistype this = Arrowblast.allocate()
local player p
local location l
local integer i = 0
local real facing
set .Caster = caster
set .TargetX = targetx
set .TargetY = targety
set .Mover = CreateTimer()
set .ArrowsMaxed = 0
set p = GetOwningPlayer(.Caster)
loop
exitwhen i == ARROW_NUMBER
set .MaxDist[i] = thistype.distancebetween(.TargetX, GetUnitX(.Caster), .TargetY, GetUnitY(.Caster) ) + GetRandomReal(-RANGE_VARIATION, RANGE_VARIATION)
if .MaxDist[i] <= RANGE_VARIATION then
set .MaxDist[i] = .MaxDist[i]+2*RANGE_VARIATION
endif
set facing = this.math(.TargetY, GetUnitY(.Caster), .TargetX, GetUnitX(.Caster)) + GetRandomReal(-ANGLE_VARIATION, ANGLE_VARIATION) / (.MaxDist[i] / CAST_RANGE)
set .Arrow[i] = CreateUnit(p, DUMMY_ID, GetUnitX(.Caster), GetUnitY(.Caster), facing)
set .Distance[i] = 0.
set .ArrowZ[i] = ARROW_Z_DEFAULT + GetRandomReal(-ARROW_Z_RANDOM, ARROW_Z_RANDOM) + GetUnitFlyHeight(.Caster)
call UnitAddAbility(.Arrow[i], 'Amrf')
call UnitRemoveAbility(.Arrow[i], 'Amrf')
call SetUnitFlyHeight(.Arrow[i], .ArrowZ[i], 0.)
set i = i + 1
endloop
call SaveInteger(hash, 0, GetHandleId(.Mover), this)
call TimerStart(.Mover, MOVE_INTERVAL, true, function thistype.arrowmove)
set p = null
return this
endmethod
method onDestroy takes nothing returns nothing
local integer i = 0
loop
exitwhen i == 0
call DestroyGroup(.Hit[i])
set .Arrow[i] = null
set .Hit[i] = null
set i = i + 1
endloop
call DestroyTimer(.Mover)
call DestroyGroup(.ArrowEnum)
set .ArrowEnum = null
set .Caster = null
set .Mover = null
endmethod
endstruct
private function Arrowcheck takes nothing returns boolean
local location l = GetSpellTargetLoc()
local unit u = GetTriggerUnit()
if GetSpellAbilityId() == ABIL_ID then
call Arrowblast.create(u, GetLocationX(l), GetLocationY(l))
endif
call RemoveLocation(l)
set l = null
set u = null
return false
endfunction
private function init takes nothing returns nothing
local trigger LocalTrig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(LocalTrig, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(LocalTrig, Condition(function Arrowcheck))
set LocalTrig = null
endfunction
endscope