2021-12-05 17:54:36 +00:00
# include <sstream>
# include "MissionTask.h"
# include "Game.h"
2023-10-21 23:31:55 +00:00
# include "Logger.h"
2021-12-05 17:54:36 +00:00
# include "Mission.h"
# include "Character.h"
# include "dServer.h"
# include "EntityManager.h"
# include "ScriptedActivityComponent.h"
# include "GameMessages.h"
# include "dZoneManager.h"
2022-12-18 15:46:04 +00:00
# include "InventoryComponent.h"
2021-12-05 17:54:36 +00:00
# include "MissionComponent.h"
# include "eMissionTaskType.h"
2023-03-04 07:16:37 +00:00
# include "eReplicaComponentType.h"
2021-12-05 17:54:36 +00:00
MissionTask : : MissionTask ( Mission * mission , CDMissionTasks * info , uint32_t mask ) {
this - > info = info ;
this - > mission = mission ;
this - > mask = mask ;
progress = 0 ;
std : : istringstream stream ( info - > taskParam1 ) ;
std : : string token ;
while ( std : : getline ( stream , token , ' , ' ) ) {
2024-02-10 11:05:25 +00:00
const auto parameter = GeneralUtils : : TryParse < uint32_t > ( token ) ;
if ( parameter ) parameters . push_back ( parameter . value ( ) ) ;
2021-12-05 17:54:36 +00:00
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
stream = std : : istringstream ( info - > targetGroup ) ;
while ( std : : getline ( stream , token , ' , ' ) ) {
2024-02-10 11:05:25 +00:00
const auto parameter = GeneralUtils : : TryParse < uint32_t > ( token ) ;
if ( parameter ) targets . push_back ( parameter . value ( ) ) ;
2021-12-05 17:54:36 +00:00
}
}
eMissionTaskType MissionTask : : GetType ( ) const {
return static_cast < eMissionTaskType > ( info - > taskType ) ;
}
uint32_t MissionTask : : GetProgress ( ) const {
return progress ;
}
void MissionTask : : SetProgress ( const uint32_t value , const bool echo ) {
if ( progress = = value ) {
return ;
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
progress = value ;
if ( ! echo ) {
return ;
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
auto * entity = mission - > GetAssociate ( ) ;
if ( entity = = nullptr ) {
return ;
}
std : : vector < float > updates ;
updates . push_back ( static_cast < float > ( progress ) ) ;
2022-02-21 04:01:55 +00:00
GameMessages : : SendNotifyMissionTask ( entity , entity - > GetSystemAddress ( ) , static_cast < int > ( info - > id ) , static_cast < int > ( 1 < < ( mask + 1 ) ) , updates ) ;
2021-12-05 17:54:36 +00:00
}
void MissionTask : : SetUnique ( const std : : vector < uint32_t > & value ) {
unique = value ;
}
void MissionTask : : AddProgress ( int32_t value ) {
value + = progress ;
if ( value > info - > targetValue ) {
value = info - > targetValue ;
}
if ( value < 0 ) {
value = 0 ;
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
SetProgress ( value ) ;
}
Mission * MissionTask : : GetMission ( ) const {
return mission ;
}
uint32_t MissionTask : : GetTarget ( ) const {
return info - > target ;
}
const CDMissionTasks & MissionTask : : GetClientInfo ( ) const {
return * info ;
}
uint32_t MissionTask : : GetMask ( ) const {
return mask ;
}
const std : : vector < uint32_t > & MissionTask : : GetUnique ( ) const {
return unique ;
}
const std : : vector < uint32_t > & MissionTask : : GetTargets ( ) const {
return targets ;
}
const std : : vector < uint32_t > & MissionTask : : GetParameters ( ) const {
return parameters ;
}
std : : vector < uint32_t > MissionTask : : GetAllTargets ( ) const {
auto targets = GetTargets ( ) ;
targets . push_back ( GetTarget ( ) ) ;
return targets ;
}
bool MissionTask : : InTargets ( const uint32_t value ) const {
auto targets = GetTargets ( ) ;
return std : : find ( targets . begin ( ) , targets . end ( ) , value ) ! = targets . end ( ) ;
}
bool MissionTask : : InAllTargets ( const uint32_t value ) const {
auto targets = GetAllTargets ( ) ;
return std : : find ( targets . begin ( ) , targets . end ( ) , value ) ! = targets . end ( ) ;
}
bool MissionTask : : InParameters ( const uint32_t value ) const {
auto parameters = GetParameters ( ) ;
return std : : find ( parameters . begin ( ) , parameters . end ( ) , value ) ! = parameters . end ( ) ;
}
bool MissionTask : : IsComplete ( ) const {
2022-04-18 08:04:29 +00:00
// Mission 668 has task uid 984 which is a bit mask. Its completion value is 3.
if ( info - > uid = = 984 ) {
return progress > = 3 ;
} else {
return progress > = info - > targetValue ;
}
2021-12-05 17:54:36 +00:00
}
void MissionTask : : Complete ( ) {
2022-02-10 00:42:17 +00:00
SetProgress ( info - > targetValue ) ;
2021-12-05 17:54:36 +00:00
}
void MissionTask : : CheckCompletion ( ) const {
if ( IsComplete ( ) ) {
mission - > CheckCompletion ( ) ;
}
}
void MissionTask : : Progress ( int32_t value , LWOOBJID associate , const std : : string & targets , int32_t count ) {
if ( IsComplete ( ) & & count > 0 ) return ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
const auto type = GetType ( ) ;
if ( count < 0 ) {
if ( mission - > IsMission ( ) & & type = = eMissionTaskType : : GATHER & & InAllTargets ( value ) ) {
2024-08-11 17:26:25 +00:00
if ( parameters . size ( ) > 0 & & ( parameters [ 0 ] & 4 ) ! = 0 ) {
2021-12-05 17:54:36 +00:00
return ;
}
auto * inventoryComponent = mission - > GetAssociate ( ) - > GetComponent < InventoryComponent > ( ) ;
if ( inventoryComponent ! = nullptr ) {
int32_t itemCount = inventoryComponent - > GetLotCountNonTransfer ( value ) ;
if ( itemCount < info - > targetValue ) {
SetProgress ( itemCount ) ;
if ( mission - > IsReadyToComplete ( ) ) {
mission - > MakeActive ( ) ;
}
}
}
}
return ;
}
Entity * entity ;
ScriptedActivityComponent * activity ;
uint32_t activityId ;
uint32_t lot ;
uint32_t collectionId ;
std : : vector < LDFBaseData * > settings ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
switch ( type ) {
case eMissionTaskType : : UNKNOWN :
break ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
case eMissionTaskType : : ACTIVITY :
{
if ( InAllTargets ( value ) ) {
AddProgress ( count ) ;
break ;
}
2023-07-15 20:56:33 +00:00
entity = Game : : entityManager - > GetEntity ( associate ) ;
2021-12-05 17:54:36 +00:00
if ( entity = = nullptr ) {
if ( associate ! = LWOOBJID_EMPTY ) {
2023-10-21 23:31:55 +00:00
LOG ( " Failed to find associated entity (%llu)! " , associate ) ;
2021-12-05 17:54:36 +00:00
}
break ;
}
2023-03-04 07:16:37 +00:00
activity = static_cast < ScriptedActivityComponent * > ( entity - > GetComponent ( eReplicaComponentType : : QUICK_BUILD ) ) ;
2021-12-05 17:54:36 +00:00
if ( activity = = nullptr ) {
break ;
}
activityId = activity - > GetActivityID ( ) ;
const auto activityIdOverride = entity - > GetVar < int32_t > ( u " activityID " ) ;
if ( activityIdOverride ! = 0 ) {
activityId = activityIdOverride ;
}
if ( ! InAllTargets ( activityId ) ) break ;
AddProgress ( count ) ;
break ;
}
case eMissionTaskType : : USE_ITEM :
case eMissionTaskType : : TALK_TO_NPC :
{
if ( GetTarget ( ) ! = value ) break ;
AddProgress ( count ) ;
break ;
}
case eMissionTaskType : : EMOTE :
{
if ( ! InParameters ( value ) ) break ;
2022-07-25 02:26:51 +00:00
2023-07-15 20:56:33 +00:00
entity = Game : : entityManager - > GetEntity ( associate ) ;
2021-12-05 17:54:36 +00:00
if ( entity = = nullptr ) {
2023-10-21 23:31:55 +00:00
LOG ( " Failed to find associated entity (%llu)! " , associate ) ;
2021-12-05 17:54:36 +00:00
break ;
}
lot = static_cast < uint32_t > ( entity - > GetLOT ( ) ) ;
if ( GetTarget ( ) ! = lot ) break ;
AddProgress ( count ) ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
break ;
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
case eMissionTaskType : : USE_SKILL :
{
2022-04-25 10:25:07 +00:00
// This is a complicated check because for some missions we need to check for the associate being in the parameters instead of the value being in the parameters.
if ( associate = = LWOOBJID_EMPTY & & GetAllTargets ( ) . size ( ) = = 1 & & GetAllTargets ( ) [ 0 ] = = - 1 ) {
if ( InParameters ( value ) ) AddProgress ( count ) ;
} else {
if ( InParameters ( associate ) & & InAllTargets ( value ) ) AddProgress ( count ) ;
2022-07-25 02:26:51 +00:00
}
2021-12-05 17:54:36 +00:00
break ;
}
case eMissionTaskType : : PERFORM_ACTIVITY :
{
2023-07-15 20:56:33 +00:00
auto * minigameManager = Game : : entityManager - > GetEntity ( associate ) ;
2021-12-05 17:54:36 +00:00
if ( minigameManager = = nullptr )
break ;
int32_t gameID = minigameManager - > GetLOT ( ) ;
auto * sac = minigameManager - > GetComponent < ScriptedActivityComponent > ( ) ;
if ( sac ! = nullptr ) {
gameID = sac - > GetActivityID ( ) ;
}
if ( info - > target ! = gameID ) {
break ;
}
2022-02-21 04:00:56 +00:00
// This special case is for shooting gallery missions that want their
// progress value set to 1 instead of being set to the target value.
2022-02-10 11:08:47 +00:00
if ( info - > targetGroup = = targets & & value > = info - > targetValue & & GetMission ( ) - > IsMission ( ) & & info - > target = = 1864 & & info - > targetGroup = = " performact_score " ) {
SetProgress ( 1 ) ;
break ;
}
2022-02-05 11:54:12 +00:00
if ( info - > targetGroup = = targets & & value > = info - > targetValue ) {
2022-02-10 00:42:17 +00:00
SetProgress ( info - > targetValue ) ;
2022-02-05 11:54:12 +00:00
break ;
}
2021-12-05 17:54:36 +00:00
break ;
}
case eMissionTaskType : : VISIT_PROPERTY :
{
if ( ! InAllTargets ( value ) ) break ;
if ( std : : find ( unique . begin ( ) , unique . end ( ) , static_cast < uint32_t > ( associate ) ) ! = unique . end ( ) ) break ;
AddProgress ( count ) ;
unique . push_back ( associate ) ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
break ;
}
case eMissionTaskType : : COLLECTION :
{
if ( ! InAllTargets ( value ) ) break ;
2022-07-25 02:26:51 +00:00
2023-07-15 20:56:33 +00:00
entity = Game : : entityManager - > GetEntity ( associate ) ;
2021-12-05 17:54:36 +00:00
if ( entity = = nullptr ) {
2023-10-21 23:31:55 +00:00
LOG ( " Failed to find associated entity (%llu)! " , associate ) ;
2021-12-05 17:54:36 +00:00
break ;
}
collectionId = entity - > GetCollectibleID ( ) ;
collectionId = static_cast < uint32_t > ( collectionId ) + static_cast < uint32_t > ( Game : : server - > GetZoneID ( ) < < 8 ) ;
if ( std : : find ( unique . begin ( ) , unique . end ( ) , collectionId ) ! = unique . end ( ) ) break ;
unique . push_back ( collectionId ) ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
SetProgress ( unique . size ( ) ) ;
auto * entity = mission - > GetAssociate ( ) ;
if ( entity = = nullptr ) break ;
auto * missionComponent = entity - > GetComponent < MissionComponent > ( ) ;
if ( missionComponent = = nullptr ) break ;
missionComponent - > AddCollectible ( collectionId ) ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
break ;
}
case eMissionTaskType : : EXPLORE :
{
if ( info - > targetGroup ! = targets ) break ;
AddProgress ( count ) ;
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
break ;
}
2022-07-25 02:26:51 +00:00
2021-12-05 17:54:36 +00:00
case eMissionTaskType : : RACING :
{
2022-02-06 22:28:27 +00:00
// The meaning of associate can be found in eRacingTaskParam.h
2021-12-05 17:54:36 +00:00
if ( parameters . empty ( ) ) break ;
2023-07-17 22:55:33 +00:00
if ( ! InAllTargets ( Game : : zoneManager - > GetZone ( ) - > GetWorldID ( ) ) & & ! ( parameters [ 0 ] = = 4 | | parameters [ 0 ] = = 5 ) & & ! InAllTargets ( value ) ) break ;
2021-12-05 17:54:36 +00:00
if ( parameters [ 0 ] ! = associate ) break ;
2022-04-18 08:04:29 +00:00
if ( associate = = 1 | | associate = = 2 | | associate = = 3 ) {
2021-12-05 17:54:36 +00:00
if ( value > info - > targetValue ) break ;
AddProgress ( info - > targetValue ) ;
}
2022-04-18 08:04:29 +00:00
// task 15 is a bit mask!
else if ( associate = = 15 ) {
if ( ! InAllTargets ( value ) ) break ;
auto tempProgress = GetProgress ( ) ;
// If we won at Nimbus Station, set bit 0
if ( value = = 1203 ) SetProgress ( tempProgress | = 1 < < 0 ) ;
// If we won at Gnarled Forest, set bit 1
else if ( value = = 1303 ) SetProgress ( tempProgress | = 1 < < 1 ) ;
// If both bits are set, then the client sees the mission as complete.
2021-12-05 17:54:36 +00:00
} else if ( associate = = 10 ) {
2022-02-05 11:28:17 +00:00
// If the player did not crash during the race, progress this task by count.
if ( value ! = 0 ) break ;
2022-07-25 02:26:51 +00:00
2022-02-05 11:28:17 +00:00
AddProgress ( count ) ;
} else if ( associate = = 4 | | associate = = 5 | | associate = = 14 ) {
if ( ! InAllTargets ( value ) ) break ;
AddProgress ( count ) ;
2022-02-06 22:28:27 +00:00
} else if ( associate = = 17 ) {
if ( ! InAllTargets ( value ) ) break ;
AddProgress ( count ) ;
2021-12-05 17:54:36 +00:00
} else {
AddProgress ( count ) ;
}
break ;
}
case eMissionTaskType : : PET_TAMING :
case eMissionTaskType : : SCRIPT :
case eMissionTaskType : : INTERACT :
case eMissionTaskType : : META :
case eMissionTaskType : : POWERUP :
case eMissionTaskType : : SMASH :
case eMissionTaskType : : GATHER :
case eMissionTaskType : : PLAYER_FLAG :
2022-02-05 12:08:40 +00:00
case eMissionTaskType : : EARN_REPUTATION :
2021-12-05 17:54:36 +00:00
{
if ( ! InAllTargets ( value ) ) break ;
AddProgress ( count ) ;
break ;
}
2022-02-05 12:08:40 +00:00
case eMissionTaskType : : PLACE_MODEL :
{
AddProgress ( count ) ;
break ;
}
2023-08-04 02:44:03 +00:00
case eMissionTaskType : : DONATION :
AddProgress ( count ) ;
break ;
2021-12-05 17:54:36 +00:00
default :
2023-10-21 23:31:55 +00:00
LOG ( " Invalid mission task type (%i)! " , static_cast < int > ( type ) ) ;
2021-12-05 17:54:36 +00:00
return ;
}
CheckCompletion ( ) ;
}
MissionTask : : ~ MissionTask ( ) {
targets . clear ( ) ;
parameters . clear ( ) ;
unique . clear ( ) ;
}