prevent player from joining game if a quest they don't have access to is in progress
This commit is contained in:
@@ -282,6 +282,12 @@ static void server_command_qset_qclear(shared_ptr<Client> c, const std::string&
|
||||
|
||||
uint16_t flag_num = stoul(args, nullptr, 0);
|
||||
|
||||
if (should_set) {
|
||||
c->game_data.character()->quest_flags.set(l->difficulty, flag_num);
|
||||
} else {
|
||||
c->game_data.character()->quest_flags.clear(l->difficulty, flag_num);
|
||||
}
|
||||
|
||||
if (is_v1_or_v2(c->version())) {
|
||||
G_SetQuestFlag_DC_PC_6x75 cmd = {{0x75, 0x02, 0x0000}, flag_num, should_set ? 0 : 1};
|
||||
send_command_t(l, 0x60, 0x00, cmd);
|
||||
|
||||
+18
-1
@@ -246,7 +246,7 @@ shared_ptr<Lobby> Client::require_lobby() const {
|
||||
return l;
|
||||
}
|
||||
|
||||
shared_ptr<const TeamIndex::Team> Client::team() {
|
||||
shared_ptr<const TeamIndex::Team> Client::team() const {
|
||||
if (!this->license) {
|
||||
throw logic_error("Client::team called on client with no license");
|
||||
}
|
||||
@@ -287,6 +287,23 @@ shared_ptr<const TeamIndex::Team> Client::team() {
|
||||
return team;
|
||||
}
|
||||
|
||||
bool Client::can_access_quest(shared_ptr<const Quest> q, uint8_t difficulty) const {
|
||||
if (this->license && (this->license->flags & License::Flag::DISABLE_QUEST_REQUIREMENTS)) {
|
||||
return true;
|
||||
}
|
||||
if ((q->require_flag >= 0) &&
|
||||
!this->game_data.character()->quest_flags.get(difficulty, q->require_flag)) {
|
||||
return false;
|
||||
}
|
||||
if (!q->require_team_reward_key.empty()) {
|
||||
auto team = this->team();
|
||||
if (!team || !team->has_reward(q->require_team_reward_key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Client::dispatch_save_game_data(evutil_socket_t, short, void* ctx) {
|
||||
reinterpret_cast<Client*>(ctx)->save_game_data();
|
||||
}
|
||||
|
||||
+4
-1
@@ -16,6 +16,7 @@
|
||||
#include "PSOProtocol.hh"
|
||||
#include "PatchFileIndex.hh"
|
||||
#include "Player.hh"
|
||||
#include "Quest.hh"
|
||||
#include "QuestScript.hh"
|
||||
#include "TeamIndex.hh"
|
||||
#include "Text.hh"
|
||||
@@ -232,7 +233,9 @@ struct Client : public std::enable_shared_from_this<Client> {
|
||||
std::shared_ptr<ServerState> require_server_state() const;
|
||||
std::shared_ptr<Lobby> require_lobby() const;
|
||||
|
||||
std::shared_ptr<const TeamIndex::Team> team();
|
||||
std::shared_ptr<const TeamIndex::Team> team() const;
|
||||
|
||||
bool can_access_quest(std::shared_ptr<const Quest> q, uint8_t difficulty) const;
|
||||
|
||||
static void dispatch_save_game_data(evutil_socket_t, short, void* ctx);
|
||||
void save_game_data();
|
||||
|
||||
+3
-19
@@ -404,25 +404,9 @@ unordered_map<uint32_t, shared_ptr<Client>> Lobby::clients_by_serial_number() co
|
||||
|
||||
QuestIndex::IncludeCondition Lobby::quest_include_condition() const {
|
||||
return [this](shared_ptr<const Quest> q) -> bool {
|
||||
if (q->require_flag >= 0) {
|
||||
for (const auto& lc : this->clients) {
|
||||
if (lc && !lc->game_data.character()->quest_flags.get(this->difficulty, q->require_flag)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!q->require_team_reward_key.empty()) {
|
||||
// TODO: Technically we should check that all clients are on the SAME
|
||||
// team, but I'm lazy (for now), so we allow clients on different teams
|
||||
// to access the quest as long as all their teams have the quest reward.
|
||||
for (const auto& lc : this->clients) {
|
||||
if (!lc) {
|
||||
continue;
|
||||
}
|
||||
auto team = lc->team();
|
||||
if (!team || !team->has_reward(q->require_team_reward_key)) {
|
||||
return false;
|
||||
}
|
||||
for (const auto& lc : this->clients) {
|
||||
if (lc && !lc->can_access_quest(q, this->difficulty)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -2287,6 +2287,10 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
send_lobby_message_box(c, "$C6Your level is too\nhigh to join this\ngame.");
|
||||
break;
|
||||
}
|
||||
if (game->quest && !c->can_access_quest(game->quest, game->difficulty)) {
|
||||
send_lobby_message_box(c, "$C6You don't have access\nto the quest in progress\nin this game.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!s->change_client_lobby(c, game)) {
|
||||
|
||||
Reference in New Issue
Block a user