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

[Snippet] BoundUtils

Level 16
Joined
Mar 3, 2006
Messages
1,564
This library will add some simple functions that will always inbound locations to the map. They are simple but may be useful.

JASS:
library BoundUtils initializer SetBoundary

/*
By: Starquizer
To implement it, simply copy the whole contents
of the library then paste it into an empty
converted-to-custom-text trigger.

To use it, use
call GetSpellTargetXBounded() instead of call GetSpellTargetX()
and
call GetSpellTargetYBounded() instead of call GetSpellTargetY()

also you have another two functions
GetBoundedX and GetBoundedY, those will inbound your x and y to the map.
*/
    globals
        public real MIN_X
        public real MIN_Y
        public real MAX_X
        public real MAX_Y
        public real MAP_MIN_X
        public real MAP_MIN_Y
        public real MAP_MAX_X
        public real MAP_MAX_Y
        private constant real SAFETY_OFFSET = 8.00
    endglobals

    private function SetBoundary takes nothing returns nothing
        local rect map = GetWorldBounds()
        set MIN_X = GetCameraBoundMinX() - 512.000
        set MIN_Y = GetCameraBoundMinY() - 256.000
        set MAX_X = GetCameraBoundMaxX() + 512.000
        set MAX_Y = GetCameraBoundMaxY() + 256.000
        set MAP_MIN_X = GetRectMinX(map)
        set MAP_MAX_X = GetRectMaxX(map)
        set MAP_MIN_Y = GetRectMinY(map)
        set MAP_MAX_Y = GetRectMaxY(map)
        set map = null
    endfunction

    function GetSpellTargetXBounded takes nothing returns real
        local real x = GetSpellTargetX()
        if x < MIN_X then
            return MIN_X + SAFETY_OFFSET
        elseif x > MAX_X then
            return MAX_X - SAFETY_OFFSET
        else
            return x
        endif
    endfunction

    function GetSpellTargetYBounded takes nothing returns real
        local real y = GetSpellTargetY()
        if y < MIN_Y then
            return MIN_Y + SAFETY_OFFSET
        elseif y > MAX_Y then
            return MAX_Y - SAFETY_OFFSET
        else
            return y
        endif
    endfunction

    function GetBoundedX takes real x returns real
        if x < MAP_MIN_X then
            return MAP_MIN_X + SAFETY_OFFSET
        elseif x > MAP_MAX_X then
            return MAP_MAX_X - SAFETY_OFFSET
        else
            return x
        endif
    endfunction

    function GetBoundedY takes real y returns real
        if y < MAP_MIN_Y then
            return MAP_MIN_Y + SAFETY_OFFSET
        elseif y > MAP_MAX_Y then
            return MAP_MAX_Y - SAFETY_OFFSET
        else
            return y
        endif
    endfunction

    function SetUnitXBounded takes unit u, real x returns nothing
        if x < MAP_MIN_X then
            call SetUnitX(u,MAP_MIN_X + SAFETY_OFFSET)
        elseif x > MAP_MAX_X then
            call SetUnitX(u,MAP_MAX_X - SAFETY_OFFSET)
        else
            call SetUnitX(u,x)
        endif
    endfunction

    function SetUnitYBounded takes unit u, real y returns nothing
        if y < MAP_MIN_Y then
            call SetUnitY(u,MAP_MIN_Y + SAFETY_OFFSET)
        elseif y > MAP_MAX_Y then
            call SetUnitY(u,MAP_MAX_Y - SAFETY_OFFSET)
        else
            call SetUnitY(u,y)
        endif
    endfunction
endlibrary
 
Last edited:
Level 16
Joined
Mar 3, 2006
Messages
1,564
Nice ;)
You could make this require WorldBounds and use those globals instead :p

But WorldBounds uses GetWorldBounds which will give different reals than GetCameraBound. Actually, I ran lots of tests to determine the difference between Enitre Map Area, Playable Map Area and Camera Bound. I used this script

JASS:
library bounds initializer AllBounds
    function AllBounds takes nothing returns nothing
        local integer i = 0
        local real minX
        local real minY
        local real maxX
        local real maxY
        local rect world = GetWorldBounds()
        local real h = 32.00
        local lightning l
        local string lightning_model = "DRAM"
        set minX = GetCameraBoundMinX()
        set minY = GetCameraBoundMinY()
        set maxX = GetCameraBoundMaxX()
        set maxY = GetCameraBoundMaxY()
        call BJDebugMsg("Camera Bound")
        call BJDebugMsg("min X = "+R2S(minX))
        call BJDebugMsg("min Y = "+R2S(minY))
        call BJDebugMsg("max X = "+R2S(maxX))
        call BJDebugMsg("max Y = "+R2S(maxY))
        call AddLightningEx(lightning_model,false,minX,minY,h,maxX,minY,h)
        call AddLightningEx(lightning_model,false,maxX,minY,h,maxX,maxY,h)
        call AddLightningEx(lightning_model,false,maxX,maxY,h,minX,maxY,h)
        call AddLightningEx(lightning_model,false,minX,maxY,h,minX,minY,h)
        //
        set minX = minX - 512.000
        set minY = minY - 256.000
        set maxX = maxX + 512.000 
        set maxY = maxY + 256.000
        call BJDebugMsg("Playable Area (With Margins)")
        call BJDebugMsg("min X = "+R2S(minX))
        call BJDebugMsg("min Y = "+R2S(minY))
        call BJDebugMsg("max X = "+R2S(maxX))
        call BJDebugMsg("max Y = "+R2S(maxY))
        set lightning_model = "DRAL"
        call AddLightningEx(lightning_model,false,minX,minY,h,maxX,minY,h)
        call AddLightningEx(lightning_model,false,maxX,minY,h,maxX,maxY,h)
        call AddLightningEx(lightning_model,false,maxX,maxY,h,minX,maxY,h)
        call AddLightningEx(lightning_model,false,minX,maxY,h,minX,minY,h)
        //
        set minX = GetRectMinX(bj_mapInitialPlayableArea)
        set minY = GetRectMinY(bj_mapInitialPlayableArea)
        set maxX = GetRectMaxX(bj_mapInitialPlayableArea)
        set maxY = GetRectMaxY(bj_mapInitialPlayableArea)
        call BJDebugMsg("Playable Area (With BJ Global)")
        call BJDebugMsg("min X = "+R2S(minX))
        call BJDebugMsg("min Y = "+R2S(minY))
        call BJDebugMsg("max X = "+R2S(maxX))
        call BJDebugMsg("max Y = "+R2S(maxY))
        set lightning_model = "DRAM"
        call AddLightningEx(lightning_model,false,minX,minY,h,maxX,minY,h)
        call AddLightningEx(lightning_model,false,maxX,minY,h,maxX,maxY,h)
        call AddLightningEx(lightning_model,false,maxX,maxY,h,minX,maxY,h)
        call AddLightningEx(lightning_model,false,minX,maxY,h,minX,minY,h)
        //
        set minX = GetRectMinX(world)
        set minY = GetRectMinY(world)
        set maxX = GetRectMaxX(world)
        set maxY = GetRectMaxY(world)
        call BJDebugMsg("Entire Map")
        call BJDebugMsg("min X = "+R2S(minX))
        call BJDebugMsg("min Y = "+R2S(minY))
        call BJDebugMsg("max X = "+R2S(maxX))
        call BJDebugMsg("max Y = "+R2S(maxY))
        set lightning_model = "DRAL"
        set l = AddLightningEx(lightning_model,false,minX,minY,h,maxX,minY,h)
        call SetLightningColor(l,1.,0.,0.,1.)
        set l = AddLightningEx(lightning_model,false,maxX,minY,h,maxX,maxY,h)
        call SetLightningColor(l,1.,0.,0.,1.)
        set l = AddLightningEx(lightning_model,false,maxX,maxY,h,minX,maxY,h)
        call SetLightningColor(l,1.,0.,0.,1.)
        set l = AddLightningEx(lightning_model,false,minX,maxY,h,minX,minY,h)
        call SetLightningColor(l,1.,0.,0.,1.)

    endfunction
endlibrary

Change the Map Size and Camera Bound Size from the Scenario menu then test and you will know what I mean.
 
Level 7
Joined
Apr 30, 2011
Messages
359
rename your constants please . . . (MIN_X, MIN_Y are too simple, should be CAM_BOUND_MIN_X, CAM_BOUND_MIN_Y, etc)
and make it GetXBounded, GetYBounded instead
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
rename your constants please . . . (MIN_X, MIN_Y are too simple, should be CAM_BOUND_MIN_X, CAM_BOUND_MIN_Y, etc)
and make it GetXBounded, GetYBounded instead

I really don't understand, shouldn't variables be short for simplicity. One of the advantages of JASS over GUI is that typing is faster so in my opinion making long variables will eliminate this advantage (that's my POV).

I used GetSpellTargetXBounded because GetSpellTargetX already exists all you need to do is add the word Bounded (and again that's my POV)

Anyway, thanks for the feedback.
 
Actually, I think its preferable to use PlayableMapArea bounds rather than CameraBounds because spells should be available for casting until the Playable Bounds which is a bit larger than the camera bounds and is the actual bounds in which it won't cause errors if you create units...

and you don't need scripts to know that, just opening a map on the editor will let you see the difference between world,camera and playable map bounds
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Actually, I think its preferable to use PlayableMapArea bounds rather than CameraBounds because spells can be casted until the Playable Bounds without errors anyway... (camera bounds is almost always less than playable bounds btw)

and you don't need scripts to know that, just opening a map on the editor will let you see the difference between world,camera and playable map bounds

PlayableMapArea Always = CameraBound + 512.000 from both Left and right and CameraBound + 256.000 from both Top and Bottom.

In the previous posts you will find a function which confirms that, paste it in an empty map header and see what I mean.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
PlayableMapArea Always = CameraBound + 512.000 from both Left and right and CameraBound + 256.000 from both Top and Bottom.

In the previous posts you will find a function which confirms that, paste it in an empty map header and see what I mean.

Unless the user manually adjusts those, which I do sometimes.
 
As I said they are greater than camera bounds... and your test proves that... so I don't don't see the point in that post...

but as I said, the actual maximum safety bounds on the map for things like unit creation is the Playable area not the camera bounds... I know it becoz that's what I use...

my only point is, why not maximize the possible bounds by using Playable Area bounds rather than camera bounds?
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Unless the user manually adjusts those, which I do sometimes.

Are you certain of this ? :vw_wtf:

Because I found that whenever I modify the camera bound from the Scenario menu the Playable map area is modified too so that the margin on left and right is always 512.0 and top and bottom is 256.0

The entire map is modified via the check box below the camera bound and it has nothing to do with the Playable area.

Am I missing something ?
 
Honestly, this is how I would write it:

JASS:
library BoundUtils requires WorldBounds
    
    function GetBoundedX takes real x returns real
    	if x > WorldBounds.maxX then
    		return WorldBounds.maxX
    	elseif x < WorldBounds.minX then
    		return WorldBounds.minX
    	endif
    	return x
    endfunction
    
    function GetBoundedY takes real y returns real
        if y > WorldBounds.maxY then
    		return WorldBounds.maxY
    	elseif y < WorldBounds.minY
    		return WorldBounds.minY
    	endif
    	return y
    endfunction

endlibrary
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Actually, for something called GetBoundedX/Y, it would be fine because the point of bounding is to avoid crashes :p

If you want something like GetSpellTargetBoundedX/Y, you would use the Camera bounds with a little offset <:

Ok, I understood what you are pointing at. So I use WorldBounds to prevent game crash when a unit gets out of the Map (Entire Map) and Camera Bound or Playable Area if I want to inbound the spell target in the playable area.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Camera bounds with a little offset = Playable Map Area... :)

Yes, that's why in my posts I mentioned the word "Margin". These margins are 512.00 on the left and right and 256.00 on the top and bottom.

Try this, it will spill the beans:


JASS:
library bounds initializer AllBounds
    function AllBounds takes nothing returns nothing
        local integer i = 0
        local real minX
        local real minY
        local real maxX
        local real maxY
        local rect world = GetWorldBounds()
        local real h = 32.00
        local real dur = 6000.
        local string lightning_model = "DRAM"
        //================================================================
        set minX = GetCameraBoundMinX()
        set minY = GetCameraBoundMinY()
        set maxX = GetCameraBoundMaxX()
        set maxY = GetCameraBoundMaxY()
        call DisplayTimedTextToPlayer(Player(0),0,0,dur,"|cff5555FFCamera Bound|r")
        call DisplayTimedTextToPlayer(Player(0),0,0,dur,"min X = "+R2S(minX)+"     min Y = "+R2S(minY))
        call DisplayTimedTextToPlayer(Player(0),0,0,dur,"max X = "+R2S(maxX)+"     max Y = "+R2S(maxY))
        call AddLightningEx(lightning_model,false,minX,minY,h,maxX,minY,h)
        call AddLightningEx(lightning_model,false,maxX,minY,h,maxX,maxY,h)
        call AddLightningEx(lightning_model,false,maxX,maxY,h,minX,maxY,h)
        call AddLightningEx(lightning_model,false,minX,maxY,h,minX,minY,h)
        //================================================================
        set minX = minX - 512.000
        set minY = minY - 256.000
        set maxX = maxX + 512.000 
        set maxY = maxY + 256.000
        call DisplayTimedTextToPlayer(Player(0),0,0,dur,"|cff00FF00Playable Area (Using Camera Bound + margin)|r")
        call DisplayTimedTextToPlayer(Player(0),0,0,dur,"min X = "+R2S(minX)+"     min Y = "+R2S(minY))
        call DisplayTimedTextToPlayer(Player(0),0,0,dur,"max X = "+R2S(maxX)+"     max Y = "+R2S(maxY))
        set lightning_model = "DRAL"
        call AddLightningEx(lightning_model,false,minX,minY,h,maxX,minY,h)
        call AddLightningEx(lightning_model,false,maxX,minY,h,maxX,maxY,h)
        call AddLightningEx(lightning_model,false,maxX,maxY,h,minX,maxY,h)
        call AddLightningEx(lightning_model,false,minX,maxY,h,minX,minY,h)
        //================================================================
        set minX = GetRectMinX(bj_mapInitialPlayableArea)
        set minY = GetRectMinY(bj_mapInitialPlayableArea)
        set maxX = GetRectMaxX(bj_mapInitialPlayableArea)
        set maxY = GetRectMaxY(bj_mapInitialPlayableArea)
        call DisplayTimedTextToPlayer(Player(0),0,0,dur,"|cffCC00CCPlayable Area (Using BJ Global bj_mapInitialPlayableArea)|r")
        call DisplayTimedTextToPlayer(Player(0),0,0,dur,"min X = "+R2S(minX)+"     min Y = "+R2S(minY))
        call DisplayTimedTextToPlayer(Player(0),0,0,dur,"max X = "+R2S(maxX)+"     max Y = "+R2S(maxY))
        set lightning_model = "MBUR"
        call SetLightningColor(AddLightningEx(lightning_model,false,minX,minY,h,maxX,minY,h),0.5,0.0,0.5,1.0)
        call SetLightningColor(AddLightningEx(lightning_model,false,maxX,minY,h,maxX,maxY,h),0.5,0.0,0.5,1.0)
        call SetLightningColor(AddLightningEx(lightning_model,false,maxX,maxY,h,minX,maxY,h),0.5,0.0,0.5,1.0)
        call SetLightningColor(AddLightningEx(lightning_model,false,minX,maxY,h,minX,minY,h),0.5,0.0,0.5,1.0)
        //================================================================
        set minX = GetRectMinX(world)
        set minY = GetRectMinY(world)
        set maxX = GetRectMaxX(world)
        set maxY = GetRectMaxY(world)
        call DisplayTimedTextToPlayer(Player(0),0,0,dur,"|cffFF0000Entire Map|r")
        call DisplayTimedTextToPlayer(Player(0),0,0,dur,"min X = "+R2S(minX)+"     min Y = "+R2S(minY))
        call DisplayTimedTextToPlayer(Player(0),0,0,dur,"max X = "+R2S(maxX)+"     max Y = "+R2S(maxY))
        set lightning_model = "DRAL"
        call SetLightningColor(AddLightningEx(lightning_model,false,minX,minY,h,maxX,minY,h),1.0,0.0,0.0,1.0)
        call SetLightningColor(AddLightningEx(lightning_model,false,maxX,minY,h,maxX,maxY,h),1.0,0.0,0.0,1.0)
        call SetLightningColor(AddLightningEx(lightning_model,false,maxX,maxY,h,minX,maxY,h),1.0,0.0,0.0,1.0)
        call SetLightningColor(AddLightningEx(lightning_model,false,minX,maxY,h,minX,minY,h),1.0,0.0,0.0,1.0)
    endfunction
endlibrary
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
so why use math when there's a function which returns it already?

You see GetCameraBound is a native function while bj_InitialMap..... is a BJ global constant, so lets suppose you imported an empty blizzard.j ==> this constant now don't exist. But since the margin will never change so my POV is that GetCameraBound + Margin is better.
 
Okay, fine maybe it is better...

though I don't see why someone would import an empty blizzard.j file, and if he does, there's a lot more systems that would be ruined, and lots of GUI actions too... So in the end, he might just delete that empty blizzard.j file... Would you mind to enlighten me a bit on why would someone do it?
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Okay, fine maybe it is better...

though I don't see why someone would import an empty blizzard.j file, and if he does, there's a lot more systems that would be ruined, and lots of GUI actions too... So in the end, he might just delete that empty blizzard.j file... Would you mind to enlighten me a bit on why would someone do it?

You are correct but I am assuming the worst, no not worse; its the ultimate worse case scenario, which is the user going nuts and insane :grin: and deleted or imported an empty blizz.j

Other than that "Playable area" is fine.
 
Level 7
Joined
Apr 30, 2011
Messages
359
It's BoundUtils_MIN_X/Y, overcold_ice, not MIN_X/Y. The current was is OK.

GetX/YBounded are pretty bad names, though I agree with the concept of not limiting it to spells. GetBoundedX/Y are better names.

didn't see 'public' prefixes
and btw, thanks for not misspelling my name @.@

and for the snippet,
you can't define camera bounds by your method -_-
and each player can have different camera bounds . .
use:
JASS:
native GetCameraBoundMaxX
native GetCameraBoundMaxY
native GetCameraBoundMinX
native GetCameraBoundMinY

hook SetCameraBounds
hook SetCameraBoundsToRect
hook SetCameraBoundsToRectForPlayerBJ

//  also:
native GetLocalPlayer

store min/max x/y differently for each players
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
At initialization the camera bound is always the same for any player until they are modified by a trigger(function) later.

As you see this library will run at initialization, saving the initial bounds to the globals after that you could modify the camera bounds as you wish, actually, I took this into account when I tried to script those functions.

Anyway, thanks for the comment.
 
Level 7
Joined
Apr 30, 2011
Messages
359
again,
i didn't see some parts of the snippet :3
missed those GetCameraBound(s) on you init, so it's fine
can you explain those margins?
i think it's minimum range between playable area and camera bound,
you 'must' add hooks when someone changes the bounds,
if not, this isn't a BoundUtils D:

and please remove:
JASS:
function GetSpellTargetXBounded
function GetSpellTargetYBounded
function SetUnitXBounded
function SetUnitYBounded
those aren't really needed, the only one needed is GetBoundedX and Y
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
I have an idea, how about keeping GetSpellTargetBoundedX/Y and changing the name to GetCameraBoundedX/Y, indicating that it bounds anything within the camera bounds :D

Ok i will tell what was on my mind when I choosed to name it GetSpellTargetXBounded().


  • I thought if one is already made a spell and decided to add this library all he/she has to do is add the word "Bounded" to GetSpellTargetX

  • When you type GetSpellTargetX a drop-down list will pop up and suggesting GetSpellTargetX , GetSpellTargetY all you have to do is select it and add the word "Bounded", I guess that will be easier than GetSpellTargetBoundedX/Y
 
Top