• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[General] Sphere Unit Selection

Status
Not open for further replies.
Level 7
Joined
Feb 9, 2021
Messages
301
I am making a map that considers 3d positions of units, and I have a spell that creates an explosion. So, I wanted to ask how heavy it is for performance to select units in the sphere for the purpose of KB and Damage and what is the best way to do it?

Edit: After thinking a little bit more about it, I can just check for the distance between the unit's z and explosion z:
JASS:
function GetDistBetweenXY3d takes real x, real y, real z, real x2, real y2, real z2  returns real
        local real dx = x2 - x
        local real dy = y2 - y
        local real dz = z - z2
       
        return SquareRoot(( dx * dx ) + ( dy * dy ) + ( dz * dz ))
    endfunction
 
Last edited:
I am making a map that considers 3d positions of units, and I have a spell that creates an explosion. So, I wanted to ask how heavy it is for performance to select units in the sphere for the purpose of KB and Damage and what is the best way to do it?

Edit: After thinking a little bit more about it, I can just check for the distance between the unit's z and explosion z:
JASS:
function GetDistBetweenXY3d takes real x, real y, real z, real x2, real y2, real z2  returns real
        local real dx = x2 - x
        local real dy = y2 - y
        local real dz = z - z2
     
        return SquareRoot(( dx * dx ) + ( dy * dy ) + ( dz * dz ))
    endfunction
Yep, it isn't much difference between this and a 2d version.
To damage units within a 3D range, I'd start call GroupEnumUnitsInRange(targetsWithinRadius, x, y, range, null) to get units within range, then loop through them and check their 3D distance to the explosion.

Something along the lines of this should do (modify as needed!)
I have put the GetZHight-part in my maps "Custom Script Code" (I.E. the "root" of all triggers, in the "map-name.w3x" in the "Trigger Editor")

JASS:
globals
    location zChecker = Location(0,0)
endglobals

function GetZHeight takes real x, real y returns real
    call MoveLocation(zChecker, x, y)
    return GetLocationZ(zChecker)
endfunction

function Iterator3DFunc takes real x, real y, real z, real range returns group
    local group targetsWithinRadius = CreateGroup()
    local group unitsToReturn = CreateGroup()
    local unit u
    local real ux
    local real uy
    call GroupEnumUnitsInRange(targetsWithinRadius, x, y, range, null)
    loop
        set u = FirstOfGroup(targetsWithinRadius)
        exitwhen u == null
        set ux = GetUnitX(u)
        set uy = GetUnitY(u)
        if GetDistBetweenXY3d(x, y, z, ux, uy, GetUnitFlyHeight(u) + GetZHeight(yx, uy)) < range  then
            call GroupAddUnit(unitsToReturn, u)
        endif
        call GroupRemoveUnit(targetsWithinRadius,u)
    endloop
    //u is already null, no need to set it to null again!
    call DestroyGroup (targetsWithinRadius)
    set targetsWithinRadius = null // No idea if this is needed tbh
    return unitsToReturn
endfunction
 
Level 7
Joined
Feb 9, 2021
Messages
301
Yep, it isn't much difference between this and a 2d version.
To damage units within a 3D range, I'd start call GroupEnumUnitsInRange(targetsWithinRadius, x, y, range, null) to get units within range, then loop through them and check their 3D distance to the explosion.

Something along the lines of this should do (modify as needed!)
I have put the GetZHight-part in my maps "Custom Script Code" (I.E. the "root" of all triggers, in the "map-name.w3x" in the "Trigger Editor")

JASS:
globals
    location zChecker = Location(0,0)
endglobals

function GetZHeight takes real x, real y returns real
    call MoveLocation(zChecker, x, y)
    return GetLocationZ(zChecker)
endfunction

function Iterator3DFunc takes real x, real y, real z, real range returns group
    local group targetsWithinRadius = CreateGroup()
    local group unitsToReturn = CreateGroup()
    local unit u
    local real ux
    local real uy
    call GroupEnumUnitsInRange(targetsWithinRadius, x, y, range, null)
    loop
        set u = FirstOfGroup(targetsWithinRadius)
        exitwhen u == null
        set ux = GetUnitX(u)
        set uy = GetUnitY(u)
        if GetDistBetweenXY3d(x, y, z, ux, uy, GetUnitFlyHeight(u) + GetZHeight(yx, uy)) < range  then
            call GroupAddUnit(unitsToReturn, u)
        endif
        call GroupRemoveUnit(targetsWithinRadius,u)
    endloop
    //u is already null, no need to set it to null again!
    call DestroyGroup (targetsWithinRadius)
    set targetsWithinRadius = null // No idea if this is needed tbh
    return unitsToReturn
endfunction
Thanks.
 
Status
Not open for further replies.
Top