#27 Re: Вопросы по скриптингу » Деление HEX числа на разряды » 23-05-2017 09:32

Так лучше не делать - может возникнуть проблема с Limit Adjuster, где выделяется новый массив указателей на model info.
Есть функция, которая возвращает model info по ид модели.

0x403DA0  ; CBaseModelInfo *__cdecl CModelInfo::GetModelInfo(int modelId)

#28 Re: Вопросы по скриптингу » Деление HEX числа на разряды » 20-05-2017 08:42

Записываешь в ячейку массива число.
Сдвигаешь на (7 - i) * 4 бит вправо (i - номер элемента в массиве, начиная с 0) (Rsh).
Убираешь всё, кроме нижних 4 бит (And).

#29 Re: Вопросы по скриптингу » Увеличение лимита обновления TXD файла » 14-05-2017 10:42

Должны, но не выгружаются.

{$CLEO .cs}
 
0000:
while 8AB0: is_key_pressed 9
    wait 0
end  
 
while true 
    0390: load_texture_dictionary 'LD_CARD'
    038F: load_sprite 1 from "cd1s"
    03F0: use_text_commands 1
    038D: draw_sprite 1 position 590.0 390.0 size 50.0 50.0 colour 255 255 255 255
    wait 0    
    0@ += 1  
    03F0: use_text_commands 0
    0AA5: call_function 0x82D4C0 num_params 3 pop 3 8 0 1@v
    0AA5: call_function 0x801E90 num_params 3 pop 3 1@v 0x804B60 0xC97B28 
    0AA5: call_function 0x801E90 num_params 3 pop 3 2@v 0x804B60 0xC97B54
    0A8D: read_memory 0xC8800C size 4 vp 0 store_to 5@
    0A8E: 3@ = 5@ + 0x8
    0A8D: read_memory 3@ size 4 vp 0 store_to 3@
    0AA8: call_method_return 0x54F6B0 struct 5@ num_params 0 pop 0 store_to 4@
    0AD1: print_formatted_now "Times Loaded: %u~n~Engine Txds: %u Engine Textures: %u~n~Txd Pool capacity: %u Txd Pool size: %u" time 150 0@ 1@ 2@ 3@ 4@
    0391: remove_texture_dictionary
end

#30 Re: Вопросы по скриптингу » Увеличение лимита обновления TXD файла » 11-05-2017 19:31

Попробуй написать скрипт, в котором идёт загрузка и выгрузка txd. Проверь, повторится ли там эта проблема.

#31 Re: Вопросы по скриптингу » Проверка после лоадскрина » 09-05-2017 17:39

Нету такого "адреса" и опкода.

Можно создать счётчик, который будет хранить кол-во "стартов" игры. Если этот счётчик больше 1 - значит, был произведён перезапуск.

Т.е. надо будет самому создать такой опкод - например, с CLEO SDK.

#32 Re: Вопросы по скриптингу » Проверка после лоадскрина » 09-05-2017 14:12

Не думаю, что есть такие "адреса".
Можно создать счётчик, который будет хранить кол-во "стартов" игры. Если этот счётчик больше 1 - значит, был произведён перезапуск.

#33 Re: Работа с памятью, EXE » база GTA III.idb (exe 1.0) » 19-04-2017 13:50

Некоторые структуры

https://drive.google.com/uc?export=down … FgtMHhHcTA

Что делать:
В IDA:

File -> Load file -> Parse C header file -> Выбрать gta3.h

Перейти на вкладку Local Types

View -> Open subviews -> Local types

В этой вкладке:

Выделить всё содержимое (Ctrl+A) -> ПКМ -> Synchronize to idb

#34 Re: Справочная информация » Новый сайт БД Опкодов » 06-04-2017 20:48

Используй базу на сайте GTAG для поиска опкодов.
http://gtag.gtagaming.com/opcode-database/opcode/05C5/

Или установи последнюю версию SB c этими опкодами.
Хотя, я не уверен, что после такого получится нормально компилировать уже готовые исходники скриптов (может поменяться порядок параметров в опкоде)

#35 Re: Работа с памятью, EXE » база GTA III.idb (exe 1.0) » 17-03-2017 19:58

Молодец.
Сколько времени ушло на это?  wow

#36 Re: Вопросы по скриптингу » Один вопрос » 05-03-2017 19:17

Shag wrote:
DK22Pac wrote:

Вот небольшая програмка, которая заменяет все "проблемные" float-числа на целые.
http://i.imgur.com/FhVHspIm.png

http://cpp.sh/6pp4

Использование: скопировать код своего скрипта, запустить на выполнение ("Run").

Круто, но к сожалению, работает только если число отделено пробелами. Запись

0@ = Object.Create(#lc_sky04, -3500.0, 0.0, -50.0)

не "видит", пока число не отделено так:

0@ = Object.Create(#lc_sky04, -3500.0 , 0.0, -50.0)

Спасибо, поправил.
http://cpp.sh/4bpp

PS Эта проблема не относится к Vice City, там float 4-байтный.

#37 Re: Вопросы по скриптингу » Один вопрос » 04-03-2017 21:49

Вот небольшая програмка, которая заменяет все "проблемные" float-числа на целые.
FhVHspIm.png

http://cpp.sh/6pp4

Использование: скопировать код своего скрипта, запустить на выполнение ("Run").

#38 Re: Вопросы по скриптингу » Как узнать значение полоски запаса воздуха? » 04-03-2017 14:26

Вариант #1 (самый простой и самый быстрый) - написать свой опкод, используя CLEO SDK и plugin-sdk.
Самое главное преимущество такого подхода, относительно скрипта - то, что скрипт остается "чистым" и понятным.

{$CLEO}
{$OPCODE 1A04=2,%2d% = get_player %1d% breath_percentage}
0000:
while true
    wait 0
    if
        0256: is_player_playing 0
    then
        1A04: 0@ = get_player 0 breath_percentage
        0AD1: print_formatted_now "%.2f" time 100 0@
    end
end

Код опкода

// 1A04: 0@ = get_player 0 breath_percentage
static OpcodeResult WINAPI Opcode_GetPlayerBreathPercentage(CScriptThread *thread) {
    int playerId = CLEO_GetIntOpcodeParam(thread);
    if ((playerId == 0 || playerId == 1) && CWorld::Players[playerId].m_pPed)
        CLEO_SetFloatOpcodeParam(thread, CWorld::Players[playerId].m_pPed->m_pPlayerData->m_fBreath / CallAndReturn<float, 0x559AF0>(8));
    else
        CLEO_SetFloatOpcodeParam(thread, 0.0f);
    return OR_CONTINUE;
}

Вариант #2 (для извращенцев)

{$CLEO}
0AC6: get_label_pointer @pop_float store_to 31@
while true
    wait 0
    if
        0256: is_player_playing 0
    then
        01F5: get_player_char 0 store_to 0@
        0A96: get_char_pointer 0@ store_to 1@
        1@ += 0x480
        0A8D: read_memory 1@ size 4 vp 0 store_to 1@
        1@ += 0x44
        0A8D: read_memory 1@ size 4 vp 0 store_to 1@
        0AA5: call_function 0x559AF0 num_params 1 pop 1 params 8
        0AC7: get_var_pointer 2@ store_to 3@
        0AA5: call_function 31@ num_params 1 pop 1 params 3@
        0073: 1@ /= 2@
        0AD1: print_formatted_now "%.2f" time 100 1@
    end
end

:pop_float
hex
    8B 44 24 04 // mov eax, [esp + 4]
    D9 18       // fstp [eax]
    C3          // retn
end

Вариант #3 (для психопатов)
UP: Передумал писать...  crazy

#39 Re: Вопросы по скриптингу » Один вопрос » 04-03-2017 07:36

DimZet13 wrote:

все float(дробные числа) компилируются в короткий float(2 байта), а то есть значения не точные и нельзя выставить значение выше 2048.0

Это лимит скриптового движка игры, а не SannyBuilder'а.

DimZet13 wrote:

после декомпиляции переводит в Dword(4 байта целые числа). А если дело касается минусовых, то вообще не вообще не восстановить(ctrl+H).
Вопрос: как все это исправить?

Разобраться, что такое исходный файл и не декомпилировать свои скрипты.

DimZet13 wrote:

как сделать так чтобы 3000.0 компилировался в нормальный float(453B8000)

Внести изменения в скриптовый движок игры. Добавить новый тип параметра - 4-байтный float, его чтение и запись.
Написать программу, которая бы в скомпилировааном скрипте заменяла все 2-байтные float на этот новый тип.

#40 Re: Вопросы по скриптингу » Получение названия анимации игрока » 28-02-2017 21:06

Jack_Savage, самое простое решение - переустановить студию, при установке выбирать Windows SDK. Ну и поддержку WinXP не забыть.
https://github.com/DK22Pac/plugin-sdk/w … -Community

#41 Re: Вопросы по скриптингу » Получение названия анимации игрока » 28-02-2017 20:53

В plugin-sdk есть пример по спавну педа.
https://github.com/DK22Pac/plugin-sdk/t … PedSpawner
Можно вызвать функцию CPopulation::AddPed или самому создать обьект класса CCivilianPed/CCopPed/CEmergencyPed и настроить ему позицию (CPlaceable::SetPosn) и добавить в игровой мир (CWorld::Add)

#42 Re: Вопросы по скриптингу » Получение названия анимации игрока » 28-02-2017 20:46

plugin.lib получается после сборки проекта plugin_sa в решении plugin-sdk.

picture.png

#43 Re: Вопросы по скриптингу » Получение названия анимации игрока » 28-02-2017 19:35

Нет. Опкоды я визываю через SCM hook в C++

Что значит "аля asi"? Это динамическая библиотека? Чем она подгружается, если не asi-loader'ом?

Кламп это графический обьект RenderWare.

"Взять" его можно в plugin-sdk, подключив хедер RenderWare.h.

Можешь выложить проект со своим плагином, я тебе помогу подключить туда библиотеку и хедеры plugin-sdk.

#44 Re: Вопросы по скриптингу » Один вопрос » 27-02-2017 17:36

Zin_869731, как варианты - нету нужных прав (администраторских) для внесения изменений, какие-то проблемы с интернет-соединением (часть пакетов докачивается уже при установке), не хватает места на диске.

Ещё тут можно посмотреть
https://support.microsoft.com/ru-ru/hel … 2015-setup

VS2017 я сам ещё не пробовал. Может попробуешь VS2015?

#45 Re: Вопросы по скриптингу » Получение названия анимации игрока » 26-02-2017 10:37

Хук ставится в место, где название анимации "переводится" в хеш. Делаем это для того, чтобы иметь возможность "перевести" хеш обратно в название (сохраняем название в карту с ключом-хешем).

static CdeclEvent<AddressList<0x4CF2D8, H_CALL>, PRIORITY_AFTER, ArgPickN<char *, 0>, unsigned int(char *)> myStoreAnimNameEvent; // Хук
 
myStoreAnimNameEvent += [](char *name) {
    animNamesMap[CKeyGen::GetUppercaseKey(name)] = name; // Сохраняем в карту
};

Получаем кол-во активных анимаций педа. Одновременно пед может проигрывать несколько анимаций (например - стоит и прицеливается)

unsigned int numAnimations = RpAnimBlendClumpGetNumAssociations(ped->m_pRwClump);
    if (numAnimations > 0) { // Если есть анимации

Получаем описание первой анимации

CAnimBlendAssociation *association = RpAnimBlendClumpGetFirstAssociation(ped->m_pRwClump);

Переводим хеш в название, используя нашу карту

sprintf(text, "%d. %s", counter + 1, animNamesMap[association->m_pAnimBlendHierarchy->m_hashKey].c_str());

В цикле получаем следующую анимацию, таким образом, "проходимся" по всем анимациям.

association = RpAnimBlendGetNextAssociation(association);

Ну и, если пишешь код C++ - надо искать хотя бы уроки в интернете и разбираться.

#46 Re: Вопросы по скриптингу » Получение названия анимации игрока » 25-02-2017 23:27

http://cleo.li/ru/plugins.html

CLEO 4 позволяет создавать новые опкоды, используя исходные коды CLEO SDK. В стартовом комплекте библиотеки можно найти три примера таких плагинов:

IniFiles.cleo - работа с INI файлами;
FileSystemOperations.cleo - работа с файлами и папками.
IntOperations.cleo - битовые операции над целыми числами (AND, OR, XOR, и т.д.).

#include "plugin.h"
#include "CLEO.h"
#include "game_sa\CPools.h"
#include "game_sa\common.h"
#include "game_sa\CKeyGen.h"
#include <map>

using namespace plugin;

/*
   SASCM.ini

1A01=2,%2d% = get_char %1d% num_of_active_animations
1A02=2,%2d% = get_char %1d% active_animations
1A03=2,%2d% = get_char %1d% main_active_animation

   opcodes.txt

1A01: 0@ = get_char 1@ num_of_active_animations
1A02: 0@v = get_char 1@ active_animations
1A03: 0@v = get_char 1@ main_active_animation
*/

class GetPedAnimationOpcodes {
public:
    static char animNameGlobalName[1024];
    static std::map<unsigned int, std::string> animNamesMap;
    static CdeclEvent<AddressList<0x4CF2D8, H_CALL>, PRIORITY_AFTER, ArgPickN<char *, 0>, unsigned int(char *)> myStoreAnimNameEvent;

    static void MyStoreAnimName(char *name) {
        animNamesMap[CKeyGen::GetUppercaseKey(name)] = name;
    }

    // 1A01: 0@ = get_char 1@ num_of_active_animations
    static OpcodeResult WINAPI Opcode_GetPedNumberOfActiveAnimations(CScriptThread *thread) {
        CPed *ped = CPools::GetPed(CLEO_GetIntOpcodeParam(thread));
        if (ped && ped->m_pRwClump)
            CLEO_SetIntOpcodeParam(thread, RpAnimBlendClumpGetNumAssociations(ped->m_pRwClump));
        else
            CLEO_SetIntOpcodeParam(thread, 0);
        return OR_CONTINUE;
    }

    // 1A02: 0@v = get_char 1@ active_animations
    static OpcodeResult WINAPI Opcode_GetPedAnimationsNames(CScriptThread *thread) {
        CPed *ped = CPools::GetPed(CLEO_GetIntOpcodeParam(thread));
        animNameGlobalName[0] = '\0';
        if (ped && ped->m_pRwClump) {
            CAnimBlendAssociation *association = RpAnimBlendClumpGetFirstAssociation(ped->m_pRwClump);
            if(association){
                strcpy_s(animNameGlobalName, animNamesMap[association->m_pAnimBlendHierarchy->m_hashKey].c_str());
                for (association = RpAnimBlendGetNextAssociation(association); association; association = RpAnimBlendGetNextAssociation(association)) {
                    strcat_s(animNameGlobalName, ",");
                    strcat_s(animNameGlobalName, animNamesMap[association->m_pAnimBlendHierarchy->m_hashKey].c_str());
                }
            }
        }
        int paramType = CLEO_GetOperandType(thread);
        if (paramType == localVarVString || paramType == localVarSString)
            CLEO_WriteStringOpcodeParam(thread, animNameGlobalName);
        else
            CLEO_SetIntOpcodeParam(thread, reinterpret_cast<int>(animNameGlobalName));
        return OR_CONTINUE;
    }

    // 1A03: 0@v = get_char 1@ main_active_animation
    static OpcodeResult WINAPI Opcode_GetPedMainAnimationName(CScriptThread *thread) {
        CPed *ped = CPools::GetPed(CLEO_GetIntOpcodeParam(thread));
        animNameGlobalName[0] = '\0';
        if (ped && ped->m_pRwClump) {
            CAnimBlendAssociation *association = RpAnimBlendClumpGetMainAssociation(ped->m_pRwClump, NULL, NULL);
            if(association)
                strcpy_s(animNameGlobalName, animNamesMap[association->m_pAnimBlendHierarchy->m_hashKey].c_str());
        }
        int paramType = CLEO_GetOperandType(thread);
        if (paramType == localVarVString || paramType == localVarSString)
            CLEO_WriteStringOpcodeParam(thread, animNameGlobalName);
        else
            CLEO_SetIntOpcodeParam(thread, reinterpret_cast<int>(animNameGlobalName));
        return OR_CONTINUE;
    }

    GetPedAnimationOpcodes() {
        CLEO_RegisterOpcode(0x1A01, Opcode_GetPedNumberOfActiveAnimations);
        CLEO_RegisterOpcode(0x1A02, Opcode_GetPedAnimationsNames);
        CLEO_RegisterOpcode(0x1A03, Opcode_GetPedMainAnimationName);
        myStoreAnimNameEvent.Add(MyStoreAnimName);
    }
} pedAnimOpcodes;

char GetPedAnimationOpcodes::animNameGlobalName[1024];
std::map<unsigned int, std::string> GetPedAnimationOpcodes::animNamesMap;
CdeclEvent<AddressList<0x4CF2D8, H_CALL>, PRIORITY_AFTER, ArgPickN<char *, 0>, unsigned int(char *)> GetPedAnimationOpcodes::myStoreAnimNameEvent;
{$CLEO}

{$OPCODE 1A01=2,%2d% = get_char %1d% num_of_active_animations}
{$OPCODE 1A02=2,%2d% = get_char %1d% active_animations}
{$OPCODE 1A03=2,%2d% = get_char %1d% main_active_animation}

thread 'ANIMOPC'

while true
    wait 0
    if
        0256: is_player_playing 0
    then
        01F5: get_player_char 0 store_to 0@
        1A02: 1@ = get_char 0@ active_animations
        0ACC: print_string 1@ time 100
    end
end

#48 Re: Вопросы по скриптингу » 2 условия в while » 25-02-2017 22:30

В конструкцию к while можно подставить только одно условие. Но можно сделать так:

while true
     wait 0 // не забываем добавить задержку в цикл с (вероятно) большим кол-вом повторений

    // обновляем 2@
    
    if or
        2@ < 50
        2@ > 78
    then
        break
    end
end

#49 Re: Вопросы по скриптингу » Получение названия анимации игрока » 25-02-2017 22:19

Cпасибо, я не хочу юзать plugin sdk просто я не понимаю что там и как вообще...

Ну тогда не знаю, как тебе ещё помочь  yahoo
Такой код

*(int*)0xB6F5F0 + 0x15C;

я писать не буду.

Могу опкодами сделать, разве что.

int numAnimations = RpAnimBlendClumpGetNumAssociations(ped->m_pRwClump);

Эта функция получает кол-во активных анимаций, прицепленных к клампу.

#50 Re: Вопросы по скриптингу » Получение названия анимации игрока » 25-02-2017 22:09

Вот пример с использованием plugin-sdk - вывод списка анимаций игрока.

Main.cpp

#include "plugin.h"
#include "game_sa\common.h"
#include "game_sa\CFont.h"
#include "game_sa\CSprite2d.h"
#include "game_sa\CKeyGen.h"
#include <map>

using namespace plugin;

class AnimNamesViewer {
public:
    AnimNamesViewer() {
        static std::map<unsigned int, std::string> animNamesMap;
        static CdeclEvent<AddressList<0x4CF2D8, H_CALL>, PRIORITY_AFTER, ArgPickN<char *, 0>, unsigned int(char *)> myStoreAnimNameEvent;

        myStoreAnimNameEvent += [](char *name) {
            animNamesMap[CKeyGen::GetUppercaseKey(name)] = name;
        };

        Events::drawingEvent += [] {
            CPed *ped = FindPlayerPed();
            if (ped && ped->m_pRwClump) {
                unsigned int numAnimations = RpAnimBlendClumpGetNumAssociations(ped->m_pRwClump);
                if (numAnimations > 0) {
                    CSprite2d::DrawRect(CRect(SCREEN_COORD_RIGHT(310.0f), SCREEN_COORD(265.0f), SCREEN_COORD_RIGHT(40.0f),
                        SCREEN_COORD(275.0f + 50.0f * numAnimations)), CRGBA(30, 30, 30, 255));
                    CFont::SetAlignment(ALIGN_LEFT);
                    CFont::SetColor(CRGBA(255, 255, 255, 255));
                    CFont::SetOutlinePosition(0);
                    CFont::SetDropColor(CRGBA(0, 0, 0, 255));
                    CFont::SetFontStyle(FONT_MENU);
                    CFont::SetProp(true);
                    CFont::SetWrapx(SCREEN_COORD_MAX_X * 2);
                    CFont::SetBackground(false, false);
                    int counter = 0;
                    CAnimBlendAssociation *association = RpAnimBlendClumpGetFirstAssociation(ped->m_pRwClump);
                    while (association) {
                        static char text[256];
                        sprintf(text, "%d. %s", counter + 1, animNamesMap[association->m_pAnimBlendHierarchy->m_hashKey].c_str());
                        if (association->m_wFlags & 0x10)
                            strcat(text, " (P)");
                        CFont::SetScale(SCREEN_MULTIPLIER(0.6f), SCREEN_MULTIPLIER(1.2f));
                        float width = CFont::GetStringWidth(text, true, false);
                        if(width > SCREEN_COORD(250.0f))
                            CFont::SetScale(SCREEN_MULTIPLIER(0.6f * SCREEN_COORD(250.0f) / width), SCREEN_MULTIPLIER(1.2f));
                        float baseY = SCREEN_COORD(300.0f) + SCREEN_COORD(50.0f) * counter;
                        CFont::PrintString(SCREEN_COORD_RIGHT(300.0f), baseY - SCREEN_COORD(25.0f), text);
                        CSprite2d::DrawRect(CRect(SCREEN_COORD_RIGHT(300.0f), baseY, SCREEN_COORD_RIGHT(50.0f), baseY + SCREEN_COORD(8.0f)),
                            CRGBA(130, 130, 130, 255));
                        CSprite2d::DrawRect(CRect(SCREEN_COORD_RIGHT(300.0f), baseY,
                            SCREEN_COORD_RIGHT(300.0f - association->m_fCurrentTime / association->m_pAnimBlendHierarchy->m_fTotalTime * 250.0f),
                            baseY + SCREEN_COORD(6.0f)), CRGBA(210, 210, 210, 255));
                        association = RpAnimBlendGetNextAssociation(association);
                        ++counter;
                    }
                    CFont::DrawFonts();
                }
            }
        };
    }
} animNamesView;

d2DHIZjm.jpg

При желании можно оформить в виде опкода.

Board footer

Powered by FluxBB