Compare commits
No commits in common. "master" and "v1.5.3" have entirely different histories.
32 changed files with 996 additions and 277 deletions
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -22,6 +22,10 @@
|
||||||
path = third-party/libzip
|
path = third-party/libzip
|
||||||
url = https://github.com/nih-at/libzip
|
url = https://github.com/nih-at/libzip
|
||||||
branch = main
|
branch = main
|
||||||
|
[submodule "efsw"]
|
||||||
|
path = third-party/efsw
|
||||||
|
url = https://github.com/SpartanJ/efsw
|
||||||
|
branch = master
|
||||||
[submodule "libcurl"]
|
[submodule "libcurl"]
|
||||||
path = third-party/curl
|
path = third-party/curl
|
||||||
url = https://github.com/curl/curl
|
url = https://github.com/curl/curl
|
||||||
|
|
|
@ -27,6 +27,7 @@ include(CMakeDependentOption)
|
||||||
cmake_dependent_option(SAVETOOL_USE_SYSTEM_CORRADE_MAGNUM "Use system-wide versions of Corrade and Magnum." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
cmake_dependent_option(SAVETOOL_USE_SYSTEM_CORRADE_MAGNUM "Use system-wide versions of Corrade and Magnum." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
||||||
cmake_dependent_option(SAVETOOL_USE_SYSTEM_SDL2 "Use a system-wide version of SDL2." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
cmake_dependent_option(SAVETOOL_USE_SYSTEM_SDL2 "Use a system-wide version of SDL2." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
||||||
cmake_dependent_option(SAVETOOL_USE_SYSTEM_LIBZIP "Use a system-wide version of libzip." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
cmake_dependent_option(SAVETOOL_USE_SYSTEM_LIBZIP "Use a system-wide version of libzip." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
||||||
|
cmake_dependent_option(SAVETOOL_USE_SYSTEM_EFSW "Use a system-wide version of EFSW." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
||||||
cmake_dependent_option(SAVETOOL_USE_SYSTEM_LIBCURL "Use a system-wide version of libcurl." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
cmake_dependent_option(SAVETOOL_USE_SYSTEM_LIBCURL "Use a system-wide version of libcurl." ON "SAVETOOL_USE_SYSTEM_LIBS" OFF)
|
||||||
|
|
||||||
if(NOT SAVETOOL_USE_SYSTEM_LIBS OR NOT (SAVETOOL_USE_SYSTEM_CORRADE_MAGNUM AND SAVETOOL_USE_SYSTEM_SDL2 AND SAVETOOL_USE_SYSTEM_LIBZIP AND SAVETOOL_USE_SYSTEM_EFSW AND SAVETOOL_USE_SYSTEM_LIBCURL))
|
if(NOT SAVETOOL_USE_SYSTEM_LIBS OR NOT (SAVETOOL_USE_SYSTEM_CORRADE_MAGNUM AND SAVETOOL_USE_SYSTEM_SDL2 AND SAVETOOL_USE_SYSTEM_LIBZIP AND SAVETOOL_USE_SYSTEM_EFSW AND SAVETOOL_USE_SYSTEM_LIBCURL))
|
||||||
|
@ -113,6 +114,13 @@ if(NOT SAVETOOL_USE_SYSTEM_LIBZIP)
|
||||||
add_subdirectory(third-party/libzip EXCLUDE_FROM_ALL)
|
add_subdirectory(third-party/libzip EXCLUDE_FROM_ALL)
|
||||||
endif(NOT SAVETOOL_USE_SYSTEM_LIBZIP)
|
endif(NOT SAVETOOL_USE_SYSTEM_LIBZIP)
|
||||||
|
|
||||||
|
if(NOT SAVETOOL_USE_SYSTEM_EFSW)
|
||||||
|
set(VERBOSE OFF CACHE BOOL "" FORCE)
|
||||||
|
set(BUILD_TEST_APP OFF CACHE BOOL "" FORCE)
|
||||||
|
set(EFSW_INSTALL OFF CACHE BOOL "" FORCE)
|
||||||
|
add_subdirectory(third-party/efsw EXCLUDE_FROM_ALL)
|
||||||
|
endif(NOT SAVETOOL_USE_SYSTEM_EFSW)
|
||||||
|
|
||||||
if(NOT SAVETOOL_USE_SYSTEM_LIBCURL)
|
if(NOT SAVETOOL_USE_SYSTEM_LIBCURL)
|
||||||
set(BUILD_CURL_EXE OFF CACHE BOOL "" FORCE)
|
set(BUILD_CURL_EXE OFF CACHE BOOL "" FORCE)
|
||||||
set(ENABLE_UNICODE ON CACHE BOOL "" FORCE)
|
set(ENABLE_UNICODE ON CACHE BOOL "" FORCE)
|
||||||
|
|
|
@ -92,6 +92,7 @@ Application::Application(const Arguments& arguments):
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateEventId = _initEventId + 1;
|
_updateEventId = _initEventId + 1;
|
||||||
|
_fileEventId = _initEventId + 2;
|
||||||
|
|
||||||
LOG_INFO("Initialising the timer subsystem.");
|
LOG_INFO("Initialising the timer subsystem.");
|
||||||
if(SDL_InitSubSystem(SDL_INIT_TIMER) != 0) {
|
if(SDL_InitSubSystem(SDL_INIT_TIMER) != 0) {
|
||||||
|
@ -190,23 +191,23 @@ Application::keyReleaseEvent(KeyEvent& event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Application::pointerPressEvent(PointerEvent& event) {
|
Application::mousePressEvent(MouseEvent& event) {
|
||||||
if(_imgui.handlePointerPressEvent(event)) return;
|
if(_imgui.handleMousePressEvent(event)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Application::pointerReleaseEvent(PointerEvent& event) {
|
Application::mouseReleaseEvent(MouseEvent& event) {
|
||||||
if(_imgui.handlePointerReleaseEvent(event)) return;
|
if(_imgui.handleMouseReleaseEvent(event)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Application::pointerMoveEvent(PointerMoveEvent& event) {
|
Application::mouseMoveEvent(MouseMoveEvent& event) {
|
||||||
if(_imgui.handlePointerMoveEvent(event)) return;
|
if(_imgui.handleMouseMoveEvent(event)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Application::scrollEvent(ScrollEvent& event) {
|
Application::mouseScrollEvent(MouseScrollEvent& event) {
|
||||||
if(_imgui.handleScrollEvent(event)) {
|
if(_imgui.handleMouseScrollEvent(event)) {
|
||||||
event.setAccepted();
|
event.setAccepted();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -225,6 +226,9 @@ Application::anyEvent(SDL_Event& event) {
|
||||||
else if(event.type == _updateEventId) {
|
else if(event.type == _updateEventId) {
|
||||||
updateCheckEvent(event);
|
updateCheckEvent(event);
|
||||||
}
|
}
|
||||||
|
else if(event.type == _fileEventId) {
|
||||||
|
fileUpdateEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <Corrade/Containers/Pointer.h>
|
#include <Corrade/Containers/Pointer.h>
|
||||||
|
@ -34,6 +35,8 @@
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include <efsw/efsw.hpp>
|
||||||
|
|
||||||
#include "../Managers/BackupManager.h"
|
#include "../Managers/BackupManager.h"
|
||||||
#include "../Managers/MassManager.h"
|
#include "../Managers/MassManager.h"
|
||||||
#include "../Managers/ProfileManager.h"
|
#include "../Managers/ProfileManager.h"
|
||||||
|
@ -51,11 +54,17 @@ using namespace Magnum;
|
||||||
|
|
||||||
namespace mbst {
|
namespace mbst {
|
||||||
|
|
||||||
class Application: public Platform::Sdl2Application {
|
class Application: public Platform::Sdl2Application, public efsw::FileWatchListener {
|
||||||
public:
|
public:
|
||||||
explicit Application(const Arguments& arguments);
|
explicit Application(const Arguments& arguments);
|
||||||
|
|
||||||
virtual ~Application();
|
~Application() override;
|
||||||
|
|
||||||
|
void handleFileAction(efsw::WatchID watch_id,
|
||||||
|
const std::string& dir,
|
||||||
|
const std::string& filename,
|
||||||
|
efsw::Action action,
|
||||||
|
std::string old_filename) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Events
|
// Events
|
||||||
|
@ -65,10 +74,10 @@ class Application: public Platform::Sdl2Application {
|
||||||
void keyPressEvent(KeyEvent& event) override;
|
void keyPressEvent(KeyEvent& event) override;
|
||||||
void keyReleaseEvent(KeyEvent& event) override;
|
void keyReleaseEvent(KeyEvent& event) override;
|
||||||
|
|
||||||
void pointerPressEvent(PointerEvent& event) override;
|
void mousePressEvent(MouseEvent& event) override;
|
||||||
void pointerReleaseEvent(PointerEvent& event) override;
|
void mouseReleaseEvent(MouseEvent& event) override;
|
||||||
void pointerMoveEvent(PointerMoveEvent& event) override;
|
void mouseMoveEvent(MouseMoveEvent& event) override;
|
||||||
void scrollEvent(ScrollEvent& event) override;
|
void mouseScrollEvent(MouseScrollEvent& event) override;
|
||||||
void textInputEvent(TextInputEvent& event) override;
|
void textInputEvent(TextInputEvent& event) override;
|
||||||
|
|
||||||
void anyEvent(SDL_Event& event) override;
|
void anyEvent(SDL_Event& event) override;
|
||||||
|
@ -81,11 +90,21 @@ class Application: public Platform::Sdl2Application {
|
||||||
|
|
||||||
void updateCheckEvent(SDL_Event& event);
|
void updateCheckEvent(SDL_Event& event);
|
||||||
|
|
||||||
|
enum FileEventType: std::int32_t {
|
||||||
|
FileAdded = efsw::Action::Add,
|
||||||
|
FileDeleted = efsw::Action::Delete,
|
||||||
|
FileModified = efsw::Action::Modified,
|
||||||
|
FileMoved = efsw::Action::Moved,
|
||||||
|
StagedUpdate = 1 << 3
|
||||||
|
};
|
||||||
|
void fileUpdateEvent(SDL_Event& event);
|
||||||
|
|
||||||
// Initialisation methods
|
// Initialisation methods
|
||||||
void initialiseConfiguration();
|
void initialiseConfiguration();
|
||||||
void initialiseGui();
|
void initialiseGui();
|
||||||
void initialiseManager();
|
void initialiseManager();
|
||||||
void initialiseMassManager();
|
void initialiseMassManager();
|
||||||
|
void initialiseFileWatcher();
|
||||||
|
|
||||||
// GUI-related methods
|
// GUI-related methods
|
||||||
void drawImGui();
|
void drawImGui();
|
||||||
|
@ -121,9 +140,9 @@ class Application: public Platform::Sdl2Application {
|
||||||
void drawBLAttachment();
|
void drawBLAttachment();
|
||||||
void drawCustomArmourStyles();
|
void drawCustomArmourStyles();
|
||||||
void drawWeapons();
|
void drawWeapons();
|
||||||
void drawWeaponCategory(Containers::StringView name, GameObjects::Weapon::Type category,
|
void drawWeaponCategory(Containers::StringView name, Containers::ArrayView<GameObjects::Weapon> weapons_view,
|
||||||
Containers::ArrayView<GameObjects::Weapon> weapons_view,
|
bool& dirty, Containers::StringView payload_type,
|
||||||
Containers::StringView payload_type, Containers::StringView payload_tooltip);
|
Containers::StringView payload_tooltip);
|
||||||
void drawWeaponEditor(GameObjects::Weapon& weapon);
|
void drawWeaponEditor(GameObjects::Weapon& weapon);
|
||||||
void drawGlobalStyles();
|
void drawGlobalStyles();
|
||||||
void drawTuning();
|
void drawTuning();
|
||||||
|
@ -167,7 +186,6 @@ class Application: public Platform::Sdl2Application {
|
||||||
|
|
||||||
template<typename Functor, typename... Args>
|
template<typename Functor, typename... Args>
|
||||||
bool drawUnsafeWidget(Functor func, Args... args) {
|
bool drawUnsafeWidget(Functor func, Args... args) {
|
||||||
static_assert(std::is_invocable_r_v<bool, Functor, Args...>);
|
|
||||||
GameState game_state = _gameState; // Copying the value to reduce the risk of a data race.
|
GameState game_state = _gameState; // Copying the value to reduce the risk of a data race.
|
||||||
ImGui::BeginDisabled(game_state != GameState::NotRunning);
|
ImGui::BeginDisabled(game_state != GameState::NotRunning);
|
||||||
bool result = func(std::forward<Args>(args)...);
|
bool result = func(std::forward<Args>(args)...);
|
||||||
|
@ -225,6 +243,7 @@ class Application: public Platform::Sdl2Application {
|
||||||
|
|
||||||
std::uint32_t _initEventId;
|
std::uint32_t _initEventId;
|
||||||
std::uint32_t _updateEventId;
|
std::uint32_t _updateEventId;
|
||||||
|
std::uint32_t _fileEventId;
|
||||||
|
|
||||||
Containers::String _lastError;
|
Containers::String _lastError;
|
||||||
|
|
||||||
|
@ -246,12 +265,26 @@ class Application: public Platform::Sdl2Application {
|
||||||
|
|
||||||
GameObjects::Weapon* _currentWeapon = nullptr;
|
GameObjects::Weapon* _currentWeapon = nullptr;
|
||||||
|
|
||||||
|
Containers::Pointer<efsw::FileWatcher> _fileWatcher;
|
||||||
|
enum watchID {
|
||||||
|
SaveDir = 0,
|
||||||
|
StagingDir = 1
|
||||||
|
};
|
||||||
|
Containers::StaticArray<2, efsw::WatchID> _watchIDs;
|
||||||
|
|
||||||
Containers::Optional<UpdateChecker> _checker{Containers::NullOpt};
|
Containers::Optional<UpdateChecker> _checker{Containers::NullOpt};
|
||||||
std::mutex _checkerMutex;
|
std::mutex _checkerMutex;
|
||||||
|
|
||||||
|
bool _modifiedBySaveTool = false;
|
||||||
bool _jointsDirty = false;
|
bool _jointsDirty = false;
|
||||||
bool _stylesDirty = false;
|
bool _stylesDirty = false;
|
||||||
bool _eyeFlareDirty = false;
|
bool _eyeFlareDirty = false;
|
||||||
|
bool _meleeDirty = false;
|
||||||
|
bool _shieldsDirty = false;
|
||||||
|
bool _bShootersDirty = false;
|
||||||
|
bool _eShootersDirty = false;
|
||||||
|
bool _bLaunchersDirty = false;
|
||||||
|
bool _eLaunchersDirty = false;
|
||||||
|
|
||||||
Containers::Optional<std::size_t> _selectedArmourSlot{Containers::NullOpt};
|
Containers::Optional<std::size_t> _selectedArmourSlot{Containers::NullOpt};
|
||||||
Containers::StaticArray<38, std::int32_t> _selectedArmourDecals{ValueInit};
|
Containers::StaticArray<38, std::int32_t> _selectedArmourDecals{ValueInit};
|
||||||
|
|
158
src/Application/Application_FileWatcher.cpp
Normal file
158
src/Application/Application_FileWatcher.cpp
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2024 Guillaume Jacquemin
|
||||||
|
//
|
||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <Corrade/Utility/Format.h>
|
||||||
|
#include <Corrade/Utility/String.h>
|
||||||
|
#include <Corrade/Utility/Unicode.h>
|
||||||
|
|
||||||
|
#include <SDL_events.h>
|
||||||
|
#include <SDL_messagebox.h>
|
||||||
|
|
||||||
|
#include <fileapi.h>
|
||||||
|
#include <handleapi.h>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
|
||||||
|
namespace mbst {
|
||||||
|
|
||||||
|
void
|
||||||
|
Application::handleFileAction(efsw::WatchID watch_id, const std::string&, const std::string& filename,
|
||||||
|
efsw::Action action, std::string old_filename)
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
SDL_zero(event);
|
||||||
|
event.type = _fileEventId;
|
||||||
|
|
||||||
|
event.user.data1 = Containers::String{Containers::AllocatedInit, filename.c_str()}.release();
|
||||||
|
|
||||||
|
if(watch_id == _watchIDs[StagingDir] && Utility::String::endsWith(filename, ".sav")) {
|
||||||
|
event.user.code = StagedUpdate | action;
|
||||||
|
SDL_PushEvent(&event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Utility::String::endsWith(filename, "Config.sav")) {
|
||||||
|
return;
|
||||||
|
} // TODO: actually do something when config files will finally be handled
|
||||||
|
|
||||||
|
if(!Utility::String::endsWith(filename, Utility::format("Profile{}.sav", _currentProfile->account()).data()) &&
|
||||||
|
filename.find("Unit") == std::string::npos)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.user.code = action;
|
||||||
|
if(action == efsw::Actions::Moved) {
|
||||||
|
event.user.data2 = Containers::String{Containers::AllocatedInit, old_filename.c_str()}.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_PushEvent(&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Application::fileUpdateEvent(SDL_Event& event) {
|
||||||
|
Containers::String filename{static_cast<char*>(event.user.data1),
|
||||||
|
std::strlen(static_cast<char*>(event.user.data1)), nullptr};
|
||||||
|
|
||||||
|
if((event.user.code & StagedUpdate) == StagedUpdate) {
|
||||||
|
_stagedMassManager->refreshMass(filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Containers::String old_filename;
|
||||||
|
|
||||||
|
std::int32_t index = 0;
|
||||||
|
std::int32_t old_index = 0;
|
||||||
|
bool is_current_profile = filename == _currentProfile->filename();
|
||||||
|
bool is_unit = filename.hasPrefix(_currentProfile->isDemo() ? "DemoUnit"_s : "Unit"_s);
|
||||||
|
if(is_unit) {
|
||||||
|
index = ((filename[_currentProfile->isDemo() ? 8 : 4] - 0x30) * 10) +
|
||||||
|
(filename[_currentProfile->isDemo() ? 9 : 5] - 0x30);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(event.user.code == FileMoved) {
|
||||||
|
old_filename = Containers::String{static_cast<char*>(event.user.data2),
|
||||||
|
std::strlen(static_cast<char*>(event.user.data2)), nullptr};
|
||||||
|
old_index = ((old_filename[_currentProfile->isDemo() ? 8 : 4] - 0x30) * 10) +
|
||||||
|
(old_filename[_currentProfile->isDemo() ? 9 : 5] - 0x30);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(event.user.code) {
|
||||||
|
case FileAdded:
|
||||||
|
if(is_unit) {
|
||||||
|
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||||
|
_massManager->refreshHangar(index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_currentMass->setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FileDeleted:
|
||||||
|
if(is_current_profile) {
|
||||||
|
_currentProfile = nullptr;
|
||||||
|
_uiState = UiState::ProfileManager;
|
||||||
|
if(!_profileManager->refreshProfiles()) {
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
||||||
|
_profileManager->lastError().data(), window());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(is_unit) {
|
||||||
|
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||||
|
_massManager->refreshHangar(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FileModified:
|
||||||
|
if(is_current_profile) {
|
||||||
|
_currentProfile->refreshValues();
|
||||||
|
}
|
||||||
|
else if(is_unit) {
|
||||||
|
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||||
|
_massManager->refreshHangar(index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(_modifiedBySaveTool && _currentMass->filename() == filename) {
|
||||||
|
auto handle = CreateFileW(Utility::Unicode::widen(Containers::StringView{filename}),
|
||||||
|
GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||||
|
if(handle && handle != INVALID_HANDLE_VALUE) {
|
||||||
|
CloseHandle(handle);
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_currentMass->setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FileMoved:
|
||||||
|
if(is_unit) {
|
||||||
|
if(old_filename.hasSuffix(".sav"_s)) {
|
||||||
|
_massManager->refreshHangar(index);
|
||||||
|
_massManager->refreshHangar(old_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_queue.addToast(Toast::Type::Warning, "Unknown file action type"_s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include <Magnum/Math/Time.h>
|
|
||||||
|
|
||||||
#include <SDL_events.h>
|
#include <SDL_events.h>
|
||||||
#include <SDL_messagebox.h>
|
#include <SDL_messagebox.h>
|
||||||
|
|
||||||
|
@ -54,8 +52,7 @@ Application::initialiseConfiguration() {
|
||||||
LOG_INFO("Reading configuration file.");
|
LOG_INFO("Reading configuration file.");
|
||||||
|
|
||||||
setSwapInterval(conf().swapInterval());
|
setSwapInterval(conf().swapInterval());
|
||||||
using namespace Math::Literals;
|
setMinimalLoopPeriod(0);
|
||||||
setMinimalLoopPeriod(0_nsec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -122,6 +119,8 @@ Application::initialiseManager() {
|
||||||
|
|
||||||
_backupManager.emplace();
|
_backupManager.emplace();
|
||||||
|
|
||||||
|
_stagedMassManager.emplace();
|
||||||
|
|
||||||
event.user.code = InitSuccess;
|
event.user.code = InitSuccess;
|
||||||
SDL_PushEvent(&event);
|
SDL_PushEvent(&event);
|
||||||
}
|
}
|
||||||
|
@ -130,8 +129,15 @@ void
|
||||||
Application::initialiseMassManager() {
|
Application::initialiseMassManager() {
|
||||||
LOG_INFO("Initialising the M.A.S.S. manager.");
|
LOG_INFO("Initialising the M.A.S.S. manager.");
|
||||||
_massManager.emplace(_currentProfile->account(), _currentProfile->isDemo());
|
_massManager.emplace(_currentProfile->account(), _currentProfile->isDemo());
|
||||||
LOG_INFO("Initialising the staged M.A.S.S. manager.");
|
}
|
||||||
_stagedMassManager.emplace();
|
|
||||||
|
void
|
||||||
|
Application::initialiseFileWatcher() {
|
||||||
|
LOG_INFO("Initialising the file watcher.");
|
||||||
|
_fileWatcher.emplace();
|
||||||
|
_watchIDs[SaveDir] = _fileWatcher->addWatch(conf().directories().gameSaves, this, false);
|
||||||
|
_watchIDs[StagingDir] = _fileWatcher->addWatch(conf().directories().staging, this, false);
|
||||||
|
_fileWatcher->watch();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,20 +55,9 @@ Application::drawManager() {
|
||||||
if(ImGui::Button(ICON_FA_ARROW_LEFT " Back to profile manager")) {
|
if(ImGui::Button(ICON_FA_ARROW_LEFT " Back to profile manager")) {
|
||||||
_currentProfile = nullptr;
|
_currentProfile = nullptr;
|
||||||
_massManager.reset();
|
_massManager.reset();
|
||||||
_stagedMassManager.reset();
|
_fileWatcher.reset();
|
||||||
_uiState = UiState::ProfileManager;
|
_uiState = UiState::ProfileManager;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
|
||||||
if(ImGui::Button(ICON_FA_SYNC_ALT " Refresh external changes")) {
|
|
||||||
_currentProfile->refreshValues();
|
|
||||||
if(!_currentProfile->valid()) {
|
|
||||||
_currentProfile = nullptr;
|
|
||||||
_profileManager->refreshProfiles();
|
|
||||||
_queue.addToast(Toast::Type::Error, "The current profile isn't valid anymore."_s);
|
|
||||||
ImGui::End();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ImGui::BeginChild("##ProfileInfo",
|
if(ImGui::BeginChild("##ProfileInfo",
|
||||||
{ImGui::GetContentRegionAvail().x * 0.60f, 0.0f},
|
{ImGui::GetContentRegionAvail().x * 0.60f, 0.0f},
|
||||||
|
@ -104,11 +93,6 @@ Application::drawManager() {
|
||||||
if(ImGui::BeginMenuBar()) {
|
if(ImGui::BeginMenuBar()) {
|
||||||
ImGui::TextUnformatted("M.A.S.S. management");
|
ImGui::TextUnformatted("M.A.S.S. management");
|
||||||
drawHelpMarker("To move, import, or export builds, drag-and-drop them.");
|
drawHelpMarker("To move, import, or export builds, drag-and-drop them.");
|
||||||
if(ImGui::SmallButton(ICON_FA_SYNC_ALT " Refresh")) {
|
|
||||||
for(int i = 0; i < 32 ; i++) {
|
|
||||||
_massManager->refreshHangar(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,13 +527,10 @@ Application::drawMassManager() {
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(0);
|
ImGui::TableSetColumnIndex(0);
|
||||||
ImGui::TextUnformatted("Staging area");
|
ImGui::TextUnformatted("Staging area");
|
||||||
|
ImGui::SameLine();
|
||||||
if(ImGui::SmallButton(ICON_FA_FOLDER_OPEN " Open staging folder")) {
|
if(ImGui::SmallButton(ICON_FA_FOLDER_OPEN " Open staging folder")) {
|
||||||
openUri(Utility::Path::toNativeSeparators(conf().directories().staging));
|
openUri(Utility::Path::toNativeSeparators(conf().directories().staging));
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
|
||||||
if(ImGui::SmallButton(ICON_FA_SYNC_ALT " Refresh")) {
|
|
||||||
_stagedMassManager->refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(const auto& mass : _stagedMassManager->stagedMasses()) {
|
for(const auto& mass : _stagedMassManager->stagedMasses()) {
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
|
@ -594,7 +575,6 @@ Application::drawMassManager() {
|
||||||
if(!_massManager->exportMass(index)) {
|
if(!_massManager->exportMass(index)) {
|
||||||
_queue.addToast(Toast::Type::Error, _massManager->lastError());
|
_queue.addToast(Toast::Type::Error, _massManager->lastError());
|
||||||
}
|
}
|
||||||
_stagedMassManager->refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndDragDropTarget();
|
ImGui::EndDragDropTarget();
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "../GameData/Accessories.h"
|
#include "../GameData/Accessories.h"
|
||||||
#define STYLENAMES_DEFINITION
|
#define STYLENAMES_DEFINITION
|
||||||
#include "../GameData/StyleNames.h"
|
#include "../GameData/StyleNames.h"
|
||||||
|
#include "../ImportExport/Export.h"
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
|
@ -72,13 +73,17 @@ Application::drawMassViewer() {
|
||||||
drawTooltip(_currentMass->filename());
|
drawTooltip(_currentMass->filename());
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(2);
|
ImGui::TableSetColumnIndex(2);
|
||||||
if(ImGui::SmallButton(ICON_FA_SYNC_ALT " Refresh external changes")) {
|
if(_currentMass->dirty()) {
|
||||||
|
ImGui::TextUnformatted("External changes detected");
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::SmallButton(ICON_FA_SYNC_ALT " Refresh")) {
|
||||||
_currentMass->refreshValues();
|
_currentMass->refreshValues();
|
||||||
_currentMass->setDirty(false);
|
_currentMass->setDirty(false);
|
||||||
_jointsDirty = false;
|
_jointsDirty = false;
|
||||||
_stylesDirty = false;
|
_stylesDirty = false;
|
||||||
_eyeFlareDirty = false;
|
_eyeFlareDirty = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(3);
|
ImGui::TableSetColumnIndex(3);
|
||||||
if(ImGui::SmallButton(ICON_FA_TIMES)) {
|
if(ImGui::SmallButton(ICON_FA_TIMES)) {
|
||||||
|
@ -186,7 +191,9 @@ Application::drawGlobalStyles() {
|
||||||
_currentMass->getGlobalStyles();
|
_currentMass->getGlobalStyles();
|
||||||
break;
|
break;
|
||||||
case DCS_Save:
|
case DCS_Save:
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeGlobalStyle(i)) {
|
if(!_currentMass->writeGlobalStyle(i)) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <imgui_internal.h>
|
#include <imgui_internal.h>
|
||||||
|
|
||||||
#include "../FontAwesome/IconsFontAwesome5.h"
|
#include "../FontAwesome/IconsFontAwesome5.h"
|
||||||
|
@ -199,7 +197,9 @@ Application::drawArmour() {
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeArmourPart(part.slot)) {
|
if(!_currentMass->writeArmourPart(part.slot)) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,8 +357,11 @@ Application::drawBLAttachment() {
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeBulletLauncherAttachments()) {
|
if(!_currentMass->writeBulletLauncherAttachments()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,7 +388,9 @@ Application::drawCustomArmourStyles() {
|
||||||
_currentMass->getArmourCustomStyles();
|
_currentMass->getArmourCustomStyles();
|
||||||
break;
|
break;
|
||||||
case DCS_Save:
|
case DCS_Save:
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeArmourCustomStyle(i)) {
|
if(!_currentMass->writeArmourCustomStyle(i)) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -149,7 +149,9 @@ Application::drawJointSliders() {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeJointSliders()) {
|
if(!_currentMass->writeJointSliders()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
_jointsDirty = false;
|
_jointsDirty = false;
|
||||||
|
@ -204,7 +206,9 @@ Application::drawFrameStyles() {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeFrameStyles()) {
|
if(!_currentMass->writeFrameStyles()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
_stylesDirty = false;
|
_stylesDirty = false;
|
||||||
|
@ -236,7 +240,9 @@ Application::drawEyeColourPicker() {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeEyeFlareColour()) {
|
if(!_currentMass->writeEyeFlareColour()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
_eyeFlareDirty = false;
|
_eyeFlareDirty = false;
|
||||||
|
@ -270,7 +276,9 @@ Application::drawCustomFrameStyles() {
|
||||||
_currentMass->getFrameCustomStyles();
|
_currentMass->getFrameCustomStyles();
|
||||||
break;
|
break;
|
||||||
case DCS_Save:
|
case DCS_Save:
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
if(!_currentMass->writeFrameCustomStyle(i)) {
|
if(!_currentMass->writeFrameCustomStyle(i)) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include "../GameData/WeaponParts.h"
|
#include "../GameData/WeaponParts.h"
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "../Configuration/Configuration.h"
|
|
||||||
|
|
||||||
namespace mbst {
|
namespace mbst {
|
||||||
|
|
||||||
|
@ -33,11 +32,13 @@ Application::drawWeapons() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float footer_height_to_reserve = ImGui::GetFrameHeightWithSpacing();
|
||||||
|
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
if(!ImGui::BeginTable("##WeaponsList", 1,
|
if(!ImGui::BeginTable("##WeaponsList", 1,
|
||||||
ImGuiTableFlags_ScrollY|ImGuiTableFlags_BordersOuter|ImGuiTableFlags_BordersInnerH,
|
ImGuiTableFlags_ScrollY|ImGuiTableFlags_BordersOuter|ImGuiTableFlags_BordersInnerH,
|
||||||
{ImGui::GetContentRegionAvail().x * 0.2f, 0.0f}))
|
{ImGui::GetContentRegionAvail().x * 0.2f, -footer_height_to_reserve}))
|
||||||
{
|
{
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
return;
|
return;
|
||||||
|
@ -45,20 +46,118 @@ Application::drawWeapons() {
|
||||||
|
|
||||||
ImGui::TableSetupColumn("Weapon");
|
ImGui::TableSetupColumn("Weapon");
|
||||||
|
|
||||||
drawWeaponCategory("Melee weapons", GameObjects::Weapon::Type::Melee, _currentMass->meleeWeapons(), "MeleeWeapon",
|
drawWeaponCategory("Melee weapons", _currentMass->meleeWeapons(), _meleeDirty, "MeleeWeapon", "Melee weapon");
|
||||||
"Melee weapon");
|
drawWeaponCategory("Shield", _currentMass->shields(), _shieldsDirty, "Shield", "Shield");
|
||||||
drawWeaponCategory("Shield", GameObjects::Weapon::Type::Shield, _currentMass->shields(), "Shield", "Shield");
|
drawWeaponCategory("Bullet shooters", _currentMass->bulletShooters(), _bShootersDirty, "BShooter", "Bullet shooter");
|
||||||
drawWeaponCategory("Bullet shooters", GameObjects::Weapon::Type::BulletShooter, _currentMass->bulletShooters(),
|
drawWeaponCategory("Energy shooters", _currentMass->energyShooters(), _eShootersDirty, "EShooter", "Energy shooter");
|
||||||
"BShooter", "Bullet shooter");
|
drawWeaponCategory("Bullet launchers", _currentMass->bulletLaunchers(), _bLaunchersDirty, "BLauncher", "Bullet launcher");
|
||||||
drawWeaponCategory("Energy shooters", GameObjects::Weapon::Type::EnergyShooter, _currentMass->energyShooters(),
|
drawWeaponCategory("Energy launchers", _currentMass->energyLaunchers(), _eLaunchersDirty, "ELauncher", "Energy launcher");
|
||||||
"EShooter", "Energy shooter");
|
|
||||||
drawWeaponCategory("Bullet launchers", GameObjects::Weapon::Type::BulletLauncher, _currentMass->bulletLaunchers(),
|
|
||||||
"BLauncher", "Bullet launcher");
|
|
||||||
drawWeaponCategory("Energy launchers", GameObjects::Weapon::Type::EnergyLauncher, _currentMass->energyLaunchers(),
|
|
||||||
"ELauncher", "Energy launcher");
|
|
||||||
|
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
|
|
||||||
|
bool dirty = _meleeDirty || _shieldsDirty || _bShootersDirty || _eShootersDirty || _bLaunchersDirty || _eLaunchersDirty;
|
||||||
|
|
||||||
|
ImGui::BeginDisabled(!dirty);
|
||||||
|
|
||||||
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save order"); })) {
|
||||||
|
if(_meleeDirty) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
|
if(!_currentMass->writeMeleeWeapons()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_meleeDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_shieldsDirty) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
|
if(!_currentMass->writeShields()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_shieldsDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_bShootersDirty) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
|
if(!_currentMass->writeBulletShooters()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_bShootersDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_eShootersDirty) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
|
if(_currentMass->writeEnergyShooters()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_eShootersDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_bLaunchersDirty) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
|
if(_currentMass->writeBulletLaunchers()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_bLaunchersDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_eLaunchersDirty) {
|
||||||
|
_modifiedBySaveTool = true;
|
||||||
|
if(_currentMass->writeEnergyLaunchers()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_eLaunchersDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if(ImGui::Button(ICON_FA_UNDO_ALT " Reset")) {
|
||||||
|
if(_meleeDirty) {
|
||||||
|
_currentMass->getMeleeWeapons();
|
||||||
|
_meleeDirty = false;
|
||||||
|
}
|
||||||
|
if(_shieldsDirty) {
|
||||||
|
_currentMass->getShields();
|
||||||
|
_shieldsDirty = false;
|
||||||
|
}
|
||||||
|
if(_bShootersDirty) {
|
||||||
|
_currentMass->getBulletShooters();
|
||||||
|
_bShootersDirty = false;
|
||||||
|
}
|
||||||
|
if(_eShootersDirty) {
|
||||||
|
_currentMass->getEnergyShooters();
|
||||||
|
_eShootersDirty = false;
|
||||||
|
}
|
||||||
|
if(_bLaunchersDirty) {
|
||||||
|
_currentMass->getBulletLaunchers();
|
||||||
|
_bLaunchersDirty = false;
|
||||||
|
}
|
||||||
|
if(_eLaunchersDirty) {
|
||||||
|
_currentMass->getEnergyLaunchers();
|
||||||
|
_eLaunchersDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -70,7 +169,7 @@ Application::drawWeapons() {
|
||||||
|
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
if(!ImGui::BeginChild("##WeaponChild")) {
|
if(!ImGui::BeginChild("##WeaponChild", {0.0f, -footer_height_to_reserve})) {
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -79,61 +178,55 @@ Application::drawWeapons() {
|
||||||
|
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
ImGui::EndGroup();
|
if(drawUnsafeWidget([](){ return ImGui::Button(ICON_FA_SAVE " Save changes to weapon category"); })) {
|
||||||
}
|
_modifiedBySaveTool = true;
|
||||||
|
switch(_currentWeapon->type) {
|
||||||
void
|
|
||||||
Application::drawWeaponCategory(Containers::StringView name, GameObjects::Weapon::Type category,
|
|
||||||
Containers::ArrayView<GameObjects::Weapon> weapons_view,
|
|
||||||
Containers::StringView payload_type, Containers::StringView payload_tooltip)
|
|
||||||
{
|
|
||||||
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::TextUnformatted(name.cbegin(), name.cend());
|
|
||||||
|
|
||||||
ImGui::PushID(name.cbegin());
|
|
||||||
|
|
||||||
if(drawUnsafeWidget(ImGui::SmallButton, ICON_FA_SAVE " Save")) {
|
|
||||||
switch(category) {
|
|
||||||
case GameObjects::Weapon::Type::Melee:
|
case GameObjects::Weapon::Type::Melee:
|
||||||
if(!_currentMass->writeMeleeWeapons()) {
|
if(!_currentMass->writeMeleeWeapons()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GameObjects::Weapon::Type::Shield:
|
case GameObjects::Weapon::Type::Shield:
|
||||||
if(!_currentMass->writeShields()) {
|
if(!_currentMass->writeShields()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GameObjects::Weapon::Type::BulletShooter:
|
case GameObjects::Weapon::Type::BulletShooter:
|
||||||
if(!_currentMass->writeBulletShooters()) {
|
if(!_currentMass->writeBulletShooters()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GameObjects::Weapon::Type::EnergyShooter:
|
case GameObjects::Weapon::Type::EnergyShooter:
|
||||||
if(!_currentMass->writeEnergyShooters()) {
|
if(!_currentMass->writeEnergyShooters()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GameObjects::Weapon::Type::BulletLauncher:
|
case GameObjects::Weapon::Type::BulletLauncher:
|
||||||
if(!_currentMass->writeBulletLaunchers()) {
|
if(!_currentMass->writeBulletLaunchers()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GameObjects::Weapon::Type::EnergyLauncher:
|
case GameObjects::Weapon::Type::EnergyLauncher:
|
||||||
if(!_currentMass->writeEnergyLaunchers()) {
|
if(!_currentMass->writeEnergyLaunchers()) {
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
_modifiedBySaveTool = false;
|
||||||
_queue.addToast(Toast::Type::Error, "Unknown weapon type");
|
_queue.addToast(Toast::Type::Error, "Unknown weapon type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if(ImGui::SmallButton(ICON_FA_UNDO_ALT " Reset")) {
|
if(ImGui::Button(ICON_FA_UNDO_ALT " Reset weapon category")) {
|
||||||
switch(category) {
|
switch(_currentWeapon->type) {
|
||||||
case GameObjects::Weapon::Type::Melee:
|
case GameObjects::Weapon::Type::Melee:
|
||||||
_currentMass->getMeleeWeapons();
|
_currentMass->getMeleeWeapons();
|
||||||
break;
|
break;
|
||||||
|
@ -157,6 +250,19 @@ Application::drawWeaponCategory(Containers::StringView name, GameObjects::Weapon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::EndGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Application::drawWeaponCategory(Containers::StringView name, Containers::ArrayView<GameObjects::Weapon> weapons_view, bool& dirty,
|
||||||
|
Containers::StringView payload_type, Containers::StringView payload_tooltip)
|
||||||
|
{
|
||||||
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(name.cbegin(), name.cend());
|
||||||
|
|
||||||
|
ImGui::PushID(payload_type.data());
|
||||||
|
|
||||||
for(std::uint32_t i = 0; i < weapons_view.size(); i++) {
|
for(std::uint32_t i = 0; i < weapons_view.size(); i++) {
|
||||||
auto& weapon = weapons_view[i];
|
auto& weapon = weapons_view[i];
|
||||||
|
|
||||||
|
@ -195,6 +301,7 @@ Application::drawWeaponCategory(Containers::StringView name, GameObjects::Weapon
|
||||||
else {
|
else {
|
||||||
weapons_view[i] = weapons_view[index];
|
weapons_view[i] = weapons_view[index];
|
||||||
}
|
}
|
||||||
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndDragDropTarget();
|
ImGui::EndDragDropTarget();
|
||||||
|
@ -216,7 +323,7 @@ Application::drawWeaponEditor(GameObjects::Weapon& weapon) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr Containers::StringView labels[] {
|
static Containers::StringView labels[] {
|
||||||
#define c(enumerator, strenum, name) name,
|
#define c(enumerator, strenum, name) name,
|
||||||
#include "../Maps/WeaponTypes.hpp"
|
#include "../Maps/WeaponTypes.hpp"
|
||||||
#undef c
|
#undef c
|
||||||
|
@ -238,35 +345,9 @@ Application::drawWeaponEditor(GameObjects::Weapon& weapon) {
|
||||||
weapon.name = name_buf.data();
|
weapon.name = name_buf.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(weapon.type == GameObjects::Weapon::Type::BulletShooter) {
|
|
||||||
ImGui::Button("Import energy shooter by dragging it here");
|
|
||||||
if(ImGui::BeginDragDropTarget()) {
|
|
||||||
if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("EShooter")) {
|
|
||||||
std::uint32_t index = *static_cast<std::uint32_t*>(payload->Data);
|
|
||||||
weapon = _currentMass->energyShooters()[index];
|
|
||||||
}
|
|
||||||
ImGui::EndDragDropTarget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(weapon.type == GameObjects::Weapon::Type::EnergyShooter) {
|
|
||||||
ImGui::Button("Import bullet shooter by dragging it here");
|
|
||||||
if(ImGui::BeginDragDropTarget()) {
|
|
||||||
if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("BShooter")) {
|
|
||||||
std::uint32_t index = *static_cast<std::uint32_t*>(payload->Data);
|
|
||||||
weapon = _currentMass->bulletShooters()[index];
|
|
||||||
}
|
|
||||||
ImGui::EndDragDropTarget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
drawAlignedText("Equipped:");
|
drawAlignedText("Equipped:");
|
||||||
|
|
||||||
if(conf().advancedMode()) {
|
|
||||||
drawAlignedText("Weapon type:");
|
|
||||||
drawAlignedText("");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(weapon.type != GameObjects::Weapon::Type::Shield) {
|
if(weapon.type != GameObjects::Weapon::Type::Shield) {
|
||||||
drawAlignedText("Damage type:");
|
drawAlignedText("Damage type:");
|
||||||
}
|
}
|
||||||
|
@ -285,47 +366,6 @@ Application::drawWeaponEditor(GameObjects::Weapon& weapon) {
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::Checkbox("##EquippedCheckbox", &weapon.attached);
|
ImGui::Checkbox("##EquippedCheckbox", &weapon.attached);
|
||||||
|
|
||||||
if(conf().advancedMode()) {
|
|
||||||
if(ImGui::RadioButton("Melee##MeleeType", weapon.type == GameObjects::Weapon::Type::Melee)) {
|
|
||||||
weapon.type = GameObjects::Weapon::Type::Melee;
|
|
||||||
if(weapon.damageType == GameObjects::Weapon::DamageType::Piercing || weapon.damageType == GameObjects::Weapon::DamageType::Plasma) {
|
|
||||||
weapon.damageType = GameObjects::Weapon::DamageType::Physical;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if(ImGui::RadioButton("Shield##ShieldType", weapon.type == GameObjects::Weapon::Type::Shield)) {
|
|
||||||
weapon.type = GameObjects::Weapon::Type::Shield;
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if(ImGui::RadioButton("Bullet shooter##BShooterType", weapon.type == GameObjects::Weapon::Type::BulletShooter)) {
|
|
||||||
weapon.type = GameObjects::Weapon::Type::BulletShooter;
|
|
||||||
if(weapon.damageType == GameObjects::Weapon::DamageType::Physical || weapon.damageType == GameObjects::Weapon::DamageType::Plasma) {
|
|
||||||
weapon.damageType = GameObjects::Weapon::DamageType::Piercing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ImGui::RadioButton("Energy shooter##EShooterType", weapon.type == GameObjects::Weapon::Type::EnergyShooter)) {
|
|
||||||
weapon.type = GameObjects::Weapon::Type::EnergyShooter;
|
|
||||||
if(weapon.damageType == GameObjects::Weapon::DamageType::Physical || weapon.damageType == GameObjects::Weapon::DamageType::Piercing) {
|
|
||||||
weapon.damageType = GameObjects::Weapon::DamageType::Plasma;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if(ImGui::RadioButton("Bullet launcher##BLauncherType", weapon.type == GameObjects::Weapon::Type::BulletLauncher)) {
|
|
||||||
weapon.type = GameObjects::Weapon::Type::BulletLauncher;
|
|
||||||
if(weapon.damageType == GameObjects::Weapon::DamageType::Physical || weapon.damageType == GameObjects::Weapon::DamageType::Plasma) {
|
|
||||||
weapon.damageType = GameObjects::Weapon::DamageType::Piercing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if(ImGui::RadioButton("Energy launcher##ELauncherType", weapon.type == GameObjects::Weapon::Type::EnergyLauncher)) {
|
|
||||||
weapon.type = GameObjects::Weapon::Type::EnergyLauncher;
|
|
||||||
if(weapon.damageType == GameObjects::Weapon::DamageType::Physical || weapon.damageType == GameObjects::Weapon::DamageType::Piercing) {
|
|
||||||
weapon.damageType = GameObjects::Weapon::DamageType::Plasma;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(weapon.type != GameObjects::Weapon::Type::Shield) {
|
if(weapon.type != GameObjects::Weapon::Type::Shield) {
|
||||||
if(weapon.type == GameObjects::Weapon::Type::Melee &&
|
if(weapon.type == GameObjects::Weapon::Type::Melee &&
|
||||||
ImGui::RadioButton("Physical##NoElement", weapon.damageType == GameObjects::Weapon::DamageType::Physical))
|
ImGui::RadioButton("Physical##NoElement", weapon.damageType == GameObjects::Weapon::DamageType::Physical))
|
||||||
|
@ -385,7 +425,7 @@ Application::drawWeaponEditor(GameObjects::Weapon& weapon) {
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
if(weapon.parts.isEmpty()) {
|
if(weapon.parts.isEmpty()) {
|
||||||
ImGui::TextUnformatted("This weapon has no parts. This is not normal.");
|
ImGui::TextUnformatted("This weapon has no parts.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,8 +467,8 @@ Application::drawWeaponEditor(GameObjects::Weapon& weapon) {
|
||||||
if(map->find(part.id) != map->cend()) {
|
if(map->find(part.id) != map->cend()) {
|
||||||
ImGui::TextUnformatted(map->at(part.id).cbegin(), map->at(part.id).cend());
|
ImGui::TextUnformatted(map->at(part.id).cbegin(), map->at(part.id).cend());
|
||||||
}
|
}
|
||||||
else if(part.id < 0) {
|
else if(part.id == -1) {
|
||||||
ImGui::TextUnformatted("<invalid part ID>");
|
ImGui::TextUnformatted("<none>");
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
ImGui::Text("ID: %i", part.id);
|
ImGui::Text("ID: %i", part.id);
|
||||||
|
@ -456,17 +496,20 @@ Application::drawWeaponEditor(GameObjects::Weapon& weapon) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(weapon.type == GameObjects::Weapon::Type::Shield ||
|
||||||
|
(weapon.type == GameObjects::Weapon::Type::BulletLauncher && _selectedWeaponPart != 0))
|
||||||
|
{
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::SmallButton("Hide part " ICON_FA_QUESTION_CIRCLE)) {
|
if(ImGui::SmallButton("Unequip")) {
|
||||||
part.id = 96 + part.id >= 0 ? (part.id / 100) * 100 : 0;
|
part.id = -1;
|
||||||
|
}
|
||||||
|
if(weapon.type == GameObjects::Weapon::Type::Shield && _selectedWeaponPart == 0) {
|
||||||
|
drawTooltip("This will make the whole shield and its accessories invisible.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
drawTooltip("This will make accessories invisible as well.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
drawTooltip(_selectedWeaponPart == 0 ?
|
|
||||||
"This will hide the selected part, but not its accessories. "
|
|
||||||
"Parts attached to this one will also be hidden, though their accessories WON'T be visible. "
|
|
||||||
"For parts that affect weapon stance/functionality, this feature will try to preserve that." :
|
|
||||||
"This will hide the selected part, but not its accessories. "
|
|
||||||
"For parts that affect weapon stance/functionality, this feature will try to preserve that.",
|
|
||||||
static_cast<float>(windowSize().x()) * 0.4f);
|
|
||||||
|
|
||||||
if(ImGui::BeginChild("##PartDetails", {}, ImGuiChildFlags_Border)) {
|
if(ImGui::BeginChild("##PartDetails", {}, ImGuiChildFlags_Border)) {
|
||||||
ImGui::TextUnformatted("Styles:");
|
ImGui::TextUnformatted("Styles:");
|
||||||
|
|
|
@ -91,6 +91,7 @@ Application::drawProfileManager() {
|
||||||
{
|
{
|
||||||
_currentProfile = _profileManager->getProfile(i);
|
_currentProfile = _profileManager->getProfile(i);
|
||||||
initialiseMassManager();
|
initialiseMassManager();
|
||||||
|
initialiseFileWatcher();
|
||||||
_uiState = UiState::MainManager;
|
_uiState = UiState::MainManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,8 @@ Application::drawAbout() {
|
||||||
if(ImGui::CollapsingHeader("Third-party components")) {
|
if(ImGui::CollapsingHeader("Third-party components")) {
|
||||||
ImGui::TextWrapped("This application uses the following third-party components:");
|
ImGui::TextWrapped("This application uses the following third-party components:");
|
||||||
|
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, 0.0f);
|
||||||
|
|
||||||
if(ImGui::TreeNodeEx("Corrade", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
if(ImGui::TreeNodeEx("Corrade", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
ImGui::Text("Version used: %s", CORRADE_VERSION_STRING);
|
ImGui::Text("Version used: %s", CORRADE_VERSION_STRING);
|
||||||
auto corrade_website = "https://magnum.graphics/corrade";
|
auto corrade_website = "https://magnum.graphics/corrade";
|
||||||
|
@ -193,6 +195,23 @@ Application::drawAbout() {
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ImGui::TreeNodeEx("Entropia File System Watcher (efsw)", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
|
auto efsw_repo = "https://github.com/SpartanJ/efsw";
|
||||||
|
drawAlignedText(ICON_FA_GITHUB " %s", efsw_repo);
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::Button("Copy to clipboard")) {
|
||||||
|
ImGui::SetClipboardText(efsw_repo);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::Button("Open in browser")) {
|
||||||
|
openUri(efsw_repo);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TextUnformatted("Licence: MIT");
|
||||||
|
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
if(ImGui::TreeNodeEx("libcurl", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
if(ImGui::TreeNodeEx("libcurl", ImGuiTreeNodeFlags_SpanAvailWidth)) {
|
||||||
ImGui::Text("Version used: %s", LIBCURL_VERSION);
|
ImGui::Text("Version used: %s", LIBCURL_VERSION);
|
||||||
auto curl_website = "https://curl.se/libcurl";
|
auto curl_website = "https://curl.se/libcurl";
|
||||||
|
@ -245,6 +264,8 @@ Application::drawAbout() {
|
||||||
|
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
#include <Corrade/Utility/Path.h>
|
#include <Corrade/Utility/Path.h>
|
||||||
|
|
||||||
#include <Magnum/Math/Time.h>
|
|
||||||
|
|
||||||
#include "../Configuration/Configuration.h"
|
#include "../Configuration/Configuration.h"
|
||||||
#include "../FontAwesome/IconsFontAwesome5.h"
|
#include "../FontAwesome/IconsFontAwesome5.h"
|
||||||
#include "../FontAwesome/IconsFontAwesome5Brands.h"
|
#include "../FontAwesome/IconsFontAwesome5Brands.h"
|
||||||
|
@ -68,6 +66,28 @@ Application::drawMainMenu() {
|
||||||
openUri(Utility::Path::toNativeSeparators(conf().directories().staging));
|
openUri(Utility::Path::toNativeSeparators(conf().directories().staging));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*if(ImGui::BeginMenu(ICON_FA_BOXES " Armoury")) {
|
||||||
|
if(ImGui::MenuItem(ICON_FA_SHIELD_ALT " Armour parts", nullptr, false,
|
||||||
|
Utility::Path::exists(conf().directories().armours)))
|
||||||
|
{
|
||||||
|
openUri(Utility::Path::toNativeSeparators(conf().directories().armours));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::MenuItem(ICON_FA_HAMMER " Weapons", nullptr, false,
|
||||||
|
Utility::Path::exists(conf().directories().weapons)))
|
||||||
|
{
|
||||||
|
openUri(Utility::Path::toNativeSeparators(conf().directories().weapons));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ImGui::MenuItem(ICON_FA_PALETTE " Custom styles", nullptr, false,
|
||||||
|
Utility::Path::exists(conf().directories().styles)))
|
||||||
|
{
|
||||||
|
openUri(Utility::Path::toNativeSeparators(conf().directories().styles));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}*/
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,8 +120,7 @@ Application::drawMainMenu() {
|
||||||
conf().setSwapInterval(i);
|
conf().setSwapInterval(i);
|
||||||
setSwapInterval(i);
|
setSwapInterval(i);
|
||||||
if(i == 0) {
|
if(i == 0) {
|
||||||
using namespace Math::Literals;
|
setMinimalLoopPeriod(0);
|
||||||
setMinimalLoopPeriod(0_nsec);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,13 +149,12 @@ Application::drawMainMenu() {
|
||||||
drawHelpMarker("This gives access to save edition features that can be considered cheats.",
|
drawHelpMarker("This gives access to save edition features that can be considered cheats.",
|
||||||
float(windowSize().x()) * 0.4f);
|
float(windowSize().x()) * 0.4f);
|
||||||
|
|
||||||
if(drawCheckbox("Advanced fuckery mode", conf().advancedMode())) {
|
if(drawCheckbox("Advanced mode", conf().advancedMode())) {
|
||||||
conf().setAdvancedMode(!conf().advancedMode());
|
conf().setAdvancedMode(!conf().advancedMode());
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
drawHelpMarker("This gives access to editing values that have unknown purposes or are undocumented. "
|
drawHelpMarker("This gives access to editing values that have unknown purposes or are undocumented.",
|
||||||
"It also grants access to some special editing features allowing things the game is NOT designed for.",
|
|
||||||
float(windowSize().x()) * 0.4f);
|
float(windowSize().x()) * 0.4f);
|
||||||
|
|
||||||
if(drawCheckbox("Check for updates on startup", conf().checkUpdatesOnStartup())) {
|
if(drawCheckbox("Check for updates on startup", conf().checkUpdatesOnStartup())) {
|
||||||
|
@ -205,7 +223,7 @@ Application::drawMainMenu() {
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
//ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
//if(conf().isRunningInWine() && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
|
//if(conf().isRunningInWine() && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
|
||||||
// ImGui::SetTooltip("Not available when running in Wine.");
|
// ImGui::SetTooltip("Not available when running in Wine.");
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -18,7 +18,7 @@ set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
set(SAVETOOL_PROJECT_VERSION 1.6.1)
|
set(SAVETOOL_PROJECT_VERSION 1.5.3)
|
||||||
|
|
||||||
find_package(Corrade REQUIRED Containers Utility)
|
find_package(Corrade REQUIRED Containers Utility)
|
||||||
if(CORRADE_TARGET_WINDOWS)
|
if(CORRADE_TARGET_WINDOWS)
|
||||||
|
@ -31,6 +31,10 @@ if(SAVETOOL_USE_SYSTEM_LIBZIP)
|
||||||
find_package(libzip REQUIRED)
|
find_package(libzip REQUIRED)
|
||||||
endif(SAVETOOL_USE_SYSTEM_LIBZIP)
|
endif(SAVETOOL_USE_SYSTEM_LIBZIP)
|
||||||
|
|
||||||
|
if(SAVETOOL_USE_SYSTEM_EFSW)
|
||||||
|
find_package(efsw REQUIRED)
|
||||||
|
endif(SAVETOOL_USE_SYSTEM_EFSW)
|
||||||
|
|
||||||
if(SAVETOOL_USE_SYSTEM_LIBCURL)
|
if(SAVETOOL_USE_SYSTEM_LIBCURL)
|
||||||
find_package(CURL REQUIRED HTTPS)
|
find_package(CURL REQUIRED HTTPS)
|
||||||
endif(SAVETOOL_USE_SYSTEM_LIBCURL)
|
endif(SAVETOOL_USE_SYSTEM_LIBCURL)
|
||||||
|
@ -131,6 +135,14 @@ set(Gvas_SOURCES
|
||||||
Gvas/PropertySerialiser.cpp
|
Gvas/PropertySerialiser.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(ImportExport_SOURCES
|
||||||
|
ImportExport/Import.h
|
||||||
|
ImportExport/Import.cpp
|
||||||
|
ImportExport/Export.h
|
||||||
|
ImportExport/Export.cpp
|
||||||
|
ImportExport/Keys.h
|
||||||
|
)
|
||||||
|
|
||||||
if(CORRADE_TARGET_WINDOWS)
|
if(CORRADE_TARGET_WINDOWS)
|
||||||
set(SAVETOOL_RC_FILE resource.rc)
|
set(SAVETOOL_RC_FILE resource.rc)
|
||||||
endif()
|
endif()
|
||||||
|
@ -141,6 +153,7 @@ add_executable(MassBuilderSaveTool
|
||||||
Application/Application.cpp
|
Application/Application.cpp
|
||||||
Application/Application_drawAbout.cpp
|
Application/Application_drawAbout.cpp
|
||||||
Application/Application_drawMainMenu.cpp
|
Application/Application_drawMainMenu.cpp
|
||||||
|
Application/Application_FileWatcher.cpp
|
||||||
Application/Application_Initialisation.cpp
|
Application/Application_Initialisation.cpp
|
||||||
Application/Application_MainManager.cpp
|
Application/Application_MainManager.cpp
|
||||||
Application/Application_MassViewer.cpp
|
Application/Application_MassViewer.cpp
|
||||||
|
@ -209,6 +222,7 @@ add_executable(MassBuilderSaveTool
|
||||||
${Logger_SOURCES}
|
${Logger_SOURCES}
|
||||||
${BinaryIo_SOURCES}
|
${BinaryIo_SOURCES}
|
||||||
${Gvas_SOURCES}
|
${Gvas_SOURCES}
|
||||||
|
${ImportExport_SOURCES}
|
||||||
${SAVETOOL_RC_FILE}
|
${SAVETOOL_RC_FILE}
|
||||||
${Assets}
|
${Assets}
|
||||||
)
|
)
|
||||||
|
@ -220,10 +234,10 @@ endif()
|
||||||
target_compile_definitions(MassBuilderSaveTool PRIVATE
|
target_compile_definitions(MassBuilderSaveTool PRIVATE
|
||||||
SAVETOOL_VERSION_STRING="${SAVETOOL_PROJECT_VERSION}"
|
SAVETOOL_VERSION_STRING="${SAVETOOL_PROJECT_VERSION}"
|
||||||
SAVETOOL_VERSION_MAJOR=1
|
SAVETOOL_VERSION_MAJOR=1
|
||||||
SAVETOOL_VERSION_MINOR=6
|
SAVETOOL_VERSION_MINOR=5
|
||||||
SAVETOOL_VERSION_PATCH=1
|
SAVETOOL_VERSION_PATCH=3
|
||||||
SAVETOOL_VERSION_PRERELEASE=false
|
SAVETOOL_VERSION_PRERELEASE=false
|
||||||
SAVETOOL_CODENAME="Glorious Fuckery"
|
SAVETOOL_CODENAME="Friendly Valkyrie"
|
||||||
SAVETOOL_SUPPORTED_GAME_VERSION="0.12.x"
|
SAVETOOL_SUPPORTED_GAME_VERSION="0.12.x"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -257,6 +271,12 @@ else()
|
||||||
target_link_libraries(MassBuilderSaveTool PRIVATE zip)
|
target_link_libraries(MassBuilderSaveTool PRIVATE zip)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(SAVETOOL_USE_SYSTEM_EFSW)
|
||||||
|
target_link_libraries(MassBuilderSaveTool PRIVATE efsw::efsw)
|
||||||
|
else()
|
||||||
|
target_link_libraries(MassBuilderSaveTool PRIVATE efsw)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CORRADE_TARGET_WINDOWS)
|
if(CORRADE_TARGET_WINDOWS)
|
||||||
target_link_libraries(MassBuilderSaveTool PRIVATE
|
target_link_libraries(MassBuilderSaveTool PRIVATE
|
||||||
Corrade::Main
|
Corrade::Main
|
||||||
|
|
|
@ -119,6 +119,10 @@ Configuration::Configuration() {
|
||||||
Containers::String executable_location = Utility::Path::split(*Utility::Path::executableLocation()).first();
|
Containers::String executable_location = Utility::Path::split(*Utility::Path::executableLocation()).first();
|
||||||
_directories.backups = Utility::Path::join(executable_location, "backups");
|
_directories.backups = Utility::Path::join(executable_location, "backups");
|
||||||
_directories.staging = Utility::Path::join(executable_location, "staging");
|
_directories.staging = Utility::Path::join(executable_location, "staging");
|
||||||
|
//auto armoury_dir = Utility::Path::join(executable_location, "armoury");
|
||||||
|
//_directories.armours = Utility::Path::join(armoury_dir, "armours");
|
||||||
|
//_directories.weapons = Utility::Path::join(armoury_dir, "weapons");
|
||||||
|
//_directories.styles = Utility::Path::join(armoury_dir, "styles");
|
||||||
_directories.temp = Utility::Path::join(executable_location, "temp");
|
_directories.temp = Utility::Path::join(executable_location, "temp");
|
||||||
|
|
||||||
if(!Utility::Path::exists(_directories.backups)) {
|
if(!Utility::Path::exists(_directories.backups)) {
|
||||||
|
@ -135,6 +139,27 @@ Configuration::Configuration() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//if(!Utility::Path::exists(_directories.armours)) {
|
||||||
|
// LOG_WARNING("Armours directory not found, creating...");
|
||||||
|
// if(!Utility::Path::make(_directories.armours)) {
|
||||||
|
// LOG_ERROR(_lastError = "Couldn't create the armours directory.");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//if(!Utility::Path::exists(_directories.weapons)) {
|
||||||
|
// LOG_WARNING("Weapons directory not found, creating...");
|
||||||
|
// if(!Utility::Path::make(_directories.weapons)) {
|
||||||
|
// LOG_ERROR(_lastError = "Couldn't create the weapons directory.");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//if(!Utility::Path::exists(_directories.styles)) {
|
||||||
|
// LOG_WARNING("Styles directory not found, creating...");
|
||||||
|
// if(!Utility::Path::make(_directories.styles)) {
|
||||||
|
// LOG_ERROR(_lastError = "Couldn't create the styles directory.");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
if(!Utility::Path::exists(_directories.temp)) {
|
if(!Utility::Path::exists(_directories.temp)) {
|
||||||
LOG_WARNING("Temporary directory not found, creating...");
|
LOG_WARNING("Temporary directory not found, creating...");
|
||||||
|
|
|
@ -70,6 +70,9 @@ class Configuration {
|
||||||
Containers::String gameScreenshots;
|
Containers::String gameScreenshots;
|
||||||
Containers::String backups;
|
Containers::String backups;
|
||||||
Containers::String staging;
|
Containers::String staging;
|
||||||
|
Containers::String armours;
|
||||||
|
Containers::String weapons;
|
||||||
|
Containers::String styles;
|
||||||
Containers::String temp;
|
Containers::String temp;
|
||||||
};
|
};
|
||||||
auto directories() const -> Directories const&;
|
auto directories() const -> Directories const&;
|
||||||
|
|
|
@ -27,9 +27,6 @@ using namespace Containers::Literals;
|
||||||
|
|
||||||
namespace mbst::GameData {
|
namespace mbst::GameData {
|
||||||
|
|
||||||
// As of this writing (2024-12-07T12:08+01:00), the IDs ending in 96 are not valid IDs in the game, but are used by the
|
|
||||||
// Save Tool to display a name instead of "ID: <number>".
|
|
||||||
|
|
||||||
// region Melee
|
// region Melee
|
||||||
static const std::map<std::int32_t, Containers::StringView> melee_grips {
|
static const std::map<std::int32_t, Containers::StringView> melee_grips {
|
||||||
{0, "Combat Grip (1H)"_s},
|
{0, "Combat Grip (1H)"_s},
|
||||||
|
@ -41,7 +38,6 @@ static const std::map<std::int32_t, Containers::StringView> melee_grips {
|
||||||
{6, "Knight Guard Grip (1H)"_s},
|
{6, "Knight Guard Grip (1H)"_s},
|
||||||
{7, "Saber Guard Grip (1H)"_s},
|
{7, "Saber Guard Grip (1H)"_s},
|
||||||
{8, "Base Grip (1H)"_s},
|
{8, "Base Grip (1H)"_s},
|
||||||
{96, "<hidden grip> (1H)"_s},
|
|
||||||
|
|
||||||
{100, "Combat Side Grip (1H)"_s},
|
{100, "Combat Side Grip (1H)"_s},
|
||||||
{101, "Hollowed Side Grip (1H)"_s},
|
{101, "Hollowed Side Grip (1H)"_s},
|
||||||
|
@ -52,14 +48,12 @@ static const std::map<std::int32_t, Containers::StringView> melee_grips {
|
||||||
{106, "Concave Side Grip (1H)"_s},
|
{106, "Concave Side Grip (1H)"_s},
|
||||||
{107, "Polehead Side Grip (1H)"_s},
|
{107, "Polehead Side Grip (1H)"_s},
|
||||||
{108, "Base Side Grip (1H)"_s},
|
{108, "Base Side Grip (1H)"_s},
|
||||||
{196, "<hidden side grip> (1H)"_s},
|
|
||||||
|
|
||||||
{200, "Combat Dual Grip (1H)"_s},
|
{200, "Combat Dual Grip (1H)"_s},
|
||||||
{201, "Hollowed Dual Grip (1H)"_s},
|
{201, "Hollowed Dual Grip (1H)"_s},
|
||||||
{202, "Plated Dual Grip (1H)"_s},
|
{202, "Plated Dual Grip (1H)"_s},
|
||||||
{203, "Concave Dual Grip (1H)"_s},
|
{203, "Concave Dual Grip (1H)"_s},
|
||||||
{204, "Polehead Dual Grip (1H)"_s},
|
{204, "Polehead Dual Grip (1H)"_s},
|
||||||
{296, "<hidden dual grip> (1H)"_s},
|
|
||||||
|
|
||||||
{400, "Combat Twin Grip (1H)"_s},
|
{400, "Combat Twin Grip (1H)"_s},
|
||||||
{401, "Sepal Twin Grip (1H)"_s},
|
{401, "Sepal Twin Grip (1H)"_s},
|
||||||
|
@ -69,7 +63,6 @@ static const std::map<std::int32_t, Containers::StringView> melee_grips {
|
||||||
{405, "Handguard Twin Grip (1H)"_s},
|
{405, "Handguard Twin Grip (1H)"_s},
|
||||||
{406, "Fullguard Twin Grip (1H)"_s},
|
{406, "Fullguard Twin Grip (1H)"_s},
|
||||||
{407, "Base Twin Grip (1H)"_s},
|
{407, "Base Twin Grip (1H)"_s},
|
||||||
{496, "<hidden twin grip> (1H)"_s},
|
|
||||||
|
|
||||||
{1000, "Combat Knuckle (R/L)"_s},
|
{1000, "Combat Knuckle (R/L)"_s},
|
||||||
{1001, "Battle Fist (R/L)"_s},
|
{1001, "Battle Fist (R/L)"_s},
|
||||||
|
@ -77,7 +70,6 @@ static const std::map<std::int32_t, Containers::StringView> melee_grips {
|
||||||
{1003, "Heavy Fist (R/L)"_s},
|
{1003, "Heavy Fist (R/L)"_s},
|
||||||
{1004, "Thick Fist (R/L)"_s},
|
{1004, "Thick Fist (R/L)"_s},
|
||||||
{1005, "Base Fist (R/L)"_s},
|
{1005, "Base Fist (R/L)"_s},
|
||||||
{1096, "<hidden fist> (R/L)"_s},
|
|
||||||
|
|
||||||
{2000, "Combat Polearm (2H)"_s},
|
{2000, "Combat Polearm (2H)"_s},
|
||||||
{2001, "Dual Guard Polearm (2H)"_s},
|
{2001, "Dual Guard Polearm (2H)"_s},
|
||||||
|
@ -87,7 +79,6 @@ static const std::map<std::int32_t, Containers::StringView> melee_grips {
|
||||||
{2005, "Sharp Polearm (2H)"_s},
|
{2005, "Sharp Polearm (2H)"_s},
|
||||||
{2006, "Ring Polearm (2H)"_s},
|
{2006, "Ring Polearm (2H)"_s},
|
||||||
{2007, "Base Polearm (2H)"_s},
|
{2007, "Base Polearm (2H)"_s},
|
||||||
{2096, "<hidden polearm> (2H)"_s},
|
|
||||||
|
|
||||||
{2100, "Combat Side Polearm (2H)"_s},
|
{2100, "Combat Side Polearm (2H)"_s},
|
||||||
{2101, "Plated Side Polearm (2H)"_s},
|
{2101, "Plated Side Polearm (2H)"_s},
|
||||||
|
@ -95,12 +86,10 @@ static const std::map<std::int32_t, Containers::StringView> melee_grips {
|
||||||
{2103, "Fin Side Polearm (2H)"_s},
|
{2103, "Fin Side Polearm (2H)"_s},
|
||||||
{2104, "Heavy Side Polearm (2H)"_s},
|
{2104, "Heavy Side Polearm (2H)"_s},
|
||||||
{2105, "Base Side Polearm (2H)"_s},
|
{2105, "Base Side Polearm (2H)"_s},
|
||||||
{2196, "<hidden side polearm> (2H)"_s},
|
|
||||||
|
|
||||||
{2200, "Combat Dual Polearm (2H)"_s},
|
{2200, "Combat Dual Polearm (2H)"_s},
|
||||||
{2201, "Studded Dual Polearm (2H)"_s},
|
{2201, "Studded Dual Polearm (2H)"_s},
|
||||||
{2202, "Circular Dual Polearm (2H)"_s},
|
{2202, "Circular Dual Polearm (2H)"_s},
|
||||||
{2296, "<hidden dual polearm> (2H)"_s},
|
|
||||||
|
|
||||||
{2400, "Combat Twin Blade (2H)"_s},
|
{2400, "Combat Twin Blade (2H)"_s},
|
||||||
{2401, "Guard Twin Blade (2H)"_s},
|
{2401, "Guard Twin Blade (2H)"_s},
|
||||||
|
@ -110,7 +99,6 @@ static const std::map<std::int32_t, Containers::StringView> melee_grips {
|
||||||
{2405, "Holder Twin Blade (2H)"_s},
|
{2405, "Holder Twin Blade (2H)"_s},
|
||||||
{2406, "Ring Twin Blade (2H)"_s},
|
{2406, "Ring Twin Blade (2H)"_s},
|
||||||
{2407, "Base Twin Blade (2H)"_s},
|
{2407, "Base Twin Blade (2H)"_s},
|
||||||
{2496, "<hidden twin blade> (2H)"_s},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::map<std::int32_t, Containers::StringView> melee_assaulters {
|
static const std::map<std::int32_t, Containers::StringView> melee_assaulters {
|
||||||
|
@ -127,35 +115,39 @@ static const std::map<std::int32_t, Containers::StringView> melee_assaulters {
|
||||||
{10, "Long Curved Blade"_s},
|
{10, "Long Curved Blade"_s},
|
||||||
{11, "Long Broad Blade"_s},
|
{11, "Long Broad Blade"_s},
|
||||||
{12, "Base L Sword"_s},
|
{12, "Base L Sword"_s},
|
||||||
|
|
||||||
{20, "Long Combat Edge"_s},
|
{20, "Long Combat Edge"_s},
|
||||||
{21, "Long Attached Edge"_s},
|
{21, "Long Attached Edge"_s},
|
||||||
|
|
||||||
{40, "Katana Blade"_s},
|
{40, "Katana Blade"_s},
|
||||||
{41, "Custom Katana Blade"_s},
|
{41, "Custom Katana Blade"_s},
|
||||||
|
|
||||||
{60, "Energy Blade (Motion)"_s},
|
{60, "Energy Blade (Motion)"_s},
|
||||||
{61, "Powered Blade"_s},
|
{61, "Powered Blade"_s},
|
||||||
{96, "<hidden long blade>"_s},
|
|
||||||
|
|
||||||
{100, "Short Metal Blade"_s},
|
{100, "Short Metal Blade"_s},
|
||||||
{101, "Short Assault Blade"_s},
|
{101, "Short Assault Blade"_s},
|
||||||
{102, "Short Fin Blade"_s},
|
{102, "Short Fin Blade"_s},
|
||||||
{103, "Base S Sword"_s},
|
{103, "Base S Sword"_s},
|
||||||
|
|
||||||
{120, "Short Combat Edge"_s},
|
{120, "Short Combat Edge"_s},
|
||||||
|
|
||||||
{160, "Short Energy Blade (Motion)"_s},
|
{160, "Short Energy Blade (Motion)"_s},
|
||||||
{161, "Short Powered Blade"_s},
|
{161, "Short Powered Blade"_s},
|
||||||
|
|
||||||
{180, "Triclaw"_s},
|
{180, "Triclaw"_s},
|
||||||
{181, "Straight Triclaw"_s},
|
{181, "Straight Triclaw"_s},
|
||||||
{182, "Griphold Claw"_s},
|
{182, "Griphold Claw"_s},
|
||||||
{183, "Energy Claw"_s},
|
{183, "Energy Claw"_s},
|
||||||
{184, "Openhold Claw"_s},
|
{184, "Openhold Claw"_s},
|
||||||
{185, "Hooktusk Claw"_s},
|
{185, "Hooktusk Claw"_s},
|
||||||
{196, "<hidden short blade>"_s},
|
|
||||||
|
|
||||||
{200, "Bracer"_s},
|
{200, "Bracer"_s},
|
||||||
{201, "Custom Bracer"_s},
|
{201, "Custom Bracer"_s},
|
||||||
{202, "Base Hammer"_s},
|
{202, "Base Hammer"_s},
|
||||||
|
|
||||||
{210, "Expanded Bracer"_s},
|
{210, "Expanded Bracer"_s},
|
||||||
{211, "Expanded Custom Bracer"_s},
|
{211, "Expanded Custom Bracer"_s},
|
||||||
{296, "<hidden bracer>"_s},
|
|
||||||
|
|
||||||
{300, "Heavy Smasher"_s},
|
{300, "Heavy Smasher"_s},
|
||||||
{301, "Heavy Basher"_s},
|
{301, "Heavy Basher"_s},
|
||||||
|
@ -164,7 +156,6 @@ static const std::map<std::int32_t, Containers::StringView> melee_assaulters {
|
||||||
{304, "Heavy Diamond Smasher"_s},
|
{304, "Heavy Diamond Smasher"_s},
|
||||||
{305, "Heavy Spinning Smasher (Motion)"_s},
|
{305, "Heavy Spinning Smasher (Motion)"_s},
|
||||||
{306, "Base L Mace"_s},
|
{306, "Base L Mace"_s},
|
||||||
{396, "<hidden heavy mace>"_s},
|
|
||||||
|
|
||||||
{400, "Light Smasher"_s},
|
{400, "Light Smasher"_s},
|
||||||
{401, "Light Basher"_s},
|
{401, "Light Basher"_s},
|
||||||
|
@ -173,13 +164,14 @@ static const std::map<std::int32_t, Containers::StringView> melee_assaulters {
|
||||||
{404, "Light Diamond Smasher"_s},
|
{404, "Light Diamond Smasher"_s},
|
||||||
{405, "Light Spinning Smasher"_s},
|
{405, "Light Spinning Smasher"_s},
|
||||||
{406, "Base S Mace"_s},
|
{406, "Base S Mace"_s},
|
||||||
|
|
||||||
{420, "War Hammer"_s},
|
{420, "War Hammer"_s},
|
||||||
{421, "Great Hammer"_s},
|
{421, "Great Hammer"_s},
|
||||||
{422, "Spiked Hammer"_s},
|
{422, "Spiked Hammer"_s},
|
||||||
{423, "Broadhead Hammer"_s},
|
{423, "Broadhead Hammer"_s},
|
||||||
|
|
||||||
{440, "Morning Star"_s},
|
{440, "Morning Star"_s},
|
||||||
{441, "Spike Ball"_s},
|
{441, "Spike Ball"_s},
|
||||||
{496, "<hidden light mace>"_s},
|
|
||||||
|
|
||||||
{500, "Combat Lance"_s},
|
{500, "Combat Lance"_s},
|
||||||
{501, "Gouger Lance"_s},
|
{501, "Gouger Lance"_s},
|
||||||
|
@ -187,7 +179,6 @@ static const std::map<std::int32_t, Containers::StringView> melee_assaulters {
|
||||||
{503, "Spinning Pointy Lance (Motion)"_s},
|
{503, "Spinning Pointy Lance (Motion)"_s},
|
||||||
{504, "Crystal Lance"_s},
|
{504, "Crystal Lance"_s},
|
||||||
{510, "Piercer"_s},
|
{510, "Piercer"_s},
|
||||||
{596, "<hidden lance>"_s},
|
|
||||||
|
|
||||||
{600, "Short Combat Lance"_s},
|
{600, "Short Combat Lance"_s},
|
||||||
{601, "Short Pointy Lance"_s},
|
{601, "Short Pointy Lance"_s},
|
||||||
|
@ -195,7 +186,6 @@ static const std::map<std::int32_t, Containers::StringView> melee_assaulters {
|
||||||
{603, "Short Crystal Lance"_s},
|
{603, "Short Crystal Lance"_s},
|
||||||
{605, "Short Combat Drill (Motion)"_s},
|
{605, "Short Combat Drill (Motion)"_s},
|
||||||
{610, "Short Piercer"_s},
|
{610, "Short Piercer"_s},
|
||||||
{696, "<hidden short lance>"_s},
|
|
||||||
|
|
||||||
{700, "Combat Axe"_s},
|
{700, "Combat Axe"_s},
|
||||||
{701, "Custom Combat Axe"_s},
|
{701, "Custom Combat Axe"_s},
|
||||||
|
@ -203,21 +193,18 @@ static const std::map<std::int32_t, Containers::StringView> melee_assaulters {
|
||||||
{703, "Frontbreak Axe"_s},
|
{703, "Frontbreak Axe"_s},
|
||||||
{704, "Maiming Axe"_s},
|
{704, "Maiming Axe"_s},
|
||||||
{705, "Delta Axe"_s},
|
{705, "Delta Axe"_s},
|
||||||
{796, "<hidden axe>"_s},
|
|
||||||
|
|
||||||
{800, "Combat Scythe"_s},
|
{800, "Combat Scythe"_s},
|
||||||
{801, "Reaper Blade"_s},
|
{801, "Reaper Blade"_s},
|
||||||
{802, "Clawtooth Scythe"_s},
|
{802, "Clawtooth Scythe"_s},
|
||||||
{803, "Wingpoint Scythe"_s},
|
{803, "Wingpoint Scythe"_s},
|
||||||
{804, "Snakebone Scythe"_s},
|
{804, "Snakebone Scythe"_s},
|
||||||
{896, "<hidden scythe>"_s},
|
|
||||||
|
|
||||||
{900, "Short Combat Scythe"_s},
|
{900, "Short Combat Scythe"_s},
|
||||||
{901, "Short Reaper Blade"_s},
|
{901, "Short Reaper Blade"_s},
|
||||||
{902, "Short Clawtooth Scythe"_s},
|
{902, "Short Clawtooth Scythe"_s},
|
||||||
{903, "Short Wingpoint Scythe"_s},
|
{903, "Short Wingpoint Scythe"_s},
|
||||||
{904, "Short Snakebone Scythe"_s},
|
{904, "Short Snakebone Scythe"_s},
|
||||||
{996, "<hidden short scythe>"_s},
|
|
||||||
};
|
};
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
@ -236,7 +223,7 @@ static const std::map<std::int32_t, Containers::StringView> shield_handles {
|
||||||
{10, "Board Handle"_s},
|
{10, "Board Handle"_s},
|
||||||
{11, "Knight Handle"_s},
|
{11, "Knight Handle"_s},
|
||||||
{12, "Cargwall Handle"_s},
|
{12, "Cargwall Handle"_s},
|
||||||
{96, "<hidden handle>"_s},
|
|
||||||
{100, "Buckler Handle"_s},
|
{100, "Buckler Handle"_s},
|
||||||
{101, "Star Handle"_s},
|
{101, "Star Handle"_s},
|
||||||
};
|
};
|
||||||
|
@ -256,7 +243,7 @@ static const std::map<std::int32_t, Containers::StringView> shield_shells {
|
||||||
{11, "Parted Shell"_s},
|
{11, "Parted Shell"_s},
|
||||||
{12, "Tapst Shell"_s},
|
{12, "Tapst Shell"_s},
|
||||||
{13, "Sidloc Shell"_s},
|
{13, "Sidloc Shell"_s},
|
||||||
{96, "<hidden shell>"_s},
|
|
||||||
{100, "V-Cross Shell"_s},
|
{100, "V-Cross Shell"_s},
|
||||||
};
|
};
|
||||||
// endregion
|
// endregion
|
||||||
|
@ -270,7 +257,6 @@ static const std::map<std::int32_t, Containers::StringView> bshooter_triggers {
|
||||||
{4, "Longhold Trigger (1H)"_s},
|
{4, "Longhold Trigger (1H)"_s},
|
||||||
{5, "Downhold Trigger (1H)"_s},
|
{5, "Downhold Trigger (1H)"_s},
|
||||||
{6, "Cellblock Trigger (1H)"_s},
|
{6, "Cellblock Trigger (1H)"_s},
|
||||||
{96, "<hidden trigger> (1H)"_s},
|
|
||||||
{99, "Base Trigger (1H)"_s},
|
{99, "Base Trigger (1H)"_s},
|
||||||
|
|
||||||
{100, "BL-Machine Trigger (2H)"_s},
|
{100, "BL-Machine Trigger (2H)"_s},
|
||||||
|
@ -278,7 +264,6 @@ static const std::map<std::int32_t, Containers::StringView> bshooter_triggers {
|
||||||
{102, "Shielded Trigger (2H)"_s},
|
{102, "Shielded Trigger (2H)"_s},
|
||||||
{103, "Platedframe Trigger (2H)"_s},
|
{103, "Platedframe Trigger (2H)"_s},
|
||||||
{104, "Sidebox Trigger (2H) (Motion)"_s},
|
{104, "Sidebox Trigger (2H) (Motion)"_s},
|
||||||
{196, "<hidden trigger> (2H)"_s},
|
|
||||||
{199, "2H Base Trigger (2H)"_s},
|
{199, "2H Base Trigger (2H)"_s},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -288,7 +273,6 @@ static const std::map<std::int32_t, Containers::StringView> bshooter_barrels {
|
||||||
{2, "Muzzlemod Barrel (1 shot)"_s},
|
{2, "Muzzlemod Barrel (1 shot)"_s},
|
||||||
{3, "Triangular Barrel (1 shot)"_s},
|
{3, "Triangular Barrel (1 shot)"_s},
|
||||||
{4, "Recoilblock Barrel (1 shot) (Motion)"_s},
|
{4, "Recoilblock Barrel (1 shot) (Motion)"_s},
|
||||||
{96, "<hidden barrel> (1 shot)"_s},
|
|
||||||
{97, "Short S Base Barrel (1 shot)"_s},
|
{97, "Short S Base Barrel (1 shot)"_s},
|
||||||
{98, "Medium S Base Barrel (1 shot)"_s},
|
{98, "Medium S Base Barrel (1 shot)"_s},
|
||||||
{99, "Long S Base Barrel (1 shot)"_s},
|
{99, "Long S Base Barrel (1 shot)"_s},
|
||||||
|
@ -297,7 +281,6 @@ static const std::map<std::int32_t, Containers::StringView> bshooter_barrels {
|
||||||
{101, "Modded Six-Barrel Gatling (Auto) (Motion)"_s},
|
{101, "Modded Six-Barrel Gatling (Auto) (Motion)"_s},
|
||||||
{102, "Four-Barrel Gatling (Auto) (Motion)"_s},
|
{102, "Four-Barrel Gatling (Auto) (Motion)"_s},
|
||||||
{103, "Retro Style Gatling (Auto) (Motion)"_s},
|
{103, "Retro Style Gatling (Auto) (Motion)"_s},
|
||||||
{196, "<hidden barrel> (Auto)"_s},
|
|
||||||
{197, "Short G Base Barrel (Auto)"_s},
|
{197, "Short G Base Barrel (Auto)"_s},
|
||||||
{198, "Medium G Base Barrel (Auto)"_s},
|
{198, "Medium G Base Barrel (Auto)"_s},
|
||||||
{199, "Long G Base Barrel (Auto)"_s},
|
{199, "Long G Base Barrel (Auto)"_s},
|
||||||
|
@ -306,7 +289,6 @@ static const std::map<std::int32_t, Containers::StringView> bshooter_barrels {
|
||||||
{201, "Wideblast Barrel (Spread) (Motion)"_s},
|
{201, "Wideblast Barrel (Spread) (Motion)"_s},
|
||||||
{202, "Pelleter Barrel (Spread) (Motion)"_s},
|
{202, "Pelleter Barrel (Spread) (Motion)"_s},
|
||||||
{203, "Lockhold Barrel (Spread) (Motion)"_s},
|
{203, "Lockhold Barrel (Spread) (Motion)"_s},
|
||||||
{296, "<hidden barrel> (Spread)"_s},
|
|
||||||
{297, "Short B Base Barrel (Spread)"_s},
|
{297, "Short B Base Barrel (Spread)"_s},
|
||||||
{298, "Medium B Base Barrel (Spread)"_s},
|
{298, "Medium B Base Barrel (Spread)"_s},
|
||||||
{299, "Long B Base Barrel (Spread)"_s},
|
{299, "Long B Base Barrel (Spread)"_s},
|
||||||
|
@ -315,7 +297,6 @@ static const std::map<std::int32_t, Containers::StringView> bshooter_barrels {
|
||||||
{301, "Roundbox Barrel (Detonate)"_s},
|
{301, "Roundbox Barrel (Detonate)"_s},
|
||||||
{302, "ShieldDet Barrel (Detonate)"_s},
|
{302, "ShieldDet Barrel (Detonate)"_s},
|
||||||
{303, "RecoilDet Barrel (Detonate) (Motion)"_s},
|
{303, "RecoilDet Barrel (Detonate) (Motion)"_s},
|
||||||
{396, "<hidden barrel> (Detonate)"_s},
|
|
||||||
{397, "Short D Base Barrel (Detonate)"_s},
|
{397, "Short D Base Barrel (Detonate)"_s},
|
||||||
{398, "Medium D Base Barrel (Detonate)"_s},
|
{398, "Medium D Base Barrel (Detonate)"_s},
|
||||||
{399, "Long D Base Barrel (Detonate)"_s},
|
{399, "Long D Base Barrel (Detonate)"_s},
|
||||||
|
@ -323,7 +304,6 @@ static const std::map<std::int32_t, Containers::StringView> bshooter_barrels {
|
||||||
{400, "Heavy Burst Barrel (Pile Bunker) (Motion)"_s},
|
{400, "Heavy Burst Barrel (Pile Bunker) (Motion)"_s},
|
||||||
{401, "Under Guard Barrel (Pile Bunker) (Motion)"_s},
|
{401, "Under Guard Barrel (Pile Bunker) (Motion)"_s},
|
||||||
{402, "Facthold Barrel (Pile Bunker) (Motion)"_s},
|
{402, "Facthold Barrel (Pile Bunker) (Motion)"_s},
|
||||||
{496, "<hidden barrel> (Pile Bunker)"_s},
|
|
||||||
{499, "Long P Base Barrel (Pile Bunker) (Motion)"_s},
|
{499, "Long P Base Barrel (Pile Bunker) (Motion)"_s},
|
||||||
};
|
};
|
||||||
// endregion
|
// endregion
|
||||||
|
@ -337,7 +317,6 @@ static const std::map<std::int32_t, Containers::StringView> eshooter_triggers {
|
||||||
{4, "EN-Needler Trigger (1H)"_s},
|
{4, "EN-Needler Trigger (1H)"_s},
|
||||||
{5, "Angular Trigger (1H)"_s},
|
{5, "Angular Trigger (1H)"_s},
|
||||||
{6, "Exposed Trigger (1H)"_s},
|
{6, "Exposed Trigger (1H)"_s},
|
||||||
{96, "<hidden trigger> (1H)"_s},
|
|
||||||
{99, "Base EnTrigger (1H)"_s},
|
{99, "Base EnTrigger (1H)"_s},
|
||||||
|
|
||||||
{100, "EN-Combat Trigger (2H)"_s},
|
{100, "EN-Combat Trigger (2H)"_s},
|
||||||
|
@ -345,7 +324,6 @@ static const std::map<std::int32_t, Containers::StringView> eshooter_triggers {
|
||||||
{102, "Framed Trigger (2H) (Motion)"_s},
|
{102, "Framed Trigger (2H) (Motion)"_s},
|
||||||
{103, "Stabilised Trigger (2H)"_s},
|
{103, "Stabilised Trigger (2H)"_s},
|
||||||
{104, "EN-Heavy Trigger (2H)"_s},
|
{104, "EN-Heavy Trigger (2H)"_s},
|
||||||
{196, "<hidden trigger> (2H)"_s},
|
|
||||||
{199, "2H Base EnTrigger (2H)"_s},
|
{199, "2H Base EnTrigger (2H)"_s},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -354,7 +332,6 @@ static const std::map<std::int32_t, Containers::StringView> eshooter_busters {
|
||||||
{1, "Delta Cycler (1 shot) (Motion)"_s},
|
{1, "Delta Cycler (1 shot) (Motion)"_s},
|
||||||
{2, "EN-Longbarrel Buster (1 shot)"_s},
|
{2, "EN-Longbarrel Buster (1 shot)"_s},
|
||||||
{3, "Kinetic Buster (1 shot) (Motion)"_s},
|
{3, "Kinetic Buster (1 shot) (Motion)"_s},
|
||||||
{96, "<hidden buster> (1 shot)"_s},
|
|
||||||
{97, "Short S Base Buster (1 shot)"_s},
|
{97, "Short S Base Buster (1 shot)"_s},
|
||||||
{98, "Medium S Base Buster (1 shot)"_s},
|
{98, "Medium S Base Buster (1 shot)"_s},
|
||||||
{99, "Long S Base Buster (1 shot)"_s},
|
{99, "Long S Base Buster (1 shot)"_s},
|
||||||
|
@ -363,7 +340,6 @@ static const std::map<std::int32_t, Containers::StringView> eshooter_busters {
|
||||||
{101, "EN-Focus Buster (Auto)"_s},
|
{101, "EN-Focus Buster (Auto)"_s},
|
||||||
{102, "Machinist Buster (Auto)"_s},
|
{102, "Machinist Buster (Auto)"_s},
|
||||||
{103, "EN-Precision Buster (Auto) (Motion)"_s},
|
{103, "EN-Precision Buster (Auto) (Motion)"_s},
|
||||||
{196, "<hidden buster> (Auto)"_s},
|
|
||||||
{197, "Short A Base Buster (Auto)"_s},
|
{197, "Short A Base Buster (Auto)"_s},
|
||||||
{198, "Medium A Base Buster (Auto)"_s},
|
{198, "Medium A Base Buster (Auto)"_s},
|
||||||
{199, "Long A Base Buster (Auto)"_s},
|
{199, "Long A Base Buster (Auto)"_s},
|
||||||
|
@ -372,7 +348,6 @@ static const std::map<std::int32_t, Containers::StringView> eshooter_busters {
|
||||||
{201, "Clawcharge Buster (Ray)"_s},
|
{201, "Clawcharge Buster (Ray)"_s},
|
||||||
{202, "Twizelcharge Buster (Ray)"_s},
|
{202, "Twizelcharge Buster (Ray)"_s},
|
||||||
{203, "Deltacharge Buster (Ray)"_s},
|
{203, "Deltacharge Buster (Ray)"_s},
|
||||||
{296, "<hidden buster> (Ray)"_s},
|
|
||||||
{297, "Short R Base Buster (Ray)"_s},
|
{297, "Short R Base Buster (Ray)"_s},
|
||||||
{298, "Medium R Base Buster (Ray)"_s},
|
{298, "Medium R Base Buster (Ray)"_s},
|
||||||
{299, "Long R Base Buster (Ray)"_s},
|
{299, "Long R Base Buster (Ray)"_s},
|
||||||
|
@ -381,7 +356,6 @@ static const std::map<std::int32_t, Containers::StringView> eshooter_busters {
|
||||||
{301, "Amplifier Buster (Wave) (Motion)"_s},
|
{301, "Amplifier Buster (Wave) (Motion)"_s},
|
||||||
{302, "Cyclonwave Buster (Wave)"_s},
|
{302, "Cyclonwave Buster (Wave)"_s},
|
||||||
{303, "Warhorn Buster (Wave) (Motion)"_s},
|
{303, "Warhorn Buster (Wave) (Motion)"_s},
|
||||||
{396, "<hidden buster> (Wave)"_s},
|
|
||||||
{397, "Short W Base Buster (Wave)"_s},
|
{397, "Short W Base Buster (Wave)"_s},
|
||||||
{398, "Medium W Base Buster (Wave)"_s},
|
{398, "Medium W Base Buster (Wave)"_s},
|
||||||
{399, "Long W Base Buster (Wave)"_s},
|
{399, "Long W Base Buster (Wave)"_s},
|
||||||
|
@ -389,7 +363,6 @@ static const std::map<std::int32_t, Containers::StringView> eshooter_busters {
|
||||||
{400, "Wiredcharge Buster (Prism) (Motion)"_s},
|
{400, "Wiredcharge Buster (Prism) (Motion)"_s},
|
||||||
{402, "Heavyclamp Buster (Prism) (Motion)"_s},
|
{402, "Heavyclamp Buster (Prism) (Motion)"_s},
|
||||||
{402, "Curlescent Buster (Prism) (Motion)"_s},
|
{402, "Curlescent Buster (Prism) (Motion)"_s},
|
||||||
{496, "<hidden buster> (Prism)"_s},
|
|
||||||
{499, "Long P Base Buster (Prism) (Motion)"_s},
|
{499, "Long P Base Buster (Prism) (Motion)"_s},
|
||||||
};
|
};
|
||||||
// endregion
|
// endregion
|
||||||
|
@ -401,7 +374,6 @@ static const std::map<std::int32_t, Containers::StringView> blauncher_pods {
|
||||||
{2, "Detector Launcher (Missile x12)"_s},
|
{2, "Detector Launcher (Missile x12)"_s},
|
||||||
{3, "BL-Triplet Pack Launcher (Missile x12)"_s},
|
{3, "BL-Triplet Pack Launcher (Missile x12)"_s},
|
||||||
{4, "Shielded Launcher (Missile x12)"_s},
|
{4, "Shielded Launcher (Missile x12)"_s},
|
||||||
{96, "<hidden launcher> (Missile x12)"_s},
|
|
||||||
{99, "H Base Pod (Missile x12)"_s},
|
{99, "H Base Pod (Missile x12)"_s},
|
||||||
|
|
||||||
{100, "Warhead Pod (Nuke x2)"_s},
|
{100, "Warhead Pod (Nuke x2)"_s},
|
||||||
|
@ -409,7 +381,6 @@ static const std::map<std::int32_t, Containers::StringView> blauncher_pods {
|
||||||
{102, "Triangular Warhead Pod (Nuke x2)"_s},
|
{102, "Triangular Warhead Pod (Nuke x2)"_s},
|
||||||
{103, "Expanded Warhead Pod (Nuke x2)"_s},
|
{103, "Expanded Warhead Pod (Nuke x2)"_s},
|
||||||
{104, "Shielded Warhead Pod (Nuke x2)"_s},
|
{104, "Shielded Warhead Pod (Nuke x2)"_s},
|
||||||
{196, "<hidden launcher> (Nuke x2)"_s},
|
|
||||||
{199, "N Base Pod (Nuke x2)"_s},
|
{199, "N Base Pod (Nuke x2)"_s},
|
||||||
|
|
||||||
{200, "Widepack Launcher (Salvo x24)"_s},
|
{200, "Widepack Launcher (Salvo x24)"_s},
|
||||||
|
@ -417,7 +388,6 @@ static const std::map<std::int32_t, Containers::StringView> blauncher_pods {
|
||||||
{202, "Double Delta Launcher (Salvo x24)"_s},
|
{202, "Double Delta Launcher (Salvo x24)"_s},
|
||||||
{203, "Hexagonal Launcher (Salvo x24)"_s},
|
{203, "Hexagonal Launcher (Salvo x24)"_s},
|
||||||
{204, "Shielded Six Launcher (Salvo x24)"_s},
|
{204, "Shielded Six Launcher (Salvo x24)"_s},
|
||||||
{296, "<hidden launcher> (Salvo x24)"_s},
|
|
||||||
{299, "S Base Pod (Salvo x24)"_s},
|
{299, "S Base Pod (Salvo x24)"_s},
|
||||||
|
|
||||||
{300, "Sentinel Cluster Pod (Cluster x40)"_s},
|
{300, "Sentinel Cluster Pod (Cluster x40)"_s},
|
||||||
|
@ -425,7 +395,6 @@ static const std::map<std::int32_t, Containers::StringView> blauncher_pods {
|
||||||
{302, "Elliptical Cluster Pod (Cluster x40)"_s},
|
{302, "Elliptical Cluster Pod (Cluster x40)"_s},
|
||||||
{303, "Sawed Cluster Pod (Cluster x40)"_s},
|
{303, "Sawed Cluster Pod (Cluster x40)"_s},
|
||||||
{304, "Pentagonal Cluster Pod (Cluster x40)"_s},
|
{304, "Pentagonal Cluster Pod (Cluster x40)"_s},
|
||||||
{396, "<hidden launcher> (Cluster x40)"_s},
|
|
||||||
{399, "C Base Pod (Cluster x40)"_s},
|
{399, "C Base Pod (Cluster x40)"_s},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -435,7 +404,6 @@ static const std::map<std::int32_t, Containers::StringView> blauncher_projectile
|
||||||
{2, "Pointhead Missile"_s},
|
{2, "Pointhead Missile"_s},
|
||||||
{3, "Marker Missile"_s},
|
{3, "Marker Missile"_s},
|
||||||
{4, "ArB Missile"_s},
|
{4, "ArB Missile"_s},
|
||||||
{96, "<hidden missile>"_s},
|
|
||||||
};
|
};
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
@ -469,8 +437,7 @@ static const std::map<std::int32_t, Containers::StringView> elauncher_generators
|
||||||
{25, "Carrier Unit"_s},
|
{25, "Carrier Unit"_s},
|
||||||
{26, "Compartment Unit"_s},
|
{26, "Compartment Unit"_s},
|
||||||
{27, "Flatedge Unit"_s},
|
{27, "Flatedge Unit"_s},
|
||||||
{96, "<hidden generator>"_s},
|
{99, "Base Generator"},
|
||||||
{99, "Base Generator"_s},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::map<std::int32_t, Containers::StringView> elauncher_pods {
|
static const std::map<std::int32_t, Containers::StringView> elauncher_pods {
|
||||||
|
@ -481,7 +448,6 @@ static const std::map<std::int32_t, Containers::StringView> elauncher_pods {
|
||||||
{4, "EN-Needler Launcher (Echo)"_s},
|
{4, "EN-Needler Launcher (Echo)"_s},
|
||||||
{5, "Spark Launcher (Echo)"_s},
|
{5, "Spark Launcher (Echo)"_s},
|
||||||
{6, "Pinpoint Launcher (Echo)"_s},
|
{6, "Pinpoint Launcher (Echo)"_s},
|
||||||
{96, "<hidden pod> (Echo)"_s},
|
|
||||||
{99, "E Base EPod (Echo)"_s},
|
{99, "E Base EPod (Echo)"_s},
|
||||||
|
|
||||||
{100, "Raystream Launcher (Beam)"_s},
|
{100, "Raystream Launcher (Beam)"_s},
|
||||||
|
@ -491,7 +457,6 @@ static const std::map<std::int32_t, Containers::StringView> elauncher_pods {
|
||||||
{104, "Crosshair Launcher (Beam)"_s},
|
{104, "Crosshair Launcher (Beam)"_s},
|
||||||
{105, "Powerlined Launcher (Beam)"_s},
|
{105, "Powerlined Launcher (Beam)"_s},
|
||||||
{106, "Attached Launcher (Beam)"_s},
|
{106, "Attached Launcher (Beam)"_s},
|
||||||
{196, "<hidden pod> (Beam)"_s},
|
|
||||||
{199, "B Base EPod (Beam)"_s},
|
{199, "B Base EPod (Beam)"_s},
|
||||||
|
|
||||||
{200, "Hilt Launcher (Slash) (Motion)"_s},
|
{200, "Hilt Launcher (Slash) (Motion)"_s},
|
||||||
|
@ -501,7 +466,6 @@ static const std::map<std::int32_t, Containers::StringView> elauncher_pods {
|
||||||
{204, "Spike Launcher (Slash)"_s},
|
{204, "Spike Launcher (Slash)"_s},
|
||||||
{205, "Tri-Pronged Launcher (Slash) (Motion)"_s},
|
{205, "Tri-Pronged Launcher (Slash) (Motion)"_s},
|
||||||
{206, "Heavyblade Launcher (Slash)"_s},
|
{206, "Heavyblade Launcher (Slash)"_s},
|
||||||
{296, "<hidden pod> (Slash)"_s},
|
|
||||||
{299, "S Base EPod (Slash)"_s},
|
{299, "S Base EPod (Slash)"_s},
|
||||||
|
|
||||||
{300, "Covering Launcher (Photon)"_s},
|
{300, "Covering Launcher (Photon)"_s},
|
||||||
|
@ -511,7 +475,6 @@ static const std::map<std::int32_t, Containers::StringView> elauncher_pods {
|
||||||
{304, "Shelled Launcher (Photon)"_s},
|
{304, "Shelled Launcher (Photon)"_s},
|
||||||
{305, "Widearm Launcher (Photon)"_s},
|
{305, "Widearm Launcher (Photon)"_s},
|
||||||
{306, "Wingspan Launcher (Photon)"_s},
|
{306, "Wingspan Launcher (Photon)"_s},
|
||||||
{396, "<hidden pod> (Photon)"_s},
|
|
||||||
{399, "P Base EPod (Photon)"_s},
|
{399, "P Base EPod (Photon)"_s},
|
||||||
};
|
};
|
||||||
// endregion
|
// endregion
|
||||||
|
|
127
src/ImportExport/Export.cpp
Normal file
127
src/ImportExport/Export.cpp
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2024 Guillaume Jacquemin
|
||||||
|
//
|
||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <Corrade/Utility/Format.h>
|
||||||
|
#include <Corrade/Utility/Path.h>
|
||||||
|
|
||||||
|
#include "../Logger/Logger.h"
|
||||||
|
#include "../BinaryIo/Writer.h"
|
||||||
|
#include "../Configuration/Configuration.h"
|
||||||
|
#include "../Utilities/Crc32.h"
|
||||||
|
|
||||||
|
#include "Keys.h"
|
||||||
|
|
||||||
|
#include "Export.h"
|
||||||
|
|
||||||
|
namespace mbst::ImportExport {
|
||||||
|
|
||||||
|
static Containers::String last_export_error;
|
||||||
|
|
||||||
|
Containers::StringView
|
||||||
|
lastExportError() {
|
||||||
|
return last_export_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
exportStyle(Containers::StringView mass_name, mbst::GameObjects::CustomStyle& style) {
|
||||||
|
Containers::String style_type_str;
|
||||||
|
switch(style.type) {
|
||||||
|
case GameObjects::CustomStyle::Type::Unknown:
|
||||||
|
style_type_str = "Style";
|
||||||
|
break;
|
||||||
|
case GameObjects::CustomStyle::Type::Frame:
|
||||||
|
style_type_str = "FrameStyle";
|
||||||
|
break;
|
||||||
|
case GameObjects::CustomStyle::Type::Armour:
|
||||||
|
style_type_str = "ArmourStyle";
|
||||||
|
break;
|
||||||
|
case GameObjects::CustomStyle::Type::Weapon:
|
||||||
|
style_type_str = "WeaponStyle";
|
||||||
|
break;
|
||||||
|
case GameObjects::CustomStyle::Type::Global:
|
||||||
|
style_type_str = "GlobalStyle";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto filename = Utility::format("{}_{}_{}.style.mbst", mass_name, style_type_str, style.name);
|
||||||
|
for(auto& c : filename) {
|
||||||
|
if(c == ' ') {
|
||||||
|
c = '_';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto path = Utility::Path::join(conf().directories().styles, filename);
|
||||||
|
BinaryIo::Writer writer{path};
|
||||||
|
|
||||||
|
if(!writer.open()) {
|
||||||
|
last_export_error = path + " couldn't be opened.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!writer.writeString("MBSTSTYLE")) {
|
||||||
|
LOG_ERROR(last_export_error = "Couldn't write magic bytes into " + filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeValueToArray<Keys::CustomStyle>(Keys::CustomStyle::Name);
|
||||||
|
writer.writeUEStringToArray(style.name);
|
||||||
|
|
||||||
|
writer.writeValueToArray<Keys::CustomStyle>(Keys::CustomStyle::Colour);
|
||||||
|
writer.writeValueToArray<Color4>(style.colour);
|
||||||
|
writer.writeValueToArray<Keys::CustomStyle>(Keys::CustomStyle::Metallic);
|
||||||
|
writer.writeValueToArray<float>(style.metallic);
|
||||||
|
writer.writeValueToArray<Keys::CustomStyle>(Keys::CustomStyle::Gloss);
|
||||||
|
writer.writeValueToArray<float>(style.gloss);
|
||||||
|
writer.writeValueToArray<Keys::CustomStyle>(Keys::CustomStyle::Glow);
|
||||||
|
writer.writeValueToArray<bool>(style.glow);
|
||||||
|
|
||||||
|
writer.writeValueToArray<Keys::CustomStyle>(Keys::CustomStyle::PatternId);
|
||||||
|
writer.writeValueToArray<std::int32_t>(style.patternId);
|
||||||
|
writer.writeValueToArray<Keys::CustomStyle>(Keys::CustomStyle::PatternOpacity);
|
||||||
|
writer.writeValueToArray<float>(style.opacity);
|
||||||
|
writer.writeValueToArray<Keys::CustomStyle>(Keys::CustomStyle::PatternOffset);
|
||||||
|
writer.writeValueToArray<Vector2>(style.offset);
|
||||||
|
writer.writeValueToArray<Keys::CustomStyle>(Keys::CustomStyle::PatternRotation);
|
||||||
|
writer.writeValueToArray<float>(style.rotation);
|
||||||
|
writer.writeValueToArray<Keys::CustomStyle>(Keys::CustomStyle::PatternScale);
|
||||||
|
writer.writeValueToArray<float>(style.scale);
|
||||||
|
|
||||||
|
if(!writer.writeUint64(writer.array().size())) {
|
||||||
|
LOG_ERROR(last_export_error = "Couldn't write data size into " + filename);
|
||||||
|
writer.closeFile();
|
||||||
|
Utility::Path::remove(path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto crc = Utilities::crc32(0, writer.array());
|
||||||
|
if(!writer.writeUint32(crc)) {
|
||||||
|
LOG_ERROR(last_export_error = "Couldn't write CRC32 checksum into " + filename);
|
||||||
|
writer.closeFile();
|
||||||
|
Utility::Path::remove(path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!writer.flushToFile()) {
|
||||||
|
LOG_ERROR(last_export_error = "Couldn't write data into " + filename);
|
||||||
|
writer.closeFile();
|
||||||
|
Utility::Path::remove(path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
src/ImportExport/Export.h
Normal file
31
src/ImportExport/Export.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2024 Guillaume Jacquemin
|
||||||
|
//
|
||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <Corrade/Containers/StringView.h>
|
||||||
|
|
||||||
|
#include "../GameObjects/CustomStyle.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
|
||||||
|
namespace mbst::ImportExport {
|
||||||
|
|
||||||
|
auto lastExportError() -> Containers::StringView;
|
||||||
|
|
||||||
|
bool exportStyle(Containers::StringView mass_name, GameObjects::CustomStyle& style);
|
||||||
|
|
||||||
|
}
|
186
src/ImportExport/Import.cpp
Normal file
186
src/ImportExport/Import.cpp
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2024 Guillaume Jacquemin
|
||||||
|
//
|
||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <Corrade/Containers/Array.h>
|
||||||
|
#include <Corrade/Containers/Optional.h>
|
||||||
|
#include <Corrade/Containers/String.h>
|
||||||
|
#include <Corrade/Utility/Path.h>
|
||||||
|
|
||||||
|
#include "../BinaryIo/Reader.h"
|
||||||
|
#include "../Configuration/Configuration.h"
|
||||||
|
#include "../Logger/Logger.h"
|
||||||
|
#include "../Utilities/Crc32.h"
|
||||||
|
|
||||||
|
#include "Keys.h"
|
||||||
|
|
||||||
|
#include "Import.h"
|
||||||
|
|
||||||
|
namespace mbst::ImportExport {
|
||||||
|
|
||||||
|
static Containers::String last_import_error;
|
||||||
|
|
||||||
|
Containers::StringView
|
||||||
|
lastImportError() {
|
||||||
|
return last_import_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
Containers::Optional<GameObjects::CustomStyle>
|
||||||
|
importStyle(Containers::StringView filename) {
|
||||||
|
auto path = Utility::Path::join(conf().directories().styles, filename);
|
||||||
|
if(!Utility::Path::exists(path)) {
|
||||||
|
LOG_ERROR(last_import_error = path + " doesn't exist.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryIo::Reader reader{path};
|
||||||
|
if(!reader.open()) {
|
||||||
|
last_import_error = path + " couldn't be opened.";
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Containers::Array<char> magic_bytes;
|
||||||
|
if(!reader.readArray(magic_bytes, 9)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read the magic bytes.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Containers::StringView magic_bytes_view = magic_bytes;
|
||||||
|
static const auto expected_magic_bytes = "MBSTSTYLE"_s;
|
||||||
|
if(magic_bytes_view != expected_magic_bytes) {
|
||||||
|
LOG_ERROR(last_import_error = "Magic bytes are mismatched.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t data_size;
|
||||||
|
if(!reader.readUint64(data_size)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read data size.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t crc;
|
||||||
|
if(!reader.readUint32(crc)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read CRC-32 checksum.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto position = reader.position();
|
||||||
|
|
||||||
|
{
|
||||||
|
Containers::Array<char> data;
|
||||||
|
if(!reader.readArray(data, data_size)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read data.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto computed_crc = Utilities::crc32(0, data);
|
||||||
|
if(computed_crc != crc) {
|
||||||
|
LOG_ERROR(last_import_error = Utility::format("CRC-32 checksum doesn't match. "
|
||||||
|
"Expected {}, got {} instead.",
|
||||||
|
crc, computed_crc));
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reader.seek(position)) {
|
||||||
|
LOG_ERROR(last_import_error = Utility::format("Couldn't seek to position {}.", position));
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObjects::CustomStyle style{};
|
||||||
|
|
||||||
|
while(!reader.eof()) {
|
||||||
|
Keys::CustomStyle key;
|
||||||
|
if(!reader.readValue(key)) {
|
||||||
|
if(reader.eof()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read key.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(key) {
|
||||||
|
case Keys::Name:
|
||||||
|
if(!reader.readUEString(style.name)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read style name.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Keys::Colour:
|
||||||
|
if(!reader.readValue<Color4>(style.colour)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read style colour.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Keys::Metallic:
|
||||||
|
if(!reader.readFloat(style.metallic)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read style metallic.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Keys::Gloss:
|
||||||
|
if(!reader.readFloat(style.gloss)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read style gloss.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Keys::Glow:
|
||||||
|
if(!reader.readValue(style.glow)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read style glow.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Keys::PatternId:
|
||||||
|
if(!reader.readInt32(style.patternId)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read style pattern ID.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Keys::PatternOpacity:
|
||||||
|
if(!reader.readFloat(style.opacity)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read style pattern opacity.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Keys::PatternOffset:
|
||||||
|
if(!reader.readValue(style.offset)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read style pattern offset.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Keys::PatternRotation:
|
||||||
|
if(!reader.readFloat(style.rotation)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read style pattern rotation.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Keys::PatternScale:
|
||||||
|
if(!reader.readFloat(style.scale)) {
|
||||||
|
LOG_ERROR(last_import_error = "Couldn't read style pattern scale.");
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR(last_import_error = Utility::format("Unknown key {}.", key));
|
||||||
|
return Containers::NullOpt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Utility::move(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
src/ImportExport/Import.h
Normal file
31
src/ImportExport/Import.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2024 Guillaume Jacquemin
|
||||||
|
//
|
||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <Corrade/Containers/StringView.h>
|
||||||
|
|
||||||
|
#include "../GameObjects/CustomStyle.h"
|
||||||
|
|
||||||
|
using namespace Corrade;
|
||||||
|
|
||||||
|
namespace mbst::ImportExport {
|
||||||
|
|
||||||
|
auto lastImportError() -> Containers::StringView;
|
||||||
|
|
||||||
|
auto importStyle(Containers::StringView filename) -> Containers::Optional<GameObjects::CustomStyle>;
|
||||||
|
|
||||||
|
}
|
36
src/ImportExport/Keys.h
Normal file
36
src/ImportExport/Keys.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// MassBuilderSaveTool
|
||||||
|
// Copyright (C) 2021-2024 Guillaume Jacquemin
|
||||||
|
//
|
||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace mbst::ImportExport::Keys {
|
||||||
|
|
||||||
|
enum CustomStyle: std::uint8_t {
|
||||||
|
Name = 0, // type: string
|
||||||
|
Colour = 1, // type: Magnum::Color4
|
||||||
|
Metallic = 2, // type: float
|
||||||
|
Gloss = 3, // type: float
|
||||||
|
Glow = 4, // type: bool
|
||||||
|
PatternId = 5, // type: std::int32_t
|
||||||
|
PatternOpacity = 6, // type: float
|
||||||
|
PatternOffset = 7, // type: Magnum::Vector2
|
||||||
|
PatternRotation = 8, // type: float
|
||||||
|
PatternScale = 9, // type: float
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
2
third-party/SDL
vendored
2
third-party/SDL
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 9791069d78747bbb0aeb9e62b18ecd62e728c466
|
Subproject commit 1fa6142903b88007c7b77d324ee78fad9966871a
|
2
third-party/corrade
vendored
2
third-party/corrade
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 0b13b42ca0ca437152961b42639615264a2d3a52
|
Subproject commit f966f918bd7dec95002921227b6bd68ccbdda113
|
2
third-party/curl
vendored
2
third-party/curl
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit aed732acb1252dcd096c295ef28391c99422d2fb
|
Subproject commit 9287563e86a5b2007fb67f68c075a87a93825861
|
1
third-party/efsw
vendored
Submodule
1
third-party/efsw
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 0c70ed2cd069a18d534989e8ae1c25ee39cba1f1
|
2
third-party/imgui
vendored
2
third-party/imgui
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 1d069cf43527bdf81b42289f7c385efac129c3a0
|
Subproject commit a8e96ae21a4ec10e5f02b19dd865dfffe8a98e67
|
2
third-party/libzip
vendored
2
third-party/libzip
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 6ba97d4167023c3421e37d3420490b467410d9b8
|
Subproject commit aa90b70e552709316cd2144837c3dd13b5fa1ec3
|
2
third-party/magnum
vendored
2
third-party/magnum
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 1d2a1c1b3e979ff3b8bd5eacadc780e3c1359945
|
Subproject commit a40020f3fff91dc9c59148f52adb0d48203799eb
|
2
third-party/magnum-integration
vendored
2
third-party/magnum-integration
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 697ddd2cccf17aa03987da9a2213af99cd6d4cd3
|
Subproject commit bf09698491f2061733dc263f375da1f02f41d8ec
|
Loading…
Reference in a new issue