1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-21 20:27:46 +00:00
sapphire/src/servers/sapphire_zone/Actor/PlayerSql.cpp

663 lines
22 KiB
C++
Raw Normal View History

#include <set>
2018-03-06 22:22:19 +01:00
#include <Common.h>
#include <Util/Util.h>
#include <Util/UtilMath.h>
#include <Logging/Logger.h>
#include <Exd/ExdDataGenerated.h>
#include <Network/PacketContainer.h>
#include <Common.h>
#include <Database/DatabaseDef.h>
2017-08-08 13:53:47 +02:00
#include "Network/GameConnection.h"
#include "Network/PacketWrappers/InitUIPacket.h"
2017-08-08 13:53:47 +02:00
2018-01-27 23:52:49 +01:00
#include "Zone/TerritoryMgr.h"
#include "Zone/Zone.h"
#include "Inventory/Item.h"
#include "Inventory/ItemContainer.h"
#include "Inventory/ItemUtil.h"
2017-08-08 13:53:47 +02:00
#include "ServerZone.h"
#include "Framework.h"
2018-03-09 00:06:44 +01:00
extern Core::Framework g_fw;
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, SessionPtr pSession )
2017-08-08 13:53:47 +02:00
{
2018-03-09 00:06:44 +01:00
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto pTeriMgr = g_fw.get< TerritoryMgr >();
auto pLog = g_fw.get< Logger >();
2017-08-08 13:53:47 +02:00
const std::string char_id_str = std::to_string( charId );
2018-03-09 00:06:44 +01:00
auto stmt = pDb->getPreparedStatement( Db::CharaDbStatements::CHARA_SEL );
stmt->setUInt( 1, charId );
2018-03-09 00:06:44 +01:00
auto res = pDb->query( stmt );
if( !res->next() )
2017-08-08 13:53:47 +02:00
return false;
m_id = charId;
auto name = res->getString( "Name" );
strcpy( m_name, name.c_str() );
2017-08-08 13:53:47 +02:00
auto zoneId = res->getUInt( "TerritoryId" );
m_prevZoneId = res->getUInt( "OTerritoryId" );
m_prevZoneType = res->getUInt( "OTerritoryType" );
2017-08-08 13:53:47 +02:00
// Position
m_pos.x = res->getFloat( "PosX" );
m_pos.y = res->getFloat( "PosY" );
m_pos.z = res->getFloat( "PosZ" );
setRot( res->getFloat( "PosR" ) );
m_prevPos.x = res->getFloat( "OPosX" );
m_prevPos.y = res->getFloat( "OPosY" );
m_prevPos.z = res->getFloat( "OPosZ" );
m_prevRot = res->getFloat( "OPosR" );
ZonePtr pCurrZone = nullptr;
// if the zone is an instanceContent zone, we need to actually find the instance
2018-03-09 00:06:44 +01:00
if( pTeriMgr->isInstanceContentTerritory( zoneId ) )
{
// try to find an instance actually linked to this player
2018-03-09 00:06:44 +01:00
pCurrZone = pTeriMgr->getLinkedInstance( m_id );
// if none found, revert to previous zone and position
if( !pCurrZone )
{
zoneId = m_prevZoneId;
m_pos.x = m_prevPos.x;
m_pos.y = m_prevPos.y;
m_pos.z = m_prevPos.z;
setRot( m_prevRot );
2018-03-09 00:06:44 +01:00
pCurrZone = pTeriMgr->getZoneByTerriId( zoneId );
}
}
else
{
2018-03-09 00:06:44 +01:00
pCurrZone =pTeriMgr->getZoneByTerriId( zoneId );
}
m_zoneId = zoneId;
2017-08-08 13:53:47 +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 )
{
2018-03-09 00:06:44 +01:00
pLog->error( "[" + char_id_str + "] Zone " + std::to_string( zoneId ) + " not found!" );
pLog->error( "[" + char_id_str + "] Setting default zone instead" );
2017-08-08 13:53:47 +02:00
// default to new gridania
// TODO: should probably just abort and mark character as corrupt
2018-03-09 00:06:44 +01:00
pCurrZone = pTeriMgr->getZoneByTerriId( 132 );
2017-08-08 13:53:47 +02:00
m_pos.x = 0.0f;
m_pos.y = 0.0f;
m_pos.z = 0.0f;
setRot( 0.0f );
2017-08-08 13:53:47 +02:00
}
// Stats
m_hp = res->getUInt( "Hp" );
m_mp = res->getUInt( "Mp" );
2017-08-08 13:53:47 +02:00
m_tp = 0;
// Model
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() );
// Minimal info
m_guardianDeity = res->getUInt8( "GuardianDeity" );
m_birthDay = res->getUInt8( "BirthDay" );
m_birthMonth = res->getUInt8( "BirthMonth" );
m_status = static_cast< ActorStatus >( res->getUInt( "Status" ) );
m_emoteMode = res->getUInt( "EmoteModeType" );
m_activeTitle = res->getUInt16( "ActiveTitle" );
m_class = static_cast< ClassJob >( res->getUInt( "Class" ) );
m_homePoint = res->getUInt8( "Homepoint" );
// Additional data
m_contentId = res->getUInt64( "ContentId" );
m_voice = res->getUInt8( "Voice" );
m_startTown = res->getUInt8( "StartTown" );
m_playTime = res->getUInt( "TotalPlayTime" );
m_bNewGame = res->getBoolean( "IsNewGame" );
m_bNewAdventurer = res->getBoolean( "IsNewAdventurer" );
m_openingSequence = res->getUInt8( "OpeningSequence" );
m_gc = res->getUInt8( "GrandCompany" );
m_cfPenaltyUntil = res->getUInt( "CFPenaltyUntil" );
m_activeTitle = res->getUInt16( "ActiveTitle" );
m_gmRank = res->getUInt8( "GMRank" );
m_equipDisplayFlags = res->getUInt8( "EquipDisplayFlags" );
m_pose = res->getUInt8( "Pose" );
// Blobs
auto howTo = res->getBlobVector( "HowTo" );
memcpy( reinterpret_cast< char* >( m_howTo ), howTo.data(), howTo.size() );
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() );
auto aetheryte = res->getBlobVector( "Aetheryte" );
memcpy( reinterpret_cast< char* >( m_aetheryte ), aetheryte.data(), aetheryte.size() );
auto unlocks = res->getBlobVector( "Unlocks" );
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() );
auto titleList = res->getBlobVector( "TitleList" );
memcpy( reinterpret_cast< char* >( m_titleList ), titleList.data(), titleList.size() );
auto mountGuide = res->getBlobVector( "Mounts" );
memcpy( reinterpret_cast< char* >( m_mountGuide ), mountGuide.data(), mountGuide.size() );
auto orchestrion = res->getBlobVector( "Orchestrion" );
memcpy( reinterpret_cast< char* >( m_orchestrion ), orchestrion.data(), orchestrion.size() );
auto gcRank = res->getBlobVector( "GrandCompanyRank" );
memcpy( reinterpret_cast< char* >( m_gcRank ), gcRank.data(), gcRank.size() );
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() )
2018-03-09 00:06:44 +01:00
pLog->error( "Player id " + char_id_str + " data corrupt!" );
2017-08-08 13:53:47 +02:00
m_maxHp = getMaxHp();
m_maxMp = getMaxMp();
2017-11-21 17:39:10 +11:00
m_mount = res->getUInt8( "Mount" );
2017-08-08 13:53:47 +02:00
m_modelSubWeapon = 0;
m_lastTickTime = 0;
calculateStats();
2017-08-08 13:53:47 +02:00
// first login, run the script event
if( m_bNewGame )
{
//g_framework.getScriptMgr().onPlayerFirstEnterWorld( pPlayer );
2017-08-08 13:53:47 +02:00
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;
// if( m_bNewAdventurer )
// setStateFlag( PlayerStateFlag::NewAdventurer );
2017-08-08 13:53:47 +02:00
setStateFlag( PlayerStateFlag::BetweenAreas );
//m_pInventory->load();
initInventory();
2017-08-08 13:53:47 +02:00
initHateSlotQueue();
initSpawnIdQueue();
2018-03-09 00:06:44 +01:00
if( !pTeriMgr->movePlayer( pCurrZone, getAsPlayer() ) )
return false;
2017-08-08 13:53:47 +02:00
return true;
}
bool Core::Entity::Player::loadActiveQuests()
2017-08-08 13:53:47 +02:00
{
2018-03-09 00:06:44 +01:00
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto stmt = pDb->getPreparedStatement( Db::CharaDbStatements::CHARA_QUEST_SEL );
stmt->setUInt( 1, m_id );
2018-03-09 00:06:44 +01:00
auto res = pDb->query( stmt );
while( res->next() )
{
2017-10-15 23:16:28 +02:00
auto slotId = res->getUInt8( 2 );
2017-10-15 23:16:28 +02:00
boost::shared_ptr< QuestActive > pActiveQuest( new QuestActive() );
pActiveQuest->c.questId = res->getUInt16( 3 );
pActiveQuest->c.sequence = res->getUInt8( 4 );
pActiveQuest->c.flags = res->getUInt8( 5 );
pActiveQuest->c.UI8A = res->getUInt8( 6 );
pActiveQuest->c.UI8B = res->getUInt8( 7 );
pActiveQuest->c.UI8C = res->getUInt8( 8 );
pActiveQuest->c.UI8D = res->getUInt8( 9 );
pActiveQuest->c.UI8E = res->getUInt8( 10 );
pActiveQuest->c.UI8F = res->getUInt8( 11 );
pActiveQuest->c.padding1 = res->getUInt8( 12 );
m_activeQuests[slotId] = pActiveQuest;
m_questIdToQuestIdx[pActiveQuest->c.questId] = slotId;
m_questIdxToQuestId[slotId] = pActiveQuest->c.questId;
}
return true;
}
bool Core::Entity::Player::loadClassData()
{
2018-03-09 00:06:44 +01:00
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
2017-10-18 20:49:37 +02:00
// ClassIdx, Exp, Lvl
2018-03-09 00:06:44 +01:00
auto stmt = pDb->getPreparedStatement( Db::CharaDbStatements::CHARA_CLASS_SEL );
stmt->setUInt( 1, m_id );
2018-03-09 00:06:44 +01:00
auto res = pDb->query( stmt );
2017-10-18 20:49:37 +02:00
while( res->next() )
2017-08-08 13:53:47 +02:00
{
2017-10-18 20:49:37 +02:00
auto index = res->getUInt16( 1 );
auto exp = res->getUInt( 2 );
auto lvl = res->getUInt8( 3 );
m_classArray[index] = lvl;
m_expArray[index] = exp;
2017-08-08 13:53:47 +02:00
}
return true;
}
bool Core::Entity::Player::loadSearchInfo()
{
2018-03-09 00:06:44 +01:00
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto stmt = pDb->getPreparedStatement( Db::CharaDbStatements::CHARA_SEARCHINFO_SEL );
stmt->setUInt( 1, m_id );
2018-03-09 00:06:44 +01:00
auto res = pDb->query( stmt );
2017-08-08 13:53:47 +02:00
if( !res->next() )
2017-08-08 13:53:47 +02:00
return false;
m_searchSelectClass = res->getUInt8( 2 );
m_searchSelectRegion = res->getUInt8( 3 );
2018-02-15 19:44:54 +11:00
// todo: internally use an std::string instead of a char[]
auto searchMessage = res->getString( 4 );
2018-02-15 19:27:44 +11:00
std::copy( searchMessage.begin(), searchMessage.end(), m_searchMessage );
2017-08-08 13:53:47 +02:00
return true;
}
void Core::Entity::Player::updateSql()
2017-08-08 13:53:47 +02:00
{
2018-03-09 00:06:44 +01:00
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
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, Orchestrion 43, "
"EquippedMannequin 44, ConfigFlags 45, QuestCompleteFlags 46, OpeningSequence 47, "
"QuestTracking 48, GrandCompany 49, GrandCompanyRank 50, Discovery 51, GMRank 52, Unlocks 53, "
"CFPenaltyUntil 54, Pose 55"*/
2018-03-09 00:06:44 +01:00
auto stmt = pDb->getPreparedStatement( Db::CharaDbStatements::CHARA_UP );
2017-10-10 00:03:24 +02:00
stmt->setInt( 1, getHp() );
stmt->setInt( 2, getMp() );
stmt->setInt( 3, 0 ); // TP
stmt->setInt( 4, 0 ); // GP
stmt->setInt( 5, 0 ); // Mode
2017-11-21 17:39:10 +11:00
stmt->setInt( 6, m_mount ); // Mount
2017-10-10 00:03:24 +02:00
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, m_emoteMode ); // EmodeModeType
2017-10-10 00:03:24 +02:00
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, getRot() );
2017-10-10 00:03:24 +02:00
stmt->setInt( 24, m_prevZoneType ); // OTerritoryType
stmt->setInt( 25, m_prevZoneId ); // OTerritoryId
stmt->setDouble( 26, m_prevPos.x );
stmt->setDouble( 27, m_prevPos.y );
stmt->setDouble( 28, m_prevPos.z );
stmt->setDouble( 29, m_prevRot );
2017-10-10 00:03:24 +02:00
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, m_activeTitle ); // ActiveTitle
2017-10-10 00:03:24 +02:00
std::vector< uint8_t > titleListVec( sizeof ( m_titleList ) );
2017-10-10 00:03:24 +02:00
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_mountGuide ) );
memcpy( mountsVec.data(), m_mountGuide, sizeof( m_mountGuide ) );
2017-10-10 00:03:24 +02:00
stmt->setBinary( 42, mountsVec );
std::vector< uint8_t > orchestrionVec( sizeof( m_orchestrion ) );
memcpy( orchestrionVec.data(), m_orchestrion, sizeof( m_orchestrion ) );
stmt->setBinary( 42, mountsVec );
2017-10-10 00:03:24 +02:00
stmt->setInt( 44, 0 ); // EquippedMannequin
stmt->setInt( 45, 0 ); // DisplayFlags
2017-10-10 00:03:24 +02:00
std::vector< uint8_t > questCompleteVec( sizeof( m_questCompleteFlags ) );
memcpy( questCompleteVec.data(), m_questCompleteFlags, sizeof( m_questCompleteFlags ) );
stmt->setBinary( 46, questCompleteVec );
2017-10-10 00:03:24 +02:00
stmt->setInt( 47, m_openingSequence );
2017-10-10 00:03:24 +02:00
std::vector< uint8_t > questTrackerVec( sizeof( m_questTracking ) );
memcpy( questTrackerVec.data(), m_questTracking, sizeof( m_questTracking ) );
stmt->setBinary( 48, questTrackerVec );
2017-10-10 00:03:24 +02:00
stmt->setInt( 49, m_gc ); // DisplayFlags
2017-10-10 00:03:24 +02:00
stmt->setBinary( 50, { m_gcRank[0], m_gcRank[1], m_gcRank[2] } );
2017-10-10 00:03:24 +02:00
std::vector< uint8_t > discoveryVec( sizeof( m_discovery ) );
memcpy( discoveryVec.data(), m_discovery, sizeof( m_discovery ) );
stmt->setBinary( 51, discoveryVec );
2017-10-10 00:03:24 +02:00
stmt->setInt( 52, m_gmRank );
2017-10-10 00:03:24 +02:00
stmt->setInt( 53, m_equipDisplayFlags );
2017-10-10 00:03:24 +02:00
std::vector< uint8_t > unlockVec( sizeof( m_unlocks ) );
memcpy( unlockVec.data(), m_unlocks, sizeof( m_unlocks ) );
stmt->setBinary( 54, unlockVec );
2017-10-10 00:03:24 +02:00
stmt->setInt( 55, m_cfPenaltyUntil );
2017-10-10 00:03:24 +02:00
stmt->setInt( 56, m_pose );
stmt->setInt( 57, m_id );
2017-10-10 00:03:24 +02:00
2018-03-09 00:06:44 +01:00
pDb->execute( stmt );
2017-10-10 00:03:24 +02:00
////// Searchinfo
2017-10-18 20:49:37 +02:00
updateDbSearchInfo();
////// QUESTS
updateDbAllQuests();
////// Class
updateDbClass();
}
void Core::Entity::Player::updateDbClass() const
{
2018-03-09 00:06:44 +01:00
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
uint8_t classJobIndex = pExdData->get< Core::Data::ClassJob >( static_cast<uint8_t>( getClass() ) )->expArrayIndex;
2017-10-18 20:49:37 +02:00
//Exp = ?, Lvl = ? WHERE CharacterId = ? AND ClassIdx = ?
2018-03-09 00:06:44 +01:00
auto stmtS = pDb->getPreparedStatement( Db::CHARA_CLASS_UP );
stmtS->setInt( 1, getExp() );
stmtS->setInt( 2, getLevel() );
2017-10-18 20:49:37 +02:00
stmtS->setInt( 3, m_id );
stmtS->setInt( 4, classJobIndex );
2018-03-09 00:06:44 +01:00
pDb->execute( stmtS );
2017-10-18 20:49:37 +02:00
}
void Core::Entity::Player::insertDbClass( const uint8_t classJobIndex ) const
{
2018-03-09 00:06:44 +01:00
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto stmtClass = pDb->getPreparedStatement( Db::CHARA_CLASS_INS );
stmtClass->setInt( 1, getId() );
stmtClass->setInt( 2, classJobIndex );
stmtClass->setInt( 3, 0 );
stmtClass->setInt( 4, 1 );
2018-03-09 00:06:44 +01:00
pDb->directExecute( stmtClass );
}
2017-10-18 20:49:37 +02:00
void Core::Entity::Player::updateDbSearchInfo() const
{
2018-03-09 00:06:44 +01:00
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto stmtS = pDb->getPreparedStatement( Db::CHARA_SEARCHINFO_UP_SELECTCLASS );
stmtS->setInt( 1, m_searchSelectClass );
stmtS->setInt( 2, m_id );
2018-03-09 00:06:44 +01:00
pDb->execute( stmtS );
2018-03-09 00:06:44 +01:00
auto stmtS1 = pDb->getPreparedStatement( Db::CHARA_SEARCHINFO_UP_SELECTREGION );
stmtS1->setInt( 1, m_searchSelectRegion );
stmtS1->setInt( 2, m_id );
2018-03-09 00:06:44 +01:00
pDb->execute( stmtS1 );
auto stmtS2 = pDb->getPreparedStatement( Db::CHARA_SEARCHINFO_UP_SEARCHCOMMENT );
2017-10-18 20:49:37 +02:00
stmtS2->setString( 1, string( m_searchMessage != nullptr ? m_searchMessage : "" ) );
stmtS2->setInt( 2, m_id );
2018-03-09 00:06:44 +01:00
pDb->execute( stmtS2 );
}
2017-08-08 13:53:47 +02:00
2017-10-18 20:49:37 +02:00
void Core::Entity::Player::updateDbAllQuests() const
{
2018-03-09 00:06:44 +01:00
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
for( int32_t i = 0; i < 30; i++ )
2017-08-08 13:53:47 +02:00
{
2017-10-18 20:49:37 +02:00
if( !m_activeQuests[i] )
continue;
2018-03-09 00:06:44 +01:00
auto stmtS3 = pDb->getPreparedStatement( Db::CHARA_QUEST_UP );
2017-10-18 20:49:37 +02:00
stmtS3->setInt( 1, m_activeQuests[i]->c.sequence );
stmtS3->setInt( 2, m_activeQuests[i]->c.flags );
stmtS3->setInt( 3, m_activeQuests[i]->c.UI8A );
stmtS3->setInt( 4, m_activeQuests[i]->c.UI8B );
stmtS3->setInt( 5, m_activeQuests[i]->c.UI8C );
stmtS3->setInt( 6, m_activeQuests[i]->c.UI8D );
stmtS3->setInt( 7, m_activeQuests[i]->c.UI8E );
stmtS3->setInt( 8, m_activeQuests[i]->c.UI8F );
stmtS3->setInt( 9, m_activeQuests[i]->c.padding1 );
stmtS3->setInt( 10, m_id);
stmtS3->setInt( 11, m_activeQuests[i]->c.questId );
2018-03-09 00:06:44 +01:00
pDb->execute( stmtS3 );
2017-10-18 20:49:37 +02:00
2017-08-08 13:53:47 +02:00
}
}
void Core::Entity::Player::deleteQuest( uint16_t questId ) const
{
2018-03-09 00:06:44 +01:00
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto stmt = pDb->getPreparedStatement( Db::CHARA_QUEST_DEL );
stmt->setInt( 1, m_id );
stmt->setInt( 2, questId );
2018-03-09 00:06:44 +01:00
pDb->execute( stmt );
}
2017-08-08 13:53:47 +02:00
void Core::Entity::Player::insertQuest( uint16_t questId, uint8_t index, uint8_t seq ) const
{
2018-03-09 00:06:44 +01:00
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto stmt = pDb->getPreparedStatement( Db::CHARA_QUEST_INS );
stmt->setInt( 1, m_id );
stmt->setInt( 2, index );
stmt->setInt( 3, questId );
stmt->setInt( 4, seq );
stmt->setInt( 5, 0 );
stmt->setInt( 6, 0 );
stmt->setInt( 7, 0 );
stmt->setInt( 8, 0 );
stmt->setInt( 9, 0 );
stmt->setInt( 10, 0 );
stmt->setInt( 11, 0 );
stmt->setInt( 12, 0 );
2018-03-09 00:06:44 +01:00
pDb->execute( stmt );
}
Core::ItemPtr Core::Entity::Player::createItem( uint32_t catalogId, uint16_t quantity )
{
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto itemInfo = pExdData->get< Core::Data::Item >( catalogId );
if( !itemInfo )
return nullptr;
uint16_t itemAmount = quantity;
if( itemInfo->stackSize == 1 )
itemAmount = 1;
if( !itemInfo )
return nullptr;
uint8_t flags = 0;
ItemPtr pItem = make_Item( Items::Util::getNextUId(),
catalogId,
itemInfo->modelMain,
itemInfo->modelSub );
pItem->setStackSize( itemAmount );
pDb->execute( "INSERT INTO charaglobalitem ( CharacterId, itemId, catalogId, stack, flags ) VALUES ( " +
std::to_string( getId() ) + ", " +
std::to_string( pItem->getUId() ) + ", " +
std::to_string( pItem->getId() ) + ", " +
std::to_string( itemAmount ) + ", " +
std::to_string( flags ) + ");" );
return pItem;
}
bool Core::Entity::Player::loadInventory()
{
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
//////////////////////////////////////////////////////////////////////////////////////////////////////
// load active gearset
auto res = pDb->query( "SELECT storageId, container_0, container_1, container_2, container_3, "
"container_4, container_5, container_6, container_7, "
"container_8, container_9, container_10, container_11, "
"container_12, container_13 "
"FROM charaitemgearset " \
"WHERE CharacterId = " + std::to_string( getId() ) + " " \
"ORDER BY storageId ASC;" );
while( res->next() )
{
uint16_t storageId = res->getUInt16( 1 );
for( uint32_t i = 1; i <= 14; i++ )
{
uint64_t uItemId = res->getUInt64( i + 1 );
if( uItemId == 0 )
continue;
ItemPtr pItem = Items::Util::loadItem( uItemId );
if( pItem == nullptr )
continue;
m_inventoryMap[storageId]->getItemMap()[i - 1] = pItem;
equipItem( static_cast< EquipSlot >( i - 1 ), pItem, false );
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
2018-07-26 23:12:02 +10:00
// Load everything
auto bagRes = pDb->query( "SELECT storageId, "
"container_0, container_1, container_2, container_3, container_4, "
"container_5, container_6, container_7, container_8, container_9, "
"container_10, container_11, container_12, container_13, container_14, "
"container_15, container_16, container_17, container_18, container_19, "
"container_20, container_21, container_22, container_23, container_24, "
"container_25, container_26, container_27, container_28, container_29, "
"container_30, container_31, container_32, container_33, container_34 "
"FROM charaiteminventory " \
"WHERE CharacterId = " + std::to_string( getId() ) + " " \
"ORDER BY storageId ASC;" );
while( bagRes->next() )
{
uint16_t storageId = bagRes->getUInt16( 1 );
2018-07-26 23:12:02 +10:00
for( uint32_t i = 1; i <= m_inventoryMap[storageId]->getMaxSize(); i++ )
{
uint64_t uItemId = bagRes->getUInt64( i + 1 );
if( uItemId == 0 )
continue;
ItemPtr pItem = Items::Util::loadItem( uItemId );
if( pItem == nullptr )
continue;
m_inventoryMap[storageId]->getItemMap()[i - 1] = pItem;
}
}
return true;
}