Author Topic: Programmatic /API to NPC coordinates in icon  (Read 5054 times)

Jeff Anderson

  • Boss
  • ****
  • Posts: 121
Programmatic /API to NPC coordinates in icon
« on: September 10, 2015, 08:04:58 PM »
 I am writing a program that orchestrates a combat sequence in city of heroes.

The program currently works by dynamically creating keybind files with the relevant icon commands, and then programmatically loads them and runs them in order to:
- target the attacking NPC model,
- run a specific set of FX effects as well as animations on the attacker as determined by a configuration file
-Target the defender
-run a set of animations depending on whether the attack hit or miss, resulted in a stunning, unconsciousness, death or Knockback with specific FX determined by the configuration file as well.
-  finally update the NPC position to account for  knock back.

I have everything working but the last piece, namely because NPC positioning requires the  editpos command, which relies on entering coordinates into a set of text boxes. In practice this is incredibly hard to automate, as the text boxes are somewhat hard to update/read using software.

Is there any other alternative mechanism to getting the XYZ coordinates of a targeted character? How was the editpos command created in the first place?

I have noticed that a xyz.exe has been developed that seems to offer some of the functionality, I am looking for, controls are easy to read and update your software, however the location doesn't take into account camera distancing so the actual coordinates are not accurate.

If anyone out there have some insight to share that would be really appreciated!
Jeff

DarkCurrent

  • Boss
  • ****
  • Posts: 211
Re: Programmatic /API to NPC coordinates in icon
« Reply #1 on: September 10, 2015, 09:35:44 PM »
When you pull this off you will be my personal hero.

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Programmatic /API to NPC coordinates in icon
« Reply #2 on: September 11, 2015, 04:56:11 AM »
How was the editpos command created in the first place?

In the space that Icon allocates inside the cityofheroes.exe process' memory, one address known as DATA_COMMANDS points at a copy of the icon_commands structure, which contains all of the icon-specific commands that get added to the master command list at runtime. The relevant one is this:

{ 0, STR_CMD_COORDS, CODE_CMD_COORDS, {{ 0 }}, 1, STR_CMD_COORDS_HELP },

Where STR_CMD_COORDS is defined as "editpos" in strings.c (the string table gets special handling because it is also pushed into client memory). The implementation of this command is actually very simple:

Code: [Select]
// ===== cmd_coords =====
// Calling convention: stdcall
// Very simple handler that toggles the coordinate display status.
unsigned char code_cmd_coords[] = {
0xBA,RELOC,                         // MOV EDX, OFFSET $draw_edit_bar
0x83,0x32,0x01,                     // XOR DWORD PTR [EDX], 1
0xC3,                               // RETN
};
reloc reloc_cmd_coords[] = {
    { ICON_DATA, DATA_SHOW_TOOLBAR },
    { RELOC_END, 0 }
};

All it does is toggle a byte in memory that the client uses in order to show the position editor or not. The window itself already existed for the map editor -- it's something that I appropriated because it was a convenient way to enter coordinates using a UI.

Most of the real magic happens in patch.c. I'm not going to quote that as it's not really very useful on its own (but you can download the Icon source code from the Git repository and take a look if you want). The important parts are right after the comments "Modify editor toolbar to affect entity position", "Move it to the corner of the screen". That section is just a bunch of hex numbers, what it's doing it rewriting the machine code of the COH client so that instead of using the selected editor object, it instead draws the coordinates of the currently targeted entity. All of that is stuff I mapped out in a debugger by hand in the disassembly view, then got the before and after opcodes to put into Icon so it could automate the patching process.

I tried to keep as much as possible in code.c, which is the completely new assembly language code that gets pushed into client memory, but some patching was still necessary to make COH interface to that new code, and a large amount of that patching happens to involve the coordinate editor.

Later on in the same file it has this:

Code: [Select]
    // Hook 'user entered new coordinates'
    PutCall(0x00440FE0, CodeAddr(CODE_POS_UPDATE_CB));
    bmagic(0x00440FEC, 0x30A13E74, 0x30A137EB);     // Jump to end after hook

That overwrites an existing function call inside the code that gets called when the user hits 'Enter' while in the coordinate editor window. It replaces the call destination with a new function that Icon pushes into client memory, followed by a jump to skip over the rest of the original code. That function is code_pos_update_cb:

Code: [Select]
// ===== pos_update_cb =====
// Calling convention: Custom
//      No stack changes (accesses parent function's stack)
//      Clobbers EAX, ECX, EDX, ESI
// Hook called from the edit toolbar's "something changed" code path.
unsigned char code_pos_update_cb[] = {
0x8D,0x74,0x24,0x20,            // LEA ESI, [ESP+20]
0xE8,RELOC,                     // CALL $get_target
// See if this is an absoulte or a relative change.
0x80,0x3D,RELOC,0x00,           // CMP BYTE PTR [$edit_transform_abs], 0
0x74, 0x12,                     // JE reltrans
0x50,                           // PUSH EAX
// Absolute transform, so push the entity and vector to face.
0x56,                           // PUSH ESI
0x50,                           // PUSH EAX
0xE8,RELOC,                     // CALL $set_ent_facing
// Use the XYZ part as new coordinates for the entity.
0x59,                           // POP ECX
0x8D,0x56,0x18,                 // LEA EDX, [ESI+18]
0xE8,RELOC,                     // CALL $ent_teleport
0xC3,                           // RETN

// reltrans:
// Relative, so we'll need some stack space for a temporary vector.
0x83,0xEC,0x10,                 // SUB ESP, 10
0x89,0x44,0xE4,0x0C,            // MOV DWORD PTR [ESP+0C], EAX
// First convert the player's matrix into a PYR trio. This suffers from some
// bad gimbal lock, but is the best we can do with the interface available.
0x8D,0x48,0x38,                 // LEA ECX, [EAX+38]
0x89,0xE2,                      // MOV EDX, ESP
0xE8,RELOC,                     // CALL $matrix_to_pyr
// Now add in the relative values entered.
0xD9,0x04,0xE4,                 // FLD DWORD PTR [ESP]
0xD8,0x06,                      // FADD DWORD PTR [ESI]
0xD9,0x1C,0xE4,                 // FSTP DWORD PTR [ESP]
0xD9,0x44,0xE4,0x04,            // FLD DWORD PTR [ESP+4]
0xD8,0x46,0x04,                 // FADD DWORD PTR [ESI+4]
0xD9,0x5C,0xE4,0x04,            // FSTP DWORD PTR [ESP+4]
0xD9,0x44,0xE4,0x08,            // FLD DWORD PTR [ESP+8]
0xD8,0x46,0x08,                 // FADD DWORD PTR [ESI+8]
0xD9,0x5C,0xE4,0x08,            // FSTP DWORD PTR [ESP+8]
// Make the entity face the resulting vector.
0x8B,0x44,0xE4,0x0C,            // MOV EAX, DWORD PTR [ESP+0C]
0x54,                           // PUSH ESP
0x50,                           // PUSH EAX
0xE8,RELOC,                     // CALL $set_ent_facing
// Now add the player's position with the entered coordinates, storing the
// result in our temporary space.
0x8B,0x4C,0xE4,0x0C,            // MOV ECX, DWORD PTR [ESP+0C]
0xD9,0x41,0x5C,                 // FLD DWORD PTR [ECX+5C]
0xD8,0x46,0x18,                 // FADD DWORD PTR [ESI+18]
0xD9,0x1C,0xE4,                 // FSTP DWORD PTR [ESP]
0xD9,0x41,0x60,                 // FLD DWORD PTR [ECX+60]
0xD8,0x46,0x1C,                 // FADD DWORD PTR [ESI+1C]
0xD9,0x5C,0xE4,0x04,            // FSTP DWORD PTR [ESP+4]
0xD9,0x41,0x64,                 // FLD DWORD PTR [ECX+64]
0xD8,0x46,0x20,                 // FADD DWORD PTR [ESI+20]
0xD9,0x5C,0xE4,0x08,            // FSTP DWORD PTR [ESP+8]
// Send the entity to the resulting coordinates.
0x89,0xE2,                      // MOV EDX, ESP
0xE8,RELOC,                     // CALL $ent_teleport
0x83,0xC4,0x10,                 // ADD ESP, 10
0xC3,                           // RETN
};
reloc reloc_pos_update_cb[] = {
    { ICON_CODE_REL, CODE_GET_TARGET },
    { COH_ABS, COHVAR_EDIT_TRANSFORM_ABS },
    { ICON_CODE_REL, CODE_ENT_SET_FACING },
    { COH_REL, COHFUNC_ENT_TELEPORT },
    { COH_REL, COHFUNC_MATRIX_TO_PYR },
    { ICON_CODE_REL, CODE_ENT_SET_FACING },
    { COH_REL, COHFUNC_ENT_TELEPORT },
    { RELOC_END, 0 }
};

The inline comments should be fairly self-explanatory. The absolute update is the easiest, it simply calls ent_teleport (a name I arbitrarily made up for a function in the COH client that instantly moves an entity to a new position without interpolating through the space in between), and set_ent_facing, which is a convenience function defined elsewhere in Icon that sets an entity's orientation based on PYR values rather than a full matrix like COH normally uses.

The second half under reltrans: handles the more complicated case of a relative transformation, which retrieves the current facing and position, then adds in the values entered.

If you haven't seen it, the full Icon source is available in the Git repo linked to in the info thread, though be aware that you need a Git client to access if. If you don't want to bother with that, I zipped up the files and tossed it on dropbox.

Be aware that Icon takes a very low-level approach to patching the client. While it does contain a few things like dynamic relocations to make it slightly more convenient than a straight binary patch, there's still a lot of machine code, though I do include the assembly in the comments to make it somewhat readable. Because of that, adding features and updates to Icon is kind of a massive pain in the butt, since it means I have to do it all in Ollydbg and then transpose it into Icon. That's the main reason that development has been focused on Paragon Chat instead, as it's a bit less of a pain to write (but is about 50,000 times more complex because of all it has to do).

Jeff Anderson

  • Boss
  • ****
  • Posts: 121
Re: Programmatic /API to NPC coordinates in icon
« Reply #3 on: September 11, 2015, 03:12:15 PM »
To make sure I understand, in order to get external client movement working I would need to add some code to the pass code that you created, specifically:

1) execute the code that gets the characters position, possibly by updating the editpos command so the command  dumps these coordinates out to a text file, something along the lines of "NPCname, X,Y, Z"

I assume I could find the relevant commands  by looking for the code near the comments "Modify editor toolbar to affect entity position",  or is this line relevant?
0xE8,RELOC,                     // CALL $get_target

2: write some kind of text file handler that looks for changes in a certain file, reads it for coordinates (instead of the editpos text box)

And call
    // Hook 'user entered new coordinates'
    PutCall(0x00440FE0, CodeAddr(CODE_POS_UPDATE_CB));
    bmagic(0x00440FEC, 0x30A13E74, 0x30A137EB);     // Jump to end after hook

Although I assume the first putcall parameter would have to be a different memory address since I'm not getting anything from the position text box.

ie: PutCall(location read from text file adress, CodeAddr(CODE_POS_UPDATE_CB));

Alternatively I can have my code update the text box and then just run this function unaltered.

I see a couple of path forward:

1 - learn enough assembly on my own to make this happen download the source code patch, etc.

2 - find a coder who knows assembly, (I actually don't, I am a Java, Python, JavaScript, etc guy) to get it done and pay him.

In your estimate (assuming that I even have the approach right) what do you think the effort would be to do the work? It looks to me to be more about setting up a memory space and writing some text handling logic / other external mechanism logic is where most of the complexity lies, as you have already patched icon in a way that modifying the targets location as possible, as well as getting those coordinates. Just need some way to access the edit position box, or the location address memory directly.

3) I thought I saw a post somewhere where somebody was actually able to use cheap tools to access some location memory directly, they used it to create an "XYZ" application, problem is is that the location on the camera, not the targeted character. Now that I know the memory addresses of the location (from what you've provided) perhaps I can use that approach to directly update the memory space
 
Final question are there specific tools IED bugger integrated development environment, Build, that you are using to assemble icon? Version of C, etc.?

Thanks again for all the great info!




Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Programmatic /API to NPC coordinates in icon
« Reply #4 on: September 11, 2015, 09:04:51 PM »
Well, there are a couple different ways you could approach it. One is to extend Icon itself, adding a command to move the target to the specified coordinates, then use your keybind files to execute that command. This method does require both knowledge of assembly language, as well as knowledge of enough machine code to take the binary output from an assembler, paste it into Icon, and replace the 'external' function calls with RELOC so that Icon can fix up the addresses based on whether or not it's an I23 or I24 client.

If you go that route, you don't really have to worry much about things like setting up a memory space. Icon already takes care of that, so if you add a new subroutine and hook it up to Icon's structures, it will go along for the ride. Worst case scenario you may run out of space and have to increase the amount of memory that Icon allocates, which is as easy as changing a single constant #define. You can then add the command itself to data.c by following the example of the existing ones. CMD_TIME is a good one because it takes a floating point argument, so you could duplicate that three times using DATA_PARAM1, DATA_PARAM1+4, and DATA_PARAM1+8, and let the game's command handler worry about parsing the floats.

Rather than messing around with the editpos text box, I would instead look at how /movenpc is implemented. It's much simpler and doesn't require any of the PutCall/bmagic junk to patch the exe, which isn't necessary for a simple slash command that doesn't need to do things like modify an existing UI. About all you'd need to do is change it from replacing the entire matrix from the player's to instead calling ent_teleport after putting a pointer to DATA_PARAM1 into EDX and [$target] into ECX.



If you don't want to have to program in assembly, you might get more mileage out of poking around in client memory yourself. That's more direct than communicating with Icon using convoluted channels of loading keybinds. It's also something you could potentially do in a language like Python (it seems that ctypes.windll can let you call ReadProcessMemory/WriteProcessMemory).

To help get you started, I grabbed a couple of useful locations from the Icon source. In a running Issue 24 client, the current target pointer is stored in memory location 0x00F14FB0 (this is actually a static variable in the exe's .data section, so it can never move around without recompiling). If the value read is 0, then there is no selected entity. If instead, there is a nonzero value there, it's a pointer to the entity structure. That means that the value you read will be the memory location of the start of the targeted entity. Since the entity structure is huge and complex, I'll just tell you that the entity's transformation matrix is stored at offset 0x38 from the start. So if you add 0x38 to the pointer in 0x00F14FB0, you'll find 12 single-precision (32-bit) floating point numbers in a row. This is a 4x3 matrix. The first 9 floats define the orientation of the entity (unit vectors for the X, Y, and Z axes), while the last 3 are the translation. If all you're after is position, you can just look at offset 0x41 instead to skip over the rotation. This matrix is used by the engine to render each frame, so if you write new values there, the entity will instantly jump to a new position.

Other useful memory locations are 0x00CAF580 for the pointer to the player's entity structure, and 0x012F6C40, which is the start of an array of 10240 pointers that point to any active entities (it's actually a lookup table for entity ID).

3) I thought I saw a post somewhere where somebody was actually able to use cheap tools to access some location memory directly, they used it to create an "XYZ" application, problem is is that the location on the camera, not the targeted character. Now that I know the memory addresses of the location (from what you've provided) perhaps I can use that approach to directly update the memory space

I haven't heard of "XYZ", but that sounds a lot like what CameraMan does, a tool I wrote for demo editors to be able to see the camera coordinates when in free-camera mode for copy/pasting into demo files. It predates Icon and directly accesses memory. For some of what you're doing, like changing locations, that would seem to be the easier route. However, something like kicking off an animation requires a function call (or your own independent animation sequencer and a way to look up the move numbers), so Icon's code-injection method is the easier way to go there.
 
Final question are there specific tools IED bugger integrated development environment, Build, that you are using to assemble icon? Version of C, etc.?

I'm using OllyDbg, which is a great debugger with features to facilitate reverse engineering. Since nothing in the client exe is labeled to start with, it's an extremely steep learning curve to figure out what it's doing. Looking at the memory locations in the Icon source might be a way to get started, because it at least gives you some reference points.

Icon is compiled with mingw32-gcc, a cross platform C compiler. Much of the "code" in it, however, is in the form of an array of bytes, which is machine code that was hand-assembled in OllyDbg, then copied out and put into a C array. The comments next to the series of bytes show the original assembly-language used to generate them.

Jeff Anderson

  • Boss
  • ****
  • Posts: 121
Re: Programmatic /API to NPC coordinates in icon
« Reply #5 on: September 13, 2015, 02:36:39 AM »
 codeWalker, thanks to your advice I am one step closer to pulling this off.

 I was able to use the static address that you gave me that always has a reference to the target, and dig through a combination of cheat engine, as well as OLLYDBG application to figure out where all the position and name variables work that I needed to write/access.

I then found a read write memory wrapper for autohotkey (the language that I'm currently using) and now have a "targeted NPC" object whose properties are merely wrappers to the memory lookup functions.

Very cool, and really powerful, it really opens up what I can do with the champions /hero system virtual table top I am building.

I still have to dig into OLLYDBG, assembler, and maybe cheat engine as I have ALOT to learn about how that all works, I think your pointers made looks way less intimidating than it was originally.

Quick question, my success today in accessing and writing directly to memory from external program makes me consider all kinds of possibilities and was wondering if you had some similar advice,/pointers/memory addresses to help get started...

1) If I want to access icon commands directly from memory I assume I could call them base on the previous information you sent already?

2) I'm thinking one thing it would be really cool is synchronizing the hero combat systems concept of stun & endurance to the hit points and endurance health bars in city of hero/icon. Would that just be a matter of finding the right memory variable and updating the numbers? Or would something more involved be required? Do you know where these are located. I am going to look on my own but was curious if you knew.

Anyways, that's it for now. I'm probably a week or two away from sharing stuff on the forum but when I do I think it's going to be pretty awesome.
« Last Edit: September 13, 2015, 04:09:15 AM by Jeff Anderson »

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Programmatic /API to NPC coordinates in icon
« Reply #6 on: September 15, 2015, 02:49:04 PM »
1) If I want to access icon commands directly from memory I assume I could call them base on the previous information you sent already?

I'm not sure this is (easily) possible with memory access alone, as it involves a control flow change. You could probably put a command in the buffer, but would still need a keystroke event to trigger the client to actually do something with it. I don't have the address of the buffer itself handy, but should be fairly easy to find with something like cheat engine or ollydbg's memory search by inputting a known string in the text box, hitting enter to send it to the command parser, then searching memory for it.

Quote
2) I'm thinking one thing it would be really cool is synchronizing the hero combat systems concept of stun & endurance to the hit points and endurance health bars in city of hero/icon. Would that just be a matter of finding the right memory variable and updating the numbers? Or would something more involved be required? Do you know where these are located. I am going to look on my own but was curious if you knew.

For issue 24, look 0x0E00 bytes into the entity (either target or player). Well maybe just player, I think the NPCs created by Icon don't have hitpoints. Anyway, at Entity+0x0E00 you'll find a pointer to the character structure. Chase down the address in the pointer, and from 0x00A4 - 0x0B6C bytes into the Character structure, you'll find the attributes block.

The attributes block is actually a set of 6 blocks back to back, each one having length 0x01CC, which is 460 bytes -- or a series of 115 floating-point numbers. The blocks correspond to the Cur, Mod, Max, Strength, Resistance, and I forget exactly what the 6th one is for. Very few of the attributes matter to the client or are even present there; most are zero.

The ones you'll probably be interested in are HitPoints (0x50), Endurance (0x58), and Meter (0x174). Add that to the start of the block you're interested in. For example, Cur HP is 0xA4 + 0x50 = 0xF4.  Max Endurance is in the third block, so it would be 0xA4 + 0x1CC + 0x1CC + 0x58 = 0x494. These are all 32-bit single precision floats, 4 bytes in length.

Meter controls the extra bar for Brutes and Dominators. It's hardcoded to show up only for those two ATs. For the tooltip to work right, Max Meter should be 1.0, and Meter should be between 0.0 and 1.0.

Jeff Anderson

  • Boss
  • ****
  • Posts: 121
Re: Programmatic /API to NPC coordinates in icon
« Reply #7 on: September 15, 2015, 11:09:39 PM »
Awesome!

I cant wait to get this implemented. The target capture stuff is working like a charm BTW cant thank you enough...

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Programmatic /API to NPC coordinates in icon
« Reply #8 on: September 16, 2015, 02:07:18 AM »
I should probably mention, if you haven't picked up on it from all the discussion there, but something like this is exactly what I'm hoping that the upcoming LUA API for Paragon Chat can be used for. With that, people will have a lot easier access to the engine internals, while being able to piggyback on XMPP to send custom messages, and having player position sync and chat already done for free. PChat can be used in offline single-player mode as well as networked, so a lot of what Icon does should eventually be possible there, but with significantly less handwritten assembly.

However, that's a long way off, and it sounds like you're making quite a bit of progress doing it "the hard way", so I think you should definitely keep at it. Feel free to ping me with questions or ideas, though I'm up to my ears in non-COH work and life stuff right now, so I can't promise to be very quick on responding.

Jeff Anderson

  • Boss
  • ****
  • Posts: 121
Re: Programmatic /API to NPC coordinates in icon
« Reply #9 on: September 16, 2015, 06:26:04 AM »
Yes, I cant wait for the Paragon chat features, but am eager to get some of these features so am going it the hard way :), I am wondering if I should switch my efforts to paragon instead, but it looks like quite a bit of work to get at icon level functionality.

Thanks again for the help so far really appreciate it.

Jeff Anderson

  • Boss
  • ****
  • Posts: 121
Re: Programmatic /API to NPC coordinates in icon
« Reply #10 on: September 16, 2015, 06:34:46 AM »
When you pull this off you will be my personal hero.

Now that put asmile on my face  :)

Jeff Anderson

  • Boss
  • ****
  • Posts: 121
Re: Programmatic /API to NPC coordinates in icon
« Reply #11 on: October 14, 2015, 05:58:36 AM »
 Codewalker,

Just wanted to drop you a quick line to say thanks, The health insurance bars now update based on who arrive target in city of heroes, to reflect the actual values of the characters represented by the model being targeted.

I've also got external movement working, which is enabled me to do some pretty cool things like moving external models, moving groups of people at the same time, having characters walk to each other, etc.

I'll make sure to post the latest version of the application along with videos this week.