Узнать индекс prop_ragdoll с помощью TR_TraceRayFilter

Nekro

Терра инкогнита
Сообщения
4,025
Реакции
2,260
Трассировка не видит регдол игрока
1. Пробовал варианты фильтров TR_TraceRayFilter source-sdk-2013/bspflags.h at master · ValveSoftware/source-sdk-2013
2. Гугл молвит, что нельзя поймать регдол https://forums.alliedmods.net/showthread.php?t=247568
3. Велв https://developer.valvesoftware.com/wiki/Prop_ragdoll
4. Пробовал и GetClientAimTarget, но нет. Так же индекс 0

Подскажите пожалуйста, можно ли поймать регдол игрока и воздействовать на него? В данном случаи удалить

C#:
#include <sdktools_functions>
#include <sdktools_engine>
#include <sdktools_trace>

bool g_InUse[MAXPLAYERS+1];
    
public Action OnPlayerRunCmd(int iClient, int &buttons)
{
    if(!(0 < iClient <= MaxClients && IsClientInGame(iClient)))
        return Plugin_Continue;

    if (!g_InUse[iClient] && buttons & IN_USE)
    {
        g_InUse[iClient] = true;
        int aim = TraceToPlayer(iClient);
        PrintToChatAll("Игрок [%N] навёл прицел на сущьность с индексом [%d]", iClient, aim);
        if (aim > MaxClients)
        {
            char class[128];
            GetEntityClassname(aim, class, sizeof(class));
            if (StrEqual(class, "prop_ragdoll", false) && CheckDistance(iClient, aim, 1000.0))
            {
                int owner = GetEntPropEnt(aim, Prop_Send, "m_hOwnerEntity");

                PrintToChatAll("Вы спрятали труп! С индексом [%d] игрока [%d]/[%N]", aim, owner, owner);
                RemoveEntity(aim);
            }
        }
    }

    else if(g_InUse[iClient] && !(buttons & IN_USE))
    {
        g_InUse[iClient] = false;
    }

    return Plugin_Continue;
}

int TraceToPlayer(int client)
{
    float vecClientEyePos[3], vecClientEyeAng[3];
    GetClientEyePosition(client, vecClientEyePos);
    GetClientEyeAngles(client, vecClientEyeAng);

    TR_TraceRayFilter(vecClientEyePos, vecClientEyeAng, MASK_ALL, RayType_Infinite, TraceRayPlayer, client);

    if (TR_DidHit(INVALID_HANDLE))
    {
        int ent = TR_GetEntityIndex(INVALID_HANDLE);
        if(ent != 0)
        {
            return ent;
        }
    }

    return 0;
}

public bool TraceRayPlayer(int entityhit, int mask, any self)
{
    if(entityhit > 0 && entityhit != self)
    {
        return true;
    }

    return false;
}

stock bool CheckDistance(int Ent1, int Ent2, float Distance)
{
    float Pos1[3], Pos2[3]; GetClientAbsOrigin(Ent1, Pos1);
    GetEntPropVector(Ent2, Prop_Send, "m_vecOrigin", Pos2);
    
    if (GetVectorDistance(Pos1, Pos2) <= Distance)
        return true;
    else
        return false;
}
 

Ganter1234

Участник
Сообщения
1,149
Реакции
667
Трассировка не видит регдол игрока
1. Пробовал варианты фильтров TR_TraceRayFilter source-sdk-2013/bspflags.h at master · ValveSoftware/source-sdk-2013
2. Гугл молвит, что нельзя поймать регдол cs_ragdoll entity and TraceRay function - AlliedModders
3. Велв Prop ragdoll - Valve Developer Community
4. Пробовал и GetClientAimTarget, но нет. Так же индекс 0

Подскажите пожалуйста, можно ли поймать регдол игрока и воздействовать на него? В данном случаи удалить

C#:
#include <sdktools_functions>
#include <sdktools_engine>
#include <sdktools_trace>

bool g_InUse[MAXPLAYERS+1];
   
public Action OnPlayerRunCmd(int iClient, int &buttons)
{
    if(!(0 < iClient <= MaxClients && IsClientInGame(iClient)))
        return Plugin_Continue;

    if (!g_InUse[iClient] && buttons & IN_USE)
    {
        g_InUse[iClient] = true;
        int aim = TraceToPlayer(iClient);
        PrintToChatAll("Игрок [%N] навёл прицел на сущьность с индексом [%d]", iClient, aim);
        if (aim > MaxClients)
        {
            char class[128];
            GetEntityClassname(aim, class, sizeof(class));
            if (StrEqual(class, "prop_ragdoll", false) && CheckDistance(iClient, aim, 1000.0))
            {
                int owner = GetEntPropEnt(aim, Prop_Send, "m_hOwnerEntity");

                PrintToChatAll("Вы спрятали труп! С индексом [%d] игрока [%d]/[%N]", aim, owner, owner);
                RemoveEntity(aim);
            }
        }
    }

    else if(g_InUse[iClient] && !(buttons & IN_USE))
    {
        g_InUse[iClient] = false;
    }

    return Plugin_Continue;
}

int TraceToPlayer(int client)
{
    float vecClientEyePos[3], vecClientEyeAng[3];
    GetClientEyePosition(client, vecClientEyePos);
    GetClientEyeAngles(client, vecClientEyeAng);

    TR_TraceRayFilter(vecClientEyePos, vecClientEyeAng, MASK_ALL, RayType_Infinite, TraceRayPlayer, client);

    if (TR_DidHit(INVALID_HANDLE))
    {
        int ent = TR_GetEntityIndex(INVALID_HANDLE);
        if(ent != 0)
        {
            return ent;
        }
    }

    return 0;
}

public bool TraceRayPlayer(int entityhit, int mask, any self)
{
    if(entityhit > 0 && entityhit != self)
    {
        return true;
    }

    return false;
}

stock bool CheckDistance(int Ent1, int Ent2, float Distance)
{
    float Pos1[3], Pos2[3]; GetClientAbsOrigin(Ent1, Pos1);
    GetEntPropVector(Ent2, Prop_Send, "m_vecOrigin", Pos2);
   
    if (GetVectorDistance(Pos1, Pos2) <= Distance)
        return true;
    else
        return false;
}
Ну я делал вот так, все прекрасно работало

C++:
public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2])
{
    if (!IsClientInGame(client) || !IsPlayerAlive(client))
        return Plugin_Continue;

    if (!InUse[client] && buttons & IN_USE)
    {
        InUse[client] = true;
        int aim = GetClientAimTarget(client, false);
        if (aim > MaxClients)
        {
            char class[128];
            float clientPos[3], aimPos[3];
            GetEntityClassname(aim, class, sizeof(class));
            GetClientAbsOrigin(client, clientPos);
            GetEntPropVector(aim, Prop_Send, "m_vecOrigin", aimPos);
            if (StrEqual(class, "prop_ragdoll", false) && GetVectorDistance(clientPos, aimPos) <= 100.0)
            {
                int owner = GetClientOfUserId(GetEntProp(aim, Prop_Send, "m_hOwnerEntity"));
                // Остальные действия
            }
        }
    }
    else if(InUse[client] && !(buttons & IN_USE))
        InUse[client] = false;

    return Plugin_Continue;
}
Сообщения автоматически склеены:

Ну я делал вот так, все прекрасно работало

C++:
public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2])
{
    if (!IsClientInGame(client) || !IsPlayerAlive(client))
        return Plugin_Continue;

    if (!InUse[client] && buttons & IN_USE)
    {
        InUse[client] = true;
        int aim = GetClientAimTarget(client, false);
        if (aim > MaxClients)
        {
            char class[128];
            float clientPos[3], aimPos[3];
            GetEntityClassname(aim, class, sizeof(class));
            GetClientAbsOrigin(client, clientPos);
            GetEntPropVector(aim, Prop_Send, "m_vecOrigin", aimPos);
            if (StrEqual(class, "prop_ragdoll", false) && GetVectorDistance(clientPos, aimPos) <= 100.0)
            {
                int owner = GetClientOfUserId(GetEntProp(aim, Prop_Send, "m_hOwnerEntity"));
                // Остальные действия
            }
        }
    }
    else if(InUse[client] && !(buttons & IN_USE))
        InUse[client] = false;

    return Plugin_Continue;
}
Вспомнил, да, он будет выдавать 0, я для этого пересоздаю ragdoll, выглядит не супер, но под то что я планировал сойдет

C-подобный:
public void OnPluginStart()
{
    HookEvent("player_death", PlayerDeath);
    HookEvent("player_death", PlayerDeathPre, EventHookMode_Pre);

public void PlayerDeath(Event event, const char[] name, bool dontBroadcast)
{
    int victim = GetClientOfUserId(event.GetInt("userid"));
    CreateDeathRagdoll(victim);
}

public Action PlayerDeathPre(Event event, const char[] name, bool dontBroadcast)
{
    int client = GetClientOfUserId(event.GetInt("userid"));
    RemoveRagdoll(client);
}

void RemoveRagdoll(int client)
{
    int Entity = GetEntPropEnt(client, Prop_Send, "m_hRagdoll");
    if(Entity != INVALID_ENT_REFERENCE)
        AcceptEntityInput(Entity, "Kill");
}

public void CreateDeathRagdoll(int iClient)
{
    int ent = CreateEntityByName("prop_ragdoll");
    if (ent == -1)
        return;
    
    char sModel[PLATFORM_MAX_PATH];
    GetClientModel(iClient, sModel, sizeof(sModel));
    DispatchKeyValueent, "model", sModel);
    DispatchSpawn(ent);
    ActivateEntity(ent);
    SetEntProp(ent, Prop_Send, "m_hOwnerEntity", GetClientUserId(iClient));
    SetEntProp(ent, Prop_Data, "m_CollisionGroup", 1);
    float vec[3];
    GetClientAbsOrigin(iClient, vec);
    TeleportEntity(ent, vec, NULL_VECTOR, NULL_VECTOR);
}
 
Последнее редактирование:

Nekro

Терра инкогнита
Сообщения
4,025
Реакции
2,260
Ка
Ну я делал вот так, все прекрасно работало

C++:
public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2])
{
    if (!IsClientInGame(client) || !IsPlayerAlive(client))
        return Plugin_Continue;

    if (!InUse[client] && buttons & IN_USE)
    {
        InUse[client] = true;
        int aim = GetClientAimTarget(client, false);
        if (aim > MaxClients)
        {
            char class[128];
            float clientPos[3], aimPos[3];
            GetEntityClassname(aim, class, sizeof(class));
            GetClientAbsOrigin(client, clientPos);
            GetEntPropVector(aim, Prop_Send, "m_vecOrigin", aimPos);
            if (StrEqual(class, "prop_ragdoll", false) && GetVectorDistance(clientPos, aimPos) <= 100.0)
            {
                int owner = GetClientOfUserId(GetEntProp(aim, Prop_Send, "m_hOwnerEntity"));
                // Остальные действия
            }
        }
    }
    else if(InUse[client] && !(buttons & IN_USE))
        InUse[client] = false;

    return Plugin_Continue;
}
Сообщения автоматически склеены:


Вспомнил, да, он будет выдавать 0, я для этого пересоздаю ragdoll, выглядит не супер, но под то что я планировал сойдет

C-подобный:
public void OnPluginStart()
{
    HookEvent("player_death", PlayerDeath);
    HookEvent("player_death", PlayerDeathPre, EventHookMode_Pre);

public void PlayerDeath(Event event, const char[] name, bool dontBroadcast)
{
    int victim = GetClientOfUserId(event.GetInt("userid"));
    CreateDeathRagdoll(victim);
}

public Action PlayerDeathPre(Event event, const char[] name, bool dontBroadcast)
{
    int client = GetClientOfUserId(event.GetInt("userid"));
    RemoveRagdoll(client);
}

void RemoveRagdoll(int client)
{
    int Entity = GetEntPropEnt(client, Prop_Send, "m_hRagdoll");
    if(Entity != INVALID_ENT_REFERENCE)
        AcceptEntityInput(Entity, "Kill");
}

public void CreateDeathRagdoll(int iClient)
{
    int ent = CreateEntityByName("prop_ragdoll");
    if (ent == -1)
        return;
    
    char sModel[PLATFORM_MAX_PATH];
    GetClientModel(iClient, sModel, sizeof(sModel));
    DispatchKeyValueent, "model", sModel);
    DispatchSpawn(ent);
    ActivateEntity(ent);
    SetEntProp(ent, Prop_Send, "m_hOwnerEntity", GetClientUserId(iClient));
    SetEntProp(ent, Prop_Data, "m_CollisionGroup", 1);
    float vec[3];
    GetClientAbsOrigin(iClient, vec);
    TeleportEntity(ent, vec, NULL_VECTOR, NULL_VECTOR);
}
Как вариант, но как то костыльно, хотелось бы просто отдовить готовый. Но если нет, то конечно создавать самому
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,520
Реакции
4,979

SenatoR

Участник
Сообщения
773
Реакции
344
При смерти ловишь рэгдол игрока, и пишешь к нему в таргет нейм, индекс клиента. Далее уже проверяешь.
НО!
В ксго классический рэгдол обрабатывается клиентом. Т.е. у нескольких игроков рэгдол может находиться в разных позах и местах.
 

Nekro

Терра инкогнита
Сообщения
4,025
Реакции
2,260
При смерти ловишь рэгдол игрока, и пишешь к нему в таргет нейм, индекс клиента. Далее уже проверяешь.
НО!
В ксго классический рэгдол обрабатывается клиентом. Т.е. у нескольких игроков рэгдол может находиться в разных позах и местах.
В ксс то же часто регдолы игроки видят по разному
 

SenatoR

Участник
Сообщения
773
Реакции
344
В ксс то же часто регдолы игроки видят по разному
Только в ксго, клиентский рэгдол не является физической сущностью, а в ксс является и ее обрабатывает сервер ( в ксс с ней можно взаимодействовать).
Разное положение рэгдола в ксс, обусловлено особенностью движка и кода. В ксго, чтобы взаимодействовать с рэгдолом, нужно спавнить новый.

Теме с рэгдолами много лет, все было разжевано еще в момент выхода игры, координально ничего не менялось. Хочешь что-то получить от рэгдола и сделать его физической сущностью, то удаляешь клиентский и спавнишь новую, независимую сущность.

Пример того, что хочешь получить, можешь посмотреть в любом ТТТ моде ( не важно, ксс или ксго)
 
Сверху Снизу