1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-06 18:57:45 +00:00

add quest achievement type handler; fix achv exd struct for 3.3;

This commit is contained in:
Alice Ogeda 2023-01-23 20:16:08 -03:00
parent 62d04d58ca
commit 9b6d24d610
6 changed files with 90 additions and 9 deletions

View file

@ -838,9 +838,10 @@ namespace Excel
uint16_t Priority;
uint8_t Category;
uint8_t Point;
int8_t UnknownConditional; // previously 2.3~3.05 padding0[0]
uint8_t ConditionType;
uint8_t Detail;
int8_t padding0[2];
int8_t padding0;
};
/* 200982 */

View file

@ -1014,10 +1014,10 @@ namespace Sapphire::Common
Classjob,
Unknown_4,// Materia related? id 304
Unknown_5,// Hunt related? id 1259
QuestUnk_6,
Quest, // Quests that need all required args met
Unknown_7,
Unknown_8,// Map discovery related
QuestUnk_9,
QuestAny,// Quests that need any required args met
ChocoboRank,
PvPRank,
WolvesDenMatches,

View file

@ -19,10 +19,10 @@ void Sapphire::Entity::Player::finishQuest( uint16_t questId, uint32_t optionalC
auto& questMgr = Common::Service< World::Manager::QuestMgr >::ref();
updateQuestsCompleted( questId );
//@todo should probably be changed to a bool function in case reward can not be obtained as quests will not complete in that case
questMgr.onCompleteQuest( *this, questId, optionalChoice );
updateQuestsCompleted( questId );
}
void Sapphire::Entity::Player::unfinishQuest( uint16_t questId )

View file

@ -74,7 +74,7 @@ bool AchievementMgr::hasAchievementUnlocked( Entity::Player& player, uint32_t ac
{
uint16_t index;
uint8_t value;
Common::Util::valueToFlagByteIndexValue( static_cast< uint16_t >( achievementId ), value, index );
Common::Util::valueToFlagByteIndexValue( achievementId, value, index );
return ( player.getAchievementList()[ index ] & value ) != 0;
}
@ -138,9 +138,6 @@ void AchievementMgr::handleLinkedAchievementsForId( Entity::Player& player, uint
bool hasAllAchievements = true;
for( const auto linkedAchvId : linkedAchv )
{
if( linkedAchvId == 0 )
continue;
if( !hasAchievementUnlocked( player, linkedAchvId ) )
{
hasAllAchievements = false;

View file

@ -119,4 +119,83 @@ namespace Sapphire::World::Manager
}
}
template<>
inline void AchievementMgr::progressAchievement< Common::Achievement::Type, Common::Achievement::Type::Quest >( Entity::Player& player, int32_t questId, uint32_t unused )
{
auto& achvDataList = player.getAchievementDataList();
// get achievements that need all achv in args completed
const auto questAchvAllList = getAchievementIdByType( Common::Achievement::Type::Quest );
// get achievements that need any of the achvs in args completed
const auto questAchvAnyList = getAchievementIdByType( Common::Achievement::Type::QuestAny );
// handle achv type for all quests in args completed
for( auto achvId : questAchvAllList )
{
if( hasAchievementUnlocked( player, achvId ) )
continue;
auto pAchv = getAchievementDetail( achvId );
auto achvExdData = pAchv->data();
std::set< uint16_t > linkedQuests{ std::make_move_iterator( std::begin( achvExdData.ConditionArg ) ),
std::make_move_iterator( std::end( achvExdData.ConditionArg ) ) };
// clear empty achievement links
linkedQuests.erase( 0 );
// check if passed quest ID is tied to this achievement
if( !linkedQuests.count( questId ) )
continue;
// verify if player has all the required quests completed
bool hasAllAchievements = true;
for( const auto questId : linkedQuests )
{
if( !player.isQuestCompleted( questId ) )
{
hasAllAchievements = false;
break;
}
}
// unlock achievement if all required quests are completed
if( hasAllAchievements )
unlockAchievement( player, achvId );
}
// handle achv type for all quests in args completed
for( auto achvId : questAchvAnyList )
{
if( hasAchievementUnlocked( player, achvId ) )
continue;
auto pAchv = getAchievementDetail( achvId );
auto achvExdData = pAchv->data();
std::set< int32_t > linkedQuests{ std::make_move_iterator( std::begin( achvExdData.ConditionArg ) ),
std::make_move_iterator( std::end( achvExdData.ConditionArg ) ) };
// clear empty quest ids
linkedQuests.erase( 0 );
// check if passed quest ID is tied to this achievement
if( !linkedQuests.count( questId ) )
continue;
// verify if player has any of the required quests completed
bool hasAllAchievements = true;
for( const auto questId : linkedQuests )
{
if( player.isQuestCompleted( questId ) )
{
unlockAchievement( player, achvId );
break;
}
}
}
}
}

View file

@ -11,6 +11,7 @@
#include "Network/PacketWrappers/Notice2Packet.h"
#include "QuestMgr.h"
#include "AchievementMgr.h"
#include "Actor/Player.h"
@ -41,6 +42,9 @@ void QuestMgr::onCompleteQuest( Entity::Player& player, uint16_t questId, uint32
server.queueForPlayer( player.getCharacterId(), questFinishPacket );
giveQuestRewards( player, questId, optionalChoice );
auto& achvMgr = Common::Service< World::Manager::AchievementMgr >::ref();
achvMgr.progressAchievementByType< Common::Achievement::Type::Quest >( player, questId );
}
void QuestMgr::onRemoveQuest( Entity::Player &player, uint8_t questIndex )