Raised This Month: $32 Target: $400
 8% 

Teleporting Player Check "Non-Stuck"


Post New Thread Reply   
 
Thread Tools Display Modes
backwards
AlliedModders Donor
Join Date: Feb 2014
Location: USA
Old 04-29-2019 , 19:01   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #11

Quote:
Originally Posted by TheDS1337 View Post
if the position you're questioning is outside the playable map then you'll how to use the function multiple times and I tried detecting if a certain point is inside/outside the playable map but it didn't work... hopefully someone will let us know.
You can call this function from CBaseEdict -> AreaNum()

https://github.com/VSES/SourceEngine...c/edict.h#L370

https://github.com/VSES/SourceEngine...roperty.h#L251

This will return an index value of the calculated PVS box an entity is currently in. These are sections in maps that aren't visible to each other and prevent ents from other pvs's from being networked frequently or at all. This reduces cpu load and networking along with preventing stuff like wallhack/esp from functioning. This function simply computes which PVS box the entity is in and if he's not in one it will return 0. This is one method to detect if the point is outside the skybox. You can move the client and check this within the same frame, if it fails to 0 you can teleport him back and the client wont see anything on his end.


You could use the function from CBaseEntity -> DetectInSkybox():

https://github.com/VSES/SourceEngine...tity.cpp#L3495

This will look through a group of cameras(?) and try to find the skybox for that area(?).
I'm unsure about how this one's working exactly as I just stumbled onto it but if it's called every time an entity is teleported or frequently you may be able to use this. It sets an effect flag on the entity for EFL_IN_SKYBOX based on the function being called.

I believe it would be testable by doing something like this:
PHP Code:
#define EFL_IN_SKYBOX (1<<17)

bool IsInSkybox(entity)
{
    return (
GetEntProp(entityProp_Data"m_iEFlags") & EFL_IN_SKYBOX);

Alternativly if you don't want to call internal functions and want a quick test that should work out on all maps that have sealed skyboxs 99% of the time. Make 6 raytraces from the point you want to check going in the forward direction of all 6 sides of a cube (forward, backward, up, down, left, right). In theory all 6 rays should hit something before they timeout from a very far distance if the point is within the level. Otherwise you can assum the void is visible from that point and not a valid teleportation location.



PHP Code:
#include <sourcemod>
#include <smlib/effects>

new beammdlhalomdl;

new 
Float:fAngle[6][3] = {{1.00.00.0}, {-1.0,0.0,0.0}, {0.0,1.0,0.0}, {0.0,-1.0,0.0}, {0.0,0.0,1.0}, {0.0,0.0,-1.0}};

public 
OnPluginStart()
{
    
RegConsoleCmd("sm_testpoint1"TestPoint1_CMD);
    
RegConsoleCmd("sm_testmypoint"TestMyPoint_CMD);
}

public 
OnMapStart()
{
    
beammdl PrecacheModel("materials/sprites/laserbeam.vmt"true);
    
halomdl PrecacheModel("materials/sprites/halo01.vmt");
}

public 
Action TestPoint1_CMD(int clientint args
{
    
float fTestSpot[3] = {274.02204.0, -14.0};
    
    if(
IsPointInLevel(fTestSpot))
        
PrintToChat(client"Your point is inside the map.");
    else
        
PrintToChat(client"Your point is outside of the map.");
}

public 
Action TestMyPoint_CMD(int clientint args
{
    
float fPlayerPos[3];
    
    
GetClientEyePosition(clientfPlayerPos);
    
    if(
IsPointInLevel(fPlayerPos))
        
PrintToChat(client"Your point is inside the map.");
    else
        
PrintToChat(client"Your point is outside of the map.");
}

bool IsPointInLevel(float fPoint[3])
{
    new 
Hits 0;
     
    
float fMin[3] = {-2.5, -2.5, -2.5};
    
float fMax[3] = {2.52.52.5};
                
    
AddVectors(fPointfMinfMin);
    
AddVectors(fPointfMaxfMax);
        
    
Effect_DrawBeamBoxToAll(fMinfMaxbeammdlhalomdl03010.01.01.021.0, { 255255255255 });
    
    for(
int c 0;6c++)
    {
        
float fEndPoint[3];
        
        for(
int i 0;3i++)
            
fEndPoint[i] = fPoint[i] + (fAngle[c][i] * 8192.0)
        
        
TR_TraceRayFilter(fPointfEndPointMASK_SHOTRayType_EndPointTraceRay); 
        
        if(
TR_GetEntityIndex(INVALID_HANDLE) != -1)
        {
            
float fRealEndPos[3];
            
TR_GetEndPosition(fRealEndPos);
            
            
TE_SetupBeamPoints(fPointfRealEndPosbeammdl00010.01.01.010.0, {25500255}, 1);
            
Hits++;
        }
        else
        {    
            
TE_SetupBeamPoints(fPointfEndPointbeammdl00010.01.01.010.0, {02550255}, 1);
        }
        
        
TE_SendToAll();
    }
    
    return (
Hits == 6);
}

public 
bool:TraceRay(entitymask)
{
    return 
true;

__________________
I highly recommend joining the SourceMod Discord Server for real time support.

Last edited by backwards; 04-29-2019 at 21:12. Reason: source and screenshot
backwards is offline
TheDS1337
Veteran Member
Join Date: Jun 2012
Old 04-30-2019 , 15:18   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #12

Quote:
Originally Posted by scorpius2k1 View Post
EDIT: Error fixed. TheDS1337's script needs compiled against latest #include files from the SourceMod git repo. As of this post, stable version (1.9) does not yet include 'TR_GetStartPosition'



Thanks, that fixed the warning but the error is still present regardless of including 'sdktools' or 'sdktools_trace.inc' which has that specific native reference.

Unfortunately, in my previous post I had tried that already:


I used TheDS1337's original code they posted above, which also has...

PHP Code:
#include <sdktools> 
...already, but still get the error. Weird!
Sorry, didn't know it wasn't included before.. I mean even the signature of TR_GetStartPosition compared to TR_GetEndPosition seemed odd.
PHP Code:
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>

/*
    X: 32.000000Y: 32.000000Z: 72.000000
    Mins[0]: -16.000000, Mins[1]: -16.000000, Mins[2]: 0.000000
    Maxs[0]: 16.000000, Maxs[1]: 16.000000, Maxs[2]: 72.000000
    Min/Maxs: 85.041168
    
    Min/Origin: 2477.570312
    Max/Origin: 2446.154785
*/

#pragma newdecls required

#define PLAYER_WIDTH 32.0
#define PLAYER_HEIGHT 72.0

int g_LaserBeam;

public 
void OnPluginStart()
{
}

public 
void OnMapStart()
{
    
g_LaserBeam PrecacheModel("materials/sprites/laserbeam.vmt"true);
}

public 
void OnClientSayCommand_Post(int client, const char[] command, const char[] sArgs)
{
    if( !
IsPlayerAlive(client) )
    {
        return;
    }
    
    if( 
strcmp(sArgs"check_fitness"false) == )
    {
        
float oldPos[3], newPos[3];    
        
GetClientAbsOrigin(clientoldPos);
        
AddVectors(oldPos, {0.00.025.0}, oldPos);    // Just elevating it a little bit, this fixes some problems with the trace collision for some reason
        
VectorCopy(oldPosnewPos);                        // CanPlayerFit fct is gonna modify the origin we give it, so we better store the old one for comparasion purposes
                
        
if( CanPlayerFit(clientnewPos) && !VectorsEqual(oldPosnewPos) )
        {
            
PrintToChat(client"Teleported from %f %f %f to %f %f %f"oldPos[0], oldPos[1], oldPos[2], newPos[0], newPos[1], newPos[2]);
            
PrintToChat(client"Distance new/old: %f"GetVectorDistance(oldPosnewPos));
            
            
TeleportEntity(clientnewPosNULL_VECTORNULL_VECTOR);
        }
    }
}

bool CanPlayerFit(int clientfloat pos[3])
{
    
float radius SquareRoot(* (PLAYER_WIDTH PLAYER_WIDTH) +  PLAYER_HEIGHT PLAYER_HEIGHT);
    
    
float heads[4][3];
    
    
heads[0][0] = pos[0] + PLAYER_WIDTH 2;
    
heads[0][1] = pos[1] + PLAYER_WIDTH 2;
    
heads[0][2] = pos[2] + PLAYER_HEIGHT 2;
    
    
heads[1][0] = pos[0] - PLAYER_WIDTH 2;
    
heads[1][1] = pos[1] - PLAYER_WIDTH 2;
    
heads[1][2] = pos[2] - PLAYER_HEIGHT 2;
    
    
heads[2][0] = pos[0] + PLAYER_WIDTH 2;
    
heads[2][1] = pos[1] - PLAYER_WIDTH 2;
    
heads[2][2] = pos[2] - PLAYER_HEIGHT 2;
    
    
heads[3][0] = pos[0] - PLAYER_WIDTH 2;
    
heads[3][1] = pos[1] + PLAYER_WIDTH 2;
    
heads[3][2] = pos[2] + PLAYER_HEIGHT 2;        
    
    
TE_SetupBeamPoints(heads[0], heads[1], g_LaserBeam00030.02.02.010.0, {00255255}, 15);  
    
TE_SendToAll();    
    
    
TE_SetupBeamPoints(heads[3], heads[2], g_LaserBeam00030.02.02.010.0, {25500255}, 15);  
    
TE_SendToAll();
    
    
int i 0trials 0dirSelection = -1;
    
    
Handle ray INVALID_HANDLE;    
    
float endPos[3], dir[3];    
    
float dist 0.0lastDist 0.0;
    
    do
    {        
        
PrintToChat(client"Trial: %d"trials 1);
        
        
SubtractVectors(heads[1], heads[0], dir);
        
ray TR_TraceRayFilterEx(heads[0], dirMASK_PLAYERSOLIDRayType_InfiniteCollisionCheckclient);
    
        if( 
ray )
        {
            if( 
TR_DidHit(ray) )
            {
                
TR_GetEndPosition(endPosray);
                                
                if( 
GetVectorDistance(posendPos) > radius )
                {
                    
PrintToChat(client"Point does not belong to %f"radius);
                    
                    
delete ray;
                    return 
true;
                }
                
                if( 
dirSelection == -|| GetRandomInt(03) == )
                {
                    for( 
04i++ )
                    {
                        
dist GetVectorDistance(endPosheads[i]);
                        
                        if( 
== )
                        {
                            
lastDist dist;
                            
dirSelection 0;
                        }
                        else if( 
dist lastDist )
                        {
                            
lastDist dist;
                            
dirSelection i;
                        }
                    }
                }
                
                
TE_SetupBeamPoints(posendPosg_LaserBeam00030.02.02.010.0, {02550255}, 15);  
                
TE_SendToAll();
                
                
SubtractVectors(heads[dirSelection], posdir);                
                
NormalizeVector(dirdir);                
            
                
PrintToChat(client"Point does belong to: %f"radius);
                
                
ScaleVector(dirradius 2.0); 
                
AddVectors(posdirpos);
                
                for( 
04i++ )
                {
                    
AddVectors(heads[i], dirheads[i]);
                }                
            }
            else
            {
                
PrintToChat(client"Trace not hitting it");    
                
                
delete ray;
                return 
false;
            }
        
            
delete ray;
        }        
    } while( ++
trials 1000 )
    
    return 
false;
}

public 
bool CollisionCheck(int entityint contentsMaskany data)
{
    return 
entity != view_as<int> (data);
}

void VectorCopy(float a[3], float b[3])
{
    
b[0] = a[0];
    
b[1] = a[1];
    
b[2] = a[2];
}

bool VectorsEqual(float a[3], float b[3])
{
    return 
a[0] == b[0] && a[1] == b[1] && a[2] == b[2] ? true false;

This should do the same thing.
Quote:
Originally Posted by 1337norway View Post
You can call this function from CBaseEdict -> AreaNum()

https://github.com/VSES/SourceEngine...c/edict.h#L370

https://github.com/VSES/SourceEngine...roperty.h#L251

This will return an index value of the calculated PVS box an entity is currently in. These are sections in maps that aren't visible to each other and prevent ents from other pvs's from being networked frequently or at all. This reduces cpu load and networking along with preventing stuff like wallhack/esp from functioning. This function simply computes which PVS box the entity is in and if he's not in one it will return 0. This is one method to detect if the point is outside the skybox. You can move the client and check this within the same frame, if it fails to 0 you can teleport him back and the client wont see anything on his end.
This seems nice, but I'm not sure if it can be done with SDKTools/Dhooks, looks more like an extension work here.

Quote:
Originally Posted by 1337norway View Post
Alternativly if you don't want to call internal functions and want a quick test that should work out on all maps that have sealed skyboxs 99% of the time. Make 6 raytraces from the point you want to check going in the forward direction of all 6 sides of a cube (forward, backward, up, down, left, right). In theory all 6 rays should hit something before they timeout from a very far distance if the point is within the level. Otherwise you can assum the void is visible from that point and not a valid teleportation location.



PHP Code:
#include <sourcemod>
#include <smlib/effects>

new beammdlhalomdl;

new 
Float:fAngle[6][3] = {{1.00.00.0}, {-1.0,0.0,0.0}, {0.0,1.0,0.0}, {0.0,-1.0,0.0}, {0.0,0.0,1.0}, {0.0,0.0,-1.0}};

public 
OnPluginStart()
{
    
RegConsoleCmd("sm_testpoint1"TestPoint1_CMD);
    
RegConsoleCmd("sm_testmypoint"TestMyPoint_CMD);
}

public 
OnMapStart()
{
    
beammdl PrecacheModel("materials/sprites/laserbeam.vmt"true);
    
halomdl PrecacheModel("materials/sprites/halo01.vmt");
}

public 
Action TestPoint1_CMD(int clientint args
{
    
float fTestSpot[3] = {274.02204.0, -14.0};
    
    if(
IsPointInLevel(fTestSpot))
        
PrintToChat(client"Your point is inside the map.");
    else
        
PrintToChat(client"Your point is outside of the map.");
}

public 
Action TestMyPoint_CMD(int clientint args
{
    
float fPlayerPos[3];
    
    
GetClientEyePosition(clientfPlayerPos);
    
    if(
IsPointInLevel(fPlayerPos))
        
PrintToChat(client"Your point is inside the map.");
    else
        
PrintToChat(client"Your point is outside of the map.");
}

bool IsPointInLevel(float fPoint[3])
{
    new 
Hits 0;
     
    
float fMin[3] = {-2.5, -2.5, -2.5};
    
float fMax[3] = {2.52.52.5};
                
    
AddVectors(fPointfMinfMin);
    
AddVectors(fPointfMaxfMax);
        
    
Effect_DrawBeamBoxToAll(fMinfMaxbeammdlhalomdl03010.01.01.021.0, { 255255255255 });
    
    for(
int c 0;6c++)
    {
        
float fEndPoint[3];
        
        for(
int i 0;3i++)
            
fEndPoint[i] = fPoint[i] + (fAngle[c][i] * 8192.0)
        
        
TR_TraceRayFilter(fPointfEndPointMASK_SHOTRayType_EndPointTraceRay); 
        
        if(
TR_GetEntityIndex(INVALID_HANDLE) != -1)
        {
            
float fRealEndPos[3];
            
TR_GetEndPosition(fRealEndPos);
            
            
TE_SetupBeamPoints(fPointfRealEndPosbeammdl00010.01.01.010.0, {25500255}, 1);
            
Hits++;
        }
        else
        {    
            
TE_SetupBeamPoints(fPointfEndPointbeammdl00010.01.01.010.0, {02550255}, 1);
        }
        
        
TE_SendToAll();
    }
    
    return (
Hits == 6);
}

public 
bool:TraceRay(entitymask)
{
    return 
true;


Yeah, I thought about that but the invisible entities got into my head, usually mappers keep the map surrounded with invisible entities that do certain functions, and also, some maps even have these kind of "invisible" rooms so I don't know if this method really works..

Last edited by TheDS1337; 04-30-2019 at 15:26.
TheDS1337 is offline
backwards
AlliedModders Donor
Join Date: Feb 2014
Location: USA
Old 04-30-2019 , 20:07   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #13

Quote:
Originally Posted by TheDS1337 View Post
Yeah, I thought about that but the invisible entities got into my head, usually mappers keep the map surrounded with invisible entities that do certain functions, and also, some maps even have these kind of "invisible" rooms so I don't know if this method really works..
It's not perfect by any means but it's something that should work a high percentage of the time. There's a few alternatives I can think of that would be perfect. Bots generate NAV spaces for walkable areas they can move around in. If the map has a decent NAV system setup you can just check if the point is within a nav bounding box X/Y with a min Z height. Although custom maps that auto generate nav don't do such a great job.

This is when you can create your own nav walkable space by randommly getting player positions over time. Find all possible spots the player can be at in any ordinary situation and build a database around this data. Triangulate the points over time to reduce database size whenever possible by checking visibility between points in ray traces. You can then have a perfect layout of where players can be teleported to safely.
__________________
I highly recommend joining the SourceMod Discord Server for real time support.
backwards is offline
Pelipoika
Veteran Member
Join Date: May 2012
Location: Inside
Old 04-30-2019 , 20:49   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #14

PHP Code:
    public bool IsOutside()
    {
        
TR_TraceRayFilter(GetAbsOrigin(this.index), view_as<float>( { -90.0, -90.0, -90.0 } ), MASK_SOLIDRayType_InfiniteFilterBaseActorsAndDatathis.index);
        
        return !!(
TR_GetSurfaceFlags() & SURF_SKY);
    } 
__________________
Pelipoika is offline
backwards
AlliedModders Donor
Join Date: Feb 2014
Location: USA
Old 04-30-2019 , 22:02   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #15

Quote:
Originally Posted by Pelipoika View Post
PHP Code:
    public bool IsOutside()
    {
        
TR_TraceRayFilter(GetAbsOrigin(this.index), view_as<float>( { -90.0, -90.0, -90.0 } ), MASK_SOLIDRayType_InfiniteFilterBaseActorsAndDatathis.index);
        
        return !!(
TR_GetSurfaceFlags() & SURF_SKY);
    } 
only works if the map has a skybox and if the player is not underneath something that isn't skybox
__________________
I highly recommend joining the SourceMod Discord Server for real time support.
backwards is offline
TheDS1337
Veteran Member
Join Date: Jun 2012
Old 05-01-2019 , 08:27   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #16

I just tried the AreaNum function, it doesn't work properly, atleast not for this purpose.. you'll have to really go outside the sky box for it to detect the playable area
TheDS1337 is offline
Neuro Toxin
Veteran Member
Join Date: Oct 2013
Location: { closing the void; }
Old 05-01-2019 , 17:29   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #17

The player origin probably needs to be the void.
__________________
Neuro Toxin is offline
scorpius2k1
Senior Member
Join Date: Feb 2016
Old 05-03-2019 , 22:55   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #18

What if the coordinates are inside a func_detail or underneath a displacement? I've tried to get a trace to hit inside/underneath these areas, but it just goes right through as if it's not even there. It works fine of course if a trace is hitting the opposite "visible" side. Below is a visual of what I am referencing. Any ideas on how to get this working inside these "void-like" areas?

__________________
{__ PIRATES COVE __} ● HIGH-KILL Community | Stats ●
Half-Life 2: Deathmatch
66.151.244.149:27016 => CONNECT

Last edited by scorpius2k1; 05-03-2019 at 23:07. Reason: Added visual image
scorpius2k1 is offline
backwards
AlliedModders Donor
Join Date: Feb 2014
Location: USA
Old 05-03-2019 , 23:12   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #19

If the ray trace engine has no collision mask set for the displacements or func_details then you'd have to create your own raytrace function and parse the .bsp file youreslf. Load the displacement chunks into memory and enumerate a point in a given direction testing if the object is within the bounds of the structure. This probably is too much work for this functionality though.
__________________
I highly recommend joining the SourceMod Discord Server for real time support.

Last edited by backwards; 05-03-2019 at 23:12.
backwards is offline
scorpius2k1
Senior Member
Join Date: Feb 2016
Old 05-04-2019 , 10:00   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #20

Quote:
Originally Posted by 1337norway View Post
If the ray trace engine has no collision mask set for the displacements or func_details then you'd have to create your own raytrace function and parse the .bsp file youreslf. Load the displacement chunks into memory and enumerate a point in a given direction testing if the object is within the bounds of the structure. This probably is too much work for this functionality though.
Great idea, but I would agree. I've not had any luck with any mask types in this situation.

What if we did a second trace back then compared the distances of them? The original existing trace, then another in reverse (second trace startpoint is original trace endpoint). My thought here is since the first trace goes through the wall if inside a func_detail, etc. that the second trace back should theoretically be shorter since it will end up hitting the outside of the wall, therefore stopping the trace. If the second trace distance is shorter than the first, then we know it's in a brush void.

Would this work? How could a trace be reversed back like this (and also taking reversing angles into consideration)

PHP Code:
// ARE WE IN A BRUSH "VOID" ?
If(fTraceDistanceBack fTraceDistance) { return true; } 
__________________
{__ PIRATES COVE __} ● HIGH-KILL Community | Stats ●
Half-Life 2: Deathmatch
66.151.244.149:27016 => CONNECT

Last edited by scorpius2k1; 05-04-2019 at 10:04. Reason: Added visual image
scorpius2k1 is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 15:41.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode