From 854ba278c8c419277b2e0d85a29a255b04c7a79d Mon Sep 17 00:00:00 2001 From: Michael Becker Date: Thu, 28 May 2020 18:16:59 -0400 Subject: [PATCH] various improvements and additions to the New World Computing / Heroes of Might and Magic plugin --- .../NewWorldComputing/NWCMap.uexml | 4 +- .../NewWorldComputing/NWCPalette.uexml | 23 +- .../NewWorldComputing/NWCPicture.uexml | 15 ++ .../NewWorldComputing/NWCResourceBIN.uexml | 17 +- .../Palette/NewWorldComputingPAL.uexml | 20 -- ...lEditor.Content.PlatformIndependent.csproj | 1 - .../DataFormatFragment.cs | 41 ++++ .../UniversalEditor.Core.csproj | 1 + .../RIFFPaletteDataFormat.cs | 81 +++++++ .../NewWorldComputing/PCX/PCXDataFormat.cs | 109 +++++++++ .../NewWorldComputing/BIN/BINDataFormat.cs | 6 + .../Animation/BINAnimationType.cs | 61 +++++ .../Animation/BINDataFormat.cs | 147 +++++++++++ .../Heroes2/CastleFragment.cs | 102 ++++++++ .../Heroes2/EventFragment.cs | 93 +++++++ .../NewWorldComputing/Heroes2/HeroFragment.cs | 167 +++++++++++++ .../Heroes2/Heroes2MapDataFormat.cs | 229 ++++++++++-------- .../Heroes2/MonsterFragment.cs | 39 +++ .../NewWorldComputing/Heroes2/TileFragment.cs | 62 +++++ .../Heroes3/Heroes3GameType.cs | 2 +- .../Heroes3/Heroes3MapDataFormat.cs | 2 +- .../NewWorldComputing/HeroSkill.cs | 41 ++++ .../NewWorldComputing/HeroSkillLevel.cs | 30 +++ .../NewWorldComputing/HeroSkillType.cs | 28 +++ .../NewWorldComputing/Map/MapArmyMonster.cs | 16 +- .../NewWorldComputing/Map/MapArtifact.cs | 39 +++ .../NewWorldComputing/Map/MapArtifactType.cs | 28 +++ .../NewWorldComputing/Map/MapCastle.cs | 2 +- .../NewWorldComputing/Map/MapCastleType.cs | 4 +- .../NewWorldComputing/Map/MapEvent.cs | 100 ++++++++ .../NewWorldComputing/Map/MapHero.cs | 45 ++++ .../NewWorldComputing/Map/MapItem.cs | 33 +++ .../NewWorldComputing/Map/MapItemType.cs | 32 +++ .../NewWorldComputing/Map/MapObjectModel.cs | 6 + .../NewWorldComputing/Map/MapResourceType.cs | 39 +++ .../NewWorldComputing/Map/MapTile.cs | 13 +- ...salEditor.Plugins.NewWorldComputing.csproj | 21 ++ 37 files changed, 1571 insertions(+), 128 deletions(-) delete mode 100644 Content/UniversalEditor.Content.PlatformIndependent/Extensions/GraphicDesigner/Associations/Palette/NewWorldComputingPAL.uexml create mode 100644 Libraries/UniversalEditor.Core/DataFormatFragment.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/Multimedia/Palette/NewWorldComputing/RIFFPaletteDataFormat.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/Multimedia/Picture/NewWorldComputing/PCX/PCXDataFormat.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/Animation/BINAnimationType.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/Animation/BINDataFormat.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/CastleFragment.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/EventFragment.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/HeroFragment.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/MonsterFragment.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/TileFragment.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/HeroSkill.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/HeroSkillLevel.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/HeroSkillType.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapArtifact.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapArtifactType.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapEvent.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapHero.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapItem.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapItemType.cs create mode 100644 Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapResourceType.cs diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCMap.uexml b/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCMap.uexml index bbaff359..364f7ff8 100644 --- a/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCMap.uexml +++ b/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCMap.uexml @@ -38,7 +38,7 @@ - + @@ -67,7 +67,7 @@ - + diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCPalette.uexml b/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCPalette.uexml index 4faf4ac9..9c25af00 100644 --- a/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCPalette.uexml +++ b/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCPalette.uexml @@ -3,7 +3,7 @@ - + *.pal @@ -16,5 +16,26 @@ + + + + + *.pal + + + + RIFF + PAL + + + + + + + + + + + \ No newline at end of file diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCPicture.uexml b/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCPicture.uexml index 95bdd0e6..04f727cc 100644 --- a/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCPicture.uexml +++ b/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCPicture.uexml @@ -47,5 +47,20 @@ + + + + + *.pcx + + + + + + + + + + \ No newline at end of file diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCResourceBIN.uexml b/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCResourceBIN.uexml index daba2d24..166ab075 100644 --- a/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCResourceBIN.uexml +++ b/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GameDeveloper/Associations/NewWorldComputing/NWCResourceBIN.uexml @@ -3,7 +3,7 @@ - + *.bin @@ -16,5 +16,20 @@ + + + + + *.bin + + + + + + + + + + \ No newline at end of file diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GraphicDesigner/Associations/Palette/NewWorldComputingPAL.uexml b/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GraphicDesigner/Associations/Palette/NewWorldComputingPAL.uexml deleted file mode 100644 index 5008a1b8..00000000 --- a/Content/UniversalEditor.Content.PlatformIndependent/Extensions/GraphicDesigner/Associations/Palette/NewWorldComputingPAL.uexml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - *.pal - - - - - - - - - - - - \ No newline at end of file diff --git a/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj b/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj index bbed5fa3..0fc02b36 100644 --- a/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj +++ b/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj @@ -608,7 +608,6 @@ - diff --git a/Libraries/UniversalEditor.Core/DataFormatFragment.cs b/Libraries/UniversalEditor.Core/DataFormatFragment.cs new file mode 100644 index 00000000..de273d89 --- /dev/null +++ b/Libraries/UniversalEditor.Core/DataFormatFragment.cs @@ -0,0 +1,41 @@ +// +// DataFormatFragment.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using System; +using UniversalEditor.IO; + +namespace UniversalEditor +{ + public abstract class DataFormatFragment + { + protected abstract T ReadInternal(IO.Reader reader); + protected abstract void WriteInternal(IO.Writer writer, T value); + + public T Read(IO.Reader reader) + { + return ReadInternal(reader); + } + public void Write(IO.Writer writer, T value) + { + WriteInternal(writer, value); + } + } +} diff --git a/Libraries/UniversalEditor.Core/UniversalEditor.Core.csproj b/Libraries/UniversalEditor.Core/UniversalEditor.Core.csproj index 171e4194..30a0a8a1 100644 --- a/Libraries/UniversalEditor.Core/UniversalEditor.Core.csproj +++ b/Libraries/UniversalEditor.Core/UniversalEditor.Core.csproj @@ -91,6 +91,7 @@ + diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/Multimedia/Palette/NewWorldComputing/RIFFPaletteDataFormat.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/Multimedia/Palette/NewWorldComputing/RIFFPaletteDataFormat.cs new file mode 100644 index 00000000..f786f12c --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/Multimedia/Palette/NewWorldComputing/RIFFPaletteDataFormat.cs @@ -0,0 +1,81 @@ +// +// RIFFPaletteDataFormat.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using System.Collections.Generic; +using UniversalEditor.DataFormats.Chunked.RIFF; +using UniversalEditor.ObjectModels.Chunked; +using UniversalEditor.ObjectModels.Multimedia.Palette; + +namespace UniversalEditor.DataFormats.Multimedia.Palette.NewWorldComputing +{ + public class RIFFPaletteDataFormat : RIFFDataFormat + { + private static DataFormatReference _dfr = null; + protected override DataFormatReference MakeReferenceInternal() + { + if (_dfr == null) + { + _dfr = new DataFormatReference(GetType()); + _dfr.Capabilities.Add(typeof(PaletteObjectModel), DataFormatCapabilities.All); + } + return _dfr; + } + + protected override void BeforeLoadInternal(Stack objectModels) + { + base.BeforeLoadInternal(objectModels); + objectModels.Push(new ChunkedObjectModel()); + } + protected override void AfterLoadInternal(Stack objectModels) + { + base.AfterLoadInternal(objectModels); + + ChunkedObjectModel riff = (objectModels.Pop() as ChunkedObjectModel); + PaletteObjectModel palette = (objectModels.Pop() as PaletteObjectModel); + + RIFFGroupChunk grp = (riff.Chunks[0] as RIFFGroupChunk); + if (grp.ID != "PAL ") + throw new InvalidDataFormatException("RIFF container does not contain a group chunk with ID 'PAL '"); + + RIFFDataChunk data = (grp.Chunks["data"] as RIFFDataChunk); + if (data == null) + throw new InvalidDataFormatException("'PAL ' group chunk does not contain a data chunk with ID 'data'"); + + if (data.Data.Length % 4 != 0) + throw new InvalidDataFormatException("'data' data chunk length is not evenly divisible by 4"); + + for (int i = 4; i < data.Data.Length; i += 4) + { + MBS.Framework.Drawing.Color color = MBS.Framework.Drawing.Color.FromRGBAByte(data.Data[i], data.Data[i + 1], data.Data[i + 2]); + palette.Entries.Add(new PaletteEntry(color)); + } + } + protected override void BeforeSaveInternal(Stack objectModels) + { + base.BeforeSaveInternal(objectModels); + + PaletteObjectModel palette = (objectModels.Pop() as PaletteObjectModel); + ChunkedObjectModel riff = new ChunkedObjectModel(); + + objectModels.Push(riff); + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/Multimedia/Picture/NewWorldComputing/PCX/PCXDataFormat.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/Multimedia/Picture/NewWorldComputing/PCX/PCXDataFormat.cs new file mode 100644 index 00000000..bb4cc336 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/Multimedia/Picture/NewWorldComputing/PCX/PCXDataFormat.cs @@ -0,0 +1,109 @@ +// +// PCXDataFormat.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using UniversalEditor.IO; +using UniversalEditor.ObjectModels.Multimedia.Palette; +using UniversalEditor.ObjectModels.Multimedia.Picture; + +namespace UniversalEditor.DataFormats.Multimedia.Picture.NewWorldComputing.PCX +{ + public class PCXDataFormat : DataFormat + { + private static DataFormatReference _dfr = null; + protected override DataFormatReference MakeReferenceInternal() + { + if (_dfr == null) + { + _dfr = base.MakeReferenceInternal(); + _dfr.Capabilities.Add(typeof(PictureObjectModel), DataFormatCapabilities.All); + _dfr.ImportOptions.Add(new CustomOptionFile("PaletteFileName", "External _palette", "Palette|*.pal")); + } + return _dfr; + } + + public string PaletteFileName { get; set; } = null; + public PaletteObjectModel Palette { get; set; } = null; + + protected override void LoadInternal(ref ObjectModel objectModel) + { + PictureObjectModel pic = (objectModel as PictureObjectModel); + if (pic == null) throw new ObjectModelNotSupportedException(); + + Reader reader = Accessor.Reader; + + if (!String.IsNullOrEmpty(PaletteFileName) && System.IO.File.Exists(PaletteFileName)) + { + Palette = Common.Reflection.GetAvailableObjectModel(PaletteFileName); + } + + uint dataLength = reader.ReadUInt32(); + uint width = reader.ReadUInt32(); + uint height = reader.ReadUInt32(); + if (dataLength != (width * height)) + { + // TODO: sanity check? + } + + pic.Width = (int)width; + pic.Height = (int)height; + + byte[] indices = reader.ReadBytes(width * height); + + if (Palette == null) + Palette = new PaletteObjectModel(); + + if (!reader.EndOfStream) + { + // byte nul = reader.ReadByte(); + // if (nul != 0) return; //eeee? + + for (int i = 0; i < 256; i++) + { + byte r = reader.ReadByte(); + byte g = reader.ReadByte(); + byte b = reader.ReadByte(); + Palette.Entries.Add(new PaletteEntry(MBS.Framework.Drawing.Color.FromRGBAByte(r, g, b))); + } + } + + int x = 0, y = 0; + for (int i = 0; i < indices.Length; i++) + { + byte index = indices[i]; + pic.SetPixel(Palette.Entries[index].Color, x, y); + + x++; + if (x >= pic.Width) + { + reader.Align(4); + + x = 0; + y++; + } + } + } + + protected override void SaveInternal(ObjectModel objectModel) + { + throw new NotImplementedException(); + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NWCSceneLayout/NewWorldComputing/BIN/BINDataFormat.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NWCSceneLayout/NewWorldComputing/BIN/BINDataFormat.cs index 5102339b..21c8d9d8 100644 --- a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NWCSceneLayout/NewWorldComputing/BIN/BINDataFormat.cs +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NWCSceneLayout/NewWorldComputing/BIN/BINDataFormat.cs @@ -173,6 +173,12 @@ namespace UniversalEditor.DataFormats.NWCSceneLayout.NewWorldComputing.BIN if (designer == null) throw new ObjectModelNotSupportedException(); + // HACK: because there simply is no better way to differentiate between window layout BINs and animation BINs (except maybe filename ending in FRM.BIN) + if (Accessor.Length == 821 && Accessor.GetFileName().EndsWith("FRM.BIN")) + { + throw new InvalidDataFormatException(); // to kick it to the *other* BIN format + } + if (!designer.Libraries.Contains(NWCSceneLayoutLibrary)) designer.Libraries.Add(NWCSceneLayoutLibrary); diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/Animation/BINAnimationType.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/Animation/BINAnimationType.cs new file mode 100644 index 00000000..43f46d38 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/Animation/BINAnimationType.cs @@ -0,0 +1,61 @@ +// +// BINAnimationType.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace UniversalEditor.DataFormats.NewWorldComputing.Animation +{ + public enum BINAnimationType + { + MOVE_START, // Start of the moving sequence on 1st animation cycle: flyers will fly up + MOVE_TILE_START, // Supposed to be played at the beginning of 2nd+ move. + MOVE_MAIN, // Core animation. Most units only have this one. + MOVE_TILE_END, // Cavalry & wolf. Played at the end of the cycle (2nd tile to 3rd), but not at the last one + MOVE_STOP, // End of the moving sequence when arrived: landing for example + MOVE_ONE, // Used when moving 1 tile. LICH and POWER_LICH doesn't have this, use MOVE_MAIN + TEMPORARY, // This is an empty placeholder for combined animation built from previous parts + STATIC, // Frame 1 + IDLE1, + IDLE2, // Idle animations: picked at random with different probablities, rarely all 5 present + IDLE3, + IDLE4, + IDLE5, + DEATH, + WINCE_UP, + WINCE_END, + ATTACK1, // Attacks, number represents the angle: 1 is TOP, 2 is CENTER, 3 is BOTTOM + ATTACK1_END, + DOUBLEHEX1, + DOUBLEHEX1_END, + ATTACK2, + ATTACK2_END, + DOUBLEHEX2, + DOUBLEHEX2_END, + ATTACK3, + ATTACK3_END, + DOUBLEHEX3, + DOUBLEHEX3_END, + SHOOT1, + SHOOT1_END, + SHOOT2, + SHOOT2_END, + SHOOT3, + SHOOT3_END + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/Animation/BINDataFormat.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/Animation/BINDataFormat.cs new file mode 100644 index 00000000..9ad713ac --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/Animation/BINDataFormat.cs @@ -0,0 +1,147 @@ +// +// BINDataFormat.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using UniversalEditor.IO; +using UniversalEditor.ObjectModels.Multimedia.SpriteAnimationCollection; + +namespace UniversalEditor.DataFormats.NewWorldComputing.Animation +{ + public class BINDataFormat : DataFormat + { + public const byte IDLE_ANIMATION_COUNT_MAX = 5; + public const byte PROJECTILE_ANGLE_MAX = 12; + public const byte FRAME_MAX = 16; + + private static DataFormatReference _dfr = null; + protected override DataFormatReference MakeReferenceInternal() + { + if (_dfr == null) + { + _dfr = base.MakeReferenceInternal(); + _dfr.Capabilities.Add(typeof(SpriteAnimationCollectionObjectModel), DataFormatCapabilities.All); + } + return _dfr; + } + + protected override void LoadInternal(ref ObjectModel objectModel) + { + SpriteAnimationCollectionObjectModel anim = (objectModel as SpriteAnimationCollectionObjectModel); + if (anim == null) + throw new ObjectModelNotSupportedException(); + + // HACK: because there simply is no better way to differentiate between window layout BINs and animation BINs (except maybe filename ending in FRM.BIN) + if (!(Accessor.Length == 821 && Accessor.GetFileName().EndsWith("FRM.BIN"))) + { + throw new InvalidDataFormatException(); // to kick it to the *other* BIN format + } + + Reader reader = Accessor.Reader; + + byte one = reader.ReadByte(); + + short eyePositionX = reader.ReadInt16(); + short eyePositionY = reader.ReadInt16(); + + // frame offsets for the future use + int[][] moveOffsets = new int[7][]; + for (int i = 0; i < 7; i++) + { + int[] moveOffset = new int[16]; + for ( int frame = 0; frame < 16; ++frame) + { + moveOffset[frame] = reader.ReadByte(); + } + moveOffsets[i] = moveOffset; + } + + // at offset 117 + byte idleAnimationCount = reader.ReadByte(); + float[] idleAnimationPriorities = new float[IDLE_ANIMATION_COUNT_MAX]; + uint[] unusedIdleDelays = new uint[IDLE_ANIMATION_COUNT_MAX]; + for (byte i = 0; i < IDLE_ANIMATION_COUNT_MAX; i++) + { + idleAnimationPriorities[i] = reader.ReadSingle(); + } + for (byte i = 0; i < IDLE_ANIMATION_COUNT_MAX; i++) + { + unusedIdleDelays[i] = reader.ReadUInt32(); + } + + // at offset 158 + uint idleAnimationDelay = reader.ReadUInt32(); + + uint moveSpeed = reader.ReadUInt32(); + uint shootSpeed = reader.ReadUInt32(); + uint flightSpeed = reader.ReadUInt32(); + + // projectile data + for (int i = 0; i < 3; i++) + { + short projectileOffsetX = reader.ReadInt16(); + short projectileOffsetY = reader.ReadInt16(); + } + + // describes how to rotate the projectile when + byte projectileAngleCount = reader.ReadByte(); + for (byte i = 0; i < PROJECTILE_ANGLE_MAX; i++) + { + // even though there are only {projectileAngleCount} items, the rest of PROJECTILE_ANGLE_MAX is filled with zeroes + float projectileAngle = reader.ReadSingle(); + } + + // Positional offsets for sprites & drawing + uint troopCountOffsetLeft = reader.ReadUInt32(); + uint troopCountOffsetRight = reader.ReadUInt32(); + + // Load animation sequences themselves + int nMaxAnimationTypes = Enum.GetValues(typeof(BINAnimationType)).Length; + + byte[] animCounts = new byte[nMaxAnimationTypes]; + byte[][] animFrames = new byte[nMaxAnimationTypes][]; + + SpriteAnimation[] anims = new SpriteAnimation[nMaxAnimationTypes]; + for (int idx = 0; idx < nMaxAnimationTypes; ++idx) + { + animCounts[idx] = reader.ReadByte(); + + anims[idx] = new SpriteAnimation(); + anims[idx].Name = Enum.GetName(typeof(BINAnimationType), idx); + } + for (int idx = 0; idx < nMaxAnimationTypes; ++idx) + { + animFrames[idx] = new byte[FRAME_MAX]; + for (byte frame = 0; frame < FRAME_MAX; frame++) + { + animFrames[idx][frame] = reader.ReadByte(); + } + for (byte frame = 0; frame < animCounts[idx]; frame++) + { + anims[idx].Frames.Add(animFrames[idx][frame]); + } + anim.Animations.Add(anims[idx]); + } + } + protected override void SaveInternal(ObjectModel objectModel) + { + throw new NotImplementedException(); + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/CastleFragment.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/CastleFragment.cs new file mode 100644 index 00000000..30cd1493 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/CastleFragment.cs @@ -0,0 +1,102 @@ +// +// CastleFragment.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using UniversalEditor.IO; +using UniversalEditor.ObjectModels.NewWorldComputing.Map; + +namespace UniversalEditor.DataFormats.NewWorldComputing.WorldMap2D.NewWorldComputing.Heroes2 +{ + public class CastleFragment : DataFormatFragment + { + protected override MapCastle ReadInternal(Reader reader) + { + MapCastle castle = new MapCastle(); + castle.Color = (MapCastleColor)reader.ReadByte(); + castle.HasCustomBuilding = reader.ReadBoolean(); + castle.Buildings = (MapBuildingType)reader.ReadUInt16(); + castle.Dwellings = (MapDwellingType)reader.ReadUInt16(); + castle.MageGuildLevel = (MapMageGuildLevel)reader.ReadByte(); + castle.HasCustomTroops = reader.ReadBoolean(); + + byte[] monsterTypes = reader.ReadBytes(5); + ushort[] monsterCounts = reader.ReadUInt16Array(5); + for (int i = 0; i < monsterTypes.Length; i++) + { + if (monsterTypes[i] != 0xFF) + { + castle.Monsters[i] = new MapArmyMonster((MapMonsterType)monsterTypes[i], monsterCounts[i]); + } + } + + castle.HasCaptain = reader.ReadBoolean(); + castle.HasCustomName = reader.ReadBoolean(); + castle.Name = reader.ReadFixedLengthString(13).TrimNull(); + castle.Type = (MapCastleType)reader.ReadByte(); + castle.IsCastle = reader.ReadBoolean(); + castle.IsUpgradable = reader.ReadBoolean(); // 00 TRUE, 01 FALSE + + byte[] unknown = reader.ReadBytes(29); + + return castle; + } + protected override void WriteInternal(Writer writer, MapCastle value) + { + writer.WriteByte((byte)value.Color); + writer.WriteBoolean(value.HasCustomBuilding); + writer.WriteUInt16((ushort)value.Buildings); + writer.WriteUInt16((ushort)value.Dwellings); + writer.WriteByte((byte)value.MageGuildLevel); + writer.WriteBoolean(value.HasCustomTroops); + + for (int i = 0; i < 5; i++) + { + if (i < value.Monsters.Length) + { + writer.WriteByte((byte)value.Monsters[i].MonsterType); + } + else + { + writer.WriteByte(0); + } + } + for (int i = 0; i < 5; i++) + { + if (i < value.Monsters.Length) + { + writer.WriteUInt16(value.Monsters[i].Amount); + } + else + { + writer.WriteUInt16(0); + } + } + + writer.WriteBoolean(value.HasCaptain); + writer.WriteBoolean(value.HasCustomName); + writer.WriteFixedLengthString(value.Name, 13); + writer.WriteByte((byte)value.Type); + writer.WriteBoolean(value.IsCastle); + writer.WriteBoolean(value.IsUpgradable); // 00 TRUE, 01 FALSE + + writer.WriteBytes(new byte[29]);// idk + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/EventFragment.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/EventFragment.cs new file mode 100644 index 00000000..47982a5c --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/EventFragment.cs @@ -0,0 +1,93 @@ +// +// EventFragment.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using UniversalEditor.IO; +using UniversalEditor.ObjectModels.NewWorldComputing.Map; + +namespace UniversalEditor.DataFormats.NewWorldComputing.WorldMap2D.NewWorldComputing.Heroes2 +{ + public class EventFragment : DataFormatFragment + { + protected override MapEvent ReadInternal(Reader reader) + { + MapEvent evt = new MapEvent(); + evt.AmountWood = reader.ReadInt32(); + evt.AmountMercury = reader.ReadInt32(); + evt.AmountOre = reader.ReadInt32(); + evt.AmountSulfur = reader.ReadInt32(); + evt.AmountCrystal = reader.ReadInt32(); + evt.AmountGems = reader.ReadInt32(); + evt.AmountGold = reader.ReadInt32(); + + short nArtifact = reader.ReadInt16(); + // evt.Artifact = (MapArtifact)nArtifact; + + evt.AllowComputer = reader.ReadBoolean(); + evt.SingleVisit = reader.ReadBoolean(); + + byte[] unknown = reader.ReadBytes(10); + + bool colorBlue = reader.ReadBoolean(); + if (colorBlue) evt.AllowedKingdoms |= MapKingdomColor.Blue; + bool colorGreen = reader.ReadBoolean(); + if (colorGreen) evt.AllowedKingdoms |= MapKingdomColor.Green; + bool colorRed = reader.ReadBoolean(); + if (colorRed) evt.AllowedKingdoms |= MapKingdomColor.Red; + bool colorYellow = reader.ReadBoolean(); + if (colorYellow) evt.AllowedKingdoms |= MapKingdomColor.Yellow; + bool colorOrange = reader.ReadBoolean(); + if (colorOrange) evt.AllowedKingdoms |= MapKingdomColor.Orange; + bool colorPurple = reader.ReadBoolean(); + if (colorPurple) evt.AllowedKingdoms |= MapKingdomColor.Purple; + + evt.Message = reader.ReadNullTerminatedString(); + return evt; + } + protected override void WriteInternal(Writer writer, MapEvent value) + { + writer.WriteInt32(value.AmountWood); + writer.WriteInt32(value.AmountMercury); + writer.WriteInt32(value.AmountOre); + writer.WriteInt32(value.AmountSulfur); + writer.WriteInt32(value.AmountCrystal); + writer.WriteInt32(value.AmountGems); + writer.WriteInt32(value.AmountGold); + + short nArtifact = 0; + writer.WriteInt16(nArtifact); + // evt.Artifact = (MapArtifact)nArtifact; + + writer.WriteBoolean(value.AllowComputer); + writer.WriteBoolean(value.SingleVisit); + + writer.WriteBytes(new byte[10]); + + writer.WriteBoolean((value.AllowedKingdoms & MapKingdomColor.Blue) == MapKingdomColor.Blue); + writer.WriteBoolean((value.AllowedKingdoms & MapKingdomColor.Green) == MapKingdomColor.Green); + writer.WriteBoolean((value.AllowedKingdoms & MapKingdomColor.Red) == MapKingdomColor.Red); + writer.WriteBoolean((value.AllowedKingdoms & MapKingdomColor.Yellow) == MapKingdomColor.Yellow); + writer.WriteBoolean((value.AllowedKingdoms & MapKingdomColor.Orange) == MapKingdomColor.Orange); + writer.WriteBoolean((value.AllowedKingdoms & MapKingdomColor.Purple) == MapKingdomColor.Purple); + + writer.WriteNullTerminatedString(value.Message); + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/HeroFragment.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/HeroFragment.cs new file mode 100644 index 00000000..fcaf9a1d --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/HeroFragment.cs @@ -0,0 +1,167 @@ +// +// HeroFragment.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using UniversalEditor.IO; +using UniversalEditor.ObjectModels.NewWorldComputing; +using UniversalEditor.ObjectModels.NewWorldComputing.Map; + +namespace UniversalEditor.DataFormats.NewWorldComputing.WorldMap2D.NewWorldComputing.Heroes2 +{ + public class HeroFragment : DataFormatFragment + { + protected override MapHero ReadInternal(Reader reader) + { + MapHero hero = new MapHero(); + bool unk = reader.ReadBoolean(); + hero.HasCustomTroops = reader.ReadBoolean(); + + byte[] monsters = reader.ReadBytes(5); + ushort[] monsterCount = reader.ReadUInt16Array(5); + for (int i = 0; i < monsters.Length; i++) + { + if (monsters[i] != 0xFF) + { + MapMonsterType monsterType = (MapMonsterType)monsters[i]; + hero.Monsters.Add(new MapArmyMonster(monsterType, monsterCount[i])); + } + } + + hero.HasCustomPortrait = reader.ReadBoolean(); + hero.CustomPortraitIndex = reader.ReadByte(); + + byte[] customArtifacts = reader.ReadBytes(3); // -1 if unset + for (int i = 0; i < customArtifacts.Length; i++) + { + if (customArtifacts[i] != 0xFF) + { + MapArtifact artifact = new MapArtifact((MapArtifactType)customArtifacts[i]); + hero.Artifacts.Add(artifact); + } + } + + byte unknown2 = reader.ReadByte(); + + hero.Experience = reader.ReadUInt32(); + + hero.HasCustomSkills = reader.ReadBoolean(); + byte[] skills = reader.ReadBytes(8); // 0xff none, pathfinding, archery, logistic, scouting, diplomacy, navigation, leadership, wisdom, + // mysticism, luck, ballistics, eagle, necromance, estate + byte[] skillLevels = reader.ReadBytes(8); // 1 = basic, 2 = advanced, 3 = expert, 0 = unset + for (int i = 0; i < skills.Length; i++) + { + if (skills[i] != 0xFF) + { + HeroSkillType type = (HeroSkillType)skills[i]; + HeroSkillLevel level = (HeroSkillLevel)skillLevels[i]; + hero.Skills.Add(new HeroSkill(type, level)); + } + } + + byte unknown3 = reader.ReadByte(); + hero.HasCustomName = reader.ReadBoolean(); + hero.Name = reader.ReadFixedLengthString(13).TrimNull(); + hero.Patrol = reader.ReadBoolean(); + hero.PatrolSquareCount = reader.ReadByte(); + + byte[] unknown4 = reader.ReadBytes(15); + return hero; + } + + protected override void WriteInternal(Writer writer, MapHero value) + { + writer.WriteBoolean(false); + writer.WriteBoolean(value.HasCustomTroops); + + for (int i = 0; i < 5; i++) + { + if (i < value.Monsters.Count) + { + writer.WriteByte((byte)value.Monsters[i].MonsterType); + } + else + { + writer.WriteByte(255); + } + } + for (int i = 0; i < 5; i++) + { + if (i < value.Monsters.Count) + { + writer.WriteUInt16((byte)value.Monsters[i].Amount); + } + else + { + writer.WriteUInt16(0); + } + } + + writer.WriteBoolean(value.HasCustomPortrait); + writer.WriteByte(value.CustomPortraitIndex); + + for (int i = 0; i < 3; i++) + { + if (i < value.Artifacts.Count) + { + writer.WriteByte((byte)value.Artifacts[i].Type); + } + else + { + writer.WriteByte(255); + } + } + + writer.WriteByte(0); + writer.WriteUInt32(value.Experience); + + writer.WriteBoolean(value.HasCustomSkills); + for (int i = 0; i < 8; i++) + { + if (i < value.Skills.Count) + { + writer.WriteByte((byte)value.Skills[i].Type); + } + else + { + writer.WriteByte(255); + } + } + for (int i = 0; i < 8; i++) + { + if (i < value.Skills.Count) + { + writer.WriteByte((byte)value.Skills[i].Level); + } + else + { + writer.WriteByte(0); + } + } + + writer.WriteByte(0); // unknown3 + writer.WriteBoolean(value.HasCustomName); + writer.WriteFixedLengthString(value.Name, 13); + writer.WriteBoolean(value.Patrol); + writer.WriteByte(value.PatrolSquareCount); + + writer.WriteBytes(new byte[15]); + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/Heroes2MapDataFormat.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/Heroes2MapDataFormat.cs index 965a6a25..7606b068 100644 --- a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/Heroes2MapDataFormat.cs +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/Heroes2MapDataFormat.cs @@ -20,9 +20,11 @@ // along with this program. If not, see . using System; +using UniversalEditor.IO; +using UniversalEditor.ObjectModels.NewWorldComputing; using UniversalEditor.ObjectModels.NewWorldComputing.Map; -namespace UniversalEditor.DataFormats.Gaming.WorldMap2D.NewWorldComputing.Heroes2 +namespace UniversalEditor.DataFormats.NewWorldComputing.WorldMap2D.NewWorldComputing.Heroes2 { /// /// Pprovides a for manipulating Heroes of Might and Magic II map files. @@ -119,138 +121,173 @@ namespace UniversalEditor.DataFormats.Gaming.WorldMap2D.NewWorldComputing.Heroes #endregion // kingdom count - br.Accessor.Seek(0x1A, IO.SeekOrigin.Begin); byte kingdomCount = br.ReadByte(); + byte nCount1 = br.ReadByte(); // idk? + byte nCount2 = br.ReadByte(); // idk? - br.Accessor.Seek(0x1D, IO.SeekOrigin.Begin); map.WinConditions = (MapWinCondition)br.ReadByte(); + map.ComputerAlsoWins = (MapWinCondition)br.ReadByte(); + map.AllowNormalVictory = br.ReadBoolean(); - byte wins1 = br.ReadByte(); - byte wins2 = br.ReadByte(); ushort wins3 = br.ReadUInt16(); - br.Accessor.Seek(0x2C, IO.SeekOrigin.Begin); - ushort wins4 = br.ReadUInt16(); - br.Accessor.Seek(0x22, IO.SeekOrigin.Begin); map.LoseConditions = (MapLoseCondition)br.ReadByte(); - - ushort loss1 = br.ReadUInt16(); - br.Accessor.Seek(0x2E, IO.SeekOrigin.Begin); - ushort loss2 = br.ReadUInt16(); + ushort u2 = br.ReadUInt16(); // starting hero - br.Accessor.Seek(0x25, IO.SeekOrigin.Begin); byte startingHero = br.ReadByte(); bool withHeroes = (startingHero == 0); - byte[] races = br.ReadBytes(5); + byte[] races = br.ReadBytes(6); - // name + ushort wins2 = br.ReadUInt16(); + ushort loss2 = br.ReadUInt16(); + + // map name br.Accessor.Seek(0x3A, IO.SeekOrigin.Begin); - map.Name = br.ReadFixedLengthString(16); - map.Name = map.Name.TrimNull(); - // name + map.Name = br.ReadFixedLengthString(16).TrimNull(); + + // map description br.Accessor.Seek(0x76, IO.SeekOrigin.Begin); - map.Description = br.ReadFixedLengthString(143); - map.Description = map.Description.TrimNull(); + map.Description = br.ReadFixedLengthString(143).TrimNull(); byte[] unknown = br.ReadBytes(157); - ushort unknown2 = br.ReadUInt16(); + ushort nObjects = br.ReadUInt16(); - // 33044 bytes between here and there - tiles (36 * 36 * 25 bytes per tile) + // 33044 bytes between here and there - tiles (width * height * 20 bytes per tile) + uint width = br.ReadUInt32(); + uint height = br.ReadUInt32(); - long pos = br.Accessor.Position; - br.Accessor.Position = pos; - - for (ushort i = 0; i < unknown2; i++) - { - MapTile tile = ReadTile(br); - } + TileFragment fragTile = new TileFragment(); for (int y = 0; y < map.Height; y++) { for (int x = 0; x < map.Width; x++) { - MapTile tile = ReadTile(br); + MapTile tile = fragTile.Read(br); map.Tiles.Add(tile); } } - #region Castle - for (byte i = 0; i < kingdomCount; i++) + // addons + uint nAddons = br.ReadUInt32(); + for (uint i = 0; i < nAddons; i++) { - MapCastle castle = ReadCastle(br); + ushort indexAddon = br.ReadUInt16(); + byte objectNameN1 = br.ReadByte(); + objectNameN1 *= 2; // idk + byte indexNameN1 = br.ReadByte(); + byte quantityN = br.ReadByte(); + byte objectNameN2 = br.ReadByte(); + byte indexNameN2 = br.ReadByte(); + uint uniqNumberN1 = br.ReadUInt32(); + uint uniqNumberN2 = br.ReadUInt32(); + } + + for (int i = 0; i < 72; i++) + { + // castle coordinates + // 72 x 3 byte (cx, cy, id) + byte cx = br.ReadByte(); + byte cy = br.ReadByte(); + byte id = br.ReadByte(); + + if (cx == 0xFF && cy == 0xFF) + continue; + + bool isCastle = false; + if ((id & 0x80) == 0x80) + { + isCastle = true; + id = (byte)(id & ~0x80); + } + + MapCastleType castleType = (MapCastleType)id; + // map.Castles.Add(new MapCastle(castleType, cx, cy, isCastle)); + } + + // kingdom resource coordinates + for (int i = 0; i < 144; i++) + { + byte cx = br.ReadByte(); + byte cy = br.ReadByte(); + byte id = br.ReadByte(); + + if (cx == 0xFF && cy == 0xFF) + continue; + + MapResourceType resourceType = (MapResourceType)id; + + } + + map.ObeliskCount = br.ReadByte(); + return; + + // idk wtf this is + uint countBlock = 0; + while (!br.EndOfStream) + { + byte l = br.ReadByte(); + byte h = br.ReadByte(); + if (l == 0 && h == 0) + break; + countBlock = (uint)(256 * (h + l) - 1); // wtf + } + + MonsterFragment fragMonster = new MonsterFragment(); + CastleFragment fragCastle = new CastleFragment(); + HeroFragment fragHero = new HeroFragment(); + EventFragment fragEvent = new EventFragment(); + + for (ushort i = 0; i < countBlock; i++) + { + ushort blockSize = br.ReadUInt16(); + + MapTile tile = FindObject(map, i); + switch ((MapItemType)blockSize) + { + case MapItemType.Monster: + { + MapArmyMonster item = fragMonster.Read(br); + map.Items.Add(item); + break; + } + case MapItemType.Castle: + { + MapCastle castle = fragCastle.Read(br); + map.Items.Add(castle); + break; + } + case MapItemType.Hero: + { + MapHero hero = fragHero.Read(br); + map.Items.Add(hero); + break; + } + } } - #endregion } - private MapTile ReadTile(IO.Reader br) + private MapTile FindObject(MapObjectModel map, ushort i) { - MapTile tile = new MapTile(); - tile.GroundType = (MapGroundType)br.ReadUInt16(); // tile (ocean, grass, snow, swamp, lava, desert, dirt, wasteland, beach) - byte objectName1 = br.ReadByte(); // level 1.0 - byte indexName1 = br.ReadByte(); // index level 1.0 or 0xFF - byte quantity1 = br.ReadByte(); // count - byte quantity2 = br.ReadByte(); // count - byte objectName2 = br.ReadByte(); // level 2.0 - byte indexName2 = br.ReadByte(); // index level 2.0 or 0xFF - byte shape = br.ReadByte(); // shape reflect % 4, 0 none, 1 vertical, 2 horizontal, 3 any - byte generalObject = br.ReadByte(); // zero or object - ushort indexAddon = br.ReadUInt16(); // zero or index addons_t - uint uniqNumber1 = br.ReadUInt32(); // level 1.0 - uint uniqNumber2 = br.ReadUInt32(); // level 2.0 - - byte[] unknown = br.ReadBytes(5); - // 259229 - return tile; - - ushort indexAddonN = br.ReadUInt16(); // zero or next addons_t - byte objectNameN1 = br.ReadByte(); // level 1.N - byte indexNameN1 = br.ReadByte(); // level 1.N or 0xFF - byte quantityN = br.ReadByte(); // - byte objectNameN2 = br.ReadByte(); // level 2.N - byte indexNameN2 = br.ReadByte(); // level 1.N or 0xFF - uint uniqNumberN1 = br.ReadUInt32(); // level 1.N - uint uniqNumberN2 = br.ReadUInt32(); // level 2.N - - return tile; - } - - private MapCastle ReadCastle(IO.Reader br) - { - MapCastle castle = new MapCastle(); - - ushort signal = br.ReadUInt16(); - - castle.Color = (MapCastleColor)br.ReadByte(); - castle.HasCustomBuilding = br.ReadBoolean(); - castle.Buildings = (MapBuildingType)br.ReadUInt16(); - castle.Dwellings = (MapDwellingType)br.ReadUInt16(); - castle.MageGuildLevel = (MapMageGuildLevel)br.ReadByte(); - castle.HasCustomTroops = br.ReadBoolean(); - - for (int i = 0; i < 5; i++) + int findobject = -1; + for (int it_index = 0; it_index < map.Tiles.Count && findobject < 0; ++it_index) { - castle.Monsters[i] = new MapArmyMonster(); - castle.Monsters[i].MonsterType = (MapMonsterType)br.ReadByte(); - } - for (int i = 0; i < 5; i++) - { - castle.Monsters[i].Amount = br.ReadUInt16(); + MapTile tile = map.Tiles[it_index]; + + // orders(quantity2, quantity1) + int orders = tile.Quantity2; // (tile.GetQuantity2() ? tile.GetQuantity2() : 0); + orders <<= 8; + orders |= tile.Quantity1; // tile.GetQuantity1(); + + if ((orders != 0) && !((orders % 0x08) != 0) && (i + 1 == orders / 0x08)) + findobject = it_index; } + if (findobject == -1) + return null; - castle.HasCaptain = br.ReadBoolean(); - castle.HasCustomName = br.ReadBoolean(); - castle.Name = br.ReadFixedLengthString(13); - castle.Name = castle.Name.TrimNull(); - castle.Type = (MapCastleType)br.ReadByte(); - castle.IsCastle = br.ReadBoolean(); - castle.IsUpgradable = br.ReadBoolean(); // 00 TRUE, 01 FALSE - - byte[] unknown = br.ReadBytes(29); - - return castle; + return map.Tiles[findobject]; } protected override void SaveInternal(ObjectModel objectModel) diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/MonsterFragment.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/MonsterFragment.cs new file mode 100644 index 00000000..abbb66f4 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/MonsterFragment.cs @@ -0,0 +1,39 @@ +// +// MonsterFragment.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using UniversalEditor.IO; +using UniversalEditor.ObjectModels.NewWorldComputing.Map; + +namespace UniversalEditor.DataFormats.NewWorldComputing.WorldMap2D.NewWorldComputing.Heroes2 +{ + public class MonsterFragment : DataFormatFragment + { + protected override MapArmyMonster ReadInternal(Reader reader) + { + MapArmyMonster item = null; //new MapArmyMonster(); + return item; + } + protected override void WriteInternal(Writer writer, MapArmyMonster value) + { + throw new NotImplementedException(); + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/TileFragment.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/TileFragment.cs new file mode 100644 index 00000000..b5d3b4ce --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes2/TileFragment.cs @@ -0,0 +1,62 @@ +// +// TileFragment.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using UniversalEditor.IO; +using UniversalEditor.ObjectModels.NewWorldComputing.Map; + +namespace UniversalEditor.DataFormats.NewWorldComputing.WorldMap2D.NewWorldComputing.Heroes2 +{ + public class TileFragment : DataFormatFragment + { + protected override MapTile ReadInternal(Reader reader) + { + MapTile tile = new MapTile(); + tile.GroundType = (MapGroundType)reader.ReadUInt16(); // tile (ocean, grass, snow, swamp, lava, desert, dirt, wasteland, beach) + tile.ObjectName1 = reader.ReadByte(); // level 1.0 + tile.IndexName1 = reader.ReadByte(); // index level 1.0 or 0xFF + tile.Quantity1 = reader.ReadByte(); // count + tile.Quantity2 = reader.ReadByte(); // count + tile.ObjectName2 = reader.ReadByte(); // level 2.0 + tile.IndexName2 = reader.ReadByte(); // index level 2.0 or 0xFF + tile.Shape = reader.ReadByte(); // shape reflect % 4, 0 none, 1 vertical, 2 horizontal, 3 any + tile.GeneralObject = reader.ReadByte(); // zero or object + tile.IndexAddon = reader.ReadUInt16(); // zero or index addons_t + tile.UniqNumber1 = reader.ReadUInt32(); // level 1.0 + tile.UniqNumber2 = reader.ReadUInt32(); // level 2.0 + return tile; + } + protected override void WriteInternal(Writer writer, MapTile value) + { + writer.WriteUInt16((ushort)value.GroundType); + writer.WriteByte(value.ObjectName1); + writer.WriteByte(value.IndexName1); + writer.WriteByte(value.Quantity1); + writer.WriteByte(value.Quantity2); + writer.WriteByte(value.ObjectName2); + writer.WriteByte(value.IndexName2); + writer.WriteByte(value.Shape); + writer.WriteByte(value.GeneralObject); + writer.WriteUInt16(value.IndexAddon); + writer.WriteUInt32(value.UniqNumber1); + writer.WriteUInt32(value.UniqNumber2); + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes3/Heroes3GameType.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes3/Heroes3GameType.cs index cf0a7ad3..0e14604b 100644 --- a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes3/Heroes3GameType.cs +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes3/Heroes3GameType.cs @@ -19,7 +19,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -namespace UniversalEditor.DataFormats.Gaming.WorldMap2D.NewWorldComputing.Heroes3 +namespace UniversalEditor.DataFormats.NewWorldComputing.WorldMap2D.NewWorldComputing.Heroes3 { /// /// Indicates the game campaign type supported by a Heroes of Might and Magic III game map. diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes3/Heroes3MapDataFormat.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes3/Heroes3MapDataFormat.cs index c2b3dfa1..e25186f3 100644 --- a/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes3/Heroes3MapDataFormat.cs +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/DataFormats/NewWorldComputing/WorldMap2D/NewWorldComputing/Heroes3/Heroes3MapDataFormat.cs @@ -22,7 +22,7 @@ using UniversalEditor.Accessors; using UniversalEditor.ObjectModels.NewWorldComputing.Map; -namespace UniversalEditor.DataFormats.Gaming.WorldMap2D.NewWorldComputing.Heroes3 +namespace UniversalEditor.DataFormats.NewWorldComputing.WorldMap2D.NewWorldComputing.Heroes3 { /// /// Provides a for manipulating Heroes of Might and Magic III map files. diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/HeroSkill.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/HeroSkill.cs new file mode 100644 index 00000000..e9f6f9f8 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/HeroSkill.cs @@ -0,0 +1,41 @@ +// +// HeroSkill.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace UniversalEditor.ObjectModels.NewWorldComputing +{ + public class HeroSkill + { + public class HeroSkillCollection + : System.Collections.ObjectModel.Collection + { + + } + + public HeroSkillType Type { get; set; } + public HeroSkillLevel Level { get; set; } = HeroSkillLevel.Basic; + + public HeroSkill(HeroSkillType type, HeroSkillLevel level) + { + Type = type; + Level = level; + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/HeroSkillLevel.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/HeroSkillLevel.cs new file mode 100644 index 00000000..63b9e211 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/HeroSkillLevel.cs @@ -0,0 +1,30 @@ +// +// HeroSkillLevel.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace UniversalEditor.ObjectModels.NewWorldComputing +{ + public enum HeroSkillLevel + { + Basic = 1, + Advanced = 2, + Expert = 3 + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/HeroSkillType.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/HeroSkillType.cs new file mode 100644 index 00000000..af37d76e --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/HeroSkillType.cs @@ -0,0 +1,28 @@ +// +// HeroSkillType.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace UniversalEditor.ObjectModels.NewWorldComputing +{ + public enum HeroSkillType + { + Unknown = 255 + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapArmyMonster.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapArmyMonster.cs index d7975f46..f405a900 100644 --- a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapArmyMonster.cs +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapArmyMonster.cs @@ -24,9 +24,21 @@ namespace UniversalEditor.ObjectModels.NewWorldComputing.Map /// /// Represents an army monster placed on a Heroes of Might and Magic map. /// - public class MapArmyMonster + public class MapArmyMonster : MapItem { + public class MapArmyMonsterCollection + : System.Collections.ObjectModel.Collection + { + + } + public ushort Amount { get; set; } = 0; public MapMonsterType MonsterType { get; set; } = MapMonsterType.Unknown; - } + + public MapArmyMonster(MapMonsterType monsterType, ushort amount) + { + MonsterType = monsterType; + Amount = amount; + } + } } diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapArtifact.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapArtifact.cs new file mode 100644 index 00000000..e7242239 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapArtifact.cs @@ -0,0 +1,39 @@ +// +// MapArtifact.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace UniversalEditor.ObjectModels.NewWorldComputing.Map +{ + public class MapArtifact : MapItem + { + public class MapArtifactCollection + : System.Collections.ObjectModel.Collection + { + + } + + public MapArtifactType Type { get; set; } = MapArtifactType.Unknown; + + public MapArtifact(MapArtifactType type) + { + Type = type; + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapArtifactType.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapArtifactType.cs new file mode 100644 index 00000000..1551eb56 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapArtifactType.cs @@ -0,0 +1,28 @@ +// +// MapArtifactType.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace UniversalEditor.ObjectModels.NewWorldComputing.Map +{ + public enum MapArtifactType : byte + { + Unknown = 255 + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapCastle.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapCastle.cs index e9c357ab..12d42b2b 100644 --- a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapCastle.cs +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapCastle.cs @@ -26,7 +26,7 @@ namespace UniversalEditor.ObjectModels.NewWorldComputing.Map /// /// Defines characteristics related to a castle placed on a map. /// - public class MapCastle + public class MapCastle : MapItem { private MapCastleColor mvarColor = MapCastleColor.Unknown; public MapCastleColor Color { get { return mvarColor; } set { mvarColor = value; } } diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapCastleType.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapCastleType.cs index 3d3a01eb..76e545e4 100644 --- a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapCastleType.cs +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapCastleType.cs @@ -26,12 +26,14 @@ namespace UniversalEditor.ObjectModels.NewWorldComputing.Map /// public enum MapCastleType : byte { + Unknown = 0xFF, Knight = 0, Barbarian = 1, Sorceress = 2, Warlock = 3, Wizard = 4, Necroman = 5, - Unknown = 6 + Multiple = 6, + Random = 7 } } diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapEvent.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapEvent.cs new file mode 100644 index 00000000..5b94513a --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapEvent.cs @@ -0,0 +1,100 @@ +// +// MapEvent.cs - represents an event which occurs on the map +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using System; + +namespace UniversalEditor.ObjectModels.NewWorldComputing.Map +{ + public class MapEvent + { + public class MapEventCollection + : System.Collections.ObjectModel.Collection + { + + } + + // resource counts + /// + /// Gets or sets the amount of Wood resource that should be given to or taken from the player. + /// + /// The amount of Wood resource that should be given to or taken from the player. + public int AmountWood { get; set; } = 0; + // resource counts + /// + /// Gets or sets the amount of Mercury resource that should be given to or taken from the player. + /// + /// The amount of Mercury resource that should be given to or taken from the player. + public int AmountMercury { get; set; } = 0; + // resource counts + /// + /// Gets or sets the amount of Ore resource that should be given to or taken from the player. + /// + /// The amount of Ore resource that should be given to or taken from the player. + public int AmountOre { get; set; } = 0; + // resource counts + /// + /// Gets or sets the amount of Sulfur resource that should be given to or taken from the player. + /// + /// The amount of Sulfur resource that should be given to or taken from the player. + public int AmountSulfur { get; set; } = 0; + // resource counts + /// + /// Gets or sets the amount of Crystal resource that should be given to or taken from the player. + /// + /// The amount of Crystal resource that should be given to or taken from the player. + public int AmountCrystal { get; set; } = 0; + // resource counts + /// + /// Gets or sets the amount of Gems resource that should be given to or taken from the player. + /// + /// The amount of Gems resource that should be given to or taken from the player. + public int AmountGems { get; set; } = 0; + // resource counts + /// + /// Gets or sets the amount of Gold resource that should be given to or taken from the player. + /// + /// The amount of Gold resource that should be given to or taken from the player. + public int AmountGold { get; set; } = 0; + + /// + /// Gets or sets a value indicating whether this is available to be triggered by a non-player (i.e., computer) character. + /// + /// true if computer players are allowed to trigger the event; otherwise, false. + public bool AllowComputer { get; set; } = false; + /// + /// Gets or sets a value indicating whether this triggers only once. + /// + /// true if this triggers only once; otherwise, false. + public bool SingleVisit { get; set; } = false; + + /// + /// Gets or sets a mask indicating the kingdom alliances which are allowed to trigger this event. + /// + /// The kingdom alliances which are allowed to trigger this event. + public MapKingdomColor AllowedKingdoms { get; set; } = MapKingdomColor.All; + + /// + /// Gets or sets the message displayed to the player upon triggering this event. + /// + /// The message displayed to the player upon triggering this event. + public string Message { get; set; } = null; + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapHero.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapHero.cs new file mode 100644 index 00000000..e51e115b --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapHero.cs @@ -0,0 +1,45 @@ +// +// MapHero.cs - represents a hero on a map +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +namespace UniversalEditor.ObjectModels.NewWorldComputing.Map +{ + public class MapHero : MapItem + { + public bool HasCustomTroops { get; set; } = false; + + public bool HasCustomName { get; set; } = false; + public string Name { get; set; } = null; + + public MapArmyMonster.MapArmyMonsterCollection Monsters { get; } = new MapArmyMonster.MapArmyMonsterCollection(); + public MapArtifact.MapArtifactCollection Artifacts { get; } = new MapArtifact.MapArtifactCollection(); + + public bool HasCustomSkills { get; set; } = false; + public HeroSkill.HeroSkillCollection Skills { get; } = new HeroSkill.HeroSkillCollection(); + + public bool HasCustomPortrait { get; set; } + public byte CustomPortraitIndex { get; set; } + + public uint Experience { get; set; } + + public bool Patrol { get; set; } = false; + public byte PatrolSquareCount { get; set; } = 0; + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapItem.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapItem.cs new file mode 100644 index 00000000..81c85277 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapItem.cs @@ -0,0 +1,33 @@ +// +// MapItem.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace UniversalEditor.ObjectModels.NewWorldComputing.Map +{ + public abstract class MapItem + { + public class MapItemCollection + : System.Collections.ObjectModel.Collection + { + + } + + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapItemType.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapItemType.cs new file mode 100644 index 00000000..3328be5d --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapItemType.cs @@ -0,0 +1,32 @@ +// +// MapItemType.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace UniversalEditor.ObjectModels.NewWorldComputing.Map +{ + public enum MapItemType + { + Monster = 0x16, + Castle = 0x46, + Hero = 0x4C, + + Unknown1 = 0xC3 + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapObjectModel.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapObjectModel.cs index d9c573b0..8c21f29a 100644 --- a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapObjectModel.cs +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapObjectModel.cs @@ -64,6 +64,9 @@ namespace UniversalEditor.ObjectModels.NewWorldComputing.Map /// The win conditions. public MapWinCondition WinConditions { get; set; } = MapWinCondition.None; + public MapWinCondition ComputerAlsoWins { get; set; } = MapWinCondition.None; + public bool AllowNormalVictory { get; set; } = false; + /// /// Indicates the condition(s) required to lose a game using this map. /// @@ -74,5 +77,8 @@ namespace UniversalEditor.ObjectModels.NewWorldComputing.Map public string Description { get; set; } = String.Empty; public MapTile.MapTileCollection Tiles { get; } = new MapTile.MapTileCollection(); + public MapItem.MapItemCollection Items { get; } = new MapItem.MapItemCollection(); + + public byte ObeliskCount { get; set; } = 0; } } diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapResourceType.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapResourceType.cs new file mode 100644 index 00000000..c08b4d77 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapResourceType.cs @@ -0,0 +1,39 @@ +// +// MapResourceType.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace UniversalEditor.ObjectModels.NewWorldComputing.Map +{ + public enum MapResourceType + { + Wood = 0x00, + Mercury, + Ore, + Sulfur, + Crystal, + Gems, + Gold, + + Lighthouse = 0x64, + DragonCity = 0x65, + + AbandonedMine = 0x67 + } +} diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapTile.cs b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapTile.cs index b8e647ce..b54f0a47 100644 --- a/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapTile.cs +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/ObjectModels/NewWorldComputing/Map/MapTile.cs @@ -36,5 +36,16 @@ namespace UniversalEditor.ObjectModels.NewWorldComputing.Map /// /// The type of the ground. public MapGroundType GroundType { get; set; } = MapGroundType.Unknown; - } + public byte ObjectName1 { get; set; } + public byte IndexName1 { get; set; } + public byte Quantity1 { get; set; } + public byte Quantity2 { get; set; } + public byte ObjectName2 { get; set; } + public byte IndexName2 { get; set; } + public byte Shape { get; set; } + public byte GeneralObject { get; set; } + public ushort IndexAddon { get; set; } + public uint UniqNumber1 { get; set; } + public uint UniqNumber2 { get; set; } + } } diff --git a/Plugins/UniversalEditor.Plugins.NewWorldComputing/UniversalEditor.Plugins.NewWorldComputing.csproj b/Plugins/UniversalEditor.Plugins.NewWorldComputing/UniversalEditor.Plugins.NewWorldComputing.csproj index ad288368..ca45878d 100644 --- a/Plugins/UniversalEditor.Plugins.NewWorldComputing/UniversalEditor.Plugins.NewWorldComputing.csproj +++ b/Plugins/UniversalEditor.Plugins.NewWorldComputing/UniversalEditor.Plugins.NewWorldComputing.csproj @@ -85,6 +85,25 @@ + + + + + + + + + + + + + + + + + + + @@ -126,6 +145,8 @@ + +