mirror of
https://github.com/HikikoMarmy/Champions-Reborn-Server.git
synced 2026-04-04 16:49:47 -03:00
660 lines
14 KiB
C++
660 lines
14 KiB
C++
#include "Game/RealmCharacter.hpp"
|
|
#include "Game/CharacterSaveTask.hpp"
|
|
#include "Common/ByteBufferReader.hpp"
|
|
#include "Common/RLEZ.hpp"
|
|
|
|
#include "logging.hpp"
|
|
|
|
RealmCharacter::RealmCharacter()
|
|
{
|
|
m_characterId = 0;
|
|
m_data.clear();
|
|
|
|
Initialize();
|
|
}
|
|
|
|
RealmCharacter::RealmCharacter( const int32_t character_id, const CharacterSlotData meta, const std::vector<uint8_t> data )
|
|
{
|
|
m_characterId = character_id;
|
|
m_data = data;
|
|
m_metaData = meta;
|
|
|
|
Initialize();
|
|
}
|
|
|
|
RealmCharacter::~RealmCharacter()
|
|
{
|
|
}
|
|
|
|
void RealmCharacter::Initialize()
|
|
{
|
|
name = "";
|
|
for( auto &val : unknown_000 )
|
|
{
|
|
val = 0;
|
|
}
|
|
|
|
unknown_str = "";
|
|
|
|
for( auto &val : unknown_004 )
|
|
{
|
|
val = 0;
|
|
}
|
|
|
|
character_class = CharacterClass::WARRIOR;
|
|
character_race = CharacterRace::BARBARIAN_M;
|
|
|
|
current_level = 0;
|
|
pending_level = 0;
|
|
|
|
unknown_009 = 0;
|
|
experience = 0;
|
|
|
|
std::memset( unknown_010, 0, sizeof( unknown_010 ) );
|
|
std::memset( stats, 0, sizeof( stats ) );
|
|
|
|
unknown_016 = 0;
|
|
current_hp = 0.0f;
|
|
maximum_hp = 0.0f;
|
|
|
|
unknown_017 = 0;
|
|
unknown_018 = 0;
|
|
unknown_019 = 0;
|
|
|
|
current_mana = 0.0f;
|
|
maximum_mana = 0.0f;
|
|
|
|
unknown_020 = 0;
|
|
|
|
attack_power = 0;
|
|
minimum_damage = 0;
|
|
maximum_damage = 0;
|
|
|
|
unknown_021 = 0;
|
|
unknown_022 = 0;
|
|
unknown_023 = 0;
|
|
unknown_024 = 0;
|
|
unknown_025 = 0;
|
|
unknown_026 = 0;
|
|
|
|
current_gold = 0;
|
|
current_skill_points = 0;
|
|
current_ability_points = 0;
|
|
has_spent_remaining_points = 0;
|
|
|
|
unknown_029 = 0;
|
|
unknown_030 = 0;
|
|
unknown_031 = 0;
|
|
unknown_032 = 0;
|
|
unknown_033 = 0;
|
|
unknown_034 = 0;
|
|
unknown_035 = 0;
|
|
unknown_036 = 0;
|
|
unknown_037 = 0;
|
|
unknown_038 = 0;
|
|
unknown_039 = 0;
|
|
unknown_040 = 0;
|
|
|
|
weight = 0.0f;
|
|
max_weight = 0.0f;
|
|
|
|
unknown_041 = 0;
|
|
unknown_042 = 0;
|
|
|
|
item_data.fill( ItemData() );
|
|
num_armor_item = 0;
|
|
unknown_043 = 0;
|
|
armor_item_data.fill( ItemData() );
|
|
num_weapon_item = 0;
|
|
unknown_044 = 0;
|
|
weapon_item_data.fill( ItemData() );
|
|
num_consumable_item = 0;
|
|
|
|
unknown_045 = 0;
|
|
unknown_046.fill( 0 );
|
|
|
|
quest_string.fill( s_quest() );
|
|
num_quests = 0;
|
|
|
|
unknown_048 = 0;
|
|
unknown_049 = 0;
|
|
unknown_050 = 0;
|
|
unknown_051 = 0;
|
|
unknown_052 = 0;
|
|
unknown_053 = 0;
|
|
unknown_054 = 0;
|
|
|
|
equipment.fill( 0 );
|
|
|
|
newStyle.fill( s_new_style() );
|
|
|
|
unknown_075 = 0;
|
|
unknown_076 = 0.0f;
|
|
|
|
unknown_077 = 0;
|
|
unknown_078 = 0;
|
|
unknown_079 = 0;
|
|
unknown_080 = 0;
|
|
unknown_081 = 0;
|
|
unknown_082 = 0;
|
|
unknown_083 = 0;
|
|
unknown_084 = 0;
|
|
unknown_085 = 0;
|
|
|
|
skill_slot[ 0 ] = 0;
|
|
skill_slot[ 1 ] = 0;
|
|
|
|
unknown_087 = 0;
|
|
unknown_088 = 0;
|
|
|
|
attackData.fill( AttackData() );
|
|
|
|
skills.fill( s_skill() );
|
|
|
|
unknown_091 = 0;
|
|
|
|
mission_progress.fill( s_difficulty_progress() );
|
|
mission_medals.fill( 0 );
|
|
|
|
evil_bitflag = 0;
|
|
good_bitflag = 0;
|
|
unknown_101 = 0;
|
|
movement_speed = 0.0f;
|
|
|
|
unknown_102 = 0;
|
|
unknown_103 = 0;
|
|
unknown_104 = 0;
|
|
unknown_105 = 0;
|
|
unknown_106 = 0;
|
|
unknown_107 = 0;
|
|
unknown_108 = 0;
|
|
unknown_109 = 0;
|
|
unknown_110 = 0;
|
|
}
|
|
|
|
const std::vector< uint8_t > RealmCharacter::Serialize() const
|
|
{
|
|
auto writer = ByteBuffer( CHARACTER_DATA_SIZE );
|
|
|
|
/*writer.write_sz_utf8(name, 32);
|
|
|
|
for( const auto &val : unknown_000 )
|
|
{
|
|
writer.write_u8( val );
|
|
}
|
|
|
|
writer.write_sz_utf8( unknown_str, 32 );
|
|
|
|
for( const auto &val : unknown_004 )
|
|
{
|
|
writer.write_i32( val );
|
|
}
|
|
|
|
writer.write_i32( static_cast< int32_t >( character_class ) );
|
|
writer.write_i32( static_cast< int32_t >( character_race ) );
|
|
|
|
writer.write_u8( current_level );
|
|
writer.write_u8( pending_level );
|
|
writer.write_u16( unknown_009 );
|
|
writer.write_i32( experience );
|
|
|
|
for( const auto &val : unknown_010 )
|
|
{
|
|
writer.write_i32( val );
|
|
}
|
|
|
|
for( const auto &stat : stats )
|
|
{
|
|
writer.write( stat );
|
|
}
|
|
|
|
writer.write_i32( unknown_016 );
|
|
writer.write_f32( current_hp );
|
|
writer.write_f32( maximum_hp );
|
|
writer.write_i32( unknown_017 );
|
|
writer.write_i32( unknown_018 );
|
|
writer.write_i32( unknown_019 );
|
|
writer.write_f32( current_mana );
|
|
writer.write_f32( maximum_mana );
|
|
writer.write_i32( unknown_020 );
|
|
writer.write_i32( attack_power );
|
|
writer.write_i32( minimum_damage );
|
|
writer.write_i32( maximum_damage );
|
|
writer.write_i32( unknown_021 );
|
|
writer.write_i32( unknown_022 );
|
|
writer.write_u8( unknown_023 );
|
|
writer.write_u8( unknown_024 );
|
|
writer.write_u8( unknown_025 );
|
|
writer.write_u8( unknown_026 );
|
|
writer.write_i32( current_gold );
|
|
writer.write_i32( current_skill_points );
|
|
writer.write_i16( current_ability_points );
|
|
writer.write_i16( has_spent_remaining_points );
|
|
|
|
writer.write_i32( unknown_029 );
|
|
writer.write_i32( unknown_030 );
|
|
writer.write_i32( unknown_031 );
|
|
writer.write_i32( unknown_032 );
|
|
writer.write_i32( unknown_033 );
|
|
writer.write_i32( unknown_034 );
|
|
writer.write_i32( unknown_035 );
|
|
writer.write_i32( unknown_036 );
|
|
writer.write_i32( unknown_037 );
|
|
writer.write_i32( unknown_038 );
|
|
writer.write_i32( unknown_039 );
|
|
writer.write_i32( unknown_040 );
|
|
|
|
writer.write_f32( weight );
|
|
writer.write_f32( max_weight );
|
|
|
|
writer.write_i32( unknown_041 );
|
|
writer.write_i32( unknown_042 );
|
|
|
|
for( const auto &item : item_data )
|
|
{
|
|
writer.write( item );
|
|
}
|
|
|
|
writer.write_i32( num_armor_item );
|
|
writer.write_i32( unknown_043 );
|
|
for( const auto &item : armor_item_data )
|
|
{
|
|
writer.write( item );
|
|
}
|
|
|
|
writer.write_i32( num_weapon_item );
|
|
writer.write_i32( unknown_044 );
|
|
for( const auto &item : weapon_item_data )
|
|
{
|
|
writer.write( item );
|
|
}
|
|
|
|
writer.write_i32( num_consumable_item );
|
|
writer.write_i32( unknown_045 );
|
|
|
|
writer.forward( 2696 );
|
|
|
|
for( const auto &quest : quest_string )
|
|
{
|
|
writer.write_sz_utf8( quest.name, 32 );
|
|
writer.write_sz_utf8( quest.description, 32 );
|
|
}
|
|
|
|
writer.write_i32( num_quests );
|
|
|
|
writer.write_i32( unknown_048 );
|
|
writer.write_i32( unknown_049 );
|
|
writer.write_i32( unknown_050 );
|
|
writer.write_i32( unknown_051 );
|
|
writer.write_i32( unknown_052 );
|
|
writer.write_i32( unknown_053 );
|
|
writer.write_i32( unknown_054 );
|
|
|
|
for( const auto &slot : equipment )
|
|
{
|
|
writer.write_i32( slot );
|
|
}
|
|
|
|
for( const auto &style : newStyle )
|
|
{
|
|
writer.write< s_new_style >( style );
|
|
}
|
|
|
|
writer.write_i32( unknown_075 );
|
|
writer.write_f32( unknown_076 );
|
|
|
|
writer.write_i32( unknown_077 );
|
|
writer.write_i32( unknown_078 );
|
|
writer.write_i32( unknown_079 );
|
|
writer.write_i32( unknown_080 );
|
|
writer.write_i32( unknown_081 );
|
|
writer.write_i32( unknown_082 );
|
|
writer.write_i32( unknown_083 );
|
|
writer.write_i32( unknown_084 );
|
|
writer.write_i32( unknown_085 );
|
|
|
|
for( const auto &skill : skill_slot )
|
|
{
|
|
writer.write_u8( skill );
|
|
}
|
|
|
|
writer.write_u8( unknown_087 );
|
|
writer.write_u8( unknown_088 );
|
|
|
|
for( const auto &attack : attackData )
|
|
{
|
|
writer.write< AttackData >( attack );
|
|
}
|
|
|
|
for( const auto &skill : skills )
|
|
{
|
|
writer.write< s_skill >( skill );
|
|
}
|
|
|
|
writer.write_i32( unknown_091 );
|
|
|
|
for( const auto &progress : mission_progress )
|
|
{
|
|
writer.write< s_difficulty_progress >( progress );
|
|
}
|
|
|
|
for( const auto &medal : mission_medals )
|
|
{
|
|
writer.write_u8( medal );
|
|
}
|
|
|
|
writer.write_u8( evil_bitflag );
|
|
writer.write_u8( good_bitflag );
|
|
|
|
writer.write_i32( unknown_101 );
|
|
|
|
writer.write_f32( movement_speed );
|
|
|
|
writer.write_u8( unknown_102 );
|
|
writer.write_u8( unknown_103 );
|
|
writer.write_u8( unknown_104 );
|
|
writer.write_u8( unknown_105 );
|
|
writer.write_u8( unknown_106 );
|
|
writer.write_u8( unknown_107 );
|
|
writer.write_u8( unknown_108 );
|
|
writer.write_u8( unknown_109 );
|
|
|
|
writer.write_i32( unknown_110 );*/
|
|
|
|
return writer.get_buffer();
|
|
}
|
|
|
|
void RealmCharacter::Deserialize( const std::vector<uint8_t> &data )
|
|
{
|
|
ByteBufferReader reader( data );
|
|
|
|
/*try
|
|
{
|
|
name = reader.readString( 32 );
|
|
|
|
for( auto &val : unknown_000 )
|
|
{
|
|
val = reader.read< uint8_t >();
|
|
}
|
|
|
|
unknown_str = reader.readString( 32 );
|
|
|
|
for( auto &val : unknown_004 )
|
|
{
|
|
val = reader.read< int32_t >();
|
|
}
|
|
|
|
character_class = static_cast< CharacterClass >( reader.read< int32_t >() );
|
|
character_race = static_cast< CharacterRace >( reader.read< int32_t >() );
|
|
|
|
current_level = reader.read< uint8_t >();
|
|
pending_level = reader.read< uint8_t >();
|
|
unknown_009 = reader.read< uint16_t >();
|
|
experience = reader.read< int32_t >();
|
|
|
|
for( auto &val : unknown_010 )
|
|
{
|
|
val = reader.read< int32_t >();
|
|
}
|
|
|
|
for( auto &stat : stats )
|
|
{
|
|
stat = reader.read< s_stats >();
|
|
}
|
|
|
|
unknown_016 = reader.read< int32_t >();
|
|
|
|
current_hp = reader.read< float_t >();
|
|
maximum_hp = reader.read< float_t >();
|
|
|
|
unknown_017 = reader.read< int32_t >();
|
|
unknown_018 = reader.read< int32_t >();
|
|
unknown_019 = reader.read< int32_t >();
|
|
|
|
current_mana = reader.read< float_t >();
|
|
maximum_mana = reader.read< float_t >();
|
|
|
|
unknown_020 = reader.read< int32_t >();
|
|
|
|
attack_power = reader.read< int32_t >();
|
|
minimum_damage = reader.read< int32_t >();
|
|
maximum_damage = reader.read< int32_t >();
|
|
|
|
unknown_021 = reader.read< int32_t >();
|
|
unknown_022 = reader.read< int32_t >();
|
|
unknown_023 = reader.read< uint8_t >();
|
|
unknown_024 = reader.read< uint8_t >();
|
|
unknown_025 = reader.read< uint8_t >();
|
|
unknown_026 = reader.read< uint8_t >();
|
|
|
|
current_gold = reader.read< int32_t >();
|
|
current_skill_points = reader.read< int32_t >();
|
|
current_ability_points = reader.read< int16_t >();
|
|
has_spent_remaining_points = reader.read< int16_t >();
|
|
|
|
//
|
|
unknown_029 = reader.read< int32_t >();
|
|
unknown_030 = reader.read< int32_t >();
|
|
unknown_031 = reader.read< int32_t >();
|
|
unknown_032 = reader.read< int32_t >();
|
|
|
|
//
|
|
unknown_033 = reader.read< int32_t >();
|
|
unknown_034 = reader.read< int32_t >();
|
|
unknown_035 = reader.read< int32_t >();
|
|
unknown_036 = reader.read< int32_t >();
|
|
|
|
//
|
|
unknown_037 = reader.read< int32_t >();
|
|
unknown_038 = reader.read< int32_t >();
|
|
unknown_039 = reader.read< int32_t >();
|
|
unknown_040 = reader.read< int32_t >();
|
|
|
|
weight = reader.read< float_t >();
|
|
max_weight = reader.read< float_t >();
|
|
|
|
unknown_041 = reader.read< int32_t >();
|
|
unknown_042 = reader.read< int32_t >();
|
|
|
|
item_data = reader.readArray< ItemData, 64>();
|
|
|
|
num_armor_item = reader.read< int32_t >();
|
|
unknown_043 = reader.read< int32_t >();
|
|
armor_item_data = reader.readArray< ItemData, 64>();
|
|
|
|
num_weapon_item = reader.read< int32_t >();
|
|
unknown_044 = reader.read< int32_t >();
|
|
weapon_item_data = reader.readArray< ItemData, 64>();
|
|
|
|
num_consumable_item = reader.read< int32_t >();
|
|
unknown_045 = reader.read< int32_t >();
|
|
unknown_046.fill( 0x00 ); // Fill with zeros, size is 2696 bytes
|
|
|
|
for( auto &quest : quest_string )
|
|
{
|
|
quest = reader.read< s_quest >();
|
|
}
|
|
num_quests = reader.read< int32_t >();
|
|
|
|
unknown_048 = reader.read< int32_t >();
|
|
unknown_049 = reader.read< int32_t >();
|
|
unknown_050 = reader.read< int32_t >();
|
|
unknown_051 = reader.read< int32_t >();
|
|
unknown_052 = reader.read< int32_t >();
|
|
unknown_053 = reader.read< int32_t >();
|
|
unknown_054 = reader.read< int32_t >();
|
|
|
|
for( auto &slot : equipment )
|
|
{
|
|
slot = reader.read< int32_t >();
|
|
}
|
|
|
|
for( auto &style : newStyle )
|
|
{
|
|
style = reader.read< s_new_style >();
|
|
}
|
|
|
|
unknown_075 = reader.read< int32_t >();
|
|
unknown_076 = reader.read< float_t >();
|
|
unknown_077 = reader.read< int32_t >();
|
|
unknown_078 = reader.read< int32_t >();
|
|
unknown_079 = reader.read< int32_t >();
|
|
unknown_080 = reader.read< int32_t >();
|
|
unknown_081 = reader.read< int32_t >();
|
|
unknown_082 = reader.read< int32_t >();
|
|
unknown_083 = reader.read< int32_t >();
|
|
unknown_084 = reader.read< int32_t >();
|
|
unknown_085 = reader.read< int32_t >();
|
|
|
|
for( auto &skill : skill_slot )
|
|
{
|
|
skill = reader.read< uint8_t >();
|
|
}
|
|
|
|
unknown_087 = reader.read< uint8_t >();
|
|
unknown_088 = reader.read< uint8_t >();
|
|
|
|
for( auto &attack : attackData )
|
|
{
|
|
attack = reader.read< AttackData >();
|
|
}
|
|
|
|
for( auto &skill : skills )
|
|
{
|
|
skill.skill_id = reader.read< int16_t >();
|
|
skill.skill_level = reader.read< int16_t >();
|
|
}
|
|
|
|
unknown_091 = reader.read< int32_t >();
|
|
|
|
for( auto &val : mission_progress )
|
|
{
|
|
val = reader.read< s_difficulty_progress >();
|
|
}
|
|
|
|
for( auto &val : mission_medals )
|
|
{
|
|
val = reader.read< uint8_t >();
|
|
}
|
|
|
|
evil_bitflag = reader.read< uint8_t >();
|
|
good_bitflag = reader.read< uint8_t >();
|
|
|
|
unknown_101 = reader.read< int32_t >();
|
|
movement_speed = reader.read< float_t >();
|
|
|
|
unknown_102 = reader.read< uint8_t >();
|
|
unknown_103 = reader.read< uint8_t >();
|
|
unknown_104 = reader.read< uint8_t >();
|
|
unknown_105 = reader.read< uint8_t >();
|
|
unknown_106 = reader.read< uint8_t >();
|
|
unknown_107 = reader.read< uint8_t >();
|
|
unknown_108 = reader.read< uint8_t >();
|
|
unknown_109 = reader.read< uint8_t >();
|
|
|
|
unknown_110 = reader.read< int32_t >();
|
|
}
|
|
catch( const std::out_of_range &e )
|
|
{
|
|
Log::Error( "Failed to deserialize RealmCharacter: %s", e.what() );
|
|
return;
|
|
}*/
|
|
}
|
|
|
|
bool RealmCharacter::ValidateData()
|
|
{
|
|
if( m_data.empty() || m_data.size() < CHARACTER_DATA_SIZE )
|
|
{
|
|
Log::Error( "Character data is invalid or too small!" );
|
|
return false;
|
|
}
|
|
|
|
if( current_level < 1 || current_level > 80 )
|
|
{
|
|
Log::Error( "Invalid character level: %d", current_level );
|
|
return false;
|
|
}
|
|
|
|
if( current_hp < 1.0f || current_hp > maximum_hp )
|
|
{
|
|
Log::Error( "Invalid HP values: current %f, maximum %f", current_hp, maximum_hp );
|
|
return false;
|
|
}
|
|
|
|
if( current_mana < 0.0f || current_mana > maximum_mana )
|
|
{
|
|
Log::Error( "Invalid mana values: current %f, maximum %f", current_mana, maximum_mana );
|
|
return false;
|
|
}
|
|
|
|
if( weight < 0.0f || weight > max_weight )
|
|
{
|
|
Log::Error( "Invalid weight values: current %f, maximum %f", weight, max_weight );
|
|
return false;
|
|
}
|
|
|
|
if( movement_speed <= 0.0f )
|
|
{
|
|
Log::Error( "Invalid movement speed: %f", movement_speed );
|
|
return false;
|
|
}
|
|
|
|
for( const auto &mission : mission_progress )
|
|
{
|
|
if( mission.mission_na < 0 || mission.mission_na > 3 )
|
|
{
|
|
Log::Error( "Invalid mission NA value: %d", mission.mission_na );
|
|
return false;
|
|
}
|
|
|
|
if( mission.mission_Disease < 0 || mission.mission_Disease > 3 )
|
|
{
|
|
Log::Error( "Invalid mission Disease value: %d", mission.mission_Disease );
|
|
return false;
|
|
}
|
|
|
|
if( mission.mission_Fear < 0 || mission.mission_Fear > 3 )
|
|
{
|
|
Log::Error( "Invalid mission Fear value: %d", mission.mission_Fear );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
CharacterSlotData RealmCharacter::GetMetaData() const
|
|
{
|
|
return m_metaData;
|
|
}
|
|
|
|
void RealmCharacter::SetMetaData( sptr_byte_stream stream )
|
|
{
|
|
m_metaData.Deserialize( stream );
|
|
}
|
|
|
|
std::vector<uint8_t> RealmCharacter::Unpack()
|
|
{
|
|
std::vector< uint8_t > output;
|
|
size_t read = 4;
|
|
|
|
while( read < m_data.size() )
|
|
{
|
|
uint8_t byte = m_data[ read++ ];
|
|
output.push_back( byte );
|
|
|
|
if( byte == 0x00 )
|
|
{
|
|
if( read >= m_data.size() )
|
|
{
|
|
break;
|
|
}
|
|
|
|
uint8_t count = m_data[ read++ ];
|
|
output.insert( output.end(), count, 0x00 );
|
|
}
|
|
}
|
|
|
|
return output;
|
|
}
|