mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-08-09 20:24:16 +00:00
.github
cmake
dAuthServer
dChatFilter
dChatServer
dCommon
dDatabase
dGame
dBehaviors
dComponents
dEntity
dGameMessages
dInventory
dMission
CMakeLists.txt
Mission.cpp
Mission.h
MissionPrerequisites.cpp
MissionPrerequisites.h
MissionTask.cpp
MissionTask.h
dPropertyBehaviors
dUtilities
CMakeLists.txt
Character.cpp
Character.h
Entity.cpp
Entity.h
EntityManager.cpp
EntityManager.h
LeaderboardManager.cpp
LeaderboardManager.h
PlayerManager.cpp
PlayerManager.h
TeamManager.cpp
TeamManager.h
TradingManager.cpp
TradingManager.h
User.cpp
User.h
UserManager.cpp
UserManager.h
dMasterServer
dNavigation
dNet
dPhysics
dScripts
dServer
dWeb
dWorldServer
dZoneManager
docs
migrations
resources
tests
thirdparty
vanity
.dockerignore
.editorconfig
.env.example
.git-blame-ignore-revs
.gitattributes
.gitignore
.gitmodules
CMakeLists.txt
CMakePresets.json
CMakeVariables.txt
CONTRIBUTING.md
Dockerfile
LICENSE
README.md
SECURITY.md
build.sh
docker-compose.yml
entrypoint.sh
logo.png
systemd.example
versions.txt
179 lines
3.7 KiB
C++
179 lines
3.7 KiB
C++
#include "MissionPrerequisites.h"
|
|
|
|
#include <sstream>
|
|
#include <ctime>
|
|
|
|
#include "CDClientManager.h"
|
|
#include "Logger.h"
|
|
|
|
|
|
PrerequisiteExpression::PrerequisiteExpression(const std::string& str) {
|
|
std::stringstream a;
|
|
std::stringstream b;
|
|
std::stringstream s;
|
|
|
|
auto bor = false;
|
|
|
|
auto sub = false;
|
|
|
|
auto done = false;
|
|
|
|
for (auto i = 0u; i < str.size(); ++i) {
|
|
if (done) {
|
|
break;
|
|
}
|
|
|
|
const auto character = str[i];
|
|
|
|
switch (character) {
|
|
case '|':
|
|
bor = true;
|
|
b << str.substr(i + 1);
|
|
done = true;
|
|
break;
|
|
case ' ':
|
|
case ')':
|
|
break;
|
|
case ',':
|
|
case '&':
|
|
case '(':
|
|
b << str.substr(i + 1);
|
|
done = true;
|
|
break;
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
if (sub) {
|
|
s << character;
|
|
} else {
|
|
a << character;
|
|
}
|
|
break;
|
|
case ':':
|
|
sub = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
this->m_or = bor;
|
|
|
|
const auto aString = a.str();
|
|
|
|
if (!aString.empty()) {
|
|
this->a = std::stoul(a.str());
|
|
} else {
|
|
this->a = 0;
|
|
}
|
|
|
|
const auto subString = s.str();
|
|
|
|
if (!subString.empty()) {
|
|
this->sub = std::stoul(s.str());
|
|
} else {
|
|
this->sub = 0;
|
|
}
|
|
|
|
const auto bString = b.str();
|
|
|
|
if (!bString.empty()) {
|
|
this->b = new PrerequisiteExpression(bString);
|
|
} else {
|
|
this->b = nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
bool PrerequisiteExpression::Execute(const std::unordered_map<uint32_t, Mission*>& missions) const {
|
|
auto a = this->a == 0;
|
|
|
|
auto b = this->b == nullptr;
|
|
|
|
if (!a) {
|
|
const auto index = missions.find(this->a);
|
|
|
|
if (index != missions.end()) {
|
|
const auto* mission = index->second;
|
|
|
|
if (this->sub != 0) {
|
|
// Special case for one Wisp Lee repeatable mission.
|
|
a = mission->GetMissionState() == static_cast<eMissionState>(this->sub);
|
|
} else if (mission->IsComplete()) {
|
|
a = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!b) {
|
|
b = this->b->Execute(missions);
|
|
}
|
|
|
|
if (this->m_or) {
|
|
return a || b;
|
|
}
|
|
|
|
return a && b;
|
|
}
|
|
|
|
|
|
PrerequisiteExpression::~PrerequisiteExpression() {
|
|
delete b;
|
|
}
|
|
|
|
|
|
bool MissionPrerequisites::CanAccept(const uint32_t missionId, const std::unordered_map<uint32_t, Mission*>& missions) {
|
|
const auto& missionIndex = missions.find(missionId);
|
|
|
|
if (missionIndex != missions.end()) {
|
|
auto* mission = missionIndex->second;
|
|
const auto& info = mission->GetClientInfo();
|
|
|
|
if (info.repeatable) {
|
|
const auto prerequisitesMet = CheckPrerequisites(missionId, missions);
|
|
|
|
// Checked by client
|
|
const time_t time = std::time(nullptr);
|
|
const time_t lock = mission->GetTimestamp() + info.cooldownTime * 60;
|
|
|
|
// If there's no time limit, just check the prerequisites, otherwise make sure both conditions are met
|
|
return (info.cooldownTime == -1 ? prerequisitesMet : (lock - time < 0)) && prerequisitesMet;
|
|
}
|
|
|
|
// Mission is already accepted and cannot be repeatedly accepted
|
|
return false;
|
|
}
|
|
|
|
// Mission is not yet accepted, check the prerequisites
|
|
return CheckPrerequisites(missionId, missions);
|
|
}
|
|
|
|
bool MissionPrerequisites::CheckPrerequisites(uint32_t missionId, const std::unordered_map<uint32_t, Mission*>& missions) {
|
|
const auto& index = expressions.find(missionId);
|
|
if (index != expressions.end()) {
|
|
return index->second->Execute(missions);
|
|
}
|
|
|
|
auto* missionsTable = CDClientManager::GetTable<CDMissionsTable>();
|
|
const auto missionEntries = missionsTable->Query([=](const CDMissions& entry) {
|
|
return entry.id == static_cast<int>(missionId);
|
|
});
|
|
|
|
if (missionEntries.empty())
|
|
return false;
|
|
|
|
auto* expression = new PrerequisiteExpression(missionEntries[0].prereqMissionID);
|
|
expressions.insert_or_assign(missionId, expression);
|
|
|
|
return expression->Execute(missions);
|
|
}
|
|
|
|
std::unordered_map<uint32_t, PrerequisiteExpression*> MissionPrerequisites::expressions = {};
|