hl2sdk icon indicating copy to clipboard operation
hl2sdk copied to clipboard

Source 2 - Reverse 9/2022 ConVar / ConCommand changes

Open psychonic opened this issue 2 years ago • 0 comments

ConVars and ConCommands in Source 2 got a rework with a Dota 2 update a couple of months ago. The implementation seems to be fully rewritten.

Some snippets from a Russian Cheat Forum:

enum class EConvarType : std::uint8_t
{
    BOOL = 0,
    INT32,
    UINT32,
    INT64,
    UINT64,
    FLOAT,
    DOUBLE,
    STRING,
    COLOR_RGBA,
    UNK_SOME_TWO_FLOATS,
    UNK_SOME_THREE_FLOATS,
    UNK_SOME_FOUR_FLOATS,
    UNK_SOME_THREE_FLOATS_AGAIN,
};

struct CvarNode
{
    ConVariable* var{};
    int some_leaf_like_index_shit{};
};

union ConVarValue
{
    bool boolean{};
    std::uint64_t u64;
    std::int64_t i64;
    std::uint32_t u32;
    std::int32_t i32;
    float flt;
    double dbl;
    const char* str;
    std::uint32_t clr_rgba;
    std::array<float, 2> two_floats;
    std::array<float, 3> three_floats;
    std::array<float, 4> four_floats;
};

struct ConVariable
{
    const char* name{};
    void* next_convar_node_like_shit{};
    void* unk1{};
    void* unk2{};
    const char* help{};
    EConvarType type{};
    int unk_maybe_number_of_times_changed{};
    int flags{};
    int unk4{};
    int CALLBACK_INDEX{};
    int unk5{};
    ConVarValue value{};
}

struct ConCmd
{
    const char* name{};
    const char* help{};
    int flags{};
    void* accessor{};
    void* accessor_related_shit_maybe{};
    int shit_unk{};
    int CallbackListIndex{};
};

struct ConCMDID
{
    static inline constexpr auto BAD_ID = 0xFFFF;
    std::uint64_t impl{};

    bool IsGood() const noexcept
    {
        return impl != BAD_ID;
    }

    void Invalidate() noexcept
    {
        impl = BAD_ID;
    }
};

struct ConCMDRegistrationInfo
{
    const char* cmd_name{};
    const char* help_str{};
    std::uint64_t flags{};
    void* callback{};
    void* unk1{};
    void* unk2{};
    void* unk3{};
    void* output_id_holder{};
};
ConCommandSource2(const std::string_view& name, const std::string_view& desc, void(* callback)(void*, const CCommand&))
{
    ICvar::ConCMDRegistrationInfo info{};
    info.cmd_name = name.data();
    info.help_str = desc.data();
    info.callback = callback;
    info.output_id_holder = this;
    Constructor::Invoke(&info);
}


...
//CCvar VVV
    private:
    //search for xrefs for constructed concmd variables.
    static inline constexpr auto UnRegisterCMDVFTable_Index = 38;
public:
    auto UnRegisterCMD(const ConCMDID& id)
    {
        CallVFunc<UnRegisterCMDVFTable_Index>(id);
    }

struct ConVarID
{
    static inline constexpr auto BAD_ID = 0xFFFFFFFF;
    std::uint64_t impl{};
    void* var_ptr{};

    bool IsGood() const noexcept
    {
        return impl != BAD_ID;
    }

    void Invalidate() noexcept
    {
        impl = BAD_ID;
    }
};
using t_CvarCallback = void(*)(const ConVarID& id, int unk1, const ConVarValue* val, const ConVarValue* old_val);


/*
    t_CvarCallback GetCVarCallback(int index)
    {
        if (index)
        {
            auto table = Member<void*>(0x80);
            if (table)
                return *reinterpret_cast<t_CvarCallback*>(reinterpret_cast<std::uintptr_t>(table) + 24 * index);
        }
        return nullptr;
    }
*/
            /*
                auto CCvar::GetCvarList() const noexcept
                {
                    return std::span<const CvarNode>{ Member<const CvarNode*>(0x40), Member<std::uint16_t>(0x58) };
                }
            */
         
for (const auto& [cvar_node, idx] : ICvar::Create()->GetCvarList() | indexed_range)
{
    if (cvar_node.var)
    {
        if (make_stringview(cvar_node.var->name) == "dota_camera_distance")
        {
            const auto old_val = cvar_node.var->value;
            cvar_node.var->value.flt = 2222.0f;
            if (auto cb = ICvar::Create()->GetCVarCallback(cvar_node.var->CALLBACK_INDEX); cb)
                cb(ICvar::ConVarID{ .impl = static_cast<std::uint64_t>(idx), .var_ptr = (void*)&cvar_node},
                    0, &cvar_node.var->value, & old_val);
        }
        if (make_stringview(cvar_node.var->name) == "sv_cheats")
        {
            const auto old_val = cvar_node.var->value;
            cvar_node.var->value.boolean = true;
            if (auto cb = ICvar::Create()->GetCVarCallback(cvar_node.var->CALLBACK_INDEX); cb)
                cb(ICvar::ConVarID{ .impl = static_cast<std::uint64_t>(idx), .var_ptr = (void*)&cvar_node },
                    0, &cvar_node.var->value, &old_val);
        }
    }
}

psychonic avatar Nov 09 '22 23:11 psychonic