From c6f220ee31afb035a76eb9e98a3ee908d29203ee Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 5 Feb 2022 03:28:17 -0800 Subject: [PATCH] Implementing and Fixing All Racing Achievements (#366) * Grammatical changes in comments * Grammatical fixes in comments Small grammatical fixes found in comments throughout the code. * Added descriptions to functions Added descriptions to functions that didn't have them to keep the code well documented * Created RacingTaskParam.h Created RacingTaskParam so eliminate magic numbers in the original implementation of completing racing missions. * Updated magic numbers in Mission.cpp Updated magic numbers in Mission.cpp to a meaningful name. * Implemented racing smashable task progression Previously, races did not progress tasks for smashing Entities. Now all achievements tracking smashables track them correctly. This has been implemented in the three Entities that can be smashed in a race (imagination boxes, track specific smashables, Forbidden Valley dragon eggs). * Updated race imagination task progression Race imagination now no longer uses a magic number when passed to missionComponent. Instead we use a number defined in an enum located in RacingTaskParam.h * Updated Race task checks Racing tasks for completing races without smashing now no longer auto complete the whole chain of missions. Tasks that track placing on tracks and races overall now properly complete. Tasks that count how many missions in a zone are completed now function. Tasks that track race completions in multiple areas now function. * Updated RacingControlComponent.cpp Fixed any tasks that required 3 players to now require 3 or more players in a race to progress. This restriction is ignored if the world config opted in for solo racing to allow progression in solo worlds. Updated magic numbers sent into missionComponent->Progress to an enum created in this PR. Fixed some indentation. * Fixed a grammatical error in variable name Fixed a grammatical error in the enum for task params --- dGame/Entity.cpp | 2 +- dGame/EntityManager.cpp | 2 +- dGame/dComponents/RacingControlComponent.cpp | 46 +++++++++----------- dGame/dComponents/RacingControlComponent.h | 4 +- dGame/dMission/Mission.cpp | 5 +++ dGame/dMission/MissionTask.cpp | 23 +++++----- dGame/dMission/MissionTask.h | 2 +- dGame/dMission/MissionTaskType.h | 2 +- dGame/dMission/RacingTaskParam.h | 20 +++++++++ dScripts/FvRaceSmashEggImagineServer.cpp | 10 +++-- dScripts/RaceImagineCrateServer.cpp | 24 +++++----- dScripts/RaceImagineCrateServer.h | 6 +++ dScripts/RaceImaginePowerup.cpp | 15 +++---- dScripts/RaceSmashServer.cpp | 9 +++- dScripts/RaceSmashServer.h | 6 +++ 15 files changed, 109 insertions(+), 67 deletions(-) create mode 100644 dGame/dMission/RacingTaskParam.h diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index dd6df1d4..6515b9b4 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -346,7 +346,7 @@ void Entity::Initialize() } /** - * Multiple components require te destructible component. + * Multiple components require the destructible component. */ int buffComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, COMPONENT_TYPE_BUFF); diff --git a/dGame/EntityManager.cpp b/dGame/EntityManager.cpp index b9c8763b..8fb75fb2 100644 --- a/dGame/EntityManager.cpp +++ b/dGame/EntityManager.cpp @@ -45,7 +45,7 @@ std::vector EntityManager::m_GhostingExcludedLOTs = { 9524, 12408, - // AG - Fotrace + // AG - Footrace 4967 }; diff --git a/dGame/dComponents/RacingControlComponent.cpp b/dGame/dComponents/RacingControlComponent.cpp index bbd85672..27df339d 100644 --- a/dGame/dComponents/RacingControlComponent.cpp +++ b/dGame/dComponents/RacingControlComponent.cpp @@ -15,6 +15,7 @@ #include "Player.h" #include "PossessableComponent.h" #include "PossessorComponent.h" +#include "RacingTaskParam.h" #include "Spawner.h" #include "VehiclePhysicsComponent.h" #include "dServer.h" @@ -401,18 +402,18 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity *player, auto *missionComponent = player->GetComponent(); - if (missionComponent != nullptr) { - missionComponent->Progress( - MissionTaskType::MISSION_TASK_TYPE_RACING, 0, 13); // Enter race - missionComponent->Progress( - MissionTaskType::MISSION_TASK_TYPE_RACING, data->finished, - 1); // Finish with rating, one track - missionComponent->Progress( - MissionTaskType::MISSION_TASK_TYPE_RACING, data->finished, - 15); // Finish with rating, multiple tracks - missionComponent->Progress( - MissionTaskType::MISSION_TASK_TYPE_RACING, data->smashedTimes, - 10); // Safe driver type missions + if (missionComponent == nullptr) return; + + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, 0, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_COMPETED_IN_RACE); // Progress task for competing in a race + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, data->smashedTimes, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SAFE_DRIVER); // Finish a race without being smashed. + + // If solo racing is enabled OR if there are 3 players in the race, progress placement tasks. + if(m_SoloRacing || m_LoadedPlayers > 2) { + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, data->finished, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_FINISH_WITH_PLACEMENT); // Finish in 1st place on a race + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, data->finished, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_FIRST_PLACE_MULTIPLE_TRACKS); // Finish in 1st place on multiple tracks. + if(m_Finished != 1) return; + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_WIN_RACE_IN_WORLD); // Finished first place in specific world. + } } else if (id == "ACT_RACE_EXIT_THE_RACE?" || id == "Exit") { auto *vehicle = EntityManager::Instance()->GetEntity(data->vehicleID); @@ -809,9 +810,7 @@ void RacingControlComponent::Update(float deltaTime) { // Reached the start point, lapped if (respawnIndex == 0) { - time_t lapTime = - std::time(nullptr) - - (player.lap == 1 ? m_StartTime : player.lapTime); + time_t lapTime = std::time(nullptr) - (player.lap == 1 ? m_StartTime : player.lapTime); // Cheating check if (lapTime < 40) { @@ -833,10 +832,9 @@ void RacingControlComponent::Update(float deltaTime) { playerEntity->GetComponent(); if (missionComponent != nullptr) { - // Lap time - missionComponent->Progress( - MissionTaskType::MISSION_TASK_TYPE_RACING, - (lapTime)*1000, 2); + + // Progress lap time tasks + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, (lapTime)*1000, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_LAP_TIME); if (player.lap == 3) { m_Finished++; @@ -852,15 +850,11 @@ void RacingControlComponent::Update(float deltaTime) { raceTime, raceTime * 1000); // Entire race time - missionComponent->Progress( - MissionTaskType::MISSION_TASK_TYPE_RACING, - (raceTime)*1000, 3); + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, (raceTime)*1000, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_TOTAL_TRACK_TIME); - auto *characterComponent = - playerEntity->GetComponent(); + auto *characterComponent = playerEntity->GetComponent(); if (characterComponent != nullptr) { - characterComponent->TrackRaceCompleted(m_Finished == - 1); + characterComponent->TrackRaceCompleted(m_Finished == 1); } // TODO: Figure out how to update the GUI leaderboard. diff --git a/dGame/dComponents/RacingControlComponent.h b/dGame/dComponents/RacingControlComponent.h index 0dbb9eaa..63d5b2e4 100644 --- a/dGame/dComponents/RacingControlComponent.h +++ b/dGame/dComponents/RacingControlComponent.h @@ -146,7 +146,7 @@ public: void HandleMessageBoxResponse(Entity* player, const std::string& id); /** - * Get the reacing data from a player's LWOOBJID. + * Get the racing data from a player's LWOOBJID. */ RacingPlayerInfo* GetPlayerData(LWOOBJID playerID); @@ -230,7 +230,7 @@ private: std::vector m_LobbyPlayers; /** - * The number of players that have fi nished the race + * The number of players that have finished the race */ uint32_t m_Finished; diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index 28f4b278..854782f9 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -11,6 +11,7 @@ #include "GameMessages.h" #include "Mail.h" #include "MissionComponent.h" +#include "RacingTaskParam.h" #include "dLocale.h" #include "dLogger.h" #include "dServer.h" @@ -314,6 +315,10 @@ void Mission::Complete(const bool yieldRewards) { missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_MISSION_COMPLETE, info->id); + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, info->id, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_COMPLETE_ANY_RACING_TASK); + + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, info->id, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_COMPLETE_TRACK_TASKS); + auto* missionEmailTable = CDClientManager::Instance()->GetTable("MissionEmail"); const auto missionId = GetMissionId(); diff --git a/dGame/dMission/MissionTask.cpp b/dGame/dMission/MissionTask.cpp index 423966c4..d90f7682 100644 --- a/dGame/dMission/MissionTask.cpp +++ b/dGame/dMission/MissionTask.cpp @@ -425,28 +425,27 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& { if (parameters.empty()) break; - if (!InAllTargets(dZoneManager::Instance()->GetZone()->GetWorldID())) break; + if (!InAllTargets(dZoneManager::Instance()->GetZone()->GetWorldID()) && !(parameters[0] == 4 || parameters[0] == 5) && !InAllTargets(value)) break; if (parameters[0] != associate) break; - if (associate == 1 || associate == 15) + if (associate == 1 || associate == 15 || associate == 2 || associate == 3) { if (value > info->targetValue) break; - AddProgress(1); - } - else if (associate == 2 || associate == 3) - { - if (info->targetValue < value) break; - AddProgress(info->targetValue); } else if (associate == 10) { - if (info->targetValue > value) - { - AddProgress(info->targetValue); - } + // If the player did not crash during the race, progress this task by count. + if (value != 0) break; + + AddProgress(count); + } + else if (associate == 4 || associate == 5 || associate == 14) + { + if (!InAllTargets(value)) break; + AddProgress(count); } else { diff --git a/dGame/dMission/MissionTask.h b/dGame/dMission/MissionTask.h index 6cdc4039..b77b9c59 100644 --- a/dGame/dMission/MissionTask.h +++ b/dGame/dMission/MissionTask.h @@ -19,7 +19,7 @@ public: * Attempts to progress this task using the provided parameters. Note that the behavior of this method is different * for each mission task type. * @param value the value to progress by - * @param associate optional object ID of an entity that was related to the porgression + * @param associate optional object ID of an entity that was related to the progression * @param targets optional multiple targets that need to be met to progress * @param count a number that indicates the times to progress */ diff --git a/dGame/dMission/MissionTaskType.h b/dGame/dMission/MissionTaskType.h index 8519e0d9..6643d161 100644 --- a/dGame/dMission/MissionTaskType.h +++ b/dGame/dMission/MissionTaskType.h @@ -5,7 +5,7 @@ enum class MissionTaskType : int { MISSION_TASK_TYPE_UNKNOWN = -1, //!< The task type is unknown MISSION_TASK_TYPE_SMASH = 0, //!< A task for smashing something MISSION_TASK_TYPE_SCRIPT = 1, //!< A task handled by a server LUA script - MISSION_TASK_TYPE_ACTIVITY = 2, //!< A task for completing a quickbuild + MISSION_TASK_TYPE_ACTIVITY = 2, //!< A task for completing a quickbuild MISSION_TASK_TYPE_ENVIRONMENT = 3, //!< A task for something in the environment MISSION_TASK_TYPE_MISSION_INTERACTION = 4, //!< A task for interacting with a mission MISSION_TASK_TYPE_EMOTE = 5, //!< A task for playing an emote diff --git a/dGame/dMission/RacingTaskParam.h b/dGame/dMission/RacingTaskParam.h new file mode 100644 index 00000000..e85d9f91 --- /dev/null +++ b/dGame/dMission/RacingTaskParam.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +enum class RacingTaskParam : int32_t { + RACING_TASK_PARAM_FINISH_WITH_PLACEMENT = 1, //SerializeEntity(killer); } - // Crate is killed by the car + // get possessor to progress statistics and tasks. auto* possessableComponent = killer->GetComponent(); if (possessableComponent != nullptr) { auto* possessor = EntityManager::Instance()->GetEntity(possessableComponent->GetPossessor()); if (possessor != nullptr) { + auto* missionComponent = possessor->GetComponent(); auto* characterComponent = possessor->GetComponent(); if (characterComponent != nullptr) { characterComponent->UpdatePlayerStatistic(ImaginationPowerUpsCollected); characterComponent->UpdatePlayerStatistic(RacingSmashablesSmashed); } + if (missionComponent == nullptr) return; + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, self->GetLOT(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASH_DRAGON_EGGS); } } diff --git a/dScripts/RaceImagineCrateServer.cpp b/dScripts/RaceImagineCrateServer.cpp index f233d408..166b3363 100644 --- a/dScripts/RaceImagineCrateServer.cpp +++ b/dScripts/RaceImagineCrateServer.cpp @@ -1,10 +1,11 @@ -#include "RaceImagineCrateServer.h" -#include "SkillComponent.h" -#include "GameMessages.h" -#include "EntityManager.h" -#include "DestroyableComponent.h" #include "CharacterComponent.h" +#include "DestroyableComponent.h" +#include "EntityManager.h" +#include "GameMessages.h" #include "PossessableComponent.h" +#include "RaceImagineCrateServer.h" +#include "RacingTaskParam.h" +#include "SkillComponent.h" void RaceImagineCrateServer::OnDie(Entity* self, Entity* killer) { @@ -13,8 +14,6 @@ void RaceImagineCrateServer::OnDie(Entity* self, Entity* killer) return; } - //GameMessages::SendPlayFXEffect(self, -1, u"pickup", "", LWOOBJID_EMPTY, 1, 1, true); - self->SetVar(u"bIsDead", true); if (killer == nullptr) @@ -38,21 +37,24 @@ void RaceImagineCrateServer::OnDie(Entity* self, Entity* killer) EntityManager::Instance()->SerializeEntity(killer); } - // Crate is killed by the car + // Find possessor of race car to progress missions and update stats. auto* possessableComponent = killer->GetComponent(); if (possessableComponent != nullptr) { auto* possessor = EntityManager::Instance()->GetEntity(possessableComponent->GetPossessor()); if (possessor != nullptr) { + auto* missionComponent = possessor->GetComponent(); auto* characterComponent = possessor->GetComponent(); + if (characterComponent != nullptr) { characterComponent->UpdatePlayerStatistic(RacingImaginationCratesSmashed); characterComponent->UpdatePlayerStatistic(RacingSmashablesSmashed); } + + // Progress racing smashable missions + if(missionComponent == nullptr) return; + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, 0, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASHABLES); } } - - - //skillComponent->CalculateBehavior(586, 9450, killer->GetObjectID(), true); } diff --git a/dScripts/RaceImagineCrateServer.h b/dScripts/RaceImagineCrateServer.h index 9e8ffa5a..42f36b30 100644 --- a/dScripts/RaceImagineCrateServer.h +++ b/dScripts/RaceImagineCrateServer.h @@ -4,5 +4,11 @@ class RaceImagineCrateServer : public CppScripts::Script { public: +/** + * @brief When a boost smashable has been smashed, this function is called + * + * @param self The Entity that called this function. + * @param killer The Entity that killed this Entity. + */ void OnDie(Entity* self, Entity* killer) override; }; diff --git a/dScripts/RaceImaginePowerup.cpp b/dScripts/RaceImaginePowerup.cpp index 91354acf..43e20e9d 100644 --- a/dScripts/RaceImaginePowerup.cpp +++ b/dScripts/RaceImaginePowerup.cpp @@ -1,9 +1,10 @@ -#include "RaceImaginePowerup.h" -#include "DestroyableComponent.h" -#include "PossessorComponent.h" -#include "EntityManager.h" #include "CharacterComponent.h" +#include "DestroyableComponent.h" +#include "EntityManager.h" #include "PossessableComponent.h" +#include "PossessorComponent.h" +#include "RaceImaginePowerup.h" +#include "RacingTaskParam.h" void RaceImaginePowerup::OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, @@ -36,9 +37,7 @@ void RaceImaginePowerup::OnFireEventServerSide(Entity *self, Entity *sender, std auto* missionComponent = sender->GetComponent(); - if (missionComponent != nullptr) - { - missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, self->GetLOT(), 12); - } + if (missionComponent == nullptr) return; + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, self->GetLOT(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_COLLECT_IMAGINATION); } } diff --git a/dScripts/RaceSmashServer.cpp b/dScripts/RaceSmashServer.cpp index 4fd09f19..059ac430 100644 --- a/dScripts/RaceSmashServer.cpp +++ b/dScripts/RaceSmashServer.cpp @@ -1,7 +1,8 @@ -#include "RaceSmashServer.h" #include "CharacterComponent.h" #include "EntityManager.h" #include "PossessableComponent.h" +#include "RaceSmashServer.h" +#include "RacingTaskParam.h" void RaceSmashServer::OnDie(Entity *self, Entity *killer) { // Crate is smashed by the car @@ -11,10 +12,16 @@ void RaceSmashServer::OnDie(Entity *self, Entity *killer) { auto* possessor = EntityManager::Instance()->GetEntity(possessableComponent->GetPossessor()); if (possessor != nullptr) { + auto* missionComponent = possessor->GetComponent(); auto* characterComponent = possessor->GetComponent(); + if (characterComponent != nullptr) { characterComponent->UpdatePlayerStatistic(RacingSmashablesSmashed); } + + // Progress racing smashable missions + if(missionComponent == nullptr) return; + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, 0, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASHABLES); } } } diff --git a/dScripts/RaceSmashServer.h b/dScripts/RaceSmashServer.h index 750bc00a..7fa1441d 100644 --- a/dScripts/RaceSmashServer.h +++ b/dScripts/RaceSmashServer.h @@ -2,5 +2,11 @@ #include "CppScripts.h" class RaceSmashServer : public CppScripts::Script { + /** + * @brief When a smashable has been destroyed, this function is called. + * + * @param self The Entity that called this function. + * @param killer The Entity that killed this Entity. + */ void OnDie(Entity *self, Entity *killer) override; };