[Lua] Grid system: check the buildable terrain. [solved]

Level 7
Joined
Jun 1, 2009
Messages
125
Hi! I have some questions about glorious Uncle's Grid system.

Q1. How one can make the grid showing up only at the buildable places? I've tried to add
JASS:
 if (IsTerrainPathableBJ(GetLocationX(posX), GetLocationY(posY), t) == false) then

but it failed (probably cause of poor synthax knowledge), the compiler returns me the error the any next line after endif.
JASS:
        for x = 0, width do
            for y = 0, height do
                posX = startX + x * 128
                posY = startY + y * 128
                if (IsTerrainPathableBJ(GetLocationX(posX), GetLocationY(posY), t) == false) then
                SetImagePosition(img, posX, posY, 0)
                img = CreateImage("Gridplane.dds",128,128,0,0,0,0,1,1,1,1)
                SetImageRenderAlways(img, true)
                SetImageColor(img, 255, 255, 255, 0)
                gs_grid[id][i] = img
                i = i + 1
                endif
            end
        end
    end

Q2. how to detect a mouse right-click to stop the grid display? In my case, the grid shows up after the <build> button was pressed.

Q3. any additional hints about possible desyncs, leaks etc done by grid system?

Thanks in advance for your help!

The GUI map example file attached.
 

Attachments

  • Grid System Uncle001.w3m
    25.8 KB · Views: 3
Level 24
Joined
Feb 27, 2019
Messages
833
Q.1
JASS:
function IsTerrainPathableBJ takes location where, pathingtype t returns boolean
    return IsTerrainPathable(GetLocationX(where), GetLocationY(where), t)
endfunction
JASS:
native GetLocationX             takes location whichLocation returns real
native GetLocationY             takes location whichLocation returns real
JASS:
native IsTerrainPathable            takes real x, real y, pathingtype t returns boolean
Ctrl + f "pathingtype" in common.j
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
I don't remember when I made this or if it's glorious or not :p

Anyway, you're trying to reference img before you set it, that could be an issue:
vJASS:
SetImagePosition(img, posX, posY, 0)
img = CreateImage("Gridplane.dds",128,128,0,0,0,0,1,1,1,1)
Also, if that's Jass code then you need to prefix function calls with the word "call" and the setting of variables with "set".

There aren't any memory leaks in your current code but you also don't show enough of your code to be certain.

Desyncs occur when something is different on one player's client than the others. Visual stuff that doesn't affect gameplay is almost always fine to change locally because there is no comparison made between clients and the game doesn't care. So changing the colors/alpha/visibility of Images is likely safe to do locally, just make sure that the Images are created for everyone.

Desync vs Safe:
If you own 5 Footman on your game and only 4 Footman on my game = Desync.
If your 5 Footman are colored purple on your game and colored red on my game = Safe, colors don't affect gameplay between others.
 
Last edited:

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
:thumbs_up: Your system was Lua, if I read it correctly.



But it is your own creation :D Anyway, I've attached the WC3 map file that has your system in.
Bro, I create a new grid system every day! I can't remember "spell/system I made for someone 400 days ago" when I make several a week. :peasant-cheers-back:

But yes, if it's in Lua then you'll have to "convert" it to Jass by changing the syntax. The function calls and logic should mostly remain the same assuming that I didn't do anything exclusive to Lua (I doubt I did).

The main things you'll need to change:
  • "end" becomes "endif" OR "endfunction" if it's at the end of the function.
  • Add back missing "set" and "call".
  • "function X()" becomes "function X takes ..." where ... is the different (parameters).
  • "nil" becomes "null".
  • Local variables need to have their type declared before their name -> "local i = 0" becomes "local integer i = 0".
  • Local variables must be declared at the top of the function.
If you send me the full code I can probably convert it myself, assuming it's not a major pain to do so.
Edit: nvm, saw the map, checking it out.
 
Last edited:

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
Here's a Jass version, unsure if everything works because I used ChatGPT to convert it and tweaked a few things without fully testing:
vJASS:
library GridSystem initializer InitGridSystem

    globals
        // Constants
        constant integer MAX_PLAYERS = 28
        constant integer TILE_SIZE = 128
 
        // Optional Configuration Arrays
        integer array gs_gridStartX
        integer array gs_gridStartY
        integer array gs_gridWidth
        integer array gs_gridHeight
 
        // Customize colors and transparency
        integer gs_gridRed = 200
        integer gs_gridGreen = 200
        integer gs_gridBlue = 200
        integer gs_gridAlpha = 255
 
        // Main Grid and Visibility
        hashtable gs_grid = null
        boolean array gs_isVisible
    endglobals
 
    // Replacement for math.floor
    private function gs_Floor takes real r returns integer
        if r >= 0.00 then
            return R2I(r)
        endif
        return R2I(r) - 1
    endfunction
 
    function gs_GetTileXY takes real num returns real
        return TILE_SIZE * I2R(gs_Floor(num / TILE_SIZE + 0.9))
    endfunction
 
    function gs_DestroyGrid takes integer id returns nothing
        local integer i = 0
        local image img = null
 
        loop
            set img = LoadImageHandle(gs_grid, id, i)
            exitwhen img == null
            call DestroyImage(img)
            set i = i + 1
        endloop
    endfunction
 
    function gs_CreateGridAtXY takes integer id, real startX, real startY, integer width, integer height, boolean isCentered returns nothing
        local integer x = 0
        local integer y = 0
        local integer i = 0
        local image img = null
        local real posX = 0
        local real posY = 0
 
        call gs_DestroyGrid(id)
        set gs_isVisible[id] = false
 
        set startX = startX - TILE_SIZE
        set startY = startY - TILE_SIZE
        set width = width - 1
        set height = height - 1
 
        if isCentered then
            set startX = startX - TILE_SIZE * (width / 2)
            set startY = startY - TILE_SIZE * (height / 2)
        endif
 
        set x = 0
        loop
            exitwhen x > width
            set y = 0
            loop
                exitwhen y > height
                set img = CreateImage("Gridplane.dds", TILE_SIZE, TILE_SIZE, 0, 0, 0, 0, 1, 1, 1, 1)
                call SetImageRenderAlways(img, true)
                call SetImageColor(img, 255, 255, 255, 0)
                set posX = startX + x * TILE_SIZE
                set posY = startY + y * TILE_SIZE
                call SetImagePosition(img, posX, posY, 0)
                call SaveImageHandle(gs_grid, id, i, img)
                set i = i + 1
                set y = y + 1
            endloop
            set x = x + 1
        endloop
    endfunction
 
    function gs_CreateGridAtPoint takes integer id, location point, integer width, integer height, boolean isCentered returns nothing
        local real startX = gs_GetTileXY(GetLocationX(point))
        local real startY = gs_GetTileXY(GetLocationY(point))
        call RemoveLocation(point)
        call gs_CreateGridAtXY(id, startX, startY, width, height, isCentered)
    endfunction
 
    function gs_CreateGridOnUnit takes integer id, unit u, integer width, integer height, boolean isCentered returns nothing
        local real startX = gs_GetTileXY(GetUnitX(u))
        local real startY = gs_GetTileXY(GetUnitY(u))
        call gs_CreateGridAtXY(id, startX, startY, width, height, isCentered)
    endfunction

    function gs_ShowGrid takes integer id returns nothing
        local integer i = 0
        local image img
        set gs_isVisible[id] = true
 
        if GetLocalPlayer() == Player(id) then
            loop
                set img = LoadImageHandle(gs_grid, id, i)
                exitwhen img == null
                call SetImageColor(img, gs_gridRed, gs_gridGreen, gs_gridBlue, gs_gridAlpha)
                set i = i + 1
            endloop
        endif
    endfunction
 
    function gs_HideGrid takes integer id returns nothing
        local integer i = 0
        local image img = null
        set gs_isVisible[id] = false
 
        if GetLocalPlayer() == Player(id) then
            loop
                set img = LoadImageHandle(gs_grid, id, i)
                exitwhen img == null
                call SetImageColor(img, 255, 255, 255, 0)
                set i = i + 1
            endloop
        endif
    endfunction

    function gs_ToggleGrid takes integer id returns boolean
        if gs_isVisible[id] then
            call gs_HideGrid(id)
            return false
        else
            call gs_ShowGrid(id)
            return true
        endif
    endfunction
 
    function gs_CreateGridForAllPlayers takes boolean isCentered returns nothing
        local integer i = 0
        loop
            exitwhen i >= MAX_PLAYERS
            call gs_CreateGridAtXY(i, I2R(gs_gridStartX[i]), I2R(gs_gridStartY[i]), gs_gridWidth[i], gs_gridHeight[i], isCentered)
            set i = i + 1
        endloop
    endfunction

    private function InitGridSystem takes nothing returns nothing
        // Customize grid settings
        local integer i = 0
        loop
            set gs_gridStartX[i] = 0
            set gs_gridStartY[i] = 0
            set gs_gridWidth[i] = 9
            set gs_gridHeight[i] = 9
            set i = i + 1
            exitwhen i >= MAX_PLAYERS
        endloop

        set gs_grid = InitHashtable()

    endfunction
 
    endlibrary
 
Last edited:
Level 7
Joined
Jun 1, 2009
Messages
125
Hmm, maybe it's just my crooked hands, but a simple copy-paste of the Jass version by ChatGPT returns multiple errors in the WorldEdit compilator.
However, I'm not sure if that conversion is mandatory.
I belive that all I need - is to find the way to screw this one to the original system

JASS:
if IsTerrainPathableBJ(Location(Pos_X, Pos_Y), PATHING_TYPE_BUILDABILITY) == true  then

Have to continue this tomorrow.
 
Level 7
Joined
Jun 1, 2009
Messages
125
Do you have JassHelper enabled?
Yes. Moreover, for this map file this option is initially locked, and I have no idea why! (pinned a screenshot).
According to your hint I've replaced
JASS:
endif
by
JASS:
end
, and the code have successifully passed through the WE compilation. But now, for some reason, it shows no grid at all, be it buildable or not:D

JASS:
for x = 0, width do
            for y = 0, height do
 
                posX = startX + x * 128
                posY = startY + y * 128

                if IsTerrainPathableBJ(Location(posX, pos_Y), PATHING_TYPE_BUILDABILITY) == true then           -- new string that I've added.

                img = CreateImage("Gridplane.dds",128,128,0,0,0,0,1,1,1,1)
                SetImageRenderAlways(img, true)
                SetImageColor(img, 255, 255, 255, 0)
                SetImagePosition(img, posX, posY, 0)
                gs_grid[id][I] = img
                i = i + 1

               end       -- new string that I've added.

            end
        end
  end
 

Attachments

  • Screen001.PNG
    Screen001.PNG
    55.3 KB · Views: 6
Level 7
Joined
Jun 1, 2009
Messages
125
I think I've found a possible issue. Nichilus have mentioned Scenario - Map Options - "Script language". It was set to "Jass" in both cases, while the grid system trigger is Lua. Perhaps that's the problem? Is it possible to use both Jass and Lua systems in one map?
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
I think I've found a possible issue. Nichilus have mentioned Scenario - Map Options - "Script language". It was set to "Jass" in both cases, while the grid system trigger is Lua. Perhaps that's the problem? Is it possible to use both Jass and Lua systems in one map?
If your map uses Lua then you can just use the original system.

I think there's some tricks to have both types of code in your map, but the basic answer is:

No, you cannot support both scripting languages.
 
Top