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!
So I want my game to behave like warcraft 2. I want the units to snap to a grid ingame.
I made my footman 2x2, my farms 4x4, my barracks 6x6, and my town hall 8x8. The buildings work great and they are placing perfectly. They make a nice grid and are good for walling in. The units when I place them in the campaign editor also work perfectly. The problem is ingame the units dont line up like I want them to. They are all over the place. I want them to work like they do in the editor, where they occupy a tile on the grid and snap to it.
Example.
So in game it works great for the buildings, they stick to the grid. The units however seem to make their own rules. They stop anywhere and their selection squares over lap and all kinds of problems. When i place/move them in the editor it works perfectly, just ingame is the problem. Anyone know how i can make it more of a "occupy a tile" Type movement ingame? I tried making my units based of guard towers and game them movement, it doesn't work any better than using just normal units, and the pathing is terrible.
I believe the WC3 engine uses circle point collision for units no matter how you set them up. There's also a small amount of "allowed overlap", or whatever you would call it, that you can see units doing when figuring out movement pathing in groups so they don't jitter in place at hard edges (clarification: they do still do this since the engine is dated; but this is pathing 101). I don't think this value can be controlled and is hard coded into the engine.
I think a more advanced solution is required for forcing them to occupy cells (unless someone else knows an editor exploit).
Seems like you want units to behave like buildings !
What @Planetary said is true but you'll notice buildings with proper pathing map and collision do not have that unit "limitation".
Only way I can thing of is make units buildings with no ground texture (but keep the pathing map).
Then give them a hidden Root ability so that they can face their targets, and unfortunately you might want to simulate the movement with triggers...
Hehe... no actually you didn't ^^
You gave them movement, and once you give them movement you lose the building properties.
Root can allow buildings to face their targets, but you must not use uproot to move the "building units", because they are not buildings anymore.
What you need to do is keep your unit as buildings, give them a hidden root to let them face targets. They must not have a ground texture of course, and when you need to move the units, you need to use the native native SetUnitPosition takes unit whichUnit, real newX, real newY returns nothing.
I understand that the problem would indeed be the movement simulation, but as your units would remain as buildings, everything else would work as intended.
EDIT : how did you actually give them "movement" by the way ?
EDIT 2: simulating movement with triggers could be worse thinking about it as you would also need to handle collision.....
1) selection graphics (circles) are a UI representation, they don't represent actual collision size
2) I went in to clarify unit collision and it does maintain square collision rules, the problem is that you want units to move to a grid location right?
2b) if 2) is true, you are looking at a custom solution where you would split the entire map into cells and determine the center of each cell that a unit should be in when they are issued an order
I see what you mean.
About the cells, I am unsure.
In my TD (link in my signature), I have a base tower that has no movement or attack.
But it has a spell that builds identical towers in a line until the targeted point. If i would move the tower to each new position instead of creating a tower, it would actually simulate the movement, respecting the size of the "cells" but without splitting the map in cells directly.
I can easily pull out my "Build blocking towers wall" function but it is in Jass as I don't use GUI.
Yes I was looking the cells and thinking the same thing. I drew some regions to simiulate cells, but I haven't had a chance to go very far with that. How would I order a unit to the centre of a region when it say, stops on a region? The unit enters a region trigger won't work if the whole map is different regions movement wouldn't work.
In Jass the GUI Regions are actually Rects, and you can create local rects, and add them to a local region and then dynamically create a trigger that checks if a unit enters this region.
Only issue in that case would be to destroy the rect once not needed anymore.
Other possibility to simulate a movement in a direction with buildings using something like my build wall function i mentioned earlier. The only problem it has is the movement would be instant. To make it move at a normal speed following the cells, all we'd need is create a repeatable timer.When the timer expires, move the unit to the new position, then start the timer again, until the destination is reached.
This of course would require to save some values in a hashtable using the handle id of the timer as a parent key. But this would be doable.
EDIT :
If anyone is interested and can read Jass, here is my Build Wall ability trigger :
JASS:
function BuildTheWall takes nothing returns boolean
local unit blockingTower=null
local unit newTower=null
local player owner=null
local integer goldLeft
local real oX
local real oY
local real tX
local real tY
local real incX
local real incY
local real sX
local real sY
local real angle
if (GetSpellAbilityId() == BBTWID) then
set blockingTower=GetSpellAbilityUnit()
set owner=GetOwningPlayer(blockingTower)
set goldLeft=GetPlayerState(owner, PLAYER_STATE_RESOURCE_GOLD)
set oX=GetUnitX(blockingTower)
set oY=GetUnitY(blockingTower)
set blockingTower=null
set tX=GetSpellTargetX()
set tY=GetSpellTargetY()
loop
set angle=bj_RADTODEG*Atan2(tY-oY,tX-oX)
if (angle<0) then
set angle=angle+360.00
endif
set angle=Round(angle/22.50)*22.50
if (angle>=0.00) and (angle<=180.00) then
set sY=1.00
else
set sY=- 1.00
endif
if ((angle>=270.00) and (angle<=360.00)) or ((angle>=0) and (angle<=90.00)) then
set sX=1.00
else
set sX=- 1.00
endif
if (angle != 180.00) then
set angle=ModuloReal(angle, 180.00)
endif
if (angle==0.00) or (angle==180.00) then
set incX=WallSize
set incY=0
endif
if (angle==22.50) or (angle==157.50) then
set incX=WallSize
set incY=WallSize / 2.00
endif
if (angle==45.00) or (angle==135.00) then
set incX=WallSize
set incY=WallSize
endif
if (angle==67.5) or (angle==112.50) then
set incX=WallSize / 2.00
set incY=WallSize
endif
if (angle==90) then
set incX=0
set incY=WallSize
endif
exitwhen ((tX-oX)*(tX-oX)+(tY-oY)*(tY-oY)<WallSize*WallSize) or (goldLeft<1)
set oX=oX+sX*incX
set oY=oY+sY*incY
set newTower=null
set newTower=CreateUnit(owner, BlockingID, oX, oY, 270.00)
call AddUnitToStock(newTower, SellID, 1, 1)
call LinkAround(newTower , true)
if (Abs(oX-GetUnitX(newTower))>16.00) or (Abs(oY-GetUnitY(newTower))>16.00) then
call LinkAround(newTower , false)
call KillUnit(newTower)
call RemoveUnit(newTower)
else
set goldLeft=goldLeft-1
endif
set newTower=null
endloop
call SetPlayerState(owner, PLAYER_STATE_RESOURCE_GOLD, goldLeft)
set owner=null
endif
return false
endfunction
function BuildBlockingTowersWall takes nothing returns nothing
local integer i=0
local trigger buildBlockingTowersWall=CreateTrigger()
loop
if ((GetPlayerSlotState(Player(i))==PLAYER_SLOT_STATE_PLAYING)) then
call TriggerRegisterPlayerUnitEvent(buildBlockingTowersWall, Player(i), EVENT_PLAYER_UNIT_SPELL_CAST, null)
endif
set i=i+1
exitwhen i>3
endloop
call TriggerAddCondition(buildBlockingTowersWall, function BuildTheWall)
set buildBlockingTowersWall=null
endfunction
Notes :
- BBTWID is the global storing my wall ability ID, it could be replaced with a dummy "move" ability
- WallSize is a global real, I have set this value to 128.0
Note it stops building when the distance with the target is low enough or when the gold is zero, so that gold part needs to be removed.
So if instead of placing a tower at each new position, one could just store the positions in two local arrays for the coordinates like MoveX and MoveY, and putting 0 as last value when the target is reached, then create a repeatable timer, store the 2 arrays in a hashtable with the timer handle id as parent key and 0 & 1 as child keys, you can also store the unit with the child key 2.
Then have a trigger that reacts to the expiration o that timer, get the parent key back using the expired timer handle id, and as the child keys for the 2 arrays and the unit are 0, 1 and 2, you can retrieve them from the hashtable and move the unit to the next position at MovX, MoveY.
I just realized that for this we would also need to save the index of the current move too.
Once unit is moved, we restart the timer until the coordinates are 0 (we could chose other values outside of the map in case there would be a risk to conflict with map center.
Anyways, I know this sounds really complicated, but I know it would work.
IF anyone has clever ideas for simpler ways to simulate a movement that would allow units to remain buildings, feel free to suggest it.
Yes I was looking the cells and thinking the same thing. I drew some regions to simiulate cells, but I haven't had a chance to go very far with that. How would I order a unit to the centre of a region when it say, stops on a region? The unit enters a region trigger won't work if the whole map is different regions movement wouldn't work.
This is a pretty beefy feature if you're not used to programmatic systems in game engines.
You would not manually use regions as that'd be the most painful thing ever. You'd run a loop through the map after fetching its maximum size in Cartesian coordinates and generate a table or hashtable of cell data. After that, you'd have helper functions that sort out wherever a unit order is being issued (check X,Y of a region, see which "cell" it is in, then calculate the "new center location" of that cell).
@Planetary : honestly, this would really be too intensive for the game engine. cell data must not be stored.
Thats why I was suggesting my method, although it is not that easy to program, and would even maybe be impossible in GUI.
But I will be honest :
If you want to make anything advanced in mapmaking, you should really give up GUI asap unless you want to drive yourself crazy.
GUI is nice when you want to do clever things that do not require too much brainstorming, but once you want the game to react differently than what it was designed for, GUI becomes a heavy weight that will stop you at every attempt.
@Planetary : honestly, this would really be too intensive for the game engine. cell data must not be stored.
Thats why I was suggesting my method, although it is not that easy to program, and would even maybe be impossible in GUI.
But I will be honest :
If you want to make anything advanced in mapmaking, you should really give up GUI asap unless you want to drive yourself crazy.
GUI is nice when you want to do clever things that do not require too much brainstorming, but once you want the game to react differently than what it was designed for, GUI becomes a heavy weight that will stop you at every attempt.
I thought about it a bit more and I think you could simulate what a cell is based on coordinates since you already know the default offset, and you wouldn't have to store any data.
But, I doubt this project is big enough to warrant such a complex system. I would honestly just work with the default unit collision at this point.
Yes thats true, knowing the offset would allow to calculate each coordinate on the fly. Hadn't thought of that.
I think it could be implemented with Jass (or LUA ^^). I am not sure unit collision would suffice as they'd still move smoothly between two cells instead of jumping from one cell to the other.
Anyways, if OP wants to make this happen, it will require appropriate decisions or rather appropriate choices ^^
I thought about it a bit more and I think you could simulate what a cell is based on coordinates since you already know the default offset, and you wouldn't have to store any data.
But, I doubt this project is big enough to warrant such a complex system. I would honestly just work with the default unit collision at this point.
This is a little over my head. I understand what your talking about but I dont understand how to implement this. This is a good solution I think. Can you help with this please? Or point me in the right direction?
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.