[Not needed] IsInsideSector(tag,x,y)

Moderator: GZDoom Developers

IsInsideSector(tag,x,y)

Postby hezenbezen » Wed Feb 17, 2021 6:02 am

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)
hezenbezen
 
Joined: 03 Feb 2021

Re: IsInsideSector(tag,x,y)

Postby Player701 » Wed Feb 17, 2021 7:17 am

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 allExpand view
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 allExpand view
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
Player701
 
 
 
Joined: 13 May 2009
Location: Russia
Discord: Player701#8214
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: IsInsideSector(tag,x,y)

Postby Nash » Fri Oct 22, 2021 1:17 am

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.
User avatar
Nash
AKA Nash Muhandes! Twitter/Facebook/Youtube: nashmuhandes
 
 
 
Joined: 27 Oct 2003
Location: Kuala Lumpur, Malaysia
Twitch ID: nashmuhandes
Github ID: nashmuhandes


Return to Closed Feature Suggestions

Who is online

Users browsing this forum: No registered users and 0 guests