2017-08-19 00:18:40 +02:00
|
|
|
#include <src/servers/Server_Common/Common.h>
|
|
|
|
#include <src/servers/Server_Common/Network/GamePacket.h>
|
|
|
|
#include <src/servers/Server_Common/Database/Database.h>
|
|
|
|
#include <src/servers/Server_Common/Util/Util.h>
|
|
|
|
#include <src/servers/Server_Common/Util/UtilMath.h>
|
|
|
|
#include <src/servers/Server_Common/Config/XMLConfig.h>
|
|
|
|
#include <src/servers/Server_Common/Logging/Logger.h>
|
|
|
|
#include <src/servers/Server_Common/Exd/ExdData.h>
|
|
|
|
#include <src/servers/Server_Common/Network/PacketContainer.h>
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
#include <set>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
|
2017-10-04 23:28:38 +02:00
|
|
|
#include <Server_Common/Database/DbLoader.h>
|
|
|
|
#include <Server_Common/Database/CharaDbConnection.h>
|
|
|
|
#include <Server_Common/Database/DbWorkerPool.h>
|
|
|
|
#include <Server_Common/Database/PreparedStatement.h>
|
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
#include "Player.h"
|
|
|
|
|
2017-08-18 17:16:15 +02:00
|
|
|
#include "src/servers/Server_Zone/Zone/ZoneMgr.h"
|
|
|
|
#include "src/servers/Server_Zone/Zone/Zone.h"
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-18 17:16:15 +02:00
|
|
|
#include "src/servers/Server_Zone/ServerZone.h"
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-18 17:16:15 +02:00
|
|
|
#include "src/servers/Server_Zone/Forwards.h"
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-08-18 17:16:15 +02:00
|
|
|
#include "src/servers/Server_Zone/Network/GameConnection.h"
|
|
|
|
#include "src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h"
|
|
|
|
#include "src/servers/Server_Zone/StatusEffect/StatusEffectContainer.h"
|
|
|
|
#include "src/servers/Server_Zone/Inventory/Inventory.h"
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-10-04 23:28:38 +02:00
|
|
|
#include "src/libraries/sapphire/mysqlConnector/MySqlConnector.h"
|
|
|
|
|
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
extern Core::Logger g_log;
|
|
|
|
extern Core::Db::Database g_database;
|
|
|
|
extern Core::ServerZone g_serverZone;
|
|
|
|
extern Core::ZoneMgr g_zoneMgr;
|
|
|
|
extern Core::Data::ExdData g_exdData;
|
2017-10-04 23:28:38 +02:00
|
|
|
extern Core::Db::DbWorkerPool< Core::Db::CharaDbConnection > g_charaDb;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
using namespace Core::Common;
|
|
|
|
using namespace Core::Network::Packets;
|
|
|
|
using namespace Core::Network::Packets::Server;
|
|
|
|
|
|
|
|
// load player from the db
|
|
|
|
bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
|
|
|
|
{
|
|
|
|
const std::string char_id_str = std::to_string( charId );
|
|
|
|
|
2017-10-10 00:03:24 +02:00
|
|
|
auto stmt = g_charaDb.getPreparedStatement( Core::Db::CharaDbStatements::CHARA_SEL );
|
2017-10-04 23:28:38 +02:00
|
|
|
|
2017-10-05 22:43:15 +02:00
|
|
|
stmt->setUInt( 1, charId );
|
2017-10-07 23:10:13 +02:00
|
|
|
auto res = g_charaDb.query( stmt );
|
2017-10-04 23:28:38 +02:00
|
|
|
|
|
|
|
if( !res->next() )
|
2017-08-08 13:53:47 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
m_id = charId;
|
|
|
|
|
2017-10-04 23:28:38 +02:00
|
|
|
auto name = res->getString( "Name" );
|
|
|
|
strcpy( m_name, name.c_str() );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-10-07 23:10:13 +02:00
|
|
|
auto zoneId = res->getUInt( "TerritoryId" );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-10-04 23:28:38 +02:00
|
|
|
ZonePtr pCurrZone = g_zoneMgr.getZone( zoneId );
|
|
|
|
m_zoneId = zoneId;
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-10-05 22:43:15 +02:00
|
|
|
// TODO: logic for instances needs to be added here
|
2017-08-08 13:53:47 +02:00
|
|
|
// see if a valid zone could be found for the character
|
|
|
|
if( !pCurrZone )
|
|
|
|
{
|
2017-10-04 23:28:38 +02:00
|
|
|
g_log.error( "[" + char_id_str + "] Zone " + std::to_string( zoneId ) + " not found!" );
|
2017-08-08 13:53:47 +02:00
|
|
|
g_log.error( "[" + char_id_str + "] Setting default zone instead" );
|
|
|
|
|
|
|
|
// default to new gridania
|
|
|
|
// TODO: should probably just abort and mark character as corrupt
|
|
|
|
pCurrZone = g_zoneMgr.getZone( 132 );
|
|
|
|
|
|
|
|
m_pos.x = 0.0f;
|
|
|
|
m_pos.y = 0.0f;
|
|
|
|
m_pos.z = 0.0f;
|
|
|
|
setRotation( 0.0f );
|
|
|
|
}
|
|
|
|
|
2017-10-04 23:28:38 +02:00
|
|
|
m_hp = res->getUInt( "Hp" );
|
|
|
|
m_mp = res->getUInt( "Mp" );
|
2017-08-08 13:53:47 +02:00
|
|
|
m_tp = 0;
|
|
|
|
|
2017-10-07 23:10:13 +02:00
|
|
|
m_pos.x = res->getFloat( "PosX" );
|
|
|
|
m_pos.y = res->getFloat( "PosY" );
|
|
|
|
m_pos.z = res->getFloat( "PosZ" );
|
|
|
|
setRotation( res->getFloat( "PosR" ) );
|
2017-10-04 23:28:38 +02:00
|
|
|
|
|
|
|
auto custom = res->getBlobVector( "Customize" );
|
|
|
|
memcpy( reinterpret_cast< char* >( m_customize ), custom.data(), custom.size() );
|
|
|
|
|
|
|
|
m_modelMainWeapon = res->getUInt64( "ModelMainWeapon" );
|
|
|
|
|
|
|
|
auto modelEq = res->getBlobVector( "ModelEquip" );
|
|
|
|
memcpy( reinterpret_cast< char* >( m_modelEquip ), modelEq.data(), modelEq.size() );
|
|
|
|
|
2017-10-05 22:43:15 +02:00
|
|
|
m_guardianDeity = res->getUInt8( "GuardianDeity" );
|
|
|
|
m_birthDay = res->getUInt8( "BirthDay" );
|
|
|
|
m_birthMonth = res->getUInt8( "BirthMonth" );
|
2017-10-04 23:28:38 +02:00
|
|
|
m_status = static_cast< ActorStatus >( res->getUInt( "Status" ) );
|
|
|
|
m_class = static_cast< ClassJob >( res->getUInt( "Class" ) );
|
2017-10-05 22:43:15 +02:00
|
|
|
m_homePoint = res->getUInt8( "Homepoint" );
|
2017-10-04 23:28:38 +02:00
|
|
|
|
|
|
|
auto howTo = res->getBlobVector( "HowTo" );
|
|
|
|
memcpy( reinterpret_cast< char* >( m_howTo ), howTo.data(), howTo.size() );
|
|
|
|
|
|
|
|
m_contentId = res->getUInt64( "ContentId" );
|
|
|
|
|
2017-10-05 22:43:15 +02:00
|
|
|
m_voice = res->getUInt8( "Voice" );
|
2017-10-04 23:28:38 +02:00
|
|
|
|
|
|
|
auto questCompleteFlags = res->getBlobVector( "QuestCompleteFlags" );
|
|
|
|
memcpy( reinterpret_cast< char* >( m_questCompleteFlags ), questCompleteFlags.data(), questCompleteFlags.size() );
|
|
|
|
|
|
|
|
auto questTracking = res->getBlobVector( "QuestTracking" );
|
|
|
|
memcpy( reinterpret_cast< char* >( m_questTracking ), questTracking.data(), questTracking.size() );
|
|
|
|
|
|
|
|
m_bNewGame = res->getBoolean( "IsNewGame" );
|
|
|
|
|
|
|
|
auto aetheryte = res->getBlobVector( "Aetheryte" );
|
|
|
|
memcpy( reinterpret_cast< char* >( m_aetheryte ), aetheryte.data(), aetheryte.size() );
|
|
|
|
|
2017-10-07 23:10:13 +02:00
|
|
|
auto unlocks = res->getBlobVector( "Unlocks" );
|
2017-10-04 23:28:38 +02:00
|
|
|
memcpy( reinterpret_cast< char* >( m_unlocks ), unlocks.data(), unlocks.size() );
|
|
|
|
|
|
|
|
auto discovery = res->getBlobVector( "Discovery" );
|
|
|
|
memcpy( reinterpret_cast< char* >( m_discovery ), discovery.data(), discovery.size() );
|
|
|
|
|
2017-10-05 22:43:15 +02:00
|
|
|
m_startTown = res->getUInt8( "StartTown" );
|
2017-10-04 23:28:38 +02:00
|
|
|
m_playTime = res->getUInt( "TotalPlayTime" );
|
|
|
|
|
|
|
|
m_bNewAdventurer = res->getBoolean( "IsNewAdventurer" );
|
|
|
|
|
2017-10-05 22:43:15 +02:00
|
|
|
m_gc = res->getUInt8( "GrandCompany" );
|
2017-10-04 23:28:38 +02:00
|
|
|
auto gcRank = res->getBlobVector( "GrandCompanyRank" );
|
|
|
|
memcpy( reinterpret_cast< char* >( m_gcRank ), gcRank.data(), gcRank.size() );
|
|
|
|
|
|
|
|
m_cfPenaltyUntil = res->getUInt( "CFPenaltyUntil" );
|
|
|
|
|
2017-10-05 22:43:15 +02:00
|
|
|
m_openingSequence = res->getUInt8( "OpeningSequence" );
|
2017-08-19 11:28:04 +09:00
|
|
|
|
2017-10-05 22:43:15 +02:00
|
|
|
m_gmRank = res->getUInt8( "GMRank" );
|
2017-08-20 02:24:19 +02:00
|
|
|
|
2017-10-05 22:43:15 +02:00
|
|
|
res->free();
|
2017-09-11 18:59:50 +02:00
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
m_pCell = nullptr;
|
|
|
|
|
|
|
|
if( !loadActiveQuests() || !loadClassData() || !loadSearchInfo() )
|
|
|
|
g_log.error( "Player id " + char_id_str + " data corrupt!" );
|
|
|
|
|
|
|
|
m_maxHp = getMaxHp();
|
|
|
|
m_maxMp = getMaxMp();
|
|
|
|
|
|
|
|
m_modelSubWeapon = 0;
|
|
|
|
m_lastTickTime = 0;
|
|
|
|
|
|
|
|
auto pPlayer = getAsPlayer();
|
|
|
|
m_pInventory = InventoryPtr( new Inventory( pPlayer ) );
|
|
|
|
|
|
|
|
pPlayer->calculateStats();
|
|
|
|
|
|
|
|
// first login, run the script event
|
|
|
|
if( m_bNewGame )
|
|
|
|
{
|
|
|
|
//g_scriptMgr.onPlayerFirstEnterWorld( pPlayer );
|
|
|
|
m_bNewGame = false;
|
|
|
|
m_hp = getMaxHp();
|
|
|
|
m_mp = getMaxMp();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( m_hp > getMaxHp() )
|
|
|
|
m_hp = getMaxHp();
|
|
|
|
|
|
|
|
if( m_mp > getMaxMp() )
|
|
|
|
m_mp = getMaxMp();
|
|
|
|
|
|
|
|
if( m_hp == 0 )
|
|
|
|
m_status = ActorStatus::Dead;
|
|
|
|
|
2017-08-13 18:28:05 +02:00
|
|
|
// if( m_bNewAdventurer )
|
|
|
|
// setStateFlag( PlayerStateFlag::NewAdventurer );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
setStateFlag( PlayerStateFlag::BetweenAreas );
|
|
|
|
|
|
|
|
m_pInventory->load();
|
|
|
|
|
|
|
|
initHateSlotQueue();
|
|
|
|
|
|
|
|
initSpawnIdQueue();
|
|
|
|
|
|
|
|
m_pStatusEffectContainer = StatusEffect::StatusEffectContainerPtr( new StatusEffect::StatusEffectContainer( shared_from_this() ) );
|
|
|
|
|
|
|
|
if( !m_playerIdToSpawnIdMap.empty() )
|
|
|
|
m_playerIdToSpawnIdMap.clear();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-10-05 22:43:15 +02:00
|
|
|
bool Core::Entity::Player::loadActiveQuests()
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2017-10-05 22:43:15 +02:00
|
|
|
|
2017-10-10 00:03:24 +02:00
|
|
|
auto stmt = g_charaDb.getPreparedStatement( Core::Db::CharaDbStatements::CHARA_QUESTINFO_SEL_LOAD );
|
2017-10-05 22:43:15 +02:00
|
|
|
|
|
|
|
stmt->setUInt( 1, m_id );
|
2017-10-07 23:10:13 +02:00
|
|
|
auto res = g_charaDb.query( stmt );
|
2017-10-05 22:43:15 +02:00
|
|
|
|
|
|
|
if( !res->next() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
auto pQR = g_database.query( "SELECT * FROM charaquest WHERE CharacterId = " + std::to_string( m_id ) + ";" );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
if( !pQR )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Db::Field* field = pQR->fetch();
|
|
|
|
|
2017-10-05 22:43:15 +02:00
|
|
|
for( uint8_t i = 0; i < 30; i++ )
|
|
|
|
{
|
|
|
|
|
|
|
|
uint16_t index = i * 10 + 1;
|
|
|
|
|
|
|
|
if( res->getUInt16( index ) != 0 )
|
|
|
|
{
|
|
|
|
|
|
|
|
boost::shared_ptr<QuestActive> pActiveQuest( new QuestActive() );
|
|
|
|
pActiveQuest->c.questId = res->getUInt16( index );
|
|
|
|
pActiveQuest->c.sequence = res->getUInt8( index + 1 );
|
|
|
|
pActiveQuest->c.flags = res->getUInt8( index + 2 );
|
|
|
|
pActiveQuest->c.UI8A = res->getUInt8( index + 3 );
|
|
|
|
pActiveQuest->c.UI8B = res->getUInt8( index + 4 );
|
|
|
|
pActiveQuest->c.UI8C = res->getUInt8( index + 5 );
|
|
|
|
pActiveQuest->c.UI8D = res->getUInt8( index + 6 );
|
|
|
|
pActiveQuest->c.UI8E = res->getUInt8( index + 7 );
|
|
|
|
pActiveQuest->c.UI8F = res->getUInt8( index + 8 );
|
|
|
|
pActiveQuest->c.padding1 = res->getUInt8( index + 9 );
|
|
|
|
m_activeQuests[i] = pActiveQuest;
|
|
|
|
|
|
|
|
m_questIdToQuestIdx[pActiveQuest->c.questId] = i;
|
|
|
|
m_questIdxToQuestId[i] = pActiveQuest->c.questId;
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_activeQuests[i] = nullptr;
|
|
|
|
m_freeQuestIdxQueue.push( i );
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Core::Entity::Player::loadClassData()
|
|
|
|
{
|
|
|
|
|
2017-10-10 00:03:24 +02:00
|
|
|
auto stmt = g_charaDb.getPreparedStatement( Core::Db::CharaDbStatements::CHARA_CLASSINFO_SEL_LOAD );
|
2017-10-05 22:43:15 +02:00
|
|
|
stmt->setUInt( 1, m_id );
|
2017-10-07 23:10:13 +02:00
|
|
|
auto res = g_charaDb.query( stmt );
|
2017-10-05 22:43:15 +02:00
|
|
|
|
|
|
|
if( !res->next() )
|
|
|
|
return false;
|
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
for( uint8_t i = 0; i < 25; i++ )
|
|
|
|
{
|
|
|
|
uint8_t index = i * 2;
|
2017-10-05 22:43:15 +02:00
|
|
|
m_classArray[i] = res->getUInt16( index + 1 );
|
|
|
|
m_expArray[i] = res->getUInt( index + 2 );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Core::Entity::Player::loadSearchInfo()
|
|
|
|
{
|
2017-10-10 00:03:24 +02:00
|
|
|
auto stmt = g_charaDb.getPreparedStatement( Core::Db::CharaDbStatements::CHARA_SEACHINFO_SEL_LOAD );
|
2017-10-05 22:43:15 +02:00
|
|
|
stmt->setUInt( 1, m_id );
|
2017-10-07 23:10:13 +02:00
|
|
|
auto res = g_charaDb.query( stmt );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
2017-10-05 22:43:15 +02:00
|
|
|
if( !res->next() )
|
2017-08-08 13:53:47 +02:00
|
|
|
return false;
|
|
|
|
|
2017-10-05 22:43:15 +02:00
|
|
|
m_searchSelectClass = res->getUInt8( 1 );
|
|
|
|
m_searchSelectRegion = res->getUInt8( 2 );
|
|
|
|
sprintf( m_searchMessage, res->getString( 3 ).c_str() );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-04 00:02:16 +02:00
|
|
|
void Core::Entity::Player::updateSql()
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
|
|
|
|
2017-10-10 00:03:24 +02:00
|
|
|
/*"Hp 1, Mp 2, Tp 3, Gp 4, Mode 5, Mount 6, InvincibleGM 7, Voice 8, "
|
|
|
|
"Customize 9, ModelMainWeapon 10, ModelSubWeapon 11, ModelSystemWeapon 12, "
|
|
|
|
"ModelEquip 13, EmoteModeType 14, Language 15, IsNewGame 16, IsNewAdventurer 17, "
|
|
|
|
"TerritoryType 18, TerritoryId 19, PosX 20, PosY 21, PosZ 22, PosR 23, "
|
|
|
|
"OTerritoryType 24, OTerritoryId 25, OPosX 26, OPosY 27, OPosZ 28, OPosR 29, "
|
|
|
|
"Class 30, Status 31, TotalPlayTime 32, HomePoint 33, FavoritePoint 34, RestPoint 35, "
|
|
|
|
"ActiveTitle 36, TitleList 37, Achievement 38, Aetheryte 39, HowTo 40, Minions 41, Mounts 42, "
|
|
|
|
"EquippedMannequin 43, ConfigFlags 44, QuestCompleteFlags 45, OpeningSequence 46, "
|
|
|
|
"QuestTracking 47, GrandCompany 48, GrandCompanyRank 49, Discovery 50, GMRank 51, Unlocks 52, "
|
|
|
|
"CFPenaltyUntil 53"*/
|
|
|
|
auto stmt = g_charaDb.getPreparedStatement( Core::Db::CharaDbStatements::CHARA_UP );
|
|
|
|
|
|
|
|
stmt->setInt( 1, getHp() );
|
|
|
|
stmt->setInt( 2, getMp() );
|
|
|
|
stmt->setInt( 3, 0 ); // TP
|
|
|
|
stmt->setInt( 4, 0 ); // GP
|
|
|
|
stmt->setInt( 5, 0 ); // Mode
|
|
|
|
stmt->setInt( 6, 0 ); // Mount
|
|
|
|
stmt->setInt( 7, 0 ); // InvicibleGM
|
|
|
|
stmt->setInt( 8, m_voice );
|
|
|
|
|
|
|
|
std::vector< uint8_t > customVec( sizeof( m_customize ) );
|
|
|
|
memcpy( customVec.data(), m_customize, sizeof( m_customize ) );
|
|
|
|
stmt->setBinary( 9, customVec );
|
|
|
|
|
|
|
|
stmt->setInt64( 10, m_modelMainWeapon );
|
|
|
|
stmt->setInt64( 11, m_modelSubWeapon );
|
|
|
|
stmt->setInt64( 12, m_modelSystemWeapon );
|
|
|
|
|
|
|
|
std::vector< uint8_t > modelVec( sizeof( m_modelEquip ) );
|
|
|
|
memcpy( modelVec.data(), m_modelEquip, sizeof( m_modelEquip ) );
|
|
|
|
stmt->setBinary( 13, modelVec );
|
|
|
|
|
|
|
|
stmt->setInt( 14, 0 ); // EmodeModeType
|
|
|
|
stmt->setInt( 15, 0 ); // Language
|
|
|
|
|
|
|
|
stmt->setInt( 16, static_cast< uint32_t >( m_bNewGame ) );
|
|
|
|
stmt->setInt( 17, static_cast< uint32_t >( m_bNewAdventurer ) );
|
|
|
|
|
|
|
|
stmt->setInt( 18, 0 ); // TerritoryType
|
|
|
|
stmt->setInt( 19, m_zoneId ); // TerritoryId
|
|
|
|
stmt->setDouble( 20, m_pos.x );
|
|
|
|
stmt->setDouble( 21, m_pos.y );
|
|
|
|
stmt->setDouble( 22, m_pos.z );
|
|
|
|
stmt->setDouble( 23, getRotation() );
|
|
|
|
|
|
|
|
stmt->setInt( 24, 0 ); // OTerritoryType
|
|
|
|
stmt->setInt( 25, 0 ); // OTerritoryId
|
|
|
|
stmt->setDouble( 26, 0.0f );
|
|
|
|
stmt->setDouble( 27, 0.0f );
|
|
|
|
stmt->setDouble( 28, 0.0f );
|
|
|
|
stmt->setDouble( 29, 0.0f );
|
|
|
|
|
|
|
|
stmt->setInt( 30, static_cast< uint8_t >( getClass() ) );
|
|
|
|
stmt->setInt( 31, static_cast< uint8_t >( getStatus() ) );
|
|
|
|
stmt->setInt( 32, m_playTime );
|
|
|
|
stmt->setInt( 33, m_homePoint );
|
|
|
|
|
|
|
|
stmt->setBinary( 34, { 0, 0, 0 } ); // FavoritePoint
|
|
|
|
stmt->setInt( 35, 0 ); // RestPoint
|
|
|
|
stmt->setInt( 36, 0 ); // ActiveTitle
|
|
|
|
|
|
|
|
std::vector< uint8_t > titleListVec( 32 );
|
|
|
|
stmt->setBinary( 37, titleListVec );
|
|
|
|
|
|
|
|
std::vector< uint8_t > achievementVec( 16 );
|
|
|
|
stmt->setBinary( 38, achievementVec );
|
|
|
|
|
|
|
|
std::vector< uint8_t > aetheryteVec( sizeof( m_aetheryte ) );
|
|
|
|
memcpy( aetheryteVec.data(), m_aetheryte, sizeof( m_aetheryte ) );
|
|
|
|
stmt->setBinary( 39, aetheryteVec );
|
|
|
|
|
|
|
|
std::vector< uint8_t > howToVec( sizeof( m_howTo ) );
|
|
|
|
memcpy( howToVec.data(), m_howTo, sizeof( m_howTo ) );
|
|
|
|
stmt->setBinary( 40, howToVec );
|
|
|
|
|
|
|
|
std::vector< uint8_t > minionsVec( sizeof( m_minions ) );
|
|
|
|
memcpy( minionsVec.data(), m_minions, sizeof( m_minions ) );
|
|
|
|
stmt->setBinary( 41, minionsVec );
|
|
|
|
|
|
|
|
std::vector< uint8_t > mountsVec( sizeof( m_mounts ) );
|
|
|
|
memcpy( mountsVec.data(), m_mounts, sizeof( m_mounts ) );
|
|
|
|
stmt->setBinary( 42, mountsVec );
|
|
|
|
|
|
|
|
stmt->setInt( 43, 0 ); // EquippedMannequin
|
|
|
|
|
|
|
|
stmt->setInt( 44, 0 ); // DisplayFlags
|
|
|
|
std::vector< uint8_t > questCompleteVec( sizeof( m_questCompleteFlags ) );
|
|
|
|
memcpy( questCompleteVec.data(), m_questCompleteFlags, sizeof( m_questCompleteFlags ) );
|
|
|
|
stmt->setBinary( 45, questCompleteVec );
|
|
|
|
|
|
|
|
stmt->setInt( 46, m_openingSequence );
|
|
|
|
|
|
|
|
std::vector< uint8_t > questTrackerVec( sizeof( m_questTracking ) );
|
|
|
|
memcpy( questTrackerVec.data(), m_questTracking, sizeof( m_questTracking ) );
|
|
|
|
stmt->setBinary( 47, questTrackerVec );
|
|
|
|
|
|
|
|
stmt->setInt( 48, m_gc ); // DisplayFlags
|
|
|
|
|
|
|
|
stmt->setBinary( 49, { m_gcRank[0], m_gcRank[1], m_gcRank[2] } );
|
|
|
|
|
|
|
|
std::vector< uint8_t > discoveryVec( sizeof( m_discovery ) );
|
|
|
|
memcpy( discoveryVec.data(), m_discovery, sizeof( m_discovery ) );
|
|
|
|
stmt->setBinary( 50, discoveryVec );
|
|
|
|
|
|
|
|
stmt->setInt( 51, m_gmRank );
|
|
|
|
|
|
|
|
std::vector< uint8_t > unlockVec( sizeof( m_unlocks ) );
|
|
|
|
memcpy( unlockVec.data(), m_unlocks, sizeof( m_unlocks ) );
|
|
|
|
stmt->setBinary( 52, unlockVec );
|
|
|
|
|
|
|
|
stmt->setInt( 53, m_cfPenaltyUntil );
|
|
|
|
|
|
|
|
stmt->setInt( 54, m_id );
|
|
|
|
|
|
|
|
g_charaDb.execute( stmt );
|
|
|
|
|
2017-08-08 13:53:47 +02:00
|
|
|
std::set< std::string > charaClassSet;
|
|
|
|
std::set< std::string > charaQuestSet;
|
|
|
|
std::set< std::string > charaInfoSearchSet;
|
|
|
|
|
|
|
|
std::string dbName = g_serverZone.getConfig()->getValue< std::string >( "Settings.General.Mysql.Database", "sapphire" );
|
|
|
|
std::string updateCharaClass = "UPDATE " + dbName + ".characlass SET ";
|
|
|
|
std::string updateCharaQuest = "UPDATE " + dbName + ".charaquest SET ";
|
|
|
|
std::string updateCharaInfoSearch = "UPDATE " + dbName + ".charainfosearch SET ";
|
|
|
|
|
|
|
|
std::string condition = " UPDATE_DATE = NOW() WHERE CharacterId = " + std::to_string( m_id ) + ";";
|
|
|
|
|
2017-10-04 00:02:16 +02:00
|
|
|
uint8_t classJobIndex = g_exdData.m_classJobInfoMap[static_cast< uint8_t >( getClass() )].exp_idx;
|
|
|
|
charaClassSet.insert( " Lv_" + std::to_string( classJobIndex ) + " = " + std::to_string( static_cast< uint32_t >( getLevel() ) ) );
|
|
|
|
charaClassSet.insert( " Exp_" + std::to_string( classJobIndex ) + " = " + std::to_string( getExp() ) );
|
|
|
|
|
|
|
|
for( int32_t i = 0; i < 30; i++ )
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2017-10-04 00:02:16 +02:00
|
|
|
if( m_activeQuests[i] != nullptr )
|
|
|
|
{
|
|
|
|
charaQuestSet.insert( " QuestId_" + std::to_string( i ) + " = " + std::to_string( m_activeQuests[i]->c.questId ) );
|
|
|
|
charaQuestSet.insert( " Sequence_" + std::to_string( i ) + " = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.sequence ) ) );
|
|
|
|
charaQuestSet.insert( " Flags_" + std::to_string( i ) + " = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.flags ) ) );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_0 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.UI8A ) ) );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_1 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.UI8B ) ) );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_2 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.UI8C ) ) );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_3 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.UI8D ) ) );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_4 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.UI8E ) ) );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_5 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.UI8F ) ) );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_6 = " + std::to_string( static_cast< uint32_t >( m_activeQuests[i]->c.padding1 ) ) );
|
|
|
|
}
|
|
|
|
else
|
2017-08-08 13:53:47 +02:00
|
|
|
{
|
2017-10-04 00:02:16 +02:00
|
|
|
charaQuestSet.insert( " QuestId_" + std::to_string( i ) + " = 0" );
|
|
|
|
charaQuestSet.insert( " Sequence_" + std::to_string( i ) + " = 0" );
|
|
|
|
charaQuestSet.insert( " Flags_" + std::to_string( i ) + " = 0" );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_0 = 0" );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_1 = 0" );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_2 = 0" );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_3 = 0" );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_4 = 0" );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_5 = 0" );
|
|
|
|
charaQuestSet.insert( " Variables_" + std::to_string( i ) + "_6 = 0" );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-04 00:02:16 +02:00
|
|
|
charaInfoSearchSet.insert( " SelectClassId = " + std::to_string( m_searchSelectClass ) );
|
|
|
|
charaInfoSearchSet.insert( " SelectRegion = " + std::to_string( m_searchSelectRegion ) );
|
|
|
|
charaInfoSearchSet.insert( " SearchComment = UNHEX('" + std::string( Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_searchMessage ), sizeof( m_searchMessage ) ) + "')" ) );
|
2017-08-08 13:53:47 +02:00
|
|
|
|
|
|
|
if( !charaInfoSearchSet.empty() )
|
|
|
|
{
|
|
|
|
for( auto entry : charaInfoSearchSet )
|
|
|
|
updateCharaInfoSearch += entry + ", ";
|
|
|
|
|
|
|
|
updateCharaInfoSearch += condition;
|
2017-09-13 11:46:17 +02:00
|
|
|
g_database.execute( updateCharaInfoSearch );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if( !charaClassSet.empty() )
|
|
|
|
{
|
|
|
|
for( auto entry : charaClassSet )
|
|
|
|
updateCharaClass += entry + ", ";
|
|
|
|
|
|
|
|
updateCharaClass += condition;
|
2017-09-13 11:46:17 +02:00
|
|
|
g_database.execute( updateCharaClass );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if( !charaQuestSet.empty() )
|
|
|
|
{
|
|
|
|
for( auto entry : charaQuestSet )
|
|
|
|
updateCharaQuest += entry + ", ";
|
|
|
|
|
|
|
|
updateCharaQuest += condition;
|
2017-09-13 11:46:17 +02:00
|
|
|
g_database.execute( updateCharaQuest );
|
2017-08-08 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|