IsInsideSector(tag,x,y)

Moderator: GZDoom Developers

Post Reply
hezenbezen
Posts: 15
Joined: Wed Feb 03, 2021 3:39 am

IsInsideSector(tag,x,y)

Post by hezenbezen »

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)
User avatar
Player701
 
 
Posts: 1640
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: IsInsideSector(tag,x,y)

Post by Player701 »

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:

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;
    }
}
And if you want to find sectors by tag, you can use a SectorTagIterator:

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;
    }
}
To use this from ACS, please see ScriptCall.
User avatar
Nash
 
 
Posts: 17439
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: IsInsideSector(tag,x,y)

Post by Nash »

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.
Post Reply

Return to “Closed Feature Suggestions [GZDoom]”