add V_V1Present token in quest conditions
This commit is contained in:
+19
-24
@@ -349,46 +349,41 @@ shared_ptr<const TeamIndex::Team> Client::team() const {
|
||||
return team;
|
||||
}
|
||||
|
||||
bool Client::can_see_quest(shared_ptr<const Quest> q, uint8_t event, uint8_t difficulty, size_t num_players) const {
|
||||
bool Client::evaluate_quest_availability_expression(
|
||||
shared_ptr<const QuestAvailabilityExpression> expr,
|
||||
uint8_t event,
|
||||
uint8_t difficulty,
|
||||
size_t num_players,
|
||||
bool v1_present) const {
|
||||
if (this->license && this->license->check_flag(License::Flag::DISABLE_QUEST_REQUIREMENTS)) {
|
||||
return true;
|
||||
}
|
||||
if (!q->available_expression) {
|
||||
if (!expr) {
|
||||
return true;
|
||||
}
|
||||
auto p = this->character();
|
||||
string expr = q->available_expression->str();
|
||||
QuestAvailabilityExpression::Env env = {
|
||||
.flags = &p->quest_flags.data.at(difficulty),
|
||||
.challenge_records = &p->challenge_records,
|
||||
.team = this->team(),
|
||||
.num_players = num_players,
|
||||
.event = event,
|
||||
.v1_present = v1_present,
|
||||
};
|
||||
int64_t ret = q->available_expression->evaluate(env);
|
||||
this->log.info("Evaluated quest availability expression %s => %s", expr.c_str(), ret ? "TRUE" : "FALSE");
|
||||
int64_t ret = expr->evaluate(env);
|
||||
if (this->log.should_log(LogLevel::INFO)) {
|
||||
string expr_str = expr->str();
|
||||
this->log.info("Evaluated quest availability expression %s => %s", expr_str.c_str(), ret ? "TRUE" : "FALSE");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Client::can_play_quest(shared_ptr<const Quest> q, uint8_t event, uint8_t difficulty, size_t num_players) const {
|
||||
if (this->license && this->license->check_flag(License::Flag::DISABLE_QUEST_REQUIREMENTS)) {
|
||||
return true;
|
||||
}
|
||||
if (!q->enabled_expression) {
|
||||
return true;
|
||||
}
|
||||
auto p = this->character();
|
||||
string expr = q->enabled_expression->str();
|
||||
QuestAvailabilityExpression::Env env = {
|
||||
.flags = &p->quest_flags.data.at(difficulty),
|
||||
.challenge_records = &p->challenge_records,
|
||||
.team = this->team(),
|
||||
.num_players = num_players,
|
||||
.event = event,
|
||||
};
|
||||
bool ret = q->enabled_expression->evaluate(env);
|
||||
this->log.info("Evaluating quest enabled expression %s => %s", expr.c_str(), ret ? "TRUE" : "FALSE");
|
||||
return ret;
|
||||
bool Client::can_see_quest(shared_ptr<const Quest> q, uint8_t event, uint8_t difficulty, size_t num_players, bool v1_present) const {
|
||||
return this->evaluate_quest_availability_expression(q->available_expression, event, difficulty, num_players, v1_present);
|
||||
}
|
||||
|
||||
bool Client::can_play_quest(shared_ptr<const Quest> q, uint8_t event, uint8_t difficulty, size_t num_players, bool v1_present) const {
|
||||
return this->evaluate_quest_availability_expression(q->enabled_expression, event, difficulty, num_players, v1_present);
|
||||
}
|
||||
|
||||
bool Client::can_use_chat_commands() const {
|
||||
|
||||
+8
-2
@@ -290,8 +290,14 @@ public:
|
||||
|
||||
std::shared_ptr<const TeamIndex::Team> team() const;
|
||||
|
||||
bool can_see_quest(std::shared_ptr<const Quest> q, uint8_t event, uint8_t difficulty, size_t num_players) const;
|
||||
bool can_play_quest(std::shared_ptr<const Quest> q, uint8_t event, uint8_t difficulty, size_t num_players) const;
|
||||
bool evaluate_quest_availability_expression(
|
||||
std::shared_ptr<const QuestAvailabilityExpression> expr,
|
||||
uint8_t event,
|
||||
uint8_t difficulty,
|
||||
size_t num_players,
|
||||
bool v1_present) const;
|
||||
bool can_see_quest(std::shared_ptr<const Quest> q, uint8_t event, uint8_t difficulty, size_t num_players, bool v1_present) const;
|
||||
bool can_play_quest(std::shared_ptr<const Quest> q, uint8_t event, uint8_t difficulty, size_t num_players, bool v1_present) const;
|
||||
|
||||
bool can_use_chat_commands() const;
|
||||
|
||||
|
||||
+17
-6
@@ -496,13 +496,22 @@ bool Lobby::any_client_loading() const {
|
||||
size_t Lobby::count_clients() const {
|
||||
size_t ret = 0;
|
||||
for (size_t x = 0; x < this->max_clients; x++) {
|
||||
if (this->clients[x].get()) {
|
||||
if (this->clients[x]) {
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Lobby::any_v1_clients_present() const {
|
||||
for (size_t x = 0; x < this->max_clients; x++) {
|
||||
if (this->clients[x] && is_v1(this->clients[x]->version())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Lobby::add_client(shared_ptr<Client> c, ssize_t required_client_id) {
|
||||
ssize_t index;
|
||||
ssize_t min_client_id = this->check_flag(Lobby::Flag::IS_SPECTATOR_TEAM) ? 4 : 0;
|
||||
@@ -752,8 +761,9 @@ Lobby::JoinError Lobby::join_error_for_client(std::shared_ptr<Client> c, const s
|
||||
}
|
||||
if (this->quest) {
|
||||
size_t num_clients = this->count_clients() + 1;
|
||||
if (!c->can_see_quest(this->quest, this->event, this->difficulty, num_clients) ||
|
||||
!c->can_play_quest(this->quest, this->event, this->difficulty, num_clients)) {
|
||||
bool v1_present = is_v1(c->version()) || this->any_v1_clients_present();
|
||||
if (!c->can_see_quest(this->quest, this->event, this->difficulty, num_clients, v1_present) ||
|
||||
!c->can_play_quest(this->quest, this->event, this->difficulty, num_clients, v1_present)) {
|
||||
return JoinError::NO_ACCESS_TO_QUEST;
|
||||
}
|
||||
}
|
||||
@@ -862,13 +872,14 @@ unordered_map<uint32_t, shared_ptr<Client>> Lobby::clients_by_serial_number() co
|
||||
|
||||
QuestIndex::IncludeCondition Lobby::quest_include_condition() const {
|
||||
size_t num_players = this->count_clients();
|
||||
return [this, num_players](shared_ptr<const Quest> q) -> QuestIndex::IncludeState {
|
||||
bool v1_present = this->any_v1_clients_present();
|
||||
return [this, num_players, v1_present](shared_ptr<const Quest> q) -> QuestIndex::IncludeState {
|
||||
bool is_enabled = true;
|
||||
for (const auto& lc : this->clients) {
|
||||
if (lc && !lc->can_see_quest(q, this->event, this->difficulty, num_players)) {
|
||||
if (lc && !lc->can_see_quest(q, this->event, this->difficulty, num_players, v1_present)) {
|
||||
return QuestIndex::IncludeState::HIDDEN;
|
||||
}
|
||||
if (lc && !lc->can_play_quest(q, this->event, this->difficulty, num_players)) {
|
||||
if (lc && !lc->can_play_quest(q, this->event, this->difficulty, num_players, v1_present)) {
|
||||
is_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,6 +252,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
|
||||
|
||||
void reassign_leader_on_client_departure(size_t leaving_client_id);
|
||||
size_t count_clients() const;
|
||||
bool any_v1_clients_present() const;
|
||||
bool any_client_loading() const;
|
||||
|
||||
void add_client(std::shared_ptr<Client> c, ssize_t required_client_id = -1);
|
||||
|
||||
@@ -259,6 +259,20 @@ string QuestAvailabilityExpression::EventLookupNode::str() const {
|
||||
return "V_Event";
|
||||
}
|
||||
|
||||
QuestAvailabilityExpression::V1PresenceLookupNode::V1PresenceLookupNode() {}
|
||||
|
||||
bool QuestAvailabilityExpression::V1PresenceLookupNode::operator==(const Node& other) const {
|
||||
return dynamic_cast<const V1PresenceLookupNode*>(&other) != nullptr;
|
||||
}
|
||||
|
||||
int64_t QuestAvailabilityExpression::V1PresenceLookupNode::evaluate(const Env& env) const {
|
||||
return env.v1_present ? 1 : 0;
|
||||
}
|
||||
|
||||
string QuestAvailabilityExpression::V1PresenceLookupNode::str() const {
|
||||
return "V_V1Present";
|
||||
}
|
||||
|
||||
QuestAvailabilityExpression::ConstantNode::ConstantNode(int64_t value)
|
||||
: value(value) {}
|
||||
|
||||
@@ -412,6 +426,9 @@ unique_ptr<const QuestAvailabilityExpression::Node> QuestAvailabilityExpression:
|
||||
if (text == "V_Event") {
|
||||
return make_unique<EventLookupNode>();
|
||||
}
|
||||
if (text == "V_V1Present") {
|
||||
return make_unique<V1PresenceLookupNode>();
|
||||
}
|
||||
|
||||
// Check for constants
|
||||
if (text == "true") {
|
||||
|
||||
@@ -21,6 +21,7 @@ public:
|
||||
std::shared_ptr<const TeamIndex::Team> team;
|
||||
size_t num_players;
|
||||
uint8_t event;
|
||||
bool v1_present;
|
||||
};
|
||||
|
||||
QuestAvailabilityExpression(const std::string& text);
|
||||
@@ -160,6 +161,15 @@ protected:
|
||||
virtual std::string str() const;
|
||||
};
|
||||
|
||||
class V1PresenceLookupNode : public Node {
|
||||
public:
|
||||
V1PresenceLookupNode();
|
||||
virtual ~V1PresenceLookupNode() = default;
|
||||
virtual bool operator==(const Node& other) const;
|
||||
virtual int64_t evaluate(const Env& env) const;
|
||||
virtual std::string str() const;
|
||||
};
|
||||
|
||||
class ConstantNode : public Node {
|
||||
public:
|
||||
ConstantNode(int64_t value);
|
||||
|
||||
@@ -36,11 +36,17 @@
|
||||
|
||||
// Quests may be set to be unavailable until a preceding quest has been
|
||||
// cleared or a team reward has been purchased. To enable this feature, set a
|
||||
// value for AvailableIf in the quest's JSON file. This field's value should
|
||||
// be an integral expression that tests one or more flags or team rewards, or
|
||||
// the number of players. An example with random values is shown below. This
|
||||
// field is ignored if the player has the DISABLE_QUEST_REQUIREMENTS flag in
|
||||
// their license.
|
||||
// value for AvailableIf in the quest's JSON file. (This is ignored if the
|
||||
// player has the DISABLE_QUEST_REQUIREMENTS flag in their license.) This
|
||||
// field's value should be an expression that tests any of the following:
|
||||
// F_XXXX: Quest flag specified in hex (e.g. F_014D)
|
||||
// CC_EpX_Y: Whether or not Challenge stage X in Episode Y is complete
|
||||
// T_ZZZ: Whether or not the player's BB team has reward ZZZ
|
||||
// V_NumPlayers: The number of players in the current game
|
||||
// V_Event: The holiday event in the current game
|
||||
// V_V1Present: Whether there are any V1 players in the current game
|
||||
// You can also use constants, parentheses, and many common integer and
|
||||
// boolean operators. An example expression with random values is shown here.
|
||||
// "AvailableIf": "(F_016D || T_EpicCustomQuest || (V_NumPlayers <= 2)) && !F_0173",
|
||||
|
||||
// On BB, quests may be disabled but still visible to the player. This
|
||||
|
||||
Reference in New Issue
Block a user