Jump to content

[Clientside] How to get real stats


Recommended Posts

I have those lines in my Client source

PythonNetworkStreamPhaseLoading.cpp -> bool CPythonNetworkStream::__RecvPlayerPoints()

for (DWORD i = 0; i < POINT_MAX_NUM; ++i)
{
	CPythonPlayer::Instance().SetStatus(i, PointsPacket.points[i]);
	
    if (i == POINT_LEVEL)
		m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byLevel = PointsPacket.points[i];
	else if (i == POINT_ST)
		m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byST = PointsPacket.points[i];
	else if (i == POINT_HT)
		m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byHT = PointsPacket.points[i];
	else if (i == POINT_DX)
		m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byDX = PointsPacket.points[i];
	else if (i == POINT_IQ)
		m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byIQ = PointsPacket.points[i];

}

PythonNetworkStreamPhaseGame.cpp -> bool CPythonNetworkStream::RecvPointChange()

case POINT_PLAYTIME:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].dwPlayMinutes = PointChange.value;
	break;
case POINT_LEVEL:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byLevel = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;
case POINT_ST:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byST = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;
case POINT_DX:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byDX = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;
case POINT_HT:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byHT = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;
case POINT_IQ:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byIQ = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;

But there is a problem with this code. If I'm riding my horse, it returns the stats the character has while riding.

For example if a character has INT: 6 and starts riding, the 6 will become 38.

If this code executes while the character is riding the horse, POINT_IQ will return 38 instead of the real INT (6).

Is there any way to get the real values?

Link to comment
Share on other sites

In Server source game/char.cpp in ComputePoints() 

if (IsPC())
	{
		if (GetMountVnum()) 
		{
			if (GetHorseST() > GetPoint(POINT_ST))
				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));

			if (GetHorseDX() > GetPoint(POINT_DX))
				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));

			if (GetHorseHT() > GetPoint(POINT_HT))
				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));

			if (GetHorseIQ() > GetPoint(POINT_IQ))
				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
		}

	}

This way horse stats will override lower stats. Those numbers are then packeted and sent to client. You could create a new packet sending base stats to client. To recive base stats from game use game/char.cpp int CHARACTER::GetPoint(type) where type is POINT_ST, POINT_DX, POINT_HT, POINT_IQ example:

game/packet.h && UserInterface/packet.h
  
  enum
{
	HEADER_CG_HANDSHAKE				= 0xdc,
  ....
    HEADER_GC_BASE_STATS			= (your_value),
  
  typedef struct base_stats
{
	BYTE	header;
	DWORD	point_ST;
	DWORD	point_DX;
	DWORD	point_HT;
	DWORD	point_IQ;
} TPacketGCBaseStats;

 then send this packet from somewhere:
 

if (IsPC())
	{
		if (GetMountVnum()) 
		{
			TPacketGCBaseStats pack;
			pack.header = HEADER_GC_BASE_STATS;
			pack.point_ST = GetPoint(POINT_ST);
			pack.point_DX = GetPoint(POINT_DX);
			pack.point_HT = GetPoint(POINT_HT);
			pack.point_IQ = GetPoint(POINT_IQ);
			ch->GetDesc()->Packet(&pack, sizeof(pack));
			if (GetHorseST() > GetPoint(POINT_ST))
				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));

			if (GetHorseDX() > GetPoint(POINT_DX))
				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));

			if (GetHorseHT() > GetPoint(POINT_HT))
				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));

			if (GetHorseIQ() > GetPoint(POINT_IQ))
				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
		}

And then recive it from client and do whatever you like with those.

REMEMBER to declare both the packet header and the typedef struct inside packet.h of client binary as well.

Link to comment
Share on other sites

2 hours ago, OtherChoice said:

In Server source game/char.cpp in ComputePoints() 


if (IsPC())
	{
		if (GetMountVnum()) 
		{
			if (GetHorseST() > GetPoint(POINT_ST))
				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));

			if (GetHorseDX() > GetPoint(POINT_DX))
				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));

			if (GetHorseHT() > GetPoint(POINT_HT))
				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));

			if (GetHorseIQ() > GetPoint(POINT_IQ))
				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
		}

	}

This way horse stats will override lower stats. Those numbers are then packeted and sent to client. You could create a new packet sending base stats to client. To recive base stats from game use game/char.cpp int CHARACTER::GetPoint(type) where type is POINT_ST, POINT_DX, POINT_HT, POINT_IQ example:


game/packet.h && UserInterface/packet.h
  
  enum
{
	HEADER_CG_HANDSHAKE				= 0xdc,
  ....
    HEADER_GC_BASE_STATS			= (your_value),
  
  typedef struct base_stats
{
	BYTE	header;
	DWORD	point_ST;
	DWORD	point_DX;
	DWORD	point_HT;
	DWORD	point_IQ;
} TPacketGCBaseStats;

 then send this packet from somewhere:
 


if (IsPC())
	{
		if (GetMountVnum()) 
		{
			TPacketGCBaseStats pack;
			pack.header = HEADER_GC_BASE_STATS;
			pack.point_ST = GetPoint(POINT_ST);
			pack.point_DX = GetPoint(POINT_DX);
			pack.point_HT = GetPoint(POINT_HT);
			pack.point_IQ = GetPoint(POINT_IQ);
			ch->GetDesc()->Packet(&pack, sizeof(pack));
			if (GetHorseST() > GetPoint(POINT_ST))
				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));

			if (GetHorseDX() > GetPoint(POINT_DX))
				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));

			if (GetHorseHT() > GetPoint(POINT_HT))
				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));

			if (GetHorseIQ() > GetPoint(POINT_IQ))
				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
		}

And then recive it from client and do whatever you like with those.

REMEMBER to declare both the packet header and the typedef struct inside packet.h of client binary as well.

I tested it and it didn't quite work. So I already had a packet in char.cpp->void CHARACTER:: Disconnect(const char * c_pszReason) and I changed it like this:

packet_point_change pack;
pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
pack.dwVID = m_vid;
pack.type = POINT_PLAYTIME;
pack.value = GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000;
pack.amount = 0;
pack.point_ST = GetPoint(POINT_ST);
pack.point_DX = GetPoint(POINT_DX);
pack.point_HT = GetPoint(POINT_HT);
pack.point_IQ = GetPoint(POINT_IQ);
GetDesc()->Packet(&pack, sizeof(struct packet_point_change));

if (GetHorseST() > GetPoint(POINT_ST))
	PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));

if (GetHorseDX() > GetPoint(POINT_DX))
	PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));

if (GetHorseHT() > GetPoint(POINT_HT))
	PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));

if (GetHorseIQ() > GetPoint(POINT_IQ))
	PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));

and then I changed this in UserInterface/PythonNetworkStreamPhaseLogin.cpp:

for (DWORD i = 0; i < POINT_MAX_NUM; ++i)
{
	CPythonPlayer::Instance().SetStatus(i, PointsPacket.points[i]);
	TPacketGCPointChange PointsPacketChange;

	if (i == POINT_LEVEL)
		m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byLevel = PointsPacket.points[i];
	else if (i == POINT_ST)
		m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byST = PointsPacketChange.point_ST;
	else if (i == POINT_HT)
		m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byHT = PointsPacketChange.point_HT;
	else if (i == POINT_DX)
		m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byDX = PointsPacketChange.point_DX;
	else if (i == POINT_IQ)
		m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byIQ = PointsPacketChange.point_IQ;
}

and I edited the packet.h files of course.

The result was that not only the problem continued to exist, but once the client starts, if the character logs out once with horse stats they are displayed each time they do, even if they don't ride a horse the next time! And not only that, when the character rides a horse in game, the HT, IQ, ST and DEX get updated but HP and SP are not updated!

Link to comment
Share on other sites

The way you are trying to work with won't go anywhere, first, the point you are packing are in a wrong place, since the first time ComputePoints() is exectuted it will check whether your horse has higher stats than yours and then replace them if so and will however pack and send them to client. If you want to make sure you have your real stat points you need to create the packet inside CHARACTER::ComputePoints() function not in void CHARACTER::Disconnect. Next point is the packet you are using: since packet_point_change (HEADER_GC_CHARACTER_POINT_CHANGE) has already a defined behavior (it has 3 different behavior actually, in PhaseGame, PhaseSelect and PhaseLoading) i suggest you to avoid using it.
Moreover if your goal is to always show base stats and hide horse bonuses, you can skip the whole client part and do in a simpler way.
I will first explain how to get both base Stats and horse Stats.

Spoiler

I just tried the code i wrote and everything works fine. There's just a couple of thing i missed when answering

 

Quote

In Server source game/char.cpp in ComputePoints() 



if (IsPC())
	{
		if (GetMountVnum()) 
		{
			if (GetHorseST() > GetPoint(POINT_ST))
				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));

			if (GetHorseDX() > GetPoint(POINT_DX))
				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));

			if (GetHorseHT() > GetPoint(POINT_HT))
				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));

			if (GetHorseIQ() > GetPoint(POINT_IQ))
				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
		}

	}

This way horse stats will override lower stats. Those numbers are then packeted and sent to client. You could create a new packet sending base stats to client. To recive base stats from game use game/char.cpp int CHARACTER::GetPoint(type) where type is POINT_ST, POINT_DX, POINT_HT, POINT_IQ example:



game/packet.h && UserInterface/packet.h
  
  enum
{
	HEADER_CG_HANDSHAKE				= 0xdc,
  ....
    HEADER_GC_BASE_STATS			= (your_value),
  
  typedef struct base_stats
{
	BYTE	header;
	DWORD	point_ST;
	DWORD	point_DX;
	DWORD	point_HT;
	DWORD	point_IQ;
} TPacketGCBaseStats;

 then send this packet from somewhere:
 



game/char.cpp ComputePoints()
if (IsPC())
	{
		if (GetMountVnum()) 
		{
			TPacketGCBaseStats pack;
			pack.header = HEADER_GC_BASE_STATS;
			pack.point_ST = GetPoint(POINT_ST);
			pack.point_DX = GetPoint(POINT_DX);
			pack.point_HT = GetPoint(POINT_HT);
			pack.point_IQ = GetPoint(POINT_IQ);
			ch->GetDesc()->Packet(&pack, sizeof(pack));
			if (GetHorseST() > GetPoint(POINT_ST))
				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));

			if (GetHorseDX() > GetPoint(POINT_DX))
				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));

			if (GetHorseHT() > GetPoint(POINT_HT))
				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));

			if (GetHorseIQ() > GetPoint(POINT_IQ))
				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
		}

Before TPacketGCBaseStats pack add this:

...
PointChange(POINT_ST, 0);
PointChange(POINT_DX, 0);
PointChange(POINT_IQ, 0);
PointChange(POINT_HT, 0);
TPacketGCBaseStats pack;
pack.header = HEADER_GC_BASE_STATS;
...

then in PythonNetworkStreamPhaseGame.cpp:


void CPythonNetworkStream::GamePhase()
{
	...
	switch (header)
		{
			case HEADER_GC_OBSERVER_ADD:
				ret = RecvObserverAddPacket();
				break;
    		....
			case HEADER_GC_BASE_STATS:
				ret = RecvBaseStatsPacket();
					break;
  		}
}

then after
bool CPythonNetworkStream::RecvPointChange()
{
  ...
}
add
bool CPythonNetworkStream::RecvBaseStatsPacket()
{
  TPacketGCBaseStats pack;
  if (!Recv(sizeof(TPacketGCBaseStats), &pack))
	{
		Tracen("Recv Base Stats Packet Error");
		return false;
	}
  //here you can do whatever you like with those number, to make sure you everything runs smoothly you can try this
  TraceError("Point_ST = %d, Point_DX =  %d, Point_HT = %d, Point_IQ = %d \n", pack.point_ST, pack.point_DX, pack.POINT_HT, pack.point_IQ);
  // so you can run your client then check syserr.txt and look at the output
}

and in PythonNetworkStream.h after
  bool RecvPointChange();
add
  bool RecvBaseStatsPacket();

 

____________________________________________________________________________________________________

If you want to totally hide horse stats you can do something like this:

Spoiler

 

in char.cpp change void CHARACTER::PointChange(BYTE type, int amount, bool bAmount, bool bBroadcast) to 

void CHARACTER::PointChange(BYTE type, int amount, int baseAmount=0, bool bAmount, bool bBroadcast) and change the definition in char.h as well (without =0 in the header file)

then at the end of the function you will find 


if (GetDesc())
	{
		struct packet_point_change pack;

		pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
		pack.dwVID = m_vid;
		pack.type = type;
		pack.value = val;

		if (bAmount)
			pack.amount = amount;
		else
			pack.amount = 0;

		if (!bBroadcast)
			GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
		else
			PacketAround(&pack, sizeof(pack));
	}
}

and change it like this

if (GetDesc())
	{
		struct packet_point_change pack;

		pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
		pack.dwVID = m_vid;
		pack.type = type;
		pack.value = baseAmount ? baseAmount : val;

		if (bAmount)
			pack.amount = amount;
		else
			pack.amount = 0;

		if (!bBroadcast)
			GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
		else
			PacketAround(&pack, sizeof(pack));
	}
}

Lastly  you need to edit char.cpp void CHARACTER::ComputePoints()
find
if (GetMountVnum()) 
		{
			if (GetHorseST() > GetPoint(POINT_ST))
				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));

			if (GetHorseDX() > GetPoint(POINT_DX))
				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));

			if (GetHorseHT() > GetPoint(POINT_HT))
				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));

			if (GetHorseIQ() > GetPoint(POINT_IQ))
				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
		}

and change it like this

if (GetMountVnum()) 
		{
			if (GetHorseST() > GetPoint(POINT_ST))
				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST), GetPoint(POINT_ST));

			if (GetHorseDX() > GetPoint(POINT_DX))
				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX), GetPoint(POINT_DX));

			if (GetHorseHT() > GetPoint(POINT_HT))
				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT), GetPoint(POINT_HT));

			if (GetHorseIQ() > GetPoint(POINT_IQ))
				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ), GetPoint(POINT_IQ));
		}

 

 

Done.

Link to comment
Share on other sites

10 hours ago, OtherChoice said:

The way you are trying to work with won't go anywhere, first, the point you are packing are in a wrong place, since the first time ComputePoints() is exectuted it will check whether your horse has higher stats than yours and then replace them if so and will however pack and send them to client. If you want to make sure you have your real stat points you need to create the packet inside CHARACTER::ComputePoints() function not in void CHARACTER::Disconnect. Next point is the packet you are using: since packet_point_change (HEADER_GC_CHARACTER_POINT_CHANGE) has already a defined behavior (it has 3 different behavior actually, in PhaseGame, PhaseSelect and PhaseLoading) i suggest you to avoid using it.
Moreover if your goal is to always show base stats and hide horse bonuses, you can skip the whole client part and do in a simpler way.
I will first explain how to get both base Stats and horse Stats.

  Hide contents

I just tried the code i wrote and everything works fine. There's just a couple of thing i missed when answering

 

Before TPacketGCBaseStats pack add this:

...
PointChange(POINT_ST, 0);
PointChange(POINT_DX, 0);
PointChange(POINT_IQ, 0);
PointChange(POINT_HT, 0);
TPacketGCBaseStats pack;
pack.header = HEADER_GC_BASE_STATS;
...

then in PythonNetworkStreamPhaseGame.cpp:



void CPythonNetworkStream::GamePhase()
{
	...
	switch (header)
		{
			case HEADER_GC_OBSERVER_ADD:
				ret = RecvObserverAddPacket();
				break;
    		....
			case HEADER_GC_BASE_STATS:
				ret = RecvBaseStatsPacket();
					break;
  		}
}

then after
bool CPythonNetworkStream::RecvPointChange()
{
  ...
}
add
bool CPythonNetworkStream::RecvBaseStatsPacket()
{
  TPacketGCBaseStats pack;
  if (!Recv(sizeof(TPacketGCBaseStats), &pack))
	{
		Tracen("Recv Base Stats Packet Error");
		return false;
	}
  //here you can do whatever you like with those number, to make sure you everything runs smoothly you can try this
  TraceError("Point_ST = %d, Point_DX =  %d, Point_HT = %d, Point_IQ = %d \n", pack.point_ST, pack.point_DX, pack.POINT_HT, pack.point_IQ);
  // so you can run your client then check syserr.txt and look at the output
}

and in PythonNetworkStream.h after
  bool RecvPointChange();
add
  bool RecvBaseStatsPacket();

 

____________________________________________________________________________________________________

If you want to totally hide horse stats you can do something like this:

  Reveal hidden contents

 

in char.cpp change void CHARACTER::PointChange(BYTE type, int amount, bool bAmount, bool bBroadcast) to 

void CHARACTER::PointChange(BYTE type, int amount, int baseAmount=0, bool bAmount, bool bBroadcast) and change the definition in char.h as well (without =0 in the header file)

then at the end of the function you will find 



if (GetDesc())
	{
		struct packet_point_change pack;

		pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
		pack.dwVID = m_vid;
		pack.type = type;
		pack.value = val;

		if (bAmount)
			pack.amount = amount;
		else
			pack.amount = 0;

		if (!bBroadcast)
			GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
		else
			PacketAround(&pack, sizeof(pack));
	}
}

and change it like this

if (GetDesc())
	{
		struct packet_point_change pack;

		pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
		pack.dwVID = m_vid;
		pack.type = type;
		pack.value = baseAmount ? baseAmount : val;

		if (bAmount)
			pack.amount = amount;
		else
			pack.amount = 0;

		if (!bBroadcast)
			GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
		else
			PacketAround(&pack, sizeof(pack));
	}
}


Lastly  you need to edit char.cpp void CHARACTER::ComputePoints()
find
if (GetMountVnum()) 
		{
			if (GetHorseST() > GetPoint(POINT_ST))
				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));

			if (GetHorseDX() > GetPoint(POINT_DX))
				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));

			if (GetHorseHT() > GetPoint(POINT_HT))
				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));

			if (GetHorseIQ() > GetPoint(POINT_IQ))
				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));
		}

and change it like this

if (GetMountVnum()) 
		{
			if (GetHorseST() > GetPoint(POINT_ST))
				PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST), GetPoint(POINT_ST));

			if (GetHorseDX() > GetPoint(POINT_DX))
				PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX), GetPoint(POINT_DX));

			if (GetHorseHT() > GetPoint(POINT_HT))
				PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT), GetPoint(POINT_HT));

			if (GetHorseIQ() > GetPoint(POINT_IQ))
				PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ), GetPoint(POINT_IQ));
		}

 

 

Done.

Thank you so much for these information they were very helpful, but my goal is not to hide the horse stats in general, just in character select. I'm trying to hide them the same way item attributes are hidden: hidden in character select, showing everywhere else.

What I did with the client and the packet set in Disconnect() came from this post:

 

Link to comment
Share on other sites

Oh ok i quite didn't get it, anyhow that's the solution you are looking for
 

This is you void CHARACTER::Disconnect(...)
//ADD this
PointChange(POINT_ST, 0);
PointChange(POINT_DX, 0);
PointChange(POINT_IQ, 0);
PointChange(POINT_HT, 0);
//end

packet_point_change pack;
pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
pack.dwVID = m_vid;
pack.type = POINT_PLAYTIME;
pack.value = GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000;
pack.amount = 0;
pack.point_ST = GetPoint(POINT_ST);
pack.point_DX = GetPoint(POINT_DX);
pack.point_HT = GetPoint(POINT_HT);
pack.point_IQ = GetPoint(POINT_IQ);
GetDesc()->Packet(&pack, sizeof(struct packet_point_change));

/*if (GetHorseST() > GetPoint(POINT_ST))
	PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));

if (GetHorseDX() > GetPoint(POINT_DX))
	PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));				REMOVE ALL THIS

if (GetHorseHT() > GetPoint(POINT_HT))
	PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));

if (GetHorseIQ() > GetPoint(POINT_IQ))
	PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));*/ 

 

Link to comment
Share on other sites

10 hours ago, OtherChoice said:

Oh ok i quite didn't get it, anyhow that's the solution you are looking for
 


This is you void CHARACTER::Disconnect(...)
//ADD this
PointChange(POINT_ST, 0);
PointChange(POINT_DX, 0);
PointChange(POINT_IQ, 0);
PointChange(POINT_HT, 0);
//end

packet_point_change pack;
pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
pack.dwVID = m_vid;
pack.type = POINT_PLAYTIME;
pack.value = GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000;
pack.amount = 0;
pack.point_ST = GetPoint(POINT_ST);
pack.point_DX = GetPoint(POINT_DX);
pack.point_HT = GetPoint(POINT_HT);
pack.point_IQ = GetPoint(POINT_IQ);
GetDesc()->Packet(&pack, sizeof(struct packet_point_change));

/*if (GetHorseST() > GetPoint(POINT_ST))
	PointChange(POINT_ST, GetHorseST() - GetPoint(POINT_ST));

if (GetHorseDX() > GetPoint(POINT_DX))
	PointChange(POINT_DX, GetHorseDX() - GetPoint(POINT_DX));				REMOVE ALL THIS

if (GetHorseHT() > GetPoint(POINT_HT))
	PointChange(POINT_HT, GetHorseHT() - GetPoint(POINT_HT));

if (GetHorseIQ() > GetPoint(POINT_IQ))
	PointChange(POINT_IQ, GetHorseIQ() - GetPoint(POINT_IQ));*/ 

 

Thanks. I tried it but it didn't work.

I tried adding the PointChange(POINT_X, 0) at the top of the function and then I tried it right above the packet initialization, none worked. I also tried the PointsPacket.points in PythonNetworkStreamPhaseLoading.cpp and then I tried again with PointsChange.point_XX from the new packet you showed me, where PointsChange = TPacketGCPointChange PointsChange. None of these worked.

Link to comment
Share on other sites

Ok after testing the original bugfix you linked i found the problem, the m_akSimplePlayerInfo array is filled in a wrong way this is the solution:
In game/char.cpp at void CHARACTER::PointsPacket() change as following
 

void CHARACTER::PointsPacket()
{
	if (!GetDesc())
		return;

	TPacketGCPoints pack;

	pack.header	= HEADER_GC_CHARACTER_POINTS;

	pack.points[POINT_LEVEL]		= GetLevel();
	pack.points[POINT_EXP]		= GetExp();
	pack.points[POINT_NEXT_EXP]		= GetNextExp();
	pack.points[POINT_HP]		= GetHP();
	pack.points[POINT_MAX_HP]		= GetMaxHP();
	pack.points[POINT_SP]		= GetSP();
	pack.points[POINT_MAX_SP]		= GetMaxSP();
	pack.points[POINT_GOLD]		= GetGold();
	pack.points[POINT_STAMINA]		= GetStamina();
	pack.points[POINT_MAX_STAMINA]	= GetMaxStamina();
	for (int i = POINT_ST; i < POINT_IQ + 1; ++i)
		pack.points[i] = GetRealPoint(i);
	
	for (int i = POINT_IQ + 1; i < POINT_MAX_NUM; ++i)
		pack.points[i] = GetPoint(i);

	GetDesc()->Packet(&pack, sizeof(TPacketGCPoints));
}

then at void CHARACTER::Disconnect add this line

if (GetDesc())
	{
  		/*add this*/
		PointsPacket();
  		/*        */
  
		packet_point_change pack;
		pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
		pack.dwVID = m_vid;
		pack.type = POINT_PLAYTIME;
		pack.value = GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000;
		pack.amount = 0;
		GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
		GetDesc()->BindCharacter(NULL);
//		BindDesc(NULL);
	}

then in client source

PythonNetworkStreamPhaseGame.cpp -> bool CPythonNetworkStream::RecvPointChange()  ------->Make these changes

case POINT_PLAYTIME:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].dwPlayMinutes = PointChange.value;
	break;
case POINT_LEVEL:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byLevel = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;
/*case POINT_ST:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byST = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;
case POINT_DX:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byDX = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;
case POINT_HT:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byHT = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;
case POINT_IQ:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byIQ = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;*/
case POINT_ST:
case POINT_DX:
case POINT_HT:
case POINT_IQ:
	__RefreshStatus();
	__RefreshSkillWindow();
break;

Every other thing is like original thread 

Quote

What I did with the client and the packet set in Disconnect() came from this post:

Tested and working.

  • Love 1
Link to comment
Share on other sites

4 hours ago, OtherChoice said:

Ok after testing the original bugfix you linked i found the problem, the m_akSimplePlayerInfo array is filled in a wrong way this is the solution:
In game/char.cpp at void CHARACTER::PointsPacket() change as following
 


void CHARACTER::PointsPacket()
{
	if (!GetDesc())
		return;

	TPacketGCPoints pack;

	pack.header	= HEADER_GC_CHARACTER_POINTS;

	pack.points[POINT_LEVEL]		= GetLevel();
	pack.points[POINT_EXP]		= GetExp();
	pack.points[POINT_NEXT_EXP]		= GetNextExp();
	pack.points[POINT_HP]		= GetHP();
	pack.points[POINT_MAX_HP]		= GetMaxHP();
	pack.points[POINT_SP]		= GetSP();
	pack.points[POINT_MAX_SP]		= GetMaxSP();
	pack.points[POINT_GOLD]		= GetGold();
	pack.points[POINT_STAMINA]		= GetStamina();
	pack.points[POINT_MAX_STAMINA]	= GetMaxStamina();
	for (int i = POINT_ST; i < POINT_IQ + 1; ++i)
		pack.points[i] = GetRealPoint(i);
	
	for (int i = POINT_IQ + 1; i < POINT_MAX_NUM; ++i)
		pack.points[i] = GetPoint(i);

	GetDesc()->Packet(&pack, sizeof(TPacketGCPoints));
}

then at void CHARACTER::Disconnect add this line


if (GetDesc())
	{
  		/*add this*/
		PointsPacket();
  		/*        */
  
		packet_point_change pack;
		pack.header = HEADER_GC_CHARACTER_POINT_CHANGE;
		pack.dwVID = m_vid;
		pack.type = POINT_PLAYTIME;
		pack.value = GetRealPoint(POINT_PLAYTIME) + (get_dword_time() - m_dwPlayStartTime) / 60000;
		pack.amount = 0;
		GetDesc()->Packet(&pack, sizeof(struct packet_point_change));
		GetDesc()->BindCharacter(NULL);
//		BindDesc(NULL);
	}

then in client source


PythonNetworkStreamPhaseGame.cpp -> bool CPythonNetworkStream::RecvPointChange()  ------->Make these changes

case POINT_PLAYTIME:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].dwPlayMinutes = PointChange.value;
	break;
case POINT_LEVEL:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byLevel = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;
/*case POINT_ST:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byST = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;
case POINT_DX:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byDX = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;
case POINT_HT:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byHT = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;
case POINT_IQ:
	m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byIQ = PointChange.value;
	__RefreshStatus();
	__RefreshSkillWindow();
	break;*/
case POINT_ST:
case POINT_DX:
case POINT_HT:
case POINT_IQ:
	__RefreshStatus();
	__RefreshSkillWindow();
break;

Every other thing is like original thread 

Tested and working.

I removed all the extra steps and left only what the post shows. Then I followed the steps above for char.cpp and PythonNetworkStreamPhaseGame.cpp. The problem is still here with a little difference... Now the horse stats are displayed only when during the logout, character rides a horse. I just don't get it we tried everything.

EDIT: Ok that was my bad actually. The problem is fixed!!!

I forgot to change

for (int i = POINT_ST; i < POINT_IQ + 1; ++i)
	pack.points[i] = GetRealPoint(i);

in PointsPacket()

was:

for (int i = POINT_ST; i < POINT_MAX_NUM; ++i)
	pack.points[i] = GetPoint(i);

but now I believe it's all right!

Thank you so much for your time. Lots of respect not just for helping me find a solution but also for not giving up on me. Cheers to you man :)

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

Announcements



×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.