Author Topic: Unit modification tutorial  (Read 6129 times)

Offline Magitek

  • Jr. Member Mark II
  • **
  • Posts: 72
Unit modification tutorial
« on: November 11, 2015, 06:35:45 am »
I was interested in bringing player starships back to their former glory, so I start hacking away at AI War. Here's a rough tutorial on the changes I did, if anyone else is interested.

I was successful in doing the following:
Adding a new research button. No more free Starship, you unlock each tier and the first tier will be more useful than before. I utilized the UNUSED2 tech to implement the research (there are eight more of these spare), I'm not sure I can add more techs beyond nine yet.
Altering the Max health of the ship.

The tools I used:
Simple assembly explorer SAE (inserts/copy pastes assembly, this is the only thing necessary)
IDA pro and it's graph view (Good for examination of the AI War Assembly-CSharp.dll)
Any C# decompiler (Helpful for understanding sections of code)

I used version 8.023 of the GOG windows edition of the game for this. Keep in mind you'll have to find the offsets yourself via searching in IDA if you're using a different version.

Files of note:
Tech.cs -> InitializeType (Stores research buttons and research cost)
ForegroundUnitTypeImmutable.cs -> InitializeType (Stores unit stats and pre-requisites)
Game.cs -> LoadImages (Load new images into memory, specifically for our tech button)
ForegroundObjectType.cs (List of all unit IDs)
TechType.cs (List of all research topics - sequential order)

Back up your Assembly-CSharp.dll first (for windows it's in AiWarGame\AIWar_Data\Managed\ ). You're sure to break it, so keep a copy handy.

Open Assembly-CSharp.dll with simply assembly. Most of the additions were copy and pasted from other sections using SAE and modified using SAE.
Keep in mind that my line numbers and yours may differ because SAE likes to throw things around a bit. It'll happen when you save and have added new lines to the code. SAE will automatically update the line numbers for functions but keep this in mind if you are saving often. In the event your switch statement doesn't line up with a working function, it'll break the game in fantastic ways. So it pays to check that you've got the correct numbers.

You'll want to take backups between steps to save yourself some headache when you make a mistake you can't fix.

If you've decompiled the source (not necessary but helpful if you're modifying other things), you should check the tech.cs file and function InitializeType and you'll see the overlying structure in C# and the research topic part of the raid starship.
Spoiler for Hiden:
   case TechType.UnlockRaidStarshipII:
      this.PurchaseCost = 2000;

You can use IDA (attach to the .NET assembly Assembly-CSharp - game doesn't need to be running) and search for all occurrences of 0x95 (Raid research II) to find the location easier. SAE is not great at searching. IDA-ViewA -> search -> immediate value -> find all -> 0x95. Keep in mind that not every 0x95 in the file is related to the research id 0x95.

Sub_B4CC0 Tech::InitializeType()

Locating the research:

If you're just interested in altering unit statistics and not adding a research topic, you can probably skip to #10.

Step #1 Tech->InitializeType: Add (0x6 research topic-UNUSED2) research topic requirement to Raidship-II's research topic
This step adds the requirement to the original Raidship and it won't be unlocked by default anymore, although the raid starship itself must also be modified also, this is just the research topic for it.

First you'll want to copy a Tech::IsStackedOnPriorBuyEntry and paste it at the top of 1e96. The assembly is 3 lines starting from ldarg.0 and ending on stfid as pictured above.
Use edit to change the ldc.i4 variable to ldc.i4.1.
Ensure you replicate the entire assembly instruction via copy+paste or it'll just crash the game. Make sure you're not a line too far up or down when pasting the code in also. It only takes one misaligned function to ruin the entire DLL.
This change makes the level 2 raidstar tech stack on top of our level 1 research which we will create shortly.

Step #2
Next you'll want to copy and paste in a Tech::Prerequisite, the format is very similar to the last assembly instruction. This time we edit the ldc.i4 to our prerequisite technology for the unlock to 6. (currently named UNUSED2)
You can also modify the research cost just above that in a similar manner.

You should save here and make sure the research panel in-game still works. If something went wrong, you should replace the DLL with the backup and try again.

Step #3 Tech->InitializeType: Add a new research topic (0x6 research topic-UNUSED2) at offset 1ec8 (SAE: Search->Offset) /  line 1898 via SAE. It should be located just below the Tech 3 research topic. Ensure that your new research topic is between a "br" assembly command and a "ldarg.0". Failure to do so will result in broken research.
You can copy the bits you need from any other topics nearby, as they all return to the branch.

You should save here, the research panel should still function.

Step #4 Tech->InitializeType: Now we merge our new function into the research switch statement. Use edit on the switch statement at the top of the file.

Because we're changing how research 0x6 works, it's critical we modify the sixth value in the branch.
It was originally just returning nothing for UNUSED2(0x6), but now it jumps to the new Raid 1 research we just created.
This is where you put in the line number of your new research function. In my case it was line 1904. (5906 simply removes the research topic.)

You should save here and ensure the game research isn't damaged.

Now when the game checks the research topics, the 0x6 research topic (UNUSED2) is defined. Now we need to make our Raid starship require the research.

Step #5 ForegroundUnitTypeImmutable->InitializeType: Add pre-requisite research (0x6) to RaidStarship near offset 16b33.
Here you're not making a new function, but inserting a research requirement to the tech 1 raid starship.

If you've decompiled the DLL, this is roughly where we are in the ForegroundUnitTypeImmutable.cs file. Finding this change is much easier in the c# source, although searching with 0x95 on IDA does reveal the MK2 research requirement. I just had no idea if a place for the MK1 even existed, but it did. It was the function without the tech pre-requisite of course.
Spoiler for Hiden:
      case ForegroundObjectType.RaidStarship:
      case ForegroundObjectType.RaidStarshipII:
      case ForegroundObjectType.RaidStarshipIII:
      case ForegroundObjectType.AIRaidStarship:
      case ForegroundObjectType.AIRaidStarshipII:
      case ForegroundObjectType.AIRaidStarshipIII:
      case ForegroundObjectType.RaidStarshipIV:
      case ForegroundObjectType.RaidStarshipV:
      case ForegroundObjectType.AIRaidStarshipIV:
      case ForegroundObjectType.AIRaidStarshipV:
Just underneath that, you'll see both the research and the unit stats. Sadly we cannot recompile this C# code because it is damaged and thus the rather large effort of hacking the assembly manually.

Step #6 /AiWarGame/RuntimeData/Language/en/Ships.xml add Unused2_Full and Unused2_Short for unlock name.
Spoiler for Hiden:
<ln id="Unused2_Full">Human Raid Starship</ln>
<ln id="Unused2_Short">Star:Raid</ln>

Step #7 TechType: rename Unused2 to UnlockUnused2 (allows it to read from the ships.xml, the game removes the "unlock" portion of the string)
You can do this by right-clicking the Unused2 entry in SAE inside TechType. (TechType is Just under Tech). Make sure you save the DLL.
This is a required rename for the words to be printed correctly when it is unlocked in coop.

Step #8 Add an image for the research button at /AiWarGame/RuntimeData/Images/Tech/UnlockUnused2.png
You can skip this step but your icon will look blank.

Step #9 Game->LoadImages: Add our image Tech/UnlockUnused2 (0x6 research topic-UNUSED2) to be loaded by the game.
The location doesn't matter, but incase you get lost, search for the string "UnlockRaidStar" in SAE.

Step #10 Editing unit statistics.
Just below the location in step 5 (ForegroundUnitTypeImmutable -> InitializeType, offset 16c60) you'll find the majority of the Raid starship's statistics and you're able to freely edit what you want. Use good old fashioned Calc.exe to convert between decimal and hexidecimal. If you want to edit other units, you will probably want to search for them using IDA using the units string name.
For example, by searching for the text string "RaidStarshipII" in IDA reveals it under the InitializeType function.
The RaidStarship-II is ID 0x234.

You can double click the parent function in order to find the base ship type.

Changes with SAE apply with glacial speed due to the massive size of the unit class. You could probably hand edit things faster but I wasn't confident enough to do so.

Here's the completed DLL with just the steps above implemented.
Make sure you don't overwrite your original DLL, or you'll have to re-download the game.

I haven't done much else yet in terms of modding, but with the knowledge above I think creating units and adding new research isn't too difficult (a little time consuming maybe)
I'm sure there are better methods, but this is my current one. It'd be a lot easier if we could just decompile and recompile the DLL in C#.. or if Arcen would open some of the functionality to modders.

Hope you found this useful.

edit: fixed step numbers and the offset in step 10.
« Last Edit: November 12, 2015, 08:29:14 pm by Magitek »

Offline Pumpkin

  • Hero Member Mark III
  • *****
  • Posts: 1,201
  • Neinzul Gardener Enclave
Re: Unit modification tutorial
« Reply #1 on: November 11, 2015, 07:38:28 am »
That's an impressive work! It reminds me of what Red.Queen did.

or if Arcen would open some of the functionality to modders.
AIW2 has been tagged as "probable". See the thread here.
Please excuse my english: I'm not a native speaker. Don't hesitate to correct me.

Offline Captain Jack

  • Hero Member Mark II
  • *****
  • Posts: 808
  • Just lucky
Re: Unit modification tutorial
« Reply #2 on: November 12, 2015, 03:28:40 pm »
Oh this is COOL. I'm copying this down for personal experiments. Thanks for sharing!

Offline AnnoyingOrange

  • Jr. Member Mark II
  • **
  • Posts: 71
Re: Unit modification tutorial
« Reply #3 on: December 10, 2018, 06:18:55 am »
In case anyone is still messing around with this, DnSpy is a pretty good tool to edit Unity dlls: a fair warning, it's very slow and memory hungry when editing large classes such as the ones used here (especially ForegroundUnitTypeImmutable), and the decompiled C sharp editor is not very reliable so sticking to the assembly editor is a good idea, but on the flip side the interface is incredibly intuitive and easy to navigate.
Editing unit stats is a bit harder than expected due to the extensive use of super-optimized opcodes such as ldc.i4.3 to indicate the constant value 3, but it's nothing too complicated.
Here I made Spirecraft Attritioners 24 times as damaging, as an example.


SMF spam blocked by CleanTalk