Skip to content

Units and Buildings can be grouped together by using the SHIFT key feature #101

Open
@xezon

Description

@xezon

Units and Buildings can be grouped together by using the SHIFT key feature. SHIFT allows to add units and buildings to existing groups. This can be exploited with game breaking consequences in the game. It is critical issue. GenTool fixes this bug by doing the following:

For game.dat

Inject code at address 0x616031 taking 6 bytes and call naked function.
esi register contains team number that is about to be used for grouping.

// The Group Selection Logic must be changed
// By default it is possible to combine any groups by using Shift key
// We must remove the possibility to select a building group with Shift:

//////////////////////////////////////////////////////////////////////////////////////

DWORD ccAddTeamInUIRet;
uint32 ccTeamNumber2;

__declspec(naked) void CC_AddTeamInUI_ZH()
{
	__asm pop [ccAddTeamInUIRet]
	__asm mov ccTeamNumber2,esi
	__asm ADD ESI,0x402
	__asm pushad

	CGameAccess::Instance.PreventInvalidGrouping(ccTeamNumber2);
	
	__asm popad
	__asm push [ccAddTeamInUIRet]
	__asm ret
}

Here is high level code of logic to prevent invalid grouping.

  1. Get the local player
  2. Get the group list of player by the given team number from esi
  3. If the first object in the group list is a building, deselect all units
  4. If the current selected object is a building, deselect all units

Note that point 4 is already done in Zero Hour, but not in Generals. The code responsible must be around address 0x616031, so when reversing the function, it can also be fixed right there more elegantly than in the example below.

void CGameAccess::PreventInvalidGrouping(uint32 teamNumber)
{
	DWORD building = 0;
	TPlayer player = 0;
	if (teamNumber < 10 && Hack_GetLocalPlayer(player) && player != 0)
	{
		TGroupList groupList;
		if (Hack_GetGroupList(player, teamNumber, groupList))
		{
			CGameArray<TGroupObject> groupObjectArray(0, 0);
			Hack_GetGroupObjectArray(groupList, groupObjectArray);
			if (TGroupObject* pFirstGroupObject = groupObjectArray.get(0))
			{
				TObject object = 0;
				Hack_GetObjectFromGroupObject(*pFirstGroupObject, object);
				Hack_GetBuildingHandle(object, building);
			}
		}
	}

	const bool selectsToBuilding = building != 0;
	const bool selectsFromBuilding = IsGenerals() && Hack_IsBuildingSelected(); // Is already fixed in Zero Hour
	if (selectsToBuilding || selectsFromBuilding)
	{
		Hack_SelectUnit(0);
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugSomething is not working right, typically is user facingCriticalSeverity: Minor < Major < Critical < BlockerGenToolRelates to GenToolZHRelates to Zero Hour

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions