Hi all, is there a way to find out if a point is inside a sector (or a set of)? Like function in title.
It's necessary for example when I want to spawn a monster inside some sector with complex boundaries.
(Actually, then I have to take into account things' radiuses, but it's solvable if I place the target sector with an indent inside the necessary sector)
IsInsideSector(tag,x,y)
Moderator: GZDoom Developers
-
-
- Posts: 1551
- Joined: Wed May 13, 2009 3:15 am
- Graphics Processor: nVidia with Vulkan support
Re: IsInsideSector(tag,x,y)
This is already possible in ZScript (and ACS via ScriptCall) by using Level.PointInSector and Level.IsPointInLevel.
Level.PointInSector returns the sector that corresponds to the provided set of XY-coordinates, so if you have a sector reference, you can compare the returned value with it. However, it'd only be a partial solution because from the point of view of the Doom engine, every point in the level corresponds to a certain sector (even those that are "outside" of it, because the engine doesn't care). That's where Level.IsPointInLevel comes in. IIRC, it was created specifically to address the "inside vs outside" problem. You can use IsPointInLevel to make sure your point is actually inside the sector. Note that it accepts a set of XYZ-coordinates instead of just XY; you can use the sector's ceiling or floor planes to get the Z value by calling SecPlane.ZatPoint (not sure if there's an easier way to get the Z value, but this one definitely works in my tests).
TL;DR: Here's some ZScript code that does more or less what you want:
And if you want to find sectors by tag, you can use a SectorTagIterator:
To use this from ACS, please see ScriptCall.
Level.PointInSector returns the sector that corresponds to the provided set of XY-coordinates, so if you have a sector reference, you can compare the returned value with it. However, it'd only be a partial solution because from the point of view of the Doom engine, every point in the level corresponds to a certain sector (even those that are "outside" of it, because the engine doesn't care). That's where Level.IsPointInLevel comes in. IIRC, it was created specifically to address the "inside vs outside" problem. You can use IsPointInLevel to make sure your point is actually inside the sector. Note that it accepts a set of XYZ-coordinates instead of just XY; you can use the sector's ceiling or floor planes to get the Z value by calling SecPlane.ZatPoint (not sure if there's an easier way to get the Z value, but this one definitely works in my tests).
TL;DR: Here's some ZScript code that does more or less what you want:
Code: Select all
class SectorUtil
{
static bool IsInsideSector(Sector sec, double x, double y)
{
let result = Level.PointInSector((x, y));
if (result == sec)
{
double z = sec.floorplane.ZatPoint((x, y));
return Level.IsPointInLevel((x, y, z));
}
return false;
}
}
Code: Select all
class SectorUtil
{
static bool IsInsideSector(Sector sec, double x, double y)
{
let result = Level.PointInSector((x, y));
if (result == sec)
{
double z = sec.floorplane.ZatPoint((x, y));
return Level.IsPointInLevel((x, y, z));
}
return false;
}
static bool IsInsideSectorTag(int tag, double x, double y)
{
let it = Level.CreateSectorTagIterator(tag);
int index;
while ((index = it.Next()) >= 0)
{
if (IsInsideSector(Level.Sectors[index], x, y))
{
return true;
}
}
return false;
}
}
-
-
- Posts: 17360
- Joined: Mon Oct 27, 2003 12:07 am
- Location: Kuala Lumpur, Malaysia
Re: IsInsideSector(tag,x,y)
A ZScript-based solution has already been provided in the 2nd post. In general, ACS functions will no longer be extended unless absolutely necessary. Most advanced use cases in ACS can now be DIY'd with the ScriptCall interface.