Depending on how good of a programer, and in what language, can play a huge role in weather you use Visual Basic (VB) or Visual C# (C#). If you have never done any kind of programing befor, I would suggest starting with VB. If you have done programing befor but never done C# I would still recomend VB, but if you have done C# then you should stick with that. Once you have decided weather your are going to use VB or C# please continue to the next step.
2)Gathering Utilities
Visual Basic, Visual C# - Download Page
Once you have downloaded and installed VB or C# please proced to the Planning section
3)Planning
Here is where your Halo 2 App Comes to life. Firts we need to have a purpose for this app, most of you have allready thought of that. Please for the sake of god, DO NOT make a map resigner, pretty much every app has a built in one and there are many more scattered around. Secound you must think about how your app will look and added features. If your app will be used a lot like Entity, you might not want a white backround. If your up at 3 in the morning dead tired it will hurt your eyes so much and its bad for you. Here is a sample of a UI I designed:

As you can see its very dark, but light enough that you can read the text fine. Next Button layout, you defenity don want a million buttons or a million sidebars with dropdown boxes. I would suggest if you are making a lot of features, to use a hide/unhide system like Entity has with RAW data. This will save space and keep everything organized. Also send some samples of running beta's to your friends, I sent the beta of my app to about 10 people to get there opion. They liked it so I kept it. But dont change somehting just because one person doesent like it, if you like it then keep it. Now if your app will take longer then a day to make, dont tell people about it. Prometheus is an example, it has been in development for I think 2 years now, and still no public release other than a beta. It will defently be a kickass programe, but some people are very impatient and get angry, these people are know as Tarts. They have no idea what it takes to make good apps and why it takes so long so they bitch because they dont understand why it takes a while.
3)Design
Lets start with simple button features. On your main form, you dont want a million small things taking up space. Instead make the smaller things there own form, or put them all in one form depending on what they are/do. Here is some simple code that displays a new form when button1 is clicked:
Code: Select all
VB
Private Sub btnForm2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnForm2.Click
Form2.Show()
End Sub

You might want to put exstensions infront of the name of your form objects. If I have a textbox for the name of the map I would name it btnMapName for button Map Name. This helps you to not get confused with other form objects.
TabControls - Tab Controls are good if you are limeted to space and need to display information on mutiple things. But one of the bad things is there disabled state. It will disable everything on that tab, wich looks horible. Instead use TabControl1.Hide() untile needed, it will hide the tab so you cant see it, then when needed use TabControl1.Show().
4)Coding
Variables - A variable is a chunk of memery that contins information such as the name of something or numbers. There are a cuple diffrent ways to declear variables and many diffrent types of variables.
Constants - A Constant is a variable that has a set value and will never change. You must declear a Constant befor any subs in your class:
Code: Select all
VB
Public Class Form2
Const MyAge As Integer = 14
End Class
Code: Select all
C#
class myclass1
{
const int myinteger = 14;
}
Code: Select all
VB
Public Class Form2
Dim MyAge As Integer
End Class
Code: Select all
C#
class myclass1
{
private int myinteger;
}
Code: Select all
VB
Public Class Form2
Public MyAge As Integer
End Class
Code: Select all
C#
class myclass1
{
public int myinteger;
}
Code: Select all
VB
Public Class Form2
Public MyAge As Integer = 14
End Class
Code: Select all
C#
class myclass1
{
public int myinteger = 14;
}
Variable Types
Decimal - dec - Decimal
Short - srt - 16 bit integers
Long - lng - 64 bit integers
Integer - int - 32 bit integers
String - str - more than one letter
Char - chr - one letter
Byte - byt - byte
Boolean - bln - True or False
There are more but there not that important.
Binary Reading and Writing - Binary Readers/Writes are what reads and write info to and from the halo 2 map or any other file. Once you understand when to use a Binary Reader/Write and XML, it will help you make process much easer. To open a Binary Reader you need one thing, the location of the file you are opening. This is done like so:
Code: Select all
VB
Dim MapLocation As String
Dim BR As New BinaryReader(New FileStream(MapLocation, FileMode.Open, FileAccess.Read, FileShare.Read))
Code: Select all
C#
string MapLocation
BinaryReader BR = new BinaryReader(new FileStream(MapLocation, FileMode.Open, FileAccess.Read, FileShare.Read));
Code: Select all
VB
BR.BaseStream.Position = 2
Code: Select all
C#
BR.BaseStream.Position = 2;
Code: Select all
VB
Imports System.IO
Public Class Form1
Private Sub btnForm2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnForm2.Click
Dim MapLocation As String
Dim MapName As String
Dim BR As New BinaryReader(New FileStream(MapLocation, FileMode.Open, FileAccess.Read, FileShare.Read))
BR.BaseStream.Position = 408
MapName = BR.ReadChars(20)
BR.Close()
End Sub
End Class
Code: Select all
C#
using System.IO;
public void Read()
{
string MapLocation;
string MapName;
BinaryReader BR = new BinaryReader(new FileStream(MapLocation, FileMode.Open, FileAccess.Read, FileShare.Read));
BR.BaseStream.Poistion = 408;
MapName = BR.ReadChars(20);
BR.Close();
}
Code: Select all
Dim BR As New BinaryReader(New FileStream(MapLocation, FileMode.Open, FileAccess.Read, FileShare.Read))
Code: Select all
BR.BaseStream.Position = 408
MapName = BR.ReadChars(20)
Code: Select all
MapName = BR.ReadChars(20)
BinaryWriters - BinaryWriters are almost the same as Binary Readers except to decleare a new BinaryWriter you would use FileAcsess.Write, FileShare.Write instead of .Read. When writing information you would want to use this:
Code: Select all
BW.Write(MapName)
Code: Select all
BW.Write(MapName);
Classes - A Class is a blank code page that you can use to do what ever you want. Classes will become your best friend soon.
Message Boxes
A Message box is a little window that pops up and displays anything you want it to. Here is how you would display a message box when a button is pressed:
Code: Select all
VB
Private Sub btnForm2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnForm2.Click
MsgBox("Hi")
End Sub
Code: Select all
public void Button1_click()
{
MessageBox.Show("Hi");
}

You can also customize you message box to change the headline, make it an information box or criticle error box:
Code: Select all
Private Sub btnForm2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnForm2.Click
MsgBox("Hi", MsgBoxStyle.Critical, "Error")
End Sub

The formula for message boxes is
Code: Select all
VB
msgbox("Headline Text", MessageBoxStyle, "Form Text")
Code: Select all
C#
MessageBox.Show("Headline Text", MessageBox Style, "Form Text");
The If, Then statment does exactly what you would guess. Here is an example:
Code: Select all
VB
Dim TagSelected As Boolean
If TagSelected = False Then
MsgBox("Select a Tag first!", MsgBoxStyle.Critical, "Error")
End If
Code: Select all
C#
{
bool TagSelected;
if (TagSelected == false) {
Interaction.MsgBox("Select a Tag first!", MsgBoxStyle.Critical, "Error");
}
}
ElseIf Command to start another If, Then statement:
Code: Select all
VB
Dim TagSelected As Boolean = False
If TagSelected = False Then
MsgBox("Select a Tag first!", MsgBoxStyle.Critical, "Error")
ElseIf TagSelected = True Then
LoadDependancys()
End If
Code: Select all
C#
{
bool TagSelected = false;
if (TagSelected == false) {
Interaction.MsgBox("Select a Tag first!", MsgBoxStyle.Critical, "Error");
}
else if (TagSelected == true) {
LoadDependancys();
}
}
Code: Select all
VB
Dim Number As Integer
If Number = 1 Then
MsgBox("1")
Else
MsgBox("Not Number 1")
End If
Code: Select all
C#
{
int Number;
if (Number == 1) {
Interaction.MsgBox("1");
}
else {
Interaction.MsgBox("Not Number 1");
}
}
The Case Select statment is for detriming the value of something that could have many values:
Code: Select all
VB
Dim Number As Integer
Select Case Number
Case Is = 0
MsgBox("0")
Case Is = 1
MsgBox("1")
Case Is = 2
MsgBox("2")
Case Is = 3
MsgBox("3")
Case Is = 4
MsgBox("4")
Case Is = 5
MsgBox("5")
End Select
Code: Select all
C#
{
int Number;
switch (Number) {
case 0:
Interaction.MsgBox("0");
break;
case 1:
Interaction.MsgBox("1");
break;
case 2:
Interaction.MsgBox("2");
break;
case 3:
Interaction.MsgBox("3");
break;
case 4:
Interaction.MsgBox("4");
break;
case 5:
Interaction.MsgBox("5");
break;
}
}
5)Coding For Exceptions
Now if you have ever used Entity you will notice it is fairly easy to get an exception. This can easy be bypassed by coding errors for the exception. Lets say you have a map open, you dont have any tags selected and you hit the dependancy's button. Normally a null refrence exception would be thrown, but you could easly change this by coding an error for it. Now most errors would be displayed in a message box. Lets say I have a boolean(True or False) for TagSelected, and if its null and I click the dependacy's button and TagSelected is false, a null refrence exception would be thrown. Heres an example on how to fix this.
Code: Select all
VB
Private Sub btnForm2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnForm2.Click
Dim TagSelected As Boolean
If TagSelected = False Then
MsgBox("Select a Tag first!", MsgBoxStyle.Critical, "Error")
ElseIf TagSelected = True Then
ReadDependancys()
End If
End Sub
Code: Select all
C#
private void btnForm2_Click(object sender, System.EventArgs e)
{
bool TagSelected;
if (TagSelected == false) {
Interaction.MsgBox("Select a Tag first!", MsgBoxStyle.Critical, "Error");
}
else if (TagSelected == true) {
ReadDependancys();
}
}

5)Coding For Halo 2
Now that you have learned what coding is all about, you are ready to start coding for halo 2.
Map Structure
Thanks to -DeToX- for this.
Halo 2 Map Structure by -DeToX-
Index - Element Name - Type
_____________________________
0 Map Header Table
1 Sound Raw Raw
2 Model Raw 1&2 Raw
-----------------------------
3 BSP 1 Raw 1
4 BSP 2 Raw 2
5 LightMap Raw
6 BSP 3 Raw 3
7 BSP 4 Raw 4
-----------------------------
8 Decorator Raw
9 Weather Raw
10 Particle Model Raw
11 Collision Raw
12 Animation Raw
-----------------------------
13 BSP Meta
14 LightMap Meta
-----------------------------
15 StringID128 Table
16 StringID Index Table
17 StringID Table Table
18 FileTabel Table
19 FileIndex Table
20 Unicode Index Table
21 ugh! (crazy) Raw
22 Unicode Table
23 Bitmap Raw
24 Index Header Table
25 Metas Meta
26 Padding Padding
------------------------------
sorry abount the spacing cant fix it.
Header
The Header is the very beginning of the file. For Halo 2 the Header is 1024 byts if I remember correctly. In the Header for Halo 2 you will find Map name, Map scenario, Map build, and a lot of info for the tags and string ID's. Now that you know your basics in coding, im going to be very brief about simple stuff, but I will explain what it does.
First create a new project in VB or VC#. Now im going to use a fairly poor meathod as the better meathod takes to long to go through. Add a new class to your project called Halo 2 Map. It should look like this:
Code: Select all
VB
Imports System.IO
Public Class EntReader
End Class
Code: Select all
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Visual_Marker_Placement_Tool.Halo_2
{
class ModelMeta
{
}
}
Code: Select all
VB
Imports System.IO
Public Class Halo_2_Map
Public Structure Halo_2_Map
End Structure
Public Structure H2Tag
End Structure
End Class
Code: Select all
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Programing_For_Halo_2
{
class Halo_2_Map
{
public struct Halo_2_Map
{
}
public struct H2Tag
{
}
}
}
Code: Select all
VB
'Header Info
Public MapLocation As String
Public MapName As String
Public MapScenario As String
Public MapBuild As String
Public IndexOffset As Long
Public IndexSize As Long
Public MetaStart As Long
Public MetaSize As Long
Public FileTableCount As Long
Public FileTableOffset As Long
Public FileTableSize As Long
Public FileTableIndexOffset As Long
Public CrazyOffset As Long
Public CrazySize As Long
Public firstStringNamesOffset As Long
Public scriptReferenceCount As Long
Public scriptReferenceSize As Long
Public scriptIndexOffset As Long
Public secondStringNamesOffset As Long
C#
//Header info
public string MapLocation;
public string MapName;
public string MapScenario;
public string MapBuild;
public long IndexOffset;
public long IndexSize;
public long MetaStart;
public long MetaSize;
public long FileTableCount;
public long FileTableOffset;
public long FileTableSize;
public long FileTableIndexOffset;
public long CrazyOffset;
public long CrazySize;
public long firstStringNamesOffset;
public long scriptReferenceCount;
public long scriptReferenceSize;
public long scriptIndexOffset;
public long secondStringNamesOffset;
Code: Select all
VB
Imports System.IO
Public Class Halo_2_Map
Public Structure Halo_2_Map
'Header Info
Public MapLocation As String
Public MapName As String
Public MapScenario As String
Public MapBuild As String
Public IndexOffset As Long
Public IndexSize As Long
Public MetaStart As Long
Public MetaSize As Long
Public FileTableCount As Long
Public FileTableOffset As Long
Public FileTableSize As Long
Public FileTableIndexOffset As Long
Public CrazyOffset As Long
Public CrazySize As Long
Public firstStringNamesOffset As Long
Public scriptReferenceCount As Long
Public scriptReferenceSize As Long
Public scriptIndexOffset As Long
Public secondStringNamesOffset As Long
Public Sub ReadHeader()
Dim BR As New BinaryReader(New FileStream(MapLocation, FileMode.Open, FileAccess.Read, FileShare.Read))
End Sub
End Structure
Public Structure H2Tag
Public TagPath As String
Public TagClass As String
Public TagID As Long
Public MetaOffset As Long
Public MetaSize As Long
End Structure
End Class
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Programing_For_Halo_2
{
class Halo_2_Map
{
public struct Halo2Map
{
//Header info
public string MapLocation;
public string MapName;
public string MapScenario;
public string MapBuild;
public long IndexOffset;
public long IndexSize;
public long MetaStart;
public long MetaSize;
public long FileTableCount;
public long FileTableOffset;
public long FileTableSize;
public long FileTableIndexOffset;
public long CrazyOffset;
public long CrazySize;
public long firstStringNamesOffset;
public long scriptReferenceCount;
public long scriptReferenceSize;
public long scriptIndexOffset;
public long secondStringNamesOffset;
public void ReadHeader()
{
BinaryReader BR = new BinaryReader(new FileStream(MapLocation, FileMode.Open, FileAccess.Read, FileShare.Read));
}
}
public struct H2Tag
{
public string TagClass;
public string TagPath;
public long TagID;
public long MetaOffset;
public long MetaSize;
}
}
}
Code: Select all
VB
'Go to the header start
BR.BaseStream.Position = 16
'Read The IndexOffset
IndexOffset = BR.ReadInt32()
'Read our IndexSize
IndexSize = BR.ReadInt32()
'Read Our MetaSize and MetaStart
MetaSize = BR.ReadInt32()
MetaStart = BR.ReadInt32()
BR.BaseStream.Position = 288
'Read the MapBuild
MapBuild = BR.ReadChars(20)
BR.BaseStream.Position = 344
'Read the CrazyOffset and CrazySize
CrazyOffset = BR.ReadInt32()
CrazySize = BR.ReadInt32()
'string ID stuff
BR.BaseStream.Position = 352
firstStringNamesOffset = BR.ReadInt32() '352
scriptReferenceCount = BR.ReadInt32() '356
scriptReferenceSize = BR.ReadInt32() '360
scriptIndexOffset = BR.ReadInt32() '364
secondStringNamesOffset = BR.ReadInt32() '368
BR.BaseStream.Position = 408
'Read the MapName
MapName = BR.ReadChars(20)
BR.BaseStream.Position = 444
'Read the MapScenario
MapScenario = BR.ReadChars(80)
BR.BaseStream.Position = 704
'Read the FileTableOffset
FileTableCount = BR.ReadInt32()
FileTableOffset = BR.ReadInt32()
FileTableSize = BR.ReadInt32()
FileTableIndexOffset = BR.ReadInt32()
BR.Close()
C#----------------------------
char chr;
//Go to the header start
BR.BaseStream.Position = 16;
//Read The IndexOffset - start of the index
IndexOffset = BR.ReadInt32();
//Read our IndexSize - size of the index
IndexSize = BR.ReadInt32();
//Read Our MetaSize and MetaStart - meta for the tags
MetaSize = BR.ReadInt32();
MetaStart = BR.ReadInt32();
BR.BaseStream.Position = 288;
//MapBuild
MapBuild = "";
while ((chr = BR.ReadChar()) != '\0')
MapBuild += chr;
BR.BaseStream.Position = 344;
//Read the CrazyOffset and CrazySize - size of the crazy raw
CrazyOffset = BR.ReadInt32();
CrazySize = BR.ReadInt32();
//string ID stuff
BR.BaseStream.Position = 352;
firstStringNamesOffset = BR.ReadInt32();
//352
scriptReferenceCount = BR.ReadInt32();
//356
scriptReferenceSize = BR.ReadInt32();
//360
scriptIndexOffset = BR.ReadInt32();
//364
secondStringNamesOffset = BR.ReadInt32();
//368
BR.BaseStream.Position = 408;
//MapName
MapName = "";
while ((chr = BR.ReadChar()) != '\0')
MapName += chr;
BR.BaseStream.Position = 444;
//MapScenario
MapScenario = "";
while ((chr = BR.ReadChar()) != '\0')
MapScenario += chr;
BR.BaseStream.Position = 708;
//FileTable - tags strings etc
FileTableCount = BR.ReadInt32();
FileTableOffset = BR.ReadInt32();
FileTableSize = BR.ReadInt32();
FileTableIndexOffset = BR.ReadInt32();
BR.Close();
Code: Select all
VB
'Index Info
Public PrimaryMagicConstant As Long
Public MapPrimaryMagic As Long
Public SecondaryMagicConstant As Long
Public MapSecondaryMagic As Long
Public ObjectIndexOffset As Long
Public ObjectIndexPointer As Long
Public ObjectCount As Long
C#
public long PrimaryMagicConstant;
public long MapPrimaryMagic;
public long SecondaryMagicConstant;
public long MapSecondaryMagic;
public long ObjectIndexOffset;
public long ObjectIndexPointer;
public long ObjectCount;