• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[JASS] Dammage units in range once per loop

Status
Not open for further replies.
Level 5
Joined
Sep 16, 2008
Messages
47
So
JASS:
                        set this.DG = CreateGroup()
                        set this.DG = CreateGroup()
                        set this.DG2 = CreateGroup()
                        call GroupEnumUnitsInRange(this.DG, this.DX, this.DY, DAMAGE_RANGE, null)
                            loop
                                set this.targets = FirstOfGroup(this.DG)
                                exitwhen this.targets == null
                                if IsUnitInGroup(this.targets, this.DG2) == false then
                                    call UnitDamageTarget(this.caster, this.targets, 25, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
                                    call GroupAddUnit(this.DG2, this.targets)
                                endif
                                call GroupRemoveUnit(this.DG, this.targets)
                            endloop
                        call BJDebugMsg(I2S(CountUnitsInGroup(this.DG2)))
                        set this.DG = null

Message shows me that there is a unit in this.DG2 group when it is in range. But when it isn't it says that there are no units in DG2 so units is not damaged once
 
Right now, this doesn't do anything.

DG and DG2 are both empty when they are created. When you enum over DG, all the units in DG will be distinct (in the end, DG2 will contain all the units that DG contained). So yes, it will deal damage to each unit only once, but in a haphazard way.

Could you explain your question a bit further, and perhaps show a bit more code? :)
 
Level 5
Joined
Sep 16, 2008
Messages
47
I don't rly care about leaks because i am always clearing all leaks after i complete spell :p

JASS:
scope Shockwaves
    globals
        private constant integer ABILITY_ID = 'A00D'
        private constant integer DUMMY_ID = 'h00A'
        private constant string MOVE_EFFECT = "Slam.mdx"
        private constant real EFFECT_CD = 0.15
        private constant real ANGLE_INC1 = - 10.00
        private constant real ANGLE_INC2 = 10.00
        private constant real MAX_ANGLE = 15.00
        private constant real MIN_ANGLE = 15.00
        private constant real DISTANCE = 1250.00
        private constant real SPEED = 20.00
        private constant real DAMAGE = 100.00
        private constant real DAMAGE_RANGE = 125.00
    endglobals
    
    globals
        private constant real FPS = 0.0312500
    endglobals
    
    function IsEnemy takes unit u, unit t returns boolean
        return IsUnitEnemy(t, GetOwningPlayer(u))
    endfunction
   
    private struct tempDat
        unit caster
        unit dummy
        unit targets
        real MaxDistance
        real Speed
        real DX
        real DY
        real CX
        real CY
        real TX
        real TY
        real MX
        real MY
        real angle
        real EffectCD
        real EffectCCD
        real moveangle
        real angleinc
        group DG
        group DG2

        static integer dindex
        static timer period
        static thistype array data

        method destroy takes nothing returns nothing
            if dindex == -1 then
                
                call ReleaseTimer(period)
            endif
            call this.deallocate()
        endmethod
       
        static method periodic takes nothing returns nothing
            local integer i = 0
            local tempDat this
            loop
                exitwhen i>dindex
                set this = data[i]
                set this.MaxDistance = this.MaxDistance - this.Speed
                    if this.MaxDistance > 0 then
                        set this.DX = GetUnitX(this.dummy)
                        set this.DY = GetUnitY(this.dummy)
                        set this.angleinc = GetRandomReal(ANGLE_INC1, ANGLE_INC2)
                        set this.moveangle = this.moveangle + this.angleinc
                        if this.moveangle > this.angle + MAX_ANGLE then
                            set this.moveangle = this.moveangle - ANGLE_INC2
                        endif
                        if this.moveangle < this.angle - MIN_ANGLE then
                            set this.moveangle = this.moveangle + ANGLE_INC2
                        endif
                        call SetUnitX(this.dummy, this.DX + this.Speed * Cos(this.moveangle * bj_DEGTORAD))
                        call SetUnitY(this.dummy, this.DY + this.Speed * Sin(this.moveangle * bj_DEGTORAD))
                        if this.EffectCCD < this.EffectCD then
                            set this.EffectCCD = this.EffectCCD + FPS
                        else
                            set this.EffectCCD = this.EffectCCD - this.EffectCD
                            call DestroyEffect(AddSpecialEffect(MOVE_EFFECT, this.DX, this.DY))
                        endif
                        set this.DG = CreateGroup()
                        set this.DG2 = CreateGroup()
                        call GroupEnumUnitsInRange(this.DG, this.DX, this.DY, DAMAGE_RANGE, null)
                            loop
                                set this.targets = FirstOfGroup(this.DG)
                                exitwhen this.targets == null
                                if IsUnitInGroup(this.targets, this.DG2) == false then
                                    call UnitDamageTarget(this.caster, this.targets, 25, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
                                    call GroupAddUnit(this.DG2, this.targets)
                                endif
                                call GroupRemoveUnit(this.DG, this.targets)
                            endloop
                        call BJDebugMsg(I2S(CountUnitsInGroup(this.DG2)))
                        set this.DG = null
                        set this.DG2 = null
                    else
                        call RemoveUnit(this.dummy)
                        set this.dummy = null
                        set this.caster = null
                        set data[i] = data[dindex]
                        set i = i - 1
                        set dindex = dindex - 1
                        call this.destroy()
                    endif
                set i = i + 1
            endloop
        endmethod
       
        static method cond takes nothing returns boolean
            local thistype this
            if GetSpellAbilityId() == ABILITY_ID then
                set this = thistype.allocate()
                set this.caster = GetTriggerUnit()
                set this.MaxDistance = DISTANCE
                set this.Speed = SPEED
                set this.EffectCD = EFFECT_CD
                set this.EffectCCD = EFFECT_CD
                set this.CX = GetUnitX(this.caster)
                set this.CY = GetUnitY(this.caster)
                set this.TX = GetSpellTargetX()
                set this.TY = GetSpellTargetY()
                set this.angle = bj_RADTODEG*Atan2(this.TY - this.CY, this.TX - this.CX)
                set this.moveangle  = this.angle
                set this.dummy = CreateUnit(GetOwningPlayer(this.caster), DUMMY_ID, this.CX, this.CY, this.angle)
                set dindex = dindex + 1
                set data[dindex] = this
                if dindex == 0 then
                    call TimerStart(period, FPS, true, function thistype.periodic)
                endif  
            endif
            return false
        endmethod
       

        static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
            call TriggerAddCondition(t, Condition(function thistype.cond))
            set dindex = -1
            set period = NewTimer()
            set t = null
        endmethod
    endstruct
endscope

Dummy move piercing units and at this moment it deals damage to them every 0.0312500 sec if they are in range.
It's so stiupid so i was trying to make them receive dmg once during loop. In GUI i had no problem with it...

Ofc spell isn't finished, there are still things to fix
 
Level 5
Joined
Sep 16, 2008
Messages
47
To make caster deal damage to units that contact moving dummy only once.

Dummy move, enemy units (i will take the care of conditions) are in range and they receive damage only once, not every 0.031250 because it makes damage impossible to calculate total damage
 
Last edited:
Level 14
Joined
Nov 18, 2007
Messages
816
A couple things id like to mention:

You are leaking a massive amount of groups: 64 per second. You can fix this by creating them when the spell is cast and destroying them when the spell is done (as was previously mentioned).

Once you do that, youll also notice that damage persists across multiple iterations, provided you also removed the two lines that set DG and DG2 to null every iteration.

Please provide normalized configuration values. private constant real SPEED = 20.00 is not something i want to configure, mostly because i at some point will want to change the resolution of the timer from 32Hz to, say 24 Hz or 40 Hz. Without normalized values i might be changing the spell in unintended ways, while a normalized value, such as 640 Units/Second would necessarily be independent of the resolution of the timer.
 
Status
Not open for further replies.
Top