Lua function to set an area of the map to block LoS
Moderator: Moderators
Lua function to set an area of the map to block LoS
SetLoSObstacle( number xmin, number ymin, number zmin, number xmax, number ymax, number zmax)
or something like that
I'd really love a way to create a los "wall" without needing to use terrain to do so. Params for the dimensions of the box; it would function just like a chunk of terrain plopped on that spot in terms of LoS. This would let us have map features (or gaia units, I guess) that block LoS, or modify LoS as part of a game mechanic.
or something like that
I'd really love a way to create a los "wall" without needing to use terrain to do so. Params for the dimensions of the box; it would function just like a chunk of terrain plopped on that spot in terms of LoS. This would let us have map features (or gaia units, I guess) that block LoS, or modify LoS as part of a game mechanic.
Re: Lua function to set an area of the map to block LoS
+1 Would be very useful, to set the ground blocking state with code, without having to have a Unit and a Footprint.
Re: Lua function to set an area of the map to block LoS
I'm talking LoS (line of sight), not footprint. As in, I'd like to be able to define an invisible movement-passable 'box' that acts as a hill in regards to unit vision (blocks it). So, for example, a building feature can properly obstruct unit sight.
Re: Lua function to set an area of the map to block LoS
Sounds basically like a sort of layer of invisible terrain sitting on top of the existing terrain map, the sum of which being used for sight-blocking. Not as powerful as Argh's desired direct-manipulation of the LOS map, but good for making features block terrain.
Curious though: what's wrong with using real terrain instead of fake terrain for the blocking features? Assuming this is for features, I mean? Wouldn't that be a better solution? Use a column of terrain inside the feature?
Seems likely that otherwise, you'll run into a limitation - a "oops, our LOS solution doesn't support X".
Of course, then you could think about the extreme case - having a whole secondary "invisible additive terrain" map that is an offset from the existing terrain map, allowing you to create graphical (but fake) bridges by putting the "graphical" terrain below the "invisible/real" terrain, and using features to represent the "invisible/real" terrain. Would work particularly well with VoidWater.
And at this point I'm spitballing in a random direction. Ignore me.
Curious though: what's wrong with using real terrain instead of fake terrain for the blocking features? Assuming this is for features, I mean? Wouldn't that be a better solution? Use a column of terrain inside the feature?
Seems likely that otherwise, you'll run into a limitation - a "oops, our LOS solution doesn't support X".
Of course, then you could think about the extreme case - having a whole secondary "invisible additive terrain" map that is an offset from the existing terrain map, allowing you to create graphical (but fake) bridges by putting the "graphical" terrain below the "invisible/real" terrain, and using features to represent the "invisible/real" terrain. Would work particularly well with VoidWater.
And at this point I'm spitballing in a random direction. Ignore me.
Re: Lua function to set an area of the map to block LoS
Pxtl: no, because that rules out doing things like smoke shells/smoke screens, or pretty much any usage of it as a game mechanic.
Re: Lua function to set an area of the map to block LoS
Whoops, terribly sorry, I am guilty of skimming.I'm talking LoS (line of sight), not footprint. As in, I'd like to be able to define an invisible movement-passable 'box' that acts as a hill in regards to unit vision (blocks it). So, for example, a building feature can properly obstruct unit sight.
Anyhow... yes, we need this. Badly.
Re: Lua function to set an area of the map to block LoS
Oh, right, forgot the smokescreen thing.Nemo wrote:Pxtl: no, because that rules out doing things like smoke shells/smoke screens, or pretty much any usage of it as a game mechanic.
Yeah, now I'm thinking about all the clever stuff you can do with features using invisible-terrain... but yeah, that's neither here nor there. Some sort of mutable-invisible-LOS-blocking-only-landscape seems to be the most direct approach to create the functionality people are talking about WRT smoke and features.
Re: Lua function to set an area of the map to block LoS
And buildings, as well. Right now, Units either can't shoot at buildings at all... or they can, and totally ignore that they're blocking the real LOS of their guns 

- Pressure Line
- Posts: 2283
- Joined: 21 May 2007, 02:09
Re: Lua function to set an area of the map to block LoS
not to mention the utter retarded-looking-ness of putting hills inside building w/respect to plane movement
- thesleepless
- Posts: 417
- Joined: 24 Oct 2007, 04:49
Re: Lua function to set an area of the map to block LoS
+1 could also be used for trees blocking LOS...
perhaps also being able to not 100% block LOS but for eg.
for a forest you can see into it a bit, but a shorter distance than you can normally see.
perhaps also being able to not 100% block LOS but for eg.
for a forest you can see into it a bit, but a shorter distance than you can normally see.
Re: Lua function to set an area of the map to block LoS
Direct manipulation of LOS map isn't a good solution in my opinion. It makes any optimization of LOS code hard because it would be inherently bound to the current implementation using rectangular fixed size grid as LOS map.Pxtl wrote:Sounds basically like a sort of layer of invisible terrain sitting on top of the existing terrain map, the sum of which being used for sight-blocking. Not as powerful as Argh's desired direct-manipulation of the LOS map, but good for making features block terrain.
OTOH it would be easy to add to the engine, but it would be a hell of a lot of work to do anything useful with it. (Need to reimplement the entire LOS raycasting system in Lua, basically, to use it for actually blocking *lines* of sight, as opposed to just adding/removing "sight" on an area of the map.)
Adding an invisible LOS blocking map (that is put on top of the terrain) is a better solution IMO, but have to watch out with performance.
For one, I see no easy solution to calculate which units to recalculate LOS for, when this map is changed. Keep in mind a unit's LOS is not recalculated unless it moves. (disregarding map damage, see below)
Of course a similar thing happens when the map is deformed, but it seems this just recalculates LOS for units directly in the quads (CQuadField quads) in which the deformation happens, which means any unit slightly out of the explosion's radius (outside quads in which explosion happened, to be precise) that had LOS on the changed terrain will keep LOS on it (until it moves), although it possibly shouldn't.
To put up some random ideas:
One way this could be implemented is to use CQuadField::GetQuads with a radius of the unit with largest LOS radius in game, and recalculating LOS for all those units (except maybe those for which it's easily calculated their LOS radius does not overlap with the area that should be updated.)
Another idea could be to just add a callout to force a LOS update for a unit. This forces the game developer to have a thorough understanding of the implementation of this part of the engine tho, if he/she wants to implement a correct and reasonably fast solution, so I'm not really in favor of this.
Or maybe doing a LOS raycast in the opposite direction, from the changed area outwards, up to the largest LOS radius in game, and updating LOS of all units which are "visible" in this raycast.
Another thing which may be disappointing is the resolution of the LOS map; high resolution hurts performance a lot as game developers have figured out, and this feature in particular might need a reasonably high resolution to work as desired. (Or you should just only make mountain sized smoke screens or other LOS obstacles...)
So maybe time to do some research on other ways to calculate LOS accurately and fast with changing terrain (which this feature is, essentially) and moving units...
Re: Lua function to set an area of the map to block LoS
I have an idea.
Instead of raycasting to the terrain, and then updating to see if any Units are within a given LOS square... why not just raycast to all Units in the sphere of the LOS, using the position of the top of the Unit's height as the starting point, and checking versus a simplified version (I'm thinking, 2X smaller, 8-bit, averaged pixels) of the heightmap? I seem to recall reading an article somewhere about doing it with a fast check vs. a voxelized representation of a heightmap, which was really fast, because you're just checking the voxels in range, not the entire mesh.
IOW... getUnitsInSphere... get list... if not on my team or Allied and not already "seen", then do a raycast. It would save a huge number of redundant steps.
After all, the Unit just needs to know what Units it can "see", and that needs to be added to the global "this Unit is visible" list, for weapons that don't raycast, or weapons with an arc (which need to test if they can reach that target, obviously).
We don't need a true terrain LOS system, basically. We just need to know what Units are visible. We aren't hiding terrain, like some engines do, so we don't need to bother with that at all!
Ooh... and that would be a massive cost-savings for World Builder or for Features... because those objects wouldn't need to be updated in LOS, ever- they'd always be on the "seen" list. In fact, the easiest way would be to get the entire list of Units every time the LOS check ran, delete all Unit IDs that are "permanently seen"... and then you're only ever checking against stuff that may or may not be visible, immediately, instead of on a Unit-by-Unit basis. A much shorter, cleaner sort, basically- what's visible to my Team.
Then we just need a special object that will block a raycast, using a cuboid volume, and allow Lua to create and destroy them. Voila, problem solved.
I think that idea would be a lot cheaper than the current system, and would make more sense. We don't need to find a traditional solution to this, since we're not doing traditional "hide the terrain" nonsense. So, let's not bother at all.
Instead of raycasting to the terrain, and then updating to see if any Units are within a given LOS square... why not just raycast to all Units in the sphere of the LOS, using the position of the top of the Unit's height as the starting point, and checking versus a simplified version (I'm thinking, 2X smaller, 8-bit, averaged pixels) of the heightmap? I seem to recall reading an article somewhere about doing it with a fast check vs. a voxelized representation of a heightmap, which was really fast, because you're just checking the voxels in range, not the entire mesh.
IOW... getUnitsInSphere... get list... if not on my team or Allied and not already "seen", then do a raycast. It would save a huge number of redundant steps.
After all, the Unit just needs to know what Units it can "see", and that needs to be added to the global "this Unit is visible" list, for weapons that don't raycast, or weapons with an arc (which need to test if they can reach that target, obviously).
We don't need a true terrain LOS system, basically. We just need to know what Units are visible. We aren't hiding terrain, like some engines do, so we don't need to bother with that at all!
Ooh... and that would be a massive cost-savings for World Builder or for Features... because those objects wouldn't need to be updated in LOS, ever- they'd always be on the "seen" list. In fact, the easiest way would be to get the entire list of Units every time the LOS check ran, delete all Unit IDs that are "permanently seen"... and then you're only ever checking against stuff that may or may not be visible, immediately, instead of on a Unit-by-Unit basis. A much shorter, cleaner sort, basically- what's visible to my Team.
Then we just need a special object that will block a raycast, using a cuboid volume, and allow Lua to create and destroy them. Voila, problem solved.
I think that idea would be a lot cheaper than the current system, and would make more sense. We don't need to find a traditional solution to this, since we're not doing traditional "hide the terrain" nonsense. So, let's not bother at all.
Re: Lua function to set an area of the map to block LoS
Some people would rage when L view isn't present anymore 
But otherwise that would be a good alternate solution yeah, and probably quite good performing too. And, it can be easily optimized by making CQuadField faster (for which there are lots of ready made algorithms available.)
If I find some time I may actually try this.

But otherwise that would be a good alternate solution yeah, and probably quite good performing too. And, it can be easily optimized by making CQuadField faster (for which there are lots of ready made algorithms available.)
If I find some time I may actually try this.
Re: Lua function to set an area of the map to block LoS
I think that that can be faked adequately. Or L view could trigger the old behavior.Some people would rage when L view isn't present anymore
But yeah, I think that this is a very fast solution to this problem, and would greatly speed the game up.
Re: Lua function to set an area of the map to block LoS
So the callout would be something like SetTerrainLOSHeight(x,y,height)?
Re: Lua function to set an area of the map to block LoS
Depends, if LOS is changed like Argh suggested, using plain raycasting between units, it might be very feasible (and even faster) to treat LOS blocking things as real objects, instead of yet another big map. (in particular if the common case is there are no such objects nearby)
So it could be e.g. Spring.CreateLosObstacle(x, y, z, radius)
(and accompanying Spring.DestroyLosObstacle(id) of course.)
So it could be e.g. Spring.CreateLosObstacle(x, y, z, radius)
(and accompanying Spring.DestroyLosObstacle(id) of course.)
- thesleepless
- Posts: 417
- Joined: 24 Oct 2007, 04:49
Re: Lua function to set an area of the map to block LoS
sounds pretty good Tobi,
any ideas on how to work in a turn based strategy style forest LOS where when you're in a forest you can see a short distance, and from outside the forest you can see a short distance into it, but normally elsewhere.
so you can sneak a force through the forest without being seen from outside where you normally would be visible if it wasnt for the forest.
any ideas on how to work in a turn based strategy style forest LOS where when you're in a forest you can see a short distance, and from outside the forest you can see a short distance into it, but normally elsewhere.
so you can sneak a force through the forest without being seen from outside where you normally would be visible if it wasnt for the forest.
Re: Lua function to set an area of the map to block LoS
When using real raycasting you could, instead of a fixed radius, just give the ray a starting "energy" and lookup what to subtract from this every step, based on some map, and have the ray only continue until it's energy reaches zero.
In your example, forest tiles would subtract more then non-forest tiles, so in effect you'd be able to see less far in the forest then outside the forest.
This does remove possibility for certain optimizations tho. (E.g. line<->sphere intersection is just a single calculation, while with the algorithm outlined above there needs to be a loop stepping over all tiles along the ray.)
In your example, forest tiles would subtract more then non-forest tiles, so in effect you'd be able to see less far in the forest then outside the forest.
This does remove possibility for certain optimizations tho. (E.g. line<->sphere intersection is just a single calculation, while with the algorithm outlined above there needs to be a loop stepping over all tiles along the ray.)
Re: Lua function to set an area of the map to block LoS
doing a raycast for each unit each frame for rendering update is just insane :x (not to forget features etc.)
Re: Lua function to set an area of the map to block LoS
No one suggested doing a raycast for each unit in each frame.
(Note though that for moving units that is actually what is happening in the current code; if the LOS radius of a unit is bigger then 16/(2*pi) LOS squares, then for a moving unit every SlowUpdate more then 16 raycasts are performed [to update the LOS map], so on average more then 1 raycast per moving unit per frame.)
There's not much need to do it more often then current LOS update, ie. once every SlowUpdate, and I bet a lot of optimizations are possible to make the raycast very cheap. (quadtree for terrain so huge flat areas only need to be checked once, for example)
(Note though that for moving units that is actually what is happening in the current code; if the LOS radius of a unit is bigger then 16/(2*pi) LOS squares, then for a moving unit every SlowUpdate more then 16 raycasts are performed [to update the LOS map], so on average more then 1 raycast per moving unit per frame.)
There's not much need to do it more often then current LOS update, ie. once every SlowUpdate, and I bet a lot of optimizations are possible to make the raycast very cheap. (quadtree for terrain so huge flat areas only need to be checked once, for example)