2022-03-06 09:51:57 +01:00
// MassBuilderSaveTool
// Copyright (C) 2021-2022 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 <algorithm>
# include "../UESaveFile/Types/ArrayProperty.h"
# include "../UESaveFile/Types/ByteProperty.h"
# include "../UESaveFile/Types/GenericStructProperty.h"
# include "../UESaveFile/Types/IntProperty.h"
# include "../UESaveFile/Types/StringProperty.h"
2022-03-12 09:34:19 +01:00
# include "../UESaveFile/Types/VectorStructProperty.h"
2022-03-06 09:51:57 +01:00
# include "Mass.h"
using namespace Containers : : Literals ;
auto Mass : : armourParts ( ) - > Containers : : ArrayView < ArmourPart > {
return _armour . parts ;
}
void Mass : : getArmourParts ( ) {
auto unit_data = _mass - > at < GenericStructProperty > ( " UnitData " _s ) ;
if ( ! unit_data ) {
2022-03-30 19:51:00 +02:00
Utility : : Error { } < < " Couldn't find unit data in " < < _filename ;
2022-03-06 09:51:57 +01:00
_state = State : : Invalid ;
return ;
}
auto armour_array = unit_data - > at < ArrayProperty > ( " Armor_10_12E266C44116DDAF57E99ABB575A4B3C " _s ) ;
if ( ! armour_array ) {
2022-03-30 19:51:00 +02:00
Utility : : Error { } < < " Couldn't find the armour parts array in " < < _filename ;
2022-03-06 09:51:57 +01:00
_state = State : : Invalid ;
return ;
}
if ( armour_array - > items . size ( ) ! = _armour . parts . size ( ) ) {
2022-03-30 19:51:00 +02:00
Utility : : Error { } < < " Armour arrays are not of the same size. Expected " < < _armour . parts . size ( ) < < Utility : : Debug : : nospace < < " , got " < < armour_array - > items . size ( ) < < " instead. " ;
2022-03-06 09:51:57 +01:00
_state = State : : Invalid ;
return ;
}
for ( UnsignedInt i = 0 ; i < armour_array - > items . size ( ) ; i + + ) {
auto part_prop = armour_array - > at < GenericStructProperty > ( i ) ;
auto & part = _armour . parts [ i ] ;
auto & armour_slot = part_prop - > at < ByteProperty > ( " Slot_3_408BA56F4C9605C7E805CF91B642249C " _s ) - > enumValue ;
# define c(enumerator, strenum, name) if(armour_slot == (strenum)) { part.slot = ArmourSlot::enumerator; } else
# include "../Maps/ArmourSlots.hpp"
# undef c
{
_state = State : : Invalid ;
Utility : : Warning { } < < " Invalid armour slot enum value in getArmourParts(). " _s ;
}
part . id = part_prop - > at < IntProperty > ( " ID_5_ACD101864D3481DE96EDACACC09BDD25 " _s ) - > value ;
auto part_styles = part_prop - > at < ArrayProperty > ( " Styles_47_3E31870441DFD7DB8BEE5C85C26B365B " _s ) ;
if ( ! part_styles ) {
2022-03-30 19:51:00 +02:00
Utility : : Error { } < < " Part styles not found for part number " < < i < < " in " < < _filename ;
2022-03-06 09:51:57 +01:00
_state = State : : Invalid ;
return ;
}
if ( part_styles - > items . size ( ) ! = part . styles . size ( ) ) {
2022-03-30 19:51:00 +02:00
Utility : : Error { } < < " Part style arrays are not of the same size. Expected " < < part . styles . size ( ) < < Utility : : Debug : : nospace < < " , got " < < part_styles - > items . size ( ) < < " instead. " ;
2022-03-06 09:51:57 +01:00
_state = State : : Invalid ;
return ;
}
for ( UnsignedInt j = 0 ; j < part_styles - > items . size ( ) ; j + + ) {
part . styles [ j ] = part_styles - > at < IntProperty > ( j ) - > value ;
}
auto decals_array = part_prop - > at < ArrayProperty > ( " Decals_42_F358794A4F18497970F56BA9627D3603 " _s ) ;
if ( ! decals_array ) {
2022-03-30 19:51:00 +02:00
Utility : : Error { } < < " Part decals not found for part number " < < i < < " in " < < _filename ;
2022-03-06 09:51:57 +01:00
_state = State : : Invalid ;
return ;
}
part . decals = Containers : : Array < Decal > { decals_array - > items . size ( ) } ;
getDecals ( part . decals , decals_array ) ;
auto accs_array = part_prop - > at < ArrayProperty > ( " Accessories_52_D902DD4241FA0050C2529596255153F3 " _s ) ;
if ( ! accs_array ) {
2022-03-30 19:51:00 +02:00
Utility : : Error { } < < " Part accessories not found for part number " < < i < < " in " < < _filename ;
2022-03-06 09:51:57 +01:00
part . accessories = Containers : : Array < Accessory > { } ;
continue ;
}
if ( part . accessories . size ( ) ! = accs_array - > items . size ( ) ) {
part . accessories = Containers : : Array < Accessory > { accs_array - > items . size ( ) } ;
}
getAccessories ( part . accessories , accs_array ) ;
}
}
auto Mass : : writeArmourPart ( ArmourSlot slot ) - > bool {
auto & part = * std : : find_if ( _armour . parts . begin ( ) , _armour . parts . end ( ) , [ & slot ] ( const ArmourPart & part ) { return slot = = part . slot ; } ) ;
auto unit_data = _mass - > at < GenericStructProperty > ( " UnitData " _s ) ;
auto armour_array = unit_data - > at < ArrayProperty > ( " Armor_10_12E266C44116DDAF57E99ABB575A4B3C " _s ) ;
Containers : : StringView slot_str = nullptr ;
switch ( slot ) {
# define c(enumerator, strenum, name) case ArmourSlot::enumerator: \
slot_str = strenum ; \
break ;
# include "../Maps/ArmourSlots.hpp"
# undef c
}
GenericStructProperty * part_prop = nullptr ;
for ( UnsignedInt i = 0 ; i < armour_array - > items . size ( ) ; i + + ) {
part_prop = armour_array - > at < GenericStructProperty > ( i ) ;
2022-04-08 12:44:30 +02:00
if ( slot_str = = part_prop - > at < ByteProperty > ( " Slot_3_408BA56F4C9605C7E805CF91B642249C " _s ) - > enumValue ) {
break ;
}
else {
2022-03-06 09:51:57 +01:00
part_prop = nullptr ;
}
}
if ( ! part_prop ) {
auto prefix = " Couldn't find the armour part for slot " _s ;
switch ( slot ) {
# define c(enumerator, strenum, name) case ArmourSlot::enumerator: \
_lastError = prefix + " ArmourSlot:: " # enumerator " . " _s ; \
break ;
# include "../Maps/ArmourSlots.hpp"
# undef c
}
return false ;
}
part_prop - > at < IntProperty > ( " ID_5_ACD101864D3481DE96EDACACC09BDD25 " _s ) - > value = part . id ;
auto part_styles = part_prop - > at < ArrayProperty > ( " Styles_47_3E31870441DFD7DB8BEE5C85C26B365B " _s ) ;
for ( UnsignedInt i = 0 ; i < part . styles . size ( ) ; i + + ) {
part_styles - > at < IntProperty > ( i ) - > value = part . styles [ i ] ;
}
auto decals_array = part_prop - > at < ArrayProperty > ( " Decals_42_F358794A4F18497970F56BA9627D3603 " _s ) ;
writeDecals ( part . decals , decals_array ) ;
if ( part . accessories . size ( ) ! = 0 ) {
auto accs_array = part_prop - > at < ArrayProperty > ( " Accessories_52_D902DD4241FA0050C2529596255153F3 " _s ) ;
writeAccessories ( part . accessories , accs_array ) ;
}
if ( ! _mass - > saveToFile ( ) ) {
_lastError = _mass - > lastError ( ) ;
return false ;
}
return true ;
}
2022-03-12 09:34:19 +01:00
auto Mass : : bulletLauncherAttachmentStyle ( ) - > BulletLauncherAttachmentStyle & {
return _armour . blAttachmentStyle ;
}
auto Mass : : bulletLauncherAttachments ( ) - > Containers : : ArrayView < BulletLauncherAttachment > {
return _armour . blAttachment ;
}
void Mass : : getBulletLauncherAttachments ( ) {
auto unit_data = _mass - > at < GenericStructProperty > ( " UnitData " _s ) ;
if ( ! unit_data ) {
2022-03-30 19:51:00 +02:00
Utility : : Error { } < < " Couldn't find unit data in " < < _filename ;
2022-03-12 09:34:19 +01:00
_state = State : : Invalid ;
return ;
}
2022-03-13 11:02:43 +01:00
auto attach_style_prop = unit_data - > at < ByteProperty > ( " WeaponBLAttachmentStyle_65_5943FCE8406F18D2C3F69285EB23A699 " _s ) ;
auto attach_array = unit_data - > at < ArrayProperty > ( " WeaponBLAttachment_61_442D08F547510A4CEE1501BBAF297BA0 " _s ) ;
2022-03-12 09:34:19 +01:00
if ( ! attach_style_prop & & ! attach_array ) {
_armour . blAttachmentStyle = BulletLauncherAttachmentStyle : : NotFound ;
return ;
}
if ( attach_style_prop & & ! attach_array ) {
_armour . blAttachmentStyle = BulletLauncherAttachmentStyle : : NotFound ;
2022-03-30 19:51:00 +02:00
Utility : : Error { } < < " Couldn't find bullet launcher attachments in " < < _filename ;
2022-03-12 09:34:19 +01:00
_state = State : : Invalid ;
return ;
}
2022-03-13 15:25:11 +01:00
if ( attach_array - > items . size ( ) = = _weapons . bulletLaunchers . size ( ) & &
attach_array - > items . size ( ) = = _armour . blAttachment . size ( ) )
2022-03-12 09:34:19 +01:00
{
for ( UnsignedInt i = 0 ; i < attach_array - > items . size ( ) ; i + + ) {
auto attachment_prop = attach_array - > at < GenericStructProperty > ( i ) ;
auto & attachment = _armour . blAttachment [ i ] ;
Containers : : StringView socket = attachment_prop - > at < StringProperty > ( " Socket_9_B9DBF30D4A1F0032A2BE2F8B342B35A9 " _s ) - > value ;
2022-03-13 15:26:00 +01:00
# define c(enumerator, strenum, name) if(socket == (strenum)) { attachment.socket = BulletLauncherSocket::enumerator; } else
2022-03-12 09:34:19 +01:00
# include "../Maps/BulletLauncherSockets.hpp"
# undef c
{
Utility : : Error { } < < " Invalid BL attachment socket. " ;
_state = State : : Invalid ;
return ;
}
auto rel_loc_prop = attachment_prop - > at < VectorStructProperty > ( " RelativeLocation_10_2F6E75DF4C40622658340E9A22D38B02 " _s ) ;
attachment . relativeLocation = Vector3 { rel_loc_prop - > x , rel_loc_prop - > y , rel_loc_prop - > z } ;
auto off_loc_prop = attachment_prop - > at < VectorStructProperty > ( " OffsetLocation_11_F42B3DA3436948FF85752DB33722382F " _s ) ;
attachment . offsetLocation = Vector3 { off_loc_prop - > x , off_loc_prop - > y , off_loc_prop - > z } ;
auto rel_rot_prop = attachment_prop - > at < VectorStructProperty > ( " RelativeRotation_12_578140464621245132CFF2A2AD85E735 " _s ) ;
attachment . relativeRotation = Vector3 { rel_rot_prop - > x , rel_rot_prop - > y , rel_rot_prop - > z } ;
auto off_rot_prop = attachment_prop - > at < VectorStructProperty > ( " OffsetRotation_13_B5980BCD47905D842D1490A1A520B064 " _s ) ;
attachment . offsetRotation = Vector3 { off_rot_prop - > x , off_rot_prop - > y , off_rot_prop - > z } ;
auto rel_scale_prop = attachment_prop - > at < VectorStructProperty > ( " RelativeScale_16_37BC80EF42699F79533F7AA7B3094E38 " _s ) ;
attachment . relativeScale = Vector3 { rel_scale_prop - > x , rel_scale_prop - > y , rel_scale_prop - > z } ;
}
}
if ( attach_style_prop ) {
Containers : : StringView attach_style = attach_style_prop - > enumValue ;
# define c(enumerator, strenum) if(attach_style == (strenum)) { _armour.blAttachmentStyle = BulletLauncherAttachmentStyle::enumerator; } else
# include "../Maps/BulletLauncherAttachmentStyles.hpp"
# undef c
{
Utility : : Error { } < < " Unknown BL attachment style enumerator. " ;
}
}
else {
_armour . blAttachmentStyle = BulletLauncherAttachmentStyle : : ActiveOne ;
}
}
auto Mass : : writeBulletLauncherAttachments ( ) - > bool {
2022-03-20 09:47:56 +01:00
auto unit_data = _mass - > at < GenericStructProperty > ( " UnitData " _s ) ;
if ( ! unit_data ) {
_state = State : : Invalid ;
_lastError = " No unit data in " + _filename ;
return false ;
}
auto attach_style_prop = unit_data - > at < ByteProperty > ( " WeaponBLAttachmentStyle_65_5943FCE8406F18D2C3F69285EB23A699 " _s ) ;
auto attach_array = unit_data - > at < ArrayProperty > ( " WeaponBLAttachment_61_442D08F547510A4CEE1501BBAF297BA0 " _s ) ;
if ( ! attach_style_prop & & ! attach_array ) {
_armour . blAttachmentStyle = BulletLauncherAttachmentStyle : : NotFound ;
_lastError = " No attachment properties to write to in " + _filename ;
return false ;
}
if ( attach_style_prop & & ! attach_array ) {
_armour . blAttachmentStyle = BulletLauncherAttachmentStyle : : NotFound ;
_state = State : : Invalid ;
_lastError = " Couldn't find the attachments in " + _filename ;
return false ;
}
if ( attach_array - > items . size ( ) = = _weapons . bulletLaunchers . size ( ) & &
attach_array - > items . size ( ) = = _armour . blAttachment . size ( ) )
{
for ( UnsignedInt i = 0 ; i < attach_array - > items . size ( ) ; i + + ) {
auto attachment_prop = attach_array - > at < GenericStructProperty > ( i ) ;
auto & attachment = _armour . blAttachment [ i ] ;
auto & socket = attachment_prop - > at < StringProperty > ( " Socket_9_B9DBF30D4A1F0032A2BE2F8B342B35A9 " _s ) - > value ;
switch ( attachment . socket ) {
# define c(enumerator, strenum, name) case BulletLauncherSocket::enumerator: socket = strenum; break;
# include "../Maps/BulletLauncherSockets.hpp"
# undef c
default :
_lastError = " Invalid socket type. " _s ;
return false ;
}
auto rel_loc_prop = attachment_prop - > at < VectorStructProperty > ( " RelativeLocation_10_2F6E75DF4C40622658340E9A22D38B02 " _s ) ;
rel_loc_prop - > x = attachment . relativeLocation . x ( ) ;
rel_loc_prop - > y = attachment . relativeLocation . y ( ) ;
rel_loc_prop - > z = attachment . relativeLocation . z ( ) ;
auto off_loc_prop = attachment_prop - > at < VectorStructProperty > ( " OffsetLocation_11_F42B3DA3436948FF85752DB33722382F " _s ) ;
off_loc_prop - > x = attachment . offsetLocation . x ( ) ;
off_loc_prop - > y = attachment . offsetLocation . y ( ) ;
off_loc_prop - > z = attachment . offsetLocation . z ( ) ;
auto rel_rot_prop = attachment_prop - > at < VectorStructProperty > ( " RelativeRotation_12_578140464621245132CFF2A2AD85E735 " _s ) ;
rel_rot_prop - > x = attachment . relativeRotation . x ( ) ;
rel_rot_prop - > y = attachment . relativeRotation . y ( ) ;
rel_rot_prop - > z = attachment . relativeRotation . z ( ) ;
auto off_rot_prop = attachment_prop - > at < VectorStructProperty > ( " OffsetRotation_13_B5980BCD47905D842D1490A1A520B064 " _s ) ;
off_rot_prop - > x = attachment . offsetRotation . x ( ) ;
off_rot_prop - > y = attachment . offsetRotation . y ( ) ;
off_rot_prop - > z = attachment . offsetRotation . z ( ) ;
auto rel_scale_prop = attachment_prop - > at < VectorStructProperty > ( " RelativeScale_16_37BC80EF42699F79533F7AA7B3094E38 " _s ) ;
rel_scale_prop - > x = attachment . relativeScale . x ( ) ;
rel_scale_prop - > y = attachment . relativeScale . y ( ) ;
rel_scale_prop - > z = attachment . relativeScale . z ( ) ;
}
}
if ( ! attach_style_prop ) {
attach_style_prop = new ByteProperty ;
attach_style_prop - > name . emplace ( " WeaponBLAttachmentStyle_65_5943FCE8406F18D2C3F69285EB23A699 " _s ) ;
attach_style_prop - > enumType = " enuBLAttachmentStyle " _s ;
ByteProperty : : ptr prop { attach_style_prop } ;
arrayAppend ( unit_data - > properties , std : : move ( prop ) ) ;
}
auto & attach_style = attach_style_prop - > enumValue ;
switch ( _armour . blAttachmentStyle ) {
# define c(enumerator, strenum) case BulletLauncherAttachmentStyle::enumerator: \
attach_style = strenum ; \
break ;
# include "../Maps/BulletLauncherAttachmentStyles.hpp"
# undef c
default :
_lastError = " Unknown BL attachment style. " ;
return false ;
}
if ( ! _mass - > saveToFile ( ) ) {
_lastError = _mass - > lastError ( ) ;
return false ;
}
return true ;
2022-03-12 09:34:19 +01:00
}
2022-03-06 09:51:57 +01:00
auto Mass : : armourCustomStyles ( ) - > Containers : : ArrayView < CustomStyle > {
return _armour . customStyles ;
}
void Mass : : getArmourCustomStyles ( ) {
auto unit_data = _mass - > at < GenericStructProperty > ( " UnitData " _s ) ;
if ( ! unit_data ) {
2022-03-30 19:51:00 +02:00
Utility : : Error { } < < " Couldn't find unit data in " < < _filename ;
2022-03-06 09:51:57 +01:00
_state = State : : Invalid ;
return ;
}
auto armour_styles = unit_data - > at < ArrayProperty > ( " ArmorStyle_42_E2F6AC3647788CB366BD469B3B7E899E " _s ) ;
if ( ! armour_styles ) {
2022-03-30 19:51:00 +02:00
Utility : : Error { } < < " Couldn't find custom armour styles in " < < _filename ;
2022-03-06 09:51:57 +01:00
_state = State : : Invalid ;
return ;
}
if ( armour_styles - > items . size ( ) ! = _armour . customStyles . size ( ) ) {
2022-03-30 19:51:00 +02:00
Utility : : Error { } < < " Custom armour style arrays are not of the same size. Expected " < < _armour . customStyles . size ( ) < < Utility : : Debug : : nospace < < " , got " < < armour_styles - > items . size ( ) < < " instead. " ;
2022-03-06 09:51:57 +01:00
_state = State : : Invalid ;
return ;
}
getCustomStyles ( _armour . customStyles , armour_styles ) ;
}
auto Mass : : writeArmourCustomStyle ( UnsignedLong index ) - > bool {
if ( index > _armour . customStyles . size ( ) ) {
_lastError = " Style index out of range. " _s ;
return false ;
}
auto unit_data = _mass - > at < GenericStructProperty > ( " UnitData " _s ) ;
if ( ! unit_data ) {
_state = State : : Invalid ;
_lastError = " Couldn't find unit data in " _s + _filename ;
return false ;
}
auto armour_styles = unit_data - > at < ArrayProperty > ( " ArmorStyle_42_E2F6AC3647788CB366BD469B3B7E899E " _s ) ;
if ( ! armour_styles ) {
_lastError = " Couldn't find armour custom styles in " _s + _filename ;
_state = State : : Invalid ;
return false ;
}
return writeCustomStyle ( _armour . customStyles [ index ] , index , armour_styles ) ;
}