Проблема взаимодействия плагина с игроком в момент прыжка

aitch

Участник
Сообщения
9
Реакции
1
Я столкнулся с проблемой, что в момент, когда игрок прыгает, мы не можем напрямую работать с его скоростью. Т.е. если бы мы в этот момент телепортировали игрока с измененной скоростью, то у нас ничего бы не вышло. Так вот, меня интересуют возможные способы решения данной проблемы. Делать это в следующем тике не выгодно, так как ведется статистика.

Этот вариант самый действенный из всех, но самый ужасный, потому что скорость меняется только в следующем тике, а в этом тике уже ведется статистика и она получается некорректной.
C-подобный:
void Takeoff()
{
    float speed = Movement_GetSpeed(this.jumper);
    if (speed > JumpTypesPre[this.type])
    {
        float velocity[3];
        Movement_GetVelocity(this.jumper, velocity);
        float diff = JumpTypesPre[this.type] / speed;
        velocity[0] = -(velocity[0] - velocity[0] * diff);
        velocity[1] = -(velocity[1] - velocity[1] * diff);
        velocity[2] = 0.0;
        SetEntPropVector(this.jumper, Prop_Send, "m_vecBaseVelocity", velocity);
    }
}
 
Решение
Если скорость модифицируется в евенте player_jump то примерно так
C:
#pragma semicolon 1

#include <sourcemod>
#include <sdktools>

Address g_addrGameMovement;

public void OnPluginStart()
{
    StartPrepSDKCall(SDKCall_Static);
    PrepSDKCall_SetSignature(SDKLibrary_Server, "@CreateInterface", 0);
    PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer);
    PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Pointer, VDECODE_FLAG_ALLOWNULL);
    PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);

    Handle call = EndPrepSDKCall();
    g_addrGameMovement = SDKCall(call, "GameMovement001", 0);
    delete call;

    HookEvent("player_jump", Event_PlayerJump);
}

void MoveData_GetVelocity(float vel[3])
{
    Address...

Ganter1234

Участник
Сообщения
1,149
Реакции
667
Я столкнулся с проблемой, что в момент, когда игрок прыгает, мы не можем напрямую работать с его скоростью. Т.е. если бы мы в этот момент телепортировали игрока с измененной скоростью, то у нас ничего бы не вышло. Так вот, меня интересуют возможные способы решения данной проблемы. Делать это в следующем тике не выгодно, так как ведется статистика.

Этот вариант самый действенный из всех, но самый ужасный, потому что скорость меняется только в следующем тике, а в этом тике уже ведется статистика и она получается некорректной.
C-подобный:
void Takeoff()
{
    float speed = Movement_GetSpeed(this.jumper);
    if (speed > JumpTypesPre[this.type])
    {
        float velocity[3];
        Movement_GetVelocity(this.jumper, velocity);
        float diff = JumpTypesPre[this.type] / speed;
        velocity[0] = -(velocity[0] - velocity[0] * diff);
        velocity[1] = -(velocity[1] - velocity[1] * diff);
        velocity[2] = 0.0;
        SetEntPropVector(this.jumper, Prop_Send, "m_vecBaseVelocity", velocity);
    }
}
К чему настолько большая точность?
 

Palonez

бб братки
Сообщения
3,035
Реакции
1,837
Я столкнулся с проблемой, что в момент, когда игрок прыгает, мы не можем напрямую работать с его скоростью. Т.е. если бы мы в этот момент телепортировали игрока с измененной скоростью, то у нас ничего бы не вышло. Так вот, меня интересуют возможные способы решения данной проблемы. Делать это в следующем тике не выгодно, так как ведется статистика.

Этот вариант самый действенный из всех, но самый ужасный, потому что скорость меняется только в следующем тике, а в этом тике уже ведется статистика и она получается некорректной.
C-подобный:
void Takeoff()
{
    float speed = Movement_GetSpeed(this.jumper);
    if (speed > JumpTypesPre[this.type])
    {
        float velocity[3];
        Movement_GetVelocity(this.jumper, velocity);
        float diff = JumpTypesPre[this.type] / speed;
        velocity[0] = -(velocity[0] - velocity[0] * diff);
        velocity[1] = -(velocity[1] - velocity[1] * diff);
        velocity[2] = 0.0;
        SetEntPropVector(this.jumper, Prop_Send, "m_vecBaseVelocity", velocity);
    }
}
Пробуй через координаты плоскостей игрока по x z высчитывать
 

vanz666

Участник
Сообщения
45
Реакции
157
Если скорость модифицируется в евенте player_jump то примерно так
C:
#pragma semicolon 1

#include <sourcemod>
#include <sdktools>

Address g_addrGameMovement;

public void OnPluginStart()
{
    StartPrepSDKCall(SDKCall_Static);
    PrepSDKCall_SetSignature(SDKLibrary_Server, "@CreateInterface", 0);
    PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer);
    PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Pointer, VDECODE_FLAG_ALLOWNULL);
    PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);

    Handle call = EndPrepSDKCall();
    g_addrGameMovement = SDKCall(call, "GameMovement001", 0);
    delete call;

    HookEvent("player_jump", Event_PlayerJump);
}

void MoveData_GetVelocity(float vel[3])
{
    Address move_data = LoadFromAddress(g_addrGameMovement + view_as<Address>(8), NumberType_Int32);
    
    vel[0] = LoadFromAddress(move_data + view_as<Address>(64), NumberType_Int32);
    vel[1] = LoadFromAddress(move_data + view_as<Address>(68), NumberType_Int32);
    vel[2] = LoadFromAddress(move_data + view_as<Address>(72), NumberType_Int32);
}

void MoveData_SetVelocity(float vel[3])
{
    Address move_data = LoadFromAddress(g_addrGameMovement + view_as<Address>(8), NumberType_Int32);
    
    StoreToAddress(move_data + view_as<Address>(64), vel[0], NumberType_Int32);
    StoreToAddress(move_data + view_as<Address>(68), vel[1], NumberType_Int32);
    StoreToAddress(move_data + view_as<Address>(72), vel[2], NumberType_Int32);
}

public void Event_PlayerJump(Event event, const char[] name, bool dontBroadcast)
{
    float vel[3];
    MoveData_GetVelocity(vel);

    vel[0] *= 2.0;
    vel[1] *= 2.0;
    
    MoveData_SetVelocity(vel);
}
Для windows необходим см версии >= 11
 
Решение

aitch

Участник
Сообщения
9
Реакции
1
Если скорость модифицируется в евенте player_jump то примерно так
C:
#pragma semicolon 1

#include <sourcemod>
#include <sdktools>

Address g_addrGameMovement;

public void OnPluginStart()
{
    StartPrepSDKCall(SDKCall_Static);
    PrepSDKCall_SetSignature(SDKLibrary_Server, "@CreateInterface", 0);
    PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer);
    PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Pointer, VDECODE_FLAG_ALLOWNULL);
    PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);

    Handle call = EndPrepSDKCall();
    g_addrGameMovement = SDKCall(call, "GameMovement001", 0);
    delete call;

    HookEvent("player_jump", Event_PlayerJump);
}

void MoveData_GetVelocity(float vel[3])
{
    Address move_data = LoadFromAddress(g_addrGameMovement + view_as<Address>(8), NumberType_Int32);
  
    vel[0] = LoadFromAddress(move_data + view_as<Address>(64), NumberType_Int32);
    vel[1] = LoadFromAddress(move_data + view_as<Address>(68), NumberType_Int32);
    vel[2] = LoadFromAddress(move_data + view_as<Address>(72), NumberType_Int32);
}

void MoveData_SetVelocity(float vel[3])
{
    Address move_data = LoadFromAddress(g_addrGameMovement + view_as<Address>(8), NumberType_Int32);
  
    StoreToAddress(move_data + view_as<Address>(64), vel[0], NumberType_Int32);
    StoreToAddress(move_data + view_as<Address>(68), vel[1], NumberType_Int32);
    StoreToAddress(move_data + view_as<Address>(72), vel[2], NumberType_Int32);
}

public void Event_PlayerJump(Event event, const char[] name, bool dontBroadcast)
{
    float vel[3];
    MoveData_GetVelocity(vel);

    vel[0] *= 2.0;
    vel[1] *= 2.0;
  
    MoveData_SetVelocity(vel);
}
Для windows необходим см версии >= 11
Все работает безупречно, но насчет версии не понял. На линуксе данный метод работает с 10 версии? Есть некоторые обстоятельства, которые не дают обновиться до 11
Да, действительно, на линухе все работает на 1.10. Спасибо
 

vanz666

Участник
Сообщения
45
Реакции
157
Все работает безупречно, но насчет версии не понял. На линуксе данный метод работает с 10 версии? Есть некоторые обстоятельства, которые не дают обновиться до 11
Да, действительно, на линухе все работает на 1.10. Спасибо
На линуксе будет работать на любой версии.

На виндовс версиях ниже 1.11 функция PrepSDKCall_SetSignature не поддерживает символьные имена во втором параметре.
Поэтому если есть надобность запустить плагин на старых версия см, то необходимо юзать PrepSDKCall_SetFromConf с подключением gamedata файла.
test_plug.games.txt:
"Games"
{
    "#default"
    {
        "Signatures"
        {
            "CreateInterface"
            {
                "library" "server"
                "windows" "@CreateInterface"
                "linux" "@CreateInterface"
            }
        }
    }
}
C:
#pragma semicolon 1

#include <sourcemod>
#include <sdktools>

Address g_addrGameMovement;

public void OnPluginStart()
{
    StartPrepSDKCall(SDKCall_Static);
    
    GameData conf = new GameData("test_plug.games");
    PrepSDKCall_SetFromConf(conf, SDKConf_Signature, "CreateInterface");
    delete conf;
    
    PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer);
    PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Pointer, VDECODE_FLAG_ALLOWNULL);
    PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);

    Handle call = EndPrepSDKCall();
    g_addrGameMovement = SDKCall(call, "GameMovement001", 0);
    delete call;

    HookEvent("player_jump", Event_PlayerJump);
}

void MoveData_GetVelocity(float vel[3])
{
    Address move_data = LoadFromAddress(g_addrGameMovement + view_as<Address>(8), NumberType_Int32);
    
    vel[0] = LoadFromAddress(move_data + view_as<Address>(64), NumberType_Int32);
    vel[1] = LoadFromAddress(move_data + view_as<Address>(68), NumberType_Int32);
    vel[2] = LoadFromAddress(move_data + view_as<Address>(72), NumberType_Int32);
}

void MoveData_SetVelocity(float vel[3])
{
    Address move_data = LoadFromAddress(g_addrGameMovement + view_as<Address>(8), NumberType_Int32);
    
    StoreToAddress(move_data + view_as<Address>(64), vel[0], NumberType_Int32);
    StoreToAddress(move_data + view_as<Address>(68), vel[1], NumberType_Int32);
    StoreToAddress(move_data + view_as<Address>(72), vel[2], NumberType_Int32);
}

public void Event_PlayerJump(Event event, const char[] name, bool dontBroadcast)
{
    float vel[3];
    MoveData_GetVelocity(vel);

    vel[0] *= 2.0;
    vel[1] *= 2.0;
    
    MoveData_SetVelocity(vel);
}
 
Сверху Снизу