Raised This Month: $51 Target: $400
 12% 

Teleporting Player Check "Non-Stuck"


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
scorpius2k1
Senior Member
Join Date: Feb 2016
Old 04-25-2019 , 15:55   Teleporting Player Check "Non-Stuck"
Reply With Quote #1

If I have coordinates already, is there a way to check BEFORE sending a player via 'TeleportEntity':

- If they will be stuck in a wall/floor/ceiling
- If they WOULD BE stuck, then TRY to adjust the coordinates
- If coordinates are UNABLE be adjusted (due to player X,Y,Z being out of bounds compared to the coordinates), then cancel
- If VALID, teleport using adjusted/existing coordinates.

Keep in mind, a player entity is:
- 32.0 pixels X & Y
- 72.0 pixels Z

So a global float used to check against coordinates could look something like:
PHP Code:
float g_fPlayerBounds[3] = {32.032.072.0}; 
In it's most basic form, I need to check the existing coordinates against the player bounds to see if they would be able to "fit" and not get stuck in walls, floors, etc. I am thinking something like this could be done somehow with a TR_TraceRayFilter to check the distances first (aka player "fit") and then somehow change the original coordinates to match the player center X, Y, Z (just halving the g_fPlayerBounds values essentially).

My reason for this:
On a flat surface, it isn't an issue to teleport a player...but curved surfaces, tight spaces are. The players feet can be put in the ground or they can be put in a wall...see where I'm going with this? I just don't want them to be stuck after teleporting.


Thanks a million for any help/insight here! Maybe there is a much easier way to do this than what I'm thinking. Currently working on a really cool plugin I would be happy to share, and this part the only thing keeping me from finishing it.

__________________
{__ PIRATES COVE __} ● HIGH-KILL Community | Stats ●
Half-Life 2: Deathmatch
66.151.244.149:27016 => CONNECT
scorpius2k1 is offline
Kailo
Senior Member
Join Date: Sep 2014
Location: Moscow, Russia
Old 04-25-2019 , 16:33   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #2

Quick answer for this. Use Hull Trace for this. Unfortunately, there is no wiki page for this. But you can easly to search it. https://sm.alliedmods.net/new-api/sdktools_trace
Players mins {-16.0, -16.0, 0.0} maxs {16.0, 16.0, 72.0}.
Tip: if your coordinate is a floor - add +1.0 for Z axis (for sure, that player does not stuck at ground)
Kailo is offline
Franc1sco
Veteran Member
Join Date: Oct 2010
Location: Spain (Madrid)
Old 04-25-2019 , 17:56   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #3

You can take a look in this
__________________
Veteran Coder -> Activity channel
Coding on CS2 and taking paid and free jobs.

Contact: Steam, Telegram or discord ( franug ).

You like my work? +Rep in my steam profile comments or donate.


Last edited by Franc1sco; 04-25-2019 at 17:56.
Franc1sco is offline
Send a message via MSN to Franc1sco
MasterMind420
BANNED
Join Date: Nov 2010
Old 04-25-2019 , 19:32   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #4

Simple solution...just gotta check if the player is moving or not...by checking there velocity i believe. and check the keys there pressing at the time. if they are pressing the key to move but not then they are stuck if u need help just pm me. but thats what i do to figure out who's stuck. Unless u absolutely need to specifically check if there stuck in specific things...like walls ceilings or floors...this is the way to go.

Last edited by MasterMind420; 04-25-2019 at 21:04.
MasterMind420 is offline
scorpius2k1
Senior Member
Join Date: Feb 2016
Old 04-25-2019 , 21:34   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #5

Quote:
Originally Posted by MasterMind420 View Post
Simple solution...just gotta check if the player is moving or not...by checking there velocity i believe. and check the keys there pressing at the time. if they are pressing the key to move but not then they are stuck if u need help just pm me. but thats what i do to figure out who's stuck. Unless u absolutely need to specifically check if there stuck in specific things...like walls ceilings or floors...this is the way to go.
Thanks for the replies everyone! This is a slightly different scenario than just a player being stuck on spawn or on another player. I don't need to worry about player movement, but only need to do a problematic check on a previously defined coordinate IF we teleported the player to that particular coordinate. We don't want the players bounding box to clip anything after fixing.

Let's say we have an X,Y,Z coordinate of 100,200,300 and if I were to move the player there with "TeleportEntity", they would be stuck in the ceiling (left pic below). Essentially what I am aiming to do is check, and if need be, fix up those coordinates so the player would not be stuck when I moved them (right pic below). The FIXED coordinates would be something like 100,200,228 (notice the Z axis was changed to compensate for the players height of 72 units). Again this checkpoint should work regardless if it is a wall/floor/ceiling/object unless it is impossible which at that point the check would return a -1 or something.

Here is a good visual (notice the bounding box of the player not being clipped in the right side pic after fix):



The plugin link Franc1sco shared seemed to be close, except it didn't work 100% of the time. I would still be left stuck sometimes, especially in ceilings for some reason. It was pretty close to what I'm after because it seemed to check in a radius around the player and act accordingly.

Again, I am sure this can somehow be done with TR_TraceRayFilter to check X,Y,Z with the player bounding box dimensions in mind (32,32,72), just how to go about it is what I am stuck on.

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

Last edited by scorpius2k1; 04-25-2019 at 21:52.
scorpius2k1 is offline
TheDS1337
Veteran Member
Join Date: Jun 2012
Old 04-25-2019 , 21:49   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #6

Quote:
Originally Posted by scorpius2k1 View Post
Thanks for the replies everyone! This is a slightly different scenario than just a player being stuck on spawn or on another player. I don't need to worry about player movement, but only need to do a problematic check on a previously defined coordinate IF we teleported the player to that particular coordinate.

Let's say we have an X,Y,Z coordinate of 100,200,300 and if I were to move the player there with "TeleportEntity", they would be stuck in the ceiling (left pic below). Essentially what I am aiming to do is check, and if need be, fix up those coordinates so the player would not be stuck when I moved them (right pic below).

Here is a good visual (notice the bounding box of the player not being clipped in the right side pic after fix):



The plugin link Franc1sco shared seemed to be close, except it didn't work 100% of the time. I would still be left stuck sometimes, especially in ceilings for some reason. It was pretty close to what I'm after because it seemed to check in a radius around the player and act accordingly.

Again, I am sure this can somehow be done with TR_TraceRayFilter to check X,Y,Z with the player bounding box dimensions in mind (32,32,72), just how to go about it is what I am stuck on.

Thanks again all!!
Launch your trace from the said origin in the x/y/z direction, and check when it hits some other entity (including worldspawn), if the distance between the hit entity and the origin is less or equal 32 units in X/Y then you can't spawn there, same for Z axis, if it's greater then you can safely spawn there.

PS: I might support you with some code tomorrow. have a good night for now.

EDIT: Here it is,
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 startPos[3], 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);
                
TR_GetStartPosition(raystartPos);
                
                if( 
GetVectorDistance(startPosendPos) > 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;

I tried with this, now this work in the simplest cases... if a you have only a portion of the player stuck in a wall or something, it'll teleport you to a close point where you can actually move.

But, playing Dust2 on CSGO, CT spawn here have a little inaccessible room, if a player gets stuck near it there's a possibility he'll go inside, since it's not really solid, as you can see here:






Otherwise, 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.





I did only a few tests with this, you should try more and see if it works for "your" own special cases. also, as you can see you can't go on looping forever.. especially doing this kind of dirty work, this function is kinda heavy so I limited the number of trials, but in my most cases I got no more than 5 trials each so it's a good sign, and bare in mind, you can't go on using this everytime the player spawns, if it somehow worked for you, you should really be considering saving the corrected origins into some files once you generate them and then use them next time the map loads.

Last edited by TheDS1337; 04-26-2019 at 16:29.
TheDS1337 is offline
scorpius2k1
Senior Member
Join Date: Feb 2016
Old 04-27-2019 , 09:48   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #7

Quote:
Originally Posted by TheDS1337 View Post
Launch your trace from the said origin in the x/y/z direction, and check when it hits some other entity (including worldspawn), if the distance between the hit entity and the origin is less or equal 32 units in X/Y then you can't spawn there, same for Z axis, if it's greater then you can safely spawn there.

PS: I might support you with some code tomorrow. have a good night for now.

EDIT: Here it is,

...

I did only a few tests with this, you should try more and see if it works for "your" own special cases. also, as you can see you can't go on looping forever.. especially doing this kind of dirty work, this function is kinda heavy so I limited the number of trials, but in my most cases I got no more than 5 trials each so it's a good sign, and bare in mind, you can't go on using this everytime the player spawns, if it somehow worked for you, you should really be considering saving the corrected origins into some files once you generate them and then use them next time the map loads.
TheDS1337, that is some NICE looking code and work my friend. Thank you! I currently have a much more basic routine with traces setup to check -/+ X,Y,Z distances of the coordinates in relation to the player bounds and they are adjusted accordingly if needed. That method works great on flat world brushes but goes bad otherwise. I really appreciate your help and time with this, thank you again -- I will give this a go over the next few days and see what I can do with it.
__________________
{__ PIRATES COVE __} ● HIGH-KILL Community | Stats ●
Half-Life 2: Deathmatch
66.151.244.149:27016 => CONNECT
scorpius2k1 is offline
scorpius2k1
Senior Member
Join Date: Feb 2016
Old 04-29-2019 , 15:02   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #8

Quote:
Originally Posted by TheDS1337 View Post
PHP Code:
AddVectors(oldPos, {0.00.025.0}, oldPos);    // LINE 42 Warning

TR_GetStartPosition(raystartPos); // LINE 101 Error 
TheDS1337, tried testing today and getting a warning and error when I tried to compile your script.

Code:
(42) : warning 213: tag mismatch
(101) : error 017: undefined symbol "TR_GetStartPosition"
I'm not sure if the error is game-specific or not, but I am trying to use this in HL2DM. I see the native in 'sdktools_trace.inc', but even if I add that specifically in, no change.

Any ideas? Would really like to test this out. Thanks!
__________________
{__ PIRATES COVE __} ● HIGH-KILL Community | Stats ●
Half-Life 2: Deathmatch
66.151.244.149:27016 => CONNECT
scorpius2k1 is offline
Kailo
Senior Member
Join Date: Sep 2014
Location: Moscow, Russia
Old 04-29-2019 , 15:49   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #9

Warning may fixed by:
PHP Code:
// Any array is int by default
AddVectors(oldPosview_as<float>({0.00.025.0}), oldPos); 
Error means you not included sdktools.inc file to your plugin, but you told otherwise. Just check everything.
Kailo is offline
scorpius2k1
Senior Member
Join Date: Feb 2016
Old 04-29-2019 , 16:02   Re: Teleporting Player Check "Non-Stuck"
Reply With Quote #10

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'

Quote:
Originally Posted by Kailo View Post
Warning may fixed by:
PHP Code:
// Any array is int by default
AddVectors(oldPosview_as<float>({0.00.025.0}), oldPos); 
Error means you not included sdktools.inc file to your plugin, but you told otherwise. Just check everything.
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:
Quote:
Originally Posted by scorpius2k1
I see the native in 'sdktools_trace.inc', but even if I add that specifically in, no change.
I used TheDS1337's original code they posted above, which also has...

PHP Code:
#include <sdktools> 
...already, but still get the error. Weird!
__________________
{__ PIRATES COVE __} ● HIGH-KILL Community | Stats ●
Half-Life 2: Deathmatch
66.151.244.149:27016 => CONNECT

Last edited by scorpius2k1; 04-29-2019 at 16:39.
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 18:14.


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