• 🏆 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!

[vJASS] A good way to handle making a 'boardgame'

Status
Not open for further replies.
Level 19
Joined
Oct 12, 2007
Messages
1,821
Hey there.

I'm working on something that looks a bit like a board game.
There are various squares where units will be placed on, and all together the field looks like the attached post.

I created rects and named them with the values you see on the picture. (ex: A4, B5.. etc)

Now I want to make something like a system that detects the border squares. So per example when I select a unit standing on -F5-, I want to do something with -E5-, -F4-, -F6- and -G5-. So the system will have to detect this in some sort of a way.

Does anyone know of an easy way to work on this, instead of creating 'if, then, else checks' for every square on the field (which will cost me alot of work).
 

Attachments

  • Field.png
    Field.png
    44.8 KB · Views: 184
Level 19
Joined
Oct 12, 2007
Messages
1,821
Well I use the rects to track which units are standing on a certain spot.
I'm quite a Warhammer fan, so there will be regiments with 12 or 16 units on those squares. So I use the rects to easily grab all units standing on the same square.
However, the rects' positions wont be changed, so coordinates would also work I guess.

EDIT:
Here's an example of what I want.
I want to locally create colored destructables showing where a selected unit is able to move to. So I have to know which spots have to be colored or are available for the unit. In the picture I 'selected' the dwarven ramriders.
 

Attachments

  • example.jpg
    example.jpg
    129.5 KB · Views: 150
Level 19
Joined
Oct 12, 2007
Messages
1,821
I made a system like this once. Maybe I can find it. If not, I could create it again.

Ah that would be nice.
But you don't have to put alot of work into making a new system like that man. That wouldn't feel right.:)
I can just try to figure something out myself, I just have to know in what direction I gotta try to find it.

What I currently got is that I created a global rect variable with double arrays.
So Tile[x][y]. And I added all rects to that. So rect A3 is called Tile[3][1]. (I decided to not use 0 values in here in case I have to make use of the borders of the playfield).
I'm just not sure if double array values are 'the way to go'. Because I never see people using them.:D
 
Level 19
Joined
Oct 12, 2007
Messages
1,821
Let me start by saying this looks epic.

Double arrays would be what I would do.

Do you just need a method of selecting the appropriate squares?

Well, I'm not really a math genius. I can handle slowly in my own tempo.:p
So I will figure out, but I was just wondering if people here knew of a good way to handle a boardgame like this. Mainly because I don't want to spend hours on something I will regret later on.
I just don't want to make bad choices early during the project.:)

I guess for now it's safe to just stick for double arrays then. Since it was my first guess, and you share that opinion. So I'm put at ease.:)
 
Level 25
Joined
Jul 10, 2006
Messages
3,315
The 4 squares adjacent to a given square with coords x, y is:
x-1, y
x+1, y
x, y-1
x, y+1

So you start with integer range = 3, and find the 4 squares adjacent to the origin.

Now you need to run this same function for each of those squares, but this time with range = range - 1, so range == 2. Repeat the process until you have range = 0, and this will give you all the squares in range 3 of the origin.

I realise I'm not exactly the best at explaining, but I hope that this has at least given you some idea of how to do it.

If Maker can find his system that would be best, but if not I'd also be happy to build it.
 
Level 19
Joined
Oct 12, 2007
Messages
1,821
Been working on it for a while. Got no problems so far and most things work smooth.
It's just that I'm not sure about the following.
I'm hiding walkable destructables, and I'm wondering if I'm able to locally hide them or would that cause a desync because they're walkable?
 
Level 25
Joined
Jul 10, 2006
Messages
3,315
Been working on it for a while. Got no problems so far and most things work smooth.
It's just that I'm not sure about the following.
I'm hiding walkable destructables, and I'm wondering if I'm able to locally hide them or would that cause a desync because they're walkable?

Take the walkability off, and then they're safe to hide.

When I did some testing hiding trees locally, they still had pathing and blocked vision.

Bridges, on the other hand, desynced the moment I ordered a unit to move to one.
 
Level 19
Joined
Oct 12, 2007
Messages
1,821
Hey guys.

I come to ask for help again, because I tried making a movement system but I'm just not good enough for it and have to give it up.
I was wondering if one of you would like to make a system for this movement for me.

It is pretty complicated because there are different types of movement and movement speed/range. Some units are able to pass other units while some aren't. Different movement types are Ground, Flying, Climbing, Swimming and Swimming+Climbing combination.

What the system has to do is basically check for each square if the unit is able to move to it or not and display that with (locally) changing the visibility of a destructable. I pre-placed those destructables on the field already and indexed them. Those destructables are coloured, so Red stands for impossible to move to, Green stands for possible and yellow is the one the unit is standing on already.

Here are some screenshots I made that explain a bit how it should look like eventually. I'll explain them for a bit.

Spellbreaker picture:
The Spellbreaker is able to move 1 step per turn. So in the picture you see where he should be able to move to, and which squares turn up coloured.

Dryad picture:
The Dryad is able to move 2 steps per turn. In the picture you see he can't 'cross' the Grunts so he can only go around them.

Knight picture:
The Knight is able to move 3 steps and can't cross Grunts either. However he can cross the Wyvern because that one is flying. But he can't stand on the same square as the Wyvern.

Gryphon picture:
The Gryphon is flying and able to move 3 steps. As you can see he can move over water and heightened terrain and cross land units like the Grunts.

Ghouls picture:
Ghouls are able to move 2 steps and are able to climb. They can't cross the Grunts but they are able to move over heightened terrain.

Myrmidon picture:
The Myrmidon has a movement of 1 step but he's able to swim. He can't move over heightened terrain.

Murloc picture:
The Murlocs have a movement of 2 steps and are able to climb and swim. The only difference they have with flying units is that they can't be crossed by land units or can't cross land units for themselves either.



I realise it's quite a big thing I'm asking, but since you already offered help I thought I maybe just tell you what I'm thinking about for the map.
If you like the idea and have time to help I would really appreciate it.
I could send you the map so you can see what I currently did already.
 

Attachments

  • Movement_Ground1.jpg
    Movement_Ground1.jpg
    76.5 KB · Views: 135
  • Movement_Ground2.jpg
    Movement_Ground2.jpg
    99.9 KB · Views: 141
  • Movement_Ground3.jpg
    Movement_Ground3.jpg
    112.8 KB · Views: 119
  • Movement_Climbing.jpg
    Movement_Climbing.jpg
    105.2 KB · Views: 119
  • Movement_Flying.jpg
    Movement_Flying.jpg
    84.9 KB · Views: 118
  • Movement_WaterClimbing.jpg
    Movement_WaterClimbing.jpg
    106.3 KB · Views: 125
  • Movement_Waterwalking.jpg
    Movement_Waterwalking.jpg
    75.3 KB · Views: 135
http://www.hiveworkshop.com/forums/...39-good-way-handle-making-boardgame-field.png

You should not skip any place here. Go for A,B,C,N,O and P from 1 to 9 as well
Then create 2D boolean array and set it to true for fields you can access.

When you pick field Xi,j just check are booleans Xi+1,j / Xi-1,j / Xi,j+1 / Xi,j-1 true, if so, add pointer there or do whatever you want with it. Simple as that.

Hint for 2D boolean array
set B[i*10 + j] = true/false

i go from 1 to 9
j go from 1 to 16
 
Level 19
Joined
Oct 12, 2007
Messages
1,821
Well this is what I've got right now.
I didn't add many checks yet. This is just a very basic first step.
My brain is just beginning to hurt for the further steps I will have to take with pathability and different unit types etc.

JASS:
scope BoardSetup initializer Init
globals
    rect array Field[9][17] ///Tile[x][y]
    destructable array Tile_Brown[9][17]
    destructable array Tile_Green[9][17]
    destructable array Tile_Red[9][17]
    destructable array Tile_Yellow[9][17]
    integer Tile3x3_Brown = 'DTrf'
    integer Tile3x3_Green = 'B003'
    integer Tile3x3_Yellow = 'B006'
    integer Tile3x3_Red = 'B002'
    integer Tile3x3_Water = 'B008'
    
    ///Field_Type displays what kind of a square it is///
    integer array Field_Type[9][17] ///0 = Land, 1 = Heightened, 2 = Water///
    ///Field_Path displays what kind of units are currently standing on the square///
    integer array Field_Path[9][17] ///0 = Free, 1 = Ground Units, 2 = Flying units///
endglobals

private function TileCreation takes nothing returns nothing
    local destructable d = GetEnumDestructable()
    local real x = GetDestructableX(d)
    local real y = GetDestructableY(d)
    local destructable t
    local integer X = 0
    local integer Y = 1
    
    if GetDestructableTypeId(d) == Tile3x3_Brown then
        loop
        exitwhen Y == 18
        
            loop
            exitwhen X == 10
                if RectContainsCoords(Field[X][Y], x, y) == true then
                    set Tile_Brown[X][Y] = d
                endif
                set X = X+1
            endloop
            set X = 0
            set Y = Y+1
        endloop
    elseif GetDestructableTypeId(d) == Tile3x3_Green then
        call ShowDestructable(d, false)
        loop
        exitwhen Y == 18
        
            loop
            exitwhen X == 10
                if RectContainsCoords(Field[X][Y], x, y) == true then
                    set Tile_Green[X][Y] = d
                endif
                set X = X+1
            endloop
            set X = 0
            set Y = Y+1
        endloop
    elseif GetDestructableTypeId(d) == Tile3x3_Red then
        call ShowDestructable(d, false)
        loop
        exitwhen Y == 18
        
            loop
            exitwhen X == 10
                if RectContainsCoords(Field[X][Y], x, y) == true then
                    set Tile_Red[X][Y] = d
                endif
                set X = X+1
            endloop
            set X = 0
            set Y = Y+1
        endloop
    elseif GetDestructableTypeId(d) == Tile3x3_Yellow then
        call ShowDestructable(d, false)
        loop
        exitwhen Y == 18
        
            loop
            exitwhen X == 10
                if RectContainsCoords(Field[X][Y], x, y) == true then
                    set Tile_Yellow[X][Y] = d
                endif
                set X = X+1
            endloop
            set X = 0
            set Y = Y+1
        endloop   
    endif
endfunction

private function Init takes nothing returns nothing

    set Field[5][0] = gg_rct_Wizard_North
    //////////////////////////
    set Field[3][1] = gg_rct_A3
    set Field[4][1] = gg_rct_A4
    set Field[5][1] = gg_rct_A5
    set Field[6][1] = gg_rct_A6
    set Field[7][1] = gg_rct_A7
    //////////////////////////
    set Field[3][2] = gg_rct_B3
    set Field[4][2] = gg_rct_B4
    set Field[5][2] = gg_rct_B5
    set Field[6][2] = gg_rct_B6
    set Field[7][2] = gg_rct_B7
    //////////////////////////
    set Field[3][3] = gg_rct_C3
    set Field[4][3] = gg_rct_C4
    set Field[5][3] = gg_rct_C5
    set Field[6][3] = gg_rct_C6
    set Field[7][3] = gg_rct_C7
    //////////////////////////
    set Field[1][4] = gg_rct_D1
    set Field[2][4] = gg_rct_D2
    set Field[3][4] = gg_rct_D3
    set Field[4][4] = gg_rct_D4
    set Field[5][4] = gg_rct_D5
    set Field[6][4] = gg_rct_D6
    set Field[7][4] = gg_rct_D7
    set Field[8][4] = gg_rct_D8
    set Field[9][4] = gg_rct_D9
    //////////////////////////
    set Field[1][5] = gg_rct_E1
    set Field[2][5] = gg_rct_E2
    set Field[3][5] = gg_rct_E3
    set Field[4][5] = gg_rct_E4
    set Field[5][5] = gg_rct_E5
    set Field[6][5] = gg_rct_E6
    set Field[7][5] = gg_rct_E7
    set Field[8][5] = gg_rct_E8
    set Field[9][5] = gg_rct_E9
    //////////////////////////
    set Field[1][6] = gg_rct_F1
    set Field[2][6] = gg_rct_F2
    set Field[3][6] = gg_rct_F3
    set Field[4][6] = gg_rct_F4
    set Field[5][6] = gg_rct_F5
    set Field[6][6] = gg_rct_F6
    set Field[7][6] = gg_rct_F7
    set Field[8][6] = gg_rct_F8
    set Field[9][6] = gg_rct_F9
    //////////////////////////
    set Field[1][7] = gg_rct_G1
    set Field[2][7] = gg_rct_G2
    set Field[3][7] = gg_rct_G3
    set Field[4][7] = gg_rct_G4
    set Field[5][7] = gg_rct_G5
    set Field[6][7] = gg_rct_G6
    set Field[7][7] = gg_rct_G7
    set Field[8][7] = gg_rct_G8
    set Field[9][7] = gg_rct_G9
    //////////////////////////
    set Field[1][8] = gg_rct_H1
    set Field[2][8] = gg_rct_H2
    set Field[3][8] = gg_rct_H3
    set Field[4][8] = gg_rct_H4
    set Field[5][8] = gg_rct_H5
    set Field[6][8] = gg_rct_H6
    set Field[7][8] = gg_rct_H7
    set Field[8][8] = gg_rct_H8
    set Field[9][8] = gg_rct_H9
    //////////////////////////
    set Field[1][9] = gg_rct_I1
    set Field[2][9] = gg_rct_I2
    set Field[3][9] = gg_rct_I3
    set Field[4][9] = gg_rct_I4
    set Field[5][9] = gg_rct_I5
    set Field[6][9] = gg_rct_I6
    set Field[7][9] = gg_rct_I7
    set Field[8][9] = gg_rct_I8
    set Field[9][9] = gg_rct_I9
    //////////////////////////
    set Field[1][10] = gg_rct_J1
    set Field[2][10] = gg_rct_J2
    set Field[3][10] = gg_rct_J3
    set Field[4][10] = gg_rct_J4
    set Field[5][10] = gg_rct_J5
    set Field[6][10] = gg_rct_J6
    set Field[7][10] = gg_rct_J7
    set Field[8][10] = gg_rct_J8
    set Field[9][10] = gg_rct_J9
    //////////////////////////
    set Field[1][11] = gg_rct_K1
    set Field[2][11] = gg_rct_K2
    set Field[3][11] = gg_rct_K3
    set Field[4][11] = gg_rct_K4
    set Field[5][11] = gg_rct_K5
    set Field[6][11] = gg_rct_K6
    set Field[7][11] = gg_rct_K7
    set Field[8][11] = gg_rct_K8
    set Field[9][11] = gg_rct_K9
    //////////////////////////
    set Field[1][12] = gg_rct_L1
    set Field[2][12] = gg_rct_L2
    set Field[3][12] = gg_rct_L3
    set Field[4][12] = gg_rct_L4
    set Field[5][12] = gg_rct_L5
    set Field[6][12] = gg_rct_L6
    set Field[7][12] = gg_rct_L7
    set Field[8][12] = gg_rct_L8
    set Field[9][12] = gg_rct_L9
    //////////////////////////
    set Field[1][13] = gg_rct_M1
    set Field[2][13] = gg_rct_M2
    set Field[3][13] = gg_rct_M3
    set Field[4][13] = gg_rct_M4
    set Field[5][13] = gg_rct_M5
    set Field[6][13] = gg_rct_M6
    set Field[7][13] = gg_rct_M7
    set Field[8][13] = gg_rct_M8
    set Field[9][13] = gg_rct_M9
    //////////////////////////
    set Field[3][14] = gg_rct_N3
    set Field[4][14] = gg_rct_N4
    set Field[5][14] = gg_rct_N5
    set Field[6][14] = gg_rct_N6
    set Field[7][14] = gg_rct_N7
    //////////////////////////
    set Field[3][15] = gg_rct_O3
    set Field[4][15] = gg_rct_O4
    set Field[5][15] = gg_rct_O5
    set Field[6][15] = gg_rct_O6
    set Field[7][15] = gg_rct_O7
    //////////////////////////
    set Field[3][16] = gg_rct_P3
    set Field[4][16] = gg_rct_P4
    set Field[5][16] = gg_rct_P5
    set Field[6][16] = gg_rct_P6
    set Field[7][16] = gg_rct_P7
    //////////////////////////
    set Field[5][17] = gg_rct_Wizard_South
    
    call EnumDestructablesInRect(gg_rct_GameField, null, function TileCreation)

endfunction 
endscope

JASS:
scope Selection initializer OnInit

function OnSelect takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local player p = GetTriggerPlayer()
    local integer x = 0
    local integer y = 1
    local integer X
    local integer Y
    
    if GetOwningPlayer(u) == p then
        /////Tile Colors/////
        loop
        exitwhen y == 18
        
            loop
            exitwhen x == 10
                ///call ShowDestructable(Tile_Brown[x][y], false)
                call ShowDestructable(Tile_Green[x][y], false)
                call ShowDestructable(Tile_Yellow[x][y], false)
                call ShowDestructable(Tile_Red[x][y], true)
                if RectContainsUnit(Field[x][y], u) == true then
                    set X = x
                    set Y = y
                endif
                set x = x+1
            endloop
            set x = 0
            set y = y+1
        endloop
        
        call ShowDestructable(Tile_Red[X][Y], false)
        call ShowDestructable(Tile_Red[X-1][Y], false)
        call ShowDestructable(Tile_Red[X+1][Y], false)
        call ShowDestructable(Tile_Red[X][Y-1], false)
        call ShowDestructable(Tile_Red[X][Y+1], false)
        call ShowDestructable(Tile_Yellow[X][Y], true)
        call ShowDestructable(Tile_Green[X-1][Y], true)
        call ShowDestructable(Tile_Green[X+1][Y], true)
        call ShowDestructable(Tile_Green[X][Y-1], true)
        call ShowDestructable(Tile_Green[X][Y+1], true)
    

    endif
endfunction

function OnDeselect takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local player p = GetTriggerPlayer()
    local integer x = 0
    local integer y = 1
    local integer X
    local integer Y
    
    if GetOwningPlayer(u) == p then
        loop
        exitwhen y == 18
        
            loop
            exitwhen x == 10
                call ShowDestructable(Tile_Red[x][y], false)
                call ShowDestructable(Tile_Yellow[x][y], false)
                call ShowDestructable(Tile_Green[x][y], false)
                ///call ShowDestructable(Tile_Brown[x][y], true)
                if RectContainsUnit(Field[x][y], u) == true then
                    set X = x
                    set Y = y
                endif
                set x = x+1
            endloop
            set x = 0
            set y = y+1
        endloop
        
    endif
endfunction

private function OnInit takes nothing returns nothing
    local trigger trig = CreateTrigger()
    local integer i = 0
    
    loop
    exitwhen i > 11
        call TriggerRegisterPlayerUnitEvent(trig, Player(i), EVENT_PLAYER_UNIT_SELECTED, null)
        set i = i + 1
    endloop
    call TriggerAddAction(trig, function OnSelect)
    
    set trig = CreateTrigger()
    set i = 0
    
    loop
    exitwhen i > 11  
        call TriggerRegisterPlayerUnitEvent(trig, Player(i), EVENT_PLAYER_UNIT_DESELECTED, null)
        set i = i + 1
    endloop
    call TriggerAddAction(trig, function OnDeselect)
    
    set trig = null
endfunction
endscope
 
Level 19
Joined
Oct 12, 2007
Messages
1,821
Alright.
Here's the map right now.
You can type -reg8 or -reg16 to see some of the regiment movement I was trying to make. For the test I used unit custom value, but this will be a new arrayed integer with the unit index as soon as I imput a unit indexer.

But yeah. Test the map and you will see how it should look like ingame.
The water and heightened area's will appear during the gameplay with various abilities and envorinement changing spells.
 

Attachments

  • BoardGame.w3x
    4 MB · Views: 97
Here you go, I used units to make example as fast as possible.
Fallowing same analogy you could make it for anything you want.
You can even define functions for different units so they can go 2 fields in any direction or move by diagonal etc etc.

I forgot to write in code SetUnitX/Y won't work for building while SetUnitPosition do.

oh below and above are reversed ^_^, but it works because you still use both :)
 

Attachments

  • BoardGame.w3x
    4 MB · Views: 79
Level 19
Joined
Oct 12, 2007
Messages
1,821
Here you go, I used units to make example as fast as possible.
Fallowing same analogy you could make it for anything you want.
You can even define functions for different units so they can go 2 fields in any direction or move by diagonal etc etc.

I forgot to write in code SetUnitX/Y won't work for building while SetUnitPosition do.

oh below and above are reversed ^_^, but it works because you still use both :)

Ah thanks.
Gonna check it out now.
And yeah I know I reversed the Y, but who cares. This is more logical to me when looking at the map.
 
Level 19
Joined
Oct 12, 2007
Messages
1,821
I worked on it even more, expanded field to 5x5
Added 2 units, each unit has it's own movement shown on selection.
Each unit can move on it's own and so on.

Still the 1 thing bothers me, when 2 units come into same field, I don't want to edit function so I'm trying to find way around.

I see what you did I'm just trying to use your info into the actual playfield. It's quite difficult because I use destructables instead of units because I want to only show colors for the controlling player which means I have to locally hide the colored fields.
I don't know much about hastables myself so I'm trying to understand what they do by looking at what you did.

But the main thing is that units can move 2 steps at once, instead of having to move 2x 1 step. If you know what I mean.
 
Here you go latest version.
I still didn't fixed that error when you leave filed it remain locked as if there is another unit.

EDIT:

Here use this script and test map ;)

JASS:
library FiledLib initializer Init

    globals
        private unit array FIELD[10][10]
        private unit array FIELD_UNIT[10][10]
        private boolean array FIELD_ALLOWED[10][10]
        
        private hashtable HASH = InitHashtable()
        private group G = CreateGroup()
    endglobals
    
    function SetUnitFieldLoc takes unit u, integer i, integer j, boolean move returns nothing
        local integer row = 1
        local integer col = 1
        
        loop
            loop
                set FIELD_ALLOWED[row][col] = false
                call SetUnitColor(FIELD[row][col], PLAYER_COLOR_BROWN)

                set col = col + 1
                exitwhen col > 5
            endloop
            
            set col = 0
            set row = row + 1
            exitwhen row > 5
        endloop

        if FIELD[i][j+1] != null then
            if FIELD_UNIT[i][j+1] == null then
                call SetUnitColor(FIELD[i][j+1], PLAYER_COLOR_GREEN)
                set FIELD_ALLOWED[i][j+1] = true
            else
                call SetUnitColor(FIELD[i][j+1], PLAYER_COLOR_RED)
                set FIELD_ALLOWED[i][j+1] = false
            endif
        endif
        
        if FIELD[i][j+2] != null then
            if FIELD_UNIT[i][j+2] == null then
                call SetUnitColor(FIELD[i][j+2], PLAYER_COLOR_GREEN)
                set FIELD_ALLOWED[i][j+2] = true
            else
                call SetUnitColor(FIELD[i][j+2], PLAYER_COLOR_RED)
                set FIELD_ALLOWED[i][j+2] = false
            endif
        endif
        
        if FIELD[i+1][j] != null then
            if FIELD_UNIT[i+1][j] == null then
                call SetUnitColor(FIELD[i+1][j], PLAYER_COLOR_GREEN)
                set FIELD_ALLOWED[i+1][j] = true
            else
                call SetUnitColor(FIELD[i+1][j], PLAYER_COLOR_RED)
                set FIELD_ALLOWED[i+1][j] = false
            endif
        endif
        
        if FIELD[i+2][j] != null then
            if FIELD_UNIT[i+2][j] == null then
                call SetUnitColor(FIELD[i+2][j], PLAYER_COLOR_GREEN)
                set FIELD_ALLOWED[i+2][j] = true
            else
                call SetUnitColor(FIELD[i+2][j], PLAYER_COLOR_RED)
                set FIELD_ALLOWED[i+2][j] = false
            endif
        endif
        
        if FIELD[i][j-1] != null then
            if FIELD_UNIT[i][j-1] == null then
                call SetUnitColor(FIELD[i][j-1], PLAYER_COLOR_GREEN)
                set FIELD_ALLOWED[i][j-1] = true
            else
                call SetUnitColor(FIELD[i][j-1], PLAYER_COLOR_RED)
                set FIELD_ALLOWED[i][j-1] = false
            endif
        endif
        
        if FIELD[i][j-2] != null then
            if FIELD_UNIT[i][j-2] == null then
                call SetUnitColor(FIELD[i][j-2], PLAYER_COLOR_GREEN)
                set FIELD_ALLOWED[i][j-2] = true
            else
                call SetUnitColor(FIELD[i][j-2], PLAYER_COLOR_RED)
                set FIELD_ALLOWED[i][j-2] = false
            endif
        endif
     
        if FIELD[i-1][j] != null then
            if FIELD_UNIT[i-1][j] == null then
                call SetUnitColor(FIELD[i-1][j], PLAYER_COLOR_GREEN)
                set FIELD_ALLOWED[i-1][j] = true
            else
                call SetUnitColor(FIELD[i-1][j], PLAYER_COLOR_RED)
                set FIELD_ALLOWED[i-1][j] = false
            endif
        endif
        
        if FIELD[i-2][j] != null then
            if FIELD_UNIT[i-2][j] == null then
                call SetUnitColor(FIELD[i-2][j], PLAYER_COLOR_GREEN)
                set FIELD_ALLOWED[i-2][j] = true
            else
                call SetUnitColor(FIELD[i-2][j], PLAYER_COLOR_RED)
                set FIELD_ALLOWED[i-2][j] = false
            endif
        endif
        
        if move then
            call SetUnitPosition(u, GetUnitX(FIELD[i][j]), GetUnitY(FIELD[i][j]))
            
            call SaveInteger(HASH, GetHandleId(u), 0, GetHandleId(FIELD[i][j]))
            call SaveInteger(HASH, GetHandleId(u), 1, i)
            call SaveInteger(HASH, GetHandleId(u), 2, j)
            set FIELD_UNIT[i][j] = u
        endif
    endfunction
    
    function TryMove takes nothing returns nothing
        local integer id = GetHandleId(GetSpellTargetUnit())
        local integer i = LoadInteger(HASH, id, 1)
        local integer j = LoadInteger(HASH, id, 2)
        if FIELD_ALLOWED[i][j] then
            set FIELD_UNIT[LoadInteger(HASH, GetHandleId(GetTriggerUnit()), 1)][LoadInteger(HASH, GetHandleId(GetTriggerUnit()), 2)] = null
            call SetUnitFieldLoc(GetTriggerUnit(), i, j, true)
        endif
    endfunction
    
    function ShowFields takes nothing returns nothing
        local integer id = LoadInteger(HASH, GetHandleId(GetTriggerUnit()), 0)
        local integer i = LoadInteger(HASH, id, 1)
        local integer j = LoadInteger(HASH, id, 2)
        call SetUnitFieldLoc(GetTriggerUnit(), i, j, false)
    endfunction
    
    function RegisterField takes integer i, integer j, real x, real y returns nothing
        set FIELD[i][j] = CreateUnit(Player(15), 'ncop', x, y,0)
        call SaveInteger(HASH, GetHandleId(FIELD[i][j]), 1, i)
        call SaveInteger(HASH, GetHandleId(FIELD[i][j]), 2, j)
        
        set FIELD_ALLOWED[i][j] = false
        call SetUnitColor(FIELD[i][j], PLAYER_COLOR_BROWN)
    endfunction
    
    function Init takes nothing returns nothing
        local trigger trig = CreateTrigger()
        
        call RegisterField(1,1, -2880.00, 1472.00)
        call RegisterField(1,2, -2496.00, 1472.00)
        call RegisterField(1,3, -2080.00, 1472.00)
        call RegisterField(1,4, -1696.00, 1472.00)
        call RegisterField(1,5, -1344.00, 1472.00)
        
        call RegisterField(2,1, -2880.00, 1056.00)
        call RegisterField(2,2, -2496.00, 1056.00)
        call RegisterField(2,3, -2080.00, 1056.00)
        call RegisterField(2,4, -1696.00, 1056.00)
        call RegisterField(2,5, -1344.00, 1056.00)
        
        call RegisterField(3,1, -2880.00, 672.00)
        call RegisterField(3,2, -2496.00, 672.00)
        call RegisterField(3,3, -2080.00, 672.00)
        call RegisterField(3,4, -1696.00, 672.00)
        call RegisterField(3,5, -1344.00, 672.00)
        
        call RegisterField(4,1, -2880.00, 288.00)
        call RegisterField(4,2, -2496.00, 288.00)
        call RegisterField(4,3, -2080.00, 288.00)
        call RegisterField(4,4, -1696.00, 288.00)
        call RegisterField(4,5, -1344.00, 288.00)
        
        call RegisterField(5,1, -2880.00, -64.00)
        call RegisterField(5,2, -2496.00, -64.00)
        call RegisterField(5,3, -2080.00, -64.00)
        call RegisterField(5,4, -1696.00, -64.00)
        call RegisterField(5,5, -1344.00, -64.00)
     
        //Test Unit and initial shit
        call SetCameraPosition(-2080.00, 704.00)
        call SetUnitFieldLoc(CreateUnit(Player(0), 'nvlk', -2880.00, 1472.00,0), 1,1,true)
        call SetUnitFieldLoc(CreateUnit(Player(0), 'nvlk', -2080.00,  704.00,0), 3,3,true)
        call SetUnitFieldLoc(CreateUnit(Player(0), 'nvlk', -2080.00,  -64.00,0), 5,3,true)
        
        call TriggerRegisterPlayerUnitEvent(trig, Player(0), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        call TriggerAddAction( trig, function TryMove )
        
        set trig = CreateTrigger()
        call TriggerRegisterPlayerUnitEvent(trig, Player(0), EVENT_PLAYER_UNIT_SELECTED, null)
        call TriggerAddAction( trig, function ShowFields )
        set trig = null
    endfunction

endlibrary
 

Attachments

  • BoardGame.w3x
    4 MB · Views: 66
Last edited:
Level 19
Joined
Oct 12, 2007
Messages
1,821
Well Kobas you inspired me to get through this hard shit and I got pretty far already. I'm not sure if I used the same approach as you did, but I ended up with this result as you can see in the picture.

Intelligence displays the amount of steps a unit can take. (Ingame I changed the name to Speed to make sence;-))
As soon as I select a unit it displays me all nearby squares up to 3 steps away and turns those green if there is currently no unit standing on it.

Things I now have to work on are:
- Checking if an enemy unit has been inbetween to prevent the unit from crossing it.
- Checking if the terrain is actually pathable in case it's heightened or water.

Getting better and better.


Here's the code:
JASS:
scope Selection initializer OnInit

function OnSelect takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local player p = GetTriggerPlayer()
    local integer x = 0
    local integer y = 1
    local integer X
    local integer Y
    local integer i = 0
    local integer Speed = GetHeroInt(u,true)
    local integer Steps = Speed
    
    if GetOwningPlayer(u) == p then
        /////Tile Colors/////
        loop
        exitwhen y == 18
        
            loop
            exitwhen x == 10
                ///if GetLocalPlayer() == p then
                    call ShowDestructable(Tile_Green[x][y], false)
                    call ShowDestructable(Tile_Yellow[x][y], false)
                    call ShowDestructable(Tile_Red[x][y], true)
                ///endif
                if RectContainsUnit(Field[x][y], u) == true then
                    set X = x
                    set Y = y
                endif
                set x = x+1
            endloop
            set x = 0
            set y = y+1
        endloop     
       
        set x = 0
        set y = 0
        
        loop
        exitwhen x > Speed
            loop
            exitwhen y > (Speed - x)
                if Field_Path[X+x][Y+y] == 0 then ///Field_Path checks if there's already a unit standing on the field or not
                    call ShowDestructable(Tile_Red[X+x][Y+y], false)
                    call ShowDestructable(Tile_Green[X+x][Y+y], true)
                endif
                if Field_Path[X-x][Y+y] == 0 then
                    call ShowDestructable(Tile_Red[X-x][Y+y], false)
                    call ShowDestructable(Tile_Green[X-x][Y+y], true)
                endif
                if Field_Path[X+x][Y-y] == 0 then
                    call ShowDestructable(Tile_Red[X+x][Y-y], false)
                    call ShowDestructable(Tile_Green[X+x][Y-y], true)
                endif
                if Field_Path[X-x][Y-y] == 0 then
                    call ShowDestructable(Tile_Red[X-x][Y-y], false)
                    call ShowDestructable(Tile_Green[X-x][Y-y], true)
                endif
                set y = y +1
                set Steps = Steps - 1
            endloop
            set Steps = Speed - x
            set y = 0
            set x = x + 1
            set Steps = Steps - 1
        endloop
        /// Center ///
        call ShowDestructable(Tile_Red[X][Y], false)
        call ShowDestructable(Tile_Green[X][Y], false)
        call ShowDestructable(Tile_Yellow[X][Y], true)
        
    endif
endfunction

function OnDeselect takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local player p = GetTriggerPlayer()
    local integer x = 0
    local integer y = 1
    local integer X
    local integer Y
    
    if GetOwningPlayer(u) == p then
        loop
        exitwhen y == 18
        
            loop
            exitwhen x == 10
                call ShowDestructable(Tile_Red[x][y], false)
                call ShowDestructable(Tile_Yellow[x][y], false)
                call ShowDestructable(Tile_Green[x][y], false)
                if RectContainsUnit(Field[x][y], u) == true then
                    set X = x
                    set Y = y
                endif
                set x = x+1
            endloop
            set x = 0
            set y = y+1
        endloop
        
    endif
endfunction

private function OnInit takes nothing returns nothing
    local trigger trig = CreateTrigger()
    local integer i = 0
    
    loop
    exitwhen i > 11
        call TriggerRegisterPlayerUnitEvent(trig, Player(i), EVENT_PLAYER_UNIT_SELECTED, null)
        set i = i + 1
    endloop
    call TriggerAddAction(trig, function OnSelect)
    
    set trig = CreateTrigger()
    set i = 0
    
    loop
    exitwhen i > 11  
        call TriggerRegisterPlayerUnitEvent(trig, Player(i), EVENT_PLAYER_UNIT_DESELECTED, null)
        set i = i + 1
    endloop
    call TriggerAddAction(trig, function OnDeselect)
    
    set trig = null
endfunction
endscope
 

Attachments

  • example.jpg
    example.jpg
    199.3 KB · Views: 100
Status
Not open for further replies.
Top