|
@@ -26,6 +26,8 @@
|
|
#include "party.hpp"
|
|
#include "party.hpp"
|
|
#include "pc.hpp"
|
|
#include "pc.hpp"
|
|
|
|
|
|
|
|
+using namespace rathena;
|
|
|
|
+
|
|
static int split_exact_quest_time(char* modif_p, int* day, int* hour, int* minute, int *second);
|
|
static int split_exact_quest_time(char* modif_p, int* day, int* hour, int* minute, int *second);
|
|
|
|
|
|
const std::string QuestDatabase::getDefaultLocation() {
|
|
const std::string QuestDatabase::getDefaultLocation() {
|
|
@@ -162,13 +164,6 @@ uint64 QuestDatabase::parseBodyNode(const ryml::NodeRef& node) {
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!this->nodeExists(targetNode, "Mob") && !this->nodeExists(targetNode, "MinLevel") && !this->nodeExists(targetNode, "MaxLevel") &&
|
|
|
|
- !this->nodeExists(targetNode, "Race") && !this->nodeExists(targetNode, "Size") && !this->nodeExists(targetNode, "Element") &&
|
|
|
|
- !this->nodeExists(targetNode, "Location") && !this->nodeExists(targetNode, "MapName")) {
|
|
|
|
- this->invalidWarning(targetNode, "Targets is missing required field, skipping.\n");
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
target = std::make_shared<s_quest_objective>();
|
|
target = std::make_shared<s_quest_objective>();
|
|
target->index = index;
|
|
target->index = index;
|
|
target->mob_id = mob_id;
|
|
target->mob_id = mob_id;
|
|
@@ -279,7 +274,7 @@ uint64 QuestDatabase::parseBodyNode(const ryml::NodeRef& node) {
|
|
|
|
|
|
uint16 mapindex = mapindex_name2idx(location.c_str(), nullptr);
|
|
uint16 mapindex = mapindex_name2idx(location.c_str(), nullptr);
|
|
|
|
|
|
- if (mapindex == 0) {
|
|
|
|
|
|
+ if (mapindex == 0 && strcmpi(location.c_str(), "All") != 0) {
|
|
this->invalidWarning(targetNode["Location"], "Map \"%s\" not found.\n", location.c_str());
|
|
this->invalidWarning(targetNode["Location"], "Map \"%s\" not found.\n", location.c_str());
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -296,6 +291,35 @@ uint64 QuestDatabase::parseBodyNode(const ryml::NodeRef& node) {
|
|
target->map_name = map_name;
|
|
target->map_name = map_name;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (this->nodeExists(targetNode, "MapMobTargets")) {
|
|
|
|
+ const auto& MapMobTargetsNode = targetNode["MapMobTargets"];
|
|
|
|
+
|
|
|
|
+ for (const auto& MapMobTargetsIt : MapMobTargetsNode) {
|
|
|
|
+ std::string mob_name;
|
|
|
|
+ c4::from_chars(MapMobTargetsIt.key(), &mob_name);
|
|
|
|
+
|
|
|
|
+ std::shared_ptr<s_mob_db> mob = mobdb_search_aegisname(mob_name.c_str());
|
|
|
|
+
|
|
|
|
+ if (!mob) {
|
|
|
|
+ this->invalidWarning(MapMobTargetsNode[MapMobTargetsIt.key()], "Mob %s does not exist, skipping.\n", mob_name.c_str());
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bool active;
|
|
|
|
+
|
|
|
|
+ if (!this->asBool(MapMobTargetsNode, mob_name, active))
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ if (!active) {
|
|
|
|
+ util::vector_erase_if_exists(target->mobs_allowed, mob->id);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!util::vector_exists( target->mobs_allowed, mob->id ))
|
|
|
|
+ target->mobs_allowed.push_back(mob->id);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
// if max_level is set, min_level is 1
|
|
// if max_level is set, min_level is 1
|
|
if (target->min_level == 0 && target->max_level > 0)
|
|
if (target->min_level == 0 && target->max_level > 0)
|
|
target->min_level = 1;
|
|
target->min_level = 1;
|
|
@@ -708,11 +732,13 @@ void quest_update_objective(struct map_session_data *sd, struct mob_data* md)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
// Process quest objectives
|
|
// Process quest objectives
|
|
|
|
+ uint8 total_check = 7; // Must pass all checks
|
|
|
|
+
|
|
for (int j = 0; j < qi->objectives.size(); j++) {
|
|
for (int j = 0; j < qi->objectives.size(); j++) {
|
|
- uint8 objective_check = 0; // Must pass all 6 checks
|
|
|
|
|
|
+ uint8 objective_check = 0;
|
|
|
|
|
|
if (qi->objectives[j]->mob_id == md->mob_id)
|
|
if (qi->objectives[j]->mob_id == md->mob_id)
|
|
- objective_check = 6;
|
|
|
|
|
|
+ objective_check = total_check;
|
|
else if (qi->objectives[j]->mob_id == 0) {
|
|
else if (qi->objectives[j]->mob_id == 0) {
|
|
if (qi->objectives[j]->min_level == 0 || qi->objectives[j]->min_level <= md->level)
|
|
if (qi->objectives[j]->min_level == 0 || qi->objectives[j]->min_level <= md->level)
|
|
objective_check++;
|
|
objective_check++;
|
|
@@ -724,17 +750,21 @@ void quest_update_objective(struct map_session_data *sd, struct mob_data* md)
|
|
objective_check++;
|
|
objective_check++;
|
|
if (qi->objectives[j]->element == ELE_ALL || qi->objectives[j]->element == md->status.def_ele)
|
|
if (qi->objectives[j]->element == ELE_ALL || qi->objectives[j]->element == md->status.def_ele)
|
|
objective_check++;
|
|
objective_check++;
|
|
- if (qi->objectives[j]->mapid < 0 || (qi->objectives[j]->mapid == sd->bl.m && md->spawn != nullptr))
|
|
|
|
|
|
+ if (qi->objectives[j]->mapid < 0)
|
|
objective_check++;
|
|
objective_check++;
|
|
- else if (qi->objectives[j]->mapid >= 0) {
|
|
|
|
|
|
+ else if (qi->objectives[j]->mapid == sd->bl.m)
|
|
|
|
+ objective_check++;
|
|
|
|
+ else {
|
|
struct map_data *mapdata = map_getmapdata(sd->bl.m);
|
|
struct map_data *mapdata = map_getmapdata(sd->bl.m);
|
|
|
|
|
|
if (mapdata->instance_id && mapdata->instance_src_map == qi->objectives[j]->mapid)
|
|
if (mapdata->instance_id && mapdata->instance_src_map == qi->objectives[j]->mapid)
|
|
objective_check++;
|
|
objective_check++;
|
|
}
|
|
}
|
|
|
|
+ if (qi->objectives[j]->mobs_allowed.empty() || util::vector_exists( qi->objectives[j]->mobs_allowed, md->mob_id ))
|
|
|
|
+ objective_check++;
|
|
}
|
|
}
|
|
|
|
|
|
- if (objective_check == 6 && sd->quest_log[i].count[j] < qi->objectives[j]->count) {
|
|
|
|
|
|
+ if (objective_check == total_check && sd->quest_log[i].count[j] < qi->objectives[j]->count) {
|
|
sd->quest_log[i].count[j]++;
|
|
sd->quest_log[i].count[j]++;
|
|
sd->save_quest = true;
|
|
sd->save_quest = true;
|
|
clif_quest_update_objective(sd, &sd->quest_log[i]);
|
|
clif_quest_update_objective(sd, &sd->quest_log[i]);
|