Initial upload.

Adding base PRC 4.19a files to repository.
This commit is contained in:
Jaysyn904
2022-10-07 13:51:24 -04:00
parent 646eb01834
commit 1662218bb4
22441 changed files with 1274376 additions and 0 deletions

Binary file not shown.

View File

@@ -0,0 +1,797 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Text;
namespace NWN.FileTypes
{
/// <summary>
/// This class represents a 2da file. It contains all of the functionality
/// necessary to merge the 2da files.
/// </summary>
public class _2DA
{
#region public properties
public const string Empty = "****";
/// <summary>
/// Gets the number of rows in the 2da.
/// </summary>
public int Rows { get { return rows.Count; } }
/// <summary>
/// Gets the number of columns in the 2da.
/// </summary>
public int Columns { get { return heading.Count; } }
/// <summary>
/// Gets the heading row.
/// </summary>
public string Heading
{
get { return BuildString(heading); }
}
/// <summary>
/// Gets the schema for the 2da, the schema defines the columns.
/// </summary>
public StringCollection Schema { get { return heading; } }
/// <summary>
/// Gets/sets the index'th row of the 2da.
/// </summary>
public string this[int index]
{
get { return BuildString((StringCollection) rows[index]); }
set
{
// Make sure we have a schema.
TestForSchema();
// Parse the line to get the individual cells and throw an exception if
// the row's cell count does not match our cell count.
StringCollection row = ParseLine(value, false);
if (row.Count < heading.Count)
throw new InvalidOperationException("Row does not contain enough cells");
else if (row.Count > heading.Count)
throw new InvalidOperationException("Row contains too many cells");
// Pad the 2da to make sure it has room for the row, then add it.
Pad(index + 1);
rows[index] = row;
}
}
/// <summary>
/// Gets/sets a cell from the 2da.
/// </summary>
public string this[int row, int column]
{
get
{
return ((StringCollection) rows[row])[column];
}
set
{
// Make sure we have a schema.
TestForSchema();
// Pad the 2da to make sure it has room for the cell, then add it.
Pad(row + 1);
((StringCollection) rows[row])[column] = value;
}
}
/// <summary>
/// Gets the 2da file name w/o any path.
/// </summary>
public string Name { get { return Path.GetFileName(fileName); } }
/// <summary>
/// Gets the 2da name with any specified path information.
/// </summary>
public string FileName { get { return fileName; } }
/// <summary>
/// Gets/sets the 2da offset. All rows in the 2da have their row numbers
/// shifted to be relative to this offset, i.e. the first row has a row
/// number of offset, the second offset + 1, etc.
/// </summary>
public int Offset
{
get { return offset; }
set
{
if (value == offset) return;
// Adjust all of the row numbers to
// the correct index value.
int index = value;
foreach (StringCollection row in rows)
{
row[0] = index.ToString();
index++;
}
// Save the offset.
offset = value;
}
}
#endregion
#region public methods
/// <summary>
/// Default constructor
/// </summary>
public _2DA()
{
heading = new StringCollection();
rows = new ArrayList();
colSizes = new int[100];
offset = 0;
fileName = string.Empty;
}
/// <summary>
/// Class constructor
/// </summary>
/// <param name="schema">The schema for the 2da. The schema defines
/// the columns contained in the 2da</param>
public _2DA(StringCollection schema) : this()
{
SetSchema(schema);
}
/// <summary>
/// Class constructor
/// </summary>
/// <param name="schema">The schema for the 2da. The schema defines
/// the columns contained in the 2da</param>
public _2DA(string[] schema) : this()
{
StringCollection schemaColl = new StringCollection();
schemaColl.AddRange(schema);
SetSchema(schemaColl);
}
/// <summary>
/// Sets the schema for the 2da. Setting the schema also clears the 2da.
/// </summary>
/// <param name="schema">The schema for the 2da. The schema defines
/// the columns contained in the 2da</param>
public void SetSchema(string schema)
{
// Setup the schema for the 2da.
heading = ParseSchema(schema);
AddRowColumnToSchema(heading);
// Changing the schema clears the 2da.
Clear();
}
/// <summary>
/// Sets the schema for the 2da. Setting the schema also clears the 2da.
/// </summary>
/// <param name="schema">The schema for the 2da. The schema defines
/// the columns contained in the 2da</param>
public void SetSchema(StringCollection schema)
{
// Setup the schema for the 2da.
heading = schema;
AddRowColumnToSchema(heading);
// Changing the schema clears the 2da.
Clear();
}
/// <summary>
/// Sets the schema for the 2da. Setting the schema also clears the 2da.
/// </summary>
/// <param name="schema">The schema for the 2da. The schema defines
/// the columns contained in the 2da</param>
public void SetSchema(string[] schema)
{
// Setup the schema for the 2da.
heading = new StringCollection();
heading.AddRange(schema);
AddRowColumnToSchema(heading);
// Changing the schema clears the 2da.
Clear();
}
/// <summary>
/// Gets the index of a column given it's heading.
/// </summary>
/// <param name="headingText">The heading text</param>
/// <returns>The index of the column or -1 if it's not found</returns>
public int GetIndex(string headingText)
{
// Loop through the headings doing a case-insensetive compare of the
// passed heading text, if we find it return the index.
for (int i = 0; i < heading.Count; i++)
if (0 == string.Compare(headingText, heading[i], true, CultureInfo.InvariantCulture))
return i;
// We didn't find the heading return -1.
return -1;
}
/// <summary>
/// Tests to see if the specified row is empty.
/// </summary>
/// <param name="row">The row to test</param>
/// <returns>true if the row is empty, false if it is not.</returns>
public bool IsEmpty (int row)
{
// Reality check on row argument.
if (row < 0 || row >= rows.Count) return false;
// Get the row and loop through all of the columns except the first
// (which is the row number) checking to see if any are not empty. As
// soon as we find a non-empty row return false.
StringCollection strings = (StringCollection) rows[row];
for (int i = 1; i < strings.Count; i++)
if (_2DA.Empty != strings[i])
{
// We need a special case here. Many 2da's use the label column
// to indicate reserved or free rows, purely as an informational
// message to someone trying to mod the 2da. If a row has data
// in the label column but no other then we want to consider the
// row empty as it has no meaningful content.
if (0 == string.Compare("label", heading[i], true, CultureInfo.InvariantCulture)) continue;
return false;
}
// All columns but the row number are empty return true.
return true;
}
/// <summary>
/// Tests to see if the specified cell is empty.
/// </summary>
/// <param name="row">The row of the cell</param>
/// <param name="column">The column of the cell</param>
/// <returns>true if the row is empty, false if it is not.</returns>
public bool IsEmpty(int row, int column)
{
return Empty == this[row, column];
}
/// <summary>
/// Clears the 2da of all cell data, preserving the schema.
/// </summary>
public void Clear()
{
// Reset the 2da to be empty.
offset = 0;
rows.Clear();
// Set the column widths to be the widths of the heading cells.
for (int i = 0; i < heading.Count; i++)
colSizes[i] = heading[i].Length;
}
/// <summary>
/// Pads the 2da to have the specified number of rows. If the 2da already has
/// more rows than the specified number nothing is done, if it doesn't then
/// blank rows are added to the end to pad.
/// </summary>
/// <param name="length">The new row count</param>
public void Pad(int length)
{
// Figure out how many rows we need to pad.
int numPad = length - rows.Count;
if (numPad <= 0) return;
// Add enough empty rows to pad the 2da.
for (int i = 0; i < numPad; i++)
{
StringCollection empty = EmptyRow(rows.Count);
rows.Add(empty);
}
}
/// <summary>
/// Copies a row from a source 2da to this 2da.
/// </summary>
/// <param name="source">The source 2da</param>
/// <param name="sourceRow">The index of the row in the source 2da</param>
/// <param name="row">The index of the row in this 2da</param>
public void CopyRow(_2DA source, int sourceRow, int row)
{
// Get the row from the source 2da and let our overload do all of the
// work.
StringCollection sourceRowData = (StringCollection) source.rows[sourceRow];
CopyRow(sourceRowData, row);
}
/// <summary>
/// Copies a row to this 2da.
/// </summary>
/// <param name="sourceRow"></param>
/// <param name="row"></param>
public void CopyRow(StringCollection sourceRow, int row)
{
// Get the target StringCollection, and determine the
// number of columns to copy being the minimum between the source
// 2da's column count and ours.
StringCollection rowData = (StringCollection) rows[row];
int columns = System.Math.Min(sourceRow.Count, heading.Count);
// Copy the row data, adjusting our column widths as necessary.
rowData[0] = row.ToString();
colSizes[0] = System.Math.Max(colSizes[0], rowData[0].Length);
for (int i = 1; i < columns; i++)
{
rowData[i] = sourceRow[i];
colSizes[i] = System.Math.Max(colSizes[i], rowData[i].Length);
}
}
/// <summary>
/// Gets the StringCollection containing the row data for the
/// given row.
/// </summary>
/// <param name="row">The row for which to get the row data</param>
/// <returns>A StringCollection containing the row data</returns>
public StringCollection GetRowData(int row)
{
return (StringCollection) rows[row];
}
/// <summary>
/// Fixes up a 2da join column by adding the given offset to all of the values
/// in the column.
/// </summary>
/// <param name="column">The index of the column (0 biased)</param>
/// <param name="offset">The offset to add to the column values</param>
public void Fixup2daColumn(int column, int offset)
{
// Loop through each row, adding offset to all of the
// values in the specified column.
foreach (StringCollection row in rows)
{
if ("****" != row[column])
{
int val = System.Int32.Parse(row[column]) + offset;
row[column] = val.ToString();
}
}
}
/// <summary>
/// Fixes up a 2da join column by adding the given offset to all of the values
/// in the column.
/// </summary>
/// <param name="column">The index of the column (0 biased)</param>
/// <param name="offset">The offset to add to the column values</param>
/// <param name="customTlk">If true, indicaets that the tlk offset is for a custom
/// tlk, this causes the custom tlk offset to be added to the offset as well.</param>
public void FixupTlkColumn(int column, int offset, bool customTlk)
{
// Custom tlk's have 0x1000000 added to their
// value, i.e. entry 0 in the tlk is really
// index 0x1000000, etc.
if (customTlk) offset += 0x1000000;
Fixup2daColumn(column, offset);
}
/// <summary>
/// Saves the 2da.
/// </summary>
public void Save()
{
SaveAs(fileName);
}
/// <summary>
/// Saves the 2da with the given file name.
/// </summary>
/// <param name="fileName">The name of the 2da</param>
public void SaveAs(string fileName)
{
using (StreamWriter writer = new StreamWriter(fileName, false, Encoding.ASCII))
{
// Write the 2da header.
writer.WriteLine(headerString);
writer.WriteLine();
writer.WriteLine(Heading);
// Write the row data.
for (int i = 0; i < rows.Count; i++)
writer.WriteLine(this[i]);
}
this.fileName = fileName;
}
#endregion
#region public static methods
/// <summary>
/// Compares 2 2da cell values to see if they are the same or not.
/// </summary>
/// <param name="value1">The first value</param>
/// <param name="value2">The second value</param>
/// <param name="ignoreCase">True if the comparison should be case-insensitive</param>
/// <returns>True if the cells are the same, false if they are different</returns>
public static bool CompareCell(string value1, string value2, bool ignoreCase)
{
return 0 == string.Compare(value1, value2, ignoreCase,
CultureInfo.InvariantCulture);
}
/// <summary>
/// Compares rows in 2 different 2da files to see if they are equal or not.
/// </summary>
/// <param name="twoDA1">The first 2da to test</param>
/// <param name="row1">The row in the first 2da to compare</param>
/// <param name="twoDA2">The second 2da to test</param>
/// <param name="row">The row in the second 2da to compare</param>
/// <param name="ignoreCase">True if the comparison should be case insensitive</param>
/// <returns>True if the rows are equal false if they are not</returns>
public static bool CompareRow(_2DA twoDA1, int row1, _2DA twoDA2, int row2,
bool ignoreCase)
{
// Get the data for each of the rows.
StringCollection row1Data = (StringCollection) twoDA1.rows[row1];
StringCollection row2Data = (StringCollection) twoDA2.rows[row2];
// If the rows have different amounts of cells then they are by
// definition different.
if (row1Data.Count != row2Data.Count) return false;
// Loop through the rows doing a cell by cell compare, stopping
// if we find any differences. We start at column 1 to skip
// the row numbrs which would of course be different.
for (int i = 1; i < row1Data.Count; i++)
if (!CompareCell(row1Data[i], row2Data[i], ignoreCase))
return false;
// The rows are identical return true.
return true;
}
/// <summary>
/// Factory method to create C2da objects from 2da files.
/// </summary>
/// <param name="fileName">The name of the 2da file</param>
/// <returns>A 2da object for the 2da file.</returns>
public static _2DA Load2da (string fileName)
{
// Open the 2da file.
_2DA file = new _2DA(fileName);
using(StreamReader reader = new StreamReader(fileName))
{
file.Read(reader);
}
return file;
}
/// <summary>
/// Factory method to create C2da objects from streams.
/// </summary>
/// <param name="stream">The stream to create the 2da object from</param>
/// <returns>A 2da object for the stream.</returns>
public static _2DA Load2da(Stream stream)
{
_2DA file = new _2DA();
using (StreamReader reader = new StreamReader(stream, Encoding.ASCII))
{
file.Read(reader);
}
return file;
}
/// <summary>
/// Merges 2 2da objects, saving the results in a 2da file. The method expects that
/// the source 2da will have at least enough rows to be contiguous with the merge
/// 2da (the source 2da should be padded by calling Pad() if necessary). If the
/// source and merge 2da's share some rows, the merge 2da rows will overwrite the
/// source 2da rows.
/// </summary>
/// <param name="source">The source 2da</param>
/// <param name="merge">The merge 2da</param>
/// <param name="outFile">The name of the output 2da</param>
public static void Merge2da (_2DA source, _2DA merge, string outFile)
{
using(StreamWriter writer = new StreamWriter(outFile, false))
{
// Write the 2da header.
writer.WriteLine(headerString);
writer.WriteLine();
writer.WriteLine(source.Heading);
// Make the column sizes in the source and 2da files to be the largest
// of each file, to make the columns have the correct width.
for (int i = 0; i < source.colSizes.Length; i++)
{
source.colSizes[i] = System.Math.Max(source.colSizes[i], merge.colSizes[i]);
merge.colSizes[i] = source.colSizes[i];
}
// output all of the source strings before our merge.
for (int i = 0; i < merge.Offset; i++)
{
string s = source[i];
writer.WriteLine(s);
}
// Test all of the rows that the merge is about to overwrite to make sure they
// are really empty. If any are not then generate a warning message for those
// rows.
int end = System.Math.Min(source.rows.Count, merge.Offset + merge.rows.Count);
for (int i = merge.Offset; i < end; i++)
if (!source.IsEmpty(i))
{
//CMain.Warning("Overwriting non-empty row {0} in {1}", i, source.FileName);
}
// output all of the merge strings.
for (int i = 0; i < merge.rows.Count; i++)
{
string s = merge[i];
writer.WriteLine(s);
}
// output any remaining source strings, in case the merge is in the middle.
for (int i = merge.Offset + merge.rows.Count; i < source.rows.Count; i++)
{
string s = source[i];
writer.WriteLine(s);
}
writer.Flush();
writer.Close();
}
}
#endregion
#region private fields/properties/methods
private const string headerString = "2DA V2.0";
private StringCollection heading;
private ArrayList rows;
private int[] colSizes;
private int offset;
private string fileName;
/// <summary>
/// Private constructor, to create objects use the static factory method
/// </summary>
/// <param name="fileName">The name of the 2da file</param>
private _2DA(string fileName) : this()
{
// Save the name of the 2da file.
this.fileName = fileName;
}
/// <summary>
/// Checks to make sure that a schema has been defined for the 2da, and throws
/// an InvalidOperationException if it doesn't.
/// </summary>
private void TestForSchema()
{
// If we have no heading row we have no schema throw an exception.
if (0 == heading.Count) throw new InvalidOperationException("2da contains no schema.");
}
/// <summary>
/// Creates an empty row for the 2da file.
/// </summary>
/// <param name="row">The index of the row which is being created</param>
/// <returns>The empty row</returns>
private StringCollection EmptyRow(int row)
{
// Create an empty row, and assign it a row number.
StringCollection empty = new StringCollection();
empty.Add(row.ToString());
// Adjust the maximum width of our column if it changed.
colSizes[0] = System.Math.Max(colSizes[0], empty[0].Length);
// Fill all other columns with the empty value.
int count = heading.Count;
for (int i = 1; i < count; i++)
{
empty.Add(_2DA.Empty);
colSizes[i] = System.Math.Max(colSizes[i], _2DA.Empty.Length);
}
// Return the empty row.
return empty;
}
/// <summary>
/// Builds a string from the data for the row. The string has padding whitespace
/// inserted such that all of the columns in the 2da will line up of the lines are
/// output to a text file.
/// </summary>
/// <param name="row">The row for which to build the string</param>
/// <returns></returns>
private string BuildString(StringCollection row)
{
System.Text.StringBuilder b = new System.Text.StringBuilder(4096);
int i = 0;
foreach (string s in row)
{
// If this is not the first row add a space separator.
if (i > 0) b.Append(' ');
// If the string contains spaces then wrap it in quotes.
string value = s;
if (value.IndexOf(' ') >= 0) value = string.Format("\"{0}\"", value);
// Add the string data and any whitespace padding necessary.
b.Append(value);
if (value.Length < colSizes[i]) b.Append(' ', colSizes[i] - value.Length);
i++;
}
return b.ToString();
}
/// <summary>
/// Adds the empty column for the row numbers to a schema
/// </summary>
/// <param name="schema">The schema to add the line to</param>
private void AddRowColumnToSchema(StringCollection schema)
{
// If the first entry is not blank then we need to add an empty
// column for the row number to the schema.
if (string.Empty != schema[0]) schema.Insert(0, string.Empty);
}
/// <summary>
/// Builds the schema for the 2da by parsing the text line.
/// </summary>
/// <param name="line">The line to parse</param>
/// <returns>A string collection containing the schema</returns>
private StringCollection ParseSchema(string line)
{
// Call ParseLine() to parse the schema line into the individual cell values,
// then add an extra blank entry for the row number.
StringCollection schema = ParseLine(line, true);
AddRowColumnToSchema(schema);
return schema;
}
/// <summary>
/// Parses a 2da file line to break the line into each of the column values.
/// Parses both the heading line (which contains no row number) and row data
/// lines (which do).
/// </summary>
/// <param name="line">The line to parse</param>
/// <param name="headerLine">True if the line is a header line</param>
/// <returns>A StringCollection containing the line's data</returns>
private StringCollection ParseLine(string line, bool headerLine)
{
StringCollection coll = new StringCollection();
// Determine the start index for the column sizes, if it's a header
// line we are parsing then the start index is 1 otherwise it's 0
int iColSize = headerLine ? 1 : 0;
try
{
for (int i= 0;;)
{
// Skip whitespace, if we skip past the end of the string then an
// index out of range exception will be thrown which we catch
// to end the parse.
while (' ' == line[i] || '\t' == line[i]) i++;
// OK, hack time. Some 2da's (itemprops.2da is the known case have
// a "Label" column as the last column. In this case the "label"
// IGNORES the rules about quoting spaces and allows spaces in the name,
// we have to catch this case by checking the schema to see if we are
// on the last column and it is called "Label".
bool isLabelColumn = !headerLine &&
coll.Count == heading.Count - 1 &&
0 == string.Compare(heading[coll.Count], "LABEL", true, CultureInfo.InvariantCulture);
// items in a 2da are separated by whitespace, unless quoted.
if (isLabelColumn)
{
// If we are reading the name column just grab the rest of the text to the
// end of the line and remove trailing whitespace.
string s = line.Substring(i);
s = s.Trim();
coll.Add(s);
i = line.Length;
}
else if ('"' == line[i])
{
// Find the end quote then add the substring.
int iEndQuote = line.IndexOf('"', i + 1);
string s = line.Substring(i + 1, iEndQuote - i - 1);
coll.Add (s);
// If the string we just added is the widest string for this column we've
// seen then save that info.
colSizes[iColSize] = System.Math.Max(colSizes[iColSize], s.Length);
iColSize++;
// Advance i past what we just added.
i = iEndQuote + 1;
}
else
{
// Find the next whitespace char and add the substring to the collection.
int iFirstWhitespace = line.IndexOfAny(new char[]{' ', '\t'}, i);
if (-1 == iFirstWhitespace) iFirstWhitespace = line.Length;
string s = line.Substring(i, iFirstWhitespace - i);
coll.Add(s);
// If the string we just added is the widest string for this column we've
// seen then save that info.
colSizes[iColSize] = System.Math.Max(colSizes[iColSize], s.Length);
iColSize++;
// Advance i past what we just added.
i = iFirstWhitespace;
}
}
}
catch (System.IndexOutOfRangeException)
{
// We use this exception as the terminating condition of the loop, so no
// error.
}
return coll;
}
/// <summary>
/// Reads 2da data from the specified stream, initializing the object with
/// the 2da data.
/// </summary>
/// <param name="reader">The reader from which to read the data</param>
private void Read(StreamReader reader)
{
// 2da files have the header followed by a line of white space.
// Consume that now.
reader.ReadLine();
reader.ReadLine();
// Read the header into memory and add an extra
// Now read the header and all of the data into memory.
for (bool fHeader = true; reader.Peek() > -1; fHeader = false)
{
string line = reader.ReadLine();
line = line.Trim();
if (0 == line.Length) continue;
// Parse the line into the collection of individual strings. If
// we have just read in the header row we don't have a heading
// for the row number, so add a dummy column to the front of
// the array so the header and data rows have the same number of
// columns.
StringCollection strings = fHeader ?
ParseSchema(line) : ParseLine(line, fHeader);
if (fHeader)
heading = strings;
else
{
// Do a reality check on the column count.
// Commented out until the CEP team fixes their fucked up 2da.
/*
if (strings.Count != Columns)
throw new InvalidOperationException(
string.Format("Row {0} in {1} does not have the correct number of columns",
rows.Count, Name));
*/
rows.Add(strings);
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,132 @@
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using HakInstaller.Utilities;
namespace HakInstaller
{
/// <summary>
/// Summary description for AboutForm.
/// </summary>
public class AboutForm : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Label labelCaption;
private System.Windows.Forms.PictureBox pictureBox;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public AboutForm()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
string name = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location);
this.Text += name;
string version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
labelCaption.Text = string.Format(labelCaption.Text, version);
Icon icon = new Icon(typeof(AboutForm), "HakInstaller.ico");
icon = new Icon(icon, 32, 32);
pictureBox.Image = icon.ToBitmap();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.labelCaption = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.pictureBox = new System.Windows.Forms.PictureBox();
this.SuspendLayout();
//
// labelCaption
//
this.labelCaption.Location = new System.Drawing.Point(96, 16);
this.labelCaption.Name = "labelCaption";
this.labelCaption.Size = new System.Drawing.Size(256, 32);
this.labelCaption.TabIndex = 0;
this.labelCaption.Text = "HakInstaller {0} - Installs custom content in NWN modules";
//
// label2
//
this.label2.Location = new System.Drawing.Point(96, 56);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(256, 16);
this.label2.TabIndex = 0;
this.label2.Text = "(C) 2004 Bleedingedge (Mark Sironi)";
//
// button1
//
this.button1.DialogResult = System.Windows.Forms.DialogResult.OK;
this.button1.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.button1.Location = new System.Drawing.Point(16, 88);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(72, 24);
this.button1.TabIndex = 5;
this.button1.Text = "&OK";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// pictureBox
//
this.pictureBox.Location = new System.Drawing.Point(24, 16);
this.pictureBox.Name = "pictureBox";
this.pictureBox.Size = new System.Drawing.Size(32, 32);
this.pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.pictureBox.TabIndex = 6;
this.pictureBox.TabStop = false;
//
// AboutForm
//
this.AcceptButton = this.button1;
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(360, 128);
this.ControlBox = false;
this.Controls.Add(this.pictureBox);
this.Controls.Add(this.button1);
this.Controls.Add(this.labelCaption);
this.Controls.Add(this.label2);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Name = "AboutForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "About ";
this.ResumeLayout(false);
}
#endregion
private void button1_Click(object sender, System.EventArgs e)
{
}
}
}

View File

@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="labelCaption.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="labelCaption.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="labelCaption.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="label2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="button1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="button1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="button1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="pictureBox.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="pictureBox.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="pictureBox.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>(Default)</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>80</value>
</data>
<data name="$this.Name">
<value>AboutForm</value>
</data>
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
</root>

View File

@@ -0,0 +1,58 @@
using System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("HakInstaller")]
[assembly: AssemblyDescription("Installs custom content in NWN modules")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("(C) 2004 Bleedingedge (Mark Sironi)")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("2.5.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

View File

@@ -0,0 +1,570 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Globalization;
using System.Reflection;
using HakInstaller.Utilities;
using NWN;
using NWN.FileTypes;
namespace HakInstaller
{
/// <summary>
/// This class impelments logic to resolve file conflicts between content
/// being added to the module from HIFs and content that already exists
/// in the module. Support is provided for the following:
///
/// TLK: If there are multiple tlk files between all content the class
/// will attempt to generate a single tlk file by merging all non-empty
/// rows into one tlk. If multiple tlk files use the same row then
/// the merge will fail.
///
/// 2DA: If HIFs and the module both have copies of the same 2da file
/// then the class will attempt to generate a merge hak containing
/// merged copies of all of the conflicting 2da's. The merged 2da's
/// will be built from the topmost version of the 2da from each HIF and
/// the module. If two content sources change the same row in a 2da
/// and the rows are not exactly the same then the merge for that 2da
/// will fail, but it will still attempt to merge other conflicting 2das.
/// </summary>
public class ConflictResolver
{
#region public properties/methods
/// <summary>
/// Class constructor
/// </summary>
/// <param name="progress">The interface used to provide progress information
/// to the user</param>
public ConflictResolver(IHakInstallProgress progress)
{
this.progress = progress;
conflictHak = string.Empty;
conflictHakDir = string.Empty;
conflictHakMessageShown = false;
}
/// <summary>
/// Attempts to resolve tlk file conflicts between the module tlk and any
/// tlk's defined in the hifs. It does this by attempting to build a
/// new tlk file containing all of the tlk entries from all tlks. If there
/// are no overlapping entries in the tlks's then this will succeed and
/// the name of the new tlk will be returned, if there are overlaps then
/// this will fail and string.Empty will be returned.
/// </summary>
/// <param name="module">The module for which we are resolving conflicts</param>
/// <param name="hifTlks">The list of tlk files from the HIFs being
/// installed.</param>
/// <returns>The name of the merge tlk file, or string.Empty if a merge tlk
/// could not be generated.</returns>
public string ResolveTlkConflict(Erf module, string[] hifTlks)
{
try
{
// Let the user know we are building a merge tlk.
progress.SetMessage("Building merge tlk for module\n'{0}'.",
Path.GetFileNameWithoutExtension(module.FileName));
// Create an array to hold all of the tlk objects.
Tlk[] tlks = new Tlk[hifTlks.Length];
// Load all of the tlk's.
for (int i = 0; i < hifTlks.Length; i++)
tlks[i] = Tlk.LoadTlk(NWNInfo.GetFullFilePath(hifTlks[i]));
// Generate the name of the new tlk file.
string newTlkFileName = GetFileName(module, "tlk");
if (null == newTlkFileName)
throw new NWNException("Cannot create new tlk file for module {0}", module.FileName);
// Get the largest entry count in all of the tlk files, we cannot move any of the tlk
// entries from where they are so the new tlk file will have as many entries as the
// largest source tlk file.
int count = 0;
foreach (Tlk tlk in tlks)
if (tlk.Count > count) count = tlk.Count;
// Create a new tlk file and add all of the entries from all of the tlk files
// to it.
Tlk newTlk = new Tlk(count);
for (int i = 0; i < count; i++)
{
// Check to see which tlk file contains this entry. If multiple tlk
// files contain this entry we cannot merge the tlk's
Tlk.TlkEntry entry = null;
foreach (Tlk tlk in tlks)
{
// Ignore empty entries.
if (i >= tlk.Count || tlk.IsEmpty(i)) continue;
// If we haven't gotten an entry for this row yet
// then save this entry. If we have then we cannot
// do the merge.
if (null == entry)
entry = tlk[i];
else
{
// Check to see if the data in two entries is the same.
// If it is then both tlk files have the same string
// data in the entry and we can still do the merge. This
// is most likely to happen at index 0 where many tlk
// files place "Bad Strref".
if (0 == string.Compare(entry.Text, tlk[i].Text, true, CultureInfo.InvariantCulture))
continue;
throw new InvalidOperationException();
}
}
// Save the entry in our new tlk file.
if (null != entry) newTlk[i] = entry;
}
// Save the new tlk file and return it's file name.
newTlk.SaveAs(NWN.NWNInfo.GetFullFilePath(newTlkFileName));
return newTlkFileName;
}
catch (InvalidOperationException)
{
// If an error occurs return string.Empty to indicate we couldn't generate
// a merge tlk.
return string.Empty;
}
}
/// <summary>
/// Attempts to resolve tlk file conflicts between the module tlk and any
/// tlk's defined in the hifs. It does this by attempting to build a
/// new tlk file containing all of the tlk entries from all tlks. If there
/// are no overlapping entries in the tlks's then this will succeed and
/// the name of the new tlk will be returned, if there are overlaps then
/// this will fail and string.Empty will be returned.
/// </summary>
/// <param name="hakInfos">The HIFs being added to the module</param>
/// <param name="module">The module for which we are resolving conflicts</param>
/// <param name="moduleInfo">The module info for the module</param>
/// <param name="conflicts">The list of files in conflict</param>
/// <returns>The name of the merge hak file, or string.Empty if a merge tlk
/// could not be generated.</returns>
public string ResolveConflicts(HakInfo[] hakInfos, Erf module, ModuleInfo moduleInfo,
OverwriteWarningCollection conflicts)
{
try
{
// Reset the message shown flag so we show the message once.
conflictHakMessageShown = false;
// Generate the name of the conflict resolution hak and the directory
// in which to place the files that will be added to the hak.
conflictHak = GetFileName(module, "hak");
conflictHakDir = NWN.NWNInfo.GetFullFilePath(conflictHak) + ".temp";
OverwriteWarningCollection copy = conflicts.Clone();
foreach (OverwriteWarning conflict in copy)
{
// Check to see if we can attempt to resolve the conflict, if
// we can then attempt to resolve it, and if the resolution is
// successful then remove the conflict from the collection.
switch (Path.GetExtension(conflict.File).ToLower())
{
case ".2da":
DisplayConflictHakMessage(module);
if (Resolve2daConflict(hakInfos, module, moduleInfo, conflict))
conflicts.Remove(conflict);
break;
}
}
// Get all of the files in the conflict hak directory, if there are none
// then there is no conflict hak.
if (!Directory.Exists(conflictHakDir)) return string.Empty;
string[] files = Directory.GetFiles(conflictHakDir);
if (0 == files.Length) return string.Empty;
// We have some resolved conflicts make the merge hak.
Erf hak = Erf.New(Erf.ErfType.HAK, "Auto-generated merge hak");
foreach (string file in files)
hak.AddFile(file, true);
hak.SaveAs(NWN.NWNInfo.GetFullFilePath(conflictHak));
return conflictHak;
}
finally
{
if (Directory.Exists(conflictHakDir)) Directory.Delete(conflictHakDir, true);
}
}
#endregion
#region private fields/properties/methods
private bool conflictHakMessageShown;
private IHakInstallProgress progress;
private string conflictHak;
private string conflictHakDir;
/// <summary>
/// Displays the building merge hak message once.
/// </summary>
/// <param name="module">The module that we are resolving conflicts for</param>
private void DisplayConflictHakMessage(Erf module)
{
if (conflictHakMessageShown) return;
// Let the user know we are building a merge tlk.
progress.SetMessage("Building merge hak for module\n'{0}'.",
Path.GetFileNameWithoutExtension(module.FileName));
conflictHakMessageShown = true;
}
/// <summary>
/// Generates a name for a conflict resolution file (hak or tlk). It generates
/// a name that is currently unused on disk.
/// </summary>
/// <param name="module">The module for which to create a new tlk file</param>
/// <param name="extension">The extension of the file to get a name for</param>
/// <returns>The tlk file name, or null if the name could not be created</returns>
private string GetFileName(Erf module, string extension)
{
// Use the first 12 characters of the module name as the base. Tlk
// files can only have 16 character names max, and we want to save 4
// characters for the index.
string namePrefix = Path.GetFileNameWithoutExtension(module.FileName);
if (namePrefix.Length > 12) namePrefix = namePrefix.Substring(0, 12);
namePrefix = namePrefix.Replace(" ", "_");
for (int i = 1; i <= 9999; i ++)
{
// Build the name using the name prefix and i, if the file name
// does not exist in the tlk directory then return it.
string name = string.Format("{0}{1:0000}.{2}", namePrefix, i, extension);
if (!File.Exists(NWNInfo.GetFullFilePath(name))) return name;
}
return null;
}
/// <summary>
/// Extracts a 2da file from the specified hak file, returning a
/// 2da object containing the 2da data.
/// </summary>
/// <param name="hak">The hak from which to extract the 2da</param>
/// <param name="fileName">The file name of the 2da</param>
/// <returns>A 2da object for the 2da file or null if the hak does not
/// contain the 2da file</returns>
private _2DA Extract2da(string hak, string fileName)
{
// Extract the 2da file from the hak and create an in memory copy.
MemoryStream stream = Erf.GetFile(NWN.NWNInfo.GetFullFilePath(hak), fileName);
return null == stream ? null : _2DA.Load2da(stream);
}
/// <summary>
/// Gets the 2da file from the module by looking at all of the haks in the
/// module info and checking each hak for the file.
/// </summary>
/// <param name="moduleInfo">The module info for the module</param>
/// <param name="fileName">The name of the 2da to get</param>
/// <returns>A 2da object for the 2da or null if the 2da is not in any
/// of the module's haks</returns>
private _2DA Get2da(ModuleInfo moduleInfo, string fileName)
{
// Get the list of haks in the module and loop through all of them
// trying to load the 2da, as soon as we get it return it.
StringCollection haks = moduleInfo.Haks;
if (null == haks) return null;
foreach (string hak in haks)
{
_2DA twoDA = Extract2da(hak + ".hak", fileName);
if (null != twoDA) return twoDA;
}
return null;
}
/// <summary>
/// Gets the 2da file from the HIF by looking at all of the haks in the
/// HIF and checking each hak for the file.
/// </summary>
/// <param name="hakInfo">The HIF</param>
/// <param name="fileName">The name of the 2da to get</param>
/// <returns>A 2da object for the 2da or null if the 2da is not in any
/// of the HIF's haks</returns>
private _2DA Get2da(HakInfo hakInfo, string fileName)
{
// Get the list of haks in the HIF and loop through all of them
// trying to load the 2da, as soon as we get it return it.
StringCollection haks = hakInfo.ModuleProperties["hak"];
if (null == haks) return null;
foreach (string hak in haks)
{
_2DA twoDA = Extract2da(hak, fileName);
if (null != twoDA) return twoDA;
}
return null;
}
/// <summary>
/// Attempts to resolve conflicts for a 2da file. It does this be attempting to
/// merge all duplicate copies of the 2da file into one merge 2da file.
/// </summary>
/// <param name="hakInfos">The HIFs being added to the module</param>
/// <param name="module">The module</param>
/// <param name="moduleInfo">The module info for the module</param>
/// <param name="conflict">The 2da file in conflict</param>
private bool Resolve2daConflict(HakInfo[] hakInfos, Erf module, ModuleInfo moduleInfo,
OverwriteWarning conflict)
{
try
{
// Create an array list and get the 2da from the module,
// adding it to the list if we get it.
ArrayList list = new ArrayList();
_2DA twoDA = Get2da(moduleInfo, conflict.File);
if (null != twoDA) list.Add(twoDA);
// Now get all of the copies of the 2da from the various HIFs and
// add them as well.
foreach (HakInfo hakInfo in hakInfos)
{
twoDA = Get2da(hakInfo, conflict.File);
if (null != twoDA) list.Add(twoDA);
}
// Load the BioWare version of the the 2da to use as a baseline, if the
// file isn't in the bioware directory then we will have to make due w/o
// it just make a blank 2da with the correct schema.
_2DA bioware = LoadBioWare2da(conflict.File);
// At this point we have all relevent copies of the conflicting 2da loaded into
// memory, we now need to generate a merge 2da if possible.
_2DA merge = Merge2das(bioware, list);
if (null == merge) return false;
// We have successfully merged all of the 2das, save the merge 2da and
// return true.
if (!Directory.Exists(conflictHakDir)) Directory.CreateDirectory(conflictHakDir);
merge.SaveAs(Path.Combine(conflictHakDir, conflict.File));
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// Loads a bioware 2da file.
/// </summary>
/// <param name="name">The name of the 2da to load</param>
/// <returns>A _2DA object representing the file.</returns>
private _2DA LoadBioWare2da(string name)
{
Stream stream = NWN.FileTypes.BIF.KeyCollection.GetFile(name);
_2DA bioware = _2DA.Load2da(stream);
return bioware;
}
/// <summary>
/// Attempts to merge all of the 2da's in the passed array list into 1 merge
/// 2da, by combining all of the non-empty rows in each 2da. If 2 2da's have
/// changes the same row then the merge will fail.
/// </summary>
/// <param name="baseline">The bioware baseline version of the 2da</param>
/// <param name="list">The list of 2da's to merge</param>
/// <returns>The merged 2da or null if the 2da's cannot be merged</returns>
private _2DA Merge2das(_2DA baseline, ArrayList list)
{
// Create a flat list to have a strongly typed list of 2da's.
_2DA[] merges = new _2DA[list.Count];
list.CopyTo(merges);
// Figure out the maximum number of rows we have to deal with
int rows = baseline.Rows;
foreach (_2DA merge in merges)
rows = System.Math.Max(rows, merge.Rows);
// Create the output 2da.
_2DA output = new _2DA(baseline.Schema);
output.Pad(rows);
// Loop through all rows attempting to merge each row into the
// output 2da.
for (int i = 0; i < rows; i++)
{
StringCollection mergedRow = null;
_2DA useForOutput = null;
foreach (_2DA merge in merges)
{
// Make an attempt to filter out junk rows with things
// such as "reserved", "deleted", etc in their labels.
// These often conflict but are really empty rows.
if (IsJunkRow(merge, i)) continue;
// If we have gone past the end of this 2da or the
// row is an empty row then ignore it.
if (i >= merge.Rows || merge.IsEmpty(i)) continue;
// If this is a row from the bioware version of the 2da
// and the data is the same as the bioware 2da then
// ignore this row in the 2da.
if (i < baseline.Rows &&
_2DA.CompareRow(baseline, i, merge, i, true)) continue;
// If we get here we have a non-empty row that differs from
// one of the bioware rows. Only 1 2da file per row can
// get past this point for use to be able to do a successful
// merge, if 2 2da's get here then 2 have changed the same
// row and we cannot merge.
// If we don't have any proposed row data yet then
// save this 2da's row data.
if (null == useForOutput)
{
useForOutput = merge;
continue;
}
// If we get here we have 2 2da's that want to change the same row.
// Our only hope for a successful merge is that the data in the
// 2 2da's is identical.
if (_2DA.CompareRow(useForOutput, i, merge, i, true)) continue;
// We already have an output 2da, which means that 2 2da's have
// changed the same row, attempt to glue all of the merge changes
// together. If we cannot generate a merged row then return null.
mergedRow = GenerateMergeRow(baseline, list, i);
if (null == mergedRow) return null;
// If we get here we have generated a merge row for all 2da's
// so we don't need to look at the data in this row any further
// break out of the loopo and use the mergedRow.
break;
}
// If we have merge 2da to copy from then copy the
// cell data. If we don't have a merge 2da but the row is
// withing the baseline 2da then copy the baseline data.
// Otherwise don't copy any data.
if (null != mergedRow)
output.CopyRow(mergedRow, i);
else if (null != useForOutput)
output.CopyRow(useForOutput, i, i);
else if (i < baseline.Rows)
output.CopyRow(baseline, i, i);
}
return output;
}
/// <summary>
/// Attempts to generate a merge row by taking all of the alterations made
/// to the bioware row from the merge 2da's and incorporating them into 1
/// row. This will work unless 2 different 2da's change the same column
/// in the row, which will make the merge fail.
/// </summary>
/// <param name="baseline">The bioware baseline 2da</param>
/// <param name="list">The list of 2da's being merged</param>
/// <param name="row">The row for which to generate a merge row</param>
/// <returns>The merged row, or null if a merge row could not be
/// generated.</returns>
private StringCollection GenerateMergeRow(_2DA baseline, ArrayList list, int row)
{
try
{
// We cannot merge if the row is not in the baseline.
if (row > baseline.Rows) return null;
// Create a copy of the merge row in the baseline 2da.
StringCollection resultRow = new StringCollection();
StringCollection baselineRow = baseline.GetRowData(row);
foreach (string s in baselineRow)
resultRow.Add(s);
// Create a bool array to keep track of which columns
// we modify.
bool[] writtenTo = new bool[resultRow.Count];
for (int i = 0; i < writtenTo.Length; i++)
writtenTo[i] = false;
foreach (_2DA merge in list)
{
// Get the row from the merge 2da.
StringCollection mergeRow = merge.GetRowData(row);
// If the collections do not have the same length then
// fail the merge, the added column may not be at the end.
if (mergeRow.Count != resultRow.Count) return null;
// Loop through all of the columns.
for (int i = 1; i < resultRow.Count; i++)
{
// Ignore empty data cells in the merge row.
if (_2DA.Empty == mergeRow[i]) continue;
// Compare the cell value against the baseline. If it is the
// same then ignore it. (the result row starts out as the baseline
// so we do not need to set these values, and we need to ignore
// them to detect double writes to the same cell)
if (_2DA.CompareCell(baselineRow[i], mergeRow[i], true))
continue;
// Compare the cells from the result row and the merge row,
// if they are different then we need to copy the merge
// row's value into the result row. However, if a previous
// merge 2da has modified this column then we have 2 different
// 2da's wanting non-bioware default values in the same
// column, if that happens there is no way to merge.
if (!_2DA.CompareCell(mergeRow[i], resultRow[i], true))
{
// If we've already changed the bioware default for this
// column we cannot merge return null.
if (writtenTo[i])
return null;
else
{
// Overwrite the bioware default for this column and
// save the fact that we have changed this column
resultRow[i] = mergeRow[i];
writtenTo[i] = true;
}
}
}
}
// If we get here we were able to take all of the various 2da
// modifications to the bioware row and make 1 merge row with all
// of the changes, return it.
return resultRow;
}
catch (Exception)
{
return null;
}
}
/// <summary>
/// Returns true if the row is a junk row.
/// </summary>
/// <param name="file">The 2da to test</param>
/// <param name="row">The row to test</param>
/// <returns>True if the row is a junk row.</returns>
private bool IsJunkRow(_2DA file, int row)
{
if (row >= file.Rows) return false;
int index = file.GetIndex("LABEL");
if (-1 == index) index = file.GetIndex("NAME");
if (-1 == index) return false;
// Check for common labels indicating that it is a junk row.
string value = file[row, index].ToLower();
if (-1 != value.IndexOf("deleted") ||
-1 != value.IndexOf("reserved") ||
-1 != value.IndexOf("user")) return true;
return false;
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,145 @@
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using NWN.FileTypes.Gff;
namespace HakInstaller
{
/// <summary>
/// Summary description for GffForm.
/// </summary>
public class GffForm : System.Windows.Forms.Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public GffForm(NWN.FileTypes.Gff.Gff gff)
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
this.gff = gff;
}
private System.Windows.Forms.TreeView tree;
private NWN.FileTypes.Gff.Gff gff;
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.tree = new System.Windows.Forms.TreeView();
this.SuspendLayout();
//
// tree
//
this.tree.Dock = System.Windows.Forms.DockStyle.Fill;
this.tree.ImageIndex = -1;
this.tree.Name = "tree";
this.tree.SelectedImageIndex = -1;
this.tree.Size = new System.Drawing.Size(536, 390);
this.tree.TabIndex = 0;
//
// GffForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(536, 390);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.tree});
this.Name = "GffForm";
this.Text = "GffForm";
this.Load += new System.EventHandler(this.GffForm_Load);
this.ResumeLayout(false);
}
#endregion
private void AddDictNodes (TreeNode parent, GffFieldDictionary dict)
{
System.Text.StringBuilder b = new System.Text.StringBuilder(1024);
foreach (DictionaryEntry entry in dict)
{
GffField field = (GffField) entry.Value;
if (field.IsList)
{
TreeNode node = parent.Nodes.Add(entry.Key.ToString());
AddCollNodes(node, ((GffListField) field).Value);
}
else if (field.IsStruct)
{
TreeNode node = parent.Nodes.Add(entry.Key.ToString());
AddDictNodes(node, ((GffStructField) field).Value);
}
else
{
b.Length = 0;
b.AppendFormat ("{0} = [{1}]", entry.Key.ToString(), field.ToString());
parent.Nodes.Add(b.ToString());
}
}
}
private void AddCollNodes(TreeNode parent, GffFieldCollection coll)
{
System.Text.StringBuilder b = new System.Text.StringBuilder(1024);
int i = 0;
foreach (GffField field in coll)
{
string name = "Entry_" + i.ToString();
i++;
if (field.IsList)
{
TreeNode node = parent.Nodes.Add(name);
AddCollNodes(node, ((GffListField) field).Value);
}
else if (field.IsStruct)
{
TreeNode node = parent.Nodes.Add(name);
AddDictNodes(node, ((GffStructField) field).Value);
}
else
{
b.Length = 0;
b.AppendFormat ("{0} = [{1}]", name, field.Value.ToString());
parent.Nodes.Add(b.ToString());
}
}
}
private void GffForm_Load(object sender, System.EventArgs e)
{
this.Text = gff.Name;
GffFieldDictionary top = gff.TopLevel;
TreeNode parent = tree.Nodes.Add("Top");
AddDictNodes(parent, top);
}
}
}

View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="$this.Name">
<value>GffForm</value>
</data>
</root>

View File

@@ -0,0 +1,450 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Threading;
using HakInstaller.Utilities;
namespace HakInstaller
{
/// <summary>
/// This class is a dictionary of hak properties. Each property contains
/// a string collection of values tied to the property.
/// </summary>
public class HakPropertyDictionary: DictionaryBase
{
#region public properties/methods
/// <summary>
/// Indexer to get the StringCollection for a given property
/// </summary>
public StringCollection this[string property]
{
get { return InnerHashtable[property] as StringCollection; }
}
/// <summary>
/// Default Constructor
/// </summary>
public HakPropertyDictionary()
{
}
/// <summary>
/// Adds a new property to the collection, creating a blank StringCollection
/// for it.
/// </summary>
/// <param name="property"></param>
public void Add(string property)
{
InnerHashtable.Add(property, new StringCollection());
}
#endregion
}
/// <summary>
/// This class represents a .hif file. This file contains information about
/// a 'hak' (hak in this case consisting of a collection of ERF, TLK, and HAK
/// files, along with a list of items in the module to modify). It provides
/// functionality to read the file into memory and access the various pieces of
/// the file.
/// </summary>
public class HakInfo
{
#region public properties/methods
/// <summary>
/// Gets the name of the HIF minus the extension.
/// </summary>
public string Name
{ get { return Path.GetFileNameWithoutExtension(fileInfo.Name); } }
/// <summary>
/// Gets the title of the HIF. This is the HIF's title property if
/// it has one, or it's file name if it doesn't.
/// </summary>
public string Title
{
get
{
StringCollection title = GetStrings(TitleKey, string.Empty);
return null == title || 0 == title.Count || string.Empty == title[0] ?
Name : title[0];
}
}
/// <summary>
/// Gets the version number of the HIF.
/// </summary>
public float Version
{
get
{
try
{
StringCollection version = GetStrings(VersionKey, string.Empty);
return (float) Convert.ToDouble(version[0], cultureUSA);
}
catch (Exception)
{
return 0;
}
}
}
/// <summary>
/// Gets the version of the HIF as a text string.
/// </summary>
public string VersionText
{
get
{
try
{
return GetStrings(VersionKey, string.Empty)[0];
}
catch (Exception)
{
return string.Empty;
}
}
}
/// <summary>
/// Gets the minimum version number of NWN required to install the HIF.
/// </summary>
public float RequiredNWNVersion
{
get
{
try
{
// Get the required string array and look for a string that starts with a
// digit, that would be the NWN version, return it if we find it.
StringCollection required = GetStrings(RequiredNWNVersionKey, string.Empty);
foreach (string s in required)
{
if (Char.IsDigit(s[0])) return (float) Convert.ToDouble(required[0], cultureUSA);
}
return 0;
}
catch (Exception)
{
return 0;
}
}
}
/// <summary>
/// Returns true if XP1 is required.
/// </summary>
public bool IsXP1Required
{
get
{
try
{
// Get the required string array and look for "XP1" or "Undrentide".
StringCollection required = GetStrings(RequiredNWNVersionKey, string.Empty);
foreach (string s in required)
{
if (0 == string.Compare("XP1", s, true, CultureInfo.InvariantCulture) ||
0 == string.Compare("Undrentide", s, true, CultureInfo.InvariantCulture))
return true;
}
}
catch (Exception)
{}
return false;
}
}
/// <summary>
/// Returns true if XP2 is required.
/// </summary>
public bool IsXP2Required
{
get
{
try
{
// Get the required string array and look for "XP1" or "Undrentide".
StringCollection required = GetStrings(RequiredNWNVersionKey, string.Empty);
foreach (string s in required)
{
if (0 == string.Compare("XP2", s, true, CultureInfo.InvariantCulture) ||
0 == string.Compare("Underdark", s, true, CultureInfo.InvariantCulture))
return true;
}
}
catch (Exception)
{}
return false;
}
}
/// <summary>
/// Gets the list of ERF files to add to the collection.
/// </summary>
public StringCollection Erfs { get { return components[ErfKey] as StringCollection; } }
/// <summary>
/// Gets the dictionary of module properties that must be added/modified.
/// </summary>
public HakPropertyDictionary ModuleProperties
{ get { return components[ModuleKey] as HakPropertyDictionary; } }
/// <summary>
/// Class constructor to load a .hif file from disk.
/// </summary>
/// <param name="fileName">The name of the hif file, hif files should
/// all live in the hak directory.</param>
public HakInfo(string fileName)
{
// Force the thread to use the invariant culture to make the install
// code work on foreign language versions of windows.
CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
try
{
fileInfo = new FileInfo(fileName);
InitializeComponents();
using(StreamReader reader = new StreamReader(fileName))
{
// Loop through all of the lines in the file.
for (int i = 1; reader.Peek() > -1; i++)
{
// Read the references line and split off the 2da file name and the references.
string line = reader.ReadLine();
line = line.Trim();
// If the line is blank or begins with a '#' ignore it.
if (0 == line.Length || '#' == line[0]) continue;
// Split the line into the type and references. If we don't get both
// parts the the line has a syntax error.
string[] strings = line.Split(':');
if (2 != strings.Length)
ThrowException("{0}: line {1}: syntax error", fileName, i.ToString());
// Save the component type and data.
string componentType = strings[0].Trim().ToLower();
string data = strings[1].Trim();
// Check to see if the component has a property. If there is
// a '.' in the name then it has a sub type, we need to split
// the component type into the type and property.
string componentProperty = string.Empty;
if (-1 != componentType.IndexOf('.'))
{
strings = componentType.Split('.');
componentType = strings[0];
componentProperty = strings[1];
}
// Split the various values, in case this can contain multiple
// values, and add each to the collection.
strings = data.Split(',');
StringCollection coll = GetStrings(componentType, componentProperty);
foreach (string s in strings)
coll.Add(s.Trim());
}
}
// The hak may or may not have a version number in it, if it doesn't add 0 so
// we always have a version number for lookup.
StringCollection version = GetStrings(VersionKey, string.Empty);
if (0 == version.Count) version.Add("0");
}
finally
{
Thread.CurrentThread.CurrentCulture = currentCulture;
}
}
/// <summary>
/// Validates the HIF to make sure that it can be installed, returning an error
/// message if it cannot.
/// </summary>
/// <param name="error">The error message if the HIF cannot be installed, or
/// string.Empty if the HIF can be installed</param>
/// <returns>True if the HIF can be installed, false if it cannot.</returns>
public bool Validate(out string error)
{
error = string.Empty;
// If the HIF has a minimum required version and the current NWN install isn't
// high enough then error out right away.
if (RequiredNWNVersion > 0 &&
(float) Convert.ToDouble(NWN.NWNInfo.Version, cultureUSA) < RequiredNWNVersion)
{
error = StringResources.GetString("ValidateNWNVersionError",
Title, RequiredNWNVersion, NWN.NWNInfo.Version);
return false;
}
// If the content requires XP1 then validate it.
if (IsXP1Required && !NWN.NWNInfo.IsXP1Installed)
{
error = StringResources.GetString("ValidateNWNXP1Error", Title);
return false;
}
// If the content requies XP2 then validate it.
if (IsXP2Required && !NWN.NWNInfo.IsXP2Installed)
{
error = StringResources.GetString("ValidateNWNXP2Error", Title);
return false;
}
// Build a list of ALL of the files referenced by the HIF.
StringCollection files = new StringCollection();
StringCollection strings = this.GetStrings(ErfKey, string.Empty);
foreach (string s in strings) files.Add(NWN.NWNInfo.GetFullFilePath(s));
strings = GetStrings(ModuleKey, "hak");
foreach (string s in strings) files.Add(NWN.NWNInfo.GetFullFilePath(s));
strings = GetStrings(ModuleKey, "tlk");
foreach (string s in strings) files.Add(NWN.NWNInfo.GetFullFilePath(s));
// Loop through all of the files checking to see which, if any, are missing.
string missingFiles = string.Empty;
foreach (string file in files)
{
// If the file is missing add it to our missing files string.
if (!File.Exists(file))
{
if (0 == missingFiles.Length) missingFiles += "\r\n";
missingFiles += "\r\n\t";
missingFiles += NWN.NWNInfo.GetPartialFilePath(Path.GetFileName(file));
}
}
// If there are missing files then format the error message and return it.
if (missingFiles.Length > 0)
error = StringResources.GetString("ValidateMissingFilesError", Title, missingFiles);
return 0 == error.Length;
}
/// <summary>
/// Override of ToString() to return the name of the HIF.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return Name;
}
#endregion
#region private static fields/properties/methods
// Create a CultureInfo for US English to do proper number conversion.
private static CultureInfo cultureUSA = new CultureInfo(0x0409);
#endregion
#region private fields/properties/methods
/// <summary>
/// Gets the string collection for the specified (type, property) from the
/// hash table.
/// </summary>
/// <param name="componentType">The component type</param>
/// <param name="componentProperty">The property, or string.Empty if
/// the type does not support properties</param>
/// <returns>The string collection for the (type, property).</returns>
private StringCollection GetStrings(string componentType, string componentProperty)
{
// Get the value for the given component if we can't find it
// then throw an exception.
object o = components[componentType];
if (null == o) ThrowException("Unknown type {0}", componentType);
if (string.Empty == componentProperty)
{
// No sub-type, the value for this component type should be
// a string collection.
if (!(o is StringCollection)) ThrowException("Type {0} requires a property", componentType);
return (StringCollection) o;
}
else
{
// Get the hashtable for the type, if there is no hashtable
// then throw an exception.
HakPropertyDictionary hash = o as HakPropertyDictionary;
if (null == hash) ThrowException("Type {0} cannot have properties", componentType);
// Get the string collection for the property, if there is no
// collection for the property yet then create one.
StringCollection coll = hash[componentProperty];
if (null == coll)
{
hash.Add(componentProperty);
coll = hash[componentProperty];
}
return coll;
}
}
/// <summary>
/// Initializes the components hash table.
/// </summary>
private void InitializeComponents()
{
// Create the hashtable then walk the key/value arrays, creating
// the proper value objects for the keys.
components = new Hashtable();
for (int i = 0; i < Keys.Length; i++)
{
System.Reflection.ConstructorInfo ci = Types[i].GetConstructor(new Type[0]);
object val = ci.Invoke(new object[0]);
components.Add(Keys[i], val);
}
}
/// <summary>
/// Throws an exception with the specified message.
/// </summary>
/// <param name="format">Format string</param>
/// <param name="args">Format arguments</param>
private void ThrowException(string format, params object[] args)
{
System.Text.StringBuilder b = new System.Text.StringBuilder();
b.AppendFormat(format, args);
throw new Exception(b.ToString());
}
// Define constants for the various component types.
private const string ErfKey = "erf";
private const string ModuleKey = "module";
private const string VersionKey = "version";
private const string RequiredNWNVersionKey = "minnwnversion";
private const string TitleKey = "title";
// Arrays that define the supported component types. Keys is an array of
// key values which match what is on the left of the ':' in the hif file.
// Types is the type of object that is placed in the hash table for each
// key.
private string[] Keys = new string[]
{
VersionKey,
RequiredNWNVersionKey,
ErfKey,
TitleKey,
ModuleKey
};
private Type[] Types = new Type[]
{
typeof(StringCollection),
typeof(StringCollection),
typeof(StringCollection),
typeof(StringCollection),
typeof(HakPropertyDictionary)
};
private Hashtable components;
private FileInfo fileInfo;
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="MJS.HakInstaller.HakInstaller.exe"
type="win32"
/>
<description>Your comment here</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1,35 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HakInstallerForm", "HakInstallerForm.csproj", "{09E68C4C-1EAD-406F-9C8C-27B3D52F5BE9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HakInstallerConsole", "HakInstallerConsole.csproj", "{C2B4588A-3CE9-4F86-BF3C-1D371C20D7A9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{09E68C4C-1EAD-406F-9C8C-27B3D52F5BE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{09E68C4C-1EAD-406F-9C8C-27B3D52F5BE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{09E68C4C-1EAD-406F-9C8C-27B3D52F5BE9}.Debug|x86.ActiveCfg = Debug|x86
{09E68C4C-1EAD-406F-9C8C-27B3D52F5BE9}.Debug|x86.Build.0 = Debug|x86
{09E68C4C-1EAD-406F-9C8C-27B3D52F5BE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{09E68C4C-1EAD-406F-9C8C-27B3D52F5BE9}.Release|Any CPU.Build.0 = Release|Any CPU
{09E68C4C-1EAD-406F-9C8C-27B3D52F5BE9}.Release|x86.ActiveCfg = Release|x86
{09E68C4C-1EAD-406F-9C8C-27B3D52F5BE9}.Release|x86.Build.0 = Release|x86
{C2B4588A-3CE9-4F86-BF3C-1D371C20D7A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2B4588A-3CE9-4F86-BF3C-1D371C20D7A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2B4588A-3CE9-4F86-BF3C-1D371C20D7A9}.Debug|x86.ActiveCfg = Debug|x86
{C2B4588A-3CE9-4F86-BF3C-1D371C20D7A9}.Debug|x86.Build.0 = Debug|x86
{C2B4588A-3CE9-4F86-BF3C-1D371C20D7A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2B4588A-3CE9-4F86-BF3C-1D371C20D7A9}.Release|Any CPU.Build.0 = Release|Any CPU
{C2B4588A-3CE9-4F86-BF3C-1D371C20D7A9}.Release|x86.ActiveCfg = Release|x86
{C2B4588A-3CE9-4F86-BF3C-1D371C20D7A9}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Binary file not shown.

View File

@@ -0,0 +1,159 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<BaseAddress>285212672</BaseAddress>
<Optimize>true</Optimize>
<DebugType>
</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup>
<ProjectType>Local</ProjectType>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{C2B4588A-3CE9-4F86-BF3C-1D371C20D7A9}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ApplicationIcon>HakInstaller.ico</ApplicationIcon>
<AssemblyKeyContainerName>
</AssemblyKeyContainerName>
<AssemblyName>HakInstallerCmdLine</AssemblyName>
<AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>
<DefaultClientScript>JScript</DefaultClientScript>
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
<DefaultTargetSchema>IE50</DefaultTargetSchema>
<DelaySign>false</DelaySign>
<OutputType>Exe</OutputType>
<RootNamespace>HakInstaller</RootNamespace>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<StartupObject>
</StartupObject>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>bin\Debug\</OutputPath>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>true</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>false</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>full</DebugType>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>Ship\</OutputPath>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>false</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>true</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>none</DebugType>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<BaseAddress>285212672</BaseAddress>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System">
<Name>System</Name>
</Reference>
<Reference Include="System.Data">
<Name>System.Data</Name>
</Reference>
<Reference Include="System.Drawing">
<Name>System.Drawing</Name>
</Reference>
<Reference Include="System.Windows.Forms">
<Name>System.Windows.Forms</Name>
</Reference>
<Reference Include="System.Xml">
<Name>System.XML</Name>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="2da.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ConflictResolver.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Erf.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Gff.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="HakInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="HakInstaller.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Key.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="MainConsole.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ModuleInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="NWNInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Tlk.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Utilities.cs">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,64 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<LastOpenVersion>7.10.3077</LastOpenVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ReferencePath>
</ReferencePath>
<CopyProjectDestinationFolder>
</CopyProjectDestinationFolder>
<CopyProjectUncPath>
</CopyProjectUncPath>
<CopyProjectOption>0</CopyProjectOption>
<ProjectView>ProjectFiles</ProjectView>
<ProjectTrust>0</ProjectTrust>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<EnableASPDebugging>false</EnableASPDebugging>
<EnableASPXDebugging>false</EnableASPXDebugging>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
<EnableSQLServerDebugging>false</EnableSQLServerDebugging>
<RemoteDebugEnabled>false</RemoteDebugEnabled>
<RemoteDebugMachine>
</RemoteDebugMachine>
<StartAction>Project</StartAction>
<StartArguments>foo.mod spellprcmerge.hif</StartArguments>
<StartPage>
</StartPage>
<StartProgram>
</StartProgram>
<StartURL>
</StartURL>
<StartWorkingDirectory>
</StartWorkingDirectory>
<StartWithIE>true</StartWithIE>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<EnableASPDebugging>false</EnableASPDebugging>
<EnableASPXDebugging>false</EnableASPXDebugging>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
<EnableSQLServerDebugging>false</EnableSQLServerDebugging>
<RemoteDebugEnabled>false</RemoteDebugEnabled>
<RemoteDebugMachine>
</RemoteDebugMachine>
<StartAction>Project</StartAction>
<StartArguments>
</StartArguments>
<StartPage>
</StartPage>
<StartProgram>
</StartProgram>
<StartURL>
</StartURL>
<StartWorkingDirectory>
</StartWorkingDirectory>
<StartWithIE>true</StartWithIE>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<StartArguments>foo.mod spellprcmerge.hif</StartArguments>
<StartWithIE>true</StartWithIE>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<StartWithIE>true</StartWithIE>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,237 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<BaseAddress>285212672</BaseAddress>
<Optimize>true</Optimize>
<DebugType>
</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup>
<ProjectType>Local</ProjectType>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{09E68C4C-1EAD-406F-9C8C-27B3D52F5BE9}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ApplicationIcon>HakInstaller.ico</ApplicationIcon>
<AssemblyKeyContainerName>
</AssemblyKeyContainerName>
<AssemblyName>HakInstaller</AssemblyName>
<AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>
<DefaultClientScript>JScript</DefaultClientScript>
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
<DefaultTargetSchema>IE50</DefaultTargetSchema>
<DelaySign>false</DelaySign>
<OutputType>WinExe</OutputType>
<RootNamespace>HakInstaller</RootNamespace>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<StartupObject>
</StartupObject>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>bin\Debug\</OutputPath>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>true</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>false</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>full</DebugType>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>Ship\</OutputPath>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>false</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>true</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>none</DebugType>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<BaseAddress>285212672</BaseAddress>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System">
<Name>System</Name>
</Reference>
<Reference Include="System.Data">
<Name>System.Data</Name>
</Reference>
<Reference Include="System.Drawing">
<Name>System.Drawing</Name>
</Reference>
<Reference Include="System.Windows.Forms">
<Name>System.Windows.Forms</Name>
</Reference>
<Reference Include="System.Xml">
<Name>System.XML</Name>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="2da.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="AboutForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ConflictResolver.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Erf.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Gff.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="GffForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="HakInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="HakInstaller.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="HifConflictsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="InstallForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="InstallFormBase.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="InstallProgressForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Key.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="MainForm.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ModuleInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="NWNInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="OverwriteWarningsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ReplacingFilesForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="SingleHIFInstallForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="SystemMenu.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Tlk.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Utilities.cs">
<SubType>Code</SubType>
</Compile>
<EmbeddedResource Include="AboutForm.resx">
<DependentUpon>AboutForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="GffForm.resx">
<DependentUpon>GffForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="HakInstaller.ico" />
<EmbeddedResource Include="HifConflictsForm.resx">
<DependentUpon>HifConflictsForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="InstallForm.resx">
<DependentUpon>InstallForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="InstallFormBase.resx">
<DependentUpon>InstallFormBase.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="InstallProgressForm.resx">
<DependentUpon>InstallProgressForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="OverwriteWarningsForm.resx">
<DependentUpon>OverwriteWarningsForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="ReplacingFilesForm.resx">
<DependentUpon>ReplacingFilesForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="SingleHIFInstallForm.resx">
<DependentUpon>SingleHIFInstallForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="strings.resx">
<SubType>Designer</SubType>
</EmbeddedResource>
<Content Include="HakInstaller.exe.manifest" />
<Content Include="strings.xsd" />
<None Include="app.config" />
<None Include="spellPak.hif" />
<None Include="spellPRCMerge.hif" />
<None Include="strings.xsx">
<DependentUpon>strings.xsd</DependentUpon>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,76 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<LastOpenVersion>7.10.3077</LastOpenVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ReferencePath>
</ReferencePath>
<CopyProjectDestinationFolder>
</CopyProjectDestinationFolder>
<CopyProjectUncPath>
</CopyProjectUncPath>
<CopyProjectOption>0</CopyProjectOption>
<ProjectView>ProjectFiles</ProjectView>
<ProjectTrust>0</ProjectTrust>
<PublishUrlHistory>publish\</PublishUrlHistory>
<InstallUrlHistory>
</InstallUrlHistory>
<SupportUrlHistory>
</SupportUrlHistory>
<UpdateUrlHistory>
</UpdateUrlHistory>
<BootstrapperUrlHistory>
</BootstrapperUrlHistory>
<ApplicationRevision>0</ApplicationRevision>
<FallbackCulture>en-US</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<EnableASPDebugging>false</EnableASPDebugging>
<EnableASPXDebugging>false</EnableASPXDebugging>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
<EnableSQLServerDebugging>false</EnableSQLServerDebugging>
<RemoteDebugEnabled>false</RemoteDebugEnabled>
<RemoteDebugMachine>
</RemoteDebugMachine>
<StartAction>Project</StartAction>
<StartArguments>-L1</StartArguments>
<StartPage>
</StartPage>
<StartProgram>
</StartProgram>
<StartURL>
</StartURL>
<StartWorkingDirectory>
</StartWorkingDirectory>
<StartWithIE>true</StartWithIE>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<EnableASPDebugging>false</EnableASPDebugging>
<EnableASPXDebugging>false</EnableASPXDebugging>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
<EnableSQLServerDebugging>false</EnableSQLServerDebugging>
<RemoteDebugEnabled>false</RemoteDebugEnabled>
<RemoteDebugMachine>
</RemoteDebugMachine>
<StartAction>Project</StartAction>
<StartArguments>"PRC Pack.hif"</StartArguments>
<StartPage>
</StartPage>
<StartProgram>
</StartProgram>
<StartURL>
</StartURL>
<StartWorkingDirectory>
</StartWorkingDirectory>
<StartWithIE>true</StartWithIE>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<StartArguments>-L1</StartArguments>
<StartWithIE>true</StartWithIE>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<StartArguments>"PRC Pack.hif"</StartArguments>
<StartWithIE>true</StartWithIE>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,207 @@
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using HakInstaller;
using HakInstaller.Utilities;
namespace HakInstaller
{
/// <summary>
/// This form displays is a comfirmation box asking the user if the
/// application should continue with replacing the listed files with
/// files from added hak(s).
/// </summary>
public class HifConflictsForm : System.Windows.Forms.Form
{
#region public properties/methods
/// <summary>
/// Class constructor
/// </summary>
/// <param name="conflicts">The list of file conflicts.</param>
public HifConflictsForm(HifConflictCollection conflicts)
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
pictureBox.Image = SystemIcons.Exclamation.ToBitmap();
// There appears to be a bug in the 1.0 version of the framework. On my
// 3.2ghz machine, if listBox.Items.Add(conflict) is placed in the
// foreach array it hangs, unless you slow it down somehow. Moving
// the add outside the loop and changing it to an AddRange() to add all
// of the conflicts in one shot makes it work correctly, thus the change
// to the code.
// Add all of the conflicts to the list box.
HifConflict[] conflictArray = new HifConflict[conflicts.Count];
for (int i = 0; i < conflicts.Count; i++)
conflictArray[i] = conflicts[i];
listBox.Items.AddRange(conflictArray);
}
#endregion
#region protected fields/properties/methods
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
#region functionality for Win32 PlaySound API
[Flags] private enum SoundFlags
{
Sync = 0x00000000, /* play synchronously (default) */
Async = 0x00000001, /* play asynchronously */
NoDefault = 0x00000002, /* silence (!default) if sound not found */
Memory = 0x00000004, /* pszSound points to a memory file */
Loop = 0x00000008, /* loop the sound until next sndPlaySound */
NoStop = 0x00000010, /* don't stop any currently playing sound */
NoWait = 0x00002000, /* don't wait if the driver is busy */
Alias = 0x00010000, /* name is a registry alias */
AliasId = 0x00110000, /* alias is a pre d ID */
Filename = 0x00020000, /* name is file name */
Resource = 0x00040004, /* name is resource name or atom */
Purge = 0x00000040, /* purge non-static events for task */
Application = 0x00000080 /* look for application specific association */
}
public static void PlaySoundEvent(string sound)
{
PlaySound(sound, 0,
(int) (SoundFlags.Async | SoundFlags.Alias | SoundFlags.NoWait));
}
[DllImport("winmm.dll", EntryPoint="PlaySound",CharSet=CharSet.Auto)]
private static extern int PlaySound(String pszSound, int hmod, int flags);
#endregion
#region Windows Form Designer generated code
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button buttonContinue;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.PictureBox pictureBox;
private System.Windows.Forms.ListBox listBox;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.buttonContinue = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.pictureBox = new System.Windows.Forms.PictureBox();
this.listBox = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// label1
//
this.label1.Location = new System.Drawing.Point(72, 16);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(240, 56);
this.label1.TabIndex = 0;
this.label1.Text = "Some modules already have some of the content you selected installed. Do you wis" +
"h to continue? The install may not work if you continue.";
//
// buttonContinue
//
this.buttonContinue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonContinue.DialogResult = System.Windows.Forms.DialogResult.OK;
this.buttonContinue.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.buttonContinue.Location = new System.Drawing.Point(16, 158);
this.buttonContinue.Name = "buttonContinue";
this.buttonContinue.Size = new System.Drawing.Size(80, 24);
this.buttonContinue.TabIndex = 2;
this.buttonContinue.Text = "C&ontinue";
//
// button2
//
this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.button2.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.button2.Location = new System.Drawing.Point(112, 158);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(80, 24);
this.button2.TabIndex = 3;
this.button2.Text = "&Cancel";
//
// pictureBox
//
this.pictureBox.Location = new System.Drawing.Point(24, 16);
this.pictureBox.Name = "pictureBox";
this.pictureBox.Size = new System.Drawing.Size(32, 32);
this.pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.pictureBox.TabIndex = 3;
this.pictureBox.TabStop = false;
//
// listBox
//
this.listBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.listBox.HorizontalScrollbar = true;
this.listBox.IntegralHeight = false;
this.listBox.Location = new System.Drawing.Point(16, 80);
this.listBox.Name = "listBox";
this.listBox.Size = new System.Drawing.Size(296, 70);
this.listBox.TabIndex = 1;
//
// HifConflictsForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(328, 198);
this.ControlBox = false;
this.Controls.Add(this.listBox);
this.Controls.Add(this.pictureBox);
this.Controls.Add(this.buttonContinue);
this.Controls.Add(this.label1);
this.Controls.Add(this.button2);
this.MinimumSize = new System.Drawing.Size(336, 232);
this.Name = "HifConflictsForm";
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Overwriting Existing Content";
this.Load += new System.EventHandler(this.ReplacingFilesForm_Load);
this.ResumeLayout(false);
}
#endregion
#region form event handlers
/// <summary>
/// Handler for the load event.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ReplacingFilesForm_Load(object sender, System.EventArgs e)
{
PlaySoundEvent("SystemExclamation");
}
#endregion
#region control event handlers
#endregion
}
}

View File

@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="label1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="label1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonContinue.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="buttonContinue.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonContinue.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="button2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="button2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="button2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="pictureBox.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="pictureBox.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="pictureBox.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="listBox.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="listBox.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="listBox.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>(Default)</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>80</value>
</data>
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Name">
<value>HifConflictsForm</value>
</data>
</root>

View File

@@ -0,0 +1,305 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using HakInstaller.Utilities;
using NWN;
namespace HakInstaller
{
/// <summary>
/// This is the main form of the HakInstaller application.
/// </summary>
public class InstallForm : InstallFormBase
{
#region public methods/properties.
/// <summary>
/// Class constructor
/// </summary>
public InstallForm()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
// Add the major/minor version number to the caption, full version
// number is available in the about box.
Version version = Assembly.GetExecutingAssembly().GetName().Version;
string versionText = string.Format("{0}.{1}", version.Major, version.Minor);
Text = string.Format(Text, versionText);
SetLabels(labelVersion, labelPath);
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
#region Windows Form Designer generated code
private System.Windows.Forms.Label labelVersion;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button buttonInstall;
private System.Windows.Forms.Button buttonCancel;
private System.Windows.Forms.CheckedListBox checkedHaks;
private System.Windows.Forms.CheckedListBox checkedModules;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label labelPath;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(InstallForm));
this.labelVersion = new System.Windows.Forms.Label();
this.checkedHaks = new System.Windows.Forms.CheckedListBox();
this.label1 = new System.Windows.Forms.Label();
this.buttonInstall = new System.Windows.Forms.Button();
this.buttonCancel = new System.Windows.Forms.Button();
this.checkedModules = new System.Windows.Forms.CheckedListBox();
this.label2 = new System.Windows.Forms.Label();
this.labelPath = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// labelVersion
//
this.labelVersion.Location = new System.Drawing.Point(24, 8);
this.labelVersion.Name = "labelVersion";
this.labelVersion.Size = new System.Drawing.Size(240, 16);
this.labelVersion.TabIndex = 0;
//
// checkedHaks
//
this.checkedHaks.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.checkedHaks.CheckOnClick = true;
this.checkedHaks.Location = new System.Drawing.Point(24, 96);
this.checkedHaks.Name = "checkedHaks";
this.checkedHaks.Size = new System.Drawing.Size(248, 169);
this.checkedHaks.Sorted = true;
this.checkedHaks.TabIndex = 3;
this.checkedHaks.ThreeDCheckBoxes = true;
this.checkedHaks.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.checkedHaks_ItemCheck);
//
// label1
//
this.label1.Location = new System.Drawing.Point(24, 72);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(248, 16);
this.label1.TabIndex = 2;
this.label1.Text = "Select the con&tent you would like to install:";
//
// buttonInstall
//
this.buttonInstall.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonInstall.Enabled = false;
this.buttonInstall.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.buttonInstall.Location = new System.Drawing.Point(24, 280);
this.buttonInstall.Name = "buttonInstall";
this.buttonInstall.Size = new System.Drawing.Size(72, 24);
this.buttonInstall.TabIndex = 6;
this.buttonInstall.Text = "&Install";
this.buttonInstall.Click += new System.EventHandler(this.buttonInstall_Click);
//
// buttonCancel
//
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.buttonCancel.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.buttonCancel.Location = new System.Drawing.Point(112, 280);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(72, 24);
this.buttonCancel.TabIndex = 7;
this.buttonCancel.Text = "&Close";
this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
//
// checkedModules
//
this.checkedModules.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.checkedModules.CheckOnClick = true;
this.checkedModules.Location = new System.Drawing.Point(288, 96);
this.checkedModules.Name = "checkedModules";
this.checkedModules.Size = new System.Drawing.Size(248, 169);
this.checkedModules.Sorted = true;
this.checkedModules.TabIndex = 5;
this.checkedModules.ThreeDCheckBoxes = true;
this.checkedModules.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.checkedModules_ItemCheck);
//
// label2
//
this.label2.Location = new System.Drawing.Point(288, 72);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(248, 16);
this.label2.TabIndex = 4;
this.label2.Text = "Select the &modules you want the haks installed in:";
//
// labelPath
//
this.labelPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.labelPath.Location = new System.Drawing.Point(24, 32);
this.labelPath.Name = "labelPath";
this.labelPath.Size = new System.Drawing.Size(504, 16);
this.labelPath.TabIndex = 1;
//
// InstallForm
//
this.AcceptButton = this.buttonInstall;
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.CancelButton = this.buttonCancel;
this.ClientSize = new System.Drawing.Size(560, 310);
this.Controls.Add(this.labelPath);
this.Controls.Add(this.label2);
this.Controls.Add(this.checkedModules);
this.Controls.Add(this.buttonInstall);
this.Controls.Add(this.label1);
this.Controls.Add(this.checkedHaks);
this.Controls.Add(this.labelVersion);
this.Controls.Add(this.buttonCancel);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MinimumSize = new System.Drawing.Size(568, 328);
this.Name = "InstallForm";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "NWN Content Installer {0}";
this.Load += new System.EventHandler(this.InstallForm_Load);
this.ResumeLayout(false);
}
#endregion
#region form event handlers
/// <summary>
/// The form's load event handler. Fills in the contents of the form and sets
/// it up.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void InstallForm_Load(object sender, System.EventArgs e)
{
// Fill in the check list boxes.
LoadHakInfoList(checkedHaks);
LoadModuleList(checkedModules);
}
#endregion
#region control event handlers
/// <summary>
/// Event handler for the ItemCheck event on the modules check list box.
/// It enables/disables the install button depending on whether at least
/// one module and hak have been selected.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void checkedModules_ItemCheck(object sender, System.Windows.Forms.ItemCheckEventArgs e)
{
// The install button should be enabled if at least one module and hak
// has been selectted. Note that this event is fired BEFORE the checked
// state of the item changes so we have to check the event args for
// it's new state.
int adjustment = CheckState.Checked == e.NewValue ? 1 : -1;
bool fModuleChecked = checkedModules.CheckedItems.Count + adjustment > 0;
bool fHakChecked = checkedHaks.CheckedItems.Count > 0;
buttonInstall.Enabled = fModuleChecked && fHakChecked;
}
/// <summary>
/// Event handler for the ItemCheck event on the haks check list box.
/// It enables/disables the install button depending on whether at least
/// one module and hak have been selected.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void checkedHaks_ItemCheck(object sender, System.Windows.Forms.ItemCheckEventArgs e)
{
// We only support checking 1 hak, so uncheck the previously checked hak if we
// are checking a hak.
if (CheckState.Checked == e.NewValue && checkedHaks.CheckedIndices.Count > 0)
checkedHaks.SetItemChecked(checkedHaks.CheckedIndices[0], false);
// The install button should be enabled if at least one module and hak
// has been selectted. Note that this event is fired BEFORE the checked
// state of the item changes so we have to check the event args for
// it's new state.
int adjustment = CheckState.Checked == e.NewValue ? 1 : -1;
bool fModuleChecked = checkedModules.CheckedItems.Count > 0;
bool fHakChecked = checkedHaks.CheckedItems.Count + adjustment > 0;
buttonInstall.Enabled = fModuleChecked && fHakChecked;
}
/// <summary>
/// Handler for the install button click event. It installs the selected
/// haks in the selected modules.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonInstall_Click(object sender, System.EventArgs e)
{
// Build an array of the checked hif files.
HakInfo[] hifs = new HakInfo[checkedHaks.CheckedItems.Count];
for (int i = 0; i < checkedHaks.CheckedIndices.Count; i++)
hifs[i] = (HakInfo) checkedHaks.CheckedItems[i];
// Count the total number of .mod/.nwm files selected.
int numModules = 0;
foreach (Module module in checkedModules.CheckedItems)
numModules += module.Modules.Length;
// Create the modules list and fill it in.
string[] modules = new string[numModules];
numModules = 0;
foreach (Module module in checkedModules.CheckedItems)
{
module.Modules.CopyTo(modules, numModules);
numModules += module.Modules.Length;
}
PerformInstall(hifs, modules);
// Clear the checked state of all modules.
CheckedListBox.CheckedIndexCollection checkedIndeces =
checkedModules.CheckedIndices;
foreach (int index in checkedIndeces)
checkedModules.SetItemChecked(index, false);
}
/// <summary>
/// Cancel button click event, it closes the application.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonCancel_Click(object sender, System.EventArgs e)
{
Application.Exit();
}
#endregion
}
}

View File

@@ -0,0 +1,267 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="labelVersion.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="labelVersion.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="labelVersion.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="checkedHaks.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="checkedHaks.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="checkedHaks.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="label1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonInstall.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="buttonInstall.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonInstall.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonCancel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="buttonCancel.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonCancel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="checkedModules.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="checkedModules.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="checkedModules.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="label2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="labelPath.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="labelPath.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="labelPath.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>(Default)</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
<data name="$this.Name">
<value>InstallForm</value>
</data>
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>80</value>
</data>
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAIAICAAAAAAAACoCAAAJgAAABAQAAAAAAAAaAUAAM4IAAAoAAAAIAAAAEAAAAABAAgAAAAAAAAE
AAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAMDAwADA3MAA8MqmAAQE
BAAICAgADAwMABEREQAWFhYAHBwcACIiIgApKSkAVVVVAE1NTQBCQkIAOTk5AIB8/wBQUP8AkwDWAP/s
zADG1u8A1ufnAJCprQAAADMAAABmAAAAmQAAAMwAADMAAAAzMwAAM2YAADOZAAAzzAAAM/8AAGYAAABm
MwAAZmYAAGaZAABmzAAAZv8AAJkAAACZMwAAmWYAAJmZAACZzAAAmf8AAMwAAADMMwAAzGYAAMyZAADM
zAAAzP8AAP9mAAD/mQAA/8wAMwAAADMAMwAzAGYAMwCZADMAzAAzAP8AMzMAADMzMwAzM2YAMzOZADMz
zAAzM/8AM2YAADNmMwAzZmYAM2aZADNmzAAzZv8AM5kAADOZMwAzmWYAM5mZADOZzAAzmf8AM8wAADPM
MwAzzGYAM8yZADPMzAAzzP8AM/8zADP/ZgAz/5kAM//MADP//wBmAAAAZgAzAGYAZgBmAJkAZgDMAGYA
/wBmMwAAZjMzAGYzZgBmM5kAZjPMAGYz/wBmZgAAZmYzAGZmZgBmZpkAZmbMAGaZAABmmTMAZplmAGaZ
mQBmmcwAZpn/AGbMAABmzDMAZsyZAGbMzABmzP8AZv8AAGb/MwBm/5kAZv/MAMwA/wD/AMwAmZkAAJkz
mQCZAJkAmQDMAJkAAACZMzMAmQBmAJkzzACZAP8AmWYAAJlmMwCZM2YAmWaZAJlmzACZM/8AmZkzAJmZ
ZgCZmZkAmZnMAJmZ/wCZzAAAmcwzAGbMZgCZzJkAmczMAJnM/wCZ/wAAmf8zAJnMZgCZ/5kAmf/MAJn/
/wDMAAAAmQAzAMwAZgDMAJkAzADMAJkzAADMMzMAzDNmAMwzmQDMM8wAzDP/AMxmAADMZjMAmWZmAMxm
mQDMZswAmWb/AMyZAADMmTMAzJlmAMyZmQDMmcwAzJn/AMzMAADMzDMAzMxmAMzMmQDMzMwAzMz/AMz/
AADM/zMAmf9mAMz/mQDM/8wAzP//AMwAMwD/AGYA/wCZAMwzAAD/MzMA/zNmAP8zmQD/M8wA/zP/AP9m
AAD/ZjMAzGZmAP9mmQD/ZswAzGb/AP+ZAAD/mTMA/5lmAP+ZmQD/mcwA/5n/AP/MAAD/zDMA/8xmAP/M
mQD/zMwA/8z/AP//MwDM/2YA//+ZAP//zABmZv8AZv9mAGb//wD/ZmYA/2b/AP//ZgAhAKUAX19fAHd3
dwCGhoYAlpaWAMvLywCysrIA19fXAN3d3QDj4+MA6urqAPHx8QD4+PgA8Pv/AKSgoACAgIAAAAD/AAD/
AAAA//8A/wAAAP8A/wD//wAA////AAAAAADdvLUHtfcH97WYtfe197v3u7W1u/e7B93dAAAAAADdu93C
3eLi4uLd4t3d4t3i3eLcwuLi3eLdvLvdAAAAvLu84uLi3eLd3Ny73Lvc3bvcu93d3cLi4uLi3bu8AAC7
u9zC3eLivLu7tbS7tdy73LW7tdy73d3ivOLdu7UAtbrc4uLi3bu1tbW7tbW7u9a8tbW73LXcvN3i3eG7
uge0u7vd4ty73eL///+83LXdwuLi3bu1u7vcu93cwty1tLS73OLivP//4uL/3Ny73eLd3dzC3eK71rvc
vNzdu7q0rrrc4t3//7vc3Lvd4uK8/93iu9zc4t3Cu7W73Lu71ZGR3Lvi///d3N273eK83eLd////3dy8
3N3d4t21u7W6kbS03OL//9273OLi3dzi/////////93C3Lvcu+K1u7TPkbTc////3dzi3dy7/////927
3P//////4rzc3bS1upGu27vd///ivNy73eLi/+Ldu9273OL////////dtbrVrrS0u9z////du9283Lzd
4v/d3Ny73N3d////4rzcurS0rrTbu93////i3eLd3P///9y73LXc3Lvc4rW71bvVtJGR1bXbtdzd////
/+K1////u92727W73dzdtbrWurvVrs+0uta63Lvd/////9z////d3Na71tvcu9y0tdy11bSRkbTVu9a6
1rvctdy7u93//7vcu7vdu7vdtbW61rS61ZHPtLrVu9a73eL//93/4v//3Lzc3dy73N261bW63LS0rpG0
1bW61tu84v////////+73d3ivN3cvLS1uta0tbS0rtW0uta6td3i/////////7vcwt7i3bvctbS03LTV
tK6utLS03LTcvN3//////93c/////+LdvNy1tNy1urS0kbO0tNW61rrd4v///9284v//////////3LS1
utW0tNWurrS0tLS0tN3i//+73P///////////7S127Xbtbq0s66us7S0tLS03eLdu////////////7u0
u9W1urXVtLS0rq6zz7S0tLS7td3//////////920tNW0tNu01bS0tLOui7SztLO0tOL///////////+0
tLS0tLq0tLS0tLSzz4uurbOttLS03f/////////ctLS0tLS01bS0tLS0rbOtka6zs7S0tLS14v/////d
u7S1tNy0tbS1tLS0tLS0rYvP1Yu0tbvcu9y83LzcvNy73bvcB9y73bvcB9y7u9y0i7UA1a7c3d3C3bzi
3cLdwt3ivOLdwt3C3eK84t3dtK7PAAAA1a67u93d4t3d3d3i3d3d4t3d3eLd3eLdtZHPzwAAAAAA1a6u
i4yui66uroaurq6Grq6uhq6uhq7Pz7UAAADwAAAHwAAAA4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAHAAAAD4AAABygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAA
AAAAAAAAAAEAAAABAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAwMDAAMDcwADwyqYABAQEAAgI
CAAMDAwAERERABYWFgAcHBwAIiIiACkpKQBVVVUATU1NAEJCQgA5OTkAgHz/AFBQ/wCTANYA/+zMAMbW
7wDW5+cAkKmtAAAAMwAAAGYAAACZAAAAzAAAMwAAADMzAAAzZgAAM5kAADPMAAAz/wAAZgAAAGYzAABm
ZgAAZpkAAGbMAABm/wAAmQAAAJkzAACZZgAAmZkAAJnMAACZ/wAAzAAAAMwzAADMZgAAzJkAAMzMAADM
/wAA/2YAAP+ZAAD/zAAzAAAAMwAzADMAZgAzAJkAMwDMADMA/wAzMwAAMzMzADMzZgAzM5kAMzPMADMz
/wAzZgAAM2YzADNmZgAzZpkAM2bMADNm/wAzmQAAM5kzADOZZgAzmZkAM5nMADOZ/wAzzAAAM8wzADPM
ZgAzzJkAM8zMADPM/wAz/zMAM/9mADP/mQAz/8wAM///AGYAAABmADMAZgBmAGYAmQBmAMwAZgD/AGYz
AABmMzMAZjNmAGYzmQBmM8wAZjP/AGZmAABmZjMAZmZmAGZmmQBmZswAZpkAAGaZMwBmmWYAZpmZAGaZ
zABmmf8AZswAAGbMMwBmzJkAZszMAGbM/wBm/wAAZv8zAGb/mQBm/8wAzAD/AP8AzACZmQAAmTOZAJkA
mQCZAMwAmQAAAJkzMwCZAGYAmTPMAJkA/wCZZgAAmWYzAJkzZgCZZpkAmWbMAJkz/wCZmTMAmZlmAJmZ
mQCZmcwAmZn/AJnMAACZzDMAZsxmAJnMmQCZzMwAmcz/AJn/AACZ/zMAmcxmAJn/mQCZ/8wAmf//AMwA
AACZADMAzABmAMwAmQDMAMwAmTMAAMwzMwDMM2YAzDOZAMwzzADMM/8AzGYAAMxmMwCZZmYAzGaZAMxm
zACZZv8AzJkAAMyZMwDMmWYAzJmZAMyZzADMmf8AzMwAAMzMMwDMzGYAzMyZAMzMzADMzP8AzP8AAMz/
MwCZ/2YAzP+ZAMz/zADM//8AzAAzAP8AZgD/AJkAzDMAAP8zMwD/M2YA/zOZAP8zzAD/M/8A/2YAAP9m
MwDMZmYA/2aZAP9mzADMZv8A/5kAAP+ZMwD/mWYA/5mZAP+ZzAD/mf8A/8wAAP/MMwD/zGYA/8yZAP/M
zAD/zP8A//8zAMz/ZgD//5kA///MAGZm/wBm/2YAZv//AP9mZgD/Zv8A//9mACEApQBfX18Ad3d3AIaG
hgCWlpYAy8vLALKysgDX19cA3d3dAOPj4wDq6uoA8fHxAPj4+ADw+/8ApKCgAICAgAAAAP8AAP8AAAD/
/wD/AAAA/wD/AP//AAD///8AAPfs9+z37Pfs9+z37PfsAOyFX4Vf7OyFX7KBsrqyuuxfhV8H7OxfhV+B
soGyurKFhV//7IVfhV+FX2uygbK6X1/s/1+FX+yFX+zsa7KBsl+F7P8HXwfsX+zsX+xrsoFfX4UH/wcH
7IoH7F+F7GuyX4Wmhez//wdfB+yFX1/shV9fiqaKX4pfigfsX4WF7KaFhaaKpuwHBwf/7F+FX+yKX1+K
pors////BwdfhV/spoWFpoqm7P+8Bwf//wcH7IVfX4qmiuwHB7z///8HpoqmX4WmiqbsvP/////spoqm
iqbss7Sz/////we0s7SztLPsAOz37Pfs9+z37Pfs9+z3AIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAAA=
</value>
</data>
</root>

View File

@@ -0,0 +1,351 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Globalization;
using System.Threading;
using System.Windows.Forms;
using HakInstaller.Utilities;
using NWN;
namespace HakInstaller
{
/// <summary>
/// Summary description for InstallFormBase.
/// </summary>
public class InstallFormBase: Form
{
#region public properties/methods
/// <summary>
/// Default constructur
/// </summary>
public InstallFormBase()
{
// Wire up event handlers
Load += new EventHandler(InstallFormBase_Load);
}
#endregion
#region protected fields/properties/methods
/// <summary>
/// Sets the proper values for the string labels.
/// </summary>
/// <param name="labelVersion">The version string</param>
/// <param name="labelPath">The path string</param>
protected void SetLabels(Label labelVersion, Label labelPath)
{
// Load strings for XP1 and XP2 installed if they are otherwise use
// nothing.
string xp1 = NWNInfo.IsXP1Installed ?
StringResources.GetString("VersionFormatXP1") : string.Empty;
string xp2 = NWNInfo.IsXP1Installed ?
StringResources.GetString("VersionFormatXP2") : string.Empty;
labelVersion.Text = StringResources.GetString("VersionFormat", NWNInfo.Version, xp1, xp2);
labelPath.Text = StringResources.GetString("PathFormat", NWNInfo.InstallPath);
}
/// <summary>
/// Loads all of the hack info files into the hak check list box.
/// </summary>
protected void LoadHakInfoList(CheckedListBox checkedHaks)
{
// Get all of the modules in the module directory and add them to
// the list box.
string[] haks = Directory.GetFiles(NWNInfo.GetPathForFile("foo.hif"), "*.hif");
foreach (string hak in haks)
{
// Load the HIF now and perform validation before adding it to the
// list of HIFs.
HakInfo hif = new HakInfo(hak);
string error;
if (hif.Validate(out error))
checkedHaks.Items.Add(hif);
else
MessageBox.Show(error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
if (0 == checkedHaks.Items.Count)
{
MessageBox.Show(StringResources.GetString("NoHIFS"), "Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
Close();
Hide();
Application.Exit();
}
}
/// <summary>
/// Loads all of the modules in the NWN modules directory into the module
/// check list box.
/// </summary>
protected void LoadModuleList(CheckedListBox checkedModules)
{
// Turn sorting on so all of the user modules get added alphabetically
checkedModules.Sorted = true;
// Get all of the modules in the module directory and add them to
// the list box.
string[] modules = Directory.GetFiles(NWNInfo.ModulesPath, "*.mod");
foreach (string module in modules)
{
checkedModules.Items.Add(new Module(Path.GetFileName(module)));
}
// Turn off sorting so we can add the OC/XP1/XP2 at the top.
checkedModules.Sorted = false;
// Add the OC/XP1/XP2 modules if appropriate.
if (NWNInfo.IsXP2ModsInstalled)
checkedModules.Items.Insert(0, new Module(StringResources.GetString("XP2Name"), NWNInfo.XP2Modules));
if (NWNInfo.IsXP1ModsInstalled)
checkedModules.Items.Insert(0, new Module(StringResources.GetString("XP1Name"), NWNInfo.XP1Modules));
if (NWNInfo.IsOCModsInstalled)
checkedModules.Items.Insert(0, new Module(StringResources.GetString("OCName"), NWNInfo.OCModules));
}
/// <summary>
/// Checks the modules to see if any of the specified hifs are installed already,
/// if they are it prompts the user to see if we should continue.
/// </summary>
/// <param name="hifs">The list of hifs</param>
/// <param name="modules">The list of modules</param>
/// <returns>True if the user cancels the operation, false if they do not</returns>
protected bool CheckForHifConflicts(HakInfo[] hifs, string[] modules)
{
// Get the list of conflicts if there aren't any then just return false.
HifConflictCollection conflicts = HakInstaller.CheckInstalledHifs(hifs, modules);
if (null == conflicts) return false;
// There are conflicts, prompt the user for what to do.
HifConflictsForm form = new HifConflictsForm(conflicts);
return DialogResult.Cancel == form.ShowDialog(this);
}
private void InitializeComponent()
{
//
// InstallFormBase
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Name = "InstallFormBase";
this.Load += new System.EventHandler(this.InstallFormBase_Load);
}
/// <summary>
/// Handler for the install button click event. It installs the selected
/// haks in the selected modules.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void PerformInstall(HakInfo[] hifs, string[] modules)
{
try
{
// Before starting check for hif conflicts and ask the user if they really want to
// continue.
if (CheckForHifConflicts(hifs, modules)) return;
// Create a progress control,
InstallProgressForm progress = new InstallProgressForm();
ThreadPool.QueueUserWorkItem(new WaitCallback(DoHakInstall),
new InstallInfo(hifs, modules, progress));
progress.ShowDialog(this);
}
finally
{
}
}
#endregion
#region private nested classes
private class InstallInfo
{
#region public properties/methods
/// <summary>
/// Gets the list of haks to add.
/// </summary>
public HakInfo[] Hifs { get { return hifs; } }
/// <summary>
/// Gets the list of modules to add haks to.
/// </summary>
public string[] Modules { get { return modules; } }
/// <summary>
/// Gets the object used to display progress information.
/// </summary>
public InstallProgressForm Progress { get { return progress; } }
/// <summary>
/// Class constructor
/// </summary>
/// <param name="hifs">The list of haks to add</param>
/// <param name="modules">The list of modules to add haks to</param>
/// <param name="progress">The object used to show progress</param>
public InstallInfo(HakInfo[] hifs, string[]modules,
InstallProgressForm progress)
{
this.hifs = hifs;
this.modules = modules;
this.progress = progress;
}
#endregion
#region private fields/properties/methods
private InstallProgressForm progress;
private HakInfo[] hifs;
private string[] modules;
#endregion
}
#endregion
#region private fields/properties/methods
private SystemMenu systemMenu;
/// <summary>
/// This function performs the install of the haks into the modules. It is
/// intended to be called in a background thread using the thread pool, allowing
/// a progress dialog to be displayed to the user while the work is being done.
/// </summary>
/// <param name="o">InstallInfo object containing the install data.</param>
protected void DoHakInstall(object o)
{
// Force the thread to use the invariant culture to make the install
// code work on foreign language versions of windows.
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
// Do the hak install and when we're done close the progress form.
InstallInfo info = (InstallInfo) o;
try
{
// The OC/XP1/XP2 files can be marked as read only, so we have to undo that
// for all modules in the list.
foreach (string module in info.Modules)
{
string file = NWNInfo.GetFullFilePath(module);
FileAttributes attrs = File.GetAttributes(file);
attrs &= ~FileAttributes.ReadOnly;
File.SetAttributes(file, attrs);
}
HakInstaller.InstallHaks(info.Hifs, info.Modules, info.Progress);
}
catch(Exception e)
{
MessageBox.Show(info.Progress, e.Message, "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
info.Progress.Close();
// Reset any .nwm files back to read only to leave them as we found them,
// in case the engine wants them marked read only.
foreach (string module in info.Modules)
{
if (0 == string.Compare(".nwm", Path.GetExtension(module), true, CultureInfo.InvariantCulture))
{
string file = NWNInfo.GetFullFilePath(module);
FileAttributes attrs = File.GetAttributes(file);
attrs |= FileAttributes.ReadOnly;
File.SetAttributes(file, attrs);
}
}
}
}
#endregion
#region menu handlers
/// <summary>
/// Event handler for the system menu About menu item.
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void OnAbout(object sender, EventArgs args)
{
AboutForm form = new AboutForm();
form.ShowDialog(this);
}
#endregion
#region form event handlers
/// <summary>
/// Event handler for the forms' load event, it wires up our system menu items. Doing
/// these in the constructor breaks CenterWindow.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void InstallFormBase_Load(object sender, System.EventArgs e)
{
systemMenu = new SystemMenu(this);
SystemMenuItem item = new SystemMenuItem("-", systemMenu);
systemMenu.Add(item);
item = new SystemMenuItem("&About", systemMenu);
item.Click += new EventHandler(OnAbout);
systemMenu.Add(item);
}
#endregion
}
/// <summary>
/// This object defines a 'module' that is displayed in the right checked list box in
/// the form. For most modules it refers to a single module, but for the bioware modules
/// it refers to a group of modules.
/// </summary>
public class Module
{
#region public properties/methods
/// <summary>
/// Gets the name of the module object, this is the text that should be
/// displayed to the user.
/// </summary>
public string Name { get { return name; } }
/// <summary>
/// Gets the list of modules that make up this module object.
/// </summary>
public string[] Modules { get { return modules; } }
/// <summary>
/// Constructor to create a module object for a single module on disk.
/// </summary>
/// <param name="module">The module</param>
public Module(string module)
{
name = Path.GetFileNameWithoutExtension(module);
modules = new string[] { module };
}
/// <summary>
/// Constructor to create a module object for a collection of modules
/// </summary>
/// <param name="name">The display name for the collection</param>
/// <param name="modules">The list of modules.</param>
public Module(string name, string[] modules)
{
this.name = name;
this.modules = modules;
}
/// <summary>
/// Override of ToString() to use the Name property.
/// </summary>
/// <returns></returns>
public override string ToString() { return Name; }
#endregion
#region private fields/properties/methods
string name;
private string[] modules;
#endregion
}
}

View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="$this.Name">
<value>InstallFormBase</value>
</data>
</root>

View File

@@ -0,0 +1,222 @@
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows.Forms;
namespace HakInstaller
{
/// <summary>
/// Summary description for InstallProgress.
/// </summary>
public class InstallProgressForm : System.Windows.Forms.Form,
IHakInstallProgress
{
#region public properties/methods
/// <summary>
/// Class constructor
/// </summary>
public InstallProgressForm()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
cancelled = false;
builder = new System.Text.StringBuilder();
}
#endregion
#region IHakInstallProgress implementation
/// <summary>
/// Gets whether the user cancelled the install.
/// </summary>
bool IHakInstallProgress.IsCancelled { get { return cancelled; } }
/// <summary>
/// Gets/sets the number of steps for the progress bar.
/// </summary>
int IHakInstallProgress.ProgressSteps
{
get { return progressBar.Maximum; }
set
{
progressBar.Minimum = 1;
progressBar.Maximum = value;
progressBar.Value = 1;
progressBar.Step = 1;
}
}
/// <summary>
/// Advances the progress bar 1 step.
/// </summary>
void IHakInstallProgress.Step()
{
progressBar.PerformStep();
}
/// <summary>
/// Sets the currently displayed progress message.
/// </summary>
/// <param name="format">Format string</param>
/// <param name="args">Message arguments</param>
void IHakInstallProgress.SetMessage(string format, params object[] args)
{
builder.Length = 0;
builder.AppendFormat(format, args);
labelMessage.Text = builder.ToString();
}
/// <summary>
/// This methods should ask the user for confirmation of replacing
/// the listed files in the module with files from sources in the
/// hif files, as this operation may break the module.
/// </summary>
/// <param name="conflicts">The list of file conflicts</param>
/// <returns>true if the files should be replaced, false if adding
/// the hak(s) to the module should be aborted</returns>
bool IHakInstallProgress.ShouldReplaceFiles(FileConflictCollection conflicts)
{
// Confirm the file replace operation with the user.
ReplacingFilesForm form = new ReplacingFilesForm(conflicts);
return DialogResult.OK == form.ShowDialog((Form) this);
}
/// <summary>
/// This method should ask the user for confirmation of overwriting
/// the listed files. If fatal is true then there is no confirmation,
/// it is just an informational message that the operation must be aborted.
/// </summary>
/// <param name="warnings">The list of warnings</param>
/// <param name="fatal">True if the warnings are fatal</param>
/// <param name="type">The type of overwrite being confirmed</param>
/// <returns>True if the operation should proceed</returns>
bool IHakInstallProgress.ShouldOverwrite(OverwriteWarningCollection warnings,
bool fatal, OverwriteWarningType type)
{
OverwriteWarningsForm form = new OverwriteWarningsForm(warnings, fatal, type);
return DialogResult.OK == form.ShowDialog((Form) this);
}
/// <summary>
/// Displays an error message to the user.
/// </summary>
/// <param name="error">The error message to display</param>
void IHakInstallProgress.DisplayErrorMessage(string error)
{
MessageBox.Show(this, error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
/// <summary>
/// Displays a message to the user.
/// </summary>
/// <param name="error">The message to display</param>
void IHakInstallProgress.DisplayMessage(string message)
{
MessageBox.Show(this, message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
#endregion
#region protected fields/properties/methods
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
#region Windows Form Designer generated code
private System.Windows.Forms.ProgressBar progressBar;
private System.Windows.Forms.Label labelMessage;
private System.Windows.Forms.Button buttonCancel;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.progressBar = new System.Windows.Forms.ProgressBar();
this.labelMessage = new System.Windows.Forms.Label();
this.buttonCancel = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// progressBar
//
this.progressBar.Location = new System.Drawing.Point(16, 56);
this.progressBar.Name = "progressBar";
this.progressBar.Size = new System.Drawing.Size(344, 16);
this.progressBar.TabIndex = 0;
//
// labelMessage
//
this.labelMessage.Location = new System.Drawing.Point(16, 16);
this.labelMessage.Name = "labelMessage";
this.labelMessage.Size = new System.Drawing.Size(344, 32);
this.labelMessage.TabIndex = 1;
this.labelMessage.Text = "label1";
//
// buttonCancel
//
this.buttonCancel.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.buttonCancel.Location = new System.Drawing.Point(16, 96);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(72, 24);
this.buttonCancel.TabIndex = 2;
this.buttonCancel.Text = "&Cancel";
this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
//
// InstallProgressForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(378, 136);
this.ControlBox = false;
this.Controls.Add(this.buttonCancel);
this.Controls.Add(this.labelMessage);
this.Controls.Add(this.progressBar);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "InstallProgressForm";
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Installing Haks";
this.ResumeLayout(false);
}
#endregion
#region private fields/properties/methods
private bool cancelled;
private System.Text.StringBuilder builder;
#endregion
#region event handlers
/// <summary>
/// Event handler for the cancel button's click event.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonCancel_Click(object sender, System.EventArgs e)
{
cancelled = true;
}
#endregion
}
}

View File

@@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="progressBar.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="progressBar.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="progressBar.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="labelMessage.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="labelMessage.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="labelMessage.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonCancel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="buttonCancel.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonCancel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>(Default)</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Name">
<value>InstallProgressForm</value>
</data>
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>80</value>
</data>
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
</root>

View File

@@ -0,0 +1,398 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using NWN.FileTypes.Tools;
namespace NWN.FileTypes.BIF
{
/// <summary>
/// The class encapsulates a NWN BIF file, allowing access to the files
/// within the BIF.
/// </summary>
internal class Bif
{
#region public properties/methods
/// <summary>
/// Class constructor. It caches the list of files in the BIF for quick
/// searching.
/// </summary>
/// <param name="name">The name of the BIF</param>
public Bif(string name)
{
// Delay loading the cache until needed.
this.name = name;
entries = null;
}
/// <summary>
/// Attempts to extract the specified file ID from the BIF, returning
/// the file's data in a Stream.
/// </summary>
/// <param name="id">The id of the file</param>
/// <returns>A stream for the file or null if the BIF does not contain
/// the file.</returns>
public Stream GetFile(uint id)
{
id = id & 0xfffff;
// If we haven't populated the cache then do so now.
if (null == entries) Cache();
// If the file isn't ours then return null.
BifEntry entry = entries[id] as BifEntry;
if (null == entry) return null;
// Read the raw data into a memory stream.
NWNLogger.Log(1, "Bif.GetFile({0}) found file in BIF {1}", id, name);
using (FileStream reader =
new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.Read))
{
// Read the file's data.
byte[] buffer = new byte[entry.Size];
reader.Seek(entry.Offset, SeekOrigin.Begin);
reader.Read(buffer, 0, buffer.Length);
// Create a memory stream for the data and return it.
MemoryStream s = new MemoryStream(buffer, false);
return s;
}
}
#endregion
#region private raw structures for reading bif file data
[StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
private struct RawHeader
{
#region members
public UInt32 FileType;
public UInt32 FilerVersion;
public UInt32 VariableResourceCount;
public UInt32 FixedResourceCount;
public UInt32 VariableTableOffset;
#endregion
}
[StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
private struct RawEntry
{
#region members
public UInt32 ID;
public UInt32 Offset;
public UInt32 FileSize;
public UInt32 ResourceType;
#endregion
}
#endregion
#region private nested classes
/// <summary>
/// Class that contains the data for a BIF file entry
/// </summary>
private class BifEntry
{
public uint Offset;
public uint Size;
}
#endregion
#region private fields/properties/methods
private string name;
private Hashtable entries;
/// <summary>
/// Caches the biff's file entries in our hashtable.
/// </summary>
private void Cache()
{
entries = new Hashtable();
using (FileStream reader =
new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.Read))
{
// Read the file header.
RawHeader header = (RawHeader)
RawSerializer.Deserialize(typeof(RawHeader), reader);
// Read all of the variable sized resources from the BIF, storing
// their size/offset entries in our hash table. Fixed resources
// are not implemented we don't have to worry about them.
reader.Seek(header.VariableTableOffset, SeekOrigin.Begin);
for (int i = 0; i < header.VariableResourceCount; i++)
{
// Read the raw entry data.
RawEntry rawEntry = (RawEntry)
RawSerializer.Deserialize(typeof(RawEntry), reader);
// Create an entry and add it to our hash table.
BifEntry entry = new BifEntry();
entry.Offset = rawEntry.Offset;
entry.Size = rawEntry.FileSize;
entries.Add((uint) (rawEntry.ID & 0xfffff), entry);
}
}
}
#endregion
}
/// <summary>
/// This class encapsulates a NWN KEY file, which contains information
/// about files stored in BIF files.
/// </summary>
internal class Key
{
/// <summary>
/// Class constructor
/// </summary>
/// <param name="name">The name of the key file to load</param>
public Key(string name)
{
keyFileName = name;
bifs = new ArrayList();
keys = new Hashtable();
// Glue the NWN install dir onto the file name and open it.
string fileName = Path.Combine(NWN.NWNInfo.InstallPath, name);
using (FileStream reader =
new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
// Read the file header.
RawHeader header = (RawHeader)
RawSerializer.Deserialize(typeof(RawHeader), reader);
// Read all of the BIF file entries from the key file.
reader.Seek(header.OffsetToFileTable, SeekOrigin.Begin);
RawFileEntry[] files = new RawFileEntry[header.BIFCount];
for (int i = 0; i < header.BIFCount; i++)
files[i] = (RawFileEntry)
RawSerializer.Deserialize(typeof(RawFileEntry), reader);
// Loop through the BIF file entries making a list of all of
// the BIFs this key file covers.
byte[] fileNameBuffer = new byte[2048];
for (int i = 0; i < header.BIFCount; i++)
{
// Read the raw name data and convert it to a string.
reader.Seek(files[i].FilenameOffset, SeekOrigin.Begin);
reader.Read(fileNameBuffer, 0, files[i].FilenameSize);
string s = RawSerializer.DeserializeString(fileNameBuffer, 0, files[i].FilenameSize);
// The path is relative to the install directory, so glue that on before adding
// the BIF to our string collection.
//if (0 != (1 & files[i].Drives))
s = Path.Combine(NWN.NWNInfo.InstallPath, s);
//else
// throw new NWNException("Uknown data in file entry block in key file {0}", name);
bifs.Add(new Bif(s));
}
// Read all of the key entries, i.e. what files are in the BIFs.
reader.Seek(header.OffsetToKeyTable, SeekOrigin.Begin);
for (int i = 0; i < header.KeyCount; i++)
{
// Read the raw data.
RawKeyEntry key = (RawKeyEntry)
RawSerializer.Deserialize(typeof(RawKeyEntry), reader);
// Build the file name from the ResRef and resource type. Then
// add the file name and ID to our hash table. If this booms then
// that is because of a resource type we don't know about, for
// now we ignore that.
ResType resType = (ResType) key.ResourceType;
try
{
string ext = resType.ToString().Substring(3, 3).ToLower();
string s = RawSerializer.DeserializeString(key.ResRef, 0, 16);
s = string.Format("{0}.{1}", s, ext);
keys.Add(s, key.ResID);
}
catch (Exception) {}
}
}
}
/// <summary>
/// Checks to see if the key contains the file, and if it does extracts
/// it from it's BIF and returns it's data in a Stream.
/// </summary>
/// <param name="file">The file to extract</param>
/// <returns>A Stream containing the file's data or null if the key
/// does not contain the file.</returns>
public Stream GetFile(string file)
{
if (!keys.Contains(file)) return null;
// The file is ours, check each of our BIFS for the file.
// The bottom 20 bits are the index in the bif and the top
// 12 bits are the bif index in our bif array.
uint id = (uint) keys[file];
uint index = id >> 20;
Bif bif = (Bif) bifs[(int) index];
return bif.GetFile(id & 0xfffff);
/*
* Not totally sure the above code is right so saving this
foreach (Bif bif in bifs)
{
// Try to load the file from the BIF, if successful return it.
Stream s = bif.GetFile(id);
if (null != s) return s;
}
// If we get here something really bad has happened.
throw new NWNException("Cannot extract file {0} from BIFs", file);
*/
}
#region private raw structures for reading key file data
[StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
private struct RawHeader
{
#region members
public UInt32 FileType;
public UInt32 FilerVersion;
public UInt32 BIFCount;
public UInt32 KeyCount;
public UInt32 OffsetToFileTable;
public UInt32 OffsetToKeyTable;
public UInt32 BuildYear;
public UInt32 BuildDay;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)] private Byte[] Reserved;
#endregion
}
[StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
private struct RawFileEntry
{
#region members
public UInt32 FileSize;
public UInt32 FilenameOffset;
public UInt16 FilenameSize;
public UInt16 Drives;
#endregion
}
[StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
private struct RawKeyEntry
{
#region members
[MarshalAs(UnmanagedType.ByValArray, SizeConst=16)] public byte[] ResRef;
public UInt16 ResourceType;
public UInt32 ResID;
#endregion
}
#endregion
#region private fields/properties/methods
private string keyFileName;
private ArrayList bifs;
private Hashtable keys;
#endregion
}
/// <summary>
/// This class implements a collection of all of the KEY files installed
/// on the user's system. It can be used to extract files from those
/// keys.
/// </summary>
public class KeyCollection
{
#region public static methods
/// <summary>
/// Looks in all of the key files for the given file, extracting it
/// from it's BIF and returning it's data in a stream.
/// </summary>
/// <param name="file">The file to extract</param>
/// <returns>A Stream containing the file data or null if the file
/// cannot be found</returns>
public static Stream GetFile(string file)
{
// Get a lower case copy of just the file name.
file = Path.GetFileName(file).ToLower();
// Loop through all of the keys looking for the file.
foreach (Key key in Singleton.keys)
{
// Ask the key for the file if we get it return it.
Stream s = key.GetFile(file);
if (null != s) return s;
}
// We couldn't find the file return null.
return null;
}
#endregion
#region private static methods
private static KeyCollection singleton;
/// <summary>
/// Gets the singleton instance
/// </summary>
private static KeyCollection Singleton
{
get
{
if (null == singleton) singleton = new KeyCollection();
return singleton;
}
}
#endregion
#region private fields/properties/methods
private ArrayList keys;
/// <summary>
/// Default constructor
/// </summary>
private KeyCollection()
{
keys = new ArrayList();
// Get a list of the key files for the NWN install and add the files
// to a StringCollection, forcing the names to lower case.
string[] filesArray = Directory.GetFiles(NWN.NWNInfo.InstallPath, "*.key");
StringCollection files = new StringCollection();
foreach (string file in filesArray)
files.Add(Path.GetFileName(file).ToLower());
// We need to do the files in a certain order, as we want to check the xp's in
// reverse order, then the main game last.
ProcessFile(files, "xp3.key");
ProcessFile(files, "xp2patch.key");
ProcessFile(files, "xp2.key");
ProcessFile(files, "xp1patch.key");
ProcessFile(files, "xp1.key");
// Now process whatever is left.
foreach (string file in files)
{
Key key = new Key(file);
keys.Add(key);
}
}
/// <summary>
/// Checks to see if the string collection contains the key file, and if it does
/// loads it and removes it from the collection.
/// </summary>
/// <param name="files">The list of files</param>
/// <param name="file">The key file to process</param>
private void ProcessFile(StringCollection files, string file)
{
if (files.Contains(file))
{
// Create the key, add it to our collection, and remove the
// file from the list as we've loaded it.
Key key = new Key(file);
keys.Add(key);
files.Remove(file);
}
}
#endregion
}
}

View File

@@ -0,0 +1,223 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using HakInstaller.Utilities;
using NWN;
namespace HakInstaller
{
/// <summary>
/// Class to contain the application's main method.
/// </summary>
public class MainContainer
{
#region private static fields/properties/methods
private static bool consoleMode = false;
private static bool installPathGiven = false;
private static StringCollection hifStrings = new StringCollection();
private static StringCollection moduleStrings = new StringCollection();
/// <summary>
/// Either displays the message in a message box or on the command line,
/// depending on whether the application is running in console mode or not.
/// </summary>
/// <param name="format">The format string</param>
/// <param name="args">The format arguments</param>
private static void ShowMessage(string format, params object[] args)
{
System.Text.StringBuilder b = new System.Text.StringBuilder();
b.AppendFormat(format, args);
if (consoleMode)
Console.WriteLine(b.ToString());
else
MessageBox.Show(b.ToString(), "Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
/// <summary>
/// Validates all of the files in the collection to make sure that they
/// exist.
/// </summary>
/// <param name="files">The list of files to validate</param>
/// <returns>True if all files exist</returns>
private static bool ValidateFiles(StringCollection files)
{
// Make sure all of the source files exist.
foreach (string file in files)
if (!File.Exists(Path.Combine(NWNInfo.GetPathForFile(file), file)))
{
ShowMessage("The file {0} does not exist", file);
return false;
}
return true;
}
/// <summary>
/// Runs the application in console mode, silently adding the haks to
/// the modules given on the command line.
/// </summary>
/// <returns>0 if successful, otherwise -1</returns>
private static int ConsoleMode()
{
// Validate the files, if we fail validation then exit now.
if (!ValidateFiles(hifStrings) || !ValidateFiles(moduleStrings))
return -1;
// Convert the string collections to arrays and install the haks
// in the modules.
string[] hifs = new string[hifStrings.Count];
hifStrings.CopyTo(hifs, 0);
string[] modules = new string[moduleStrings.Count];
moduleStrings.CopyTo(modules, 0);
try
{
HakInstaller.InstallHaks(hifs, modules, null);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return 0;
}
/// <summary>
/// Terminates the application.
/// </summary>
/// <param name="showHelp">True if help should be displayed.</param>
private static void Terminate(bool showHelp)
{
if (showHelp) Help();
throw new EntryPointNotFoundException();
}
/// <summary>
/// Displays help
/// </summary>
private static void Help()
{
Console.WriteLine("HakInstaller: install hak/erf/tlk files in modules");
Console.WriteLine("Usage: HakInstaller -n<path> file.hif/mod ...");
Console.WriteLine(" -n<path>:Specifies the NWN install path, if this is not given");
Console.WriteLine(" then it will be read from the registry.");
Console.WriteLine("");
Console.WriteLine("One or more .hif and .mod files may be specified on the command");
Console.WriteLine("line, if none are given a UI will be displayed allowing you to");
Console.WriteLine("choose the hif/mod files. Paths should not be given on the files");
Console.WriteLine("they will be searched for in the appropriate subdirectories of");
Console.WriteLine("the NWN install path (as either given on the command line or read");
Console.WriteLine("from the registry).");
}
/// <summary>
/// Processes command line arguments.
/// </summary>
/// <param name="args"></param>
private static void ProcessArguments(string[] args)
{
foreach (string arg in args)
{
// Process any command line switches.
if ('-' == arg[0] || '/' == arg[1])
{
switch (arg[1])
{
case 'n':
case 'N':
// The NWN install path was specified on the command line,
// save it to override whatever is in the registry.
installPathGiven = true;
NWNInfo.InstallPath = arg.Substring(2);
// Make sure that the directory exists.
if (!Directory.Exists(NWNInfo.InstallPath))
{
ShowMessage("The path '{0}' does not exist.", NWNInfo.InstallPath);
Terminate(false);
}
break;
default:
Help();
break;
}
}
else
{
// If we get a hif or module on the command line then we
// are in console mode.
consoleMode = true;
string extension = Path.GetExtension(arg);
if (0 == string.Compare(".hif", extension, true))
hifStrings.Add(arg);
else if (0 == string.Compare(".mod", extension, true))
moduleStrings.Add(arg);
else
{
Console.WriteLine("Unknown file {0}\n", arg);
Terminate(true);
}
}
}
// We must have at least one hif and one mod if we are in console mode.
if (consoleMode && (0 == hifStrings.Count || 0 == moduleStrings.Count))
{
Console.WriteLine("Must specify at least one .mod and one .hif file\n");
Terminate(true);
}
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static int Main(string[] args)
{
try
{
// Process command line arguments.
ProcessArguments(args);
// Make sure NWN is installed before doing anything. If the user
// gave an install path on the command line we could be installing on
// a remote machine, so do not check for an install on this machine.
if (!installPathGiven && !NWNInfo.IsInstalled)
{
ShowMessage("Neverwinter Nights is not installed");
return -1;
}
if (consoleMode)
return ConsoleMode();
else
{
// Requires .NET framework 1.1
//Application.EnableVisualStyles();
Application.Run(new InstallForm());
return 0;
}
}
catch (EntryPointNotFoundException)
{
// Dummy exception thrown to terminate the application by Help(),
// don't display anything just return -1.
return -1;
}
catch (Exception e)
{
ShowMessage(e.Message);
return -1;
}
}
#endregion
}
}

View File

@@ -0,0 +1,205 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using HakInstaller.Utilities;
using NWN;
namespace HakInstaller
{
/// <summary>
/// Class to contain the application's main method.
/// </summary>
public class MainConsole
{
#region private static fields/properties/methods
private static bool installPathGiven = false;
private static StringCollection hifStrings = new StringCollection();
private static StringCollection moduleStrings = new StringCollection();
/// <summary>
/// Validates all of the files in the collection to make sure that they
/// exist.
/// </summary>
/// <param name="files">The list of files to validate</param>
/// <returns>True if all files exist</returns>
private static bool ValidateFiles(StringCollection files)
{
// Make sure all of the source files exist.
foreach (string file in files)
if (!File.Exists(Path.Combine(NWNInfo.GetPathForFile(file), file)))
{
Console.WriteLine("The file {0} does not exist", file);
return false;
}
return true;
}
/// <summary>
/// Runs the application in console mode, silently adding the haks to
/// the modules given on the command line.
/// </summary>
/// <returns>0 if successful, otherwise -1</returns>
private static int ConsoleMode()
{
// Validate the files, if we fail validation then exit now.
if (!ValidateFiles(hifStrings) || !ValidateFiles(moduleStrings))
return -1;
// Convert the string collections to arrays and install the haks
// in the modules.
HakInfo[] hifs = new HakInfo[hifStrings.Count];
for (int i = 0; i < hifStrings.Count; i++)
hifs[i] = new HakInfo(hifStrings[i]);
string[] modules = new string[moduleStrings.Count];
moduleStrings.CopyTo(modules, 0);
try
{
HakInstaller.InstallHaks(hifs, modules, null);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return 0;
}
/// <summary>
/// Terminates the application.
/// </summary>
/// <param name="showHelp">True if help should be displayed</param>
private static void Terminate(bool showHelp) { Terminate(showHelp, string.Empty); }
/// <summary>
/// Terminates the application, displaying an error message
/// </summary>
/// <param name="showHelp">True if help should be displayed</param>
/// <param name="format">Format string for the error message to display</param>
/// <param name="args"></param>
private static void Terminate(bool showHelp, string format, params object[] args)
{
// Display the error message if one was given.
if (string.Empty != format) Console.WriteLine(format, args);
// If showHelp is true then display application help, leaving a blank
// line between the help and the error message.
if (showHelp)
{
if (string.Empty != format) Console.WriteLine("");
Help();
}
// Throw an EntryPointNotFoundException to terminate the application.
throw new EntryPointNotFoundException();
}
/// <summary>
/// Displays help
/// </summary>
private static void Help()
{
Console.WriteLine("HakInstaller: install hak/erf/tlk files in modules");
Console.WriteLine("Usage: HakInstaller -n<path> file.hif/mod ...");
Console.WriteLine(" -n<path>:Specifies the NWN install path, if this is not given");
Console.WriteLine(" then it will be read from the registry.");
Console.WriteLine("");
Console.WriteLine("One or more .hif and .mod files may be specified on the command");
Console.WriteLine("line, if none are given a UI will be displayed allowing you to");
Console.WriteLine("choose the hif/mod files. Paths should not be given on the files");
Console.WriteLine("they will be searched for in the appropriate subdirectories of");
Console.WriteLine("the NWN install path (as either given on the command line or read");
Console.WriteLine("from the registry).");
}
/// <summary>
/// Processes command line arguments.
/// </summary>
/// <param name="args"></param>
private static void ProcessArguments(string[] args)
{
foreach (string arg in args)
{
// Process any command line switches.
if ('-' == arg[0] || '/' == arg[1])
{
switch (arg[1])
{
case 'n':
case 'N':
// The NWN install path was specified on the command line,
// save it to override whatever is in the registry.
installPathGiven = true;
NWNInfo.InstallPath = arg.Substring(2);
// Make sure that the directory exists.
if (!Directory.Exists(NWNInfo.InstallPath))
Terminate(false, "The path '{0}' does not exist.", NWNInfo.InstallPath);
break;
default:
Terminate(true);
break;
}
}
else
{
// Add the file to the appropriate collection based on it's
// extension.
string extension = Path.GetExtension(arg);
if (0 == string.Compare(".hif", extension, true))
hifStrings.Add(arg);
else if (0 == string.Compare(".mod", extension, true))
moduleStrings.Add(arg);
else
Terminate(true, "Unknown file {0}", arg);
}
}
// We must have at least one hif and one mod if we are in console mode.
if (0 == hifStrings.Count || 0 == moduleStrings.Count)
Terminate(true, "Must specify at least one .mod and one .hif file\n");
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static int Main(string[] args)
{
try
{
// Process command line arguments.
ProcessArguments(args);
// Make sure NWN is installed before doing anything. If the user
// gave an install path on the command line we could be installing on
// a remote machine, so do not check for an install on this machine.
if (!installPathGiven && !NWNInfo.IsInstalled)
{
Console.WriteLine("Neverwinter Nights is not installed");
return -1;
}
return ConsoleMode();
}
catch (EntryPointNotFoundException)
{
// Dummy exception thrown to terminate the application by Help(),
// don't display anything just return -1.
return -1;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return -1;
}
}
#endregion
}
}

View File

@@ -0,0 +1,166 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Globalization;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using HakInstaller.Utilities;
using NWN;
using NWN.FileTypes.Tools;
namespace HakInstaller
{
/// <summary>
/// Class to contain the application's main method.
/// </summary>
public class MainForm
{
#region public static properties/methods
/// <summary>
/// Gets the single hif to use for the installer, or string.Empty if there is no single hif.
/// </summary>
public static string Hif { get { return hif; } }
#endregion
#region private static fields/properties/methods
private static bool installPathGiven = false;
private static string hif = string.Empty;
/// <summary>
/// Either displays the message in a message box or on the command line,
/// depending on whether the application is running in console mode or not.
/// </summary>
/// <param name="format">The format string</param>
/// <param name="args">The format arguments</param>
private static void ShowMessage(string format, params object[] args)
{
System.Text.StringBuilder b = new System.Text.StringBuilder();
b.AppendFormat(format, args);
MessageBox.Show(b.ToString(), "Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
/// <summary>
/// Terminates the application.
/// </summary>
private static void Terminate() { Terminate(string.Empty); }
/// <summary>
/// Terminates the application, displaying an error message
/// </summary>
/// <param name="format">Format string for the error message to display</param>
/// <param name="args"></param>
private static void Terminate(string format, params object[] args)
{
// Display the error message if one was given.
if (string.Empty != format) ShowMessage(format, args);
// Throw an EntryPointNotFoundException to terminate the application.
throw new EntryPointNotFoundException();
}
/// <summary>
/// Processes command line arguments.
/// </summary>
/// <param name="args"></param>
private static void ProcessArguments(string[] args)
{
foreach (string arg in args)
{
// Process any command line switches.
if ('-' == arg[0] || '/' == arg[1])
{
switch (arg[1])
{
case 'n':
case 'N':
// The NWN install path was specified on the command line,
// save it to override whatever is in the registry.
installPathGiven = true;
NWNInfo.InstallPath = arg.Substring(2);
// Make sure that the directory exists.
if (!Directory.Exists(NWNInfo.InstallPath))
Terminate("The path '{0}' does not exist.", NWNInfo.InstallPath);
// the registry values were irrelevant so replace with sensible defaults
NWNInfo.Version = "1.69";
NWNInfo.IsXP1Installed = true;
NWNInfo.IsXP2Installed = true;
break;
case 'l':
case 'L':
// Turn logging on and set the minimum severity if it was given.
NWNLogger.Logging = true;
if (arg.Length > 2) NWNLogger.MinimumLogLevel = Convert.ToInt32(arg.Substring(2));
break;
default:
Terminate("Unknown command line argument {0}", arg);
break;
}
}
else
{
// We can take one HIF on the command line, if this argument is a HIF and we
// don't have our single HIF yet then save it, otherwise it is an invalid
// command.
if (0 == string.Compare(".hif", Path.GetExtension(arg), true, CultureInfo.InvariantCulture) &&
string.Empty == hif)
hif = arg;
else
Terminate("Unknown command line argument {0}", arg);
}
}
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
try
{
// Set the log file name to be our application name.
NWNLogger.LogFile = Application.ProductName + ".txt";
// Process command line arguments.
ProcessArguments(args);
// Make sure NWN is installed before doing anything. If the user
// gave an install path on the command line we could be installing on
// a remote machine, so do not check for an install on this machine.
if (!installPathGiven && !NWNInfo.IsInstalled)
Terminate("Neverwinter Nights is not installed");
// Requires .NET framework 1.1
// If we are running as the PRC installer or a single HIF OEM reskin, then
// show our single HIF form, otherwise show the generic form.
Application.EnableVisualStyles();
if (string.Empty != hif)
Application.Run(new SingleHIFInstallForm());
else
Application.Run(new InstallForm());
}
catch (EntryPointNotFoundException)
{
// Dummy exception thrown to terminate the application by Help(),
// don't display anything just return -1.
}
catch (Exception e)
{
ShowMessage(e.Message);
}
finally
{
// Turn off logging in case it was on this will flush the file.
NWNLogger.Logging = false;
}
}
#endregion
}
}

View File

@@ -0,0 +1,385 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using NWN.FileTypes.Gff;
namespace NWN.FileTypes
{
/// <summary>
/// This class defines the functionality for a .IFO file, which contains
/// information about the module. This is based on the GFF file format;
/// this class derives form Gff and provised IFO specific functionality.
/// </summary>
public class ModuleInfo: NWN.FileTypes.Gff.Gff
{
#region public properties/methods
public const string FileName = "module.ifo";
/// <summary>
/// Indexer allowing get/set access to any of the module's exposed
/// properties. Exposed properties are added to the properties
/// dictionary, which provides a translation between a human readable
/// name and the property's label.
/// </summary>
public string this[string property]
{
get
{
// Look up the property in our dictionary to get the label name, if it
// is not there then throw an exception.
GffFieldSchema schema = properties[property];
if (null == schema) throw new NWNException("{0} is not a valid module property", property);
// Look up the field for the label. If we cannot look it up then
// it has not been added to the module info file, we need to add
// it ourselves.
GffField field = GetField(schema);
// Figure out what to return based on the field's type. Currently
// only ResRef and ExoString fields are supported.
switch (field.Type)
{
case GffFieldType.ExoString:
case GffFieldType.ResRef:
return (string) field.Value;
default:
throw new InvalidCastException("propety is not a text property");
}
}
set
{
// Look up the property in our dictionary to get the label name, if it
// is not there then throw an exception.
GffFieldSchema schema = properties[property];
if (null == schema) throw new NWNException("{0} is not a valid module property", property);
// Look up the field for the label. If we cannot look it up then
// it has not been added to the module info file, we need to add
// it ourselves.
GffField field = GetField(schema);
// Figure out what to do based on the field's type, currently only
// ResRef and ExoString types are supported.
switch (field.Type)
{
case GffFieldType.ExoString:
case GffFieldType.ResRef:
field.Value = value;
break;
default:
throw new InvalidCastException("propety is not a text property");
}
}
}
/// <summary>
/// Gets/sets the custom tlk property.
/// </summary>
public string CustomTlk
{
get
{
// Get the schema for the field and get it, creating it if it is not there.
// Then return the field's value.
GffFieldSchema schema = properties["customtlk"];
GffExoStringField field = (GffExoStringField) GetField(schema);
return field.Value;
}
set
{
// Get the schema for the field and get it, creating it if it is not there.
// Then set the field's value.
GffFieldSchema schema = properties["customtlk"];
GffExoStringField field = (GffExoStringField) GetField(schema);
field.Value = value;
}
}
/// <summary>
/// Gets the list of haks currently attached to the module.
/// </summary>
public StringCollection Haks
{
get
{
// Get the hak list field.
GffListField listField = (GffListField) GetField(properties[HakList]);
GffFieldCollection list = listField.Value;
// Create a string collection object and loop through all of the
// structs in the hak list adding the haks.
StringCollection haks = new StringCollection();
foreach (GffStructField field in list)
{
// Get the string entry for the value.
GffFieldDictionary dict = field.Value;
GffField structValue = dict[HakEntry];
haks.Add(structValue.Value.ToString());
}
return haks;
}
}
/// <summary>
/// Class constructor
/// </summary>
/// <param name="path">The path to the module info file, this should NOT
/// contain the file name</param>
public ModuleInfo(string path) : base(Path.Combine(path, FileName))
{
Construct();
}
/// <summary>
/// Class constructor to create the object from a stream, useful for creating
/// the module info object without decompressing the module. The current seek
/// position of the stream must point to the start of the module info file.
/// </summary>
/// <param name="stream">The stream to read the file data from.</param>
public ModuleInfo(Stream stream) : base(stream)
{
Construct();
}
/// <summary>
/// Adds the passed hif name / version number to the list of hifs installed on
/// the module. Both arrays must be the same length.
/// </summary>
/// <param name="hifs">The hifs to add</param>
/// <param name="versions">The version numbers of the hifs</param>
public void AddInstalledHakInfos(string[] hifs, float[] versions)
{
// Get the current values if any.
string[] currentHifs;
float[] currentVersions;
GetInstalledHakInfos(out currentHifs, out currentVersions);
// Create StringCollections for them so we can use IndexOf() for searching.
StringCollection colHifs = new StringCollection();
colHifs.AddRange(currentHifs);
ArrayList colVersions = new ArrayList();
colVersions.AddRange(currentVersions);
// Check for duplicates, pruning duplicates out of the current list.
foreach (string hif in hifs)
{
// Find the hif in the current values, if we don't find it then
// skip it.
int index = colHifs.IndexOf(hif);
if (-1 == index) continue;
// Remove it from the current list.
colHifs.RemoveAt(index);
colVersions.RemoveAt(index);
}
// Now build a string with all of the current hifs/version numbers then
// all of the added hif/version numbers.
System.Text.StringBuilder b = new StringBuilder();
for (int i = 0; i < colHifs.Count; i++)
{
if (b.Length > 0) b.Append(";");
b.AppendFormat("{0};{1}", colHifs[i], colVersions[i].ToString());
}
for (int i = 0; i < hifs.Length; i++)
{
if (b.Length > 0) b.Append(";");
b.AppendFormat("{0};{1}", hifs[i], versions[i].ToString());
}
// Get the schema for the field and get it, creating it if it is not there.
// Then save the StringBuilder text as the field's value.
GffFieldSchema schema = properties["installedhifs"];
GffExoStringField field = (GffExoStringField) GetField(schema);
field.Value = b.ToString();
}
/// <summary>
/// Gets the list of hifs that are currently installed on the module, and their version
/// numbers.
/// </summary>
/// <param name="hifs">Returns the list of hifs</param>
/// <param name="versions">Returns the version numbers of the hifs</param>
public void GetInstalledHakInfos(out string[] hifs, out float[] versions)
{
// Get the schema for the field and get it, creating it if it is not there.
// Then return the field's value.
GffFieldSchema schema = properties["installedhifs"];
GffExoStringField field = (GffExoStringField) GetField(schema);
// Split the string into the list of hif and version numbers. If the
// field is empty then we will get back 1 string, an empty string.
string[] strings = field.Value.Split(';');
// Create string arrays for the hif names and version numbers.
hifs = new string[strings.Length / 2];
versions = new float[strings.Length / 2];
if (strings.Length > 1)
{
// Fill in the hif/version arrays with the string values.
for (int i = 0, index = 0; i < strings.Length; i += 2, index++)
hifs[index] = strings[i];
for (int i = 1, index = 0; i < strings.Length; i += 2, index++)
versions[index] = (float) Convert.ToDouble(strings[i]);
}
}
/// <summary>
/// This method adds an array of area files to the module info's area list. It prunes
/// duplicates before adding the areas.
/// </summary>
/// <param name="areas"></param>
public void AddAreas(string[] areas)
{
UpdateList(AreaList, AreaEntry, AreaStructID, GffFieldType.ResRef, areas);
}
/// <summary>
/// This method adds an array of hak files to the module info. It prunes
/// duplicates before adding the haks.
/// </summary>
/// <param name="haks">The list of haks to add</param>
public void AddHaks(string[] haks)
{
UpdateList(HakList, HakEntry, HakStructID, GffFieldType.ExoString, haks);
}
/// <summary>
/// This method adds an array of scripts to the module's cache list. It
/// prunes duplicates before adding the scripts.
/// </summary>
/// <param name="scripts">The list of scripts to add</param>
public void AddToCache(string[] scripts)
{
UpdateList(CacheList, CacheEntry, CacheStructID, GffFieldType.ResRef, scripts);
}
#endregion
#region private fields/properties/methods
private const string HakList = "Mod_HakList";
private const string HakEntry = "Mod_Hak";
private const string CacheList = "Mod_CacheNSSList";
private const string CacheEntry = "ResRef";
private const string AreaList = "Mod_Area_list";
private const string AreaEntry = "Area_Name";
private const uint HakStructID = 8;
private const uint CacheStructID = 9;
private const uint AreaStructID = 6;
private GffSchemaCollection properties;
/// <summary>
/// This method constructs the ModuleInfo object.
/// </summary>
private void Construct()
{
// Create our property schema, filling it in with the properties we
// manipulate. This is not a complete schema, it is only for the
// properties considered 'interesting'.
properties = new GffSchemaCollection();
properties.Add(new GffFieldSchema("onacquireitem", "Mod_OnAcquirItem", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onactivateitem", "Mod_OnActvtItem", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("oncliententer", "Mod_OnClientEntr", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onclientleave", "Mod_OnClientLeav", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("oncutsceneabort", "Mod_OnCutsnAbort", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onheartbeat", "Mod_OnHeartbeat", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onmoduleload", "Mod_OnModLoad", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onmodulestart", "Mod_OnModStart", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onplayerchat", "Mod_OnPlrChat", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onplayerdeath", "Mod_OnPlrDeath", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onplayerdying", "Mod_OnPlrDying", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onplayerequipitem", "Mod_OnPlrEqItm", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onplayerlevelup", "Mod_OnPlrLvlUp", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onplayerrest", "Mod_OnPlrRest", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onplayerunequipitem", "Mod_OnPlrUnEqItm", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onplayerrespawn", "Mod_OnSpawnBtnDn", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onunaquireitem", "Mod_OnUnAqreItem", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("onuserdefined", "Mod_OnUsrDefined", GffFieldType.ResRef));
properties.Add(new GffFieldSchema("customtlk", "Mod_CustomTlk", GffFieldType.ExoString));
// This field is not part of the bioware schema for a module info file, we add it to keep
// track of what HIFs have been installed on a module. The value is a string with
// the following format "HIF;Version;HIF;Version;...". We make it a string instead of
// a list because a list would require us to assign a structure ID, and worry about
// BioWare using the ID later.
properties.Add(new GffFieldSchema("installedhifs", "InstalledHIFs", GffFieldType.ExoString));
// These properties aren't exposed out to the user, so we don't give them real names, we just
// use the tag as the ui name.
properties.Add(new GffFieldSchema("Mod_Area_list", "Mod_Area_list", GffFieldType.List));
properties.Add(new GffFieldSchema("Mod_HakList", "Mod_HakList", GffFieldType.List));
properties.Add(new GffFieldSchema("Mod_CacheNSSList", "Mod_CacheNSSList", GffFieldType.List));
}
/// <summary>
/// This method updates the cache and hak list properties in the module
/// info, adding the passed array of strings to the appropriate property.
/// Both of these lists consist of an array of structures with 1 string
/// item in each struture.
/// </summary>
/// <param name="listTag">The property name for the list</param>
/// <param name="entryTag">The property name for each string in the list's
/// structures</param>
/// <param name="structID">The structure ID of the structures in the list</param>
/// <param name="stringType">The data type of the string in the list, either
/// ExoString or ResRef</param>
/// <param name="values">The array of strings to add, duplicates are pruned</param>
private void UpdateList(string listTag, string entryTag, uint structID,
GffFieldType stringType, string[] values)
{
// Get the array of elements in the list.
GffListField listField = (GffListField) GetField(properties[listTag]);
GffFieldCollection list = listField.Value;
// Create a string collection containing lower case copies of all of
// the strings.
StringCollection strings = new StringCollection();
strings.AddRange(values);
for (int i = 0; i < strings.Count; i ++)
strings[i] = strings[i].ToLower();
// Make a first pass and eliminate any strings that are already
// in the module.
foreach (GffStructField field in list)
{
// Get the string entry for the value.
GffFieldDictionary dict = field.Value;
GffField structValue = dict[entryTag];
// Check to see if the hak is in the list of haks to add if it is
// then remove it.
int index = strings.IndexOf((string) structValue.Value);
if (-1 != index) strings.RemoveAt(index);
}
// Now loop through all of the remaining strings and add them to the
// beginning of the list. We walk the list backwards adding the items
// to the beginning of the list's collection, so when we are done
// all of the added items are in order at the FRONT of the list.
for (int i = strings.Count - 1; i >= 0; i--)
{
// Create a ExoString field for the hak file name.
GffField structValue = GffFieldFactory.CreateField(stringType);
structValue.Value = strings[i];
// Create a GffStructField for the new list element and
// save the exoString hak name in it.
GffStructField listStruct = (GffStructField)
GffFieldFactory.CreateField(GffFieldType.Struct);
listStruct.StructureType = structID;
listStruct.Value = new GffFieldDictionary();
listStruct.Value.Add(entryTag, structValue);
// Add the structure to the list.
list.Insert(0, listStruct);
}
}
#endregion
}
}

View File

@@ -0,0 +1,279 @@
using System;
using System.IO;
using Microsoft.Win32;
namespace NWN
{
/// <summary>
/// This class encapsulates various information about the NWN application.
/// </summary>
public class NWNInfo
{
#region public static properties/methods
/// <summary>
/// Gets whether or not NWN is installed on this PC.
/// </summary>
public static bool IsInstalled { get { return singleton.installed; } }
/// <summary>
/// Returns true if XP1 is installed.
/// </summary>
public static bool IsXP1Installed {
get { return singleton.isXP1Installed; }
set { singleton.isXP1Installed = value; }
}
/// <summary>
/// Returns true if XP2 is installed.
/// </summary>
public static bool IsXP2Installed {
get { return singleton.isXP2Installed; }
set { singleton.isXP2Installed = value; }
}
/// <summary>
/// Returns true if the OC modules are installed.
/// </summary>
public static bool IsOCModsInstalled
{
get
{
// Return true if all of the modules are on disk.
foreach (string module in ocModules)
{
string file = Path.Combine(NWMPath, module);
if (!File.Exists(file)) return false;
}
return true;
}
}
/// <summary>
/// Returns true if the XP1 modules are installed.
/// </summary>
public static bool IsXP1ModsInstalled
{
get
{
// Return true if all of the modules are on disk.
foreach (string module in xp1Modules)
{
string file = Path.Combine(NWMPath, module);
if (!File.Exists(file)) return false;
}
return true;
}
}
/// <summary>
/// Returns true if the XP2 modules are installed.
/// </summary>
public static bool IsXP2ModsInstalled
{
get
{
// Return true if all of the modules are on disk.
foreach (string module in xp2Modules)
{
string file = Path.Combine(NWMPath, module);
if (!File.Exists(file)) return false;
}
return true;
}
}
/// <summary>
/// Gets the list of OC modules.
/// </summary>
public static string[] OCModules { get { return ocModules; } }
/// <summary>
/// Gets the list of XP1 modules
/// </summary>
public static string[] XP1Modules { get { return xp1Modules; } }
/// <summary>
/// Gets the list of XP2 modules.
/// </summary>
public static string[] XP2Modules { get { return xp2Modules; } }
/// <summary>
/// Gets/sets the path that NWN is installed in. The path may be set to
/// allow for the manipulation of NWN on remote installs or for multiple
/// installs. If the path is set to string.Empty, then the value will
/// revert back to the install path in the registry.
/// </summary>
public static string InstallPath
{
get
{
return string.Empty == singleton.overridePath ?
singleton.installPath : singleton.overridePath;
}
set
{
singleton.overridePath = value;
}
}
/// <summary>
/// Gets the path for the bioware modules.
/// </summary>
public static string NWMPath { get { return Path.Combine(InstallPath, "nwm"); } }
/// <summary>
/// Gets the path for the tools subdirectory.
/// </summary>
public static string ToolsPath { get { return Path.Combine(InstallPath, "Utils"); } }
/// <summary>
/// Gets the path for the modules subdirectory.
/// </summary>
public static string ModulesPath { get { return Path.Combine(InstallPath, "Modules"); } }
/// <summary>
/// Gets the path for the hak info files.
/// </summary>
public static string HakInfoPath { get { return HakPath; } }
/// <summary>
/// Gets the path for the hak .
/// </summary>
public static string HakPath { get { return Path.Combine(InstallPath, "hak"); } }
/// <summary>
/// Gets the installed NWN version.
/// </summary>
public static string Version {
get { return singleton.version; }
set { singleton.version = value; }
}
/// <summary>
/// Gets the full path for the specified NWN file.
/// </summary>
/// <param name="file">The NWM file to get the full path for.</param>
/// <returns>The full path to the NWM file.</returns>
public static string GetFullFilePath(string file)
{
return Path.Combine(GetPathForFile(file), file);
}
/// <summary>
/// Gets the partial path (relative to the NWN install directory) of
/// the file, i.e. hak\foo.hak, etc.
/// </summary>
/// <param name="file">The NWM file to get the full path for.</param>
/// <returns>The partial path to the NWM file.</returns>
public static string GetPartialFilePath(string file)
{
// Determine the path based on the file's extension. Hif files are
// a new file type (hack info) that we use to store information about
// what files are contained in a 'hak'.
FileInfo info = new FileInfo(file);
switch (info.Extension.ToLower())
{
case ".tlk":
return Path.Combine("tlk", file);
case ".erf":
return Path.Combine("erf", file);
case ".hif":
case ".hak":
return Path.Combine("hak", file);
case ".mod":
return Path.Combine("modules", file);
case ".nwm":
return Path.Combine("nwm", file);
default:
return file;
}
}
/// <summary>
/// This method gets the path that the specified NWN file should be
/// installed in. It supports .mod, .nwm, .tlk, .erf, .hak file types.
/// </summary>
/// <param name="file">The file to get the path for</param>
/// <returns>The path that the file should be installed in</returns>
public static string GetPathForFile(string file)
{
// Determine the path based on the file's extension. Hif files are
// a new file type (hack info) that we use to store information about
// what files are contained in a 'hak'.
FileInfo info = new FileInfo(file);
switch (info.Extension.ToLower())
{
case ".tlk":
return Path.Combine(InstallPath, "tlk");
case ".erf":
return Path.Combine(InstallPath, "erf");
case ".hif":
case ".hak":
return Path.Combine(InstallPath, "hak");
case ".mod":
return Path.Combine(InstallPath, "modules");
case ".nwm":
return Path.Combine(InstallPath, "nwm");
}
// If we get here the file is something we don't know about, return
// string.Empty.
return string.Empty;
}
#endregion
#region private fields/properties/methods
/// <summary>
/// Class constructor implemented as private, since the object is a singleton
/// and can only be created internally.
/// </summary>
private NWNInfo()
{
RegistryKey key = Registry.LocalMachine.OpenSubKey(regPath);
// If we were able to open up the NWN registry key then NWW is
// installed on the PC, save the important registration information.
if (null != key)
{
installed = true;
installPath = key.GetValue(regLocation) as string;
version = key.GetValue(regVersion) as string;
}
// Check for the XP1 Guid registry entry, if it's there then
// mark XP1 as being installed.
key = Registry.LocalMachine.OpenSubKey(regXP1Path);
if (null != key && null != key.GetValue(regGuid)) isXP1Installed = true;
// Check for the XP2 Guid registry entry, if it's there then
// mark XP2 as being installed.
key = Registry.LocalMachine.OpenSubKey(regXP2Path);
if (null != key && null != key.GetValue(regGuid)) isXP2Installed = true;
}
// Module lists for the various modules in the OC/XP1/XP2
private static string[] ocModules = new string[] { "Prelude.nwm", "Chapter1.nwm", "Chapter1E.nwm",
"Chapter2.nwm", "Chapter2E.nwm", "Chapter3.nwm", "Chapter4.nwm" };
private static string[] xp1Modules = new string[]
{ "XP1-Chapter 1.nwm", "XP1-Interlude.nwm", "XP1-Chapter 2.nwm" };
private static string[] xp2Modules = new string[]
{ "XP2_Chapter1.nwm", "XP2_Chapter2.nwm", "XP2_Chapter3.nwm" };
private const string regPath = @"SOFTWARE\BioWare\NWN\Neverwinter";
private const string regXP1Path = @"SOFTWARE\BioWare\NWN\Undrentide";
private const string regXP2Path = @"SOFTWARE\BioWare\NWN\Underdark";
private const string regGuid = "Guid";
private const string regLocation = "Location";
private const string regVersion = "Version";
private static NWNInfo singleton = new NWNInfo();
private string installPath = string.Empty;
private string overridePath = string.Empty;
private string version = string.Empty;
private bool installed = false;
private bool isXP1Installed = false;
private bool isXP2Installed = false;
#endregion
}
}

View File

@@ -0,0 +1,244 @@
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using HakInstaller;
using HakInstaller.Utilities;
namespace HakInstaller
{
/// <summary>
/// This form displays is a comfirmation box asking the user if the
/// application should continue with replacing the listed files with
/// files from added hak(s).
/// </summary>
public class OverwriteWarningsForm : System.Windows.Forms.Form
{
#region public properties/methods
/// <summary>
/// Class constructor
/// </summary>
/// <param name="conflicts">The list of file conflicts.</param>
public OverwriteWarningsForm(OverwriteWarningCollection warnings,
bool fatal, OverwriteWarningType type)
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
pictureBox.Image = SystemIcons.Exclamation.ToBitmap();
// There appears to be a bug in the 1.0 version of the framework. On my
// 3.2ghz machine, if listBox.Items.Add(conflict) is placed in the
// foreach array it hangs, unless you slow it down somehow. Moving
// the add outside the loop and changing it to an AddRange() to add all
// of the conflicts in one shot makes it work correctly, thus the change
// to the code.
// Add all of the conflicts to the list box.
ListViewItem[] items = new ListViewItem[warnings.Count];
for (int i = 0; i < warnings.Count; i++)
items[i] = new ListViewItem(new String[]
{ warnings[i].Replacer, warnings[i].File, warnings[i].Source });
listView.Items.AddRange(items);
// Load the appropriate prompt text.
labelPrompt.Text = StringResources.GetString(type.ToString());
// If we have fatal errors then turn off the continue button, the user
// can only cancel.
if (fatal) buttonContinue.Enabled = false;
}
#endregion
#region protected fields/properties/methods
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
#region functionality for Win32 PlaySound API
[Flags] private enum SoundFlags
{
Sync = 0x00000000, /* play synchronously (default) */
Async = 0x00000001, /* play asynchronously */
NoDefault = 0x00000002, /* silence (!default) if sound not found */
Memory = 0x00000004, /* pszSound points to a memory file */
Loop = 0x00000008, /* loop the sound until next sndPlaySound */
NoStop = 0x00000010, /* don't stop any currently playing sound */
NoWait = 0x00002000, /* don't wait if the driver is busy */
Alias = 0x00010000, /* name is a registry alias */
AliasId = 0x00110000, /* alias is a pre d ID */
Filename = 0x00020000, /* name is file name */
Resource = 0x00040004, /* name is resource name or atom */
Purge = 0x00000040, /* purge non-static events for task */
Application = 0x00000080 /* look for application specific association */
}
public static void PlaySoundEvent(string sound)
{
PlaySound(sound, 0,
(int) (SoundFlags.Async | SoundFlags.Alias | SoundFlags.NoWait));
}
[DllImport("winmm.dll", EntryPoint="PlaySound",CharSet=CharSet.Auto)]
private static extern int PlaySound(String pszSound, int hmod, int flags);
#endregion
#region Windows Form Designer generated code
private System.Windows.Forms.Button buttonContinue;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.PictureBox pictureBox;
private System.Windows.Forms.Label labelPrompt;
private System.Windows.Forms.ListView listView;
private System.Windows.Forms.ColumnHeader columnFile;
private System.Windows.Forms.ColumnHeader columnReplacer;
private System.Windows.Forms.ColumnHeader columnSource;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.labelPrompt = new System.Windows.Forms.Label();
this.buttonContinue = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.pictureBox = new System.Windows.Forms.PictureBox();
this.listView = new System.Windows.Forms.ListView();
this.columnReplacer = new System.Windows.Forms.ColumnHeader();
this.columnFile = new System.Windows.Forms.ColumnHeader();
this.columnSource = new System.Windows.Forms.ColumnHeader();
this.SuspendLayout();
//
// labelPrompt
//
this.labelPrompt.Location = new System.Drawing.Point(72, 16);
this.labelPrompt.Name = "labelPrompt";
this.labelPrompt.Size = new System.Drawing.Size(488, 40);
this.labelPrompt.TabIndex = 0;
this.labelPrompt.Text = "Some modules already have some of the content you selected installed. Do you wis" +
"h to continue? The install may not work if you continue.";
//
// buttonContinue
//
this.buttonContinue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonContinue.DialogResult = System.Windows.Forms.DialogResult.OK;
this.buttonContinue.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.buttonContinue.Location = new System.Drawing.Point(16, 296);
this.buttonContinue.Name = "buttonContinue";
this.buttonContinue.Size = new System.Drawing.Size(80, 26);
this.buttonContinue.TabIndex = 2;
this.buttonContinue.Text = "C&ontinue";
//
// button2
//
this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.button2.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.button2.Location = new System.Drawing.Point(112, 296);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(80, 26);
this.button2.TabIndex = 3;
this.button2.Text = "&Cancel";
//
// pictureBox
//
this.pictureBox.Location = new System.Drawing.Point(24, 16);
this.pictureBox.Name = "pictureBox";
this.pictureBox.Size = new System.Drawing.Size(32, 32);
this.pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.pictureBox.TabIndex = 3;
this.pictureBox.TabStop = false;
//
// listView
//
this.listView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.listView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnReplacer,
this.columnFile,
this.columnSource});
this.listView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.listView.Location = new System.Drawing.Point(16, 72);
this.listView.MultiSelect = false;
this.listView.Name = "listView";
this.listView.Size = new System.Drawing.Size(568, 208);
this.listView.Sorting = System.Windows.Forms.SortOrder.Ascending;
this.listView.TabIndex = 4;
this.listView.View = System.Windows.Forms.View.Details;
//
// columnReplacer
//
this.columnReplacer.Text = "Overwriter";
this.columnReplacer.Width = 150;
//
// columnFile
//
this.columnFile.Text = "File";
this.columnFile.Width = 150;
//
// columnSource
//
this.columnSource.Text = "Source";
this.columnSource.Width = 240;
//
// OverwriteWarningsForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(600, 334);
this.ControlBox = false;
this.Controls.Add(this.listView);
this.Controls.Add(this.pictureBox);
this.Controls.Add(this.buttonContinue);
this.Controls.Add(this.labelPrompt);
this.Controls.Add(this.button2);
this.MinimumSize = new System.Drawing.Size(608, 368);
this.Name = "OverwriteWarningsForm";
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Overwriting Existing Content";
this.Load += new System.EventHandler(this.ReplacingFilesForm_Load);
this.ResumeLayout(false);
}
#endregion
#region form event handlers
/// <summary>
/// Handler for the load event.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ReplacingFilesForm_Load(object sender, System.EventArgs e)
{
PlaySoundEvent("SystemExclamation");
}
#endregion
#region control event handlers
#endregion
}
}

View File

@@ -0,0 +1,193 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="labelPrompt.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="labelPrompt.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="labelPrompt.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonContinue.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="buttonContinue.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonContinue.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="button2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="button2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="button2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="pictureBox.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="pictureBox.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="pictureBox.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="listView.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="listView.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="listView.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="columnReplacer.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="columnReplacer.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="columnFile.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="columnFile.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="columnSource.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="columnSource.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>(Default)</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
<data name="$this.Name">
<value>OverwriteWarningsForm</value>
</data>
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>80</value>
</data>
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
</root>

View File

@@ -0,0 +1,87 @@
using System;
using System.IO;
using System.Text;
using NWN;
namespace HakInstaller
{
/// <summary>
/// Summary description for PRCHif.
/// </summary>
public class PRCHif
{
/// <summary>
/// Gets the file name of the PRC hif.
/// </summary>
public static string PRCHifFileName { get { return "PRC Consortium Pack.hif"; } }
/// <summary>
/// Gets the full path to the PRC hif.
/// </summary>
public static string PRCHifFullPath { get { return NWNInfo.GetFullFilePath(PRCHifFileName); } }
/// <summary>
/// Creates a temporary HIF file on disk for the PRC pack.
/// </summary>
public static void CreatePRCHif()
{
using (StreamWriter writer = new StreamWriter(PRCHifFullPath, false, Encoding.ASCII))
{
writer.Write(HIF);
}
}
/// <summary>
/// String constant for the PRC hif, the PRC version of the installer uses
/// this as its HIF instead of looking for HIF files.
/// </summary>
private const string HIF =
"Title : PRC Pack\r\n" +
"Version : 2.0\r\n" +
"MinNWNVersion : 1.62, XP1, XP2\r\n" +
"# Erf for the MMM areas\r\n" +
"erf : prc_consortium.erf\r\n" +
"# Haks used by the prc pack.\r\n" +
"module.Hak : prc_2das.hak\r\n" +
"module.Hak : prc_craft2das.hak\r\n" +
"module.Hak : prc_scripts.hak\r\n" +
"module.Hak : prc_textures.hak\r\n" +
"module.Hak : prc_misc.hak\r\n" +
"# Custom tlk used by the prc pack.\r\n" +
"module.CustomTlk : prc_consortium.tlk\r\n" +
"# Events that need to be wired up.\r\n" +
"module.OnAcquireItem : prc_onaquire\r\n" +
"module.OnActivateItem : prc_onactivate\r\n" +
"module.OnClientEnter : prc_onenter\r\n" +
"module.OnClientLeave : prc_onleave\r\n" +
"module.OnCutsceneAbort : prc_oncutabort\r\n" +
"module.OnHeartbeat : prc_onheartbeat\r\n" +
"module.OnModuleLoad : prc_onmodload\r\n" +
"module.OnPlayerDeath : prc_ondeath\r\n" +
"module.OnPlayerDying : prc_ondying\r\n" +
"module.OnPlayerEquipItem : prc_equip\r\n" +
"module.OnPlayerLevelUp : prc_levelup\r\n" +
"module.OnPlayerRest : prc_rest\r\n" +
"module.OnPlayerRespawn : prc_onrespawn\r\n" +
"module.OnUnaquireItem : prc_onunaquire\r\n" +
"module.OnPlayerUnequipItem : prc_unequip\r\n" +
"module.OnUserDefined : prc_onuserdef\r\n" +
"# Cache PRC scripts for better performance.\r\n" +
"module.Cache : prc_add_spl_pen\r\n" +
"module.Cache : prc_add_spell_dc\r\n" +
"module.Cache : prc_set_dmg_type\r\n" +
"module.Cache : prc_caster_level\r\n" +
"module.Cache : prc_onaquire\r\n" +
"module.Cache : prc_onactivate\r\n" +
"module.Cache : prc_equip\r\n" +
"module.Cache : prc_onheartbeat\r\n" +
"module.Cache : prc_onunaquire\r\n" +
"module.Cache : prc_onuserdef\r\n";
}
}

View File

@@ -0,0 +1,381 @@
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using HakInstaller;
using HakInstaller.Utilities;
namespace HakInstaller
{
/// <summary>
/// This form displays is a comfirmation box asking the user if the
/// application should continue with replacing the listed files with
/// files from added hak(s).
/// </summary>
public class ReplacingFilesForm : System.Windows.Forms.Form
{
#region public properties/methods
/// <summary>
/// Class constructor
/// </summary>
/// <param name="conflicts">The list of file conflicts.</param>
public ReplacingFilesForm(FileConflictCollection conflicts)
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
// Ignore events while initializing the form.
ignoreEvents = true;
pictureBox.Image = SystemIcons.Exclamation.ToBitmap();
// There appears to be a bug in the 1.0 version of the framework. On my
// 3.2ghz machine, if listBox.Items.Add(conflict) is placed in the
// foreach array it hangs, unless you slow it down somehow. Moving
// the add outside the loop and changing it to an AddRange() to add all
// of the conflicts in one shot makes it work correctly, thus the change
// to the code.
// Add all of the conflicts to the list box.
FileConflict[] conflictArray = new FileConflict[conflicts.Count];
for (int i = 0; i < conflicts.Count; i++)
conflictArray[i] = conflicts[i];
listBox.Items.AddRange(conflictArray);
// Loop through all of the conflicts setting their check state as appropriate.
foreach (FileConflict conflict in conflicts)
{
int index = listBox.Items.IndexOf(conflict);
listBox.SetItemChecked(index, conflict.ReplaceFile);
}
ignoreEvents = false;
}
#endregion
#region protected fields/properties/methods
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
#region functionality for Win32 PlaySound API
[Flags] private enum SoundFlags
{
Sync = 0x00000000, /* play synchronously (default) */
Async = 0x00000001, /* play asynchronously */
NoDefault = 0x00000002, /* silence (!default) if sound not found */
Memory = 0x00000004, /* pszSound points to a memory file */
Loop = 0x00000008, /* loop the sound until next sndPlaySound */
NoStop = 0x00000010, /* don't stop any currently playing sound */
NoWait = 0x00002000, /* don't wait if the driver is busy */
Alias = 0x00010000, /* name is a registry alias */
AliasId = 0x00110000, /* alias is a pre d ID */
Filename = 0x00020000, /* name is file name */
Resource = 0x00040004, /* name is resource name or atom */
Purge = 0x00000040, /* purge non-static events for task */
Application = 0x00000080 /* look for application specific association */
}
public static void PlaySoundEvent(string sound)
{
PlaySound(sound, 0,
(int) (SoundFlags.Async | SoundFlags.Alias | SoundFlags.NoWait));
}
[DllImport("winmm.dll", EntryPoint="PlaySound",CharSet=CharSet.Auto)]
private static extern int PlaySound(String pszSound, int hmod, int flags);
#endregion
#region Windows Form Designer generated code
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button buttonContinue;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.PictureBox pictureBox;
private System.Windows.Forms.CheckedListBox listBox;
private System.Windows.Forms.MenuItem menuItemViewHakFile;
private System.Windows.Forms.MenuItem menuItemViewModFile;
private System.Windows.Forms.ContextMenu contextMenuView;
private System.Windows.Forms.Button buttonSelectAll;
private System.Windows.Forms.Button buttonClearAll;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.buttonContinue = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.pictureBox = new System.Windows.Forms.PictureBox();
this.listBox = new System.Windows.Forms.CheckedListBox();
this.contextMenuView = new System.Windows.Forms.ContextMenu();
this.menuItemViewHakFile = new System.Windows.Forms.MenuItem();
this.menuItemViewModFile = new System.Windows.Forms.MenuItem();
this.buttonSelectAll = new System.Windows.Forms.Button();
this.buttonClearAll = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label1
//
this.label1.Location = new System.Drawing.Point(72, 16);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(328, 56);
this.label1.TabIndex = 0;
this.label1.Text = "The following files in the module are being replaced by files in the hak\'s erfs. " +
" This may cause the module to not run properly. Select cancel to abort adding " +
"the hak, or check the files that you want to replace in the module and select co" +
"ntinue.";
//
// buttonContinue
//
this.buttonContinue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonContinue.DialogResult = System.Windows.Forms.DialogResult.OK;
this.buttonContinue.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.buttonContinue.Location = new System.Drawing.Point(16, 278);
this.buttonContinue.Name = "buttonContinue";
this.buttonContinue.Size = new System.Drawing.Size(96, 24);
this.buttonContinue.TabIndex = 4;
this.buttonContinue.Text = "C&ontinue";
//
// button2
//
this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.button2.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.button2.Location = new System.Drawing.Point(128, 278);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(96, 24);
this.button2.TabIndex = 5;
this.button2.Text = "&Cancel";
//
// pictureBox
//
this.pictureBox.Location = new System.Drawing.Point(24, 16);
this.pictureBox.Name = "pictureBox";
this.pictureBox.Size = new System.Drawing.Size(32, 32);
this.pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.pictureBox.TabIndex = 3;
this.pictureBox.TabStop = false;
//
// listBox
//
this.listBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.listBox.ContextMenu = this.contextMenuView;
this.listBox.Location = new System.Drawing.Point(16, 80);
this.listBox.Name = "listBox";
this.listBox.Size = new System.Drawing.Size(296, 184);
this.listBox.Sorted = true;
this.listBox.TabIndex = 1;
this.listBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.listBox_ItemCheck);
//
// contextMenuView
//
this.contextMenuView.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItemViewHakFile,
this.menuItemViewModFile});
this.contextMenuView.Popup += new System.EventHandler(this.contextMenuView_Popup);
//
// menuItemViewHakFile
//
this.menuItemViewHakFile.Index = 0;
this.menuItemViewHakFile.Text = "View &Hak File";
this.menuItemViewHakFile.Click += new System.EventHandler(this.menuItemViewHakFile_Click);
//
// menuItemViewModFile
//
this.menuItemViewModFile.Index = 1;
this.menuItemViewModFile.Text = "View &Module File";
this.menuItemViewModFile.Click += new System.EventHandler(this.menuItemViewModFile_Click);
//
// buttonSelectAll
//
this.buttonSelectAll.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.buttonSelectAll.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.buttonSelectAll.Location = new System.Drawing.Point(328, 88);
this.buttonSelectAll.Name = "buttonSelectAll";
this.buttonSelectAll.Size = new System.Drawing.Size(72, 24);
this.buttonSelectAll.TabIndex = 2;
this.buttonSelectAll.Text = "&Select All";
this.buttonSelectAll.Click += new System.EventHandler(this.buttonSelectAll_Click);
//
// buttonClearAll
//
this.buttonClearAll.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.buttonClearAll.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.buttonClearAll.Location = new System.Drawing.Point(328, 128);
this.buttonClearAll.Name = "buttonClearAll";
this.buttonClearAll.Size = new System.Drawing.Size(75, 24);
this.buttonClearAll.TabIndex = 3;
this.buttonClearAll.Text = "Clear &All";
this.buttonClearAll.Click += new System.EventHandler(this.buttonClearAll_Click);
//
// ReplacingFilesForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(416, 310);
this.ControlBox = false;
this.Controls.Add(this.buttonClearAll);
this.Controls.Add(this.buttonSelectAll);
this.Controls.Add(this.listBox);
this.Controls.Add(this.pictureBox);
this.Controls.Add(this.buttonContinue);
this.Controls.Add(this.label1);
this.Controls.Add(this.button2);
this.MinimumSize = new System.Drawing.Size(424, 344);
this.Name = "ReplacingFilesForm";
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Replace Files?";
this.Load += new System.EventHandler(this.ReplacingFilesForm_Load);
this.ResumeLayout(false);
}
#endregion
#region private fields/properties/methods
private bool ignoreEvents;
#endregion
#region form event handlers
/// <summary>
/// Handler for the load event.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ReplacingFilesForm_Load(object sender, System.EventArgs e)
{
PlaySoundEvent("SystemExclamation");
}
#endregion
#region control event handlers
/// <summary>
/// Handler for the list box's item check event.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void listBox_ItemCheck(object sender, System.Windows.Forms.ItemCheckEventArgs e)
{
if (ignoreEvents) return;
// Update the ReplaceFile property of the FileConflict object being clicked on
// based on the new state of the check.
FileConflict conflict = (FileConflict) listBox.Items[e.Index];
conflict.ReplaceFile = CheckState.Checked == e.NewValue;
}
/// <summary>
/// Handler for the view hak file menu pick, just runs wordpad to view
/// the file (only works for text files obviously).
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void menuItemViewHakFile_Click(object sender, System.EventArgs e)
{
// Just run wordpad to view the file.
FileConflict conflict = (FileConflict) listBox.SelectedItem;
string args = "\"" + conflict.HakFile + "\"";
System.Diagnostics.Process.Start("wordpad.exe", args);
}
/// <summary>
/// Handler for the view module file menu pick, just runs wordpad to view
/// the file (only works for text files obviously).
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void menuItemViewModFile_Click(object sender, System.EventArgs e)
{
// Just run notepad to view the file.
FileConflict conflict = (FileConflict) listBox.SelectedItem;
string args = "\"" + conflict.ModuleFile + "\"";
System.Diagnostics.Process.Start("wordpad.exe", args);
}
/// <summary>
/// Handler ofr the context menu's popup event, enables/disables menu items
/// and sets their text appropriately.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void contextMenuView_Popup(object sender, System.EventArgs e)
{
int index = listBox.SelectedIndex;
FileConflict conflict = index >= 0 ? (FileConflict) listBox.SelectedItem : null;
// Menu picks are only enabled if a script source ".NSS" file is selected.
bool enabled = index >= 0 &&
0 == string.Compare(Path.GetExtension(conflict.FileName), ".nss", true, CultureInfo.InvariantCulture);
menuItemViewHakFile.Enabled = enabled;
menuItemViewModFile.Enabled = enabled;
// Glue the selected file name onto the menu picks if they are enabled.
if (enabled)
{
menuItemViewHakFile.Text = StringResources.GetString("ViewHakFileFormat",
listBox.SelectedItem.ToString());
menuItemViewModFile.Text = StringResources.GetString("ViewModFileFormat",
listBox.SelectedItem.ToString());
}
else
{
menuItemViewHakFile.Text = StringResources.GetString("ViewHakFile");
menuItemViewModFile.Text = StringResources.GetString("ViewModFile");
}
}
/// <summary>
/// Handler for the select all button, selects all files for replacing
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonSelectAll_Click(object sender, System.EventArgs e)
{
listBox.BeginUpdate();
for (int i = 0; i < listBox.Items.Count; i++)
listBox.SetItemChecked(i, true);
listBox.EndUpdate();
}
/// <summary>
/// Handler for the clear all button, clears all files to prevent replacement.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonClearAll_Click(object sender, System.EventArgs e)
{
listBox.BeginUpdate();
for (int i = 0; i < listBox.Items.Count; i++)
listBox.SetItemChecked(i, false);
listBox.EndUpdate();
}
#endregion
}
}

View File

@@ -0,0 +1,214 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="label1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="label1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonContinue.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="buttonContinue.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonContinue.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="button2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="button2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="button2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="pictureBox.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="pictureBox.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="pictureBox.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="listBox.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="listBox.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="listBox.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="contextMenuView.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="contextMenuView.Location" type="System.Drawing.Point, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</data>
<data name="contextMenuView.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuItemViewHakFile.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuItemViewHakFile.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuItemViewModFile.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuItemViewModFile.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonSelectAll.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="buttonSelectAll.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonSelectAll.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonClearAll.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="buttonClearAll.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonClearAll.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>(Default)</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.Name">
<value>ReplacingFilesForm</value>
</data>
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>80</value>
</data>
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
</root>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,135 @@
# HIF files may consist of any of the following tags. All tags are optional.
# Tags that support multiple data items may have the data comma separated and/or
# may have multiple entries. If a multiple entries are given for a tag that only
# supports 1 value then the fist value in the file is used. Blank lines are ignored
# as are lines starting with a '#'.
#
# Tag format is
#
# <tag> : <value1>, <value2>, ..., <valuen>
#
# All white space is optional, and tags may also be given on multiple lines
# as follows:
#
# <tag> : <value1>
# <tag> : <value2>
# ...
# <tag> : <valuen>
#
# The following tags are supported:
#
# Title : Allows you to specify the title for the HIF, if the installer is run in
# single HIF mode then the installer's title bar will have the HIF's title,
# or file name if the HIF has no title. The format of the title is
# <HIF TITLE> Module Updater <HIF VERSION>
# Version : Allows you to specify the version number for your content. Modules
# that the HIF is added to are tagged with the version number.
# MinNWNVersion : Allows you to specify the minimum version of NWN that is required,
# and whether your content requies XP1 or XP2. For the NWN version use the
# standard format, i.e. 1.62, 1.31, etc. For the Expansions use XP1 or
# Undrentide for SoU and XP2 or Underdark for HotU. If you list multiple
# requirements separate them by commas. For example:
# MinNWNVersion : 1.62, XP1, XP2
# will make your content require NWN 1.62 or later and both expansions.
# erf : Imports the listed erf files into the module
# module.Hak : haks to add to the module
# module.CustomTlk : Custom tlk file for the module, only 1 value.
# module.Cache : Adds the given scripts the module's script cache.
# module.Areas: Adds the given ResRefs to the module's area list.
# module.OnAcquireItem : Assigns script(s) to handle this module event
# module.OnActivateItem : Assigns script(s) to handle this module event
# module.OnClientEnter : Assigns script(s) to handle this module event
# module.OnClientLeave : Assigns script(s) to handle this module event
# module.OnCutsceneAbort : Assigns script(s) to handle this module event
# module.OnHeartbeat : Assigns script(s) to handle this module event
# module.OnModuleLoad : Assigns script(s) to handle this module event
# module.OnModuleStart : Assigns script(s) to handle this module event
# module.OnPlayerDeath : Assigns script(s) to handle this module event
# module.OnPlayerDying : Assigns script(s) to handle this module event
# module.OnPlayerEquipItem : Assigns script(s) to handle this module event
# module.OnPlayerLevelUp : Assigns script(s) to handle this module event
# module.OnPlayerRest : Assigns script(s) to handle this module event
# module.OnPlayerUnEquipItem : Assigns script(s) to handle this module event
# module.OnPlayerRespawn : Assigns script(s) to handle this module event
# module.OnUnaquireItem : Assigns script(s) to handle this module event
# module.OnUserDefined : Assigns script(s) to handle this module event
# Title for the HIF.
Title : PRC
# Add the PRC pack version and specify at least 1.62 to install.
Version : 3.7.0Alpha
MinNWNVersion: 1.67
# ERF with the required areas.
erf : prc_consortium.erf
# Haks used by the prc pack.
#commented out since its not actually needed in a module and causing CEP conflicts.
# module.Hak : prc_include.hak
module.Hak : prc_2das.hak
module.Hak : prc_scripts.hak
module.Hak : prc_newspellbook.hak
module.Hak : prc_spells.hak
module.Hak : prc_epicspells.hak
module.Hak : prc_psionics.hak
module.Hak : prc_race.hak
module.Hak : prc_textures.hak
module.Hak : prc_misc.hak
module.Hak : prc_craft2das.hak
# Custom tlk used by the prc pack.
module.CustomTlk : prc_consortium.tlk
# Events that need to be wired up.
module.OnAcquireItem : prc_onaquire
module.OnActivateItem : prc_onactivate
module.OnClientEnter : prc_onenter
module.OnClientLeave : prc_onleave
module.OnCutsceneAbort : prc_oncutabort
module.OnHeartbeat : prc_onheartbeat
module.OnModuleLoad : prc_onmodload
module.OnPlayerChat : prc_onplayerchat
module.OnPlayerDeath : prc_ondeath
module.OnPlayerDying : prc_ondying
module.OnPlayerEquipItem : prc_equip
module.OnPlayerLevelUp : prc_levelup
module.OnPlayerRest : prc_rest
module.OnPlayerRespawn : prc_onrespawn
module.OnUnaquireItem : prc_onunaquire
module.OnPlayerUnequipItem : prc_unequip
module.OnUserDefined : prc_onuserdef
# Cache PRC scripts for better performance.
module.Cache : prc_onaquire
module.Cache : prc_onactivate
module.Cache : prc_onenter
module.Cache : prc_onleave
module.Cache : prc_oncutabort
module.Cache : prc_onheartbeat
module.Cache : prc_onmodload
module.Cache : prc_ondeath
module.Cache : prc_ondying
module.Cache : prc_equip
module.Cache : prc_levelup
module.Cache : prc_rest
module.Cache : prc_onplayerchat
module.Cache : prc_onrespawn
module.Cache : prc_onunaquire
module.Cache : prc_unequip
module.Cache : prc_onuserdef
module.Cache : prc_onhitcast
# Cache bioware summon AI scripts
module.Cache : nw_ch_ac5
module.Cache : nw_ch_ace
module.Cache : nw_ch_ac3
module.Cache : nw_ch_ac4
module.Cache : nw_ch_ac6
module.Cache : nw_ch_ac7
module.Cache : nw_ch_ac8
module.Cache : nw_ch_ac1
module.Cache : nw_ch_ac2
module.Cache : nw_ch_aca
module.Cache : nw_ch_summon_9
module.Cache : nw_ch_acb
module.Cache : nw_ch_acd

View File

@@ -0,0 +1,284 @@
IMPORTANT NOTES
===============
This tool REQUIRES version 1.0 of the Microsoft .NET Framework,
this is available for download at:
http://www.microsoft.com/downloads/details.aspx?familyid=D7158DEE-A83F-4E21-B05A-009D06457787&displaylang=en
GENERAL INFORMATION
===================
HakInstaller is a tool that allows you to easily add player based haks
to modules. A player based hak is a hak whose contents are intended
for the player, rather than the module designer. For example the PRC
Consortium's PRC pack. I wrote this tool because I got sick of having
to add these haks to module after module as I played them, and having
to remember to do all of the steps correctly (often forgetting one).
Two versions of the tool are included, a windowed version and a command
line version. The command line version is suitable for being invoked
from batch files (or even NWNX) whereas the full UI version is more
suitable to the individual player.
The application takes a 'hak' (in this case a 'hak' is a collection of
one or more hak, erf, and tlk files, and adds/merges them (as appropriate)
to a module, and also sets up any required module event that the hak
may need to handle to work correctly. If the module already has scripts
attached to the events, then the tool will create a new script that
executes both the old script and the haks's script. In a nutshell, this
allows you to add haks to a module by pressing a button and letting the
tool do all the work, rather than you having to go through a checklist
of steps, possibly missing one.
The tool gets the configuration information for a hak from hif files
(hak information), these files are text files that contain configuration
information, THEY SHOULD BE PLACED IN YOUR NWN HAK DIRECTORY, the tool
will look for them there. The tool comes with hif files for the PRC
Consortium's PRC pack, my spell pak, and the PRC merge version of my
spell pak, but there is nothing to stop anyone else from making hif
definitions for other haks.
If all you want to do is use the tool to add the PRC pack or spell pak
to modules, just copy the hif files into NWN's hak directory and double
click HakInstaller.exe.
To use the windows UI version just double click on HakInstaller.exe,
it will present you with a list of haks that have hif files on the left
and a list of all of your installed modules on the right, check the haks
that you want to install and check the modules you want them installed
in and click install, it will then add/merge the hak content to all of
your selected modules. If there are any file conflicts (for example,
suppose you merge the prc pack hak into a module that has changed some
spell scripts, a warning dialog will be displayed showing you the files
that are going to be overwritten asking for your permission to overwrite
them. You can check the files you want to overwrite in the module (by
default they are all checked) and you can view the hak / module scripts
in wordpad to compare them. To view a script file, select it then right
click in the list box, you will get a menu.
To use the command line version run it from the command line, passing it
all the .hif and .mod files you want to use on the command line. It will
then do the same thing as the windows UI version, except that it will not
warn you about overwriting files, it will just overwrite them.
Both versions of the tool read your NWN installation information from
the windows registry, if you are running the tools on a PC other than the
one that NWN is installed on (or you are running them under mono on linux)
then you must use the -n<path> command line option to specify the install
path of NWN.
FOR CONTENT CREATORS
====================
While my utility was designed for the spell pak (now deceased) and PRC
pack, anyone making player based haks can take advantage of the tool to
install their content into modules. All you need to do is write the
HIF describing the content of your 'hak' and package that along with
the installer (just give me credit for the installer) in your shipping
file (zip, rar, whatever).
To facilitate this, version 2.0 (and later) support running in single HIF
mode; this is done by passing a HIF on the command line. If this is done
the list box of HIFs will not be shown, instead the application will reskin
to just list modules and the title of the application will be your HIFs
Title, or the file name if the HIF has no title.
To make support easier the installer will validate all of the files described
in your hif are present on disk, if for some reason they aren't then an
error message will be displayed and the HIF will not be added to the list of
HIFs (if in single HIF mode the application will just exit).
You can also specify a minimum NWN version, and whether you require XP1 and
XP2 installed, if the installed version of NWN does not meet the requirements
you specify then the install will fail as above.
The tool supports tlk file merging between the module's tlk file (if it has
one) and any tlk files contained in the HIF. You may specify multiple tlk
files in the hif, at run time the tool will attempt to build a single tlk file
by merging all of the HIF tlk files with the module tlk file. If this is
successful then that tlk file will be used for the module, if it fails for any
reason (most likely entries being used in duplicate tlk files) it will display
an error message and abort adding the content to the module. In order for the
merge to succeed, none of the tlk files can have strings at the same location,
for example if tlk1.tlk contains "foo" at entry 100 and "tlk2.tlk" contains
"bar" at entry 100 then the merge will fail. The lone exception to this is
that multiple tlk files may have "Bad Strref" at location 0, it will ignore
all of the duplicates in this case.
The tool supports 2da file merging between the module's haks (if any) and
any 2da's contained in the HIF. The tool will attempt to generate a merge
hak (and place it at the top of the hak list) containing merged copies of
all of the conflicting 2da's. If for some reason any of the 2da's cannot
be successfully merged the tool will still attempt to merge any other conflicting
2da's.
If a merge hak and/or tlk were generated it will tell the user so that they
can delete the files when they are finished with the module.
VERSION HISTORY
===============
2.5 - Added support for 1.69 patch XP3.bif/key also for the OnPlayerChat
event.
2.2 - Enhanced the 2da merging logic. The installer can now merge changes
made by multiple haks to the same row as long as the row is a modified bioware
row and no 2 haks change the same column with a different value. Various
bug fixes.
2.0 - Various bug fixes.
2.0 Beta 2 - Various bug fixes, CEP HIF.
2.0 - Added Title, Version, and MinNWNVersion keywords to the HIF scripts.
Changes to support a single HIF skin if a HIF is passed on the command line,
allowing content creators to use the installer as their dedicated "install"
program to update modules. Added HIF content checking, the installer now
validates that all files described in the HIF are actually present on disk,
displaying an error message (and not installing the HIF) if they are not.
Added the ability of HIFs to specify a minimum required version of NWN, the
HIF will not install if the user's version of NWN is less than the required
version.
Added support for merging conflicting tlk files and creating a merge tlk file
to be used by the module.
Added support for merging conflicting 2da files across all HIFs and creating
a merge hak containing merged versions of the 2da's.
2.4 - Synced version with module updater, fixed bug to make the installer work
with 2da items with spaces in them.
1.41 - Recompiled for .NET Framework 1.1. Fixed a bug adding heartbeat
events.
1.4 - Added support for adding areas to modules in the HIF. Added support
for BMU music files in erfs/haks/modules.
1.32 Fixed duplicate key bug.
1.31 Fixed a bug that caused the window to not come up centered. Changed
the content check list box to be single selection, since this was causing
some confusion.
1.3 Changed to add any areas in added content to the module's area list to fix
a bug introduced in 1.62. Added support for the OC/XP1/XP2. Changed the
installer check to see if content has already been installed in modules, and
warn the user before continuing. Added extensive overwrite checking, it
will now check the module and all it's haks vs. the content being added
to make sure nobody overwrites anybody else. Fixed the bug with GFF
versions. Fixed the bug with "imput string is not in the correct format".
1.22 Fixed a bug that cause an exception if you did not overwrite replaced
files.
1.21 Updates HIF files for PRC pack 1.9
1.2 Changed the replace file dialog so that you can selectively replace files,
and view script files (.NSS) in wordpad.
1.1 Fixed a bug that made certain ExoLoc strings crash the application.
1.0 Initial version
APPENDIX 1 - SAMPLE HIF FILE
============================
The sample hif files contain comments in them that document the layout and
syntax of a hif file, this appendix assumes that you have already looked
at one of the sample hif files, I will go over the prc_consortium.hif file
here and show what is happening.
First, here is the contents of the hif file (minus the giant comment at the
top describing the format of hif files):
# Custom Content title and version number.
Title : PRC Pack
Version : 2.0
# Specify that the user must have both expansions installed and 1.62
MinNWNVersion : 1.62, XP1, XP2
# Import there ERF files into the module.
erf : prc_consortium.erf
# Haks and custom tlk's used by the module.
module.Hak : prc_consortium.hak
module.CustomTlk : prc_consortium.tlk
# Events that need to be wired up.
module.OnClientEnter : prc_onenter
module.OnPlayerLevelUp : prc_levelup
module.OnPlayerEquipItem : prc_equip
module.OnPlayerUnequipItem : prc_unequip
# Cache PRC scripts for better performance.
module.Cache : screen_targets
module.Cache : prc_caster_level
module.Cache : set_damage_type
module.Cache : change_metamagic
module.Cache : add_spell_dc
module.Cache : add_spell_penetr
module.Cache : add_damage
module.Cache : add_damageshield
module.Cache : add_randdamage
module.Cache : add_healing
module.Cache : add_hitpoints
First there is a single erf given, prc_consortium.erf. The tool merges the
contents of all erf files into the module, so all of the files in
prc_consortium.erf will be added to the module.
It will then add prc_consortium.hak to the module's hak list (if multiple
haks are specified they will be added in the order they are in the hif
file, which means hak files listed first will take precedence over hak files
listed later).
prc_consortium.tlk will be set as the module's custom tlk file.
The scripts prc_onenter, prc_levelup, prc_equip, and prc_unequip will be added
to the OnClientEnter, OnPlayerLevelUp, OnPlayerEquipItem, and OnPlayerUnequipItem
module events. If any of these events already have scripts attached, then
the tool will create a new script, naming it "hif_<EventName>" (truncating to
16 characters) and will then add ExecuteScript() calls to execute the old
script and the appropriate PRC script.
You will notice that the above steps are what the PRC pack's read me tell you to
do to each module you add the pack to.
One final step has been added, which is a speed optomization. The scripts
screen_targets, prc_caster_level, set_damage_type, change_metamagic,
add_spell_dc, add_spell_penetr, add_damage, add_damageshield, add_randdamage,
add_healing, and add_hitpoints will be added to the module's script cache.
This step is not strictly required to get the PRC pack to work, however it
will increase the speed at which the pack runs. These scripts are called
internally when any spell (or some feats) are used, adding them to the cache
prevents the NWN engine from having to load them each time you cast a spell.
CAVEATS
The tool does not update the palette files, so any blueprint templates imported
from erf's will not show up in the toolset until you right click in the
appropriate custom palette and do a refresh.
The tool DOES NOT rebuild the module like the BioWare toolset
does whenever you add a hak. If a hak/erf that the hif is importing contains
a modified BioWare script include file, then the module will not work properly
without being recompiled in the toolset. For haks like this you will still
have to open the module in the toolset after HakInstaller is done and do a
rebuild of the module. For example if you use the tool to import a hif that
overwrote the include file for the default combat AI, none of the changes would
take effect on any of the module's creatures until you opened the module in
the toolset and did a build (the include file is there but since no scrips have
been recompiled none of them know about the changes).

View File

@@ -0,0 +1,273 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Globalization;
using System.Threading;
using System.Windows.Forms;
using HakInstaller.Utilities;
using NWN;
namespace HakInstaller
{
/// <summary>
/// This is the main form of the HakInstaller application.
/// </summary>
public class SingleHIFInstallForm : InstallFormBase
{
#region public methods/properties.
/// <summary>
/// Class constructor
/// </summary>
public SingleHIFInstallForm()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
SetLabels(labelVersion, labelPath);
// Validate our HIF to make sure we can really install.
ValidateHIF();
// Save the HIF title as the title for our form.
Text = StringResources.GetString("SingleHIFTitle", hif.Title,
hif.VersionText);
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
#region Windows Form Designer generated code
private System.Windows.Forms.Label labelVersion;
private System.Windows.Forms.Button buttonInstall;
private System.Windows.Forms.Button buttonCancel;
private System.Windows.Forms.CheckedListBox checkedModules;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label labelPath;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(SingleHIFInstallForm));
this.labelVersion = new System.Windows.Forms.Label();
this.buttonInstall = new System.Windows.Forms.Button();
this.buttonCancel = new System.Windows.Forms.Button();
this.checkedModules = new System.Windows.Forms.CheckedListBox();
this.label2 = new System.Windows.Forms.Label();
this.labelPath = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// labelVersion
//
this.labelVersion.Location = new System.Drawing.Point(24, 8);
this.labelVersion.Name = "labelVersion";
this.labelVersion.Size = new System.Drawing.Size(240, 16);
this.labelVersion.TabIndex = 0;
//
// buttonInstall
//
this.buttonInstall.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonInstall.Enabled = false;
this.buttonInstall.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.buttonInstall.Location = new System.Drawing.Point(24, 280);
this.buttonInstall.Name = "buttonInstall";
this.buttonInstall.Size = new System.Drawing.Size(64, 24);
this.buttonInstall.TabIndex = 6;
this.buttonInstall.Text = "&Install";
this.buttonInstall.Click += new System.EventHandler(this.buttonInstall_Click);
//
// buttonCancel
//
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.buttonCancel.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.buttonCancel.Location = new System.Drawing.Point(104, 280);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(64, 24);
this.buttonCancel.TabIndex = 7;
this.buttonCancel.Text = "&Close";
this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
//
// checkedModules
//
this.checkedModules.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.checkedModules.CheckOnClick = true;
this.checkedModules.Location = new System.Drawing.Point(24, 96);
this.checkedModules.Name = "checkedModules";
this.checkedModules.Size = new System.Drawing.Size(320, 169);
this.checkedModules.Sorted = true;
this.checkedModules.TabIndex = 5;
this.checkedModules.ThreeDCheckBoxes = true;
this.checkedModules.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.checkedModules_ItemCheck);
//
// label2
//
this.label2.Location = new System.Drawing.Point(24, 72);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(328, 16);
this.label2.TabIndex = 4;
this.label2.Text = "Select the &modules you want to update to use the PRC pack:";
//
// labelPath
//
this.labelPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.labelPath.Location = new System.Drawing.Point(24, 32);
this.labelPath.Name = "labelPath";
this.labelPath.Size = new System.Drawing.Size(320, 16);
this.labelPath.TabIndex = 1;
//
// SingleHIFInstallForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.CancelButton = this.buttonCancel;
this.ClientSize = new System.Drawing.Size(368, 318);
this.Controls.Add(this.labelPath);
this.Controls.Add(this.label2);
this.Controls.Add(this.checkedModules);
this.Controls.Add(this.buttonInstall);
this.Controls.Add(this.labelVersion);
this.Controls.Add(this.buttonCancel);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MinimumSize = new System.Drawing.Size(376, 352);
this.Name = "SingleHIFInstallForm";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "title goes here";
this.SizeChanged += new System.EventHandler(this.InstallForm_SizeChanged);
this.Load += new System.EventHandler(this.InstallForm_Load);
this.ResumeLayout(false);
}
#endregion
#region private fields/properties/methods
private HakInfo hif;
/// <summary>
/// Validates the single HIF and throws an EntryPointNotFoundException
/// to exit the application if it does not validate.
/// </summary>
private void ValidateHIF()
{
hif = new HakInfo(NWNInfo.GetFullFilePath(MainForm.Hif));
// Validate the PRC pack HIF, if validation fails then display
// the error message and exit the app.
string error;
if (!hif.Validate(out error))
{
MessageBox.Show(error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
throw new EntryPointNotFoundException();
}
}
#endregion
#region form event handlers
/// <summary>
/// The form's load event handler. Fills in the contents of the form and sets
/// it up.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void InstallForm_Load(object sender, System.EventArgs e)
{
// Fill in the check list boxes.
LoadModuleList(checkedModules);
}
private void InstallForm_SizeChanged(object sender, System.EventArgs e)
{
}
#endregion
#region control event handlers
/// <summary>
/// Event handler for the ItemCheck event on the modules check list box.
/// It enables/disables the install button depending on whether at least
/// one module and hak have been selected.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void checkedModules_ItemCheck(object sender, System.Windows.Forms.ItemCheckEventArgs e)
{
// The install button should be enabled if at least one module and hak
// has been selectted. Note that this event is fired BEFORE the checked
// state of the item changes so we have to check the event args for
// it's new state.
int adjustment = CheckState.Checked == e.NewValue ? 1 : -1;
bool fModuleChecked = checkedModules.CheckedItems.Count + adjustment > 0;
buttonInstall.Enabled = fModuleChecked;
}
/// <summary>
/// Handler for the install button click event. It installs the selected
/// haks in the selected modules.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonInstall_Click(object sender, System.EventArgs e)
{
// Count the total number of .mod/.nwm files selected.
int numModules = 0;
foreach (Module module in checkedModules.CheckedItems)
numModules += module.Modules.Length;
// Create the modules list and fill it in.
string[] modules = new string[numModules];
numModules = 0;
foreach (Module module in checkedModules.CheckedItems)
{
module.Modules.CopyTo(modules, numModules);
numModules += module.Modules.Length;
}
PerformInstall(new HakInfo[1] { hif }, modules);
// Clear the checked state of all modules.
CheckedListBox.CheckedIndexCollection checkedIndeces =
checkedModules.CheckedIndices;
foreach (int index in checkedIndeces)
checkedModules.SetItemChecked(index, false);
}
/// <summary>
/// Cancel button click event, it closes the application.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonCancel_Click(object sender, System.EventArgs e)
{
Application.Exit();
}
#endregion
}
}

View File

@@ -0,0 +1,249 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="labelVersion.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="labelVersion.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="labelVersion.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonInstall.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="buttonInstall.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonInstall.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonCancel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="buttonCancel.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="buttonCancel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="checkedModules.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="checkedModules.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="checkedModules.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="label2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="labelPath.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="labelPath.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="labelPath.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>(Default)</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Name">
<value>SingleHIFInstallForm</value>
</data>
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>80</value>
</data>
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAIAICAAAAAAAACoCAAAJgAAABAQAAAAAAAAaAUAAM4IAAAoAAAAIAAAAEAAAAABAAgAAAAAAAAE
AAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAMDAwADA3MAA8MqmAAQE
BAAICAgADAwMABEREQAWFhYAHBwcACIiIgApKSkAVVVVAE1NTQBCQkIAOTk5AIB8/wBQUP8AkwDWAP/s
zADG1u8A1ufnAJCprQAAADMAAABmAAAAmQAAAMwAADMAAAAzMwAAM2YAADOZAAAzzAAAM/8AAGYAAABm
MwAAZmYAAGaZAABmzAAAZv8AAJkAAACZMwAAmWYAAJmZAACZzAAAmf8AAMwAAADMMwAAzGYAAMyZAADM
zAAAzP8AAP9mAAD/mQAA/8wAMwAAADMAMwAzAGYAMwCZADMAzAAzAP8AMzMAADMzMwAzM2YAMzOZADMz
zAAzM/8AM2YAADNmMwAzZmYAM2aZADNmzAAzZv8AM5kAADOZMwAzmWYAM5mZADOZzAAzmf8AM8wAADPM
MwAzzGYAM8yZADPMzAAzzP8AM/8zADP/ZgAz/5kAM//MADP//wBmAAAAZgAzAGYAZgBmAJkAZgDMAGYA
/wBmMwAAZjMzAGYzZgBmM5kAZjPMAGYz/wBmZgAAZmYzAGZmZgBmZpkAZmbMAGaZAABmmTMAZplmAGaZ
mQBmmcwAZpn/AGbMAABmzDMAZsyZAGbMzABmzP8AZv8AAGb/MwBm/5kAZv/MAMwA/wD/AMwAmZkAAJkz
mQCZAJkAmQDMAJkAAACZMzMAmQBmAJkzzACZAP8AmWYAAJlmMwCZM2YAmWaZAJlmzACZM/8AmZkzAJmZ
ZgCZmZkAmZnMAJmZ/wCZzAAAmcwzAGbMZgCZzJkAmczMAJnM/wCZ/wAAmf8zAJnMZgCZ/5kAmf/MAJn/
/wDMAAAAmQAzAMwAZgDMAJkAzADMAJkzAADMMzMAzDNmAMwzmQDMM8wAzDP/AMxmAADMZjMAmWZmAMxm
mQDMZswAmWb/AMyZAADMmTMAzJlmAMyZmQDMmcwAzJn/AMzMAADMzDMAzMxmAMzMmQDMzMwAzMz/AMz/
AADM/zMAmf9mAMz/mQDM/8wAzP//AMwAMwD/AGYA/wCZAMwzAAD/MzMA/zNmAP8zmQD/M8wA/zP/AP9m
AAD/ZjMAzGZmAP9mmQD/ZswAzGb/AP+ZAAD/mTMA/5lmAP+ZmQD/mcwA/5n/AP/MAAD/zDMA/8xmAP/M
mQD/zMwA/8z/AP//MwDM/2YA//+ZAP//zABmZv8AZv9mAGb//wD/ZmYA/2b/AP//ZgAhAKUAX19fAHd3
dwCGhoYAlpaWAMvLywCysrIA19fXAN3d3QDj4+MA6urqAPHx8QD4+PgA8Pv/AKSgoACAgIAAAAD/AAD/
AAAA//8A/wAAAP8A/wD//wAA////AAAAAADdvLUHtfcH97WYtfe197v3u7W1u/e7B93dAAAAAADdu93C
3eLi4uLd4t3d4t3i3eLcwuLi3eLdvLvdAAAAvLu84uLi3eLd3Ny73Lvc3bvcu93d3cLi4uLi3bu8AAC7
u9zC3eLivLu7tbS7tdy73LW7tdy73d3ivOLdu7UAtbrc4uLi3bu1tbW7tbW7u9a8tbW73LXcvN3i3eG7
uge0u7vd4ty73eL///+83LXdwuLi3bu1u7vcu93cwty1tLS73OLivP//4uL/3Ny73eLd3dzC3eK71rvc
vNzdu7q0rrrc4t3//7vc3Lvd4uK8/93iu9zc4t3Cu7W73Lu71ZGR3Lvi///d3N273eK83eLd////3dy8
3N3d4t21u7W6kbS03OL//9273OLi3dzi/////////93C3Lvcu+K1u7TPkbTc////3dzi3dy7/////927
3P//////4rzc3bS1upGu27vd///ivNy73eLi/+Ldu9273OL////////dtbrVrrS0u9z////du9283Lzd
4v/d3Ny73N3d////4rzcurS0rrTbu93////i3eLd3P///9y73LXc3Lvc4rW71bvVtJGR1bXbtdzd////
/+K1////u92727W73dzdtbrWurvVrs+0uta63Lvd/////9z////d3Na71tvcu9y0tdy11bSRkbTVu9a6
1rvctdy7u93//7vcu7vdu7vdtbW61rS61ZHPtLrVu9a73eL//93/4v//3Lzc3dy73N261bW63LS0rpG0
1bW61tu84v////////+73d3ivN3cvLS1uta0tbS0rtW0uta6td3i/////////7vcwt7i3bvctbS03LTV
tK6utLS03LTcvN3//////93c/////+LdvNy1tNy1urS0kbO0tNW61rrd4v///9284v//////////3LS1
utW0tNWurrS0tLS0tN3i//+73P///////////7S127Xbtbq0s66us7S0tLS03eLdu////////////7u0
u9W1urXVtLS0rq6zz7S0tLS7td3//////////920tNW0tNu01bS0tLOui7SztLO0tOL///////////+0
tLS0tLq0tLS0tLSzz4uurbOttLS03f/////////ctLS0tLS01bS0tLS0rbOtka6zs7S0tLS14v/////d
u7S1tNy0tbS1tLS0tLS0rYvP1Yu0tbvcu9y83LzcvNy73bvcB9y73bvcB9y7u9y0i7UA1a7c3d3C3bzi
3cLdwt3ivOLdwt3C3eK84t3dtK7PAAAA1a67u93d4t3d3d3i3d3d4t3d3eLd3eLdtZHPzwAAAAAA1a6u
i4yui66uroaurq6Grq6uhq6uhq7Pz7UAAADwAAAHwAAAA4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAHAAAAD4AAABygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAA
AAAAAAAAAAEAAAABAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAwMDAAMDcwADwyqYABAQEAAgI
CAAMDAwAERERABYWFgAcHBwAIiIiACkpKQBVVVUATU1NAEJCQgA5OTkAgHz/AFBQ/wCTANYA/+zMAMbW
7wDW5+cAkKmtAAAAMwAAAGYAAACZAAAAzAAAMwAAADMzAAAzZgAAM5kAADPMAAAz/wAAZgAAAGYzAABm
ZgAAZpkAAGbMAABm/wAAmQAAAJkzAACZZgAAmZkAAJnMAACZ/wAAzAAAAMwzAADMZgAAzJkAAMzMAADM
/wAA/2YAAP+ZAAD/zAAzAAAAMwAzADMAZgAzAJkAMwDMADMA/wAzMwAAMzMzADMzZgAzM5kAMzPMADMz
/wAzZgAAM2YzADNmZgAzZpkAM2bMADNm/wAzmQAAM5kzADOZZgAzmZkAM5nMADOZ/wAzzAAAM8wzADPM
ZgAzzJkAM8zMADPM/wAz/zMAM/9mADP/mQAz/8wAM///AGYAAABmADMAZgBmAGYAmQBmAMwAZgD/AGYz
AABmMzMAZjNmAGYzmQBmM8wAZjP/AGZmAABmZjMAZmZmAGZmmQBmZswAZpkAAGaZMwBmmWYAZpmZAGaZ
zABmmf8AZswAAGbMMwBmzJkAZszMAGbM/wBm/wAAZv8zAGb/mQBm/8wAzAD/AP8AzACZmQAAmTOZAJkA
mQCZAMwAmQAAAJkzMwCZAGYAmTPMAJkA/wCZZgAAmWYzAJkzZgCZZpkAmWbMAJkz/wCZmTMAmZlmAJmZ
mQCZmcwAmZn/AJnMAACZzDMAZsxmAJnMmQCZzMwAmcz/AJn/AACZ/zMAmcxmAJn/mQCZ/8wAmf//AMwA
AACZADMAzABmAMwAmQDMAMwAmTMAAMwzMwDMM2YAzDOZAMwzzADMM/8AzGYAAMxmMwCZZmYAzGaZAMxm
zACZZv8AzJkAAMyZMwDMmWYAzJmZAMyZzADMmf8AzMwAAMzMMwDMzGYAzMyZAMzMzADMzP8AzP8AAMz/
MwCZ/2YAzP+ZAMz/zADM//8AzAAzAP8AZgD/AJkAzDMAAP8zMwD/M2YA/zOZAP8zzAD/M/8A/2YAAP9m
MwDMZmYA/2aZAP9mzADMZv8A/5kAAP+ZMwD/mWYA/5mZAP+ZzAD/mf8A/8wAAP/MMwD/zGYA/8yZAP/M
zAD/zP8A//8zAMz/ZgD//5kA///MAGZm/wBm/2YAZv//AP9mZgD/Zv8A//9mACEApQBfX18Ad3d3AIaG
hgCWlpYAy8vLALKysgDX19cA3d3dAOPj4wDq6uoA8fHxAPj4+ADw+/8ApKCgAICAgAAAAP8AAP8AAAD/
/wD/AAAA/wD/AP//AAD///8AAPfs9+z37Pfs9+z37PfsAOyFX4Vf7OyFX7KBsrqyuuxfhV8H7OxfhV+B
soGyurKFhV//7IVfhV+FX2uygbK6X1/s/1+FX+yFX+zsa7KBsl+F7P8HXwfsX+zsX+xrsoFfX4UH/wcH
7IoH7F+F7GuyX4Wmhez//wdfB+yFX1/shV9fiqaKX4pfigfsX4WF7KaFhaaKpuwHBwf/7F+FX+yKX1+K
pors////BwdfhV/spoWFpoqm7P+8Bwf//wcH7IVfX4qmiuwHB7z///8HpoqmX4WmiqbsvP/////spoqm
iqbss7Sz/////we0s7SztLPsAOz37Pfs9+z37Pfs9+z3AIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAAA=
</value>
</data>
</root>

View File

@@ -0,0 +1,202 @@
//
// This code was pulled from www.developerfusion.com
//
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows;
using System.Collections;
namespace System
{
public class SystemMenu : ArrayList
{
public const int BYPOSITION = 0x400;
public const int REMOVE = 0x1000;
public const int CHECKED = 0x8;
public const int APPEND = 0x100;
public const int SEPERATOR = 0x800;
public const int GRAYED = 0x1;
public const int DISABLED = 0x2;
public const int BITMAP = 0x4;
public const int RADIOCHECK = 0x200;
public const int BREAK = 0x40;
public const int BARBREAK = 0x20;
[DllImport("user32.dll")]
private static extern int GetSystemMenu(int HWND);
[DllImport("user32.dll")]
private static extern int AppendMenu(int MenuHandle, int Props, int FlagsW, string text);
[DllImport("user32.dll")]
private static extern int RemoveMenu(int MenuHandle, int pos, int Flags);
[DllImport("user32.dll")]
private static extern int GetMenuItemID(int Menuhandle, int pos);
[DllImport("user32.dll")]
private static extern int ModifyMenu(int MHandle, int pos,int flags,int newPos,string text);
private Form form;
private int SystemMenuHandle;
public int Handle
{
get { return SystemMenuHandle; }
}
public SystemMenu(Form f) : base(0)
{
form = f;
SystemMenuHandle = GetSystemMenu(form.Handle.ToInt32());
}
public void Add(SystemMenuItem MI)
{
base.Add(MI);
if(MI.Text == "-")
{
AppendMenu(SystemMenuHandle,SystemMenu.SEPERATOR,MI.MenuID,null);
}
else
{
AppendMenu(SystemMenuHandle,MI.Flags,MI.MenuID,MI.Text);
}
}
public void Remove(SystemMenuItem MI)
{
base.Remove(MI);
RemoveMenu(SystemMenuHandle, MI.MenuID, 0);
}
public void ModifyMenuPosition(int pos, int flags, string text)
{
ModifyMenu(this.Handle, pos, flags|SystemMenu.BYPOSITION, pos, text);
}
public new SystemMenuItem this[int index]
{
get { return (SystemMenuItem)base[index]; }
set
{
if(value!=null)
{
SystemMenuItem MI = (SystemMenuItem)value;
ModifyMenu(this.Handle, this[index].MenuID, MI.Flags, MI.MenuID, MI.Text); }
base[index] = (object)value;
}
}
}// end of class SystemMenu
public class SystemMenuItem : MenuItem
{
[DllImport("user32.dll")]
private static extern int GetSystemMenu(int HWND);
[DllImport("user32.dll")]
private static extern int AppendMenu(int MenuHandle, int Props, int FlagsW, string text);
[DllImport("user32.dll")]
private static extern int RemoveMenu(int MenuHandle, int pos, int Flags);
[DllImport("user32.dll")]
private static extern int GetMenuItemID(int Menuhandle, int pos);
[DllImport("user32.dll")]
private static extern int ModifyMenu(int MHandle, int pos,int flags,int newPos,string text);
[DllImport("user32.dll")]
private static extern int CheckMenuItem(int HMenu, int pos, int flags);
private int flags = 0;
public int Flags
{
get { return flags; }
}
private SystemMenu menu;
public SystemMenuItem(string text, SystemMenu SM)
{
base.Text = text;
menu = SM;
if(text == "-")
this.flags = SystemMenu.SEPERATOR;
}
public new int MenuID
{
get { return base.MenuID; }
}
public SystemMenuItem CloneMenu(int should_be_null)
{
should_be_null = 0;
return new SystemMenuItem(this.Text, menu);
}
public new bool Checked
{
get { return base.Checked; }
set
{
base.Checked = value;
if(base.Checked)
{
flags = (flags|SystemMenu.CHECKED);
CheckMenuItem(menu.Handle, this.MenuID, flags);
}
else
{
flags = (flags&(~SystemMenu.CHECKED));
CheckMenuItem(menu.Handle, this.MenuID, flags);
}
}
}
public new string Text
{
get { return base.Text; }
set
{
base.Text = value;
ModifyMenu(menu.Handle, this.MenuID, this.flags, this.MenuID, base.Text);
}
}
public new bool Break
{
get { return base.Break; }
set
{
base.Break = value;
if(base.Break)
{
flags = flags|SystemMenu.BREAK;
ModifyMenu(menu.Handle, this.MenuID, this.flags, this.MenuID, base.Text);
}
else
{
flags = flags&(~SystemMenu.BREAK);
ModifyMenu(menu.Handle, this.MenuID, this.flags, this.MenuID, base.Text);
}
}
}
public new bool BarBreak
{
get { return base.BarBreak; }
set
{
base.BarBreak = value;
if(base.BarBreak)
{
flags = flags|SystemMenu.BARBREAK;
ModifyMenu(menu.Handle, this.MenuID, this.flags, this.MenuID, base.Text);
}
else
{
flags = flags&(~SystemMenu.BARBREAK);
ModifyMenu(menu.Handle, this.MenuID, this.flags, this.MenuID, base.Text);
}
}
}
}//end of class SystemMenuItem
}

View File

@@ -0,0 +1,632 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Runtime.InteropServices;
namespace NWN.FileTypes
{
/// <summary>
/// This class represents a tlk file. It contains all of the functionality necessary to
/// merge tlk files.
/// </summary>
public class Tlk
{
#region public nested classes
/// <summary>
/// Flags for the ResRef data.
/// </summary>
[Flags] public enum ResRefFlags: int
{
None = 0x0000,
TextPresent = 0x0001,
SoundPresent = 0x0002,
SoundLengthPresent = 0x0004,
}
/// <summary>
/// This class defines an entry in the tlk file. It contains all of the data for
/// the entry.
/// </summary>
public class TlkEntry
{
#region public properties/methods
/// <summary>
/// Gets/sets the entrie's flags
/// </summary>
public ResRefFlags Flags { get { return flags; } set { flags = value; } }
/// <summary>
/// Gets/sets the sound ResRef
/// </summary>
public string SoundResRef
{
get { return soundResRef; }
set
{
soundResRef = value;
if (string.Empty != soundResRef)
flags |= ResRefFlags.SoundPresent;
else
flags &= ~ResRefFlags.SoundPresent;
}
}
/// <summary>
/// Gets/sets the volume variance.
/// </summary>
public int VolumnVariance { get { return volumeVariance; } set { volumeVariance = value; } }
/// <summary>
/// Gets/sets the pitch variance.
/// </summary>
public int PitchVariance { get { return pitchVariance; } set { pitchVariance = value; } }
/// <summary>
/// Gets/sets the sound length.
/// </summary>
public float SoundLength
{
get { return soundLength; }
set
{
soundLength = value;
if (0 != soundLength)
flags |= ResRefFlags.SoundLengthPresent;
else
flags &= ~ResRefFlags.SoundLengthPresent;
}
}
/// <summary>
/// Gets/sets the entry text.
/// </summary>
public string Text
{
get { return text; }
set
{
text = value;
if (string.Empty != text)
flags |= ResRefFlags.TextPresent;
else
flags &= ~ResRefFlags.TextPresent;
}
}
/// <summary>
/// Returns true if the tlk entry is empty.
/// </summary>
public bool IsEmpty { get { return flags == ResRefFlags.None; } }
/// <summary>
/// Default constructor
/// </summary>
public TlkEntry()
{
flags = ResRefFlags.None;
volumeVariance = 0;
pitchVariance = 0;
soundLength = 0;
soundResRef = string.Empty;;
this.text = string.Empty;
}
/// <summary>
/// Constuctor to create an entry for a string.
/// </summary>
/// <param name="text">The text.</param>
public TlkEntry(string text)
{
flags = ResRefFlags.TextPresent;
volumeVariance = 0;
pitchVariance = 0;
soundLength = 0;
soundResRef = string.Empty;
this.text = text;
}
#endregion
#region private fields/properties/methods
private ResRefFlags flags;
public int volumeVariance;
public int pitchVariance;
public float soundLength;
public string soundResRef;
public string text;
#endregion
}
#endregion
#region public properties
/// <summary>
/// Gets the tlk key to be used in dictionary lookups, this is a lower case version
/// of the name.
/// </summary>
public string Key { get { return name.ToLower(); } }
/// <summary>
/// Gets the name of the tlk file, the name does not include any path information.
/// </summary>
public string Name { get { return name; } }
/// <summary>
/// Gets the number of entries in the tlk file.
/// </summary>
public int Count { get { return header.stringCount; } }
/// <summary>
/// Does a lookup in the tlk file, returning the entry for the specified index.
/// </summary>
public TlkEntry this[int index]
{
get
{
// If the index is out of range return null.
if (index >= header.stringCount || index < 0) return null;
// Create a TlkEntry for the entry
TlkEntry entry = new TlkEntry();
entry.PitchVariance = resRefs[index].pitchVariance;
entry.SoundLength = resRefs[index].soundLength;
entry.VolumnVariance = resRefs[index].volumeVariance;
entry.SoundResRef = resRefs[index].soundResRef;
entry.Text = strings[index];
entry.Flags = (ResRefFlags) resRefs[index].flags;
// Return the created entry.
return entry;
}
set
{
// Make sure the index is within range.
if (index >= header.stringCount || index < 0) throw new IndexOutOfRangeException();
resRefs[index].pitchVariance = value.PitchVariance;
resRefs[index].soundLength = value.SoundLength;
resRefs[index].volumeVariance = value.VolumnVariance;
resRefs[index].soundResRef = value.SoundResRef;
resRefs[index].flags = (int) value.Flags;
strings[index] = value.Text;
}
}
#endregion
#region public methods
/// <summary>
/// Default constructor.
/// </summary>
/// <param name="count">The initial number of entries in the tlk file.</param>
public Tlk(int count)
{
name = string.Empty;
header = new TlkHeader();
resRefs = new RawResRef[count];
strings = new string[count];
header.fileType = tlkFile;
header.fileVersion = tlkVersion;
header.stringCount = count;
header.stringOffset = 0;
for (int i = 0; i < count; i++)
{
resRefs[i] = new RawResRef();
resRefs[i].flags = (int) ResRefFlags.None;
resRefs[i].offsetToString = 0;
resRefs[i].pitchVariance = 0;
resRefs[i].soundLength = 0;
resRefs[i].soundResRef = string.Empty;
resRefs[i].stringSize = 0;
resRefs[i].volumeVariance = 0;
strings[i] = string.Empty;
}
}
/// <summary>
/// Returns true if the index'th entry is empty.
/// </summary>
/// <param name="index">The index of the entry to test</param>
/// <returns>True if the entry is empty false if it is not</returns>
public bool IsEmpty(int index)
{
if (index >= header.stringCount || index < 0) throw new ArgumentOutOfRangeException();
return (int) ResRefFlags.None == resRefs[index].flags || string.Empty == strings[index];
}
/// <summary>
/// Pads the tlk to have at least the specified number of entries. If the tlk file
/// has less entries than what is given, blank entries are inserted to pad.
/// </summary>
/// <param name="length">The new number of entries</param>
public void Pad(int length)
{
// If the tlk file is larger than the pad count then do nothing.
if (header.stringCount >= length) return;
// Add blank entries to the tlk file to pad.
RawResRef[] padded = new RawResRef[length];
resRefs.CopyTo(padded, 0);
for (int i = resRefs.Length; i < padded.Length; i++)
{
padded[i].flags = 0;
padded[i].offsetToString = 0;
padded[i].pitchVariance = 0;
padded[i].stringSize = 0;
padded[i].volumeVariance = 0;
padded[i].soundLength = 0.0f;
padded[i].soundResRef = string.Empty;
}
string[] paddedStrings = new string[length];
paddedStrings.CopyTo(strings, 0);
for (int i = strings.Length; i < paddedStrings.Length; i++)
paddedStrings[i] = string.Empty;
// Save the new RawResRef array and update the number of entries in
// the header.
header.stringCount = length;
resRefs = padded;
strings = paddedStrings;
}
/// <summary>
/// Saves the tlk file, the tlk file must have been given a name or this will
/// throw an InvalidOperationException.
/// </summary>
public void Save()
{
if (string.Empty == name) throw new InvalidOperationException();
SaveAs(name);
}
/// <summary>
/// Saves the tlk file under the specified file name.
/// </summary>
/// <param name="fileName">The name in which to save the file.</param>
public void SaveAs(string fileName)
{
using (FileStream writer =
new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
// Figure out how big of a buffer we need to store all of the string data.
int count = 0;
foreach (string s in strings)
count += s.Length;
// Copy all of the string data to a byte array.
int stringDataIndex = 0;
byte[] stringData = new byte[count];
for (int i = 0; i < resRefs.Length; i++)
{
// Ignore entries w/o strings.
if (0 == ((int) ResRefFlags.TextPresent & resRefs[i].flags) ||
string.Empty == strings[i])
{
// Blank the string size and offset just in case to keep
// the tlk file clean.
resRefs[i].stringSize = 0;
resRefs[i].offsetToString = 0;
continue;
}
// Copy the string bytes to the byte array.
for (int j = 0; j < strings[i].Length; j++)
stringData[stringDataIndex + j] = (byte) strings[i][j];
// Save the string offset and size in the ResRef structure.
resRefs[i].offsetToString = stringDataIndex;
resRefs[i].stringSize = strings[i].Length;
// Increment the buffer index to the next free byte.
stringDataIndex += strings[i].Length;
}
// Set the offset to the string data in the header and write the header out.
header.stringOffset = headerSize + (resRefs.Length * RawResRefSize);
byte[] buffer = RawSerialize(header);
writer.Write(buffer, 0, buffer.Length);
// Write all of the ResRef entries out.
for (int i = 0; i < resRefs.Length; i++)
{
buffer = RawSerialize(resRefs[i]);
writer.Write(buffer, 0, buffer.Length);
}
// Write the raw string data out.
writer.Write(stringData, 0, stringData.Length);
}
this.name = fileName;
}
#endregion
#region public static methods
/// <summary>
/// Creates a Tlk object for the specified tlk file.
/// </summary>
/// <param name="fileName">The tlk file</param>
/// <returns>A Tlk object representing the tlk file</returns>
public static Tlk LoadTlk(string fileName)
{
// Open the tlk file.
Tlk tlk = new Tlk();
using (FileStream reader =
new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
// Save the name of the tlk file.
FileInfo info = new FileInfo(fileName);
tlk.name = info.Name;
// Read the header and decode it.
byte[] buffer = new byte[Tlk.headerSize];
if (reader.Read(buffer, 0, buffer.Length) != buffer.Length)
ThrowException("Tlk file {0} is corrupt", fileName);
tlk.DeserializeHeader(buffer);
// Do a reality check on the tlk file.
if (tlk.header.fileType != tlkFile)
ThrowException("{0} is not a tlk file", fileName);
if (tlk.header.fileVersion != tlkVersion)
ThrowException("{0} is an unsupported tlk file", fileName);
// Read the RawResRef array and decode it.
int size = tlk.header.stringCount * Tlk.RawResRefSize;
buffer = new byte[size];
if (reader.Read(buffer, 0, buffer.Length) != buffer.Length)
ThrowException("Tlk file {0} is corrupt", fileName);
tlk.DeserializeRawResRefs(buffer);
// Read the raw string data.
buffer = new byte[reader.Length - tlk.header.stringOffset];
if (reader.Read(buffer, 0, buffer.Length) != buffer.Length)
ThrowException("Tlk file {0} is corrupt", fileName);
// Load the strings from the raw bytes into our string array.
tlk.strings = new string[tlk.header.stringCount];
for (int i = 0; i < tlk.header.stringCount; i++)
tlk.strings[i] = tlk.GetStringFromBuffer(buffer, i);
}
return tlk;
}
/// <summary>
/// Merges 2 tlk objects, saving the results in the specified tlk file. The merge tlk file
/// is just added to the end of the source tlk file. Unlike 2da merging, the merge tlk
/// does not overwrite any entries in the source tlk. Tlk entries are not row critical like
/// 2da rows (since tlk strings are not saved in character files), so exact positioning of
/// them is not as critical.
/// </summary>
/// <param name="source">The source tlk</param>
/// <param name="merge">The merge tlk</param>
/// <param name="outFile">The name of the output tlk file</param>
/// <returns>The offset of the first entry of the merge tlk in the output file. This offset
/// can be used to fixup 2da entries that refer to the merge tlk.</returns>
public static int MergeTlk(Tlk source, Tlk merge, string outFile)
{
/*
// Open the output tlk.
using (FileStream writer =
new FileStream(outFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
// Build a RawResRef array containing both the source and merge RawResRef arrays. Then
// loop through all of the merge entries and fixup the string offsets to point
// past the source data to the merge data, which we will glue on the end of the
// source data.
RawResRef[] outResRefs = new RawResRef[source.resRefs.Length + merge.resRefs.Length];
source.resRefs.CopyTo(outResRefs, 0);
merge.resRefs.CopyTo(outResRefs, source.resRefs.Length);
for (int i = source.resRefs.Length; i < outResRefs.Length; i++)
{
if (0 != (outResRefs[i].flags & (int) ResRefFlags.textPresent))
outResRefs[i].offsetToString += source.stringBytes.Length;
}
// Build a header with a string count of all of the source + merge strings, then
// write it out.
TlkHeader headerOut = source.header;
headerOut.stringCount += merge.header.stringCount;
headerOut.stringOffset = headerSize + (outResRefs.Length * RawResRefSize);
byte[] headerBytes = RawSerialize(headerOut);
writer.Write(headerBytes, 0, headerBytes.Length);
// Write the RawResRef data.
for (int i = 0; i < outResRefs.Length; i++)
{
byte[] bytes = RawSerialize(outResRefs[i]);
writer.Write(bytes, 0, bytes.Length);
}
// Write the source and merge string data out to the file.
writer.Write(source.stringBytes, 0, source.stringBytes.Length);
writer.Write(merge.stringBytes, 0, merge.stringBytes.Length);
writer.Flush();
writer.Close();
}
// Return the number of strings in the source tlk. Since we glued the merge
// tlk onto the end of the source tlk, this value will be the fixup value we need
// to correct 2da tlk references.
return source.header.stringCount;
*/
return 0;
}
#endregion
#region private methods
/// <summary>
/// Private constructor, instances of this class must
/// </summary>
private Tlk()
{
header = new TlkHeader();
resRefs = null;
strings = null;
}
/// <summary>
/// Gets the index'th string from the raw string buffer.
/// </summary>
/// <param name="buffer">The raw string buffer</param>
/// <param name="index">Index of the string to get</param>
/// <returns>The index'th string</returns>
private string GetStringFromBuffer(byte[] buffer, int index)
{
// If the index is out of range or the text present flag is not set then
// return an empty string.
if (index >= header.stringCount ||
0 == (resRefs[index].flags & (int) ResRefFlags.TextPresent)) return string.Empty;;
// Can't find a converter to build a string from a byte array, so we
// need a local char array to do the dirty work.
int offset = resRefs[index].offsetToString;
char[] chars = new char[resRefs[index].stringSize];
for (int i = 0; i < chars.Length; i++)
chars[i] = (char) buffer[i + offset];
return new string(chars);
}
/// <summary>
/// Deserializes the header from the given byte array.
/// </summary>
/// <param name="bytes">The byte array containing the header</param>
private void DeserializeHeader(byte[] bytes)
{
// Alloc a hglobal to store the bytes.
IntPtr buffer = Marshal.AllocHGlobal(bytes.Length);
try
{
// Copy the data to unprotected memory, then convert it to a TlkHeader
// structure
Marshal.Copy(bytes, 0, buffer, bytes.Length);
object o = Marshal.PtrToStructure(buffer, typeof(TlkHeader));
header = (TlkHeader) o;
}
finally
{
// Free the hglobal before exiting.
Marshal.FreeHGlobal(buffer);
}
}
/// <summary>
/// Deserializes the RawResRef array from the given byte array.
/// </summary>
/// <param name="bytes"></param>
private void DeserializeRawResRefs(byte[] bytes)
{
// Alloc a hglobal to store the bytes.
IntPtr buffer = Marshal.AllocHGlobal(RawResRefSize);
try
{
// Create a RawResRef array for all of the entries and loop
// through the array populating it.
resRefs = new RawResRef[header.stringCount];
for (int i = 0; i < resRefs.Length; i++)
{
// Copy the bytes of the i'th RawResRef to unprotected memory
// and convert it to a RawResRef structure.
Marshal.Copy(bytes, i * RawResRefSize, buffer, RawResRefSize);
object o = Marshal.PtrToStructure(buffer, typeof(RawResRef));
resRefs[i] = (RawResRef) o;
}
}
finally
{
// Free the hglobal before exiting.
Marshal.FreeHGlobal(buffer);
}
}
#endregion
#region private static methods
/// <summary>
/// Throws an NWNException exception
/// </summary>
/// <param name="format">The message format string</param>
/// <param name="args">Message arguments</param>
private static void ThrowException(string format, params object[] args)
{
throw new NWNException(format, args);
}
/// <summary>
/// This method serializes an arbitrary object to a byte array for storage in
/// a tlk file. The object should have it's data mapped to proper positions
/// or the serialization won't work.
/// </summary>
/// <param name="o">The object to serialize</param>
/// <returns></returns>
private static byte[] RawSerialize(object o)
{
// Allocate a hglobal to store the object's data.
int rawsize = Marshal.SizeOf(o);
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
try
{
// Copy the object to unprotected memory, then copy that to a byte array.
Marshal.StructureToPtr(o, buffer, false);
byte[] rawdata = new byte[rawsize];
Marshal.Copy(buffer, rawdata, 0, rawsize);
return rawdata;
}
finally
{
// Free the hglobal before exiting
Marshal.FreeHGlobal(buffer);
}
}
#endregion
#region private nested structures/classes
/// <summary>
/// Structure to store the header of the tlk file. This is mapped directly over the
/// bytes loaded from the tlk file, so we need to declare the mapping explicitly.
/// Using LayoutKind.Sequential should work, but I had problems with it so used
/// Explicit to force the issue. fileType and fileVersions are really strings, but
/// .NET insists on null terminating strings, and these strings are not null terminated.
/// They are both 4 bytes so using Int32 works.
/// </summary>
[StructLayout(LayoutKind.Explicit, Pack=1, CharSet=CharSet.Ansi)] private struct TlkHeader
{
[FieldOffsetAttribute(0)] public Int32 fileType;
[FieldOffsetAttribute(4)] public Int32 fileVersion;
[FieldOffsetAttribute(8)] public Int32 language;
[FieldOffsetAttribute(12)] public Int32 stringCount;
[FieldOffsetAttribute(16)] public Int32 stringOffset;
}
/// <summary>
/// Structure to represent a RawResRef entry in a tlk file. This is mapped directly over the
/// bytes loaded from the tlk file, so we need to declare the mapping explicitly.
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)] private struct RawResRef
{
public Int32 flags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=16)] public String soundResRef;
public Int32 volumeVariance;
public Int32 pitchVariance;
public Int32 offsetToString;
public Int32 stringSize;
public float soundLength;
}
#endregion
#region private fields
private const int headerSize = 20;
private const int RawResRefSize = 40;
private const Int32 tlkFile = 0x204b4c54;
private const Int32 tlkVersion = 0x302e3356;
private string name;
private TlkHeader header;
private RawResRef[] resRefs;
private string[] strings;
#endregion
}
}

View File

@@ -0,0 +1,58 @@
using System;
using System.Reflection;
using System.Resources;
using System.Text;
namespace HakInstaller.Utilities
{
/// <summary>
/// This class is used to manipulate the assembly's string resources.
/// </summary>
public class StringResources
{
#region public static properties/methods
/// <summary>
/// Gets the specified string from the string resource file.
/// </summary>
/// <param name="name">The name of the string to load</param>
/// <returns>The string value</returns>
public static string GetString(string name)
{
return singleton.rm.GetString(name);
}
/// <summary>
/// Gets the specified format string from the string resource file, formatting
/// it with the passed string arguments.
/// </summary>
/// <param name="name">The name of the format string to load</param>
/// <param name="args">The string format arguments</param>
/// <returns>The formatted string value</returns>
public static string GetString(string name, params object[] args)
{
// Get the format string from the resource file and
// format it with the passed arguments.
string format = singleton.rm.GetString(name);
singleton.builder.Length = 0;
singleton.builder.AppendFormat(format, args);
return singleton.builder.ToString();
}
#endregion
#region private fields/properties/methods
/// <summary>
/// Class constructor made private because class is a singleton.
/// </summary>
private StringResources()
{
builder = new StringBuilder();
rm = new ResourceManager("HakInstaller.strings", Assembly.GetExecutingAssembly());
}
private static StringResources singleton = new StringResources();
private StringBuilder builder;
private ResourceManager rm;
#endregion
}
}

View File

@@ -0,0 +1,67 @@
# HIF files may consist of any of the following tags. All tags are optional.
# Tags that support multiple data items may have the data comma separated and/or
# may have multiple entries. If a multiple entries are given for a tag that only
# supports 1 value then the fist value in the file is used. Blank lines are ignored
# as are lines starting with a '#'.
#
# Tag format is
#
# <tag> : <value1>, <value2>, ..., <valuen>
#
# All white space is optional, and tags may also be given on multiple lines
# as follows:
#
# <tag> : <value1>
# <tag> : <value2>
# ...
# <tag> : <valuen>
#
# The following tags are supported:
#
# erf : Imports the listed erf files into the module
# module.Hak : haks to add to the module
# module.CustomTlk : Custom tlk file for the module, only 1 value.
# module.Cache : Adds the given scripts the module's script cache.
# module.OnAcquireItem : Assigns script(s) to handle this module event
# module.OnActivateItem : Assigns script(s) to handle this module event
# module.OnClientEnter : Assigns script(s) to handle this module event
# module.OnClientLeave : Assigns script(s) to handle this module event
# module.OnCutsceneAbort : Assigns script(s) to handle this module event
# module.OnHeartbeat : Assigns script(s) to handle this module event
# module.OnModuleLoad : Assigns script(s) to handle this module event
# module.OnModuleStart : Assigns script(s) to handle this module event
# module.OnPlayerDeath : Assigns script(s) to handle this module event
# module.OnPlayerDying : Assigns script(s) to handle this module event
# module.OnPlayerEquipItem : Assigns script(s) to handle this module event
# module.OnPlayerLevelUp : Assigns script(s) to handle this module event
# module.OnPlayerRest : Assigns script(s) to handle this module event
# module.OnPlayerUnEquipItem : Assigns script(s) to handle this module event
# module.OnPlayerRespawn : Assigns script(s) to handle this module event
# module.OnUnaquireItem : Assigns script(s) to handle this module event
# module.OnUserDefined : Assigns script(s) to handle this module event
# Import there ERF files into the module.
erf : spellpak.erf, prc_consortium.erf
# Haks and custom tlk's used by the module.
module.Hak : spellPRCMerge.hak, spellPak.hak, prc_consortium.hak
module.CustomTlk : spellsPRCMerge.tlk
# Events that need to be wired up.
module.OnClientEnter : prc_onenter
module.OnPlayerLevelUp : prc_levelup
module.OnPlayerEquipItem : prc_equip
module.OnPlayerUnequipItem : prc_unequip
# Cache PRC scripts for better performance.
module.Cache : screen_targets
module.Cache : prc_caster_level
module.Cache : set_damage_type
module.Cache : change_metamagic
module.Cache : add_spell_dc
module.Cache : add_spell_penetr
module.Cache : add_damage
module.Cache : add_damageshield
module.Cache : add_randdamage
module.Cache : add_healing
module.Cache : add_hitpoints

View File

@@ -0,0 +1,61 @@
# HIF files may consist of any of the following tags. All tags are optional.
# Tags that support multiple data items may have the data comma separated and/or
# may have multiple entries. If a multiple entries are given for a tag that only
# supports 1 value then the fist value in the file is used. Blank lines are ignored
# as are lines starting with a '#'.
#
# Tag format is
#
# <tag> : <value1>, <value2>, ..., <valuen>
#
# All white space is optional, and tags may also be given on multiple lines
# as follows:
#
# <tag> : <value1>
# <tag> : <value2>
# ...
# <tag> : <valuen>
#
# The following tags are supported:
#
# erf : Imports the listed erf files into the module
# module.Hak : haks to add to the module
# module.CustomTlk : Custom tlk file for the module, only 1 value.
# module.Cache : Adds the given scripts the module's script cache.
# module.OnAcquireItem : Assigns script(s) to handle this module event
# module.OnActivateItem : Assigns script(s) to handle this module event
# module.OnClientEnter : Assigns script(s) to handle this module event
# module.OnClientLeave : Assigns script(s) to handle this module event
# module.OnCutsceneAbort : Assigns script(s) to handle this module event
# module.OnHeartbeat : Assigns script(s) to handle this module event
# module.OnModuleLoad : Assigns script(s) to handle this module event
# module.OnModuleStart : Assigns script(s) to handle this module event
# module.OnPlayerDeath : Assigns script(s) to handle this module event
# module.OnPlayerDying : Assigns script(s) to handle this module event
# module.OnPlayerEquipItem : Assigns script(s) to handle this module event
# module.OnPlayerLevelUp : Assigns script(s) to handle this module event
# module.OnPlayerRest : Assigns script(s) to handle this module event
# module.OnPlayerUnEquipItem : Assigns script(s) to handle this module event
# module.OnPlayerRespawn : Assigns script(s) to handle this module event
# module.OnUnaquireItem : Assigns script(s) to handle this module event
# module.OnUserDefined : Assigns script(s) to handle this module event
# Import there ERF files into the module.
erf : spellpak.erf
# Haks and custom tlk's used by the module.
module.Hak : spellPak.hak
module.CustomTlk : spellPak.tlk
# Cache PRC scripts for better performance.
module.Cache : screen_targets
module.Cache : prc_caster_level
module.Cache : set_damage_type
module.Cache : change_metamagic
module.Cache : add_spell_dc
module.Cache : add_spell_penetr
module.Cache : add_damage
module.Cache : add_damageshield
module.Cache : add_randdamage
module.Cache : add_healing
module.Cache : add_hitpoints

View File

@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8" ?>
<root xmlns="http://tempuri.org/strings.xsd">
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="ResMimeType">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="Version">
<value>1.0.0.0</value>
</resheader>
<resheader name="Reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="Writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="VersionFormat">
<value>NWN{1}{2} version {0} installed.</value>
</data>
<data name="PathFormat">
<value>Install Path: {0}</value>
</data>
<data name="ViewHakFile">
<value>View Hak File</value>
</data>
<data name="ViewModFile">
<value>View Module File</value>
</data>
<data name="ViewHakFileFormat">
<value>View Hak {0}</value>
</data>
<data name="ViewModFileFormat">
<value>View Module {0}</value>
</data>
<data name="XP2Name">
<value>Hordes of the Underdark Campaign</value>
</data>
<data name="XP1Name">
<value>Shadows of Undrentide Campaign</value>
</data>
<data name="OCName">
<value>Neverwinter Original Campaign</value>
</data>
<data name="HifsOverwritesModule">
<value>Some module content is going to get overwritten by haks being installed into the module. The module may not play correctly, do you wish to continue?</value>
</data>
<data name="ModuleOverwritesHifs">
<value>Some content being added will be ignored because it is contained in haks already in the module. The module may not play correctly, do you wish to continue?</value>
</data>
<data name="ValidateNWNVersionError">
<value>The {0} custom content cannot be installed because it requires at least version {1} of NWN, and you are currently running version {2}.</value>
</data>
<data name="ValidateMissingFilesError">
<value>The {0} custom content cannot be installed because the following files are missing: {1}</value>
</data>
<data name="NoHIFS">
<value>There is no custom content to install. The installer will now close.</value>
</data>
<data name="ValidateNWNXP1Error">
<value>The {0} custom content cannot be installed because it requires the Shadows of Undrentide expansion.</value>
</data>
<data name="ValidateNWNXP2Error">
<value>The {0} custom content cannot be installed because it requires the Hordes of the Underdark expansion.</value>
</data>
<data name="SingleHIFTitle">
<value>{0} {1} Module Updater</value>
</data>
<data name="VersionFormatXP1">
<value>, SoU</value>
</data>
<data name="VersionFormatXP2">
<value>, HotU</value>
</data>
</root>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0"?>
<xs:schema id="root" targetNamespace="http://tempuri.org/strings.xsd" xmlns:mstns="http://tempuri.org/strings.xsd" xmlns="http://tempuri.org/strings.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="qualified" elementFormDefault="qualified">
<xs:element name="root" msdata:IsDataSet="true" msdata:EnforceConstraints="False">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="data">
<xs:complexType>
<xs:sequence>
<xs:element name="value" type="xs:string" minOccurs="0" msdata:Ordinal="1" />
<xs:element name="comment" type="xs:string" minOccurs="0" msdata:Ordinal="2" />
</xs:sequence>
<xs:attribute name="name" form="unqualified" type="xs:string" />
<xs:attribute name="type" form="unqualified" type="xs:string" />
<xs:attribute name="mimetype" form="unqualified" type="xs:string" />
</xs:complexType>
</xs:element>
<xs:element name="resheader">
<xs:complexType>
<xs:sequence>
<xs:element name="value" type="xs:string" minOccurs="0" msdata:Ordinal="1" />
</xs:sequence>
<xs:attribute name="name" form="unqualified" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!--This file is auto-generated by the XML Schema Designer. It holds layout information for components on the designer surface.-->
<XSDDesignerLayout />

View File

@@ -0,0 +1,2 @@
copy /y ship\*.exe C:\Games\NeverwinterNights\utils
copy /y ship\HakInstaller.exe C:\Development\nwnprc\CompiledResources\PRCModuleUpdater.exe

Binary file not shown.

Binary file not shown.

BIN
trunk/tools/NWNTools.rar Normal file

Binary file not shown.

Binary file not shown.

BIN
trunk/tools/Precacher.mod Normal file

Binary file not shown.

BIN
trunk/tools/Rar.exe Normal file

Binary file not shown.

BIN
trunk/tools/cat.exe Normal file

Binary file not shown.

View File

@@ -0,0 +1,67 @@
// -------------------------
// CLS_FEAT_2DA by WodahsEht
// -------------------------
// Basically this utility goes through any specified cls_feat_*.2da and determines which feats
// are duplicated. It's not exactly the fastest algorithm possible but it shouldn't take long at
// all to parse all 2da's in one fell swoop.
//
// If you want to parse all 2da's at one time, add this line to a batch file:
// for %%a in (..\2das\cls_feat_*.2da) do cls_feat_2da.exe %%a
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[])
{
char featnum[1000][20];
int i, j, k;
char find[20];
FILE *input2da;
input2da = fopen(argv[1],"r");
if (input2da == NULL)
{
printf("Error, invalid file name.\n");
return (1);
}
while (i != -1 && !feof(input2da))
{
fscanf(input2da, "%s", &find);
if (strcmp(find, "OnMenu") == 0)
i = -1;
}
i = 0;
while (!feof(input2da))
{
fscanf(input2da, "%*s");
fscanf(input2da, "%*s");
fscanf(input2da, "%s", &featnum[i]);
fscanf(input2da, "%*s");
fscanf(input2da, "%*s");
fscanf(input2da, "%*s");
i++;
}
fclose(input2da);
i--;
i = (i > 1000) ? 1000 : i;
for (j = 0 ; j <= i ; j++)
{
for (k = j - 1 ; k >= 0 ; k--)
{
if (strcmp(featnum[j], featnum[k]) == 0 &&
strcmp(featnum[j], "****") != 0 &&
strcmp(featnum[k], "****") != 0)
printf("Lines %i and %i have the same feat number.\n", j/* + 4*/, k/* + 4*/); // Busquishage - Ornedan
}
}
return (0);
}

Binary file not shown.

View File

@@ -0,0 +1,4 @@
javac prc\prc\*.java prc\prc\autodoc\*.java prc\prc\makedep\*.java prc\prc\utils\*.java
cd prc
jar -cvfm ..\prc.jar ..\manifest.txt *.*
pause

BIN
trunk/tools/cygiconv-2.dll Normal file

Binary file not shown.

BIN
trunk/tools/cygintl-2.dll Normal file

Binary file not shown.

BIN
trunk/tools/cygintl-3.dll Normal file

Binary file not shown.

BIN
trunk/tools/cygintl-8.dll Normal file

Binary file not shown.

BIN
trunk/tools/cygpcre-0.dll Normal file

Binary file not shown.

BIN
trunk/tools/cygwin1.dll Normal file

Binary file not shown.

BIN
trunk/tools/cygxml2-2.dll Normal file

Binary file not shown.

BIN
trunk/tools/cygz.dll Normal file

Binary file not shown.

BIN
trunk/tools/diff.exe Normal file

Binary file not shown.

BIN
trunk/tools/erf-1.2.1.zip Normal file

Binary file not shown.

BIN
trunk/tools/erf.exe Normal file

Binary file not shown.

131
trunk/tools/fileend.c Normal file
View File

@@ -0,0 +1,131 @@
/*
fileend.c
generates switches for use with PRCGetFileEnd()
By: Flaming_Sword
Created: Sept 5, 2006
Modified: June 12, 2009
USE: Run with path to directory containing 2das to create fileends for,
will otherwise use default relative path to 2das
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <sys/types.h>
#include <dirent.h>
//#define DEBUG
#define MIN(x, y) (x <= y) ? x : y
int main(int argc, char *argv[])
{
char *sFile;
char *sTemp = (char *) malloc(65536 * sizeof(char));
char sDir[] = "../2das/";
char *pt;
char sName[20];
char sPath[256];
FILE *fp;
DIR *dp;
int nCount, i, add_slash = 0;
struct dirent *ep;
if(argc < 1) return;
if(argc > 1)
{
for(i = 0; argv[1][i] != '\0'; i++)
{
if(argv[1][i] == '\\')
argv[1][i] = '/';
}
if(argv[1][i - 1] != '/')
{
add_slash = 1;
}
}
if(argc == 1 || argv[1] == NULL)
{
pt = sDir;
}
else
{
pt = argv[1];
}
dp = opendir(pt);
printf(" //START AUTO-GENERATED FILEENDS\n");
if (dp != NULL)
{
#ifdef DEBUG
printf(" //found dir %s\n", sDir);
#endif
while (ep = readdir (dp))
{
memset(sPath, 0, sizeof(sPath));
memcpy(sPath, pt, MIN(sizeof(sPath), strlen(pt)));
if(add_slash)
strcat(sPath, "/");
sFile = ep->d_name;
strcat(sPath, sFile);
#ifdef DEBUG
printf("//%s\n", sPath);
#endif
#ifdef DEBUG
printf("//null compare\n");
#endif
if(strstr(sFile, ".2da") == NULL && strstr(sFile, "2DA") == NULL)
continue;
#ifdef DEBUG
printf("//file open\n");
#endif
fp = fopen(sPath, "r");
if(fp == NULL)
{
printf(" //error opening %s\n", sFile);
continue;
}
nCount = 0;
#ifdef DEBUG
printf("//fgets\n");
#endif
fgets(sTemp, 65535, fp);
#ifdef DEBUG
printf("//comp\n");
#endif
if(strncmp(sTemp, "2DA", 3))
{
fclose(fp);
#ifdef DEBUG
printf("//sTemp = %s\n", sTemp);
#endif
continue;
}
nCount++;
for(i = 0; i < 20; i++)
sName[i] = sFile[i];
while(fgets(sTemp, 65536, fp))
{
nCount++;
}
#ifdef DEBUG
printf("//print\n");
#endif
printf(" SetPRCSwitch(%cPRC_FILE_END_%s%c, %d);\n", 34, strtok(sName, "."), 34, nCount - 4);
fclose(fp);
}
(void) closedir (dp);
}
else
{
printf("Directory %s not found\n", argv[1]);
}
printf(" //END AUTO-GENERATED FILEENDS\n");
free(sTemp);
return 0;
}

Binary file not shown.

BIN
trunk/tools/grep.exe Normal file

Binary file not shown.

BIN
trunk/tools/icons/prc.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,61 @@
; Java Launcher
;--------------
;You want to change the next four lines
Name "CharacterCreator"
Caption "PRC/CODI Java Characer Creator"
Icon "prc.ico"
OutFile "CharacterCreator.exe"
SilentInstall silent
AutoCloseWindow true
ShowInstDetails nevershow
;You want to change the next two lines too
!define JAR "CC.jar"
Section ""
Call GetJRE
Pop $R0
; change for your purpose (-jar etc.)
StrCpy $0 '"$R0" -Xmx200M -Xms200M -jar ${JAR}'
SetOutPath $EXEDIR
ExecWait $0
SectionEnd
Function GetJRE
;
; Find JRE (javaw.exe)
; 1 - in .\jre directory (JRE Installed with application) [removed as it's not for this]
; 2 - in JAVA_HOME environment variable
; 3 - in the registry
; 4 - assume javaw.exe in current dir or PATH
Push $R0
Push $R1
; ClearErrors
; StrCpy $R0 "$EXEDIR\jre\bin\javaw.exe"
; IfFileExists $R0 JreFound
; StrCpy $R0 ""
ClearErrors
ReadEnvStr $R0 "JAVA_HOME"
StrCpy $R0 "$R0\bin\javaw.exe"
IfErrors 0 JreFound
ClearErrors
ReadRegStr $R1 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" "CurrentVersion"
ReadRegStr $R0 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment\$R1" "JavaHome"
StrCpy $R0 "$R0\bin\javaw.exe"
IfErrors 0 JreFound
StrCpy $R0 "javaw.exe"
JreFound:
Pop $R1
Exch $R0
FunctionEnd

Binary file not shown.

View File

@@ -0,0 +1,9 @@
There are currently no Linux binaries of Moneo (or .SOs) with SQL support.
This is due in large part to the absence of SCO/RCO hooking in the Linux port of NWNX2, making the point of SQL in LetoScript nearly moot.
If you're running Linux, and you'd like to try and compile with SQL support, jump into LetoScript.inc and uncomment the {$DEFINE LETOSCRIPT_SQL} flag there. I suggest trying with the {$DEFINE LETOSCRIPT_SQL_LETO} flag for SQLite3 support, just as a test, and then (if you can get Zeos functioning in your Kylix), you could try with {$DEFINE LETOSCRIPT_SQL_ZEOS} for full MySQL support. If you get either working, I'd be interested in hearing about your experience:
http://weathersong.infopop.cc
dragon@weathersong.net

View File

@@ -0,0 +1,105 @@
$abbrev;
$lowHD;
$highHD;
$sizeplus;
$j;
for($j = 1; $j<= 7; $j++)
{
if($j == 1)
{
$abbrev = 'clay';
$lowHD = 12;
$highHD = 33;
$sizeplus = 19;
}
if($j == 2)
{
$abbrev = 'fles';
$lowHD = 10;
$highHD = 27;
$sizeplus = 19;
}
if($j == 3)
{
$abbrev = 'ston';
$lowHD = 15;
$highHD = 42;
$sizeplus = 22;
}
if($j == 4)
{
$abbrev = 'adam';
$lowHD = 55;
$highHD = 108;
$sizeplus = 83;
}
if($j == 5)
{
$abbrev = 'demo';
$lowHD = 5;
$highHD = 0;
}
if($j == 6)
{
$abbrev = 'iron';
$lowHD = 19;
$highHD = 54;
$sizeplus = 25;
}
if($j == 7)
{
$abbrev = 'mith';
$lowHD = 37;
$highHD = 72;
$sizeplus = 55;
}
print $abbrev;
print ' ';
print $lowHD;
print ' ';
print $highHD;
print "\n";
if($highHD > 80)
{
$highHD = 80;
}
%file = "..\\..\\others\\prc_con_$abbrev.utc" or die $!;
$i;
$sizeadded = 0;
$count = 0;
for($i=$lowHD; $i<=$highHD; $i = $i+1)
{
/ClassList/[0]/ClassLevel = /ClassList/[0]/ClassLevel+1;
if($i%2 == 0)
{
/HitPoints = /HitPoints+5;
/CurrentHitPoints = /CurrentHitPoints+5;
/MaxHitPoints = /MaxHitPoints+5;
}
else
{
/HitPoints = /HitPoints+6;
/CurrentHitPoints = /CurrentHitPoints+6;
/MaxHitPoints = /MaxHitPoints+6;
}
if($i>=$sizeplus and $sizeadded == 0)
{
add Name => /FeatList/Feat, Value => 2293, Type => gffWord, SetIfExists => TRUE;
$sizeadded = 1;
print "Added size \n";
}
if($count%5 == 0)
{
$name = "prc_con_"+$abbrev+"_$i";
/TemplateResRef = $name;
$name = "$name.utc";
%file = ">..\\..\\others\\$name";
print "Written to file $name\n";
}
$count = $count+1;
}
close %file;
}

View File

@@ -0,0 +1 @@
Moneo.exe golem.ls -> test.log

View File

@@ -0,0 +1,40 @@
%store = '.\prc_merchant.utm' or die $!;
meta dir=> '..\..\Craft2das' or die $!;
$name = 'prc_recipe';
$i = 0;
$max = 1000;
$x = 0;
$y = 0;
$count = 0;
add Name => /StoreList/[2]/ItemList, Type=>gffList;
/ResRef = $name;
/LocName = $name;
/Tag = $name;
for($i=0; $i<=$max; $i++)
{
$resref = lookup 'item_to_ireq', $i, 'RECIPE_TAG';
if($resref eq '')
{
print "no entry\n";
}
else
{
add /StoreList/[2]/ItemList/InventoryRes, $resref, gffResRef;
add /StoreList/[2]/ItemList/[_]/Infinite, 1, gffByte;
add /StoreList/[2]/ItemList/[_]/Repos_PosX, $x, gffByte;
add /StoreList/[2]/ItemList/[_]/Repos_Posy, $y, gffByte;
$x++;
if($x>9)
{
$x = 0;
$y++;
}
/StoreList/[2]/ItemList/[_].id = $count;
$count++;
}
print "$resref $x $y /StoreList/[2]/ItemList/[_]/InventoryRes /StoreList/[2]/ItemList/[_]/Infinite /StoreList/[2]/ItemList/[_]/Repos_PosX /StoreList/[2]/ItemList/[_]/Repos_Posy \n";
}
%store = ">..\\..\\others\\$name.utm";

View File

@@ -0,0 +1 @@
Moneo.exe "prc recipe merchant maker.ls" -> test.log

View File

@@ -0,0 +1 @@
Moneo.exe "prc recipe merchant maker.ls" -> test.log

View File

@@ -0,0 +1,31 @@
%store = '.\prc_merchant.utm' or die $!;
meta dir=> '..\..\Craft2das' or die $!;
$name = 'prc_recipe';
$i = 0;
$max = 776;
$x = 0;
$y = 0;
add Name => /StoreList/[2]/ItemList, Type=>gffList;
/ResRef = $name;
/LocName = $name;
/Tag = $name;
for($i=0; $i<=$max; $i++)
{
$resref = lookup 'item_to_ireq', $i, 'RECIPE_TAG';
add /StoreList/[2]/ItemList/InventoryRes, $resref, gffResRef;
add /StoreList/[2]/ItemList/[_]/Infinite, 1, gffByte;
add /StoreList/[2]/ItemList/[_]/Repos_PosX, $x, gffByte;
add /StoreList/[2]/ItemList/[_]/Repos_Posy, $y, gffByte;
$x++;
if($x>9)
{
$x = 0;
$y++;
}
print "$resref $x $y /StoreList/[2]/ItemList/InventoryRes /StoreList/[2]/ItemList/[_]/Infinite /StoreList/[2]/ItemList/[_]/Repos_PosX /StoreList/[2]/ItemList/[_]/Repos_Posy \n";
}
%store = ">$name.utm";

Binary file not shown.

BIN
trunk/tools/linux/erf Normal file

Binary file not shown.

BIN
trunk/tools/linux/tlk2xml Normal file

Binary file not shown.

BIN
trunk/tools/linux/tlktools Normal file

Binary file not shown.

BIN
trunk/tools/linux/xml2tlk Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More