1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-03 17:27:47 +00:00

Cleanups in player

This commit is contained in:
Mordred 2025-01-02 09:22:10 +01:00
parent 4a46b3dd80
commit 168cfb1a36
11 changed files with 196 additions and 147 deletions

View file

@ -38,6 +38,7 @@ namespace Sapphire::Common
const uint16_t ARRSIZE_ORCHESTRION = 40u; const uint16_t ARRSIZE_ORCHESTRION = 40u;
const uint16_t ARRSIZE_MONSTERNOTE = 12u; const uint16_t ARRSIZE_MONSTERNOTE = 12u;
const uint16_t ARRSIZE_BORROWACTION = 10u; const uint16_t ARRSIZE_BORROWACTION = 10u;
const uint16_t ARRSIZE_CONDITION = 12u;
const uint8_t TOWN_COUNT = 6; const uint8_t TOWN_COUNT = 6;

View file

@ -707,7 +707,7 @@ void BNpc::onDeath()
if( pPlayer ) if( pPlayer )
{ {
playerMgr.onMobKill( *pPlayer, *this ); playerMgr.onMobKill( *pPlayer, *this );
pPlayer->gainExp( paramGrowthInfo->data().BaseExp ); playerMgr.onGainExp( *pPlayer, paramGrowthInfo->data().BaseExp );
} }
} }

View file

@ -474,60 +474,6 @@ Player::Discovery& Player::getDiscoveryBitmask()
return m_discovery; return m_discovery;
} }
void Player::discover( int16_t mapId, int16_t subId )
{
auto& exdData = Common::Service< Data::ExdData >::ref();
int32_t offset;
auto info = exdData.getRow< Excel::Map >( mapId );
if( !info )
{
PlayerMgr::sendDebug( *this, "discover(): Could not obtain map data for map_id == {0}", mapId );
return;
}
const auto& mapData = info->data();
if( mapData.IsUint16Discovery )
offset = 2 * mapData.DiscoveryIndex;
else
offset = 320 + 4 * mapData.DiscoveryIndex;
uint16_t index;
uint8_t value;
Util::valueToFlagByteIndexValue( subId, value, index );
m_discovery[ offset + index ] |= value;
uint16_t level = getLevel();
uint32_t exp = ( exdData.getRow< Excel::ParamGrow >( level )->data().NextExp * 5 / 100 );
gainExp( exp );
// gain 10x additional EXP if entire map is completed
uint32_t mask = mapData.DiscoveryFlag;
uint32_t discoveredAreas;
if( info->data().IsUint16Discovery )
{
discoveredAreas = ( m_discovery[ offset + 1 ] << 8 ) | m_discovery[ offset ];
}
else
{
discoveredAreas = ( m_discovery[ offset + 3 ] << 24 ) |
( m_discovery[ offset + 2 ] << 16 ) |
( m_discovery[ offset + 1 ] << 8 ) |
m_discovery[ offset ];
}
bool allDiscovered = ( ( discoveredAreas & mask ) == mask );
if( allDiscovered )
{
gainExp( exp * 10 );
}
}
bool Player::isNewAdventurer() const bool Player::isNewAdventurer() const
{ {
return m_bNewAdventurer; return m_bNewAdventurer;
@ -621,13 +567,13 @@ bool Player::hasMount( uint32_t mountId ) const
void Player::gainExp( uint32_t amount ) void Player::gainExp( uint32_t amount )
{ {
uint32_t currentExp = getExp(); uint32_t currentExp = getCurrentExp();
uint16_t level = getLevel(); uint16_t level = getLevel();
auto currentClass = static_cast< uint8_t >( getClass() ); auto currentClass = static_cast< uint8_t >( getClass() );
if( level >= Common::MAX_PLAYER_LEVEL ) if( level >= Common::MAX_PLAYER_LEVEL )
{ {
setExp( 0 ); setCurrentExp( 0 );
if( currentExp != 0 ) if( currentExp != 0 )
Network::Util::Packet::sendActorControlSelf( *this, getId(), UpdateUiExp, currentClass, 0 ); Network::Util::Packet::sendActorControlSelf( *this, getId(), UpdateUiExp, currentClass, 0 );
@ -647,14 +593,14 @@ void Player::gainExp( uint32_t amount )
if( level + 1 >= Common::MAX_PLAYER_LEVEL ) if( level + 1 >= Common::MAX_PLAYER_LEVEL )
amount = 0; amount = 0;
setExp( amount ); setCurrentExp( amount );
levelUp(); levelUp();
} }
else else
setExp( currentExp + amount ); setCurrentExp( currentExp + amount );
Network::Util::Packet::sendActorControlSelf( *this, getId(), GainExpMsg, currentClass, amount ); Network::Util::Packet::sendActorControlSelf( *this, getId(), GainExpMsg, currentClass, amount );
Network::Util::Packet::sendActorControlSelf( *this, getId(), UpdateUiExp, currentClass, getExp() ); Network::Util::Packet::sendActorControlSelf( *this, getId(), UpdateUiExp, currentClass, getCurrentExp() );
} }
void Player::levelUp() void Player::levelUp()
@ -696,14 +642,14 @@ bool Player::isClassJobUnlocked( Common::ClassJob classJob ) const
return getLevelForClass( classJob ) != 0; return getLevelForClass( classJob ) != 0;
} }
uint32_t Player::getExp() const uint32_t Player::getCurrentExp() const
{ {
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
uint8_t classJobIndex = exdData.getRow< Excel::ClassJob >( static_cast< uint8_t >( getClass() ) )->data().WorkIndex; uint8_t classJobIndex = exdData.getRow< Excel::ClassJob >( static_cast< uint8_t >( getClass() ) )->data().WorkIndex;
return m_expArray[ classJobIndex ]; return m_expArray[ classJobIndex ];
} }
void Player::setExp( uint32_t amount ) void Player::setCurrentExp( uint32_t amount )
{ {
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
uint8_t classJobIndex = exdData.getRow< Excel::ClassJob >( static_cast< uint8_t >( getClass() ) )->data().WorkIndex; uint8_t classJobIndex = exdData.getRow< Excel::ClassJob >( static_cast< uint8_t >( getClass() ) )->data().WorkIndex;
@ -1591,75 +1537,6 @@ Sapphire::Common::HuntingLogEntry& Player::getHuntingLogEntry( uint8_t index )
return m_huntingLogEntries[ index ]; return m_huntingLogEntries[ index ];
} }
void Player::updateHuntingLog( uint16_t id )
{
std::vector< uint32_t > rankRewards{ 2500, 10000, 20000, 30000, 40000 };
const auto maxRank = 4;
auto& pExdData = Common::Service< Data::ExdData >::ref();
// make sure we get the matching base-class if a job is being used
auto classJobInfo = pExdData.getRow< Excel::ClassJob >( static_cast< uint8_t >( getClass() ) );
if( !classJobInfo )
return;
auto currentClassId = classJobInfo->data().MainClass;
auto& logEntry = m_huntingLogEntries[ currentClassId - 1 ];
bool logChanged = false;
bool allSectionsComplete = true;
for( int i = 1; i <= 10; ++i )
{
bool sectionComplete = true;
bool sectionChanged = false;
auto monsterNoteId = static_cast< uint32_t >( classJobInfo->data().MainClass * 10000 + logEntry.rank * 10 + i );
auto note = pExdData.getRow< Excel::MonsterNote >( monsterNoteId );
// for classes that don't have entries, if the first fails the rest will fail
if( !note )
break;
for( auto x = 0; x < 4; ++x )
{
auto note1 = pExdData.getRow< Excel::MonsterNoteTarget >( note->data().Target[ x ] );
if( note1->data().Monster == id && logEntry.entries[ i - 1 ][ x ] < note->data().NeededKills[ x ] )
{
logEntry.entries[ i - 1 ][ x ]++;
Network::Util::Packet::sendActorControlSelf( *this, getId(), HuntingLogEntryUpdate, monsterNoteId, x, logEntry.entries[ i - 1 ][ x ] );
logChanged = true;
sectionChanged = true;
}
if( logEntry.entries[ i - 1 ][ x ] != note->data().NeededKills[ x ] )
sectionComplete = false;
}
if( logChanged && sectionComplete && sectionChanged )
{
Network::Util::Packet::sendActorControlSelf( *this, getId(), HuntingLogSectionFinish, monsterNoteId, i, 0 );
gainExp( note->data().RewardExp );
}
if( !sectionComplete )
{
allSectionsComplete = false;
}
}
if( logChanged && allSectionsComplete )
{
Network::Util::Packet::sendActorControlSelf( *this, getId(), HuntingLogRankFinish, 4 );
gainExp( rankRewards[ logEntry.rank ] );
if( logEntry.rank < 4 )
{
logEntry.rank++;
memset( logEntry.entries, 0, 40 );
Network::Util::Packet::sendActorControlSelf( *this, getId(), HuntingLogRankUnlock, currentClassId, logEntry.rank + 1, 0 );
}
}
if( logChanged )
Network::Util::Packet::sendHuntingLog( *this );
}
void Player::setActiveLand( uint8_t land, uint8_t ward ) void Player::setActiveLand( uint8_t land, uint8_t ward )
{ {
m_activeLand.plot = land; m_activeLand.plot = land;

View file

@ -34,7 +34,7 @@ namespace Sapphire::Entity
using AetheryteList = std::array< uint8_t, Common::ARRSIZE_AETHERYTES >; using AetheryteList = std::array< uint8_t, Common::ARRSIZE_AETHERYTES >;
using UnlockList = std::array< uint8_t, Common::ARRSIZE_UNLOCKS >; using UnlockList = std::array< uint8_t, Common::ARRSIZE_UNLOCKS >;
using OrchestrionList = std::array< uint8_t, Common::ARRSIZE_ORCHESTRION >; using OrchestrionList = std::array< uint8_t, Common::ARRSIZE_ORCHESTRION >;
using Condition = std::array< uint8_t, 12 >; using Condition = std::array< uint8_t, Common::ARRSIZE_CONDITION >;
using ClassList = std::array< uint16_t, Common::ARRSIZE_CLASSJOB >; using ClassList = std::array< uint16_t, Common::ARRSIZE_CLASSJOB >;
using ExpList = std::array< uint32_t, Common::ARRSIZE_CLASSJOB >; using ExpList = std::array< uint32_t, Common::ARRSIZE_CLASSJOB >;
@ -215,10 +215,10 @@ namespace Sapphire::Entity
bool isClassJobUnlocked( Common::ClassJob classJob ) const; bool isClassJobUnlocked( Common::ClassJob classJob ) const;
/*! returns the exp of the currently active class / job */ /*! returns the exp of the currently active class / job */
uint32_t getExp() const; uint32_t getCurrentExp() const;
/*! sets the exp of the currently active class / job */ /*! sets the exp of the currently active class / job */
void setExp( uint32_t amount ); void setCurrentExp( uint32_t amount );
/*! adds exp to the currently active class / job */ /*! adds exp to the currently active class / job */
void gainExp( uint32_t amount ); void gainExp( uint32_t amount );
@ -423,9 +423,6 @@ namespace Sapphire::Entity
/*! get homepoint */ /*! get homepoint */
uint8_t getHomepoint() const; uint8_t getHomepoint() const;
/*! discover subarea subid fo map map_id, also send udpate packet */
void discover( int16_t mapId, int16_t subId );
/*! return a reference to the discovery bitmask array */ /*! return a reference to the discovery bitmask array */
Discovery& getDiscoveryBitmask(); Discovery& getDiscoveryBitmask();
@ -781,8 +778,6 @@ namespace Sapphire::Entity
Common::HuntingLogEntry& getHuntingLogEntry( uint8_t index ); Common::HuntingLogEntry& getHuntingLogEntry( uint8_t index );
void updateHuntingLog( uint16_t id );
uint64_t getPartyId() const; uint64_t getPartyId() const;
void setPartyId( uint64_t partyId ); void setPartyId( uint64_t partyId );

View file

@ -493,7 +493,7 @@ void Player::updateDbClass() const
//Exp = ?, Lvl = ?, BorrowAction = ? WHERE CharacterId = ? AND ClassIdx = ? //Exp = ?, Lvl = ?, BorrowAction = ? WHERE CharacterId = ? AND ClassIdx = ?
auto stmtS = db.getPreparedStatement( Db::CHARA_CLASS_UP ); auto stmtS = db.getPreparedStatement( Db::CHARA_CLASS_UP );
stmtS->setInt( 1, getExp() ); stmtS->setInt( 1, getCurrentExp() );
stmtS->setInt( 2, getLevel() ); stmtS->setInt( 2, getLevel() );
std::vector< uint8_t > borrowActionVec( borrowAction.size() * 4 ); std::vector< uint8_t > borrowActionVec( borrowAction.size() * 4 );

View file

@ -3,7 +3,7 @@
#include <Service.h> #include <Service.h>
#include <Exd/ExdData.h> #include <Exd/ExdData.h>
#include <Util/Util.h>
#include <Territory/Land.h> #include <Territory/Land.h>
#include <Manager/TerritoryMgr.h> #include <Manager/TerritoryMgr.h>
@ -206,7 +206,7 @@ void PlayerMgr::onMobKill( Entity::Player& player, Entity::BNpc& bnpc )
scriptMgr.onBNpcKill( player, bnpc ); scriptMgr.onBNpcKill( player, bnpc );
if( player.hasReward( Common::UnlockEntry::HuntingLog ) ) if( player.hasReward( Common::UnlockEntry::HuntingLog ) )
player.updateHuntingLog( bnpc.getBNpcNameId() ); onUpdateHuntingLog( player, bnpc.getBNpcNameId() );
} }
void PlayerMgr::sendLoginMessage( Entity::Player& player ) void PlayerMgr::sendLoginMessage( Entity::Player& player )
@ -341,6 +341,99 @@ void PlayerMgr::checkAutoAttack( Entity::Player& player, uint64_t tickCount ) co
} }
void PlayerMgr::onGainExp( Entity::Player& player, uint32_t exp )
{
uint32_t currentExp = player.getCurrentExp();
uint16_t level = player.getLevel();
auto currentClass = static_cast< uint8_t >( player.getClass() );
if( level >= Common::MAX_PLAYER_LEVEL )
{
player.setCurrentExp( 0 );
if( currentExp != 0 )
Network::Util::Packet::sendActorControlSelf( player, player.getId(), UpdateUiExp, currentClass, 0 );
return;
}
auto& exdData = Common::Service< Data::ExdData >::ref();
uint32_t neededExpToLevel = exdData.getRow< Excel::ParamGrow >( level )->data().NextExp;
uint32_t neededExpToLevelPlus1 = exdData.getRow< Excel::ParamGrow >( level + 1 )->data().NextExp;
if( ( currentExp + exp ) >= neededExpToLevel )
{
// levelup
exp = ( currentExp + exp - neededExpToLevel ) > neededExpToLevelPlus1 ? neededExpToLevelPlus1 - 1 : ( currentExp + exp - neededExpToLevel );
if( level + 1 >= Common::MAX_PLAYER_LEVEL )
exp = 0;
player.setCurrentExp( exp );
player.levelUp();
}
else
player.setCurrentExp( currentExp + exp );
Network::Util::Packet::sendActorControlSelf( player, player.getId(), GainExpMsg, currentClass, exp );
Network::Util::Packet::sendActorControlSelf( player, player.getId(), UpdateUiExp, currentClass, player.getCurrentExp() );
}
void PlayerMgr::onDiscoverArea( Entity::Player& player, int16_t mapId, int16_t subId )
{
auto& exdData = Common::Service< Data::ExdData >::ref();
int32_t offset;
auto info = exdData.getRow< Excel::Map >( mapId );
if( !info )
{
sendDebug( player, "discover(): Could not obtain map data for map_id == {0}", mapId );
return;
}
const auto& mapData = info->data();
if( mapData.IsUint16Discovery )
offset = 2 * mapData.DiscoveryIndex;
else
offset = 320 + 4 * mapData.DiscoveryIndex;
uint16_t index;
uint8_t value;
Common::Util::valueToFlagByteIndexValue( subId, value, index );
auto& discovery = player.getDiscoveryBitmask();
discovery[ offset + index ] |= value;
uint16_t level = player.getLevel();
uint32_t exp = ( exdData.getRow< Excel::ParamGrow >( level )->data().NextExp * 5 / 100 );
onGainExp( player, exp );
// gain 10x additional EXP if entire map is completed
uint32_t mask = mapData.DiscoveryFlag;
uint32_t discoveredAreas;
if( info->data().IsUint16Discovery )
{
discoveredAreas = ( discovery[ offset + 1 ] << 8 ) | discovery[ offset ];
}
else
{
discoveredAreas = ( discovery[ offset + 3 ] << 24 ) |
( discovery[ offset + 2 ] << 16 ) |
( discovery[ offset + 1 ] << 8 ) |
discovery[ offset ];
}
bool allDiscovered = ( ( discoveredAreas & mask ) == mask );
if( allDiscovered )
{
onGainExp( player, exp * 10 );
}
}
////////// Helper /////////// ////////// Helper ///////////
@ -364,3 +457,75 @@ void PlayerMgr::sendLogMessage( Entity::Player& player, uint32_t messageId, uint
{ {
Network::Util::Packet::sendActorControlTarget( player, player.getId(), LogMsg, messageId, param2, param3, param4, param5, param6 ); Network::Util::Packet::sendActorControlTarget( player, player.getId(), LogMsg, messageId, param2, param3, param4, param5, param6 );
} }
void PlayerMgr::onUpdateHuntingLog( Entity::Player& player, uint8_t id )
{
std::vector< uint32_t > rankRewards{ 2500, 10000, 20000, 30000, 40000 };
const auto maxRank = 4;
auto& pExdData = Common::Service< Data::ExdData >::ref();
// make sure we get the matching base-class if a job is being used
auto classJobInfo = pExdData.getRow< Excel::ClassJob >( static_cast< uint8_t >( player.getClass() ) );
if( !classJobInfo )
return;
auto currentClassId = classJobInfo->data().MainClass;
auto& logEntry = player.getHuntingLogEntry( currentClassId - 1 );
bool logChanged = false;
bool allSectionsComplete = true;
for( int i = 1; i <= 10; ++i )
{
bool sectionComplete = true;
bool sectionChanged = false;
auto monsterNoteId = static_cast< uint32_t >( classJobInfo->data().MainClass * 10000 + logEntry.rank * 10 + i );
auto note = pExdData.getRow< Excel::MonsterNote >( monsterNoteId );
// for classes that don't have entries, if the first fails the rest will fail
if( !note )
break;
for( auto x = 0; x < 4; ++x )
{
auto note1 = pExdData.getRow< Excel::MonsterNoteTarget >( note->data().Target[ x ] );
if( note1->data().Monster == id && logEntry.entries[ i - 1 ][ x ] < note->data().NeededKills[ x ] )
{
logEntry.entries[ i - 1 ][ x ]++;
Network::Util::Packet::sendActorControlSelf( player, player.getId(), HuntingLogEntryUpdate, monsterNoteId, x, logEntry.entries[ i - 1 ][ x ] );
logChanged = true;
sectionChanged = true;
}
if( logEntry.entries[ i - 1 ][ x ] != note->data().NeededKills[ x ] )
sectionComplete = false;
}
if( logChanged && sectionComplete && sectionChanged )
{
Network::Util::Packet::sendActorControlSelf( player, player.getId(), HuntingLogSectionFinish, monsterNoteId, i, 0 );
onGainExp( player, note->data().RewardExp );
}
if( !sectionComplete )
{
allSectionsComplete = false;
}
}
if( logChanged && allSectionsComplete )
{
Network::Util::Packet::sendActorControlSelf( player, player.getId(), HuntingLogRankFinish, 4 );
onGainExp( player, rankRewards[ logEntry.rank ] );
if( logEntry.rank < 4 )
{
logEntry.rank++;
memset( logEntry.entries, 0, 40 );
Network::Util::Packet::sendActorControlSelf( player, player.getId(), HuntingLogRankUnlock, currentClassId, logEntry.rank + 1, 0 );
}
}
if( logChanged )
Network::Util::Packet::sendHuntingLog( player );
}

View file

@ -34,6 +34,12 @@ namespace Sapphire::World::Manager
void onUpdate( Sapphire::Entity::Player& player, uint64_t tickCount ); void onUpdate( Sapphire::Entity::Player& player, uint64_t tickCount );
void onGainExp( Sapphire::Entity::Player& player, uint32_t exp );
void onDiscoverArea( Sapphire::Entity::Player& player, int16_t mapId, int16_t subId );
void onUpdateHuntingLog( Sapphire::Entity::Player& player, uint8_t id );
//////////// Helpers //////////// Helpers
static void sendServerNotice( Sapphire::Entity::Player& player, const std::string& message ); static void sendServerNotice( Sapphire::Entity::Player& player, const std::string& message );

View file

@ -9,6 +9,8 @@
#include "Network/GameConnection.h" #include "Network/GameConnection.h"
#include <Manager/PlayerMgr.h>
#include "QuestMgr.h" #include "QuestMgr.h"
#include "AchievementMgr.h" #include "AchievementMgr.h"
@ -60,6 +62,7 @@ void QuestMgr::onRemoveQuest( Entity::Player &player, uint8_t questIndex )
bool QuestMgr::giveQuestRewards( Entity::Player& player, uint16_t questId, uint32_t optionalChoice ) bool QuestMgr::giveQuestRewards( Entity::Player& player, uint16_t questId, uint32_t optionalChoice )
{ {
auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref();
auto& exdData = Common::Service< Data::ExdData >::ref(); auto& exdData = Common::Service< Data::ExdData >::ref();
auto questInfo = exdData.getRow< Excel::Quest >( static_cast< uint32_t >( Event::EventHandler::EventHandlerType::Quest ) << 16 | questId ); auto questInfo = exdData.getRow< Excel::Quest >( static_cast< uint32_t >( Event::EventHandler::EventHandlerType::Quest ) << 16 | questId );
@ -71,7 +74,9 @@ bool QuestMgr::giveQuestRewards( Entity::Player& player, uint16_t questId, uint3
// TODO: check if there is room in inventory, else return false; // TODO: check if there is room in inventory, else return false;
if( exp > 0 ) if( exp > 0 )
player.gainExp( exp ); {
playerMgr.onGainExp( player, exp );
}
for( uint32_t i = 0; i < 6; i++ ) for( uint32_t i = 0; i < 6; i++ )
{ {

View file

@ -225,7 +225,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR
targetPlayer->getTerritoryTypeId(), targetPlayer->getTerritoryTypeId(),
static_cast< uint8_t >( targetPlayer->getClass() ), static_cast< uint8_t >( targetPlayer->getClass() ),
targetPlayer->getLevel(), targetPlayer->getLevel(),
targetPlayer->getExp(), targetPlayer->getCurrentExp(),
targetPlayer->getSearchMessage(), targetPlayer->getSearchMessage(),
targetPlayer->getPlayTime() ); targetPlayer->getPlayTime() );
break; break;
@ -307,7 +307,7 @@ void Sapphire::Network::GameConnection::gmCommandHandler( const Packets::FFXIVAR
} }
case GmCommand::Exp: case GmCommand::Exp:
{ {
targetPlayer->gainExp( param1 ); playerMgr().onGainExp( *targetPlayer, param1 );
PlayerMgr::sendServerNotice( player, "{0} Exp was added to {1}", param1, targetPlayer->getName()); PlayerMgr::sendServerNotice( player, "{0} Exp was added to {1}", param1, targetPlayer->getName());
break; break;
} }

View file

@ -318,7 +318,7 @@ void Sapphire::Network::GameConnection::newDiscoveryHandler( const Packets::FFXI
discoveryPacket->data().mapId = tInfo->data().Map; discoveryPacket->data().mapId = tInfo->data().Map;
discoveryPacket->data().mapPartId = pRefInfo->data.discoveryIndex; discoveryPacket->data().mapPartId = pRefInfo->data.discoveryIndex;
server().queueForPlayer( player.getCharacterId(), discoveryPacket ); server().queueForPlayer( player.getCharacterId(), discoveryPacket );
player.discover( tInfo->data().Map, pRefInfo->data.discoveryIndex ); playerMgr().onDiscoverArea( player, tInfo->data().Map, pRefInfo->data.discoveryIndex );
} }

View file

@ -84,7 +84,7 @@ void Util::Packet::sendStatusUpdate( Entity::Player& player )
playerStatusUpdate->data().Lv = player.getLevel(); playerStatusUpdate->data().Lv = player.getLevel();
playerStatusUpdate->data().Lv1 = player.getLevel(); playerStatusUpdate->data().Lv1 = player.getLevel();
playerStatusUpdate->data().LvSync = 0; //player.getLevelSync(); playerStatusUpdate->data().LvSync = 0; //player.getLevelSync();
playerStatusUpdate->data().Exp = player.getExp(); playerStatusUpdate->data().Exp = player.getCurrentExp();
server().queueForPlayer( player.getCharacterId(), playerStatusUpdate ); server().queueForPlayer( player.getCharacterId(), playerStatusUpdate );
} }