1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-26 14:37:44 +00:00
This commit is contained in:
Mordred 2017-10-10 18:53:17 +02:00
commit b37c6f2402
26 changed files with 486 additions and 54 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 537 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -0,0 +1,38 @@
class CmnDefCutSceneReplayDef
{
def CmnDefCutSceneReplayDef()
{
this.id = 721028;
}
def Scene00000( player )
{
player.eventPlay( this.id, 0, 0x2000/*flags*/, 0/*unk*/, 1/*unk*/,
fun( player, eventId, param1, param2, param3 )
{
if( param2 != 0 )
{
CmnDefCutSceneReplay.Scene00001( player, param2 );
}
});
}
def Scene00001( player, returnScene )
{
player.eventPlay( this.id, 1, 0xFB2EC8F8/*flags*/, 0/*unk*/, 1, returnScene,
fun( player, eventId, param1, param2, param3 )
{
});
}
def onTalk( eventId, player, actorId )
{
this.Scene00000( player );
}
};
GLOBAL CmnDefCutSceneReplay = CmnDefCutSceneReplayDef();

View file

@ -0,0 +1,62 @@
class CmnDefInnBedDef
{
def CmnDefInnBedDef()
{
this.id = 720916;
}
def Scene00000( player ) //Menu
{
player.eventPlay( this.id, 0, 0x2000/*flags*/, 0/*unk*/, 1/*unk*/,
fun( player, eventId, param1, param2, param3 )
{
if( param2 > 1 )
{
CmnDefInnBed.Scene00001( player, param2 );
}
});
}
def Scene00001( player, what ) //Lay down
{
player.eventPlay( this.id, 1, 0xF32E48F8/*flags*/, 0/*unk*/, 1/*unk*/, what,
fun( player, eventId, param1, param2, param3 )
{
CmnDefInnBed.Scene00002( player, param2 );
});
}
def Scene00002( player, what ) //Log out
{
player.eventPlay( this.id, 2, 0xF32E48F8/*flags*/, 0/*unk*/, 1/*unk*/, what,
fun( player, eventId, param1, param2, param3 )
{
});
}
def Scene00100( player ) //Wake up
{
player.eventPlay( this.id, 100, 0xF32E48F8/*flags*/, 0/*unk*/, 0/*unk*/,
fun( player, eventId, param1, param2, param3 )
{
});
}
def onTalk( eventId, player, actorId )
{
this.Scene00000( player );
}
def onEnterTerritory( eventId, player, param1, param2 )
{
this.Scene00100( player );
}
};
GLOBAL CmnDefInnBed = CmnDefInnBedDef();

View file

@ -0,0 +1,26 @@
class HouFurOrchestrionDef
{
def HouFurOrchestrionDef()
{
this.id = 721226;
}
def Scene00000( player )
{
player.eventPlay( this.id, 0, 0x2000/*flags*/, 0/*unk*/, 1/*unk*/,
fun( player, eventId, param1, param2, param3 )
{
});
}
def onTalk( eventId, player, actorId )
{
this.Scene00000( player );
}
};
GLOBAL HouFurOrchestrion = HouFurOrchestrionDef();

View file

@ -70,7 +70,9 @@ CREATE TABLE IF NOT EXISTS `charadetail` (
`StepIndex` int(5) DEFAULT NULL,
`ChocoboTaxiStandFlags` binary(8) DEFAULT NULL,
`GMRank` int(3) DEFAULT '0',
`EquipDisplayFlags` int(3) DEFAULT '0',
`unlocks` binary(64) DEFAULT NULL,
`Orchestrion` binary(38) DEFAULT NULL,
`CharacterId` int(20) NOT NULL DEFAULT '0',
`IS_DELETE` int(3) DEFAULT '0',
`IS_NOT_ACTIVE_FLG` int(3) DEFAULT '0',

View file

@ -23,3 +23,10 @@
-- ALTER TABLE `charadetail` CHANGE `OpeningSequence` `OpeningSequence` INT(3) NULL DEFAULT '0';
-- -------------------------------------------
-- update.sql Before Merge into Other SQL's 30/08/2017
-- -------------------------------------------
-- ALTER TABLE `charadetail` ADD `EquipDisplayFlags` int(3) DEFAULT '0' AFTER `GMRank`;
-- -------------------------------------------
-- update.sql before titles added 09/10/2017
ALTER TABLE `charadetail` CHANGE `TitleList` `Titlelist` BINARY(48) NULL DEFAULT NULL;
ALTER TABLE `charadetail` ADD COLUMN `Orchestrion` BINARY(38) DEFAULT NULL AFTER `unlocks`;

View file

@ -288,6 +288,7 @@ namespace Core {
Aetherytes = 0x00000080, // Attuned aetherytes
HomePoint = 0x00000100, // Current homepoint
HowTo = 0x00000200,
Title = 0x00000400,
HpMp = 0x00000800,
QuestTracker = 0x00001000,
@ -946,9 +947,11 @@ namespace Core {
SetMaxGearSets = 0x230,
ToggleDisplayHeadAndWeapon = 0x260,
SetCharaGearParamUI = 0x260,
GearSetEquipMsg = 0x321
GearSetEquipMsg = 0x321,
ToggleOrchestrionUnlock = 0x396
};
enum struct ChatType : uint32_t
@ -1056,6 +1059,15 @@ namespace Core {
Unused100
};
enum EquipDisplayFlags : uint8_t
{
HideNothing = 0x0,
HideHead = 0x1,
HideWeapon = 0x2,
Visor = 0x40,
};
struct ServerEntry
{
uint32_t serverId;

View file

@ -109,15 +109,19 @@ namespace Packets {
QuestCompleteList = 0x017F, // updated 4.1
QuestFinish = 0x0180, // updated 4.1
QuestMessage = 0x0179,
QuestTracker = 0x0181,
ActorSpawn = 0x0190,
ActorFreeSpawn = 0x0191,
InitZone = 0x019A,
WeatherChange = 0x01AF,
Discovery = 0x01B2,
QuestTracker = 0x0181, // updated for sb
ActorSpawn = 0x0190, // todo: split into playerspawn/actorspawn and use opcode 0x110/0x111
ActorFreeSpawn = 0x0191, // unchanged for sb
InitZone = 0x019A, // unchanged for sb
WeatherChange = 0x01AF, // updated for sb
PlayerTitleList = 0x01B1, // updated for 4.06
Discovery = 0x01B2, // updated for sb
EorzeaTimeOffset = 0x01B4,
EquipDisplayFlags = 0x01C0,
CFAvailableContents = 0x01CF,
PrepareZoning = 0x0248, // updated 4.1
@ -183,8 +187,12 @@ namespace Packets {
ReturnEventHandler = 0x0131, // updated 4.1
TradeReturnEventHandler = 0x0132, // updated 4.1
LinkshellEventHandler = 0x0144, // updated 4.1 ??
LinkshellEventHandler1 = 0x0145, // updated 4.1 ??
ReqEquipDisplayFlagsChange = 0x014C, // updated 4.1 ??
};
////////////////////////////////////////////////////////////////////////////////

View file

@ -368,8 +368,8 @@ struct FFXIVIpcPlayerSpawn : FFXIVIpcBasePacket<PlayerSpawn>
uint32_t u20;
uint32_t ownerId;
uint32_t u22;
uint32_t hPCurr;
uint32_t hPMax;
uint32_t hPCurr;
uint32_t displayFlags;
uint16_t fateID;
uint16_t mPCurr;
@ -639,6 +639,14 @@ struct FFXIVIpcUpdateClassInfo : FFXIVIpcBasePacket<UpdateClassInfo>
uint32_t restedExp;
};
/**
* Structural representation of the packet sent by the server
* to send the titles available to the player
*/
struct FFXIVIpcPlayerTitleList : FFXIVIpcBasePacket<PlayerTitleList>
{
uint8_t titleList[48];
};
/**
* Structural representation of the packet sent by the server
@ -781,7 +789,7 @@ struct FFXIVIpcInitUI : FFXIVIpcBasePacket<InitUI>
uint8_t unknownRest[32];
uint8_t tripleTriadCards[26];
uint8_t unknownRest1[21];
uint8_t orchestrionMask[19];
uint8_t orchestrionMask[38];
uint8_t hallOfNoviceCompleteMask[3];
uint8_t unknownMask2[11];
uint8_t unknownMask3[16];
@ -1286,6 +1294,14 @@ struct FFXIVIpcEorzeaTimeOffset : FFXIVIpcBasePacket<EorzeaTimeOffset>
uint64_t timestamp;
};
/**
* Structural representation of the packet sent by the server
* to set the gear show/hide status of a character
*/
struct FFXIVIpcEquipDisplayFlags : FFXIVIpcBasePacket<EquipDisplayFlags>
{
uint8_t bitmask;
};
} /* Server */

View file

@ -175,6 +175,12 @@ namespace Core {
char unlocks[64];
memset( unlocks, 0, 64 );
char titleList[48];
memset( titleList, 0, 48 );
char orchestrion[38];
memset( orchestrion, 0, 38 );
int16_t questTracking[5] = { -1, -1, -1, -1, -1 };
uint16_t size = static_cast< uint16_t >( m_lookMap.size() );
@ -270,6 +276,8 @@ namespace Core {
" unlocks, "
" QuestTracking, "
" Aetheryte, "
" TitleList, "
" Orchestrion, "
" GMRank, "
" UPDATE_DATE ) "
" VALUES (" + std::to_string( m_iD ) + ", "
@ -285,6 +293,8 @@ namespace Core {
+ "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)unlocks, 64 ) ) + "'), "
+ "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)questTracking, 10 ) ) + "'), "
+ "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)aetherytes, 12 ) ) + "'),"
+ "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)titleList, 48 ) ) + "'),"
+ "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)orchestrion, 38 ) ) + "'),"
+ std::to_string( m_gmRank ) + ", NOW());" );

View file

@ -92,7 +92,11 @@ void Core::Action::ActionCast::onInterrupt()
m_pSource->getAsPlayer()->sendStateFlags();
auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt,
0x219, 1, m_id, 1 );
0x219, 1, m_id, 0 );
// Note: When cast interrupt from taking too much damage, set the last value to 1. This enables the cast interrupt effect. Example:
// auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt, 0x219, 1, m_id, 0 );
m_pSource->sendToInRangeSet( control, true );
}

View file

@ -696,9 +696,13 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint32_t actionId, u
if ( isPlayer() && !ActionCollision::isActorApplicable( pTarget.shared_from_this(), TargetFilter::Enemies ) )
break;
pTarget.takeDamage( static_cast< uint32_t >( param1 ) );
pTarget.onActionHostile( shared_from_this() );
sendToInRangeSet( effectPacket, true );
pTarget.takeDamage( static_cast< uint32_t >( param1 ) );
if ( pTarget.isAlive() )
pTarget.onActionHostile( shared_from_this() );
}
else
{
@ -711,8 +715,11 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint32_t actionId, u
effectPacket.data().effectTarget = pHitActor->getId();
sendToInRangeSet( effectPacket, true ); // todo: send to range of what? ourselves? when mob script hits this is going to be lacking
pHitActor->takeDamage( static_cast< uint32_t >( param1 ) );
pHitActor->onActionHostile( shared_from_this() );
if( pHitActor->isAlive() )
pHitActor->onActionHostile( shared_from_this() );
// Debug
if ( isPlayer() )

View file

@ -43,6 +43,16 @@ public:
Active = 1,
};
enum DisplayFlags : uint16_t
{
ActiveStance = 0x001,
Invisible = 0x020,
HideHead = 0x040,
HideWeapon = 0x080,
Faded = 0x100,
Visor = 0x800,
};
enum struct ActorStatus : uint8_t
{
Idle = 0x01,

View file

@ -388,6 +388,11 @@ void Core::Entity::Player::setZone( uint32_t zoneId )
sendInventory();
if( isLogin() )
{
queuePacket(ActorControlPacket143( getId(), SetCharaGearParamUI, m_equipDisplayFlags, 1 ) );
}
// set flags, will be reset automatically by zoning ( only on client side though )
pPlayer->setStateFlag( PlayerStateFlag::BetweenAreas );
pPlayer->setStateFlag( PlayerStateFlag::BetweenAreas1 );
@ -603,6 +608,18 @@ void Core::Entity::Player::learnAction( uint8_t actionId )
queuePacket( ActorControlPacket143( getId(), ToggleActionUnlock, actionId, 1 ) );
}
void Core::Entity::Player::learnSong( uint8_t songId, uint32_t itemId )
{
uint16_t index;
uint8_t value;
Util::valueToFlagByteIndexValue( songId, value, index );
m_orchestrion[index] |= value;
setSyncFlag( Unlocks );
queuePacket( ActorControlPacket143( getId(), ToggleOrchestrionUnlock, songId, 1, itemId ) );
}
bool Core::Entity::Player::isActionLearned( uint8_t actionId ) const
{
uint16_t index;
@ -1192,6 +1209,11 @@ const uint8_t * Core::Entity::Player::getUnlockBitmask() const
return m_unlocks;
}
const uint8_t * Core::Entity::Player::getOrchestrionBitmask() const
{
return m_orchestrion;
}
uint64_t Core::Entity::Player::getContentId() const
{
return m_contentId;
@ -1415,6 +1437,55 @@ void Core::Entity::Player::setIsLogin( bool bIsLogin )
m_bIsLogin = bIsLogin;
}
uint8_t * Core::Entity::Player::getTitleList()
{
return m_titleList;
}
uint16_t Core::Entity::Player::getTitle() const
{
return m_title;
}
void Core::Entity::Player::addTitle( uint16_t titleId )
{
uint16_t index;
uint8_t value;
Util::valueToFlagByteIndexValue( titleId, value, index );
m_titleList[index] |= value;
setSyncFlag( PlayerSyncFlags::Title );
}
void Core::Entity::Player::setTitle( uint16_t titleId )
{
uint16_t index;
uint8_t value;
Util::valueToFlagByteIndexValue( titleId, value, index );
if ( ( m_titleList[index] & value ) == 0 ) // Player doesn't have title - bail
return;
m_title = titleId;
sendToInRangeSet( ActorControlPacket142( getId(), SetTitle, titleId ), true );
setSyncFlag( PlayerSyncFlags::Title );
}
void Core::Entity::Player::setEquipDisplayFlags( uint8_t state )
{
m_equipDisplayFlags = state;
GamePacketNew< FFXIVIpcEquipDisplayFlags, ServerZoneIpcType > paramPacket( getId() );
paramPacket.data().bitmask = m_equipDisplayFlags;
sendToInRangeSet( paramPacket, true );
setSyncFlag( PlayerSyncFlags::Status );
}
uint8_t Core::Entity::Player::getEquipDisplayFlags() const
{
return m_equipDisplayFlags;
}
void Core::Entity::Player::autoAttack( ActorPtr pTarget )
{

View file

@ -328,6 +328,18 @@ public:
void teleport( uint16_t aetheryteId, uint8_t type = 1 );
/*! prepares zoning / fades out the screen */
void prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadoutTime = 0, uint16_t animation = 0 );
/*! get player's title list (available titles) */
uint8_t * getTitleList();
/*! get player's active title */
uint16_t getTitle() const;
/*! add title to player title list */
void addTitle( uint16_t titleId );
/*! change player's active title */
void setTitle( uint16_t titleId );
/*! change gear param state */
void setEquipDisplayFlags( uint8_t state );
/*! get gear param state and send update to inRangeSet */
uint8_t getEquipDisplayFlags() const;
void calculateStats() override;
void sendStats();
@ -361,10 +373,14 @@ public:
void updateHowtosSeen( uint32_t howToId );
/*! learn an action / update the unlock bitmask. */
void learnAction( uint8_t actionId );
/*! learn a song / update the unlock bitmask. */
void learnSong( uint8_t songId, uint32_t itemId );
/*! check if an action is already unlocked in the bitmask. */
bool isActionLearned( uint8_t actionId ) const;
/*! return a const pointer to the unlock bitmask array */
const uint8_t * getUnlockBitmask() const;
/*! return a const pointer to the orchestrion bitmask array */
const uint8_t * getOrchestrionBitmask() const;
// Spawn handling
@ -565,7 +581,8 @@ private:
uint8_t status;
} m_retainerInfo[8];
uint8_t m_titleList[32];
uint16_t m_title;
uint8_t m_titleList[48];
uint8_t m_achievement[16];
uint8_t m_howTo[33];
uint8_t m_homePoint;
@ -581,6 +598,7 @@ private:
uint32_t m_expArray[25];
uint8_t m_aetheryte[16];
uint8_t m_unlocks[64];
uint8_t m_orchestrion[38];
uint8_t m_openingSequence;
@ -599,6 +617,8 @@ private:
uint8_t m_gmRank;
uint16_t zoneId;
uint8_t m_equipDisplayFlags;
bool m_bInCombat;
bool m_bLoadingComplete;
bool m_bAutoattack;

View file

@ -81,7 +81,11 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
"cd.GrandCompanyRank, "
"cd.CFPenaltyUntil, "
"cd.OpeningSequence, "
"cd.GMRank "
"cd.GMRank, "
"cd.EquipDisplayFlags, "
"cd.ActiveTitle, "
"cd.TitleList, " // 40
"cd.Orchestrion "
"FROM charabase AS c "
" INNER JOIN charadetail AS cd "
" ON c.CharacterId = cd.CharacterId "
@ -89,7 +93,7 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
if( !pQR )
{
g_log.error( "Player id " + char_id_str + " does not exist!" );
g_log.error( "[DB] Failed loading Player ID " + char_id_str );
return false;
}
@ -173,6 +177,12 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
m_openingSequence = field[36].get< uint32_t >();
m_gmRank = field[37].get< uint8_t >();
m_equipDisplayFlags = field[38].get< uint8_t >();
m_title = field[39].get< uint8_t >();
field[40].getBinary( reinterpret_cast< char* >( m_titleList ), sizeof( m_titleList ) );
field[41].getBinary( reinterpret_cast< char* >( m_orchestrion ), sizeof( m_orchestrion ) );
m_pCell = nullptr;
@ -300,22 +310,32 @@ void Core::Entity::Player::createUpdateSql()
charaDetailSet.insert( " Homepoint = " + std::to_string( m_homePoint ) );
if( m_updateFlags & PlayerSyncFlags::Discovery )
charaDetailSet.insert( " Discovery = UNHEX('" + std::string( Util::binaryToHexString( static_cast< uint8_t* >( m_discovery ), sizeof( m_discovery ) ) ) + "')" );
charaDetailSet.insert( " Discovery = UNHEX('" + Util::binaryToHexString( static_cast< uint8_t* >( m_discovery ), sizeof( m_discovery ) ) + "')" );
if( m_updateFlags & PlayerSyncFlags::PlayTime )
charaDetailSet.insert( " TotalPlayTime = " + std::to_string( m_playTime ) );
if( m_updateFlags & PlayerSyncFlags::Unlocks )
charaDetailSet.insert( " unlocks = UNHEX('" + std::string( Util::binaryToHexString( static_cast< uint8_t* >( m_unlocks ), sizeof( m_unlocks ) ) ) + "')" );
{
charaDetailSet.insert( " unlocks = UNHEX('" + Util::binaryToHexString( static_cast< uint8_t* >( m_unlocks ), sizeof( m_unlocks ) ) + "')");
charaDetailSet.insert( " Orchestrion = UNHEX('" + Util::binaryToHexString( static_cast< uint8_t* >( m_orchestrion ), sizeof( m_orchestrion ) ) + "')" );
}
if( m_updateFlags & PlayerSyncFlags::QuestTracker )
charaDetailSet.insert( " QuestTracking = UNHEX('" + std::string( Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_questTracking ), sizeof( m_questTracking ) ) ) + "')" );
charaDetailSet.insert( " QuestTracking = UNHEX('" + Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_questTracking ), sizeof( m_questTracking ) ) + "')" );
if( m_updateFlags & PlayerSyncFlags::HowTo )
charaDetailSet.insert( " HowTo = UNHEX('" + std::string( Util::binaryToHexString( static_cast< uint8_t* >( m_howTo ), sizeof( m_howTo ) ) ) + "')" );
charaDetailSet.insert( " HowTo = UNHEX('" + Util::binaryToHexString( static_cast< uint8_t* >( m_howTo ), sizeof( m_howTo ) ) + "')" );
if ( m_updateFlags & PlayerSyncFlags::Title )
{
charaDetailSet.insert( " ActiveTitle = " + std::to_string( m_title ) );
charaDetailSet.insert( " TitleList = UNHEX('" + Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_titleList ), sizeof( m_titleList ) ) + "')" );
}
if( m_updateFlags & PlayerSyncFlags::Aetherytes )
charaDetailSet.insert( " Aetheryte = UNHEX('" + std::string( Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_aetheryte ), sizeof( m_aetheryte ) ) ) + "')" );
charaDetailSet.insert( " Aetheryte = UNHEX('" + Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_aetheryte ), sizeof( m_aetheryte ) ) + "')" );
if( m_updateFlags & PlayerSyncFlags::NewGame )
@ -327,7 +347,7 @@ void Core::Entity::Player::createUpdateSql()
if( m_updateFlags & PlayerSyncFlags::GC )
{
charaDetailSet.insert( " GrandCompany = " + std::to_string( m_gc ) );
charaDetailSet.insert( " GrandCompanyRank = UNHEX('" + std::string( Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_gcRank ), sizeof( m_gcRank ) ) ) + "')" );
charaDetailSet.insert( " GrandCompanyRank = UNHEX('" + Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_gcRank ), sizeof( m_gcRank ) ) + "')" );
}
if( m_updateFlags & PlayerSyncFlags::CFPenaltyTime )
@ -347,9 +367,10 @@ void Core::Entity::Player::createUpdateSql()
charaBaseSet.insert( " Hp = " + std::to_string( getHp() ) );
charaBaseSet.insert( " Mp = " + std::to_string( getMp() ) );
charaBaseSet.insert( " Mode = " + std::to_string( static_cast< uint32_t >( getStance() ) ) );
charaBaseSet.insert( " ModelEquip = UNHEX('" + std::string( Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_modelEquip ), 40 ) ) + "')" );
charaBaseSet.insert( " ModelEquip = UNHEX('" + Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_modelEquip ), 40 ) + "')" );
charaDetailSet.insert( " Class = " + std::to_string( static_cast< uint32_t >( getClass() ) ) );
charaDetailSet.insert( " Status = " + std::to_string( static_cast< uint8_t >( getStatus() ) ) );
charaDetailSet.insert( " EquipDisplayFlags = " + std::to_string( static_cast< uint8_t >( getEquipDisplayFlags() ) ) );
}
if( m_updateFlags & PlayerSyncFlags::OpeningSeq )
@ -359,7 +380,7 @@ void Core::Entity::Player::createUpdateSql()
if( m_updateFlags & PlayerSyncFlags::Quests )
{
charaDetailSet.insert( " QuestCompleteFlags = UNHEX('" + std::string( Util::binaryToHexString( static_cast< uint8_t* >( m_questCompleteFlags ), 200 ) ) + "')" );
charaDetailSet.insert( " QuestCompleteFlags = UNHEX('" + Util::binaryToHexString( static_cast< uint8_t* >( m_questCompleteFlags ), 200 ) + "')" );
for( int32_t i = 0; i < 30; i++ )
{
@ -396,7 +417,7 @@ void Core::Entity::Player::createUpdateSql()
{
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 ) ) + "')" ) );
charaInfoSearchSet.insert( " SearchComment = UNHEX('" + Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_searchMessage ), sizeof( m_searchMessage ) ) + "')" );
}
if( !charaInfoSearchSet.empty() )

View file

@ -118,6 +118,7 @@ void Core::DebugCommandHandler::scriptReload( char * data, Core::Entity::PlayerP
boost::shared_ptr<Core::DebugCommand> command )
{
g_scriptMgr.reload();
pPlayer->sendDebug( "Scripts reloaded." );
}
void Core::DebugCommandHandler::set( char * data, Core::Entity::PlayerPtr pPlayer, boost::shared_ptr<Core::DebugCommand> command )
@ -182,13 +183,6 @@ void Core::DebugCommandHandler::set( char * data, Core::Entity::PlayerPtr pPlaye
pPlayer->teleport( aetheryteId );
}
else if( ( subCommand == "unlockaetheryte" ) && ( params != "" ) )
{
for( uint8_t i = 0; i < 255; i++ )
pPlayer->registerAetheryte( i );
}
else if( ( subCommand == "discovery" ) && ( params != "" ) )
{
int32_t map_id;
@ -304,13 +298,21 @@ void Core::DebugCommandHandler::add( char * data, Core::Entity::PlayerPtr pPlaye
int32_t duration;
uint16_t param;
sscanf( params.c_str(), "%d %d %hd", &id, &duration, &param );
sscanf( params.c_str(), "%d %d %hu", &id, &duration, &param );
StatusEffect::StatusEffectPtr effect( new StatusEffect::StatusEffect( id, pPlayer, pPlayer, duration, 3000 ) );
effect->setParam( param );
pPlayer->addStatusEffect( effect );
}
else if ( subCommand == "title" )
{
uint32_t titleId;
sscanf( params.c_str(), "%u", &titleId );
pPlayer->addTitle( titleId );
pPlayer->sendNotice( "Added title (ID: " + std::to_string( titleId ) + ")" );
}
else if( subCommand == "spawn" )
{
int32_t model, name;
@ -333,7 +335,6 @@ void Core::DebugCommandHandler::add( char * data, Core::Entity::PlayerPtr pPlaye
pPlayer->queuePacket( pPe );
}
else if( subCommand == "actrl" )
{
// temporary research packet

View file

@ -93,8 +93,9 @@ Core::Network::GameConnection::GameConnection( Core::Network::HivePtr pHive,
setZoneHandler( ClientZoneIpcType::CFRegisterRoulette, "CFRegisterRoulette", &GameConnection::cfRegisterRoulette );
setZoneHandler( ClientZoneIpcType::CFCommenceHandler, "CFDutyAccepted", &GameConnection::cfDutyAccepted);
setZoneHandler( ClientZoneIpcType::ReqEquipDisplayFlagsChange, "ReqEquipDisplayFlagsChange",&GameConnection::reqEquipDisplayFlagsHandler);
setChatHandler( ClientChatIpcType::TellReq, "TellReq", &GameConnection::tellHandler);
setChatHandler( ClientChatIpcType::TellReq, "TellReq", &GameConnection::tellHandler);
}
@ -116,7 +117,7 @@ void Core::Network::GameConnection::OnAccept( const std::string & host, uint16_t
void Core::Network::GameConnection::OnDisconnect()
{
g_log.debug( "DISCONNECT" );
g_log.debug( "GameConnection DISCONNECT" );
m_pSession = nullptr;
}
@ -167,7 +168,7 @@ void Core::Network::GameConnection::OnRecv( std::vector< uint8_t > & buffer )
void Core::Network::GameConnection::OnError( const boost::system::error_code & error )
{
g_log.debug( "ERROR" );
g_log.debug( "GameConnection ERROR: " + error.message() );
}
void Core::Network::GameConnection::queueInPacket( Core::Network::Packets::GamePacketPtr inPacket )
@ -380,10 +381,21 @@ void Core::Network::GameConnection::handlePackets( const Core::Network::Packets:
{
g_log.info( "[" + std::string( id ) + "] Session not registered, creating" );
// return;
g_serverZone.createSession( playerId );
if( !g_serverZone.createSession( playerId ) )
{
Disconnect();
return;
}
session = g_serverZone.getSession( playerId );
}
if( !session->isValid() ) //TODO: Catch more things in lobby and send real errors
{
g_log.error( "[" + std::string(id) + "] Session INVALID, disconnecting" );
Disconnect();
return;
}
// if not set, set the session for this connection
if( !m_pSession && session )
m_pSession = session;
@ -418,8 +430,6 @@ void Core::Network::GameConnection::handlePackets( const Core::Network::Packets:
sendSinglePacket( &pPe );
}
break;
}

View file

@ -116,10 +116,10 @@ public:
DECLARE_HANDLER( gm1Handler );
DECLARE_HANDLER( gm2Handler );
DECLARE_HANDLER( reqEquipDisplayFlagsHandler );
DECLARE_HANDLER( tellHandler );
};

View file

@ -114,10 +114,23 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in
}
case 0x69: // Cancel cast
{
if( pPlayer->checkAction() )
if( pPlayer->getCurrentAction() != nullptr )
pPlayer->getCurrentAction()->setInterrupted();
break;
}
case 0x12E: // Set player title
{
pPlayer->setTitle( param1 );
break;
}
case 0x12F: // Get title list
{
GamePacketNew< FFXIVIpcPlayerTitleList, ServerZoneIpcType > titleListPacket( pPlayer->getId() );
memcpy( titleListPacket.data().titleList, pPlayer->getTitleList(), sizeof( titleListPacket.data().titleList ) );
pPlayer->queuePacket( titleListPacket );
break;
}
case 0x133: // Update howtos seen
{
uint32_t howToId = static_cast< uint32_t >( param1 );

View file

@ -72,6 +72,8 @@ enum GmCommand
Exp = 0x0068,
Inv = 0x006A,
Orchestrion = 0x0074,
Item = 0x00C8,
Gil = 0x00C9,
Collect = 0x00CA,
@ -84,6 +86,7 @@ enum GmCommand
QuestInspect = 0x0131,
GC = 0x0154,
GCRank = 0x0155,
Aetheryte = 0x015E,
Teri = 0x0258,
TeriInfo = 0x025D,
Jump = 0x025E,
@ -364,6 +367,52 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
" was switched." );
break;
}
case GmCommand::Aetheryte:
{
if( param1 == 0 )
{
if( param2 == 0 )
{
for( uint8_t i = 0; i < 255; i++ )
targetActor->getAsPlayer()->registerAetheryte( i );
pPlayer->sendNotice( "All Aetherytes for " + targetPlayer->getName() +
" were turned on." );
}
else
{
targetActor->getAsPlayer()->registerAetheryte( param2 );
pPlayer->sendNotice( "Aetheryte " + std::to_string( param2 ) + " for " + targetPlayer->getName() +
" was turned on." );
}
}
break;
}
case GmCommand::Orchestrion:
{
if( param1 == 1 )
{
if( param2 == 0 )
{
for( uint8_t i = 0; i < 255; i++ )
targetActor->getAsPlayer()->learnSong( i, 0 );
pPlayer->sendNotice( "All Songs for " + targetPlayer->getName() +
" were turned on." );
}
else
{
targetActor->getAsPlayer()->learnSong( param2, 0 );
pPlayer->sendNotice( "Song " + std::to_string( param2 ) + " for " + targetPlayer->getName() +
" was turned on." );
}
}
break;
}
default:
pPlayer->sendUrgent( "GM1 Command not implemented: " + std::to_string( commandId ) );

View file

@ -285,7 +285,11 @@ void Core::Network::GameConnection::updatePositionHandler( const Packets::GamePa
}
void Core::Network::GameConnection::reqEquipDisplayFlagsHandler( const Packets::GamePacket& inPacket,
Entity::PlayerPtr pPlayer )
{
pPlayer->setEquipDisplayFlags( inPacket.getValAt< uint8_t >( 0x20 ) );
}
void Core::Network::GameConnection::zoneLineHandler( const Packets::GamePacket& inPacket,
Entity::PlayerPtr pPlayer )

View file

@ -42,7 +42,7 @@ private:
m_data.namedayMonth = player->getBirthMonth();
m_data.namedayDay = player->getBirthDay();
// TODO: Support grand company status.
m_data.grandCompany = static_cast< Common::GrandCompany >( player->getStartTown() );
m_data.grandCompany = static_cast< Common::GrandCompany >( player->getGc() );
//m_data.gcRank = GCRank::None;
// TODO: Support starting city.
@ -62,6 +62,8 @@ private:
m_data.exp[i] = player->getExpArray()[i];
}
memcpy( m_data.orchestrionMask, player->getOrchestrionBitmask(), sizeof( m_data.orchestrionMask ) );
memcpy( m_data.unlockBitmask, player->getUnlockBitmask(), sizeof( m_data.unlockBitmask ) );
memcpy( m_data.discovery, player->getDiscoveryBitmask(), sizeof( m_data.discovery ) );

View file

@ -36,41 +36,47 @@ namespace Server {
// TODO: temporary gm rank
//m_data.gmRank = 0xff;
m_data.currentMount = 0;
m_data.classJob = pPlayer->getClass();
//m_data.status = static_cast< uint8_t >( pPlayer->getStatus() );
m_data.hPCurr = pPlayer->getHp();
m_data.mPCurr = pPlayer->getMp();
m_data.tPCurr = pPlayer->getTp();
m_data.hPMax = pPlayer->getMaxHp();
m_data.mPMax = pPlayer->getMaxMp();
m_data.gmRank = pPlayer->getGmRank();
//m_data.tPMax = 3000;
m_data.level = pPlayer->getLevel();
m_data.gmRank = pPlayer->getGmRank();
memcpy( m_data.look, pPlayer->getLookArray(), 26 );
auto item = pPlayer->getInventory()->getItemAt( Inventory::GearSet0, Inventory::EquipSlot::MainHand );
if( item )
m_data.mainWeaponModel = item->getModelId1();
m_data.secWeaponModel = pPlayer->getModelSubWeapon();
m_data.models[0] = pPlayer->getModelForSlot( Inventory::EquipSlot::Head );
m_data.models[1] = pPlayer->getModelForSlot( Inventory::EquipSlot::Body );
m_data.models[2] = pPlayer->getModelForSlot( Inventory::EquipSlot::Hands );
m_data.models[3] = pPlayer->getModelForSlot( Inventory::EquipSlot::Legs );
m_data.models[4] = pPlayer->getModelForSlot( Inventory::EquipSlot::Feet );
strcpy( m_data.name, pPlayer->getName().c_str() );
m_data.pos.x = pPlayer->getPos().x;
m_data.pos.y = pPlayer->getPos().y;
m_data.pos.z = pPlayer->getPos().z;
m_data.voice = pPlayer->getVoiceId();
m_data.rotation = Math::Util::floatToUInt16Rot( pPlayer->getRotation() );
m_data.title = pPlayer->getTitle();
m_data.voice = pPlayer->getVoiceId();
m_data.currentMount = 0;
m_data.onlineStatus = static_cast< uint8_t >( pPlayer->getOnlineStatus() );
//m_data.u23 = 0x04;
//m_data.u24 = 256;
m_data.state = 1;
m_data.state = static_cast< uint8_t >( pPlayer->getStatus() );
m_data.type = 1;
if( pTarget == pPlayer )
{
@ -85,7 +91,22 @@ namespace Server {
if( pPlayer->getZoningType() != Common::ZoneingType::None )
{
m_data.displayFlags |= 0x20;
m_data.displayFlags |= Entity::Actor::DisplayFlags::Invisible;
}
if( pPlayer->getEquipDisplayFlags() & Core::Common::EquipDisplayFlags::HideHead )
{
m_data.displayFlags |= Entity::Actor::DisplayFlags::HideHead;
}
if( pPlayer->getEquipDisplayFlags() & Core::Common::EquipDisplayFlags::HideWeapon )
{
m_data.displayFlags |= Entity::Actor::DisplayFlags::HideWeapon;
}
if( pPlayer->getEquipDisplayFlags() & Core::Common::EquipDisplayFlags::Visor )
{
m_data.displayFlags |= Entity::Actor::DisplayFlags::Visor;
}
m_data.targetId = pPlayer->getTargetId();

View file

@ -9,6 +9,7 @@
Core::Session::Session( uint32_t sessionId )
: m_sessionId( sessionId )
, m_isValid( false )
, m_lastDataTime( static_cast< uint32_t >( time( nullptr ) ) )
{
@ -50,7 +51,12 @@ bool Core::Session::loadPlayer()
m_pPlayer = Entity::PlayerPtr( new Entity::Player() );
if( !m_pPlayer->load( m_sessionId, shared_from_this() ) )
{
m_isValid = false;
return false;
}
m_isValid = true;
return true;
@ -61,6 +67,9 @@ void Core::Session::close()
if( m_pZoneConnection )
m_pZoneConnection->Disconnect();
if( m_pChatConnection )
m_pChatConnection->Disconnect();
// remove the session from the player
if( m_pPlayer )
// reset the zone, so the zone handler knows to remove the actor
@ -77,6 +86,11 @@ uint32_t Core::Session::getLastDataTime() const
return m_lastDataTime;
}
bool Core::Session::isValid() const
{
return m_isValid;
}
void Core::Session::updateLastDataTime()
{
m_lastDataTime = static_cast< uint32_t >( time( nullptr ) );

View file

@ -35,6 +35,8 @@ namespace Core {
void update();
bool isValid() const;
Entity::PlayerPtr getPlayer() const;
private:
@ -44,6 +46,8 @@ namespace Core {
uint32_t m_lastDataTime;
bool m_isValid;
Network::GameConnectionPtr m_pZoneConnection;
Network::GameConnectionPtr m_pChatConnection;