From 226df9737a001b4ddcfb899e41710561a77e59b4 Mon Sep 17 00:00:00 2001
From: Li
Date: Wed, 8 Mar 2023 10:27:17 +1300
Subject: [PATCH] add the ability to add weapons from within the application
---
LibW4M/Data/Highscores/HighscoreCollective.cs | 5 ++
.../InputMapping/InputMappingCollective.cs | 11 +++
LibW4M/Data/SaveDataCollective.cs | 2 +-
LibW4M/Data/SaveDataEntry.cs | 14 +++-
LibW4M/Data/Schemes/SchemesCollective.cs | 5 ++
LibW4M/Data/Stats/StatsCollective.cs | 5 ++
LibW4M/Data/Stats/TeamStatsCollective.cs | 5 ++
LibW4M/Data/Teams/TeamsCollective.cs | 5 ++
LibW4M/Data/WeaponFactory/WeaponData.cs | 41 +++++++++-
LibW4M/Data/WeaponFactory/WeaponStore.cs | 81 +++++++++++++++----
.../Data/WeaponFactory/WeaponsCollective.cs | 6 ++
LibW4M/W4SaveFile.cs | 4 +
LibXom/Data/XomFile.cs | 13 ++-
LibXom/Data/XomType.cs | 8 ++
.../CollectiveListAddDelete.Designer.cs | 2 +-
W4Gui/Tabs/WeaponsTab.cs | 4 +-
16 files changed, 187 insertions(+), 24 deletions(-)
diff --git a/LibW4M/Data/Highscores/HighscoreCollective.cs b/LibW4M/Data/Highscores/HighscoreCollective.cs
index b032ee1..4403585 100644
--- a/LibW4M/Data/Highscores/HighscoreCollective.cs
+++ b/LibW4M/Data/Highscores/HighscoreCollective.cs
@@ -13,6 +13,11 @@ namespace LibW4M.Data.Highscores
{
}
+ public override void Create()
+ {
+ throw new NotImplementedException();
+ }
+
public override void Load()
{
// highscore data is stored after teams data section of TeamDataCollective.
diff --git a/LibW4M/Data/InputMapping/InputMappingCollective.cs b/LibW4M/Data/InputMapping/InputMappingCollective.cs
index c4a4483..443ea81 100644
--- a/LibW4M/Data/InputMapping/InputMappingCollective.cs
+++ b/LibW4M/Data/InputMapping/InputMappingCollective.cs
@@ -2,6 +2,7 @@
using LibXom.Data;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -14,6 +15,11 @@ namespace LibW4M.Data.InputMapping
{
}
+ public override void Create()
+ {
+ throw new NotImplementedException();
+ }
+
public override void Load()
{
int[] collective = mainContainer.Decompress();
@@ -39,5 +45,10 @@ namespace LibW4M.Data.InputMapping
}
mainContainer.CompressAndUpdate(collective);
}
+
+ private string GetDebuggerDisplay()
+ {
+ return ToString();
+ }
}
}
diff --git a/LibW4M/Data/SaveDataCollective.cs b/LibW4M/Data/SaveDataCollective.cs
index cdd370a..39d4545 100644
--- a/LibW4M/Data/SaveDataCollective.cs
+++ b/LibW4M/Data/SaveDataCollective.cs
@@ -48,7 +48,7 @@ namespace LibW4M.Data
}
}
}
-
+ public abstract void Create();
public abstract override void Load();
public abstract override void Save();
diff --git a/LibW4M/Data/SaveDataEntry.cs b/LibW4M/Data/SaveDataEntry.cs
index 0904cee..70aa9e6 100644
--- a/LibW4M/Data/SaveDataEntry.cs
+++ b/LibW4M/Data/SaveDataEntry.cs
@@ -29,7 +29,7 @@ namespace LibW4M.Data
public virtual string FriendlyName
{ get
{
- return mainContainer.Type.Name;
+ return this.mainContainer.Type.Name;
}
}
public override int GetHashCode()
@@ -44,16 +44,24 @@ namespace LibW4M.Data
public abstract void Load();
public abstract void Save();
+
+ internal virtual void loadDefaults()
+ {
+ //this.Save();
+ }
public virtual void DeleteEntries()
{
this.mainContainer.Delete();
}
- public SaveDataEntry (W4SaveFile fileBelongs, XomContainer mainContainer)
+ internal SaveDataEntry (W4SaveFile fileBelongs, XomContainer mainContainer, bool load=true)
{
this.fileBelongs = fileBelongs;
this.mainContainer = mainContainer;
- this.Load();
+ if (load)
+ this.Load();
+ else
+ this.loadDefaults();
}
}
}
diff --git a/LibW4M/Data/Schemes/SchemesCollective.cs b/LibW4M/Data/Schemes/SchemesCollective.cs
index e481400..46910bf 100644
--- a/LibW4M/Data/Schemes/SchemesCollective.cs
+++ b/LibW4M/Data/Schemes/SchemesCollective.cs
@@ -14,6 +14,11 @@ namespace LibW4M.Data.Schemes
{
}
+ public override void Create()
+ {
+ throw new NotImplementedException();
+ }
+
public override void Load()
{
int[] collective = mainContainer.Decompress();
diff --git a/LibW4M/Data/Stats/StatsCollective.cs b/LibW4M/Data/Stats/StatsCollective.cs
index e4b1e80..8a8db83 100644
--- a/LibW4M/Data/Stats/StatsCollective.cs
+++ b/LibW4M/Data/Stats/StatsCollective.cs
@@ -16,6 +16,11 @@ namespace LibW4M.Data.Stats
{
}
+ public override void Create()
+ {
+ throw new NotImplementedException();
+ }
+
public override void Load()
{
int[] decompressedCollective = mainContainer.Decompress();
diff --git a/LibW4M/Data/Stats/TeamStatsCollective.cs b/LibW4M/Data/Stats/TeamStatsCollective.cs
index 83c1711..45f8ba9 100644
--- a/LibW4M/Data/Stats/TeamStatsCollective.cs
+++ b/LibW4M/Data/Stats/TeamStatsCollective.cs
@@ -105,5 +105,10 @@ namespace LibW4M.Data.Stats
mainContainer.CompressAndUpdate(newCollective);
}
+
+ public override void Create()
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/LibW4M/Data/Teams/TeamsCollective.cs b/LibW4M/Data/Teams/TeamsCollective.cs
index 49190fb..8e777e3 100644
--- a/LibW4M/Data/Teams/TeamsCollective.cs
+++ b/LibW4M/Data/Teams/TeamsCollective.cs
@@ -14,6 +14,11 @@ namespace LibW4M.Data.Teams
{
}
+ public override void Create()
+ {
+ throw new NotImplementedException();
+ }
+
public override void Load()
{
int[] decompressedCollective = mainContainer.Decompress();
diff --git a/LibW4M/Data/WeaponFactory/WeaponData.cs b/LibW4M/Data/WeaponFactory/WeaponData.cs
index 5415fad..67a818d 100644
--- a/LibW4M/Data/WeaponFactory/WeaponData.cs
+++ b/LibW4M/Data/WeaponFactory/WeaponData.cs
@@ -45,7 +45,7 @@ namespace LibW4M.Data.WeaponFactory
public float ClusterSpread;
public float ClusterMaxSpeed;
- public WeaponData(W4SaveFile fileBelongs, XomContainer mainContainer) : base(fileBelongs, mainContainer)
+ public WeaponData(W4SaveFile fileBelongs, XomContainer mainContainer, bool load=true) : base(fileBelongs, mainContainer, load)
{
}
@@ -122,7 +122,46 @@ namespace LibW4M.Data.WeaponFactory
}
}
}
+ internal override void loadDefaults()
+ {
+ this.Name = this.fileBelongs.LookupString("Untitled Weapon");
+ this.Type = 0;
+ this.DetonationType = DetonationType.Impact;
+ this.Homing = false;
+ this.HomingAvoidLand = false;
+ this.Poison = false;
+ this.EffectedByWind = true;
+ this.FireOnGround = false;
+
+ this.RetreatTime = -1;
+
+ this.WormDamageRadius = 0.75f;
+
+ this.WormDamageMagnitude = 0.5f;
+ this.LandDamageRadius = 0.5f;
+ this.Push = 0.5f;
+
+ this.ProjectileCollisionRadius = 1.0f;
+ this.FuseTime = -1;
+
+ this.GraphicalResources = new XomString[4] { this.fileBelongs.LookupString("Factory.TankGunBody"), this.fileBelongs.LookupString("Factory.TankGunBarrel"), this.fileBelongs.LookupString("Factory.TankGunButt"), this.fileBelongs.LookupString("Factory.TankGunSight") };
+ this.GraphicalLocators = new XomString[4] { this.fileBelongs.LookupString("TANK_body_locator"), this.fileBelongs.LookupString("TANK_barrel_root_locator"), this.fileBelongs.LookupString("TANK_butt_root_locator"), this.fileBelongs.LookupString("TANK_sight_root_locator") };
+
+ this.LaunchFX = this.fileBelongs.LookupString("");
+ this.ArielFX = this.fileBelongs.LookupString("WXP_BazookaTrailPack");
+ this.DetonationFX = this.fileBelongs.LookupString("WXP_ExplosionX_Med");
+
+ this.PayloadResourceId = 55;
+ this.ProjectileLaunchType = ProjectileLaunchType.Launched;
+ this.ProjectilePowersUp = true;
+ this.ProjectileNumClusters = 0;
+ this.ProjectileMaxPower = 0.5f;
+ this.ClusterSpread = 0.300000012f;
+ this.ClusterMaxSpeed = 0.0f;
+
+ base.loadDefaults();
+ }
public override void Load()
{
using (XomStreamReader reader = new XomStreamReader(new MemoryStream(this.mainContainer.GetData())))
diff --git a/LibW4M/Data/WeaponFactory/WeaponStore.cs b/LibW4M/Data/WeaponFactory/WeaponStore.cs
index 16faf47..b4bba90 100644
--- a/LibW4M/Data/WeaponFactory/WeaponStore.cs
+++ b/LibW4M/Data/WeaponFactory/WeaponStore.cs
@@ -17,38 +17,91 @@ namespace LibW4M.Data.WeaponFactory
public WeaponData Cluster;
public bool StockWeapon;
- internal XomContainer weaponContainer;
- internal XomContainer clusterContainer;
+
- public WeaponStore(W4SaveFile fileBelongs, XomContainer mainContainer) : base(fileBelongs, mainContainer)
+ internal WeaponStore(W4SaveFile fileBelongs, XomContainer mainContainer, bool load=true) : base(fileBelongs, mainContainer, load)
{
}
public override void Load()
{
- int[] weaponStore = this.mainContainer.Decompress();
- this.StockWeapon = (weaponStore[0] == 1);
- this.weaponContainer = this.fileBelongs.LookupContainerById(weaponStore[1]);
- this.clusterContainer = this.fileBelongs.LookupContainerById(weaponStore[2]);
+ using (XomStreamReader reader = new XomStreamReader(new MemoryStream(mainContainer.GetData())))
+ {
+ reader.Skip(3);
- this.Weapon = new WeaponData(this.fileBelongs, this.weaponContainer);
- this.Cluster = new WeaponData(this.fileBelongs, this.clusterContainer);
+ this.StockWeapon = reader.ReadBool();
+ this.Weapon = new WeaponData(this.fileBelongs, this.fileBelongs.LookupContainerById(reader.ReadCompressedInt()));
+ this.Cluster = new WeaponData(this.fileBelongs, this.fileBelongs.LookupContainerById(reader.ReadCompressedInt()));
+ }
}
public override void Save()
{
this.Weapon.Save();
this.Cluster.Save();
+ using (MemoryStream ms = new MemoryStream())
+ {
+ using (XomStreamWriter writer = new XomStreamWriter(ms))
+ {
+ writer.Skip(3);
- int[] weaponStore = this.mainContainer.Decompress();
- weaponStore[0] = (this.StockWeapon ? 1 : 0);
- weaponStore[1] = this.weaponContainer.Id;
- weaponStore[2] = this.clusterContainer.Id;
- this.mainContainer.CompressAndUpdate(weaponStore);
+ writer.WriteBool(this.StockWeapon);
+ writer.WriteCompressedInt(this.Weapon.mainContainer.Id);
+ writer.WriteCompressedInt(this.Cluster.mainContainer.Id);
+
+ ms.Seek(0x00, SeekOrigin.Begin);
+ mainContainer.SetData(ms.ToArray());
+ }
+ }
}
+ internal override void loadDefaults()
+ {
+ this.StockWeapon = false;
+ this.Weapon = new WeaponData(this.fileBelongs, this.fileBelongs.CreateContainer("WeaponFactoryContainer"), false);
+ this.Cluster = new WeaponData(this.fileBelongs, this.fileBelongs.CreateContainer("WeaponFactoryContainer"), false);
+
+ // Clusters should have different defaults, lets just go fix that :)
+ this.Cluster.Name = this.fileBelongs.LookupString("");
+ this.Cluster.Type = 1;
+ this.Cluster.DetonationType = DetonationType.Impact;
+
+ this.Cluster.Homing = false;
+ this.Cluster.HomingAvoidLand = false;
+ this.Cluster.Poison = false;
+ this.Cluster.EffectedByWind = false;
+ this.Cluster.FireOnGround = false;
+
+ this.Cluster.RetreatTime = 0;
+
+ this.Cluster.WormDamageRadius = 0.75f;
+
+ this.Cluster.WormDamageMagnitude = 0.5f;
+ this.Cluster.LandDamageRadius = 0.5f;
+ this.Cluster.Push = 0.5f;
+
+ this.Cluster.ProjectileCollisionRadius = 1.0f;
+ this.Cluster.FuseTime = -1;
+
+ this.Cluster.GraphicalResources = new XomString[0];
+ this.Cluster.GraphicalLocators = new XomString[0];
+
+ this.Cluster.LaunchFX = this.fileBelongs.LookupString("");
+ this.Cluster.ArielFX = this.fileBelongs.LookupString("");
+ this.Cluster.DetonationFX = this.fileBelongs.LookupString("WXP_ExploCluster");
+
+ this.Cluster.PayloadResourceId = 16;
+ this.Cluster.ProjectileLaunchType = ProjectileLaunchType.Thrown;
+ this.Cluster.ProjectilePowersUp = false;
+ this.Cluster.ProjectileNumClusters = 0;
+ this.Cluster.ProjectileMaxPower = 0.0f;
+ this.Cluster.ClusterSpread = 0.5f;
+ this.Cluster.ClusterMaxSpeed = 0.0f;
+
+ base.loadDefaults();
+ }
public override void DeleteEntries()
{
diff --git a/LibW4M/Data/WeaponFactory/WeaponsCollective.cs b/LibW4M/Data/WeaponFactory/WeaponsCollective.cs
index 3a587df..7821360 100644
--- a/LibW4M/Data/WeaponFactory/WeaponsCollective.cs
+++ b/LibW4M/Data/WeaponFactory/WeaponsCollective.cs
@@ -25,6 +25,12 @@ namespace LibW4M.Data.WeaponFactory
}
return null;
}
+
+ public override void Create()
+ {
+ this.collectiveEntries.Add(new WeaponStore(this.fileBelongs, this.fileBelongs.CreateContainer("StoreWeaponFactory"), false));
+ }
+
public override void Load()
{
int[] collective = mainContainer.Decompress();
diff --git a/LibW4M/W4SaveFile.cs b/LibW4M/W4SaveFile.cs
index b4ae952..589717f 100644
--- a/LibW4M/W4SaveFile.cs
+++ b/LibW4M/W4SaveFile.cs
@@ -215,6 +215,10 @@ namespace LibW4M
return strings;
}
+ public XomContainer CreateContainer(string type)
+ {
+ return xomFile.CreateContainer(type);
+ }
public XomContainer LookupContainerById(int id)
{
return xomFile.GetContainerById(id);
diff --git a/LibXom/Data/XomFile.cs b/LibXom/Data/XomFile.cs
index 816f943..3825b80 100644
--- a/LibXom/Data/XomFile.cs
+++ b/LibXom/Data/XomFile.cs
@@ -54,6 +54,13 @@ namespace LibXom.Data
return xomStrings.Count - 1;
}
+
+ public XomContainer CreateContainer(string typeName)
+ {
+ XomType type = GetTypeByName(typeName);
+ return type.NewContainer();
+ }
+
public void ClearAllStrings()
{
xomStrings.Clear();
@@ -181,9 +188,9 @@ namespace LibXom.Data
XomBlock[] containerBlocks = XomBlockHandler.GetBlocksByName(xomBlocks, "CTNR");
- if (moikBlock is not MoikBlock) throw new XomBlockNotFoundException("XOM contained no MOIK block!, Is it corrupted?");
- if (schemeBlock is not SchmBlock) throw new XomBlockNotFoundException("XOM contained no SCHM block!, Is it corrupted?");
- if (stringBlock is not StrsBlock) throw new XomBlockNotFoundException("XOM contained no STRS block!, Is it corrupted?");
+ if (moikBlock is not MoikBlock) throw new XomBlockNotFoundException("XOM contained no MOIK block!, Is the XOM corrupted?");
+ if (schemeBlock is not SchmBlock) throw new XomBlockNotFoundException("XOM contained no SCHM block!, Is the XOM corrupted?");
+ if (stringBlock is not StrsBlock) throw new XomBlockNotFoundException("XOM contained no STRS block!, Is the XOM corrupted?");
version = moikBlock.Version;
unk0 = schemeBlock.Unk0;
diff --git a/LibXom/Data/XomType.cs b/LibXom/Data/XomType.cs
index 44f29e7..c3ffc6f 100644
--- a/LibXom/Data/XomType.cs
+++ b/LibXom/Data/XomType.cs
@@ -60,6 +60,14 @@ namespace LibXom.Data
int indx = this.getContainerIndex(container);
this.xomContainers[indx].data = newData;
}
+
+ public XomContainer NewContainer()
+ {
+ XomContainer xomContainer = new XomContainer(this.fileBelongs, this.Name, new byte[0x3]);
+ this.xomContainers.Add(xomContainer);
+ return xomContainer;
+ }
+
public void DeleteContainer(XomContainer container)
{
int indx = this.getContainerIndex(container);
diff --git a/W4Gui/Components/CollectiveListAddDelete.Designer.cs b/W4Gui/Components/CollectiveListAddDelete.Designer.cs
index 008db22..33972a0 100644
--- a/W4Gui/Components/CollectiveListAddDelete.Designer.cs
+++ b/W4Gui/Components/CollectiveListAddDelete.Designer.cs
@@ -72,7 +72,7 @@
// btnAdd
//
this.btnAdd.Dock = System.Windows.Forms.DockStyle.Fill;
- this.btnAdd.Enabled = false;
+ this.btnAdd.Enabled = true;
this.btnAdd.Location = new System.Drawing.Point(3, 3);
this.btnAdd.Name = "btnAdd";
this.btnAdd.Size = new System.Drawing.Size(116, 26);
diff --git a/W4Gui/Tabs/WeaponsTab.cs b/W4Gui/Tabs/WeaponsTab.cs
index 86fa7f4..c7a3960 100644
--- a/W4Gui/Tabs/WeaponsTab.cs
+++ b/W4Gui/Tabs/WeaponsTab.cs
@@ -54,7 +54,9 @@ namespace W4Gui.Tabs
private void weaponList_NewButton(object sender, EventArgs e)
{
- throw new NotImplementedException("Adding new weapons from here not implemented yet ;)");
+ DataManager.SaveFile.WeaponFactoryCollective.Create();
+ weaponList.List.Add(DataManager.SaveFile.WeaponFactoryCollective.Last().FriendlyName);
+ weaponList.List.SelectedIndex = (weaponList.List.Items.Count - 1);
}
private void weaponList_DeleteButton(object sender, EventArgs e)