• 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.
  • It's time for the first HD Modeling Contest of 2025. Join the theme discussion for Hive's HD Modeling Contest #7! Click here to post your idea!

Damage Detection System Problem

Status
Not open for further replies.
Level 21
Joined
May 16, 2012
Messages
640
Hello guys, in my map I've created a system to spawn units in waves (code below) and i recently imported a Physical Damage Detection System (PDD) made by looking_for_help aka eey and i'm using it to create some orb effect similar triggers. In the test map that comes with PDD, the triggers works great and the system looks to be working correctly in my map too, the problem is, in the first wave of enemy's, the trigger that I've created works (Orb of Fire kind of trigger), but when the second wave of enemy's come and the trigger fires for them it bugs out.

(Spawn Code)
JASS:
scope Spawn1 initializer Init

private function Conditions takes nothing returns boolean
    if(udg_WaveKills_Event == 1 or udg_Event_4000_Flag == 1 or udg_Event2_Flag2 == 1 or udg_MuradinEvent_Flag == 1) then
        return false
    endif
    return true
endfunction

private function Actions takes nothing returns nothing
    local location c
    local integer i
    set c = Location(GetRectCenterX(gg_rct_Castle), GetRectCenterY(gg_rct_Castle))
    if ( udg_Race_Turn == 0 ) then
        set i = 0
        loop
            exitwhen i > (udg_NumberOfPlayers_Integer - 1)
            call CreateNUnitsLoc((5 * udg_Portal_Vector[i]), 'hfoo', Player(10), Location(GetRectCenterX(udg_Spawn_Region_Vector[i]), GetRectCenterY(udg_Spawn_Region_Vector[i])), 0.00)
            call GroupPointOrderLoc(bj_lastCreatedGroup, "attack", c)
            call CreateNUnitsLoc((5 * udg_Portal_Vector[i]), 'hrif', Player(11), Location(GetRectCenterX(udg_Spawn_Region_Vector[i]), GetRectCenterY(udg_Spawn_Region_Vector[i])), 0.00)
            call GroupPointOrderLoc(bj_lastCreatedGroup, "attack", c)
            if (udg_HumanCounter == 1 and udg_Difficult_Level == 3) then
                call CreateNUnitsLoc((1 * udg_Portal_Vector[i]), 'H005', Player(9), Location(GetRectCenterX(udg_Spawn_Region_Vector[i]), GetRectCenterY(udg_Spawn_Region_Vector[i])), 0.00)
                call GroupPointOrderLoc(bj_lastCreatedGroup, "attack", c)
                call SetHeroStr(bj_lastCreatedUnit, (150 * udg_HeroLevelCounter), true)
                call SetHeroAgi(bj_lastCreatedUnit, (150 * udg_HeroLevelCounter), true)
                call SetHeroInt(bj_lastCreatedUnit, (150 * udg_HeroLevelCounter), true)
                call SetHeroLevel(bj_lastCreatedUnit, udg_HeroLevelCounter, false)
            endif
            set i = i + 1
        endloop
        if (udg_HumanCounter == 1) then
            set udg_HumanCounter = 0
        else
            set udg_HumanCounter = udg_HumanCounter + 1
        endif
        set udg_Race_Turn = 1
    else
        if ( udg_Race_Turn == 1 ) then
            set i = 0
            loop
                exitwhen i > ( udg_NumberOfPlayers_Integer - 1 )
                call CreateNUnitsLoc((5 * udg_Portal_Vector[i]), 'ogru', Player(10), Location(GetRectCenterX(udg_Spawn_Region_Vector[i]), GetRectCenterY(udg_Spawn_Region_Vector[i])), 0.00)
                call GroupPointOrderLoc(bj_lastCreatedGroup, "attack", c)
                call CreateNUnitsLoc((5 * udg_Portal_Vector[i]), 'ohun', Player(11), Location(GetRectCenterX(udg_Spawn_Region_Vector[i]), GetRectCenterY(udg_Spawn_Region_Vector[i])), 0.00)
                call GroupPointOrderLoc(bj_lastCreatedGroup, "attack", c)
                if (udg_OrcCounter == 1 and udg_Difficult_Level == 3) then
                    call CreateNUnitsLoc((1 * udg_Portal_Vector[i]), 'O003', Player(9), Location(GetRectCenterX(udg_Spawn_Region_Vector[i]), GetRectCenterY(udg_Spawn_Region_Vector[i])), 0.00)
                    call GroupPointOrderLoc(bj_lastCreatedGroup, "attack", c)
                    call SetHeroStr(bj_lastCreatedUnit, (150 * udg_HeroLevelCounter), true)
                    call SetHeroAgi(bj_lastCreatedUnit, (150 * udg_HeroLevelCounter), true)
                    call SetHeroInt(bj_lastCreatedUnit, (150 * udg_HeroLevelCounter), true)
                    call SetHeroLevel(bj_lastCreatedUnit, udg_HeroLevelCounter, false)
                endif
                set i = i + 1
            endloop
            if (udg_OrcCounter == 1) then
                set udg_OrcCounter = 0
            else
                set udg_OrcCounter = udg_OrcCounter + 1
            endif
            set udg_Race_Turn = 2
        else
            if ( udg_Race_Turn == 2 ) then
                set i = 0
                loop
                    exitwhen i > ( udg_NumberOfPlayers_Integer - 1 )
                    call CreateNUnitsLoc((5 * udg_Portal_Vector[i]), 'ugho', Player(10), Location(GetRectCenterX(udg_Spawn_Region_Vector[i]), GetRectCenterY(udg_Spawn_Region_Vector[i])), 0.00)
                    call GroupPointOrderLoc(bj_lastCreatedGroup, "attack", c)
                    call CreateNUnitsLoc((5 * udg_Portal_Vector[i]), 'ucry', Player(11), Location(GetRectCenterX(udg_Spawn_Region_Vector[i]), GetRectCenterY(udg_Spawn_Region_Vector[i])), 0.00)
                    call GroupPointOrderLoc(bj_lastCreatedGroup, "attack", c)
                    if (udg_UndeadCounter == 1 and udg_Difficult_Level == 3) then
                        call CreateNUnitsLoc((1 * udg_Portal_Vector[i]), 'U007', Player(9), Location(GetRectCenterX(udg_Spawn_Region_Vector[i]), GetRectCenterY(udg_Spawn_Region_Vector[i])), 0.00)
                        call GroupPointOrderLoc(bj_lastCreatedGroup, "attack", c)
                        call SetHeroStr(bj_lastCreatedUnit, (150 * udg_HeroLevelCounter), true)
                        call SetHeroAgi(bj_lastCreatedUnit, (150 * udg_HeroLevelCounter), true)
                        call SetHeroInt(bj_lastCreatedUnit, (150 * udg_HeroLevelCounter), true)
                        call SetHeroLevel(bj_lastCreatedUnit, udg_HeroLevelCounter, false)
                    endif
                    set i = i + 1
                endloop
                if (udg_UndeadCounter == 1) then
                    set udg_UndeadCounter = 0
                else
                    set udg_UndeadCounter = udg_UndeadCounter + 1
                endif
                set udg_Race_Turn = 3
            else
                if ( udg_Race_Turn == 3 ) then
                    set i = 0
                    loop
                        exitwhen i > ( udg_NumberOfPlayers_Integer - 1 )
                        call CreateNUnitsLoc((5 * udg_Portal_Vector[i]), 'esen', Player(10), Location(GetRectCenterX(udg_Spawn_Region_Vector[i]), GetRectCenterY(udg_Spawn_Region_Vector[i])), 0.00)
                        call GroupPointOrderLoc(bj_lastCreatedGroup, "attack", c)
                        call CreateNUnitsLoc((5 * udg_Portal_Vector[i]), 'earc', Player(11), Location(GetRectCenterX(udg_Spawn_Region_Vector[i]), GetRectCenterY(udg_Spawn_Region_Vector[i])), 0.00)
                        call GroupPointOrderLoc(bj_lastCreatedGroup, "attack", c)
                        if (udg_NightElfCounter == 1 and udg_Difficult_Level == 3) then
                            call CreateNUnitsLoc((1 * udg_Portal_Vector[i]), 'E002', Player(9), Location(GetRectCenterX(udg_Spawn_Region_Vector[i]), GetRectCenterY(udg_Spawn_Region_Vector[i])), 0.00)
                            call GroupPointOrderLoc(bj_lastCreatedGroup, "attack", c)
                            call SetHeroStr(bj_lastCreatedUnit, (150 * udg_HeroLevelCounter), true)
                            call SetHeroAgi(bj_lastCreatedUnit, (150 * udg_HeroLevelCounter), true)
                            call SetHeroInt(bj_lastCreatedUnit, (150 * udg_HeroLevelCounter), true)
                            call SetHeroLevel(bj_lastCreatedUnit, udg_HeroLevelCounter, false)
                        endif
                        set i = i + 1
                    endloop
                    if (udg_NightElfCounter == 1) then
                        set udg_NightElfCounter = 0
                        set udg_HeroLevelCounter = udg_HeroLevelCounter + 1
                    else
                        set udg_NightElfCounter = udg_NightElfCounter + 1
                    endif
                    set udg_Race_Turn = 0
                endif
            endif
        endif
    endif
    call RemoveLocation(c)
    set c = null
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    set gg_trg_Spawn1 = CreateTrigger()
    call DisableTrigger( gg_trg_Spawn1 )
    call TriggerRegisterTimerEvent(gg_trg_Spawn1, 30.00, true)
    call TriggerAddCondition(gg_trg_Spawn1, Condition( function Conditions ) )
    call TriggerAddAction(gg_trg_Spawn1, function Actions )
endfunction

endscope

*CreateNUnitsLoc is a custom function that i created.


(Orb of Fire Code)
JASS:
scope OrbFire initializer Init

private function Conditions takes nothing returns boolean
     return ((UnitHasItemOfTypeBJ(udg_PDD_source, 'I01J') == true) and (udg_PDD_damageType == udg_PDD_PHYSICAL))
endfunction

private function GroupFilter takes nothing returns boolean
    local unit u
    set u = GetFilterUnit()
    return ((IsUnitEnemy(u, GetOwningPlayer(udg_PDD_source)) == true) and (u != udg_PDD_target) and ((GetUnitState(u, UNIT_STATE_LIFE) <= 0) == false))
    set u = null
endfunction

private function GroupCallBack takes nothing returns nothing
    local unit u
    set u = GetEnumUnit()
    call UnitDamageTargetEx(udg_PDD_source, u, 100.0, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_FIRE, null)
    set u = null
endfunction

private function Actions takes nothing returns nothing
    local location l
    local group g = CreateGroup()
    set l = GetUnitLoc(udg_PDD_target)
    call GroupEnumUnitsInRangeOfLoc(g, l, 350.00, Condition(function GroupFilter))
    call ForGroup(g, function GroupCallBack )
    call RemoveLocation(l)
    call DestroyGroup(g)
    set l = null
    set g = null
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterVariableEvent( t, "udg_PDD_damageEventTrigger", EQUAL, 1.00 )
    call TriggerAddCondition( t, Condition( function Conditions ) )
    call TriggerAddAction( t, function Actions )
endfunction

endscope

*UnitDamageTargetEx is a custom function that comes with the PDD, The author instructed us to use it to avoid recursion problems in his system.

As you can see, the first type of units created by the Spawn Code are 5 footman and 5 rifleman and the second are 5 Grunts and 5 Troll Headhunters and then 5 Ghouls and 5 Crypt Fiends and lastly 5 Archers and 5 Huntresses and it keeps looping. Also, as you can see, the Orb of Fire trigger only fires when the source of damage has an item of type of my custom orb of fire item and the type of damage is physical and it deals code damage (PDD can differentiate from physical, spell or code which is neat). As i said before, for the first wave (5 footman and 5 rifleman) it works fine (see below image, red is physical damage, green is code damage), but for the second and subsequent waves its buggy (see second image).

1.png

(Here the first units to be ever spawned, the orb trigger works fine, every attack 100 code damage is dealt to units nearby but not the unit being attacked)

2.png

(Here the second waves interact with the unit with the item and it bugs out. As you can see the 100 bonus damage is applied multiple times to the units and with different damage types, physical and code damage respectively)

3.png

(Finally after the first attack against a second wave unit, the AoE damage is not applied anymore and on top of that the the damage of the attack is applied twice to the unit being attacked)

I've tried everything that i could think of to solve this, but i'm really lost now. Appreciate the help and thx.
 
Your custom function returns group or unit?
CreateNUnitsLoc
you refer to bj_lastCreatedGroup, but also (when creating a hero) to bj_lastCreatedUnit

Please declare this native
native UnitAlive takes unit u returns boolean and try in Orb trigger
JASS:
return ((IsUnitEnemy(u, GetOwningPlayer(udg_PDD_source))) and (u != udg_PDD_target) and (UnitAlive(u)))
checking life using above native is safer.
 
Level 21
Joined
May 16, 2012
Messages
640
Your custom function returns group or unit?
CreateNUnitsLoc
you refer to bj_lastCreatedGroup, but also (when creating a hero) to bj_lastCreatedUnit

Please declare this native
native UnitAlive takes unit u returns boolean and try in Orb trigger
JASS:
return ((IsUnitEnemy(u, GetOwningPlayer(udg_PDD_source))) and (u != udg_PDD_target) and (UnitAlive(u)))
checking life using above native is safer.


this is my custom function:

JASS:
function CreateNUnitsLoc takes integer count, integer unitid, player whichPlayer, location whichLoc, real face returns group
    local location l
    call GroupClear(bj_lastCreatedGroup)
    set l = whichLoc
    loop
        set count = count - 1
        exitwhen count < 0
            set bj_lastCreatedUnit = CreateUnitAtLoc(whichPlayer, unitid, l, face)
            call RemoveGuardPosition(bj_lastCreatedUnit)
            call GroupAddUnit(bj_lastCreatedGroup, bj_lastCreatedUnit)
    endloop
    call RemoveLocation(l)
    set l = null
    return bj_lastCreatedGroup
endfunction

i set both last created unit and re-use the last created group.

About declaring that native. I just declare it? no coding what it does? how will it work? Also i changed that line and started using a GetUnitLife which is a function provided by the PDD author. I suppose its even safer, considering that the author said that if we ever use damage modifier provided by his system, we need to use that function to get the correct values.

In further tests I've made, i figured it out (i guess) what the problem was. In the system the author created a function that runs periodically everry 60 secto clear memory leaks i suppose:

JASS:
function ClearMemory_Actions takes nothing returns nothing
    local group g = CreateGroup()
    local code c = function DamageEngine
 
    // Reset the damage event
    call GroupEnumUnitsInRect(g, GetWorldBounds(), null)
    call ResetTrigger(udg_PDD_damageEvent)
    call DestroyTrigger(udg_PDD_damageEvent)
    set udg_PDD_damageEvent = null
 
    // Rebuild it then
    set udg_PDD_damageEvent = CreateTrigger()
    call TriggerAddCondition(udg_PDD_damageEvent, Filter(c))
    call ForGroup(g, function RestoreTriggers)
    call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 5.00, "Cleaning Memory")
    // Clean things up
    call DestroyGroup(g)
    set g = null
    set c = null
endfunction

this function runs every 60 sec when:

JASS:
local group g = CreateGroup()
    local region r = CreateRegion()
    local trigger UnitEnters = CreateTrigger()
    local trigger ClearMemory = CreateTrigger()
    local code cDamageEngine = function DamageEngine
    local code cUnitEnters = function UnitEntersMap
    local code cClearMemory = function ClearMemory_Actions
    local code cRunAllocatedAttacks = function RunAllocatedAttacks

// Clear memory leaks
    call TriggerRegisterTimerEvent(ClearMemory, udg_PDD_TRIGGER_CLEANUP_PERIOD, true)
    call TriggerAddCondition(ClearMemory, Filter(cClearMemory))

And the value of udg_PDD_TRIGGER_CLEANUP_PERIOD is 60.0 sec. I've noticed that every other group of units bugged my Orb of Fire trigger, meaning that the first group (5 footman and 5 rifleman) and third (5 Ghouls and 5 Crypt Fiend) the item works correctly, and the second and fourth groups got buggy. Than i realized that the second and fourth groups spawned every 60.0 (cuz the Spawn Code runs every 30.0), so i changed the value of udg_PDD_TRIGGER_CLEANUP_PERIOD to 33.33 and it started working perfectly. I'm not really sure why, but i'm guessing that before, every 60.0 sec all the handles were recycled or destroyed and units spawning at that exact moment were not considered by the system, but its just a guess.

Anyway, changing that value fixed everything, and in my map no unit is spawned with a multiple of 33.33, so i guess i'm safe for now.
 
Status
Not open for further replies.
Top