diff --git a/src/library/Syroot.Worms.Armageddon/Scheme.cs b/src/library/Syroot.Worms.Armageddon/Scheme.cs
index 40a7396..cc660c0 100644
--- a/src/library/Syroot.Worms.Armageddon/Scheme.cs
+++ b/src/library/Syroot.Worms.Armageddon/Scheme.cs
@@ -1,1062 +1,1036 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using Syroot.BinaryData;
-using Syroot.Worms.Core;
-using Syroot.Worms.Core.IO;
-
-namespace Syroot.Worms.Armageddon
-{
- ///
- /// Represents a scheme stored in a WSC file which contains game settings and armory configuration, including
- /// RubberWorm settings encoded in those.
- /// Used by WA and WWP. S. https://worms2d.info/Game_scheme_file.
- ///
- public class Scheme : ILoadableFile, ISaveableFile
- {
- // ---- CONSTANTS ----------------------------------------------------------------------------------------------
-
- private const string _signature = "SCHM";
-
- // Lookup tables.
- private static readonly Dictionary _mapWaterRiseToRaw = new Dictionary()
- {
- [0] = 0,
- [5] = 1,
- [13] = 19,
- [20] = 2,
- [21] = 55,
- [29] = 43,
- [37] = 47,
- [45] = 3,
- [52] = 26,
- [53] = 25,
- [61] = 27,
- [64] = 8,
- [69] = 33,
- [77] = 13,
- [80] = 4,
- [84] = 18,
- [85] = 23,
- [93] = 11,
- [101] = 15,
- [109] = 29,
- [116] = 22,
- [117] = 57,
- [125] = 5,
- [133] = 63,
- [141] = 45,
- [148] = 30,
- [149] = 9,
- [157] = 21,
- [165] = 17,
- [173] = 61,
- [180] = 6,
- [181] = 39,
- [189] = 37,
- [197] = 31,
- [205] = 51,
- [208] = 12,
- [212] = 14,
- [213] = 41,
- [221] = 53,
- [229] = 49,
- [237] = 35,
- [244] = 10,
- [245] = 7,
- [253] = 59
- };
- private static readonly byte[] _objectCounts = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85,
- 90, 95, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250 };
-
- // ---- MEMBERS ------------------------------------------------------------------------------------------------
-
- private byte _mineDelay;
- private byte _turnTime;
- private byte _roundTimeMinutes;
- private byte _roundTimeSeconds;
- private byte _numberOfWins;
- private sbyte _rwGravity;
- private sbyte _rwGravityConstBlackHole;
- private sbyte _rwGravityPropBlackHole;
- private byte _rwKaosMod;
-
- // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
-
- ///
- /// Initializes a new instance of the class.
- ///
- public Scheme()
- {
- Version = SchemeVersion.Extended;
- Weapons = new SchemeWeaponSetting[GetWeaponCount()];
- }
-
- ///
- /// Initializes a new instance of the class, loading the data from the given
- /// .
- ///
- /// The to load the data from.
- public Scheme(Stream stream) => Load(stream);
-
- ///
- /// Initializes a new instance of the class, loading the data from the given file.
- ///
- /// The name of the file to load the data from.
- public Scheme(string fileName) => Load(fileName);
-
- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
-
- ///
- /// Gets or sets the of this scheme, controlling whether super weapon settings
- /// are stored or not.
- ///
- public SchemeVersion Version { get; set; }
-
- ///
- /// Gets or sets the delay in seconds between each team's turn to allow relaxed switching of seats.
- ///
- public byte HotSeatDelay { get; set; }
-
- ///
- /// Gets or sets the time in seconds available for a worm to retreat after using a weapon which ends the turn
- /// while standing on land.
- ///
- public byte RetreatTime { get; set; }
-
- ///
- /// Gets or sets the time in seconds available for a worm to retreat after using a weapon which ends the turn
- /// while on a rope.
- ///
- public byte RetreatTimeRope { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the total round time until sudden death will be displayed in the
- /// turn timer.
- ///
- public bool ShowRoundTime { get; set; }
-
- ///
- /// Gets or sets a value indicating whether significant turns will be replayed in offline games.
- ///
- public bool AutomaticReplays { get; set; }
-
- ///
- /// Gets or sets the percentual amount of fall damage applied, relative to normal fall damage being 100%.
- ///
- public SchemeFallDamage FallDamage { get; set; }
-
- ///
- /// Gets or sets a value indicating whether worms cannot walk and are mostly stuck at their current position
- /// without using any utilities.
- ///
- public bool ArtilleryMode { get; set; }
-
- ///
- /// Gets or sets a value indicating the scheme editor used to modify this scheme. Originally used to indicate
- /// the unimplemented Bounty Mode.
- ///
- public SchemeEditor SchemeEditor { get; set; }
-
- ///
- /// Gets or sets a value indicating the stockpiling of armory between game rounds.
- ///
- public SchemeStockpiling StockpilingMode { get; set; }
-
- ///
- /// Gets or sets a value indicating the worm selection order determining the next worm to be played.
- ///
- public SchemeWormSelect WormSelectMode { get; set; }
-
- ///
- /// Gets or sets a value indicating the action triggered when Sudden Death starts.
- ///
- public SchemeSuddenDeathEvent SuddenDeathEvent { get; set; }
-
- ///
- /// Gets or sets the amount in pixels which the water will rise between turns after Sudden Death was triggered.
- ///
- public SchemeWaterRise WaterRiseRate { get; set; }
-
- ///
- /// Gets or sets the percentual probability of a weapon crate to drop between turns. Negative values might crash
- /// the game.
- ///
- public sbyte WeaponCrateProbability { get; set; }
-
- ///
- /// Gets or sets a value indicating whether donor cards can spawn upon a worm's death.
- ///
- public bool DonorCards { get; set; }
-
- ///
- /// Gets or sets the percentual probability of a health crate to drop between turns. Negative values might crash
- /// the game.
- ///
- public sbyte HealthCrateProbability { get; set; }
-
- ///
- /// Gets or sets the amount of health included in a health crate added to the collecting worm's energy.
- ///
- public byte HealthCrateEnergy { get; set; }
-
- ///
- /// Gets or sets the percentual probability of a utility crate to drop between turns. Negative values might
- /// crash the game.
- ///
- public sbyte UtilityCrateProbability { get; set; }
-
- ///
- /// Gets or sets the type of objects which can be placed on the map.
- ///
- public SchemeObjectType ObjectTypes { get; set; }
-
- ///
- /// Gets or sets the maximum number of objects (mines or oil drums) on the map.
- ///
- public SchemeObjectCount ObjectCount { get; set; }
-
- ///
- /// Gets or sets the number of seconds a mine requires to explode. Can be 1-3 and 5-127 seconds.
- ///
- public byte MineDelay
- {
- get => _mineDelay;
- set
- {
- if (value == 4 || value > 0x7F)
- throw new ArgumentException("Mine delay must be between 0-127 and not be 4.", nameof(value));
- _mineDelay = value;
- }
- }
-
- ///
- /// Gets or sets a value indicating whether the mine fuse will be randomly chosen between fractions of 1 to 3
- /// seconds. If true, the setting will be ignored.
- ///
- public bool MineDelayRandom { get; set; }
-
- ///
- /// Gets or sets a value indicating whether mines can refuse to explode after their count down.
- ///
- public bool DudMines { get; set; }
-
- ///
- /// Gets or sets a value indicating whether worms are placed manually by the players for their initial position
- /// at round start.
- ///
- public bool ManualWormPlacement { get; set; }
-
- ///
- /// Gets or sets the initial worm energy at round start.
- ///
- public byte WormEnergy { get; set; }
-
- ///
- /// Gets or sets the turn time in seconds available for the player to move. Must be in the range of 0-127.
- ///
- public byte TurnTime
- {
- get => _turnTime;
- set
- {
- if (value > 0x7F)
- throw new ArgumentException("Turn time must be between 0-127.", nameof(value));
- _turnTime = value;
- }
- }
-
- ///
- /// Gets or sets a value indicating whether the turn time is unlimited. If true, the
- /// setting will be ignored.
- ///
- public bool TurnTimeInfinite { get; set; }
-
- ///
- /// Gets or sets the round time before sudden death is triggered between 0-127 minutes.
- ///
- public byte RoundTimeMinutes
- {
- get => _roundTimeMinutes;
- set
- {
- if (value > 0x7F)
- throw new ArgumentException("Round time must be between 0-127 minutes.", nameof(value));
- _roundTimeMinutes = value;
- }
- }
-
- ///
- /// Gets or sets the round time before sudden death is triggered in between 0-128 seconds. When 0,
- /// is used instead.
- ///
- public byte RoundTimeSeconds
- {
- get => _roundTimeSeconds;
- set
- {
- if (value > 0x80)
- throw new ArgumentException("Round time must be between 0-128 seconds.", nameof(value));
- _roundTimeSeconds = value;
- }
- }
-
- ///
- /// Gets or sets the number of round wins required to win the game. Must not be 0.
- ///
- public byte NumberOfWins
- {
- get => _numberOfWins;
- set
- {
- if (value == 0)
- throw new ArgumentException("Number of wins must not be 0.", nameof(value));
- _numberOfWins = value;
- }
- }
-
- ///
- /// Gets or sets a value indicating whether blood effects are enabled.
- ///
- public bool Blood { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the Super Sheep weapon gets upgraded to the Aqua Sheep, which can
- /// fly underwater.
- ///
- public bool AquaSheep { get; set; }
-
- ///
- /// Gets or sets a value indicating whether sheeps will jump out of exploding crates.
- ///
- public bool SheepHeaven { get; set; }
-
- ///
- /// Gets or sets a value indicating whether worms have infinity energy, killable only by drowning them.
- ///
- public bool GodWorms { get; set; }
-
- ///
- /// Gets or sets a value indicating whether terrain cannot be destroyed by explosions.
- ///
- public bool IndestructibleLand { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the Grenade weapon is more powerful.
- ///
- public bool UpgradedGrenade { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the Shotgun weapon shoots twice for each of the two shots.
- ///
- public bool UpgradedShotgun { get; set; }
-
- ///
- /// Gets or sets a value indicating whether cluster weapon explode into more clusters.
- ///
- public bool UpgradedCluster { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the Longbow weapon is more powerful.
- ///
- public bool UpgradedLongbow { get; set; }
-
- ///
- /// Gets or sets a value indicating whether team weapons will be given to the teams, overriding the default
- /// weapon settings for them.
- ///
- public bool EnableTeamWeapons { get; set; }
-
- ///
- /// Gets or sets a value indicating whether super weapons can be collected from crates.
- ///
- public bool EnableSuperWeapons { get; set; }
-
- ///
- /// Gets the array of instances, each mapping to one weapon at the index of
- /// the enumeration. Depending on the scheme , super weapons
- /// might not be stored in this array.
- ///
- public SchemeWeaponSetting[] Weapons { get; set; }
-
- // ---- RubberWorm Settings ----
-
- ///
- /// Gets or sets a value whether power is unlocked like in TestStuff. Configurable with the /alp command.
- ///
- public bool RwAntiLockPower { get; set; }
-
- ///
- /// Gets or sets a value indicating whether worms falling into water will be reset to the last solid location
- /// they stood on. Configurable with the /antisink command.
- ///
- public bool RwAntiSink { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the aim direction of a weapon will be reset at turn start.
- /// Configurable with the /reaim command.
- ///
- public bool RwAutoReaim { get; set; }
-
- ///
- /// Gets or sets a value whether the aim of a weapon loops in full rather than half circles. Configurable with
- /// the /cira command.
- ///
- public bool RwCircularAim { get; set; }
-
- ///
- /// Gets or sets the maximum number of crates existing on the map at the same time. 0 disables this feature,
- /// default limit is 5. Configurable with the /cratelimit command.
- ///
- public byte RwCrateLimit { get; set; }
-
- ///
- /// Gets or sets the maximum number of crates spawning per turn and enables the crate counter. Configurable with
- /// the /craterate command.
- ///
- public byte RwCrateRate { get; set; }
-
- ///
- /// Gets or sets a value indicating whether crate shower is enabled throughout a turn. Configurable with the
- /// /crateshower command.
- ///
- public bool RwCrateShower { get; set; }
-
- ///
- /// Gets or sets a value indicating whether weapon fuses can be selected between 0-9 seconds and herd counts
- /// between 1-10 animals. Configurable with the /fuseex command.
- ///
- public bool RwExtendedFuse { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the turn timer is paused while launching a weapon. Configurable with
- /// the /fdpt or /nopause commands.
- ///
- public bool RwFireDoesntPauseTimer { get; set; }
-
- ///
- /// Gets or sets the maximum number of flame particles active at the same time in the scale of 100x.
- /// Configurable with the /flames command.
- ///
- public byte RwFlameLimit { get; set; }
-
- ///
- /// Gets or sets the friction deaccelerating objects touching solid ground. 96 is default, 100 is no friction,
- /// higher values accelerate objects. Configurable with the /friction command.
- ///
- public byte RwFriction { get; set; }
-
- ///
- /// Gets or sets the amount of gravity. Ranges from -64-63 where 0 and 12 are default gravity and negative
- /// values pull objects upwards. Configurable with the /gravity command. When set,
- /// and are reset.
- ///
- public sbyte RwGravity
- {
- get => _rwGravity;
- set
- {
- if (value != 0)
- {
- RwGravityConstBlackHole = 0;
- RwGravityPropBlackHole = 0;
- }
- _rwGravity = value;
- }
- }
-
- ///
- /// gets or sets the amount of gravity acting as a constant black hole. Ranges from -32 to 31. Configurable with
- /// the /cbh command. When set, and are reset.
- ///
- public sbyte RwGravityConstBlackHole
- {
- get => _rwGravityConstBlackHole;
- set
- {
- if (value != 0)
- {
- RwGravity = 0;
- RwGravityPropBlackHole = 0;
- }
- _rwGravityConstBlackHole = value;
- }
- }
-
- ///
- /// Gets or sets the amount of gravity acting as a proportional black hole. Ranges from -32 to 31. Configurable
- /// with the /pbh command. When set, and are
- /// reset.
- ///
- public sbyte RwGravityPropBlackHole
- {
- get => _rwGravityPropBlackHole;
- set
- {
- if (value != 0)
- {
- RwGravity = 0;
- RwGravityConstBlackHole = 0;
- }
- _rwGravityPropBlackHole = value;
- }
- }
-
- ///
- /// Gets or sets the Kaos game scheme mod. 0 for none, 1-5 for the corresponding mod. Configurable with the
- /// /kaosmod command.
- ///
- public byte RwKaosMod
- {
- get => _rwKaosMod;
- set
- {
- if (value > 0xF)
- throw new ArgumentException("Kaos mod must not be greater than 15.");
- _rwKaosMod = value;
- }
- }
-
- ///
- /// Gets or sets the rope knocking power in percent, where 100 is the default power. Configurable with the
- /// /knock command.
- ///
- public byte RwKnockForce { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the loss of control while moving a worm ends does no longer end the
- /// turn and allows the player to continue moving. Configurable with the /ldet or /stoicworm commands.
- ///
- public bool RwLoseControlDoesntEndTurn { get; set; }
-
- ///
- /// Gets or sets the maximum speed a player can reach while roping. 16 is default, 32 is like in TestStuff, 255
- /// is unlimited. Configurable with the /speed command.
- ///
- public byte RwMaxRopeSpeed { get; set; }
-
- ///
- /// Gets or sets a value indicating whether using a weapon does no longer end the turn and allows to shoot
- /// multiple weapons in one turn. Configurable with the /sdet or /multishot commands.
- ///
- public bool RwShotDoesntEndTurn { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the weapons Armageddon, Earthquake and Indian Nuke Test are affected
- /// by aswell. Configurable with the /usw command.
- ///
- public bool RwShotDoesntEndTurnAll { get; set; }
-
- ///
- /// Gets or sets a value indicating whether all objects are pushed by explosions near them. Configurable with
- /// the /ope command.
- ///
- public bool RwObjectPushByExplosion { get; set; }
-
- ///
- /// Gets or sets a value indicating whether worms can be selected at any time during the turn, as long as worm
- /// selection is activated. Configurable with the /swat command.
- ///
- public bool RwSelectWormAnytime { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the Ninja Rope is more powerful. Configurable with the /ir or /rope+
- /// commands.
- ///
- public bool RwUpgradedRope { get; set; }
-
- ///
- /// Gets or sets the (special) game version to be forced. Configurable with the /version command.
- /// S. http://worms2d.info/List_of_Worms_Armageddon_logic_versions.
- ///
- public ushort RwVersionOverride { get; set; }
-
- ///
- /// Gets or sets the amount of air viscosity affecting objects. Odd numbers affect worms too. Configurable with
- /// the /visc command.
- ///
- public byte RwViscosity { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the selected weapon no longer resets to a remembered one upon
- /// shooting it. Configurable with the /wdca command.
- ///
- public bool RwWeaponsDontChange { get; set; }
-
- ///
- /// Gets or sets the influence power of the wind affecting all weapons. 255 is the same influence as the
- /// Bazooka. Odd numbers affect worms too. Configurable with the /wind command.
- ///
- public byte RwWindPower { get; set; }
-
- ///
- /// Gets or sets the power with which worms bounce off terrain, where 0 disables this feature and 255 fully
- /// bounces worms back without speed loss. Configurable with the /rubber command.
- ///
- public byte RwWormBouncyness { get; set; }
-
- // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
-
- ///
- /// Loads the data from the given .
- ///
- /// The to load the data from.
- public void Load(Stream stream)
- {
- using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
-
- // Read the header.
- if (reader.ReadString(_signature.Length) != _signature)
- throw new InvalidDataException("Invalid WSC file signature.");
- Version = reader.ReadEnum(true);
-
- // Read the options.
- HotSeatDelay = reader.Read1Byte();
- RetreatTime = reader.Read1Byte();
- RetreatTimeRope = reader.Read1Byte();
- ShowRoundTime = reader.ReadBoolean();
- AutomaticReplays = reader.ReadBoolean();
- FallDamage = (SchemeFallDamage)(reader.ReadByte() * 50 % 0x100 * 2);
- ArtilleryMode = reader.ReadBoolean();
- SchemeEditor = reader.ReadEnum(false);
- StockpilingMode = reader.ReadEnum(true);
- WormSelectMode = reader.ReadEnum(true);
- SuddenDeathEvent = reader.ReadEnum(true);
- WaterRiseRate = (SchemeWaterRise)(Math.Pow(reader.ReadByte(), 2) * 5 % 0x100);
- WeaponCrateProbability = reader.ReadSByte();
- DonorCards = reader.ReadBoolean();
- HealthCrateProbability = reader.ReadSByte();
- HealthCrateEnergy = reader.Read1Byte();
- UtilityCrateProbability = reader.ReadSByte();
- LoadObjectTypesAndCount(reader);
- LoadMineDelayConfig(reader);
- DudMines = reader.ReadBoolean();
- ManualWormPlacement = reader.ReadBoolean();
- WormEnergy = reader.Read1Byte();
- LoadTurnTimeConfig(reader);
- LoadRoundTimeConfig(reader);
- NumberOfWins = (byte)Math.Max(1, reader.ReadByte());
- Blood = reader.ReadBoolean();
- AquaSheep = reader.ReadBoolean();
- SheepHeaven = reader.ReadBoolean();
- GodWorms = reader.ReadBoolean();
- IndestructibleLand = reader.ReadBoolean();
- UpgradedGrenade = reader.ReadBoolean();
- UpgradedShotgun = reader.ReadBoolean();
- UpgradedCluster = reader.ReadBoolean();
- UpgradedLongbow = reader.ReadBoolean();
- EnableTeamWeapons = reader.ReadBoolean();
- EnableSuperWeapons = reader.ReadBoolean();
-
- // Read the weapon settings. Old versions do not store super weapon settings.
- Weapons = new SchemeWeaponSetting[64];
- int weaponCount = GetWeaponCount();
- for (int i = 0; i < weaponCount; i++)
- Weapons[i] = reader.ReadStruct();
-
- // Ignore possible unknown WWP trash at the end of the file.
-
- // Parse the RubberWorm settings.
- LoadRubberWormSettings();
- }
-
- ///
- /// Loads the data from the given file.
- ///
- /// The name of the file to load the data from.
- public void Load(string fileName)
- {
- using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
- Load(stream);
- }
-
- ///
- /// Saves the data into the given .
- ///
- /// The to save the data to.
- public void Save(Stream stream) => Save(stream, SchemeSaveFormat.ExtendedWithObjectCount);
-
- ///
- /// Saves the data into the given with the specified .
- ///
- /// The to save the data to.
- /// The to respect when storing the settings.
- public void Save(Stream stream, SchemeSaveFormat format)
- {
- using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII);
-
- // Write the header.
- writer.Write(_signature, StringCoding.Raw);
- writer.Write((byte)Version);
-
- // Write the options.
- writer.Write(HotSeatDelay);
- writer.Write(RetreatTime);
- writer.Write(RetreatTimeRope);
- writer.Write(ShowRoundTime);
- writer.Write(AutomaticReplays);
- writer.Write((byte)((int)FallDamage / 4 * 41 % 0x80));
- writer.Write(ArtilleryMode);
- writer.WriteEnum(SchemeEditor, false);
- writer.WriteEnum(StockpilingMode, true);
- writer.WriteEnum(WormSelectMode, true);
- writer.WriteEnum(SuddenDeathEvent, true);
- writer.Write(_mapWaterRiseToRaw[(byte)WaterRiseRate]);
- writer.Write(WeaponCrateProbability);
- writer.Write(DonorCards);
- writer.Write(HealthCrateProbability);
- writer.Write(HealthCrateEnergy);
- writer.Write(UtilityCrateProbability);
- SaveObjectTypesAndCount(writer, format);
- SaveMineDelayConfig(writer);
- writer.Write(DudMines);
- writer.Write(ManualWormPlacement);
- writer.Write(WormEnergy);
- SaveTurnTimeConfig(writer);
- SaveRoundTimeConfig(writer);
- writer.Write(NumberOfWins);
- writer.Write(Blood);
- writer.Write(AquaSheep);
- writer.Write(SheepHeaven);
- writer.Write(GodWorms);
- writer.Write(IndestructibleLand);
- writer.Write(UpgradedGrenade);
- writer.Write(UpgradedShotgun);
- writer.Write(UpgradedCluster);
- writer.Write(UpgradedLongbow);
- writer.Write(EnableTeamWeapons);
- writer.Write(EnableSuperWeapons);
-
- // Transfer the RubberWorm settings to unused weapon configuration.
- SaveRubberWormSettings();
-
- // Write the weapon settings. Old versions do not store super weapon settings.
- int weaponCount = GetWeaponCount();
- foreach (SchemeWeaponSetting weapon in Weapons)
- writer.WriteStruct(weapon);
- }
-
- ///
- /// Saves the data in the given file.
- ///
- /// The name of the file to save the data in.
- public void Save(string fileName) => Save(fileName, SchemeSaveFormat.ExtendedWithObjectCount);
-
- ///
- /// Saves the data in the given file with the specified .
- ///
- /// The name of the file to save the data in.
- /// The to respect when storing the settings.
- public void Save(string fileName, SchemeSaveFormat format)
- {
- using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
- Save(stream, format);
- }
-
- // ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
-
- private void LoadObjectTypesAndCount(BinaryStream reader)
- {
- // Invalid values default to 8 mines.
- ObjectTypes = SchemeObjectType.Mines;
- ObjectCount = SchemeObjectCount.Count8;
-
- byte raw = reader.Read1Byte();
- if (raw < 12)
- {
- // WA before 3.6.28.0 and WWP only store object type.
- switch (raw)
- {
- case 0x00:
- ObjectTypes = SchemeObjectType.None;
- break;
- case 0x02:
- ObjectTypes = SchemeObjectType.OilDrums;
- break;
- case 0x05:
- ObjectTypes = SchemeObjectType.Mines | SchemeObjectType.OilDrums;
- break;
- }
- }
- else
- {
- // WA since 3.6.28.0 encodes object type and count in one byte.
- int modulo = raw % 4;
- switch (modulo)
- {
- case 0x00:
- ObjectTypes = SchemeObjectType.None;
- break;
- case 0x02:
- ObjectTypes = SchemeObjectType.OilDrums;
- break;
- case 0x03:
- ObjectTypes = SchemeObjectType.Mines | SchemeObjectType.OilDrums;
- break;
- }
- ObjectCount = (SchemeObjectCount)_objectCounts[(raw - (8 + modulo)) / 4];
- }
- }
-
- private void LoadMineDelayConfig(BinaryStream reader)
- {
- byte raw = reader.Read1Byte();
- if (raw == 4 || raw > 0x7F)
- {
- MineDelay = 0;
- MineDelayRandom = true;
- }
- else
- {
- MineDelay = raw;
- MineDelayRandom = false;
- }
- }
-
- private void LoadTurnTimeConfig(BinaryStream reader)
- {
- byte raw = reader.Read1Byte();
- if (raw > 0x7F)
- {
- TurnTime = 0;
- TurnTimeInfinite = true;
- }
- else
- {
- TurnTime = raw;
- TurnTimeInfinite = false;
- }
- }
-
- private void LoadRoundTimeConfig(BinaryStream reader)
- {
- byte raw = reader.Read1Byte();
- if (raw > 0x7F)
- {
- RoundTimeMinutes = 0;
- RoundTimeSeconds = (byte)(raw - 0x7F);
- }
- else
- {
- RoundTimeMinutes = raw;
- RoundTimeSeconds = 0;
- }
- }
-
- private void LoadRubberWormSettings()
- {
- RwEarthquakeProb earthquakeProb = (RwEarthquakeProb)Weapons[(int)SchemeWeapon.Earthquake].Probability;
- RwAntiLockPower = earthquakeProb.HasFlag(RwEarthquakeProb.AntiLockPower);
- RwAutoReaim = earthquakeProb.HasFlag(RwEarthquakeProb.AutoReaim);
- RwCircularAim = earthquakeProb.HasFlag(RwEarthquakeProb.CircularAim);
- RwShotDoesntEndTurnAll = earthquakeProb.HasFlag(RwEarthquakeProb.ShotDoesntEndTurnAll);
- RwKaosMod = ((byte)earthquakeProb).DecodeByte(4, 4);
-
- RwAntiSink = Weapons[(int)SchemeWeapon.SheepStrike].Probability != 0;
- RwCrateLimit = (byte)Weapons[(int)SchemeWeapon.MagicBullet].Probability;
- RwCrateRate = (byte)Weapons[(int)SchemeWeapon.NuclearTest].Probability;
-
- RwMoleSquadronProb moleSquadronProb = (RwMoleSquadronProb)Weapons[(int)SchemeWeapon.MoleSquadron]
- .Probability;
- RwCrateShower = moleSquadronProb.HasFlag(RwMoleSquadronProb.CrateShower);
- RwExtendedFuse = moleSquadronProb.HasFlag(RwMoleSquadronProb.ExtendedFuse);
- RwFireDoesntPauseTimer = moleSquadronProb.HasFlag(RwMoleSquadronProb.FireDoesntPauseTimer);
- RwLoseControlDoesntEndTurn = moleSquadronProb.HasFlag(RwMoleSquadronProb.LoseControlDoesntEndTurn);
- RwObjectPushByExplosion = moleSquadronProb.HasFlag(RwMoleSquadronProb.ObjectPushByExplosion);
- RwShotDoesntEndTurn = moleSquadronProb.HasFlag(RwMoleSquadronProb.ShotDoesntEndTurn);
- RwUpgradedRope = moleSquadronProb.HasFlag(RwMoleSquadronProb.UpgradedRope);
- RwWeaponsDontChange = moleSquadronProb.HasFlag(RwMoleSquadronProb.WeaponsDontChange);
-
- RwFlameLimit = (byte)Weapons[(int)SchemeWeapon.ScalesOfJustice].Probability;
- RwFriction = (byte)Weapons[(int)SchemeWeapon.SalvationArmy].Probability;
-
- // 8th and 7th bit control constant / proportional black hole gravity, otherwise normal gravity.
- byte mailStrikeProb = (byte)Weapons[(int)SchemeWeapon.MailStrike].Probability;
- if (mailStrikeProb.GetBit(7))
- {
- if (mailStrikeProb.GetBit(6))
- RwGravityPropBlackHole = mailStrikeProb.DecodeSByte(6);
- else
- RwGravityConstBlackHole = mailStrikeProb.DecodeSByte(6);
- }
- else
- {
- RwGravity = mailStrikeProb.DecodeSByte(7);
- }
-
- RwKnockForce = (byte)Weapons[(int)SchemeWeapon.SuperBananaBomb].Probability;
- RwMaxRopeSpeed = (byte)Weapons[(int)SchemeWeapon.MineStrike].Probability;
- RwSelectWormAnytime = ((byte)Weapons[(int)SchemeWeapon.MBBomb].Probability).GetBit(1);
-
- byte[] versionBytes = new byte[2];
- versionBytes[0] = (byte)Weapons[(int)SchemeWeapon.SelectWorm].Probability;
- versionBytes[1] = (byte)Weapons[(int)SchemeWeapon.Freeze].Probability;
- RwVersionOverride = BitConverter.ToUInt16(versionBytes, 0);
-
- RwViscosity = (byte)Weapons[(int)SchemeWeapon.ConcreteDonkey].Probability;
- RwWindPower = (byte)Weapons[(int)SchemeWeapon.SuicideBomber].Probability;
- RwWormBouncyness = (byte)Weapons[(int)SchemeWeapon.Armageddon].Probability;
- }
-
- private int GetWeaponCount()
- {
- // Old versions do not store super weapon settings.
- return Version == SchemeVersion.Extended ? 64 : 45;
- }
-
- private void SaveObjectTypesAndCount(BinaryStream writer, SchemeSaveFormat format)
- {
- byte raw = 0;
- if (format == SchemeSaveFormat.ExtendedWithObjectCount)
- {
- // WA since 3.6.28.0 encodes object type and count in one byte.
- switch (ObjectTypes)
- {
- case SchemeObjectType.Mines:
- raw = 0x01;
- break;
- case SchemeObjectType.OilDrums:
- raw = 0x02;
- break;
- case SchemeObjectType.Mines | SchemeObjectType.OilDrums:
- raw = 0x03;
- break;
- }
- // Get the index of the object count and compute the raw value from that.
- int index = Array.IndexOf(_objectCounts, (byte)ObjectCount);
- raw = (byte)(index * 4 + 8 + raw);
- }
- else
- {
- // WA before 3.6.28.0 and WWP only store object type.
- switch (ObjectTypes)
- {
- case SchemeObjectType.Mines:
- raw = 0x01;
- break;
- case SchemeObjectType.OilDrums:
- raw = 0x02;
- break;
- case SchemeObjectType.Mines | SchemeObjectType.OilDrums:
- raw = 0x05;
- break;
- }
- }
- writer.Write(raw);
- }
-
- private void SaveMineDelayConfig(BinaryStream writer)
- {
- if (MineDelayRandom)
- writer.Write((byte)4);
- else
- writer.Write(MineDelay);
- }
-
- private void SaveTurnTimeConfig(BinaryStream writer)
- {
- if (TurnTimeInfinite)
- writer.Write((byte)0xFF);
- else
- writer.Write(TurnTime);
- }
-
- private void SaveRoundTimeConfig(BinaryStream writer)
- {
- if (RoundTimeSeconds > 0)
- writer.Write((byte)(0xFF - (RoundTimeSeconds - 1)));
- else
- writer.Write(RoundTimeMinutes);
- }
-
- private void SaveRubberWormSettings()
- {
- byte earthquakeProb = 0;
- if (RwAntiLockPower) earthquakeProb |= (byte)RwEarthquakeProb.AntiLockPower;
- if (RwAutoReaim) earthquakeProb |= (byte)RwEarthquakeProb.AutoReaim;
- if (RwCircularAim) earthquakeProb |= (byte)RwEarthquakeProb.CircularAim;
- if (RwShotDoesntEndTurnAll) earthquakeProb |= (byte)RwEarthquakeProb.ShotDoesntEndTurnAll;
- earthquakeProb = earthquakeProb.Encode(RwKaosMod, 4);
- Weapons[(int)SchemeWeapon.Earthquake].Probability = (sbyte)earthquakeProb;
-
- Weapons[(int)SchemeWeapon.SheepStrike].Probability = (sbyte)(RwAntiSink ? 1 : 0);
- Weapons[(int)SchemeWeapon.MagicBullet].Probability = (sbyte)RwCrateLimit;
- Weapons[(int)SchemeWeapon.NuclearTest].Probability = (sbyte)RwCrateRate;
-
- RwMoleSquadronProb moleSquadronProb = RwMoleSquadronProb.None;
- if (RwCrateShower) moleSquadronProb |= RwMoleSquadronProb.CrateShower;
- if (RwExtendedFuse) moleSquadronProb |= RwMoleSquadronProb.ExtendedFuse;
- if (RwFireDoesntPauseTimer) moleSquadronProb |= RwMoleSquadronProb.FireDoesntPauseTimer;
- if (RwLoseControlDoesntEndTurn) moleSquadronProb |= RwMoleSquadronProb.LoseControlDoesntEndTurn;
- if (RwObjectPushByExplosion) moleSquadronProb |= RwMoleSquadronProb.ObjectPushByExplosion;
- if (RwShotDoesntEndTurn) moleSquadronProb |= RwMoleSquadronProb.ShotDoesntEndTurn;
- if (RwUpgradedRope) moleSquadronProb |= RwMoleSquadronProb.UpgradedRope;
- if (RwWeaponsDontChange) moleSquadronProb |= RwMoleSquadronProb.WeaponsDontChange;
- Weapons[(int)SchemeWeapon.MoleSquadron].Probability = (sbyte)moleSquadronProb;
-
- Weapons[(int)SchemeWeapon.ScalesOfJustice].Probability = (sbyte)RwFlameLimit;
- Weapons[(int)SchemeWeapon.SalvationArmy].Probability = (sbyte)RwFriction;
-
- // 8th and 7th bit control constant / proportional black hole gravity, otherwise normal gravity.
- byte mailStrikeProb = 0;
- if (RwGravity != 0)
- {
- mailStrikeProb = mailStrikeProb.Encode(RwGravity, 7);
- }
- else if (RwGravityConstBlackHole != 0)
- {
- mailStrikeProb = mailStrikeProb.EnableBit(7);
- mailStrikeProb = mailStrikeProb.Encode(RwGravityConstBlackHole, 6);
- }
- else if (RwGravityPropBlackHole != 0)
- {
- mailStrikeProb = mailStrikeProb.EnableBit(7);
- mailStrikeProb = mailStrikeProb.EnableBit(6);
- mailStrikeProb = mailStrikeProb.Encode(RwGravityPropBlackHole, 6);
- }
- Weapons[(int)SchemeWeapon.MailStrike].Probability = (sbyte)mailStrikeProb;
-
- Weapons[(int)SchemeWeapon.SuperBananaBomb].Probability = (sbyte)RwKnockForce;
- Weapons[(int)SchemeWeapon.MineStrike].Probability = (sbyte)RwMaxRopeSpeed;
- byte mbBombProb = ((byte)Weapons[(int)SchemeWeapon.MBBomb].Probability).SetBit(0, RwSelectWormAnytime);
- Weapons[(int)SchemeWeapon.MBBomb].Probability = (sbyte)mbBombProb;
-
- byte[] versionBytes = BitConverter.GetBytes(RwVersionOverride);
- Weapons[(int)SchemeWeapon.SelectWorm].Probability = (sbyte)versionBytes[0];
- Weapons[(int)SchemeWeapon.Freeze].Probability = (sbyte)versionBytes[1];
-
- Weapons[(int)SchemeWeapon.ConcreteDonkey].Probability = (sbyte)RwViscosity;
- Weapons[(int)SchemeWeapon.SuicideBomber].Probability = (sbyte)RwWindPower;
- Weapons[(int)SchemeWeapon.Armageddon].Probability = (sbyte)RwWormBouncyness;
- }
-
- // ---- ENUMERATIONS -------------------------------------------------------------------------------------------
-
- [Flags]
- private enum RwEarthquakeProb : byte
- {
- None = 0,
- AutoReaim = 1 << 0,
- CircularAim = 1 << 1,
- AntiLockPower = 1 << 2,
- ShotDoesntEndTurnAll = 1 << 3
- // Remaining bits represent kaosmod version.
- }
-
- [Flags]
- private enum RwMoleSquadronProb : byte
- {
- None = 0,
- ShotDoesntEndTurn = 1 << 0,
- LoseControlDoesntEndTurn = 1 << 1,
- FireDoesntPauseTimer = 1 << 2,
- UpgradedRope = 1 << 3,
- CrateShower = 1 << 4,
- ObjectPushByExplosion = 1 << 5,
- WeaponsDontChange = 1 << 6,
- ExtendedFuse = 1 << 7
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Syroot.BinaryData;
+using Syroot.Worms.Core;
+using Syroot.Worms.Core.IO;
+
+namespace Syroot.Worms.Armageddon
+{
+ ///
+ /// Represents a scheme stored in a WSC file which contains game settings and armory configuration, including
+ /// RubberWorm settings encoded in those.
+ /// Used by WA and WWP. S. https://worms2d.info/Game_scheme_file.
+ ///
+ public class Scheme : ILoadableFile, ISaveableFile
+ {
+ // ---- CONSTANTS ----------------------------------------------------------------------------------------------
+
+ private const string _signature = "SCHM";
+
+ private const int _objectCount5Step = 30;
+ private const int _objectCount10Step = 44;
+ private const int _objectCountLastStep = 59;
+
+ // Lookup tables.
+ private static readonly Dictionary _mapWaterRiseToRaw = new Dictionary()
+ {
+ [0] = 0,
+ [5] = 1,
+ [13] = 19,
+ [20] = 2,
+ [21] = 55,
+ [29] = 43,
+ [37] = 47,
+ [45] = 3,
+ [52] = 26,
+ [53] = 25,
+ [61] = 27,
+ [64] = 8,
+ [69] = 33,
+ [77] = 13,
+ [80] = 4,
+ [84] = 18,
+ [85] = 23,
+ [93] = 11,
+ [101] = 15,
+ [109] = 29,
+ [116] = 22,
+ [117] = 57,
+ [125] = 5,
+ [133] = 63,
+ [141] = 45,
+ [148] = 30,
+ [149] = 9,
+ [157] = 21,
+ [165] = 17,
+ [173] = 61,
+ [180] = 6,
+ [181] = 39,
+ [189] = 37,
+ [197] = 31,
+ [205] = 51,
+ [208] = 12,
+ [212] = 14,
+ [213] = 41,
+ [221] = 53,
+ [229] = 49,
+ [237] = 35,
+ [244] = 10,
+ [245] = 7,
+ [253] = 59
+ };
+
+ // ---- MEMBERS ------------------------------------------------------------------------------------------------
+
+ private byte _objectCount;
+ private byte _mineDelay;
+ private byte _turnTime;
+ private byte _roundTimeMinutes;
+ private byte _roundTimeSeconds;
+ private byte _numberOfWins;
+ private sbyte _rwGravity;
+ private sbyte _rwGravityConstBlackHole;
+ private sbyte _rwGravityPropBlackHole;
+ private byte _rwKaosMod;
+
+ // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Scheme()
+ {
+ Version = SchemeVersion.Extended;
+ Weapons = new SchemeWeaponSetting[GetWeaponCount()];
+ }
+
+ ///
+ /// Initializes a new instance of the class, loading the data from the given
+ /// .
+ ///
+ /// The to load the data from.
+ public Scheme(Stream stream) => Load(stream);
+
+ ///
+ /// Initializes a new instance of the class, loading the data from the given file.
+ ///
+ /// The name of the file to load the data from.
+ public Scheme(string fileName) => Load(fileName);
+
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ ///
+ /// Gets or sets the of this scheme, controlling whether super weapon settings
+ /// are stored or not.
+ ///
+ public SchemeVersion Version { get; set; }
+
+ ///
+ /// Gets or sets the delay in seconds between each team's turn to allow relaxed switching of seats.
+ ///
+ public byte HotSeatDelay { get; set; }
+
+ ///
+ /// Gets or sets the time in seconds available for a worm to retreat after using a weapon which ends the turn
+ /// while standing on land.
+ ///
+ public byte RetreatTime { get; set; }
+
+ ///
+ /// Gets or sets the time in seconds available for a worm to retreat after using a weapon which ends the turn
+ /// while on a rope.
+ ///
+ public byte RetreatTimeRope { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the total round time until sudden death will be displayed in the
+ /// turn timer.
+ ///
+ public bool ShowRoundTime { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether significant turns will be replayed in offline games.
+ ///
+ public bool AutomaticReplays { get; set; }
+
+ ///
+ /// Gets or sets the percentual amount of fall damage applied, relative to normal fall damage being 100%.
+ ///
+ public SchemeFallDamage FallDamage { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether worms cannot walk and are mostly stuck at their current position
+ /// without using any utilities.
+ ///
+ public bool ArtilleryMode { get; set; }
+
+ ///
+ /// Gets or sets a value indicating the scheme editor used to modify this scheme. Originally used to indicate
+ /// the unimplemented Bounty Mode.
+ ///
+ public SchemeEditor SchemeEditor { get; set; }
+
+ ///
+ /// Gets or sets a value indicating the stockpiling of armory between game rounds.
+ ///
+ public SchemeStockpiling StockpilingMode { get; set; }
+
+ ///
+ /// Gets or sets a value indicating the worm selection order determining the next worm to be played.
+ ///
+ public SchemeWormSelect WormSelectMode { get; set; }
+
+ ///
+ /// Gets or sets a value indicating the action triggered when Sudden Death starts.
+ ///
+ public SchemeSuddenDeathEvent SuddenDeathEvent { get; set; }
+
+ ///
+ /// Gets or sets the amount in pixels which the water will rise between turns after Sudden Death was triggered.
+ ///
+ public SchemeWaterRise WaterRiseRate { get; set; }
+
+ ///
+ /// Gets or sets the percentual probability of a weapon crate to drop between turns. Negative values might crash
+ /// the game.
+ ///
+ public sbyte WeaponCrateProbability { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether donor cards can spawn upon a worm's death.
+ ///
+ public bool DonorCards { get; set; }
+
+ ///
+ /// Gets or sets the percentual probability of a health crate to drop between turns. Negative values might crash
+ /// the game.
+ ///
+ public sbyte HealthCrateProbability { get; set; }
+
+ ///
+ /// Gets or sets the amount of health included in a health crate added to the collecting worm's energy.
+ ///
+ public byte HealthCrateEnergy { get; set; }
+
+ ///
+ /// Gets or sets the percentual probability of a utility crate to drop between turns. Negative values might
+ /// crash the game.
+ ///
+ public sbyte UtilityCrateProbability { get; set; }
+
+ ///
+ /// Gets or sets the type of objects which can be placed on the map.
+ ///
+ public SchemeObjectType ObjectTypes { get; set; }
+
+ ///
+ /// Gets or sets the maximum number of objects (mines or oil drums) on the map. Note that setting this value
+ /// rounds it valid count.
+ ///
+ public byte ObjectCount
+ {
+ get => _objectCount;
+ set
+ {
+ if (value > 100)
+ _objectCount = (byte)(value - value % 10);
+ else if (value > 30)
+ _objectCount = (byte)(value - value % 5);
+ else if (value == 0)
+ _objectCount = 1;
+ else
+ _objectCount = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the number of seconds a mine requires to explode. Can be 1-3 and 5-127 seconds.
+ ///
+ public byte MineDelay
+ {
+ get => _mineDelay;
+ set
+ {
+ if (value == 4 || value > 0x7F)
+ throw new ArgumentException("Mine delay must be between 0-127 and not be 4.", nameof(value));
+ _mineDelay = value;
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the mine fuse will be randomly chosen between fractions of 1 to 3
+ /// seconds. If true, the setting will be ignored.
+ ///
+ public bool MineDelayRandom { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether mines can refuse to explode after their count down.
+ ///
+ public bool DudMines { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether worms are placed manually by the players for their initial position
+ /// at round start.
+ ///
+ public bool ManualWormPlacement { get; set; }
+
+ ///
+ /// Gets or sets the initial worm energy at round start.
+ ///
+ public byte WormEnergy { get; set; }
+
+ ///
+ /// Gets or sets the turn time in seconds available for the player to move. Must be in the range of 0-127.
+ ///
+ public byte TurnTime
+ {
+ get => _turnTime;
+ set
+ {
+ if (value > 0x7F)
+ throw new ArgumentException("Turn time must be between 0-127.", nameof(value));
+ _turnTime = value;
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the turn time is unlimited. If true, the
+ /// setting will be ignored.
+ ///
+ public bool TurnTimeInfinite { get; set; }
+
+ ///
+ /// Gets or sets the round time before sudden death is triggered between 0-127 minutes.
+ ///
+ public byte RoundTimeMinutes
+ {
+ get => _roundTimeMinutes;
+ set
+ {
+ if (value > 0x7F)
+ throw new ArgumentException("Round time must be between 0-127 minutes.", nameof(value));
+ _roundTimeMinutes = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the round time before sudden death is triggered in between 0-128 seconds. When 0,
+ /// is used instead.
+ ///
+ public byte RoundTimeSeconds
+ {
+ get => _roundTimeSeconds;
+ set
+ {
+ if (value > 0x80)
+ throw new ArgumentException("Round time must be between 0-128 seconds.", nameof(value));
+ _roundTimeSeconds = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the number of round wins required to win the game. Must not be 0.
+ ///
+ public byte NumberOfWins
+ {
+ get => _numberOfWins;
+ set
+ {
+ if (value == 0)
+ throw new ArgumentException("Number of wins must not be 0.", nameof(value));
+ _numberOfWins = value;
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether blood effects are enabled.
+ ///
+ public bool Blood { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the Super Sheep weapon gets upgraded to the Aqua Sheep, which can
+ /// fly underwater.
+ ///
+ public bool AquaSheep { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether sheeps will jump out of exploding crates.
+ ///
+ public bool SheepHeaven { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether worms have infinity energy, killable only by drowning them.
+ ///
+ public bool GodWorms { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether terrain cannot be destroyed by explosions.
+ ///
+ public bool IndestructibleLand { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the Grenade weapon is more powerful.
+ ///
+ public bool UpgradedGrenade { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the Shotgun weapon shoots twice for each of the two shots.
+ ///
+ public bool UpgradedShotgun { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether cluster weapon explode into more clusters.
+ ///
+ public bool UpgradedCluster { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the Longbow weapon is more powerful.
+ ///
+ public bool UpgradedLongbow { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether team weapons will be given to the teams, overriding the default
+ /// weapon settings for them.
+ ///
+ public bool EnableTeamWeapons { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether super weapons can be collected from crates.
+ ///
+ public bool EnableSuperWeapons { get; set; }
+
+ ///
+ /// Gets the array of instances, each mapping to one weapon at the index of
+ /// the enumeration. Depending on the scheme , super weapons
+ /// might not be stored in this array.
+ ///
+ public SchemeWeaponSetting[] Weapons { get; set; }
+
+ // ---- RubberWorm Settings ----
+
+ ///
+ /// Gets or sets a value whether power is unlocked like in TestStuff. Configurable with the /alp command.
+ ///
+ public bool RwAntiLockPower { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether worms falling into water will be reset to the last solid location
+ /// they stood on. Configurable with the /antisink command.
+ ///
+ public bool RwAntiSink { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the aim direction of a weapon will be reset at turn start.
+ /// Configurable with the /reaim command.
+ ///
+ public bool RwAutoReaim { get; set; }
+
+ ///
+ /// Gets or sets a value whether the aim of a weapon loops in full rather than half circles. Configurable with
+ /// the /cira command.
+ ///
+ public bool RwCircularAim { get; set; }
+
+ ///
+ /// Gets or sets the maximum number of crates existing on the map at the same time. 0 disables this feature,
+ /// default limit is 5. Configurable with the /cratelimit command.
+ ///
+ public byte RwCrateLimit { get; set; }
+
+ ///
+ /// Gets or sets the maximum number of crates spawning per turn and enables the crate counter. Configurable with
+ /// the /craterate command.
+ ///
+ public byte RwCrateRate { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether crate shower is enabled throughout a turn. Configurable with the
+ /// /crateshower command.
+ ///
+ public bool RwCrateShower { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether weapon fuses can be selected between 0-9 seconds and herd counts
+ /// between 1-10 animals. Configurable with the /fuseex command.
+ ///
+ public bool RwExtendedFuse { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the turn timer is paused while launching a weapon. Configurable with
+ /// the /fdpt or /nopause commands.
+ ///
+ public bool RwFireDoesntPauseTimer { get; set; }
+
+ ///
+ /// Gets or sets the maximum number of flame particles active at the same time in the scale of 100x.
+ /// Configurable with the /flames command.
+ ///
+ public byte RwFlameLimit { get; set; }
+
+ ///
+ /// Gets or sets the friction deaccelerating objects touching solid ground. 96 is default, 100 is no friction,
+ /// higher values accelerate objects. Configurable with the /friction command.
+ ///
+ public byte RwFriction { get; set; }
+
+ ///
+ /// Gets or sets the amount of gravity. Ranges from -64-63 where 0 and 12 are default gravity and negative
+ /// values pull objects upwards. Configurable with the /gravity command. When set,
+ /// and are reset.
+ ///
+ public sbyte RwGravity
+ {
+ get => _rwGravity;
+ set
+ {
+ if (value != 0)
+ {
+ RwGravityConstBlackHole = 0;
+ RwGravityPropBlackHole = 0;
+ }
+ _rwGravity = value;
+ }
+ }
+
+ ///
+ /// gets or sets the amount of gravity acting as a constant black hole. Ranges from -32 to 31. Configurable with
+ /// the /cbh command. When set, and are reset.
+ ///
+ public sbyte RwGravityConstBlackHole
+ {
+ get => _rwGravityConstBlackHole;
+ set
+ {
+ if (value != 0)
+ {
+ RwGravity = 0;
+ RwGravityPropBlackHole = 0;
+ }
+ _rwGravityConstBlackHole = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the amount of gravity acting as a proportional black hole. Ranges from -32 to 31. Configurable
+ /// with the /pbh command. When set, and are
+ /// reset.
+ ///
+ public sbyte RwGravityPropBlackHole
+ {
+ get => _rwGravityPropBlackHole;
+ set
+ {
+ if (value != 0)
+ {
+ RwGravity = 0;
+ RwGravityConstBlackHole = 0;
+ }
+ _rwGravityPropBlackHole = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the Kaos game scheme mod. 0 for none, 1-5 for the corresponding mod. Configurable with the
+ /// /kaosmod command.
+ ///
+ public byte RwKaosMod
+ {
+ get => _rwKaosMod;
+ set
+ {
+ if (value > 0xF)
+ throw new ArgumentException("Kaos mod must not be greater than 15.");
+ _rwKaosMod = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the rope knocking power in percent, where 100 is the default power. Configurable with the
+ /// /knock command.
+ ///
+ public byte RwKnockForce { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the loss of control while moving a worm ends does no longer end the
+ /// turn and allows the player to continue moving. Configurable with the /ldet or /stoicworm commands.
+ ///
+ public bool RwLoseControlDoesntEndTurn { get; set; }
+
+ ///
+ /// Gets or sets the maximum speed a player can reach while roping. 16 is default, 32 is like in TestStuff, 255
+ /// is unlimited. Configurable with the /speed command.
+ ///
+ public byte RwMaxRopeSpeed { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether using a weapon does no longer end the turn and allows to shoot
+ /// multiple weapons in one turn. Configurable with the /sdet or /multishot commands.
+ ///
+ public bool RwShotDoesntEndTurn { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the weapons Armageddon, Earthquake and Indian Nuke Test are affected
+ /// by aswell. Configurable with the /usw command.
+ ///
+ public bool RwShotDoesntEndTurnAll { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether all objects are pushed by explosions near them. Configurable with
+ /// the /ope command.
+ ///
+ public bool RwObjectPushByExplosion { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether worms can be selected at any time during the turn, as long as worm
+ /// selection is activated. Configurable with the /swat command.
+ ///
+ public bool RwSelectWormAnytime { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the Ninja Rope is more powerful. Configurable with the /ir or /rope+
+ /// commands.
+ ///
+ public bool RwUpgradedRope { get; set; }
+
+ ///
+ /// Gets or sets the (special) game version to be forced. Configurable with the /version command.
+ /// S. http://worms2d.info/List_of_Worms_Armageddon_logic_versions.
+ ///
+ public ushort RwVersionOverride { get; set; }
+
+ ///
+ /// Gets or sets the amount of air viscosity affecting objects. Odd numbers affect worms too. Configurable with
+ /// the /visc command.
+ ///
+ public byte RwViscosity { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the selected weapon no longer resets to a remembered one upon
+ /// shooting it. Configurable with the /wdca command.
+ ///
+ public bool RwWeaponsDontChange { get; set; }
+
+ ///
+ /// Gets or sets the influence power of the wind affecting all weapons. 255 is the same influence as the
+ /// Bazooka. Odd numbers affect worms too. Configurable with the /wind command.
+ ///
+ public byte RwWindPower { get; set; }
+
+ ///
+ /// Gets or sets the power with which worms bounce off terrain, where 0 disables this feature and 255 fully
+ /// bounces worms back without speed loss. Configurable with the /rubber command.
+ ///
+ public byte RwWormBouncyness { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Loads the data from the given .
+ ///
+ /// The to load the data from.
+ public void Load(Stream stream)
+ {
+ using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
+
+ // Read the header.
+ if (reader.ReadString(_signature.Length) != _signature)
+ throw new InvalidDataException("Invalid WSC file signature.");
+ Version = reader.ReadEnum(true);
+
+ // Read the options.
+ HotSeatDelay = reader.Read1Byte();
+ RetreatTime = reader.Read1Byte();
+ RetreatTimeRope = reader.Read1Byte();
+ ShowRoundTime = reader.ReadBoolean();
+ AutomaticReplays = reader.ReadBoolean();
+ FallDamage = (SchemeFallDamage)(reader.ReadByte() * 50 % 0x100 * 2);
+ ArtilleryMode = reader.ReadBoolean();
+ SchemeEditor = reader.ReadEnum(false);
+ StockpilingMode = reader.ReadEnum(true);
+ WormSelectMode = reader.ReadEnum(true);
+ SuddenDeathEvent = reader.ReadEnum(true);
+ WaterRiseRate = (SchemeWaterRise)(Math.Pow(reader.ReadByte(), 2) * 5 % 0x100);
+ WeaponCrateProbability = reader.ReadSByte();
+ DonorCards = reader.ReadBoolean();
+ HealthCrateProbability = reader.ReadSByte();
+ HealthCrateEnergy = reader.Read1Byte();
+ UtilityCrateProbability = reader.ReadSByte();
+ LoadObjectTypesAndCount(reader);
+ LoadMineDelayConfig(reader);
+ DudMines = reader.ReadBoolean();
+ ManualWormPlacement = reader.ReadBoolean();
+ WormEnergy = reader.Read1Byte();
+ LoadTurnTimeConfig(reader);
+ LoadRoundTimeConfig(reader);
+ NumberOfWins = (byte)Math.Max(1, reader.ReadByte());
+ Blood = reader.ReadBoolean();
+ AquaSheep = reader.ReadBoolean();
+ SheepHeaven = reader.ReadBoolean();
+ GodWorms = reader.ReadBoolean();
+ IndestructibleLand = reader.ReadBoolean();
+ UpgradedGrenade = reader.ReadBoolean();
+ UpgradedShotgun = reader.ReadBoolean();
+ UpgradedCluster = reader.ReadBoolean();
+ UpgradedLongbow = reader.ReadBoolean();
+ EnableTeamWeapons = reader.ReadBoolean();
+ EnableSuperWeapons = reader.ReadBoolean();
+
+ // Read the weapon settings. Old versions do not store super weapon settings.
+ Weapons = new SchemeWeaponSetting[64];
+ int weaponCount = GetWeaponCount();
+ for (int i = 0; i < weaponCount; i++)
+ Weapons[i] = reader.ReadStruct();
+
+ // Ignore possible unknown WWP trash at the end of the file.
+
+ // Parse the RubberWorm settings.
+ LoadRubberWormSettings();
+ }
+
+ ///
+ /// Loads the data from the given file.
+ ///
+ /// The name of the file to load the data from.
+ public void Load(string fileName)
+ {
+ using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
+ Load(stream);
+ }
+
+ ///
+ /// Saves the data into the given .
+ ///
+ /// The to save the data to.
+ public void Save(Stream stream) => Save(stream, SchemeSaveFormat.ExtendedWithObjectCount);
+
+ ///
+ /// Saves the data into the given with the specified .
+ ///
+ /// The to save the data to.
+ /// The to respect when storing the settings.
+ public void Save(Stream stream, SchemeSaveFormat format)
+ {
+ using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
+
+ // Write the header.
+ writer.Write(_signature, StringCoding.Raw);
+ writer.Write((byte)Version);
+
+ // Write the options.
+ writer.Write(HotSeatDelay);
+ writer.Write(RetreatTime);
+ writer.Write(RetreatTimeRope);
+ writer.Write(ShowRoundTime);
+ writer.Write(AutomaticReplays);
+ writer.Write((byte)((int)FallDamage / 4 * 41 % 0x80));
+ writer.Write(ArtilleryMode);
+ writer.WriteEnum(SchemeEditor, false);
+ writer.WriteEnum(StockpilingMode, true);
+ writer.WriteEnum(WormSelectMode, true);
+ writer.WriteEnum(SuddenDeathEvent, true);
+ writer.Write(_mapWaterRiseToRaw[(byte)WaterRiseRate]);
+ writer.Write(WeaponCrateProbability);
+ writer.Write(DonorCards);
+ writer.Write(HealthCrateProbability);
+ writer.Write(HealthCrateEnergy);
+ writer.Write(UtilityCrateProbability);
+ SaveObjectTypesAndCount(writer, format);
+ SaveMineDelayConfig(writer);
+ writer.Write(DudMines);
+ writer.Write(ManualWormPlacement);
+ writer.Write(WormEnergy);
+ SaveTurnTimeConfig(writer);
+ SaveRoundTimeConfig(writer);
+ writer.Write(NumberOfWins);
+ writer.Write(Blood);
+ writer.Write(AquaSheep);
+ writer.Write(SheepHeaven);
+ writer.Write(GodWorms);
+ writer.Write(IndestructibleLand);
+ writer.Write(UpgradedGrenade);
+ writer.Write(UpgradedShotgun);
+ writer.Write(UpgradedCluster);
+ writer.Write(UpgradedLongbow);
+ writer.Write(EnableTeamWeapons);
+ writer.Write(EnableSuperWeapons);
+
+ // Transfer the RubberWorm settings to unused weapon configuration.
+ SaveRubberWormSettings();
+
+ // Write the weapon settings. Old versions do not store super weapon settings.
+ int weaponCount = GetWeaponCount();
+ foreach (SchemeWeaponSetting weapon in Weapons)
+ writer.WriteStruct(weapon);
+ }
+
+ ///
+ /// Saves the data in the given file.
+ ///
+ /// The name of the file to save the data in.
+ public void Save(string fileName) => Save(fileName, SchemeSaveFormat.ExtendedWithObjectCount);
+
+ ///
+ /// Saves the data in the given file with the specified .
+ ///
+ /// The name of the file to save the data in.
+ /// The to respect when storing the settings.
+ public void Save(string fileName, SchemeSaveFormat format)
+ {
+ using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
+ Save(stream, format);
+ }
+
+ // ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
+
+ private void LoadObjectTypesAndCount(BinaryStream reader)
+ {
+ byte raw = reader.Read1Byte();
+ switch (raw)
+ {
+ case 3: case 4: raw = 1; break;
+ case 6: case 7: raw = 0; break;
+ }
+
+ // Determine object count.
+ int step = Math.Min(raw < 8 ? 8 : raw / 4 - 2, _objectCountLastStep);
+ if (step >= _objectCount10Step)
+ step = 100 + 10 * (step - _objectCount10Step);
+ else if (step >= _objectCount5Step)
+ step = 30 + 5 * (step - _objectCount5Step);
+ ObjectCount = (byte)step;
+
+ // Determine object types.
+ ObjectTypes = raw == 5 // old "both" value
+ ? SchemeObjectType.Both
+ : (SchemeObjectType)(raw & (byte)SchemeObjectType.Both);
+ }
+
+ private void LoadMineDelayConfig(BinaryStream reader)
+ {
+ byte raw = reader.Read1Byte();
+ if (raw == 4 || raw > 0x7F)
+ {
+ MineDelay = 0;
+ MineDelayRandom = true;
+ }
+ else
+ {
+ MineDelay = raw;
+ MineDelayRandom = false;
+ }
+ }
+
+ private void LoadTurnTimeConfig(BinaryStream reader)
+ {
+ byte raw = reader.Read1Byte();
+ if (raw > 0x7F)
+ {
+ TurnTime = 0;
+ TurnTimeInfinite = true;
+ }
+ else
+ {
+ TurnTime = raw;
+ TurnTimeInfinite = false;
+ }
+ }
+
+ private void LoadRoundTimeConfig(BinaryStream reader)
+ {
+ byte raw = reader.Read1Byte();
+ if (raw > 0x7F)
+ {
+ RoundTimeMinutes = 0;
+ RoundTimeSeconds = (byte)(raw - 0x7F);
+ }
+ else
+ {
+ RoundTimeMinutes = raw;
+ RoundTimeSeconds = 0;
+ }
+ }
+
+ private void LoadRubberWormSettings()
+ {
+ RwEarthquakeProb earthquakeProb = (RwEarthquakeProb)Weapons[(int)SchemeWeapon.Earthquake].Probability;
+ RwAntiLockPower = earthquakeProb.HasFlag(RwEarthquakeProb.AntiLockPower);
+ RwAutoReaim = earthquakeProb.HasFlag(RwEarthquakeProb.AutoReaim);
+ RwCircularAim = earthquakeProb.HasFlag(RwEarthquakeProb.CircularAim);
+ RwShotDoesntEndTurnAll = earthquakeProb.HasFlag(RwEarthquakeProb.ShotDoesntEndTurnAll);
+ RwKaosMod = ((byte)earthquakeProb).DecodeByte(4, 4);
+
+ RwAntiSink = Weapons[(int)SchemeWeapon.SheepStrike].Probability != 0;
+ RwCrateLimit = (byte)Weapons[(int)SchemeWeapon.MagicBullet].Probability;
+ RwCrateRate = (byte)Weapons[(int)SchemeWeapon.NuclearTest].Probability;
+
+ RwMoleSquadronProb moleSquadronProb = (RwMoleSquadronProb)Weapons[(int)SchemeWeapon.MoleSquadron]
+ .Probability;
+ RwCrateShower = moleSquadronProb.HasFlag(RwMoleSquadronProb.CrateShower);
+ RwExtendedFuse = moleSquadronProb.HasFlag(RwMoleSquadronProb.ExtendedFuse);
+ RwFireDoesntPauseTimer = moleSquadronProb.HasFlag(RwMoleSquadronProb.FireDoesntPauseTimer);
+ RwLoseControlDoesntEndTurn = moleSquadronProb.HasFlag(RwMoleSquadronProb.LoseControlDoesntEndTurn);
+ RwObjectPushByExplosion = moleSquadronProb.HasFlag(RwMoleSquadronProb.ObjectPushByExplosion);
+ RwShotDoesntEndTurn = moleSquadronProb.HasFlag(RwMoleSquadronProb.ShotDoesntEndTurn);
+ RwUpgradedRope = moleSquadronProb.HasFlag(RwMoleSquadronProb.UpgradedRope);
+ RwWeaponsDontChange = moleSquadronProb.HasFlag(RwMoleSquadronProb.WeaponsDontChange);
+
+ RwFlameLimit = (byte)Weapons[(int)SchemeWeapon.ScalesOfJustice].Probability;
+ RwFriction = (byte)Weapons[(int)SchemeWeapon.SalvationArmy].Probability;
+
+ // 8th and 7th bit control constant / proportional black hole gravity, otherwise normal gravity.
+ byte mailStrikeProb = (byte)Weapons[(int)SchemeWeapon.MailStrike].Probability;
+ if (!mailStrikeProb.GetBit(7))
+ RwGravity = mailStrikeProb.DecodeSByte(7);
+ else if (mailStrikeProb.GetBit(6))
+ RwGravityPropBlackHole = mailStrikeProb.DecodeSByte(6);
+ else
+ RwGravityConstBlackHole = mailStrikeProb.DecodeSByte(6);
+
+ RwKnockForce = (byte)Weapons[(int)SchemeWeapon.SuperBananaBomb].Probability;
+ RwMaxRopeSpeed = (byte)Weapons[(int)SchemeWeapon.MineStrike].Probability;
+ RwSelectWormAnytime = ((byte)Weapons[(int)SchemeWeapon.MBBomb].Probability).GetBit(1);
+
+ byte[] versionBytes = new byte[2];
+ versionBytes[0] = (byte)Weapons[(int)SchemeWeapon.SelectWorm].Probability;
+ versionBytes[1] = (byte)Weapons[(int)SchemeWeapon.Freeze].Probability;
+ RwVersionOverride = BitConverter.ToUInt16(versionBytes, 0);
+
+ RwViscosity = (byte)Weapons[(int)SchemeWeapon.ConcreteDonkey].Probability;
+ RwWindPower = (byte)Weapons[(int)SchemeWeapon.SuicideBomber].Probability;
+ RwWormBouncyness = (byte)Weapons[(int)SchemeWeapon.Armageddon].Probability;
+ }
+
+ private int GetWeaponCount()
+ {
+ // Old versions do not store super weapon settings.
+ return Version == SchemeVersion.Extended ? 64 : 45;
+ }
+
+ private void SaveObjectTypesAndCount(BinaryStream writer, SchemeSaveFormat format)
+ {
+ byte raw;
+ if (format == SchemeSaveFormat.ExtendedWithObjectCount && ObjectCount != 8)
+ {
+ // WA since 3.6.28.0 encodes object type and count in one byte.
+ raw = (byte)ObjectTypes;
+
+ int step = ObjectCount;
+ if (ObjectCount >= 100)
+ step = _objectCount10Step + (ObjectCount - 100) / 10;
+ else if (ObjectCount >= 30)
+ step = _objectCount5Step + (ObjectCount - 30) / 5;
+ raw |= (byte)(4 * step + 8);
+ }
+ else
+ {
+ // WA before 3.6.28.0 and WWP only store object type.
+ raw = ObjectTypes == SchemeObjectType.Both ? (byte)5 : (byte)ObjectTypes;
+ }
+ writer.Write(raw);
+ }
+
+ private void SaveMineDelayConfig(BinaryStream writer)
+ {
+ if (MineDelayRandom)
+ writer.Write((byte)4);
+ else
+ writer.Write(MineDelay);
+ }
+
+ private void SaveTurnTimeConfig(BinaryStream writer)
+ {
+ if (TurnTimeInfinite)
+ writer.Write((byte)0xFF);
+ else
+ writer.Write(TurnTime);
+ }
+
+ private void SaveRoundTimeConfig(BinaryStream writer)
+ {
+ if (RoundTimeSeconds > 0)
+ writer.Write((byte)(0xFF - (RoundTimeSeconds - 1)));
+ else
+ writer.Write(RoundTimeMinutes);
+ }
+
+ private void SaveRubberWormSettings()
+ {
+ byte earthquakeProb = 0;
+ if (RwAntiLockPower) earthquakeProb |= (byte)RwEarthquakeProb.AntiLockPower;
+ if (RwAutoReaim) earthquakeProb |= (byte)RwEarthquakeProb.AutoReaim;
+ if (RwCircularAim) earthquakeProb |= (byte)RwEarthquakeProb.CircularAim;
+ if (RwShotDoesntEndTurnAll) earthquakeProb |= (byte)RwEarthquakeProb.ShotDoesntEndTurnAll;
+ earthquakeProb = earthquakeProb.Encode(RwKaosMod, 4);
+ Weapons[(int)SchemeWeapon.Earthquake].Probability = (sbyte)earthquakeProb;
+
+ Weapons[(int)SchemeWeapon.SheepStrike].Probability = (sbyte)(RwAntiSink ? 1 : 0);
+ Weapons[(int)SchemeWeapon.MagicBullet].Probability = (sbyte)RwCrateLimit;
+ Weapons[(int)SchemeWeapon.NuclearTest].Probability = (sbyte)RwCrateRate;
+
+ RwMoleSquadronProb moleSquadronProb = RwMoleSquadronProb.None;
+ if (RwCrateShower) moleSquadronProb |= RwMoleSquadronProb.CrateShower;
+ if (RwExtendedFuse) moleSquadronProb |= RwMoleSquadronProb.ExtendedFuse;
+ if (RwFireDoesntPauseTimer) moleSquadronProb |= RwMoleSquadronProb.FireDoesntPauseTimer;
+ if (RwLoseControlDoesntEndTurn) moleSquadronProb |= RwMoleSquadronProb.LoseControlDoesntEndTurn;
+ if (RwObjectPushByExplosion) moleSquadronProb |= RwMoleSquadronProb.ObjectPushByExplosion;
+ if (RwShotDoesntEndTurn) moleSquadronProb |= RwMoleSquadronProb.ShotDoesntEndTurn;
+ if (RwUpgradedRope) moleSquadronProb |= RwMoleSquadronProb.UpgradedRope;
+ if (RwWeaponsDontChange) moleSquadronProb |= RwMoleSquadronProb.WeaponsDontChange;
+ Weapons[(int)SchemeWeapon.MoleSquadron].Probability = (sbyte)moleSquadronProb;
+
+ Weapons[(int)SchemeWeapon.ScalesOfJustice].Probability = (sbyte)RwFlameLimit;
+ Weapons[(int)SchemeWeapon.SalvationArmy].Probability = (sbyte)RwFriction;
+
+ // 8th and 7th bit control constant / proportional black hole gravity, otherwise normal gravity.
+ byte mailStrikeProb = 0;
+ if (RwGravity != 0)
+ {
+ mailStrikeProb = mailStrikeProb.Encode(RwGravity, 7);
+ }
+ else if (RwGravityConstBlackHole != 0)
+ {
+ mailStrikeProb = mailStrikeProb.EnableBit(7);
+ mailStrikeProb = mailStrikeProb.Encode(RwGravityConstBlackHole, 6);
+ }
+ else if (RwGravityPropBlackHole != 0)
+ {
+ mailStrikeProb = mailStrikeProb.EnableBit(7);
+ mailStrikeProb = mailStrikeProb.EnableBit(6);
+ mailStrikeProb = mailStrikeProb.Encode(RwGravityPropBlackHole, 6);
+ }
+ Weapons[(int)SchemeWeapon.MailStrike].Probability = (sbyte)mailStrikeProb;
+
+ Weapons[(int)SchemeWeapon.SuperBananaBomb].Probability = (sbyte)RwKnockForce;
+ Weapons[(int)SchemeWeapon.MineStrike].Probability = (sbyte)RwMaxRopeSpeed;
+ byte mbBombProb = ((byte)Weapons[(int)SchemeWeapon.MBBomb].Probability).SetBit(0, RwSelectWormAnytime);
+ Weapons[(int)SchemeWeapon.MBBomb].Probability = (sbyte)mbBombProb;
+
+ byte[] versionBytes = BitConverter.GetBytes(RwVersionOverride);
+ Weapons[(int)SchemeWeapon.SelectWorm].Probability = (sbyte)versionBytes[0];
+ Weapons[(int)SchemeWeapon.Freeze].Probability = (sbyte)versionBytes[1];
+
+ Weapons[(int)SchemeWeapon.ConcreteDonkey].Probability = (sbyte)RwViscosity;
+ Weapons[(int)SchemeWeapon.SuicideBomber].Probability = (sbyte)RwWindPower;
+ Weapons[(int)SchemeWeapon.Armageddon].Probability = (sbyte)RwWormBouncyness;
+ }
+
+ // ---- ENUMERATIONS -------------------------------------------------------------------------------------------
+
+ [Flags]
+ private enum RwEarthquakeProb : byte
+ {
+ None = 0,
+ AutoReaim = 1 << 0,
+ CircularAim = 1 << 1,
+ AntiLockPower = 1 << 2,
+ ShotDoesntEndTurnAll = 1 << 3
+ // Remaining bits represent kaosmod version.
+ }
+
+ [Flags]
+ private enum RwMoleSquadronProb : byte
+ {
+ None = 0,
+ ShotDoesntEndTurn = 1 << 0,
+ LoseControlDoesntEndTurn = 1 << 1,
+ FireDoesntPauseTimer = 1 << 2,
+ UpgradedRope = 1 << 3,
+ CrateShower = 1 << 4,
+ ObjectPushByExplosion = 1 << 5,
+ WeaponsDontChange = 1 << 6,
+ ExtendedFuse = 1 << 7
+ }
+ }
+}
diff --git a/src/library/Syroot.Worms.Armageddon/SchemeEnums.cs b/src/library/Syroot.Worms.Armageddon/SchemeEnums.cs
index 78e4a54..295b74a 100644
--- a/src/library/Syroot.Worms.Armageddon/SchemeEnums.cs
+++ b/src/library/Syroot.Worms.Armageddon/SchemeEnums.cs
@@ -1,1624 +1,1319 @@
-using System;
-
-namespace Syroot.Worms.Armageddon
-{
- ///
- /// Represents the known versions of scheme file formats.
- ///
- public enum SchemeVersion : byte
- {
- ///
- /// The standard format used by WA before version 3.6.28.0 and WWP. It does not store super weapon settings.
- ///
- Standard = 1,
-
- ///
- /// The extended format used by WA since version 3.6.28.0.
- ///
- Extended = 2
- }
-
- ///
- /// Represents the possible variations of the options stored in a scheme file.
- ///
- public enum SchemeSaveFormat
- {
- ///
- /// Represents the format.
- ///
- Standard,
-
- ///
- /// Represents the format, and does not store object counts.
- ///
- Extended,
-
- ///
- /// Represents the format, and stores object counts (supported since WA
- /// 3.6.28.0).
- ///
- ExtendedWithObjectCount
- }
-
- ///
- /// Represents the fall damage in percent, relative to the normal fall damage being 100%.
- ///
- public enum SchemeFallDamage
- {
- ///
- /// No fall damage.
- ///
- None = 0,
-
- ///
- /// 4% fall damage.
- ///
- Percent4 = 4,
-
- ///
- /// 8% fall damage.
- ///
- Percent8 = 8,
-
- ///
- /// 12% fall damage.
- ///
- Percent12 = 12,
-
- ///
- /// 16% fall damage.
- ///
- Percent16 = 16,
-
- ///
- /// 20% fall damage.
- ///
- Percent20 = 20,
-
- ///
- /// 24% fall damage.
- ///
- Percent24 = 24,
-
- ///
- /// 28% fall damage.
- ///
- Percent28 = 28,
-
- ///
- /// 32% fall damage.
- ///
- Percent32 = 32,
-
- ///
- /// 36% fall damage.
- ///
- Percent36 = 36,
-
- ///
- /// 40% fall damage.
- ///
- Percent40 = 40,
-
- ///
- /// 44% fall damage.
- ///
- Percent44 = 44,
-
- ///
- /// 48% fall damage.
- ///
- Percent48 = 48,
-
- ///
- /// 52% fall damage.
- ///
- Percent52 = 52,
-
- ///
- /// 56% fall damage.
- ///
- Percent56 = 56,
-
- ///
- /// 60% fall damage.
- ///
- Percent60 = 60,
-
- ///
- /// 64% fall damage.
- ///
- Percent64 = 64,
-
- ///
- /// 68% fall damage.
- ///
- Percent68 = 68,
-
- ///
- /// 72% fall damage.
- ///
- Percent72 = 72,
-
- ///
- /// 76% fall damage.
- ///
- Percent76 = 76,
-
- ///
- /// 80% fall damage.
- ///
- Percent80 = 80,
-
- ///
- /// 84% fall damage.
- ///
- Percent84 = 84,
-
- ///
- /// 88% fall damage.
- ///
- Percent88 = 88,
-
- ///
- /// 92% fall damage.
- ///
- Percent92 = 92,
-
- ///
- /// 96% fall damage.
- ///
- Percent96 = 96,
-
- ///
- /// 100% fall damage.
- ///
- Percent100 = 100,
-
- ///
- /// 104% fall damage.
- ///
- Percent104 = 104,
-
- ///
- /// 108% fall damage.
- ///
- Percent108 = 108,
-
- ///
- /// 112% fall damage.
- ///
- Percent112 = 112,
-
- ///
- /// 116% fall damage.
- ///
- Percent116 = 116,
-
- ///
- /// 120% fall damage.
- ///
- Percent120 = 120,
-
- ///
- /// 124% fall damage.
- ///
- Percent124 = 124,
-
- ///
- /// 128% fall damage.
- ///
- Percent128 = 128,
-
- ///
- /// 132% fall damage.
- ///
- Percent132 = 132,
-
- ///
- /// 136% fall damage.
- ///
- Percent136 = 136,
-
- ///
- /// 140% fall damage.
- ///
- Percent140 = 140,
-
- ///
- /// 144% fall damage.
- ///
- Percent144 = 144,
-
- ///
- /// 148% fall damage.
- ///
- Percent148 = 148,
-
- ///
- /// 152% fall damage.
- ///
- Percent152 = 152,
-
- ///
- /// 156% fall damage.
- ///
- Percent156 = 156,
-
- ///
- /// 160% fall damage.
- ///
- Percent160 = 160,
-
- ///
- /// 164% fall damage.
- ///
- Percent164 = 164,
-
- ///
- /// 168% fall damage.
- ///
- Percent168 = 168,
-
- ///
- /// 172% fall damage.
- ///
- Percent172 = 172,
-
- ///
- /// 176% fall damage.
- ///
- Percent176 = 176,
-
- ///
- /// 180% fall damage.
- ///
- Percent180 = 180,
-
- ///
- /// 184% fall damage.
- ///
- Percent184 = 184,
-
- ///
- /// 188% fall damage.
- ///
- Percent188 = 188,
-
- ///
- /// 192% fall damage.
- ///
- Percent192 = 192,
-
- ///
- /// 196% fall damage.
- ///
- Percent196 = 196,
-
- ///
- /// 200% fall damage.
- ///
- Percent200 = 200,
-
- ///
- /// 204% fall damage.
- ///
- Percent204 = 204,
-
- ///
- /// 208% fall damage.
- ///
- Percent208 = 208,
-
- ///
- /// 212% fall damage.
- ///
- Percent212 = 212,
-
- ///
- /// 216% fall damage.
- ///
- Percent216 = 216,
-
- ///
- /// 220% fall damage.
- ///
- Percent220 = 220,
-
- ///
- /// 224% fall damage.
- ///
- Percent224 = 224,
-
- ///
- /// 228% fall damage.
- ///
- Percent228 = 228,
-
- ///
- /// 232% fall damage.
- ///
- Percent232 = 232,
-
- ///
- /// 236% fall damage.
- ///
- Percent236 = 236,
-
- ///
- /// 240% fall damage.
- ///
- Percent240 = 240,
-
- ///
- /// 244% fall damage.
- ///
- Percent244 = 244,
-
- ///
- /// 248% fall damage.
- ///
- Percent248 = 248,
-
- ///
- /// 252% fall damage.
- ///
- Percent252 = 252,
-
- ///
- /// 256% fall damage.
- ///
- Percent256 = 256,
-
- ///
- /// 260% fall damage.
- ///
- Percent260 = 260,
-
- ///
- /// 264% fall damage.
- ///
- Percent264 = 264,
-
- ///
- /// 268% fall damage.
- ///
- Percent268 = 268,
-
- ///
- /// 272% fall damage.
- ///
- Percent272 = 272,
-
- ///
- /// 276% fall damage.
- ///
- Percent276 = 276,
-
- ///
- /// 280% fall damage.
- ///
- Percent280 = 280,
-
- ///
- /// 284% fall damage.
- ///
- Percent284 = 284,
-
- ///
- /// 288% fall damage.
- ///
- Percent288 = 288,
-
- ///
- /// 292% fall damage.
- ///
- Percent292 = 292,
-
- ///
- /// 296% fall damage.
- ///
- Percent296 = 296,
-
- ///
- /// 300% fall damage.
- ///
- Percent300 = 300,
-
- ///
- /// 304% fall damage.
- ///
- Percent304 = 304,
-
- ///
- /// 308% fall damage.
- ///
- Percent308 = 308,
-
- ///
- /// 312% fall damage.
- ///
- Percent312 = 312,
-
- ///
- /// 316% fall damage.
- ///
- Percent316 = 316,
-
- ///
- /// 320% fall damage.
- ///
- Percent320 = 320,
-
- ///
- /// 324% fall damage.
- ///
- Percent324 = 324,
-
- ///
- /// 328% fall damage.
- ///
- Percent328 = 328,
-
- ///
- /// 332% fall damage.
- ///
- Percent332 = 332,
-
- ///
- /// 336% fall damage.
- ///
- Percent336 = 336,
-
- ///
- /// 340% fall damage.
- ///
- Percent340 = 340,
-
- ///
- /// 344% fall damage.
- ///
- Percent344 = 344,
-
- ///
- /// 348% fall damage.
- ///
- Percent348 = 348,
-
- ///
- /// 352% fall damage.
- ///
- Percent352 = 352,
-
- ///
- /// 356% fall damage.
- ///
- Percent356 = 356,
-
- ///
- /// 360% fall damage.
- ///
- Percent360 = 360,
-
- ///
- /// 364% fall damage.
- ///
- Percent364 = 364,
-
- ///
- /// 368% fall damage.
- ///
- Percent368 = 368,
-
- ///
- /// 372% fall damage.
- ///
- Percent372 = 372,
-
- ///
- /// 376% fall damage.
- ///
- Percent376 = 376,
-
- ///
- /// 380% fall damage.
- ///
- Percent380 = 380,
-
- ///
- /// 384% fall damage.
- ///
- Percent384 = 384,
-
- ///
- /// 388% fall damage.
- ///
- Percent388 = 388,
-
- ///
- /// 392% fall damage.
- ///
- Percent392 = 392,
-
- ///
- /// 396% fall damage.
- ///
- Percent396 = 396,
-
- ///
- /// 400% fall damage.
- ///
- Percent400 = 400,
-
- ///
- /// 404% fall damage.
- ///
- Percent404 = 404,
-
- ///
- /// 408% fall damage.
- ///
- Percent408 = 408,
-
- ///
- /// 412% fall damage.
- ///
- Percent412 = 412,
-
- ///
- /// 416% fall damage.
- ///
- Percent416 = 416,
-
- ///
- /// 420% fall damage.
- ///
- Percent420 = 420,
-
- ///
- /// 424% fall damage.
- ///
- Percent424 = 424,
-
- ///
- /// 428% fall damage.
- ///
- Percent428 = 428,
-
- ///
- /// 432% fall damage.
- ///
- Percent432 = 432,
-
- ///
- /// 436% fall damage.
- ///
- Percent436 = 436,
-
- ///
- /// 440% fall damage.
- ///
- Percent440 = 440,
-
- ///
- /// 444% fall damage.
- ///
- Percent444 = 444,
-
- ///
- /// 448% fall damage.
- ///
- Percent448 = 448,
-
- ///
- /// 452% fall damage.
- ///
- Percent452 = 452,
-
- ///
- /// 456% fall damage.
- ///
- Percent456 = 456,
-
- ///
- /// 460% fall damage.
- ///
- Percent460 = 460,
-
- ///
- /// 464% fall damage.
- ///
- Percent464 = 464,
-
- ///
- /// 468% fall damage.
- ///
- Percent468 = 468,
-
- ///
- /// 472% fall damage.
- ///
- Percent472 = 472,
-
- ///
- /// 476% fall damage.
- ///
- Percent476 = 476,
-
- ///
- /// 480% fall damage.
- ///
- Percent480 = 480,
-
- ///
- /// 484% fall damage.
- ///
- Percent484 = 484,
-
- ///
- /// 488% fall damage.
- ///
- Percent488 = 488,
-
- ///
- /// 492% fall damage.
- ///
- Percent492 = 492,
-
- ///
- /// 496% fall damage.
- ///
- Percent496 = 496,
-
- ///
- /// 500% fall damage.
- ///
- Percent500 = 500,
-
- ///
- /// 504% fall damage.
- ///
- Percent504 = 504,
-
- ///
- /// 508% fall damage.
- ///
- Percent508 = 508
- }
-
- ///
- /// Represents the known identifiers of scheme editors stored in schemes modified by them.
- ///
- public enum SchemeEditor : byte
- {
- None = 0,
- LeTotalKiller = 0x5F,
- SchemeEddy = 0x89
- }
-
- ///
- /// Represents the stockpiling mode of weapon armory between rounds.
- ///
- public enum SchemeStockpiling : byte
- {
- Off = 0,
- On = 1,
- Anti = 2
- }
-
- ///
- /// Represents the method to determine the next turn's worm.
- ///
- public enum SchemeWormSelect : byte
- {
- ///
- /// Worms are selected in the order in which they appear in the team.
- ///
- Sequential = 0,
-
- ///
- /// Worms are selected by the player.
- ///
- Manual = 1,
-
- ///
- /// Worms are selected randomly.
- ///
- Random = 2
- }
-
- ///
- /// Represents the event triggered when the round timer runs out.
- ///
- public enum SchemeSuddenDeathEvent : byte
- {
- ///
- /// The round ends and is drawn.
- ///
- RoundEnd = 0,
-
- ///
- /// A nuklear test is triggered.
- ///
- NuclearStrike = 1,
-
- ///
- /// The worms health is reduced to 1.
- ///
- HealthDrop = 2,
-
- ///
- /// No special event is triggered and the water only rises in the rate specified in the scheme.
- ///
- WaterRise = 3
- }
-
- ///
- /// Represents the water rise in pixels after sudden death was triggered.
- ///
- public enum SchemeWaterRise : byte
- {
- ///
- /// No water rise.
- ///
- None = 0,
-
- ///
- /// 5 pixels water rise.
- ///
- Pixels5 = 5,
-
- ///
- /// 13 pixels water rise.
- ///
- Pixels13 = 13,
-
- ///
- /// 20 pixels water rise.
- ///
- Pixels20 = 20,
-
- ///
- /// 21 pixels water rise.
- ///
- Pixels21 = 21,
-
- ///
- /// 29 pixels water rise.
- ///
- Pixels29 = 29,
-
- ///
- /// 37 pixels water rise.
- ///
- Pixels37 = 37,
-
- ///
- /// 45 pixels water rise.
- ///
- Pixels45 = 45,
-
- ///
- /// 52 pixels water rise.
- ///
- Pixels52 = 52,
-
- ///
- /// 53 pixels water rise.
- ///
- Pixels53 = 53,
-
- ///
- /// 61 pixels water rise.
- ///
- Pixels61 = 61,
-
- ///
- /// 64 pixels water rise.
- ///
- Pixels64 = 64,
-
- ///
- /// 69 pixels water rise.
- ///
- Pixels69 = 69,
-
- ///
- /// 77 pixels water rise.
- ///
- Pixels77 = 77,
-
- ///
- /// 80 pixels water rise.
- ///
- Pixels80 = 80,
-
- ///
- /// 84 pixels water rise.
- ///
- Pixels84 = 84,
-
- ///
- /// 85 pixels water rise.
- ///
- Pixels85 = 85,
-
- ///
- /// 93 pixels water rise.
- ///
- Pixels93 = 93,
-
- ///
- /// 101 pixels water rise.
- ///
- Pixels101 = 101,
-
- ///
- /// 109 pixels water rise.
- ///
- Pixels109 = 109,
-
- ///
- /// 116 pixels water rise.
- ///
- Pixels116 = 116,
-
- ///
- /// 117 pixels water rise.
- ///
- Pixels117 = 117,
-
- ///
- /// 125 pixels water rise.
- ///
- Pixels125 = 125,
-
- ///
- /// 133 pixels water rise.
- ///
- Pixels133 = 133,
-
- ///
- /// 141 pixels water rise.
- ///
- Pixels141 = 141,
-
- ///
- /// 148 pixels water rise.
- ///
- Pixels148 = 148,
-
- ///
- /// 149 pixels water rise.
- ///
- Pixels149 = 149,
-
- ///
- /// 157 pixels water rise.
- ///
- Pixels157 = 157,
-
- ///
- /// 165 pixels water rise.
- ///
- Pixels165 = 165,
-
- ///
- /// 173 pixels water rise.
- ///
- Pixels173 = 173,
-
- ///
- /// 180 pixels water rise.
- ///
- Pixels180 = 180,
-
- ///
- /// 181 pixels water rise.
- ///
- Pixels181 = 181,
-
- ///
- /// 189 pixels water rise.
- ///
- Pixels189 = 189,
-
- ///
- /// 197 pixels water rise.
- ///
- Pixels197 = 197,
-
- ///
- /// 205 pixels water rise.
- ///
- Pixels205 = 205,
-
- ///
- /// 208 pixels water rise.
- ///
- Pixels208 = 208,
-
- ///
- /// 212 pixels water rise.
- ///
- Pixels212 = 212,
-
- ///
- /// 213 pixels water rise.
- ///
- Pixels213 = 213,
-
- ///
- /// 221 pixels water rise.
- ///
- Pixels221 = 221,
-
- ///
- /// 229 pixels water rise.
- ///
- Pixels229 = 229,
-
- ///
- /// 237 pixels water rise.
- ///
- Pixels237 = 237,
-
- ///
- /// 244 pixels water rise.
- ///
- Pixels244 = 244,
-
- ///
- /// 245 pixels water rise.
- ///
- Pixels245 = 245,
-
- ///
- /// 253 pixels water rise.
- ///
- Pixels253 = 253
- }
-
- ///
- /// Represents the types of objects which can appear on the map.
- ///
- [Flags]
- public enum SchemeObjectType
- {
- None = 0,
- Mines = 1 << 0,
- OilDrums = 1 << 1
- }
-
- ///
- /// Represents the possible maximum number of objects which can appear on the map.
- ///
- public enum SchemeObjectCount
- {
- ///
- /// No objects.
- ///
- None = 0,
-
- ///
- /// Up to 1 object.
- ///
- Count1 = 1,
-
- ///
- /// Up to 2 objects.
- ///
- Count2 = 2,
-
- ///
- /// Up to 3 objects.
- ///
- Count3 = 3,
-
- ///
- /// Up to 4 objects.
- ///
- Count4 = 4,
-
- ///
- /// Up to 5 objects.
- ///
- Count5 = 5,
-
- ///
- /// Up to 6 objects.
- ///
- Count6 = 6,
-
- ///
- /// Up to 7 objects.
- ///
- Count7 = 7,
-
- ///
- /// Up to 8 objects.
- ///
- Count8 = 8,
-
- ///
- /// Up to 9 objects.
- ///
- Count9 = 9,
-
- ///
- /// Up to 10 objects.
- ///
- Count10 = 10,
-
- ///
- /// Up to 11 objects.
- ///
- Count11 = 11,
-
- ///
- /// Up to 12 objects.
- ///
- Count12 = 12,
-
- ///
- /// Up to 13 objects.
- ///
- Count13 = 13,
-
- ///
- /// Up to 14 objects.
- ///
- Count14 = 14,
-
- ///
- /// Up to 15 objects.
- ///
- Count15 = 15,
-
- ///
- /// Up to 16 objects.
- ///
- Count16 = 16,
-
- ///
- /// Up to 17 objects.
- ///
- Count17 = 17,
-
- ///
- /// Up to 18 objects.
- ///
- Count18 = 18,
-
- ///
- /// Up to 19 objects.
- ///
- Count19 = 19,
-
- ///
- /// Up to 20 objects.
- ///
- Count20 = 20,
-
- ///
- /// Up to 21 objects.
- ///
- Count21 = 21,
-
- ///
- /// Up to 22 objects.
- ///
- Count22 = 22,
-
- ///
- /// Up to 23 objects.
- ///
- Count23 = 23,
-
- ///
- /// Up to 24 objects.
- ///
- Count24 = 24,
-
- ///
- /// Up to 25 objects.
- ///
- Count25 = 25,
-
- ///
- /// Up to 26 objects.
- ///
- Count26 = 26,
-
- ///
- /// Up to 27 objects.
- ///
- Count27 = 27,
-
- ///
- /// Up to 28 objects.
- ///
- Count28 = 28,
-
- ///
- /// Up to 29 objects.
- ///
- Count29 = 29,
-
- ///
- /// Up to 30 objects.
- ///
- Count30 = 30,
-
- ///
- /// Up to 35 objects.
- ///
- Count35 = 35,
-
- ///
- /// Up to 40 objects.
- ///
- Count40 = 40,
-
- ///
- /// Up to 45 objects.
- ///
- Count45 = 45,
-
- ///
- /// Up to 50 objects.
- ///
- Count50 = 50,
-
- ///
- /// Up to 55 objects.
- ///
- Count55 = 55,
-
- ///
- /// Up to 60 objects.
- ///
- Count60 = 60,
-
- ///
- /// Up to 65 objects.
- ///
- Count65 = 65,
-
- ///
- /// Up to 70 objects.
- ///
- Count70 = 70,
-
- ///
- /// Up to 75 objects.
- ///
- Count75 = 75,
-
- ///
- /// Up to 80 objects.
- ///
- Count80 = 80,
-
- ///
- /// Up to 85 objects.
- ///
- Count85 = 85,
-
- ///
- /// Up to 90 objects.
- ///
- Count90 = 90,
-
- ///
- /// Up to 95 objects.
- ///
- Count95 = 95,
-
- ///
- /// Up to 100 objects.
- ///
- Count100 = 100,
-
- ///
- /// Up to 110 objects.
- ///
- Count110 = 110,
-
- ///
- /// Up to 120 objects.
- ///
- Count120 = 120,
-
- ///
- /// Up to 130 objects.
- ///
- Count130 = 130,
-
- ///
- /// Up to 140 objects.
- ///
- Count140 = 140,
-
- ///
- /// Up to 150 objects.
- ///
- Count150 = 150,
-
- ///
- /// Up to 160 objects.
- ///
- Count160 = 160,
-
- ///
- /// Up to 170 objects.
- ///
- Count170 = 170,
-
- ///
- /// Up to 180 objects.
- ///
- Count180 = 180,
-
- ///
- /// Up to 190 objects.
- ///
- Count190 = 190,
-
- ///
- /// Up to 200 objects.
- ///
- Count200 = 200,
-
- ///
- /// Up to 210 objects.
- ///
- Count210 = 210,
-
- ///
- /// Up to 220 objects.
- ///
- Count220 = 220,
-
- ///
- /// Up to 230 objects.
- ///
- Count230 = 230,
-
- ///
- /// Up to 240 objects.
- ///
- Count240 = 240,
-
- ///
- /// Up to 250 objects.
- ///
- Count250 = 250
- }
-
- ///
- /// Represents the weapons in the game.
- ///
- public enum SchemeWeapon
- {
- ///
- /// The Bazooka weapon.
- ///
- Bazooka,
-
- ///
- /// The Homing Missile weapon.
- ///
- HomingMissile,
-
- ///
- /// The Mortar weapon.
- ///
- Mortar,
-
- ///
- /// The Grenade weapon.
- ///
- Grenade,
-
- ///
- /// The Cluster Bomb weapon.
- ///
- ClusterBomb,
-
- ///
- /// The Skunk weapon.
- ///
- Skunk,
-
- ///
- /// The Petrol Bomb weapon.
- ///
- PetrolBomb,
-
- ///
- /// The Banana Bomb weapon.
- ///
- BananaBomb,
-
- ///
- /// The Handgun weapon.
- ///
- Handgun,
-
- ///
- /// The Shotgun weapon.
- ///
- Shotgun,
-
- ///
- /// The Uzi weapon.
- ///
- Uzi,
-
- ///
- /// The Minigun weapon.
- ///
- Minigun,
-
- ///
- /// The Longbow weapon.
- ///
- Longbow,
-
- ///
- /// The Airstrike weapon.
- ///
- Airstrike,
-
- ///
- /// The Napalm Strike weapon.
- ///
- NapalmStrike,
-
- ///
- /// The Mine weapon.
- ///
- Mine,
-
- ///
- /// The Firepunch weapon.
- ///
- Firepunch,
-
- ///
- /// The Dragonball weapon.
- ///
- Dragonball,
-
- ///
- /// The Kamikaze weapon.
- ///
- Kamikaze,
-
- ///
- /// The Prod weapon.
- ///
- Prod,
-
- ///
- /// The Battle Axe weapon.
- ///
- BattleAxe,
-
- ///
- /// The Blowtorch weapon.
- ///
- Blowtorch,
-
- ///
- /// The Pneumatic Drill weapon.
- ///
- PneumaticDrill,
-
- ///
- /// The Girder weapon.
- ///
- Girder,
-
- ///
- /// The Ninja Rope weapon.
- ///
- NinjaRope,
-
- ///
- /// The Parachute weapon.
- ///
- Parachute,
-
- ///
- /// The Bungee weapon.
- ///
- Bungee,
-
- ///
- /// The Teleport weapon.
- ///
- Teleport,
-
- ///
- /// The Dynamite weapon.
- ///
- Dynamite,
-
- ///
- /// The Sheep weapon.
- ///
- Sheep,
-
- ///
- /// The Baseball Bat weapon.
- ///
- BaseballBat,
-
- ///
- /// The Flame Thrower weapon.
- ///
- Flamethrower,
-
- ///
- /// The Homing Pigeon weapon.
- ///
- HomingPigeon,
-
- ///
- /// The Mad Cow weapon.
- ///
- MadCow,
-
- ///
- /// The Holy Hand Grenade weapon.
- ///
- HolyHandGrenade,
-
- ///
- /// The Old Woman weapon.
- ///
- OldWoman,
-
- ///
- /// The Sheep Launcher weapon.
- ///
- SheepLauncher,
-
- ///
- /// The Super Sheep or Aqua Sheep weapon.
- ///
- SuperSheep,
-
- ///
- /// The Mole Bomb weapon.
- ///
- MoleBomb,
-
- ///
- /// The Jetpack utility.
- ///
- Jetpack,
-
- ///
- /// The Low Gravity utility.
- ///
- LowGravity,
-
- ///
- /// The Laser Sight utility.
- ///
- LaserSight,
-
- ///
- /// The Fast Walk utility.
- ///
- FastWalk,
-
- ///
- /// The Invisibility utility.
- ///
- Invisibility,
-
- ///
- /// The Damage x2 utility.
- ///
- DamageX2,
-
- ///
- /// The Freeze super weapon.
- ///
- Freeze,
-
- ///
- /// The Super Banana Bomb super weapon.
- ///
- SuperBananaBomb,
-
- ///
- /// The Mine Strike super weapon.
- ///
- MineStrike,
-
- ///
- /// The Girder Starter Pack super weapon.
- ///
- GirderStarterPack,
-
- ///
- /// The Earthquake super weapon.
- ///
- Earthquake,
-
- ///
- /// The Scales Of Justice super weapon.
- ///
- ScalesOfJustice,
-
- ///
- /// The Ming Vase super weapon.
- ///
- MingVase,
-
- ///
- /// The Mike's Carpet Bomb super weapon.
- ///
- MikesCarpetBomb,
-
- ///
- /// The Patsy's Magic Bullet super weapon.
- ///
- MagicBullet,
-
- ///
- /// The Indian Nuclear Test super weapon.
- ///
- NuclearTest,
-
- ///
- /// The Select Worm super weapon.
- ///
- SelectWorm,
-
- ///
- /// The Salvation Army super weapon.
- ///
- SalvationArmy,
-
- ///
- /// The Mole Squadron super weapon.
- ///
- MoleSquadron,
-
- ///
- /// The MB Bomb super weapon.
- ///
- MBBomb,
-
- ///
- /// The Concrete Donkey super weapon.
- ///
- ConcreteDonkey,
-
- ///
- /// The Suicide Bomber super weapon.
- ///
- SuicideBomber,
-
- ///
- /// The Sheep Strike super weapon.
- ///
- SheepStrike,
-
- ///
- /// The Mail Strike super weapon.
- ///
- MailStrike,
-
- ///
- /// The Armageddon super weapon.
- ///
- Armageddon
- }
-}
+using System;
+
+namespace Syroot.Worms.Armageddon
+{
+ ///
+ /// Represents the known versions of scheme file formats.
+ ///
+ public enum SchemeVersion : byte
+ {
+ ///
+ /// The standard format used by WA before version 3.6.28.0 and WWP. It does not store super weapon settings.
+ ///
+ Standard = 1,
+
+ ///
+ /// The extended format used by WA since version 3.6.28.0.
+ ///
+ Extended = 2
+ }
+
+ ///
+ /// Represents the possible variations of the options stored in a scheme file.
+ ///
+ public enum SchemeSaveFormat
+ {
+ ///
+ /// Represents the format.
+ ///
+ Standard,
+
+ ///
+ /// Represents the format, and does not store object counts.
+ ///
+ Extended,
+
+ ///
+ /// Represents the format, and stores object counts (supported since WA
+ /// 3.6.28.0).
+ ///
+ ExtendedWithObjectCount
+ }
+
+ ///
+ /// Represents the fall damage in percent, relative to the normal fall damage being 100%.
+ ///
+ public enum SchemeFallDamage
+ {
+ ///
+ /// No fall damage.
+ ///
+ None = 0,
+
+ ///
+ /// 4% fall damage.
+ ///
+ Percent4 = 4,
+
+ ///
+ /// 8% fall damage.
+ ///
+ Percent8 = 8,
+
+ ///
+ /// 12% fall damage.
+ ///
+ Percent12 = 12,
+
+ ///
+ /// 16% fall damage.
+ ///
+ Percent16 = 16,
+
+ ///
+ /// 20% fall damage.
+ ///
+ Percent20 = 20,
+
+ ///
+ /// 24% fall damage.
+ ///
+ Percent24 = 24,
+
+ ///
+ /// 28% fall damage.
+ ///
+ Percent28 = 28,
+
+ ///
+ /// 32% fall damage.
+ ///
+ Percent32 = 32,
+
+ ///
+ /// 36% fall damage.
+ ///
+ Percent36 = 36,
+
+ ///
+ /// 40% fall damage.
+ ///
+ Percent40 = 40,
+
+ ///
+ /// 44% fall damage.
+ ///
+ Percent44 = 44,
+
+ ///
+ /// 48% fall damage.
+ ///
+ Percent48 = 48,
+
+ ///
+ /// 52% fall damage.
+ ///
+ Percent52 = 52,
+
+ ///
+ /// 56% fall damage.
+ ///
+ Percent56 = 56,
+
+ ///
+ /// 60% fall damage.
+ ///
+ Percent60 = 60,
+
+ ///
+ /// 64% fall damage.
+ ///
+ Percent64 = 64,
+
+ ///
+ /// 68% fall damage.
+ ///
+ Percent68 = 68,
+
+ ///
+ /// 72% fall damage.
+ ///
+ Percent72 = 72,
+
+ ///
+ /// 76% fall damage.
+ ///
+ Percent76 = 76,
+
+ ///
+ /// 80% fall damage.
+ ///
+ Percent80 = 80,
+
+ ///
+ /// 84% fall damage.
+ ///
+ Percent84 = 84,
+
+ ///
+ /// 88% fall damage.
+ ///
+ Percent88 = 88,
+
+ ///
+ /// 92% fall damage.
+ ///
+ Percent92 = 92,
+
+ ///
+ /// 96% fall damage.
+ ///
+ Percent96 = 96,
+
+ ///
+ /// 100% fall damage.
+ ///
+ Percent100 = 100,
+
+ ///
+ /// 104% fall damage.
+ ///
+ Percent104 = 104,
+
+ ///
+ /// 108% fall damage.
+ ///
+ Percent108 = 108,
+
+ ///
+ /// 112% fall damage.
+ ///
+ Percent112 = 112,
+
+ ///
+ /// 116% fall damage.
+ ///
+ Percent116 = 116,
+
+ ///
+ /// 120% fall damage.
+ ///
+ Percent120 = 120,
+
+ ///
+ /// 124% fall damage.
+ ///
+ Percent124 = 124,
+
+ ///
+ /// 128% fall damage.
+ ///
+ Percent128 = 128,
+
+ ///
+ /// 132% fall damage.
+ ///
+ Percent132 = 132,
+
+ ///
+ /// 136% fall damage.
+ ///
+ Percent136 = 136,
+
+ ///
+ /// 140% fall damage.
+ ///
+ Percent140 = 140,
+
+ ///
+ /// 144% fall damage.
+ ///
+ Percent144 = 144,
+
+ ///
+ /// 148% fall damage.
+ ///
+ Percent148 = 148,
+
+ ///
+ /// 152% fall damage.
+ ///
+ Percent152 = 152,
+
+ ///
+ /// 156% fall damage.
+ ///
+ Percent156 = 156,
+
+ ///
+ /// 160% fall damage.
+ ///
+ Percent160 = 160,
+
+ ///
+ /// 164% fall damage.
+ ///
+ Percent164 = 164,
+
+ ///
+ /// 168% fall damage.
+ ///
+ Percent168 = 168,
+
+ ///
+ /// 172% fall damage.
+ ///
+ Percent172 = 172,
+
+ ///
+ /// 176% fall damage.
+ ///
+ Percent176 = 176,
+
+ ///
+ /// 180% fall damage.
+ ///
+ Percent180 = 180,
+
+ ///
+ /// 184% fall damage.
+ ///
+ Percent184 = 184,
+
+ ///
+ /// 188% fall damage.
+ ///
+ Percent188 = 188,
+
+ ///
+ /// 192% fall damage.
+ ///
+ Percent192 = 192,
+
+ ///
+ /// 196% fall damage.
+ ///
+ Percent196 = 196,
+
+ ///
+ /// 200% fall damage.
+ ///
+ Percent200 = 200,
+
+ ///
+ /// 204% fall damage.
+ ///
+ Percent204 = 204,
+
+ ///
+ /// 208% fall damage.
+ ///
+ Percent208 = 208,
+
+ ///
+ /// 212% fall damage.
+ ///
+ Percent212 = 212,
+
+ ///
+ /// 216% fall damage.
+ ///
+ Percent216 = 216,
+
+ ///
+ /// 220% fall damage.
+ ///
+ Percent220 = 220,
+
+ ///
+ /// 224% fall damage.
+ ///
+ Percent224 = 224,
+
+ ///
+ /// 228% fall damage.
+ ///
+ Percent228 = 228,
+
+ ///
+ /// 232% fall damage.
+ ///
+ Percent232 = 232,
+
+ ///
+ /// 236% fall damage.
+ ///
+ Percent236 = 236,
+
+ ///
+ /// 240% fall damage.
+ ///
+ Percent240 = 240,
+
+ ///
+ /// 244% fall damage.
+ ///
+ Percent244 = 244,
+
+ ///
+ /// 248% fall damage.
+ ///
+ Percent248 = 248,
+
+ ///
+ /// 252% fall damage.
+ ///
+ Percent252 = 252,
+
+ ///
+ /// 256% fall damage.
+ ///
+ Percent256 = 256,
+
+ ///
+ /// 260% fall damage.
+ ///
+ Percent260 = 260,
+
+ ///
+ /// 264% fall damage.
+ ///
+ Percent264 = 264,
+
+ ///
+ /// 268% fall damage.
+ ///
+ Percent268 = 268,
+
+ ///
+ /// 272% fall damage.
+ ///
+ Percent272 = 272,
+
+ ///
+ /// 276% fall damage.
+ ///
+ Percent276 = 276,
+
+ ///
+ /// 280% fall damage.
+ ///
+ Percent280 = 280,
+
+ ///
+ /// 284% fall damage.
+ ///
+ Percent284 = 284,
+
+ ///
+ /// 288% fall damage.
+ ///
+ Percent288 = 288,
+
+ ///
+ /// 292% fall damage.
+ ///
+ Percent292 = 292,
+
+ ///
+ /// 296% fall damage.
+ ///
+ Percent296 = 296,
+
+ ///
+ /// 300% fall damage.
+ ///
+ Percent300 = 300,
+
+ ///
+ /// 304% fall damage.
+ ///
+ Percent304 = 304,
+
+ ///
+ /// 308% fall damage.
+ ///
+ Percent308 = 308,
+
+ ///
+ /// 312% fall damage.
+ ///
+ Percent312 = 312,
+
+ ///
+ /// 316% fall damage.
+ ///
+ Percent316 = 316,
+
+ ///
+ /// 320% fall damage.
+ ///
+ Percent320 = 320,
+
+ ///
+ /// 324% fall damage.
+ ///
+ Percent324 = 324,
+
+ ///
+ /// 328% fall damage.
+ ///
+ Percent328 = 328,
+
+ ///
+ /// 332% fall damage.
+ ///
+ Percent332 = 332,
+
+ ///
+ /// 336% fall damage.
+ ///
+ Percent336 = 336,
+
+ ///
+ /// 340% fall damage.
+ ///
+ Percent340 = 340,
+
+ ///
+ /// 344% fall damage.
+ ///
+ Percent344 = 344,
+
+ ///
+ /// 348% fall damage.
+ ///
+ Percent348 = 348,
+
+ ///
+ /// 352% fall damage.
+ ///
+ Percent352 = 352,
+
+ ///
+ /// 356% fall damage.
+ ///
+ Percent356 = 356,
+
+ ///
+ /// 360% fall damage.
+ ///
+ Percent360 = 360,
+
+ ///
+ /// 364% fall damage.
+ ///
+ Percent364 = 364,
+
+ ///
+ /// 368% fall damage.
+ ///
+ Percent368 = 368,
+
+ ///
+ /// 372% fall damage.
+ ///
+ Percent372 = 372,
+
+ ///
+ /// 376% fall damage.
+ ///
+ Percent376 = 376,
+
+ ///
+ /// 380% fall damage.
+ ///
+ Percent380 = 380,
+
+ ///
+ /// 384% fall damage.
+ ///
+ Percent384 = 384,
+
+ ///
+ /// 388% fall damage.
+ ///
+ Percent388 = 388,
+
+ ///
+ /// 392% fall damage.
+ ///
+ Percent392 = 392,
+
+ ///
+ /// 396% fall damage.
+ ///
+ Percent396 = 396,
+
+ ///
+ /// 400% fall damage.
+ ///
+ Percent400 = 400,
+
+ ///
+ /// 404% fall damage.
+ ///
+ Percent404 = 404,
+
+ ///
+ /// 408% fall damage.
+ ///
+ Percent408 = 408,
+
+ ///
+ /// 412% fall damage.
+ ///
+ Percent412 = 412,
+
+ ///
+ /// 416% fall damage.
+ ///
+ Percent416 = 416,
+
+ ///
+ /// 420% fall damage.
+ ///
+ Percent420 = 420,
+
+ ///
+ /// 424% fall damage.
+ ///
+ Percent424 = 424,
+
+ ///
+ /// 428% fall damage.
+ ///
+ Percent428 = 428,
+
+ ///
+ /// 432% fall damage.
+ ///
+ Percent432 = 432,
+
+ ///
+ /// 436% fall damage.
+ ///
+ Percent436 = 436,
+
+ ///
+ /// 440% fall damage.
+ ///
+ Percent440 = 440,
+
+ ///
+ /// 444% fall damage.
+ ///
+ Percent444 = 444,
+
+ ///
+ /// 448% fall damage.
+ ///
+ Percent448 = 448,
+
+ ///
+ /// 452% fall damage.
+ ///
+ Percent452 = 452,
+
+ ///
+ /// 456% fall damage.
+ ///
+ Percent456 = 456,
+
+ ///
+ /// 460% fall damage.
+ ///
+ Percent460 = 460,
+
+ ///
+ /// 464% fall damage.
+ ///
+ Percent464 = 464,
+
+ ///
+ /// 468% fall damage.
+ ///
+ Percent468 = 468,
+
+ ///
+ /// 472% fall damage.
+ ///
+ Percent472 = 472,
+
+ ///
+ /// 476% fall damage.
+ ///
+ Percent476 = 476,
+
+ ///
+ /// 480% fall damage.
+ ///
+ Percent480 = 480,
+
+ ///
+ /// 484% fall damage.
+ ///
+ Percent484 = 484,
+
+ ///
+ /// 488% fall damage.
+ ///
+ Percent488 = 488,
+
+ ///
+ /// 492% fall damage.
+ ///
+ Percent492 = 492,
+
+ ///
+ /// 496% fall damage.
+ ///
+ Percent496 = 496,
+
+ ///
+ /// 500% fall damage.
+ ///
+ Percent500 = 500,
+
+ ///
+ /// 504% fall damage.
+ ///
+ Percent504 = 504,
+
+ ///
+ /// 508% fall damage.
+ ///
+ Percent508 = 508
+ }
+
+ ///
+ /// Represents the known identifiers of scheme editors stored in schemes modified by them.
+ ///
+ public enum SchemeEditor : byte
+ {
+ None = 0,
+ LeTotalKiller = 0x5F,
+ SchemeEddy = 0x89
+ }
+
+ ///
+ /// Represents the stockpiling mode of weapon armory between rounds.
+ ///
+ public enum SchemeStockpiling : byte
+ {
+ Off = 0,
+ On = 1,
+ Anti = 2
+ }
+
+ ///
+ /// Represents the method to determine the next turn's worm.
+ ///
+ public enum SchemeWormSelect : byte
+ {
+ ///
+ /// Worms are selected in the order in which they appear in the team.
+ ///
+ Sequential = 0,
+
+ ///
+ /// Worms are selected by the player.
+ ///
+ Manual = 1,
+
+ ///
+ /// Worms are selected randomly.
+ ///
+ Random = 2
+ }
+
+ ///
+ /// Represents the event triggered when the round timer runs out.
+ ///
+ public enum SchemeSuddenDeathEvent : byte
+ {
+ ///
+ /// The round ends and is drawn.
+ ///
+ RoundEnd = 0,
+
+ ///
+ /// A nuklear test is triggered.
+ ///
+ NuclearStrike = 1,
+
+ ///
+ /// The worms health is reduced to 1.
+ ///
+ HealthDrop = 2,
+
+ ///
+ /// No special event is triggered and the water only rises in the rate specified in the scheme.
+ ///
+ WaterRise = 3
+ }
+
+ ///
+ /// Represents the water rise in pixels after sudden death was triggered.
+ ///
+ public enum SchemeWaterRise : byte
+ {
+ ///
+ /// No water rise.
+ ///
+ None = 0,
+
+ ///
+ /// 5 pixels water rise.
+ ///
+ Pixels5 = 5,
+
+ ///
+ /// 13 pixels water rise.
+ ///
+ Pixels13 = 13,
+
+ ///
+ /// 20 pixels water rise.
+ ///
+ Pixels20 = 20,
+
+ ///
+ /// 21 pixels water rise.
+ ///
+ Pixels21 = 21,
+
+ ///
+ /// 29 pixels water rise.
+ ///
+ Pixels29 = 29,
+
+ ///
+ /// 37 pixels water rise.
+ ///
+ Pixels37 = 37,
+
+ ///
+ /// 45 pixels water rise.
+ ///
+ Pixels45 = 45,
+
+ ///
+ /// 52 pixels water rise.
+ ///
+ Pixels52 = 52,
+
+ ///
+ /// 53 pixels water rise.
+ ///
+ Pixels53 = 53,
+
+ ///
+ /// 61 pixels water rise.
+ ///
+ Pixels61 = 61,
+
+ ///
+ /// 64 pixels water rise.
+ ///
+ Pixels64 = 64,
+
+ ///
+ /// 69 pixels water rise.
+ ///
+ Pixels69 = 69,
+
+ ///
+ /// 77 pixels water rise.
+ ///
+ Pixels77 = 77,
+
+ ///
+ /// 80 pixels water rise.
+ ///
+ Pixels80 = 80,
+
+ ///
+ /// 84 pixels water rise.
+ ///
+ Pixels84 = 84,
+
+ ///
+ /// 85 pixels water rise.
+ ///
+ Pixels85 = 85,
+
+ ///
+ /// 93 pixels water rise.
+ ///
+ Pixels93 = 93,
+
+ ///
+ /// 101 pixels water rise.
+ ///
+ Pixels101 = 101,
+
+ ///
+ /// 109 pixels water rise.
+ ///
+ Pixels109 = 109,
+
+ ///
+ /// 116 pixels water rise.
+ ///
+ Pixels116 = 116,
+
+ ///
+ /// 117 pixels water rise.
+ ///
+ Pixels117 = 117,
+
+ ///
+ /// 125 pixels water rise.
+ ///
+ Pixels125 = 125,
+
+ ///
+ /// 133 pixels water rise.
+ ///
+ Pixels133 = 133,
+
+ ///
+ /// 141 pixels water rise.
+ ///
+ Pixels141 = 141,
+
+ ///
+ /// 148 pixels water rise.
+ ///
+ Pixels148 = 148,
+
+ ///
+ /// 149 pixels water rise.
+ ///
+ Pixels149 = 149,
+
+ ///
+ /// 157 pixels water rise.
+ ///
+ Pixels157 = 157,
+
+ ///
+ /// 165 pixels water rise.
+ ///
+ Pixels165 = 165,
+
+ ///
+ /// 173 pixels water rise.
+ ///
+ Pixels173 = 173,
+
+ ///
+ /// 180 pixels water rise.
+ ///
+ Pixels180 = 180,
+
+ ///
+ /// 181 pixels water rise.
+ ///
+ Pixels181 = 181,
+
+ ///
+ /// 189 pixels water rise.
+ ///
+ Pixels189 = 189,
+
+ ///
+ /// 197 pixels water rise.
+ ///
+ Pixels197 = 197,
+
+ ///
+ /// 205 pixels water rise.
+ ///
+ Pixels205 = 205,
+
+ ///
+ /// 208 pixels water rise.
+ ///
+ Pixels208 = 208,
+
+ ///
+ /// 212 pixels water rise.
+ ///
+ Pixels212 = 212,
+
+ ///
+ /// 213 pixels water rise.
+ ///
+ Pixels213 = 213,
+
+ ///
+ /// 221 pixels water rise.
+ ///
+ Pixels221 = 221,
+
+ ///
+ /// 229 pixels water rise.
+ ///
+ Pixels229 = 229,
+
+ ///
+ /// 237 pixels water rise.
+ ///
+ Pixels237 = 237,
+
+ ///
+ /// 244 pixels water rise.
+ ///
+ Pixels244 = 244,
+
+ ///
+ /// 245 pixels water rise.
+ ///
+ Pixels245 = 245,
+
+ ///
+ /// 253 pixels water rise.
+ ///
+ Pixels253 = 253
+ }
+
+ ///
+ /// Represents the types of objects which can appear on the map.
+ ///
+ [Flags]
+ public enum SchemeObjectType
+ {
+ None,
+ Mines = 1 << 0,
+ OilDrums = 1 << 1,
+ Both = Mines | OilDrums
+ }
+
+ ///
+ /// Represents the weapons in the game.
+ ///
+ public enum SchemeWeapon
+ {
+ ///
+ /// The Bazooka weapon.
+ ///
+ Bazooka,
+
+ ///
+ /// The Homing Missile weapon.
+ ///
+ HomingMissile,
+
+ ///
+ /// The Mortar weapon.
+ ///
+ Mortar,
+
+ ///
+ /// The Grenade weapon.
+ ///
+ Grenade,
+
+ ///
+ /// The Cluster Bomb weapon.
+ ///
+ ClusterBomb,
+
+ ///
+ /// The Skunk weapon.
+ ///
+ Skunk,
+
+ ///
+ /// The Petrol Bomb weapon.
+ ///
+ PetrolBomb,
+
+ ///
+ /// The Banana Bomb weapon.
+ ///
+ BananaBomb,
+
+ ///
+ /// The Handgun weapon.
+ ///
+ Handgun,
+
+ ///
+ /// The Shotgun weapon.
+ ///
+ Shotgun,
+
+ ///
+ /// The Uzi weapon.
+ ///
+ Uzi,
+
+ ///
+ /// The Minigun weapon.
+ ///
+ Minigun,
+
+ ///
+ /// The Longbow weapon.
+ ///
+ Longbow,
+
+ ///
+ /// The Airstrike weapon.
+ ///
+ Airstrike,
+
+ ///
+ /// The Napalm Strike weapon.
+ ///
+ NapalmStrike,
+
+ ///
+ /// The Mine weapon.
+ ///
+ Mine,
+
+ ///
+ /// The Firepunch weapon.
+ ///
+ Firepunch,
+
+ ///
+ /// The Dragonball weapon.
+ ///
+ Dragonball,
+
+ ///
+ /// The Kamikaze weapon.
+ ///
+ Kamikaze,
+
+ ///
+ /// The Prod weapon.
+ ///
+ Prod,
+
+ ///
+ /// The Battle Axe weapon.
+ ///
+ BattleAxe,
+
+ ///
+ /// The Blowtorch weapon.
+ ///
+ Blowtorch,
+
+ ///
+ /// The Pneumatic Drill weapon.
+ ///
+ PneumaticDrill,
+
+ ///
+ /// The Girder weapon.
+ ///
+ Girder,
+
+ ///
+ /// The Ninja Rope weapon.
+ ///
+ NinjaRope,
+
+ ///
+ /// The Parachute weapon.
+ ///
+ Parachute,
+
+ ///
+ /// The Bungee weapon.
+ ///
+ Bungee,
+
+ ///
+ /// The Teleport weapon.
+ ///
+ Teleport,
+
+ ///
+ /// The Dynamite weapon.
+ ///
+ Dynamite,
+
+ ///
+ /// The Sheep weapon.
+ ///
+ Sheep,
+
+ ///
+ /// The Baseball Bat weapon.
+ ///
+ BaseballBat,
+
+ ///
+ /// The Flame Thrower weapon.
+ ///
+ Flamethrower,
+
+ ///
+ /// The Homing Pigeon weapon.
+ ///
+ HomingPigeon,
+
+ ///
+ /// The Mad Cow weapon.
+ ///
+ MadCow,
+
+ ///
+ /// The Holy Hand Grenade weapon.
+ ///
+ HolyHandGrenade,
+
+ ///
+ /// The Old Woman weapon.
+ ///
+ OldWoman,
+
+ ///
+ /// The Sheep Launcher weapon.
+ ///
+ SheepLauncher,
+
+ ///
+ /// The Super Sheep or Aqua Sheep weapon.
+ ///
+ SuperSheep,
+
+ ///
+ /// The Mole Bomb weapon.
+ ///
+ MoleBomb,
+
+ ///
+ /// The Jetpack utility.
+ ///
+ Jetpack,
+
+ ///
+ /// The Low Gravity utility.
+ ///
+ LowGravity,
+
+ ///
+ /// The Laser Sight utility.
+ ///
+ LaserSight,
+
+ ///
+ /// The Fast Walk utility.
+ ///
+ FastWalk,
+
+ ///
+ /// The Invisibility utility.
+ ///
+ Invisibility,
+
+ ///
+ /// The Damage x2 utility.
+ ///
+ DamageX2,
+
+ ///
+ /// The Freeze super weapon.
+ ///
+ Freeze,
+
+ ///
+ /// The Super Banana Bomb super weapon.
+ ///
+ SuperBananaBomb,
+
+ ///
+ /// The Mine Strike super weapon.
+ ///
+ MineStrike,
+
+ ///
+ /// The Girder Starter Pack super weapon.
+ ///
+ GirderStarterPack,
+
+ ///
+ /// The Earthquake super weapon.
+ ///
+ Earthquake,
+
+ ///
+ /// The Scales Of Justice super weapon.
+ ///
+ ScalesOfJustice,
+
+ ///
+ /// The Ming Vase super weapon.
+ ///
+ MingVase,
+
+ ///
+ /// The Mike's Carpet Bomb super weapon.
+ ///
+ MikesCarpetBomb,
+
+ ///
+ /// The Patsy's Magic Bullet super weapon.
+ ///
+ MagicBullet,
+
+ ///
+ /// The Indian Nuclear Test super weapon.
+ ///
+ NuclearTest,
+
+ ///
+ /// The Select Worm super weapon.
+ ///
+ SelectWorm,
+
+ ///
+ /// The Salvation Army super weapon.
+ ///
+ SalvationArmy,
+
+ ///
+ /// The Mole Squadron super weapon.
+ ///
+ MoleSquadron,
+
+ ///
+ /// The MB Bomb super weapon.
+ ///
+ MBBomb,
+
+ ///
+ /// The Concrete Donkey super weapon.
+ ///
+ ConcreteDonkey,
+
+ ///
+ /// The Suicide Bomber super weapon.
+ ///
+ SuicideBomber,
+
+ ///
+ /// The Sheep Strike super weapon.
+ ///
+ SheepStrike,
+
+ ///
+ /// The Mail Strike super weapon.
+ ///
+ MailStrike,
+
+ ///
+ /// The Armageddon super weapon.
+ ///
+ Armageddon
+ }
+}
diff --git a/src/tool/Syroot.Worms.Scratchpad/Program.cs b/src/tool/Syroot.Worms.Scratchpad/Program.cs
index 9346265..6a7775d 100644
--- a/src/tool/Syroot.Worms.Scratchpad/Program.cs
+++ b/src/tool/Syroot.Worms.Scratchpad/Program.cs
@@ -1,71 +1,94 @@
-using System;
-using System.Drawing.Imaging;
-using System.IO;
-using Syroot.Worms.Mgame;
-
-namespace Syroot.Worms.Scratchpad
-{
- internal class Program
- {
- // ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
-
- private static void Main(string[] args)
- {
- }
-
- private static void ConvertIgdImages()
- {
- string igdFolder = @"C:\Games\WWP Aqua\Images";
- string pngFolder = @"D:\Pictures\IGD";
- Directory.CreateDirectory(pngFolder);
-
- foreach (string igdFilePath in Directory.GetFiles(igdFolder, "*.igd", SearchOption.AllDirectories))
- {
-
- // Load the IGD and let it convert the images.
- Igd igd = new Igd(igdFilePath);
-
- // Save the images in the output folder under a relative path.
- string igdFileFolder = Path.GetDirectoryName(igdFilePath);
- string relativePath = igdFileFolder.Substring(igdFolder.Length).TrimStart(Path.DirectorySeparatorChar);
- string pngIgdFolder = Path.Combine(pngFolder, relativePath, Path.GetFileName(igdFilePath));
- Directory.CreateDirectory(pngIgdFolder);
- for (int i = 0; i < igd.Images.Count; i++)
- {
- string pngFileName = Path.ChangeExtension(i.ToString(), "png");
- IgdImage image = igd.Images[i];
- image.RawBitmap.ToBitmap().Save(Path.Combine(pngIgdFolder, pngFileName), ImageFormat.Png);
- }
- }
- }
-
- private static void ConvertKsfImages()
- {
- string ksfFolder = @"C:\Games\Online Worms\Ksf";
- string palFolder = @"C:\Games\Online Worms\Palette";
- string pngFolder = @"D:\Pictures\KSF";
- Directory.CreateDirectory(pngFolder);
- Palette fallbackPalette = new Palette(Path.Combine(palFolder, "StaticImage.pal"));
-
- foreach (string ksfFilePath in Directory.GetFiles(ksfFolder, "*.ksf"))
- {
- // Try to find a palette for every KSF, otherwise use fallback palette.
- string ksfFileName = Path.GetFileName(ksfFilePath);
- string palFilePath = Path.Combine(palFolder, Path.ChangeExtension(ksfFileName, "pal"));
- Palette palette = File.Exists(palFilePath) ? new Palette(palFilePath) : fallbackPalette;
-
- // Load the KSF and let it convert the images.
- Ksf ksf = new Ksf(ksfFilePath, palette);
-
- // Save the images in the output folder.
- string pngKsfFolder = Path.Combine(pngFolder, ksfFileName);
- Directory.CreateDirectory(pngKsfFolder);
- for (int i = 0; i < ksf.Images.Count; i++)
- {
- string pngFileName = Path.ChangeExtension(i.ToString(), "png");
- ksf.Images[i].RawBitmap?.ToBitmap().Save(Path.Combine(pngKsfFolder, pngFileName), ImageFormat.Png);
- }
- }
- }
- }
+using System;
+using System.Collections.Generic;
+using System.Drawing.Imaging;
+using System.IO;
+using Syroot.Worms.Armageddon;
+using Syroot.Worms.Mgame;
+
+namespace Syroot.Worms.Scratchpad
+{
+ internal class Program
+ {
+ // ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
+
+ private static void Main()
+ {
+ IEnumerable fileNames = Directory.EnumerateFiles(
+ @"C:\Games\Worms Armageddon 3.7.2.1\User\Schemes", "*.wsc", SearchOption.AllDirectories);
+
+ foreach (string fileName in fileNames)
+ {
+ string tempFile = Path.GetTempFileName();
+ using (Stream tempStream = new FileStream(tempFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
+ {
+ // Load the scheme and save it to temp file.
+ Scheme origScheme = new Scheme(fileName);
+ tempStream.Position = 0;
+ origScheme.Save(tempStream);
+
+ // Load the temp file.
+ tempStream.Position = 0;
+ Scheme newScheme = new Scheme(tempStream);
+
+ if (origScheme.ObjectCount != newScheme.ObjectCount || origScheme.ObjectTypes != newScheme.ObjectTypes)
+ throw new InvalidOperationException("mismatch");
+ }
+ File.Delete(tempFile);
+ }
+ }
+
+ private static void ConvertIgdImages()
+ {
+ string igdFolder = @"C:\Games\WWP Aqua\Images";
+ string pngFolder = @"D:\Pictures\IGD";
+ Directory.CreateDirectory(pngFolder);
+
+ foreach (string igdFilePath in Directory.GetFiles(igdFolder, "*.igd", SearchOption.AllDirectories))
+ {
+ // Load the IGD and let it convert the images.
+ Igd igd = new Igd(igdFilePath);
+
+ // Save the images in the output folder under a relative path.
+ string igdFileFolder = Path.GetDirectoryName(igdFilePath);
+ string relativePath = igdFileFolder.Substring(igdFolder.Length).TrimStart(Path.DirectorySeparatorChar);
+ string pngIgdFolder = Path.Combine(pngFolder, relativePath, Path.GetFileName(igdFilePath));
+ Directory.CreateDirectory(pngIgdFolder);
+ for (int i = 0; i < igd.Images.Count; i++)
+ {
+ string pngFileName = Path.ChangeExtension(i.ToString(), "png");
+ IgdImage image = igd.Images[i];
+ image.RawBitmap.ToBitmap().Save(Path.Combine(pngIgdFolder, pngFileName), ImageFormat.Png);
+ }
+ }
+ }
+
+ private static void ConvertKsfImages()
+ {
+ string ksfFolder = @"C:\Games\Online Worms\Ksf";
+ string palFolder = @"C:\Games\Online Worms\Palette";
+ string pngFolder = @"D:\Pictures\KSF";
+ Directory.CreateDirectory(pngFolder);
+ Palette fallbackPalette = new Palette(Path.Combine(palFolder, "StaticImage.pal"));
+
+ foreach (string ksfFilePath in Directory.GetFiles(ksfFolder, "*.ksf"))
+ {
+ // Try to find a palette for every KSF, otherwise use fallback palette.
+ string ksfFileName = Path.GetFileName(ksfFilePath);
+ string palFilePath = Path.Combine(palFolder, Path.ChangeExtension(ksfFileName, "pal"));
+ Palette palette = File.Exists(palFilePath) ? new Palette(palFilePath) : fallbackPalette;
+
+ // Load the KSF and let it convert the images.
+ Ksf ksf = new Ksf(ksfFilePath, palette);
+
+ // Save the images in the output folder.
+ string pngKsfFolder = Path.Combine(pngFolder, ksfFileName);
+ Directory.CreateDirectory(pngKsfFolder);
+ for (int i = 0; i < ksf.Images.Count; i++)
+ {
+ string pngFileName = Path.ChangeExtension(i.ToString(), "png");
+ ksf.Images[i].RawBitmap?.ToBitmap().Save(Path.Combine(pngKsfFolder, pngFileName), ImageFormat.Png);
+ }
+ }
+ }
+ }
}
\ No newline at end of file