| 
  • If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • You already know Dokkio is an AI-powered assistant to organize & manage your digital files & messages. Very soon, Dokkio will support Outlook as well as One Drive. Check it out today!

View
 

Adding and Editing Creatures

This version was saved 12 years, 3 months ago View current version     Page history
Saved by James Koppel
on June 6, 2012 at 1:10:15 am
 

Project Ironfist distinguishes itself by the ability to add new content, and new creatures are the most important type.

 

We added the first new creature as a proof-of-concept, and used this accomplishment to help with the initial announcement of the game shortly afterwards.  There's a lot of room for improvement, as some of the steps are still in the proof-of-concept stage, so a lot of this tutorial will change, but adding new creatures turned out to be a lot easier than we expected it to be.

 

Parts of this tutorial require basic familiarity with the command line. Here are a few introductions to the command line.

 

Windows: http://www.voidspace.org.uk/python/articles/command_line.shtml

Mac & Linux: http://linuxcommand.org/learning_the_shell.php

 

You should already have the Project Ironfist repository set up, which you learn how to do in the Setting up the Repository tutorial.

 

Making the Sprite

 

A creature starts off as a set of PNG images, one for each frame. This is mostly outside the scope of this tutorial. You can find spriting tutorials elsewhere, but there is no substitute for the hard work and critical eye needed to make good art.

 

There are a few other considerations. First, the frames must be drawn using the HoMM II Palette, KB.PAL, pictured below, and also available in the ironfist/art/palette folder of the repository. You should select some color not in the palette to use as the background; our tools will convert it to be transparent. We have not yet added support for creature shadow and selection highlight, but they will work the same way as the background color.

 

 

Second, all frames should be have the same dimensions. For the walking animation, the creature should be moving forward within the frame.

 

Converting to ICN

 

The next task is to pack your frames together into the format used by the game, the ICN sprite archive format. We wrote a tool to do this. The ICNWriter is inefficient and dirty (it tends to produce less-compressed files than in the original game), but it gets the job done.

 

You will need the Java compiler installed for this, though it comes preinstalled on many machines.

 

The ICNWriter lies in the tools/icn directory in the repository. Fire up your command line and move to that directory.  Use the following command to compile it.

 

    javac ICNWriter.java
  

Now, make sure all your frames are in the same folder, and that nothing else is in that folder. You'll now need a path to that folder. This is easiest if you copy the folder to be in the same directory as the ICNWriter. If the folder is named 

 

You will now need to invoke the ICNWriter using three things: The path to the directory with the frames, the palette to use, and the background color. Give the color in ARGB format, which is like the common RGB format, but has an extra value in the front for the opacity. The ICNWriter will then print out a binary dump of the ICN file it creates; you can redirect this dump to a file using the ">" operator.

 

For example, if you had a folder named "kobold" in the same directory as the ICNWriter, you were using the HoMM II palette (KB.PAL), you used perfectly opaque bright purple (RGB FF00FF, or ARGB FFFF00FF) as the background color, and you wanted to save the final results in KOBOLD.ICN, you would run the following command. 

 

     java ICNWriter kobold KB.PAL FFFF00FF > KOBOLD.ICN

 

A file named "KOBOLD.ICN" ready for use in the game will now appear in the same directory as the ICNWriter.

 

Every frame is placed in the ICN in the order the PNG file is returned by the operating system, usually alphabetical order. Remember this!

 

Note that, if you did not use the palette, ICNConverter will convert each pixel to the nearest color in the palette.

 

Setting the form

 

While the ICN file stores your sprites, the FRM (creature form) file tells the game how to use them. Most importantly, it tells the game how to put frames together into animations.

 

This is a big area of improvement in this process. We still have not labeled all the animations, and we still do not fully understand everything that the creature form files do. We're editing them using a fairly general tool for Mac, and we still don't have a good solution for Windows and Linux. At some point, we will likely finish reverse-engineering the FRM format, and then create a specialized program to generate them.

 

We edit FRM files using SynalyzeIt ( http://www.synalysis.net/ ), a free hex editor for the Mac which makes it easy to work with fixed binary formats. There is a similar program for Windows called the 010 Editor, but it's a bit expensive.

 

First, in SynalyzeIt, open the "creatureform.grammar" file in the tools/creature-form directory in the repo. You will probably want to edit an existing creature-form; go ahead and open GOBLMFRM.BIN in the tools/creature-form/example folder. SynalyzeIt will ask you if you want to apply the grammar; click "Ok."

 

You will now see something like this:

 

 

On the left is a binary view of the creature form file. The grammar file tells SynalyzeIt how to break up the file into various fields. On the right you will see an entry for each field.

 

The most important fields are the last 68 fields of the file: 34 fields giving the number of frames in each animation, followed by 34 lists giving, for each animation, the indices of the frames used in that animation. Remember how the ICNWriter program (usually) inserts frames in alphabetical order? You will need that information here.

 

Adding Sounds

 

You'll need to give your creature a short name, a four-letter abbreviation. For kobolds, we'll use "kbld."

 

Every creature needs four sounds, for attacking, moving, taking damage, and dying. For kobolds, these must be named "kbldattk.82M", "kbldmove.82M", "kbldwnce.82M", and "kbldkill.82M", and similarly for other creatures, depending on the short name. Shooters need an additional fifth sound for shooting. If kobolds could shoot, this would be called "kbldshot.82M".

An "82m=M" file is a raw WAV file with playback rate 22050 Hz. At some point, we'll write a tutorial on how to package sounds for the game. For now, copy the sounds from another creature and rename it.

 

Packing Resources

 

The artwork, creature form, and sounds together give everything the game needs to display your creature. The final step in getting the data into the game is to package them together with the other game resources.

 

All game data is packed into AGG (aggregate) files. These are archive files, similar to ZIP or RAR files, which can contain thousands of other files, including virtually all the game artwork. All the resources for the original game lie in HEROES2.AGG; everything for the Price of Loyalty expansion lies in HEROES2X.AGG. Everything you produce will be placed into ironfist.agg .

 

Making an AGG file is similar to making an ICN, but simpler. You will again need to use the Java compiler and the command line. You will first need to navigate to the tools/agg folder in the repository and compile the Agg tool with the following command:

 

     javac Agg.java

 

Now, place everything you wish to place into ironfist.agg into a folder named "ironfist". Place this folder in the same directory as the Agg tool, and run the following command.

 

     java Agg ironfist
 

This will create your "ironfist.agg" file. Place ironfist.agg in the Heroes2 DATA folder. Congratulations! Your resources will now be loaded into the game. Now we need to tell the game to use your creature.

 

Setting Creature Data

 

This is getting off the edge of the map: we don't have a proper process for setting the stats of your creatures. But this is also where we got a pleasant surprise: It turns out that, once you have the resources for the creature, adding it to the game is a matter of adding entries to several data tables.

 

If you're an artist, feel free to stop at this point. We're going to build ways of seeing your creature in action that don't involve recompiling the game. But if you're brave and want to press on without assistance, keep reading.

 

At the moment, these data tables live in the assembly file. We are planning to create a way to automatically move data tables over to C, or move them outside the realm of code entirely, but we could easily move these by hand. Still, at the moment, editing data tables means tweaking the assembly. Here's how to do it:

 

First, put all-lowercase strings giving the name of your creature, plural name of your creature, the ICN file, and the creature-form file somewhere in the data section. Anywhere. For example:

 

     Kobold_frm db 'kobldfrm.bin',0

     Kobold_name db 'kobold',0

     Kobold_plural_name db 'kobolds',0

     Kobold_Icn db 'kobold.icn',0     

This deserves repeating: all strings should be all lowercase. The trailing zero in the strings denotes the null terminator.

 

Find the following tables in the assembly:

 

     creatureIconNames
     creature_form_table
     creatureSingularNames
     creaturePluralNames

 

For each of these tables, you will need to append a reference to the relevant string.  For example, the "creatureSingularNames" table looks something like this:

 

     

creatureSingularNames dd offset aPeasant, offset aArcher, offset aRanger, offset aPikeman

                dd offset aVeteranPikeman, offset aSwordsman, offset aMasterSwordsma ; "peasant"

                dd offset aCavalry, offset aChampion, offset aPaladin

                dd offset aCrusader, offset aGoblin, offset aOrc, offset aOrcChief

                dd offset aWolf, offset aOgre, offset aOgreLord, offset aTroll_0

                dd offset aWarTroll, offset aCyclops, offset aSprite, offset aDwarf_0

                dd offset aBattleDwarf, offset aElf, offset aGrandElf

                dd offset aDruid_0, offset aGreaterDruid, offset aUnicorn

                dd offset aPhoenix, offset aCentaur, offset aGargoyle

                dd offset aGriffin, offset aMinotaur, offset aMinotaurKing

                dd offset aHydra_0, offset aGreenDragon, offset aRedDragon

                dd offset aBlackDragon, offset aHalfling, offset aBoar

                dd offset aIronGolem, offset aSteelGolem, offset aRoc

                dd offset aMage_0, offset aArchmage, offset aGiant, offset aTitan_0

                dd offset aSkeleton, offset aZombie, offset aMutantZombie

                dd offset aMummy_0, offset aRoyalMummy, offset aVampire

                dd offset aVampireLord, offset aLich, offset aPowerLich

                dd offset aBoneDragon, offset aRogue_0, offset aNomad_0

                dd offset aGhost_0, offset aGenie_0, offset aMedusa, offset aEarthElemental

                dd offset aAirElemental, offset aFireElemental, offset aWaterElemental

This is a list of pointers to the singular names of every creature in the game, ordered by their ID. Add your creature by appending the following line:

 

     dd offset Kobold_name

 

Note that this makes kobolds the 66th entry in the table. By doing so, we are implicitly giving kobolds an ID of 66.

 

Do similar things for the other three tables.

 

You will now need to give stats to your creature. Find the data table "creature_table" . You should see a bunch of entries that look like this:

 

     creatureStats <20, 21h, 11h, 12, 1, 0, 2, 1, 1, 1, 1, 0, 'psnt', 0, 0>

 

Each one of these creates an instance of the "creatureStats" structure to store information about your creature. Numbers that end in 'h' are hexadecimal.Add a similar entry to the end for yours. Here's the declaration of the creatureStats structure, which tells you what each of the fields do:

 

     creatureStats struct 

     cost dw ?

     fight_value dd ?

     fight_value_aux db ?

     growth db ?

     hp dw ?

     faction db ?

     speed db ?

     attack db ?

     defense db ?

     min_damage db ?

     max_damage db ?

     shots db ?

     short_name db 5 dup(?)

     creature_flags dw ?

     _  dw ?

     creatureStats ends

Some creature abilities (requires two-hexes, double attack, two-hex attack, flying) are specified in the creature_flags. Giving a special creature ability or making it require a special resource to purchase require deeper code modification, and are outside the scope of this tutorial.

 

After you make these changes, you will need to recompile the game. See the relevant tutorial: Getting Started with Coding

 

Adding to Maps

 

We have not yet modded the map editor, so we really don't have a proper way of putting creatures into maps. Still, if you want to see your creature moving, you can manually hex-edit a map to add it in.

 

In the normal Heroes 2 map editor, create a neutral town, and put 1337 Water Elementals in the garrison. Save the map. Open the map file in a hex editor, and search for the number "1337." This should bring you to the part of the map that specifies that the garrison has 1337 Water Elementals. You should see the number 65, the ID of Water Elementals, adjacent to the 1337. Change the ID to the ID of your creature, and change the quantity to whatever you want. Load the map in the game. Congratulations! You've fully added a creature.

 

Why are we adding them to the garrison of a neutral town? There are still a few things we have not put work into figuring out how to do: primarily adding in the portraits that display when you view a creature in your own army. We do know that the biggest challenges will be legal ones though: To do this, we will either need to substantially modify the code, or put your artwork in the same file as original artwork from the game. 

Comments (0)

You don't have permission to comment on this page.