Quantcast
Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
    1. Welcome to GTAForums!

    1. GTANet.com

    1. GTA Online

      1. The Diamond Casino Heist
      2. Find Lobbies & Players
      3. Guides & Strategies
      4. Vehicles
      5. Content Creator
      6. Help & Support
    2. Red Dead Online

      1. Frontier Pursuits
      2. Find Lobbies & Outlaws
      3. Help & Support
    3. Crews

    1. Red Dead Redemption 2

      1. PC
      2. Gameplay
      3. Missions
      4. Help & Support
    2. Red Dead Redemption

    1. Grand Theft Auto Series

    2. GTA 6

      1. St Andrews Cathedral
    3. GTA V

      1. PC
      2. Guides & Strategies
      3. Help & Support
    4. GTA IV

      1. The Lost and Damned
      2. The Ballad of Gay Tony
      3. Guides & Strategies
      4. Help & Support
    5. GTA Chinatown Wars

    6. GTA Vice City Stories

    7. GTA Liberty City Stories

    8. GTA San Andreas

      1. Guides & Strategies
      2. Help & Support
    9. GTA Vice City

      1. Guides & Strategies
      2. Help & Support
    10. GTA III

      1. Guides & Strategies
      2. Help & Support
    11. Top Down Games

      1. GTA Advance
      2. GTA 2
      3. GTA
    1. GTA Mods

      1. GTA V
      2. GTA IV
      3. GTA III, VC & SA
      4. Tutorials
    2. Red Dead Mods

      1. Documentation
    3. Mod Showroom

      1. Scripts & Plugins
      2. Maps
      3. Total Conversions
      4. Vehicles
      5. Textures
      6. Characters
      7. Tools
      8. Other
      9. Workshop
    4. Featured Mods

      1. DYOM
      2. OpenIV
      3. GTA: Underground
      4. GTA: Liberty City
      5. GTA: State of Liberty
    1. Rockstar Games

    2. Rockstar Collectors

    1. Off-Topic

      1. General Chat
      2. Gaming
      3. Technology
      4. Movies & TV
      5. Music
      6. Sports
      7. Vehicles
    2. Expression

      1. Graphics / Visual Arts
      2. GFX Requests & Tutorials
      3. Writers' Discussion
      4. Debates & Discussion
    3. Gangs

    1. Announcements

    2. Support

    3. Suggestions

whyperioN

[HELP] New player money account. (C++ / asi)

Recommended Posts

whyperioN
Posted (edited)

Hello again, I am working on a very different plugin. My goal is to add a new money account to the player. I even managed to increase this, but I cannot save it in the save file. Btw, I know I asked you a lot of questions on this subject. I have a lot of ideas in mind and these ideas can contribute to the GTA community. But I do not have enough information for this. Sorry.

 

at starting:

w0pbWu.png

 

When I press the TAB key:

sLv2qw.png

 

When I entered the save game or start a new game:

uv1Iee.png

 

When I close the game and open it:

8KvRLT.png

 

How can I save this money account in a save file?

I am waiting for yor help.

 

#include "plugin.h"
#include "common.h"
#include "CFont.h"
#include "CTimer.h"

using namespace plugin;

class My2DText {
public:
    My2DText() {
        // Initialise your plugin here
        static char myText[8];
        static int bankMoney = 0;
        static int keyPressTime = 0;

        Events::drawingEvent += [] {

            CFont::SetColor(CRGBA(255, 255, 255, 255));
            CFont::SetDropShadowPosition(0);
#ifdef GTASA
            
            CFont::SetBackground(false, false);
            CFont::SetProportional(true);
            CFont::SetOrientation(ALIGN_CENTER);
            CFont::SetFontStyle(3);
            CFont::m_nFontShadow = 0;
            CFont::m_nFontOutline = 2;
            CFont::m_nFontOutlineSize = 2;
#else
            static wchar_t myText[8];
            CFont::SetBackgroundOff();
            CFont::SetPropOn();
            CFont::SetCentreOn();
            CFont::SetFontStyle(0);
#endif

            CFont::SetCentreSize(SCREEN_COORD_MAX_X);
            CFont::SetScale(SCREEN_MULTIPLIER(1.25f), SCREEN_MULTIPLIER(2.6f));

            float fX = 692;
            float fY = 170;

#ifdef GTASA
            sprintf(myText, "$%08d", bankMoney);
            CFont::PrintString(fX, fY, myText);
#else
            swprintf(myText, L"$%08d", bankMoney);
            CFont::PrintString(fX, fY, myText);
#endif
        };
        
        Events::gameProcessEvent += [] {
        
            CPed* playa = FindPlayerPed();
            if (playa && KeyPressed(VK_TAB) && CTimer::m_snTimeInMilliseconds - keyPressTime > 500)
            {
                keyPressTime = CTimer::m_snTimeInMilliseconds;
                bankMoney += 1000000;
            }
            if (bankMoney > 99999999)
            {
                bankMoney = 99999999;
            }
        };
        
    }
} my2DText;

 

Edited by whyperioN
code fix and wrong screenshot

Share this post


Link to post
Share on other sites
B1ack_Wh1te

You need to rewrite the functions CPlayerInfo::Save(0x5D3AC0) and CPlayerInfo::Load(0x5D3B00). To do this, create functions with a code similar to the original and add your own code to them to save and load your values, and then add a jump from the beginning of the original functions to yours. So the game when you call these functions will call yours.

  • Like 1

Share this post


Link to post
Share on other sites
whyperioN
On 6/22/2020 at 8:10 PM, B1ack_Wh1te said:

You need to rewrite the functions CPlayerInfo::Save(0x5D3AC0) and CPlayerInfo::Load(0x5D3B00). To do this, create functions with a code similar to the original and add your own code to them to save and load your values, and then add a jump from the beginning of the original functions to yours. So the game when you call these functions will call yours.

First of all, thank you for your answer. I've been busy for a few days. I was just able to enter the forum and just look. Now, "CPlayerInfo ::" did not have a Save member.
I was able to find it on CPlayerPed and CPed. And I studied the function, but I did not understand anything.

Here is the code: 

// CPed.cpp
// Converted from bool CPed::Save(void) 0x5D5730
bool CPed::Save()
{
    return ((bool (__thiscall *)(CPed*))(*(void ***)this)[25])(this);
}
// CPed.h
bool Save(); // in PLUGIN_API class

 

Share this post


Link to post
Share on other sites
B1ack_Wh1te

You don’t need a function CPed::Save, because its code is more complicated CPlayerInfo::Save. I indicated their addresses in the message above.
1) Open the database and see their pseudo-code.
f574317ecfb9.png
2) Create a function with the same code (do not forget that this is a class method).
7c7c22f1416a.png
8099b67f1ffb.png
3) Create a jump from the beginning of the original function to your new one so that when you call it, your function is called.
 

template <typename T>
inline static void * GetMethodPtr(T method)
{
	union
	{
		T in;
		void * out;
	} u = { method };
	return u.out;
}

class PluginSdkProject1 {
public:
    PluginSdkProject1() {
		patch::RedirectJump(0x5D3AC0, GetMethodPtr(&CPlayerInfo::SavePatch));
		// ...
    }
} pluginSdkProject1;

Do the same for the download function.

  • Like 1

Share this post


Link to post
Share on other sites
whyperioN
2 hours ago, B1ack_Wh1te said:

You don’t need a function CPed::Save, because its code is more complicated CPlayerInfo::Save. I indicated their addresses in the message above.
1) Open the database and see their pseudo-code.
f574317ecfb9.png
2) Create a function with the same code (do not forget that this is a class method).
7c7c22f1416a.png
8099b67f1ffb.png
3) Create a jump from the beginning of the original function to your new one so that when you call it, your function is called.
 

template <typename T>
inline static void * GetMethodPtr(T method)
{
	union
	{
		T in;
		void * out;
	} u = { method };
	return u.out;
}

class PluginSdkProject1 {
public:
    PluginSdkProject1() {
		patch::RedirectJump(0x5D3AC0, GetMethodPtr(&CPlayerInfo::SavePatch));
		// ...
    }
} pluginSdkProject1;

Do the same for the download function.

Thank you for trying so hard, but there is still a problem. I am not sure there is a point that I missed, I tried every way but I could not do it as you did. The compiler doesn't allow me to define functions. All libraries are attached but the compiler doesn't allow it.

Share this post


Link to post
Share on other sites
B1ack_Wh1te
Posted (edited)

I noticed that there is no CPlayerInfoSaveStructure class in the SDK plugin.
You can create it yourself, but there is another solution that should suit you. You simply create a method that will call the original, and then execute your code. To do this, you need to go to the beginning of the method in the database and see its code. As you know, a jump to another address takes 5 bytes (1 byte is an opcode, 4 bytes is an offset to an address). And in order to call the original function, while placing a jump at its beginning, you need to find out which assembly instructions occupy these 5 bytes.
aed386933f93.png
The first command takes 3 bytes, the second - 1, the third - 4. Since the first and second will not be enough (3 + 1 < 5), you will have to take the third. Next you must create a function that will simulate the original. You enter these three commands there, and then make the transition to the address of the next assembly command.

void _declspec(naked) OriginalPlayerInfoSave()
{
	__asm
	{
		sub     esp, 2Ch;
		push    ecx;
		lea     ecx, [esp + 8];
		push	0x5D3AC8;
		retn;
	}
}

Next, you need to create a class with a method that will be called instead of the original function. It is imperative that this is exactly the non-static class method so that there are no problems with possible problems with the ecx register and that you can get this. In the method itself, you first make a call to a function that simulates the original. Her convention is __thisсall, because this function is a class method. And then you write your code.

class CPlayerInfoPatch
{
public:
	void NewSaveMethod()
	{
		((void (__thiscall *)(CPlayerInfoPatch *))reinterpret_cast<DWORD>(&OriginalPlayerInfoSave))(this);
		// Your code...
		CGenericGameStorage::_SaveDataToWorkBuffer(&bankMoney, sizeof(bankMoney));
	}
};

But, there is a chance that someone could just as well rewrite this address in their plugin. In order for the modifications to not have a conflict, you can create a separate variable that will store the address for calling the desired function. You read the first byte. If it is 0xE9, then someone has already rewritten this function and you need to find out the new address to which the jump is made. So you get an offset to the new address, add the initial address and 5 (length jump command) to it and get the address of the new function.
 

BYTE firstByte = patch::Get<BYTE>(0x5D3AC0);
if (firstByte == 0xE9)
	g_nAdressSaveFunction = patch::Get<DWORD>(0x5D3AC0 + 1) + 0x5D3AC0 + 5;
else
	g_nAdressSaveFunction = reinterpret_cast<DWORD>(&OriginalPlayerInfoSave);


If you add all this code instead, you can get the following:
 

void _declspec(naked) OriginalPlayerInfoSave()
{
	__asm
	{
		sub     esp, 2Ch;
		push    ecx;
		lea     ecx, [esp + 8];
		push	0x5D3AC8;
		retn;
	}
}

DWORD g_nAdressSaveFunction;
class CPlayerInfoPatch
{
public:
	void NewSaveMethod()
	{
		((void (__thiscall *)(CPlayerInfoPatch *))g_nAdressSaveFunction)(this);
		// Your code...
		CGenericGameStorage::_SaveDataToWorkBuffer(&bankMoney, sizeof(bankMoney));
	}
};

template <typename T>
inline static void * GetMethodPtr(T method)
{
	union
	{
		T in;
		void * out;
	} u = { method };
	return u.out;
}

class PluginSdkProject1 {
public:
	PluginSdkProject1() {
		BYTE firstByte = patch::Get<BYTE>(0x5D3AC0);
		if (firstByte == 0xE9)
			g_nAdressSaveFunction = patch::Get<DWORD>(0x5D3AC0 + 1) + 0x5D3AC0 + 5;
		else
			g_nAdressSaveFunction = reinterpret_cast<DWORD>(&OriginalPlayerInfoSave);
		patch::RedirectJump(0x5D3AC0, GetMethodPtr(&CPlayerInfoPatch::NewSaveMethod));
		// ...
	}
} pluginSdkProject1;

And then you just have to do the same for the load function (0x5D3B00) and clear (0x56F330).

Edited by B1ack_Wh1te
  • Like 2

Share this post


Link to post
Share on other sites
whyperioN

Thank you so much, you are the best. When I complete the plugin, I will share the full code here.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • 1 User Currently Viewing
    0 members, 0 Anonymous, 1 Guest

×
×
  • Create New...

Important Information

By using GTAForums.com, you agree to our Terms of Use and Privacy Policy.