Func GetTarget()

02/21/2024 03:00 rexroy1#1
Hi all, I'm new here and looking for some assistance on an AutoIt tool for researching AI targeting behaviours. I've been troubleshooting with @[Only registered and activated users can see links. Click Here To Register...] but thought I would ask the collective brain hive for assistance.

In essence, my current problem is with the GetTarget() function. In GWA2, it calls
Code:
MemoryRead(GetValue('TargetLogBase'))
where that memory doesn't seem to exist. GetCurrentTargetID() which calls MemoryRead($mAgentBase - 1280) where $mAgentBase = MemoryRead(GetScannedAddress('ScanAgentBase', 13)) works perfectly, but I have a need to GetTargets from other agents.

Any thoughts on what the problem could be or any possible solutions?

This is all working towards getting the GetAgentDanger() function working to test AI targeting on different armor levels and insignia combinations on heros, so any help with that function would also solve the issue :).

Thanks!
02/22/2024 07:00 Underavelvetmoon#2
Quote:
Originally Posted by rexroy1 View Post
Hi all, I'm new here and looking for some assistance on an AutoIt tool for researching AI targeting behaviours. I've been troubleshooting with @[Only registered and activated users can see links. Click Here To Register...] but thought I would ask the collective brain hive for assistance.

In essence, my current problem is with the GetTarget() function. In GWA2, it calls
Code:
MemoryRead(GetValue('TargetLogBase'))
where that memory doesn't seem to exist. GetCurrentTargetID() which calls MemoryRead($mAgentBase - 1280) where $mAgentBase = MemoryRead(GetScannedAddress('ScanAgentBase', 13)) works perfectly, but I have a need to GetTargets from other agents.

Any thoughts on what the problem could be or any possible solutions?

This is all working towards getting the GetAgentDanger() function working to test AI targeting on different armor levels and insignia combinations on heros, so any help with that function would also solve the issue :).

Thanks!
Firstly, are you definitely using an up to date GWA2? I havent tested it in my own because I would have to write something to test it with and I dont have time, but this is what I have it setup as:

Code:
Func GetTarget($aAgent)
	Local $lAgentID

	If IsDllStruct($aAgent) = 0 Then
		$lAgentID = ConvertID($aAgent)
	Else
		$lAgentID = DllStructGetData($aAgent, 'ID')
	EndIf

	Return MemoryRead(GetValue('TargetLogBase') + 4 * $lAgentID)
EndFunc
Second, when using targets like this, in my experience with GWA2, it is quite clunky, you have to make sure you are passing it the right information. I think something like this should work:

Code:
Global $aName = "Dunkoro"

Func TargetTest()
Local $cName = GetAgentByName($aName)
Local $aTarget

$aTarget = GetTarget($cName)
; Print or update something to display target
EndFunc
If that doesnt work, you could try creating an array and passing it GetParty and then passing that through GetTarget. If GetTarget isnt working after all this, it might be worth delving into ToolBox and seeing if they have a function to do a similar thing and then just chuck it into ChatGPT to turn it into AutoIt code lol.
02/23/2024 03:04 rexroy1#3
I believe the version of GWA2 is up to date and the GetTarget() I have is the same as the one you posted:
Code:
Func GetTarget($aAgent)
	Local $lAgentID

	If IsDllStruct($aAgent) = 0 Then
		$lAgentID = ConvertID($aAgent)
	Else
		$lAgentID = DllStructGetData($aAgent, 'ID')
	EndIf

	Return MemoryRead(GetValue('TargetLogBase') + 4 * $lAgentID)
EndFunc
I tried passing it various agents from GetAgentByID(); GetAgentByName(); and I think the agent passing is correct as several other agent based information functions work if I just replace GetTarget() with a different function (e.g. using the exact same code but replacing GetTarget() with: GetEnergy(); GetHealth(); GetIsMoving(); GetHasCondition() all output correctly).

I tried a bunch of different testing implementations but at the most basic:
Code:
$CharID = GetMyID()
$CharAgent = GetAgentByID($CharID)
$TargetAgent1 = GetTarget($CharAgent)
$TestDLLA1 = DllStructGetData($TargetAgent1, 'ID')
ConsoleWrite($TargetAgent1 & @LF & $TestDLLA1 & @LF)
The GetPartyDanger() I believe does what you suggested (passing GetParty() array to GetTarget()) but that also doesn't work:
Code:
Func GetPartyDanger($aAgentArray = 0, $aParty = 0)
	If $aAgentArray == 0 Then $aAgentArray = GetAgentArray(0xDB)
	If $aParty == 0 Then $aParty = GetParty($aAgentArray)

	Local $lReturnArray[$aParty[0] + 1]
	$lReturnArray[0] = $aParty[0]
	For $i = 1 To $lReturnArray[0]
		$lReturnArray[$i] = 0
	Next

	For $i = 1 To $aAgentArray[0]
		If BitAND(DllStructGetData($aAgentArray[$i], 'Effects'), 0x0010) > 0 Then ContinueLoop
		If DllStructGetData($aAgentArray[$i], 'HP') <= 0 Then ContinueLoop
		If Not GetIsLiving($aAgentArray[$i]) Then ContinueLoop
		If DllStructGetData($aAgentArray[$i], "Allegiance") > 3 Then ContinueLoop ; ignore NPCs, spirits, minions, pets

		For $j = 1 To $aParty[0]
			If GetTarget(DllStructGetData($aAgentArray[$i], "ID")) == DllStructGetData($aParty[$j], "ID") Then
				If GetDistance($aAgentArray[$i], $aParty[$j]) < 5000 Then
					If DllStructGetData($aAgentArray[$i], "Team") <> 0 Then
						If DllStructGetData($aAgentArray[$i], "Team") <> DllStructGetData($aParty[$j], "Team") Then
							$lReturnArray[$j] += 1
						EndIf
					ElseIf DllStructGetData($aAgentArray[$i], "Allegiance") <> DllStructGetData($aParty[$j], "Allegiance") Then
						$lReturnArray[$j] += 1
					EndIf
				EndIf
			EndIf
		Next
	Next
	Return $lReturnArray
EndFunc
Thanks for the troubleshooting help though! I will search GWCA to see if I can find something similar :). Might be obvious to those knowledgable in the area but I didn't realise you could just translate GWCA to GWCA2 and have it function. Unfortunately I think it is a problem with the GetValue('TargetLogBase') so might be a challenge to work backwards in GWCA to see all the things I would need. Regardless, I appreciate the help!
02/23/2024 03:20 rexroy1#4
I believe I am using an up-to-date version of GWA2. The GetTarget () is identical to the one you posted:
Code:
Func GetTarget($aAgent)
	Local $lAgentID

	If IsDllStruct($aAgent) = 0 Then
		$lAgentID = ConvertID($aAgent)
	Else
		$lAgentID = DllStructGetData($aAgent, 'ID')
	EndIf

	Return MemoryRead(GetValue('TargetLogBase') + 4 * $lAgentID)
EndFunc
I also think the agent passing is working correctly. Using the exact same code but replacing it with other agent-based information functions all seem to output correctly (e.g. replacing GetTarget() with GetEnergy(); GetHealth(); GetIsMoving(); GetHasCondition() all seem to work).

I have tried various implimentations but at the most basic:
Code:
$CharID = GetMyID()
$CharAgent = GetAgentByID($CharID)
$TargetAgent1 = GetTarget($CharAgent)
$TestDLLA1 = DllStructGetData($TargetAgent1, 'ID')
ConsoleWrite($TargetAgent1 & @LF & $TestDLLA1 & @LF)
I think GetPartyDanger() does something similar as what you suggested (passing a GetParty() array to GetTarget()) but that also does not work:
Code:
Func GetPartyDanger($aAgentArray = 0, $aParty = 0)
	If $aAgentArray == 0 Then $aAgentArray = GetAgentArray(0xDB)
	If $aParty == 0 Then $aParty = GetParty($aAgentArray)

	Local $lReturnArray[$aParty[0] + 1]
	$lReturnArray[0] = $aParty[0]
	For $i = 1 To $lReturnArray[0]
		$lReturnArray[$i] = 0
	Next

	For $i = 1 To $aAgentArray[0]
		If BitAND(DllStructGetData($aAgentArray[$i], 'Effects'), 0x0010) > 0 Then ContinueLoop
		If DllStructGetData($aAgentArray[$i], 'HP') <= 0 Then ContinueLoop
		If Not GetIsLiving($aAgentArray[$i]) Then ContinueLoop
		If DllStructGetData($aAgentArray[$i], "Allegiance") > 3 Then ContinueLoop ; ignore NPCs, spirits, minions, pets

		For $j = 1 To $aParty[0]
			If GetTarget(DllStructGetData($aAgentArray[$i], "ID")) == DllStructGetData($aParty[$j], "ID") Then
				If GetDistance($aAgentArray[$i], $aParty[$j]) < 5000 Then
					If DllStructGetData($aAgentArray[$i], "Team") <> 0 Then
						If DllStructGetData($aAgentArray[$i], "Team") <> DllStructGetData($aParty[$j], "Team") Then
							$lReturnArray[$j] += 1
						EndIf
					ElseIf DllStructGetData($aAgentArray[$i], "Allegiance") <> DllStructGetData($aParty[$j], "Allegiance") Then
						$lReturnArray[$j] += 1
					EndIf
				EndIf
			EndIf
		Next
	Next
	Return $lReturnArray
EndFunc
Thanks for the troubleshooting assistance. Might be obvious for those knowledgable in the area, but I didn't realise you could just translate GWCA to GWA2 and have it function correctly (because of memory reads etc.). I will search GWCA to see if I can find something similar. I think the problem is with GetValue('TargetLogBase') so I think it will be challenging for a notice such as myself to work backwords through GWCA to see all the things I would need to add, but will give it a shot :). Regardless, I appreciate the help.
02/23/2024 06:58 Underavelvetmoon#5
Quote:
Originally Posted by rexroy1 View Post
I believe I am using an up-to-date version of GWA2. The GetTarget () is identical to the one you posted:
Code:
Func GetTarget($aAgent)
	Local $lAgentID

	If IsDllStruct($aAgent) = 0 Then
		$lAgentID = ConvertID($aAgent)
	Else
		$lAgentID = DllStructGetData($aAgent, 'ID')
	EndIf

	Return MemoryRead(GetValue('TargetLogBase') + 4 * $lAgentID)
EndFunc
I also think the agent passing is working correctly. Using the exact same code but replacing it with other agent-based information functions all seem to output correctly (e.g. replacing GetTarget() with GetEnergy(); GetHealth(); GetIsMoving(); GetHasCondition() all seem to work).

I have tried various implimentations but at the most basic:
Code:
$CharID = GetMyID()
$CharAgent = GetAgentByID($CharID)
$TargetAgent1 = GetTarget($CharAgent)
$TestDLLA1 = DllStructGetData($TargetAgent1, 'ID')
ConsoleWrite($TargetAgent1 & @LF & $TestDLLA1 & @LF)
I think GetPartyDanger() does something similar as what you suggested (passing a GetParty() array to GetTarget()) but that also does not work:
Code:
Func GetPartyDanger($aAgentArray = 0, $aParty = 0)
	If $aAgentArray == 0 Then $aAgentArray = GetAgentArray(0xDB)
	If $aParty == 0 Then $aParty = GetParty($aAgentArray)

	Local $lReturnArray[$aParty[0] + 1]
	$lReturnArray[0] = $aParty[0]
	For $i = 1 To $lReturnArray[0]
		$lReturnArray[$i] = 0
	Next

	For $i = 1 To $aAgentArray[0]
		If BitAND(DllStructGetData($aAgentArray[$i], 'Effects'), 0x0010) > 0 Then ContinueLoop
		If DllStructGetData($aAgentArray[$i], 'HP') <= 0 Then ContinueLoop
		If Not GetIsLiving($aAgentArray[$i]) Then ContinueLoop
		If DllStructGetData($aAgentArray[$i], "Allegiance") > 3 Then ContinueLoop ; ignore NPCs, spirits, minions, pets

		For $j = 1 To $aParty[0]
			If GetTarget(DllStructGetData($aAgentArray[$i], "ID")) == DllStructGetData($aParty[$j], "ID") Then
				If GetDistance($aAgentArray[$i], $aParty[$j]) < 5000 Then
					If DllStructGetData($aAgentArray[$i], "Team") <> 0 Then
						If DllStructGetData($aAgentArray[$i], "Team") <> DllStructGetData($aParty[$j], "Team") Then
							$lReturnArray[$j] += 1
						EndIf
					ElseIf DllStructGetData($aAgentArray[$i], "Allegiance") <> DllStructGetData($aParty[$j], "Allegiance") Then
						$lReturnArray[$j] += 1
					EndIf
				EndIf
			EndIf
		Next
	Next
	Return $lReturnArray
EndFunc
Thanks for the troubleshooting assistance. Might be obvious for those knowledgable in the area, but I didn't realise you could just translate GWCA to GWA2 and have it function correctly (because of memory reads etc.). I will search GWCA to see if I can find something similar. I think the problem is with GetValue('TargetLogBase') so I think it will be challenging for a notice such as myself to work backwords through GWCA to see all the things I would need to add, but will give it a shot :). Regardless, I appreciate the help.
No worries mate, it would seem that something is indeed wrong with the pointer then.

I wouldnt say its common knowledge, but I personally have been using ChatGPT to convert complex code in other projects, like Java to AutoIt, Pine to Java, C++ to Java, and so on, so I am pretty sure that you could quite easily use it to convert anything from GWCA.

I might have some time this weekend to have a look through it and see what I can find.
02/23/2024 22:10 rexroy1#6
I think it is an issue with the 'ScanTargetLog:' pointer and I think from my review GWCA only has code for Current target (being the player)
Code:
; definition of GetTarget() function 
inline Agent   *GetTarget() { return GetAgentByID(GetTargetId()); }


; GetTargetID defined in different file
        uint32_t GetTargetId() {
            return *(uint32_t*)TargetAgentIdPtr;
        }

;TargetAgentIdPtr 
        address = Scanner::Find( "\x3B\xDF\x0F\x95", "xxxx", -0x0089);
        if (address) {
            ChangeTarget_Func = (ChangeTarget_pt)address;

            TargetAgentIdPtr = *(uintptr_t*)(address + 0x94);
            if (!Scanner::IsValidPtr(TargetAgentIdPtr))
                TargetAgentIdPtr = 0;

; Scanner Find 
uintptr_t GW::Scanner::Find(const char* pattern, const char* mask, int offset, Section section) {
    return FindInRange(pattern, mask, offset, sections[section].start, sections[section].end);
}

' Find in Range 
uintptr_t GW::Scanner::FindInRange(const char* pattern, const char* mask, int offset, DWORD start, DWORD end) {
    char first = pattern[0];
    size_t patternLength = strlen(mask ? mask : pattern);
    bool found = false;
    end -= patternLength;

    if (start > end) {
        // Scan backward
        for (DWORD i = start; i >= end; i--) {
            if (*(char*)i != first)
                continue;
            found = true;
            //For each byte in the pattern
            for (size_t idx = 0; idx < patternLength; idx++) {
                if ((!mask || mask[idx] == 'x') && pattern[idx] != *(char*)(i + idx)) {
                    found = false;
                    break;
                }
            }
            if (found)
                return i + offset;
        }
    }
    else {
        // Scan forward
        for (DWORD i = start; i < end; i++) {
            if (*(char*)i != first)
                continue;
            found = true;
            //For each byte in the pattern
            for (size_t idx = 0; idx < patternLength; idx++) {
                if ((!mask || mask[idx] == 'x') && pattern[idx] != *(char*)(i + idx)) {
                    found = false;
                    break;
                }
            }
            if (found)
                return i + offset;
        }
    }
    return NULL;
}
I spent a few hours trying to find a pattern through CheatEngine with no luck. Does anyone on the forum have experience with assembler/updating GWA2 patterns?