Tools:
This project is going to be built with Unity since I have a lot of experience working with it. It will make long-term maintenance a pain (annual upgrades), but it shouldn't take more than a few hours each year to update. It will be very important not to let the project rot to the point of being unsalvagable.
The editor's missions will work exclusively with the C# Mission SDK through the use of its JSON data files. There will be an extra feature to export the MAP portion through OP2 Utility, but for the most part, data will be saved in JSON. For devs that prefer to work in C++, don't forget you can link to the C# SDK and continue working in C++.
Feature Specification:
--------
Menu bar
--------
File:
New
Open...
Import Map...
Save
Save As...
Export Map...
Exit
Edit:
Map Properties
Mission Properties
Player Properties
--------------
Map Properties
--------------
Width
Height
------------------
Mission Properties
------------------
Description
MapName
TechTreeName
MissionType (DropDown)
MaxTechLevel (DropDown)
UnitOnlyMission (Checkbox)
DaylightEverywhere (Checkbox)
DaylightMoves (Require DaylightEverywhere=false, Checkbox)
InitialLightLevel (int inputfield)
Music Playlist
Scroll list of tracks
Add track (dropdown)
Remove track
Move up/down
Repeat start index
-----------------
Player Properties
-----------------
Scroll list of players
Add Player
Remove Player
TechLevel
MoraleLevel
FreeMorale
ColonyType (dropdown: Eden, Plymouth)
IsHuman (checkbox)
BotType (dropdown)
Color (dropdown)
Allies: Togglable scroll list of players
Center View X
Center View Y
Kids
Workers
Scientists
CommonOre
RareOre
Food
SolarSatellites
Scroll list of completed research
Add topic (dropdown: Data pulled from tech file)
Remove topic
----------
Paint Pane
----------
Dropdown (Terrain, CellTypes, Resources, Walls and Tubes, Disasters, Units, Structures, Locations)
Terrain:
Tiles (Extract BMP)
CellTypes:
CellType (dropdown)
Resources:
Prebaked Icon
Common Mining Beacon
Rare Mining Beacon
- Yield (dropdown)
- Variant (dropdown)
- *Spawn Area (width/height)
Fumarole
- *Spawn Area
Magma Vent
- *Spawn Area
Circle Marker
DNA Marker
- *Spawn Area
Wreckage:
- Type (dropdown: spaceship parts)
- IsVisible (checkbox)
- *Spawn Area
Walls and Tubes:
Prebaked Icon
Tube
Wall
Lava Wall
Microbe Wall
Disasters:
DisasterType (dropdown)
*SrcArea
*DestArea
Size
Duration
StartTime
EndTime
MinDelay
MaxDelay
(If disaster has both src and dest areas, must place both for disaster area to appear)
--NOTE--
*Areas are painted by clicking and dragging to create the size
Units/Structures:
Colony (dropdown: Eden, Plymouth)
Prebaked Icon
Direction
CargoType (dropdown: Convec=StructureKit, Truck=TruckCargo) Must be convec or truck
CargoAmount (int inputfield, cargo truck only)
Locations: (Used for triggers)
ID (alphanumeric?)
*Spawn Area
--------
Triggers
--------
TBD
-------------------
AI Base Preplanning
-------------------
TBD
Please let me know if you have any feature requests or changes you would like to see, and also if you see any problems with the current list.
I finally have some time to work on this again.
I now cache a minimap tileset texture along with the regular one when they are first loaded, so that has been optimized. Thanks for the idea, Leeor!
Also removed unnecessary tile refresh which was already happening during SetTiles, and added a progress bar for importing.
Still can't get resourceManager working:
extern EXPORT unsigned __int64 __stdcall ResourceManager_GetResourceSize(const char* archiveDirectory, const char* filename, bool accessArchives)
{
ofstream outputFile;
outputFile.open("quicklog.txt");
outputFile << "archiveDirectory = " << archiveDirectory << "\n";
outputFile << "filename = " << filename << "\n";
if (accessArchives)
outputFile << "accessArchives = true\n";
else
outputFile << "accessArchives = false\n";
outputFile.close();
ResourceManager resourceManager(archiveDirectory);
std::unique_ptr<Stream::BidirectionalReader> stream = resourceManager.GetResourceStream(filename, accessArchives);
if (stream == nullptr)
{
ofstream outputFile;
outputFile.open("quicklog2.txt");
outputFile << "hit 0";
return 0;
}
return stream->Length();
}
Prints out:
archiveDirectory = E:/Business/Freelance/Projects/Outpost2/Outpost2exe
filename = well0008.bmp
accessArchives = true
...and stream is null.
Tried different archive directories - with/without trailing slash, forward vs back slashes... Can't get it to work.
Will probably have to debug the utility itself to figure this one out.
I looked into this. From cursory examination, there may be a bug when the archiveDirectory does not match the current working directory. In that case, when scanning the resource folder for .vol and .clm files, all non-existent files (using the current working directory, not the resource folder) are filtered out of the search results. This causes the archives to not be seen and loaded. That would result in no packed files being found and nullptr being returned for the stream.
Edit: To debug, consider using GetArchiveFilenames to see if any archives are loaded.
Despite my earlier comment, I'm not sure a trailing slash is actually needed. For reference though, I would have used the path:
E:/Business/Freelance/Projects/Outpost2/Outpost2exe/
The trailing slash makes the name unambiguously a directory name.
The editor was built against the old OPU release. Seems to work fine on there.
I'm not clear on why GOG is different.
Logs say that well0000.bmp is found in the GOG directory.
2120 bytes are loaded.
The BMP library then tries to parse the BMP data, but immediately runs into an issue:
The first two bytes (header) does not match an expected BMP format:
Read: 16976
Expected: 19778
It then rejects parsing, and later code throws an exception when it tries to use the missing texture.
If I try to skip the header, it just fails later:
Unsupported image format: 524288
The GOG format must be different. Perhaps it is compressed and OPU was not? What was different about OPU?
EDIT:
I used the editor to extract well0000.bmp to a file and it can't be viewed (GOG version. OPU-OK). Further investigation shows that this file is stored in different .vol archives. OPU had it in art.vol at size 2102, while GOG has it in maps.vol at 2120. Both are marked as uncompressed. I'm not sure what is going on here.
I have this working and will submit a fixed version soon, but I have a question about OP2Utility.
// Read tileset represented by Outpost 2 specific format into memory
// After Reading into memory, reformats into standard 8 bit indexed bitmap before returning results
BitmapFile ReadCustomTileset(Stream::Reader& reader);
This seems to imply that the resulting BitmapFile will be in a standard format.
I used this and then wrote the data back out to a byte array to pass to a third-party library.
While the image would load, it was upside-down due to inverted scan lines.
I see some other manipulation in that function, notably bitmapFile.SwapRedAndBlue(), but it does not call bitmapFile.InvertScanLines()
So the question is: Are inverted scan lines considered "standard format"?
It seems strange to me that I have to check for inverted scan lines before writing out a standard bmp, but it could be a deficiency in the library I'm using.
The output looks correct through Windows viewer. The other lib just doesn't invert when the height is negative, so I will just need to check for this.
GOG works correctly. All unit tests are passing.
I am having an issue with BitmapFile.ReadIndexed on OPU 1.3.7 for well0001.bmp in art.vol.
The size of pixels does not match the image's height time pitch.
If I remove the exception, the image loads fine.
These are the passed in parameters:
VerifyPixelSizeMatchesImageDimensionsWithPitch(bitCount = 8, width = 32, height = 8608, pixelsWithPitchSize = 275458)
The first three parameters look correct based on the file property dialog in file explorer. I am not sure how to verify the last one.
I'm curious if this affects OP2Utility C++. The ported code looks to be identical for this function.
EDIT:
I studied the bitmap format a bit. This looks like a case where the BMP file is not formatted to spec. Windows/OP2 ignore this as there is enough information to correctly parse the file.
The BMP pixel container size is 2 bytes more than what it should be. It has two extra bytes of padding at the end that put it out of the 4-byte alignment specification. It is awkward, but it appears this just gets trimmed by most apps/libraries for rendering since the width/height properties will not use the full container.
For OP2UtilityDotNet, I am going to change the exception to only throw when the file's container size is too small for the width/height/bitCount. If there is extra fat at the end, it will pass validation. This appears to work successfully.
It may be worth considering doing this for OP2Utility C++ as well.
Commit for this change:
Fix for bmp files with excess padding. (https://github.com/TechCor8/OP2UtilityDotNet/commit/d6651f666acbcdaa5f35d2320310ae3cdeb7da2b)