• Ищем качественного (не новичок) разработчиков Xenforo для этого форума! В идеале, чтобы ты был фулл стек программистом. Если у тебя есть что показать, то свяжись с нами по контактным данным: https://t.me/DREDD

Исходник Server bones for airflow v1.5 (not the best implementation)

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
11 Дек 2023
Сообщения
15
Реакции
6
C++:
Expand Collapse Copy
#include "globals.hpp"
#include "ik_solver.hpp"
#include "server_bones.hpp"
#include "animations.hpp"

namespace bone_merge
{
    std::uintptr_t& get_bone_merge(c_cs_player* player)
    {
        return [I](std::uintptr_t[/I])((std::uintptr_t)player + [I]offsets::get_bone_merge.cast<std::uintptr_t[/I]>());
    }

    void update_cache(std::uintptr_t& bone_merge)
    {
        static auto update_bone_merge_cache = offsets::update_merge_cache.cast<void(__thiscall*)(std::uintptr_t)>();
        update_bone_merge_cache(bone_merge);
    }
}

INLINE mstudioposeparamdesc_t* get_pose_param(c_studio_hdr* hdr, int index)
{
    static auto get_pose_parameter = offsets::get_pose_parameter.cast<mstudioposeparamdesc_t * (__thiscall*)(c_studio_hdr*, int)>();
    return get_pose_parameter(hdr, index);
}

void clamp_bones_info_t::store(c_cs_player* player)
{
    auto collideable = player->get_collideable();
    if (!collideable)
        return;

    collision_change_time = player->collision_change_time();
    collision_change_origin = player->collision_change_origin();

    auto& base_origin = player == HACKS->local ? player->get_abs_origin() : player->origin();
    origin = base_origin;
    collision_origin = base_origin;

    view_offset = player->view_offset();
    ground_entity = player->ground_entity();

    mins = collideable->get_mins();
    maxs = collideable->get_maxs();
}

void clamp_bones_info_t::store(anim_record_t* record)
{
    collision_change_time = record->collision_change_time;
    collision_change_origin = record->collision_change_origin;

    origin = record->origin;
    collision_origin = record->origin;

    view_offset = record->view_offset;
    ground_entity = record->ground_entity;

    mins = record->mins;
    maxs = record->maxs;
}

void c_bone_builder::clamp_bones_in_bbox(c_cs_player* player, matrix3x4_t* matrix, int mask, float curtime, vec3_t& eye_angles, clamp_bones_info_t& clamp_info) {
    if (!matrix)
        return;

    auto hdr = player->get_studio_hdr();
    if (!hdr)
        return;

    this->bone_flags_base = hdr->bone_flags().base();
    this->bone_parent_count = hdr->bone_parent_count();

    auto studiohdr = [I]reinterpret_cast<studiohdr_t*[/I]>(hdr);
    if (!studiohdr)
        return;

    auto head_bone = 8;
    if (head_bone < 0)
        return;

    auto collision_origin = clamp_info.collision_origin;

    auto collision_bb_min = clamp_info.mins;
    auto collision_bb_max = clamp_info.maxs;

    auto max_collision_pos_z = collision_origin.z + collision_bb_max.z + collision_bb_min.z;
    auto new_pos_z = max_collision_pos_z;

    auto change_collision_time_diff = curtime - clamp_info.collision_change_time;
    if (change_collision_time_diff < 0.2f)
    {
        auto time_multiplier = std::clamp(change_collision_time_diff * 5.f, 0.f, 1.f);
        new_pos_z = math::lerp(time_multiplier, clamp_info.collision_change_origin, max_collision_pos_z);
    }

    auto head_bone_position = matrix[head_bone].get_origin();

    vec3_t eye_position{}, forward{}, right{}, up{};
    eye_position = clamp_info.origin + clamp_info.view_offset;
    math::angle_vectors(eye_angles, &forward, &right, &up);

    vec3_t head_position_to_change{};
    auto target_difference = head_bone_position.dot(right) - eye_position.dot(right);

    if (std::fabs(target_difference) <= 3.f)
        head_position_to_change = head_bone_position;
    else
    {
        auto head_direction = 0.f;
        if (target_difference < 0.f)
            head_direction = -1.f;
        else
            head_direction = 1.f;

        auto adjusted_right_direction = (right.normalized() * 3.f) * head_direction;
        head_position_to_change = (head_bone_position - (right * target_difference)) + adjusted_right_direction;
    }

    if (head_position_to_change.z > (new_pos_z - 4.f))
        head_position_to_change.z = new_pos_z - 4.f;

    auto head_position_delta = vec3_t{ head_position_to_change.x - eye_position.x, head_position_to_change.y - eye_position.y, 0.f };

    if (head_position_delta.length() > 11.f)
    {
        auto normalized_delta = head_position_delta.normalized();
        head_position_to_change.x = (normalized_delta.x * 11.f) + eye_position.x;
        head_position_to_change.y = (normalized_delta.y * 11.f) + eye_position.y;
    }

    auto head_pos_difference = head_bone_position - head_position_to_change;
    if (!head_pos_difference.valid() || head_pos_difference.length_sqr() >= 900.f)
        return;

    auto left_ankle_bone = 68;
    auto right_ankle_bone = 75;
    auto spine_3_bone = 6;

    mstudioikchain_t* left_chain = nullptr;
    mstudioikchain_t* right_chain = nullptr;

    auto deref_hdr = [I](std::uintptr_t[/I])(hdr);
    auto bone_chains = [I](int[/I])(deref_hdr + 0x11C);

    if (studiohdr->bones <= 0 || bone_chains <= 0)
        return;

    if (bone_chains > 0)
    {
        auto ik_chain_ptr = deref_hdr + [I](int[/I])(deref_hdr + 0x120);

        auto left_chain = 0, right_chain = 0;
        for (int i = 0; i < bone_chains; ++i)
        {
            auto current_chain_index = [I](int[/I])([I](int[/I])(ik_chain_ptr + 12) + ik_chain_ptr + 56);

            if (left_ankle_bone == current_chain_index)
                left_chain = ik_chain_ptr;
            else if (right_ankle_bone == current_chain_index)
                right_chain = ik_chain_ptr;

            if (left_chain && right_chain)
                break;

            ik_chain_ptr += 16;
        }
    }

    auto left_ankle_bone_position = matrix[left_ankle_bone].get_origin();
    auto right_ankle_bone_position = matrix[right_ankle_bone].get_origin();
    auto lowest_ankle_position_z = std::min(left_ankle_bone_position.z, right_ankle_bone_position.z);

    auto solve_left_ik = false;
    auto solve_right_ik = false;

    auto ground_entity = (c_base_entity*)HACKS->entity_list->get_client_entity_handle(clamp_info.ground_entity);

    auto head_adjust = 0.7740f;
    auto height_amount = 0.f;
    auto bone_parent = -1;

    for (int i = 0; i < studiohdr->bones; ++i)
    {
        auto& current_bone = matrix[i];
        auto current_bone_origin = current_bone.get_origin();

        if (!(this->bone_flags_base[i] & mask))
            continue;

        if (i == left_ankle_bone && left_chain && ground_entity)
        {
            solve_left_ik = true;
            continue;
        }
        else if (i == right_ankle_bone && right_chain && ground_entity)
        {
            solve_right_ik = true;
            continue;
        }

        if (ground_entity)
        {
            if (this->bone_parent_count)
            {
                if (i >= 0 && spine_3_bone >= 0)
                {
                    auto studio_hdr_mat_iter = [I]reinterpret_cast<int[/I]>(reinterpret_cast<std::uintptr_t>(hdr) + 0x44);
                    bone_parent = [I]reinterpret_cast<int[/I]>(studio_hdr_mat_iter + 4 * i);

                    if (bone_parent != -1)
                    {
                        while (bone_parent != spine_3_bone)
                        {
                            bone_parent = [I]reinterpret_cast<int[/I]>(studio_hdr_mat_iter + 4 * bone_parent);
                            if (bone_parent == -1)
                                goto LABEL_56;
                        }
                        goto LABEL_63;
                    }
                }
            }
        LABEL_56:
            auto height_diff = current_bone_origin.z - (head_bone_position.z - head_position_to_change.z);
            if (lowest_ankle_position_z == head_bone_position.z)
            {
                if ((height_diff - head_bone_position.z) >= 0.f)
                {
                    head_adjust = 0.7740f;
                    goto LABEL_62;
                }
            LABEL_60:
                head_adjust = 0.f;
            }
            else
            {
                auto height_lerp = (height_diff - lowest_ankle_position_z) / (head_bone_position.z - lowest_ankle_position_z);
                if (height_lerp < 0.f)
                    goto LABEL_60;

                head_adjust = std::min(height_lerp, 1.f);
            }
        LABEL_62:
            height_amount = head_bone_position.z - head_position_to_change.z;
        }
    LABEL_63:
        current_bone_origin -= (head_pos_difference * head_adjust);
        current_bone.set_origin(current_bone_origin);
    }

    if (solve_left_ik)
        studio_solve_ik(left_chain->link(0)->bone, left_chain->link(1)->bone, left_ankle_bone, left_ankle_bone_position, matrix);

    if (solve_right_ik)
        studio_solve_ik(right_chain->link(0)->bone, right_chain->link(1)->bone, right_ankle_bone, right_ankle_bone_position, matrix);
}

void c_bone_builder::store(c_cs_player* player, matrix3x4_t* matrix, int mask, c_studio_hdr* hdr, int* flags_base, int parent_count)
{
    animating = player;
    this->hdr = hdr;

    layers = player->animlayers();
    layer_count = player->animlayers_count();

    time = player == HACKS->local ? HACKS->predicted_time : player->sim_time();

    angles = player->get_abs_angles();
    origin = HACKS->local ? player->get_abs_origin() : player->origin();

    this->matrix = matrix ? matrix : player->bone_cache().base();
    this->mask = mask & ~BONE_USED_BY_BONE_MERGE;

    attachments = false;
    ik_ctx = false;
    dispatch = true;

    bone_flags_base = flags_base;
    bone_parent_count = parent_count;

    player->store_poses(poses.data());
    eye_angles = player->eye_angles();

    auto weapon = (c_base_combat_weapon*)(HACKS->entity_list->get_client_entity_handle(player->active_weapon()));

    c_cs_player* world_weapon = nullptr;
    if (weapon)
        world_weapon = (c_cs_player*)(HACKS->entity_list->get_client_entity_handle(weapon->weapon_world_model()));

    if (world_weapon)
        math::memcpy_sse(poses_world.data(), world_weapon->pose_parameter(), sizeof(float) * 24);
    else
        math::memcpy_sse(poses_world.data(), player->pose_parameter(), sizeof(float) * 24);

    filled = true;
}

void c_bone_builder::setup_bones()
{
    alignas(16) vec3_t position[128] = { };
    alignas(16) quaternion_t q[128] = { };

    auto anim = ANIMFIX->get_anims(animating->index());
    auto ik_context = (c_ik_context*)animating->ik_ctx();

    if (!ik_ctx)
        ik_context = nullptr;

    hdr = animating->get_studio_hdr();

    if (!hdr)
        return;

    uint32_t bone_computed[8]{};
    std::memset(bone_computed, 0, 8 * sizeof(uint32_t));

    bool sequences_available = ![I](int[/I])([I](uintptr_t[/I])hdr + 0x150) || [I](int[/I])((uintptr_t)hdr + 0x4);

    if (ik_context)
    {
        ik_context->init(hdr, &angles, &origin, time, TIME_TO_TICKS(HACKS->global_vars->framecount), mask);

        if (sequences_available)
            get_skeleton(position, q);

        // animating->standard_blending_rules(hdr, position, q, time, BONE_USED_BY_ANYTHING);

        animating->update_ik_locks(time);
        ik_context->update_targets(position, q, matrix, (uint8_t*)bone_computed);

        animating->calc_ik_locks(time);
        ik_context->solve_dependencies(position, q, matrix, (uint8_t*)bone_computed);
    }
    else if (sequences_available)
        get_skeleton(position, q);

    matrix3x4_t transform{};
    transform.angle_matrix(angles, origin);

    studio_build_matrices(hdr, transform, position, q, mask, matrix, bone_computed);

    if (mask & BONE_USED_BY_ATTACHMENT && attachments)
        animating->attachments_helper();

    animating->last_bone_setup_time() = time;

    animating->bone_accessor()->readable_bones |= mask;
    animating->bone_accessor()->writable_bones |= mask;

    static auto invalidate_bone_cache = offsets::invalidate_bone_cache.cast<std::uint64_t>();
    static auto model_bone_counter = [I](std::uintptr_t[/I])(invalidate_bone_cache + 0xA);

    animating->model_recent_bone_counter() = [I](std::uint32_t[/I])model_bone_counter;

    const auto mdl = animating->get_model();
    if (!mdl)
        return;

    auto hdr = HACKS->model_info->get_studio_model(mdl);
    if (!hdr)
        return;

    const auto hitbox_set = hdr->hitbox_set(animating->hitbox_set());
    if (!hitbox_set)
        return;

    for (int i{}; i < hitbox_set->num_hitboxes; ++i)
    {
        const auto hitbox = hitbox_set->hitbox(i);
        if (!hitbox || hitbox->radius >= 0.f)
            continue;

        matrix3x4_t rot_mat{};
        rot_mat.angle_matrix(hitbox->rotation);
        rot_mat.contact_transforms(matrix[hitbox->bone]);
    }

    if (animating == HACKS->local)
    {
        clamp_bones_info_t info{};
        info.store(animating);

        clamp_bones_in_bbox(animating, matrix, mask, time, animating->eye_angles(), info);
    }
}

INLINE bool can_be_animated(c_cs_player* player)
{
    if (!player->use_new_animstate() || !player->animstate())
        return false;

    auto weapon = (c_base_combat_weapon*)(HACKS->entity_list->get_client_entity_handle(player->active_weapon()));

    if (!weapon)
        return false;

    auto world_model = (c_cs_player*)(HACKS->entity_list->get_client_entity_handle(weapon->weapon_world_model()));
    if (!world_model || [I](short[/I])((std::uintptr_t)world_model + 0x26E) == -1)
        return player == HACKS->local;

    return true;
}

INLINE float get_pose_parameter_value(c_studio_hdr* hdr, int index, float value)
{
    if (index < 0 || index > 24)
        return 0.f;

    auto pose_parameter = get_pose_param(hdr, index);
    if (!pose_parameter)
        return 0.f;

    if (pose_parameter->loop)
    {
        float wrap = (pose_parameter->start + pose_parameter->end) / 2.f + pose_parameter->loop / 2.f;
        float shift = pose_parameter->loop - wrap;

        value = value - pose_parameter->loop * std::floorf((value + shift) / pose_parameter->loop);
    }

    return (value - pose_parameter->start) / (pose_parameter->end - pose_parameter->start);
}

void merge_matching_poses(std::uintptr_t& bone_merge, float* poses, float* target_poses)
{
    bone_merge::update_cache(bone_merge);

    if ([I](std::uintptr_t[/I])(bone_merge + 0x10) && [I](std::uintptr_t[/I])(bone_merge + 0x8C))
    {
        int* index = (int*)(bone_merge + 0x20);

        for (int i = 0; i < 24; ++i)
        {
            if (*index != -1)
            {
                c_cs_player* target = [I](c_cs_player*[/I])(bone_merge + 0x4);
                c_studio_hdr* hdr = target->get_studio_hdr();
                float pose_param_value = 0.f;

                if (hdr && [I](studiohdr_t*[/I])hdr && i >= 0)
                {
                    float pose = target_poses[i];
                    auto pose_param = get_pose_param(hdr, i);

                    pose_param_value = pose * (pose_param->end - pose_param->start) + pose_param->start;
                }

                c_cs_player* second_target = [I](c_cs_player*[/I])(bone_merge);
                c_studio_hdr* second_hdr = second_target->get_studio_hdr();

                poses[*index] = get_pose_parameter_value(second_hdr, *index, pose_param_value);
            }

            ++index;
        }
    }
}

void c_bone_builder::get_skeleton(vec3_t* position, quaternion_t* q)
{
    alignas(16) vec3_t new_position[128]{};
    alignas(16) quaternion_t new_q[128]{};

    auto ik_context = (c_ik_context*)animating->ik_ctx();

    if (!ik_ctx)
        ik_context = nullptr;

    alignas(16) char buffer[32];
    alignas(16) bone_setup_t* bone_setup = (bone_setup_t*)&buffer;

    bone_setup->hdr = hdr;
    bone_setup->mask = mask;
    bone_setup->pose_parameter = poses.data();
    bone_setup->pose_debugger = nullptr;

    bone_setup->init_pose(position, q, hdr);
    bone_setup->accumulate_pose(position, q, animating->sequence(), animating->cycle(), 1.f, time, ik_context);

    int layer[13] = { };

    for (int i = 0; i < layer_count; ++i)
    {
        c_animation_layers& final_layer = layers[i];

        if (final_layer.weight > 0.f && final_layer.order != 13 && final_layer.order >= 0 && final_layer.order < layer_count)
            layer[final_layer.order] = i;
    }

    char tmp_buffer[4208]{};
    auto world_ik = (c_ik_context*)tmp_buffer;

    auto weapon = (c_base_combat_weapon*)HACKS->entity_list->get_client_entity_handle(animating->active_weapon());
    c_cs_player* world_weapon = nullptr;
    if (weapon)
        world_weapon = (c_cs_player*)HACKS->entity_list->get_client_entity_handle(weapon->weapon_world_model());

    auto wrong_weapon = [&]()
        {
            if (can_be_animated(animating) && world_weapon)
            {
                uintptr_t bone_merge = bone_merge::get_bone_merge(world_weapon);
                if (bone_merge)
                {
                    merge_matching_poses(bone_merge, poses_world.data(), poses.data());

                    auto world_hdr = world_weapon->get_studio_hdr();

                    world_ik->constructor();
                    world_ik->init(world_hdr, &angles, &origin, time, 0, mask);

                    alignas(16) char buffer2[32]{};
                    alignas(16) bone_setup_t* world_setup = (bone_setup_t*)&buffer2;

                    world_setup->hdr = world_hdr;
                    world_setup->mask = mask;
                    world_setup->pose_parameter = poses_world.data();
                    world_setup->pose_debugger = nullptr;

                    world_setup->init_pose(new_position, new_q, world_hdr);

                    for (int i = 0; i < layer_count; ++i)
                    {
                        c_animation_layers* layer = &layers[i];

                        if (layer && layer->sequence > 1 && layer->weight > 0.f)
                        {
                            if (dispatch && animating == HACKS->local)
                                animating->update_dispatch_layer(layer, world_hdr, layer->sequence);

                            if (!dispatch || layer->second_dispatch_sequence <= 0 || layer->second_dispatch_sequence >= ([I](studiohdr_t*[/I])world_hdr)->local_seq)
                                bone_setup->accumulate_pose(position, q, layer->sequence, layer->cycle, layer->weight, time, ik_context);
                            else if (dispatch)
                            {
                                static auto copy_from_follow = offsets::copy_from_follow.cast<void(__thiscall*)(std::uintptr_t, vec3_t*, quaternion_t*, int, vec3_t*, quaternion_t*)>();
                                static auto add_dependencies = offsets::add_dependencies.cast<void(__thiscall*)(c_ik_context*, float, int, int, const float[], float)>();
                                static auto copy_to_follow = offsets::copy_to_follow.cast<void(__thiscall*)(std::uintptr_t, vec3_t*, quaternion_t*, int, vec3_t*, quaternion_t*)>();

                                copy_from_follow(bone_merge, position, q, mask, new_position, new_q);
                                if (ik_context)
                                    add_dependencies(ik_context, [I](float[/I])((std::uintptr_t)animating + 0xA14), layer->sequence, layer->cycle, poses.data(), layer->weight);

                                world_setup->accumulate_pose(new_position, new_q, layer->second_dispatch_sequence, layer->cycle, layer->weight, time, world_ik);
                                copy_to_follow(bone_merge, new_position, new_q, mask, position, q);
                            }
                        }
                    }

                    world_ik->destructor();
                    return false;
                }
            }
            return true;
        };

    if (wrong_weapon())
    {
        for (int i = 0; i < this->layer_count; ++i)
        {
            int layer_count = layer[i];

            if (layer_count >= 0 && layer_count < this->layer_count)
            {
                c_animation_layers* final_layer = &layers[i];
                bone_setup->accumulate_pose(position, q, final_layer->sequence, final_layer->cycle, final_layer->weight, time, ik_context);
            }
        }
    }

    if (ik_context)
    {
        world_ik->constructor();
        world_ik->init(hdr, &angles, &origin, time, 0, mask);
        bone_setup->calc_autoplay_sequences(position, q, time, world_ik);
        world_ik->destructor();
    }
    else
        bone_setup->calc_autoplay_sequences(position, q, time, nullptr);

    bone_setup->calc_bone_adjust(position, q, (float*)((std::uintptr_t)animating + 0xA54), mask);
}

void c_bone_builder::studio_build_matrices(c_studio_hdr* hdr, const matrix3x4_t& world_transform, vec3_t* pos, quaternion_t* q, int mask, matrix3x4_t* out, uint32_t* bone_computed)
{
    int i = 0;
    int chain_length = 0;
    int bone = -1;
    auto studio_hdr = [I](studiohdr_t*[/I])hdr;

    if (bone < -1 || bone >= studio_hdr->bones)
        bone = 0;

    c_utl_vector<int>* bone_parent = (c_utl_vector<int>*)((std::uintptr_t)hdr + 0x44);
    c_utl_vector<int>* bone_flags = (c_utl_vector<int>*)((std::uintptr_t)hdr + 0x30);

    int chain[128]{};
    if (bone <= -1)
    {
        chain_length = studio_hdr->bones;

        for (i = 0; i < studio_hdr->bones; ++i)
            chain[chain_length - i - 1] = i;
    }
    else
    {
        i = bone;

        do
        {
            chain[chain_length++] = i;
            i = bone_parent->element(i);

        } while (i != -1);
    }

    matrix3x4_t bone_matrix{};
    for (int j = chain_length - 1; j >= 0; --j)
    {
        i = chain[j];

        if ((1 << (i & 0x1F)) & bone_computed[i >> 5])
            continue;

        int flag = bone_flags->element(i);
        int parent = bone_parent->element(i);

        if ((flag & mask) && q)
        {
            bone_matrix.quaternion_matrix(q[i], pos[i]);

            if (parent == -1)
                out[i] = world_transform.contact_transforms(bone_matrix);
            else
                out[i] = out[parent].contact_transforms(bone_matrix);
        }
    }
}


C++:
Expand Collapse Copy
#pragma once

struct anim_record_t;

namespace bone_merge
{
    std::uintptr_t& get_bone_merge(c_cs_player* player);
    void update_cache(std::uintptr_t& bone_merge);
}

struct clamp_bones_info_t
{
    float collision_change_time{};
    float collision_change_origin{};

    vec3_t origin{};
    vec3_t collision_origin{};
    vec3_t view_offset{};

    vec3_t mins{};
    vec3_t maxs{};

    std::uint32_t ground_entity{};

    void store(c_cs_player* player);
    void store(anim_record_t* record);
};

extern float get_pose_parameter_value(c_studio_hdr* hdr, int index, float value);

class c_bone_builder
{
private:
    void get_skeleton(vec3_t* position, quaternion_t* q);
    void studio_build_matrices(c_studio_hdr* hdr, const matrix3x4_t& world_transform, vec3_t* pos, quaternion_t* q, int mask, matrix3x4_t* out, uint32_t* bone_computed);

public:
    bool filled{};

    bool ik_ctx{};
    bool attachments{};
    bool dispatch{};

    int mask{};
    int layer_count{};

    int* bone_flags_base{};
    int bone_parent_count{};

    float time{};
    float pred_time{};

    matrix3x4_t* matrix{};
    c_studio_hdr* hdr{};
    c_animation_layers* layers{};
    c_cs_player* animating{};

    vec3_t origin{};
    vec3_t angles{};
    vec3_t eye_angles{};

    std::array<float, 24> poses{};
    std::array<float, 24> poses_world{};

    void clamp_bones_in_bbox(c_cs_player* player, matrix3x4_t* matrix, int mask, float curtime, vec3_t& eye_angles, clamp_bones_info_t& clamp_info);
    void store(c_cs_player* player, matrix3x4_t* matrix, int mask, c_studio_hdr* hdr, int* flags_base, int parent_count);

    void setup_bones();

    INLINE void reset()
    {
        filled = false;
        ik_ctx = false;
        attachments = false;
        bone_parent_count = false;

        mask = 0;
        layer_count = 0;
        layer_count = 0;

        time = 0.f;
        pred_time = 0.f;

        matrix = nullptr;
        hdr = nullptr;
        layers = nullptr;
        animating = nullptr;
        bone_flags_base = nullptr;

        origin.reset();
        angles.reset();
        eye_angles.reset();

        poses = {};
        poses_world = {};
    }
};

was done hastily, there are problems and flaws, there is anti-pasta!
 
  • Мне нравится
Реакции: mj12
i am sorry, havent been there active long time, what did i miss, why does peoples just sending public code from hack that includes in topic??? lmfao

there is nothing useful nobody cares about ur server bones cause just no need lol
 
  • Мне нравится
Реакции: mj12
Назад
Сверху Снизу