Questinfo correction (#5523)
* Corrected questinfo bubble not always being displayed * Docs updated * Changed qi_display to std::vector Co-authored-by: Lemongrass3110 <lemongrass@kstp.at> Thanks to @lighta @aleos89 @Lemongrass3110 !
This commit is contained in:
parent
67b95f8660
commit
a33887b59f
@ -9260,7 +9260,7 @@ Examples:
|
||||
|
||||
*questinfo <Icon>{,<Map Mark Color>{,"<condition>"}};
|
||||
|
||||
This command should only be used in an OnInit label.
|
||||
This command should only be used in OnInit/OnInstanceInit labels.
|
||||
Show an emotion on top of a NPC, and optionally, a colored mark in the mini-map like "viewpoint".
|
||||
When a user is doing some action, each NPC is checked for questinfo that has been set on the map.
|
||||
If questinfo is present, it will check if the player fulfill the condition.
|
||||
|
@ -3691,10 +3691,6 @@ void map_data_copy(struct map_data *dst_map, struct map_data *src_map) {
|
||||
dst_map->skill_duration.insert(src_map->skill_duration.begin(), src_map->skill_duration.end());
|
||||
|
||||
dst_map->zone = src_map->zone;
|
||||
|
||||
// Mimic questinfo
|
||||
if (!src_map->qi_data.empty())
|
||||
src_map->qi_data = dst_map->qi_data;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4343,29 +4339,27 @@ int log_sql_init(void)
|
||||
|
||||
void map_remove_questinfo(int m, struct npc_data *nd) {
|
||||
struct map_data *mapdata = map_getmapdata(m);
|
||||
struct s_questinfo *qi;
|
||||
|
||||
nullpo_retv(nd);
|
||||
nullpo_retv(mapdata);
|
||||
|
||||
for (int i = 0; i < mapdata->qi_data.size(); i++) {
|
||||
qi = &mapdata->qi_data[i];
|
||||
if (qi && qi->nd == nd) {
|
||||
script_free_code(qi->condition);
|
||||
mapdata->qi_data.erase(mapdata->qi_data.begin() + i);
|
||||
}
|
||||
}
|
||||
util::vector_erase_if_exists(mapdata->qi_npc, nd->bl.id);
|
||||
nd->qi_data.clear();
|
||||
}
|
||||
|
||||
static void map_free_questinfo(struct map_data *mapdata) {
|
||||
nullpo_retv(mapdata);
|
||||
|
||||
for (const auto &it : mapdata->qi_data) {
|
||||
if (it.condition)
|
||||
script_free_code(it.condition);
|
||||
for (const auto &it : mapdata->qi_npc) {
|
||||
struct npc_data *nd = map_id2nd(it);
|
||||
|
||||
if (!nd || nd->qi_data.empty())
|
||||
continue;
|
||||
|
||||
nd->qi_data.clear();
|
||||
}
|
||||
|
||||
mapdata->qi_data.clear();
|
||||
mapdata->qi_npc.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4876,6 +4870,10 @@ void do_final(void){
|
||||
map_quit(sd);
|
||||
mapit_free(iter);
|
||||
|
||||
for (int i = 0; i < map_num; i++) {
|
||||
map_free_questinfo(map_getmapdata(i));
|
||||
}
|
||||
|
||||
/* prepares npcs for a faster shutdown process */
|
||||
do_clear_npc();
|
||||
|
||||
@ -4939,7 +4937,6 @@ void do_final(void){
|
||||
for (int j=0; j<MAX_MOB_LIST_PER_MAP; j++)
|
||||
if (mapdata->moblist[j]) aFree(mapdata->moblist[j]);
|
||||
}
|
||||
map_free_questinfo(mapdata);
|
||||
mapdata->damage_adjust = {};
|
||||
}
|
||||
|
||||
|
@ -722,13 +722,6 @@ struct iwall_data {
|
||||
bool shootable;
|
||||
};
|
||||
|
||||
struct s_questinfo {
|
||||
struct npc_data *nd;
|
||||
e_questinfo_types icon;
|
||||
e_questinfo_markcolor color;
|
||||
struct script_code* condition;
|
||||
};
|
||||
|
||||
struct map_data {
|
||||
char name[MAP_NAME_LENGTH];
|
||||
uint16 index; // The map index used by the mapindex* functions.
|
||||
@ -766,7 +759,7 @@ struct map_data {
|
||||
struct Channel *channel;
|
||||
|
||||
/* ShowEvent Data Cache */
|
||||
std::vector<s_questinfo> qi_data;
|
||||
std::vector<int> qi_npc;
|
||||
|
||||
/* speeds up clif_updatestatus processing by causing hpmeter to run only when someone with the permission can view it */
|
||||
unsigned short hpmeter_visible;
|
||||
|
@ -2483,6 +2483,8 @@ int npc_unload(struct npc_data* nd, bool single) {
|
||||
}
|
||||
}
|
||||
|
||||
nd->qi_data.clear();
|
||||
|
||||
script_stop_sleeptimers(nd->bl.id);
|
||||
aFree(nd);
|
||||
|
||||
|
@ -51,6 +51,18 @@ struct s_npc_buy_list {
|
||||
#pragma pack(pop)
|
||||
#endif // not NetBSD < 6 / Solaris
|
||||
|
||||
struct s_questinfo {
|
||||
e_questinfo_types icon;
|
||||
e_questinfo_markcolor color;
|
||||
struct script_code* condition;
|
||||
|
||||
~s_questinfo(){
|
||||
if( this->condition != nullptr ){
|
||||
script_free_code( this->condition );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct npc_data {
|
||||
struct block_list bl;
|
||||
struct unit_data ud; //Because they need to be able to move....
|
||||
@ -112,6 +124,8 @@ struct npc_data {
|
||||
struct sc_display_entry **sc_display;
|
||||
unsigned char sc_display_count;
|
||||
|
||||
std::vector<std::shared_ptr<s_questinfo>> qi_data;
|
||||
|
||||
struct {
|
||||
t_tick timeout;
|
||||
unsigned long color;
|
||||
|
@ -1690,9 +1690,6 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_
|
||||
sd->vars_ok = false;
|
||||
sd->vars_received = 0x0;
|
||||
|
||||
sd->qi_display = nullptr;
|
||||
sd->qi_count = 0;
|
||||
|
||||
//warp player
|
||||
if ((i=pc_setpos(sd,sd->status.last_point.map, sd->status.last_point.x, sd->status.last_point.y, CLR_OUTSIGHT)) != SETPOS_OK) {
|
||||
ShowError ("Last_point_map %s - id %d not found (error code %d)\n", mapindex_id2name(sd->status.last_point.map), sd->status.last_point.map, i);
|
||||
@ -13319,33 +13316,6 @@ void pc_validate_skill(struct map_session_data *sd) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle to remember if the questinfo is displayed yet or not.
|
||||
* @param qi_display Display flag
|
||||
* @param show If show is true and qi_display is 0, set qi_display to 1 and show the event bubble.
|
||||
* If show is false and qi_display is 1, set qi_display to 0 and hide the event bubble.
|
||||
**/
|
||||
static void pc_show_questinfo_sub(struct map_session_data *sd, bool *qi_display, struct s_questinfo *qi, bool show) {
|
||||
if (show) {
|
||||
// Check if need to be displayed
|
||||
if ((*qi_display) != 1) {
|
||||
(*qi_display) = 1;
|
||||
clif_quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Check if need to be hide
|
||||
if ((*qi_display) != 0) {
|
||||
(*qi_display) = 0;
|
||||
#if PACKETVER >= 20120410
|
||||
clif_quest_show_event(sd, &qi->nd->bl, QTYPE_NONE, QMARK_NONE);
|
||||
#else
|
||||
clif_quest_show_event(sd, &qi->nd->bl, QTYPE_QUEST, QMARK_NONE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show available NPC Quest / Event Icon Check [Kisuka]
|
||||
* @param sd Player
|
||||
@ -13360,28 +13330,45 @@ void pc_show_questinfo(struct map_session_data *sd) {
|
||||
struct map_data *mapdata = map_getmapdata(sd->bl.m);
|
||||
nullpo_retv(mapdata);
|
||||
|
||||
if (mapdata->qi_data.empty())
|
||||
if (mapdata->qi_npc.empty())
|
||||
return;
|
||||
if (mapdata->qi_data.size() != sd->qi_count)
|
||||
if (mapdata->qi_npc.size() != sd->qi_display.size())
|
||||
return; // init was not called yet
|
||||
|
||||
struct s_questinfo *qi = nullptr;
|
||||
bool show;
|
||||
for (int i = 0; i < mapdata->qi_npc.size(); i++) {
|
||||
struct npc_data *nd = map_id2nd(mapdata->qi_npc[i]);
|
||||
|
||||
for (int i = 0; i < mapdata->qi_data.size(); i++) {
|
||||
qi = &mapdata->qi_data[i];
|
||||
if (!qi)
|
||||
continue;
|
||||
if (!nd || nd->qi_data.empty())
|
||||
continue;
|
||||
|
||||
if (!qi->condition)
|
||||
show = true;
|
||||
else {
|
||||
if (achievement_check_condition(qi->condition, sd))
|
||||
bool show = false;
|
||||
|
||||
for (auto &qi : nd->qi_data) {
|
||||
if (!qi->condition || achievement_check_condition(qi->condition, sd)) {
|
||||
show = true;
|
||||
else
|
||||
show = false;
|
||||
// Check if need to be displayed
|
||||
if (!sd->qi_display[i].is_active || qi->icon != sd->qi_display[i].icon || qi->color != sd->qi_display[i].color) {
|
||||
sd->qi_display[i].is_active = true;
|
||||
sd->qi_display[i].icon = qi->icon;
|
||||
sd->qi_display[i].color = qi->color;
|
||||
clif_quest_show_event(sd, &nd->bl, qi->icon, qi->color);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (show == false) {
|
||||
// Check if need to be hide
|
||||
if (sd->qi_display[i].is_active) {
|
||||
sd->qi_display[i].is_active = false;
|
||||
sd->qi_display[i].icon = QTYPE_NONE;
|
||||
sd->qi_display[i].color = QMARK_NONE;
|
||||
#if PACKETVER >= 20120410
|
||||
clif_quest_show_event(sd, &nd->bl, QTYPE_NONE, QMARK_NONE);
|
||||
#else
|
||||
clif_quest_show_event(sd, &nd->bl, QTYPE_QUEST, QMARK_NONE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
pc_show_questinfo_sub(sd, &sd->qi_display[i], qi, show);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -13394,11 +13381,7 @@ void pc_show_questinfo_reinit(struct map_session_data *sd) {
|
||||
#if PACKETVER >= 20090218
|
||||
nullpo_retv(sd);
|
||||
|
||||
if (sd->qi_display) {
|
||||
aFree(sd->qi_display);
|
||||
sd->qi_display = nullptr;
|
||||
}
|
||||
sd->qi_count = 0;
|
||||
sd->qi_display.clear();
|
||||
|
||||
if (sd->bl.m < 0 || sd->bl.m >= MAX_MAPINDEX)
|
||||
return;
|
||||
@ -13406,10 +13389,14 @@ void pc_show_questinfo_reinit(struct map_session_data *sd) {
|
||||
struct map_data *mapdata = map_getmapdata(sd->bl.m);
|
||||
nullpo_retv(mapdata);
|
||||
|
||||
if (mapdata->qi_data.empty())
|
||||
if (mapdata->qi_npc.empty())
|
||||
return;
|
||||
|
||||
CREATE(sd->qi_display, bool, (sd->qi_count = mapdata->qi_data.size()));
|
||||
sd->qi_display.reserve( mapdata->qi_npc.size() );
|
||||
|
||||
for( int i = 0; i < mapdata->qi_npc.size(); i++ ){
|
||||
sd->qi_display.push_back( s_qi_display() );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -267,6 +267,12 @@ struct s_combos {
|
||||
uint32 pos;
|
||||
};
|
||||
|
||||
struct s_qi_display {
|
||||
bool is_active;
|
||||
e_questinfo_types icon;
|
||||
e_questinfo_markcolor color;
|
||||
};
|
||||
|
||||
struct map_session_data {
|
||||
struct block_list bl;
|
||||
struct unit_data ud;
|
||||
@ -678,8 +684,7 @@ struct map_session_data {
|
||||
std::vector<int> cloaked_npc;
|
||||
|
||||
/* ShowEvent Data Cache flags from map */
|
||||
bool *qi_display;
|
||||
int qi_count;
|
||||
std::vector<s_qi_display> qi_display;
|
||||
|
||||
// temporary debug [flaviojs]
|
||||
const char* debug_file;
|
||||
|
@ -19733,9 +19733,6 @@ BUILDIN_FUNC(questinfo)
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
struct s_questinfo qi;
|
||||
struct script_code *script = nullptr;
|
||||
int color = QMARK_NONE;
|
||||
int icon = script_getnum(st, 2);
|
||||
|
||||
#if PACKETVER >= 20120410
|
||||
@ -19772,6 +19769,8 @@ BUILDIN_FUNC(questinfo)
|
||||
icon = icon + 1;
|
||||
#endif
|
||||
|
||||
int color = QMARK_NONE;
|
||||
|
||||
if (script_hasdata(st, 3)) {
|
||||
color = script_getnum(st, 3);
|
||||
if (color < QMARK_NONE || color >= QMARK_MAX) {
|
||||
@ -19781,6 +19780,8 @@ BUILDIN_FUNC(questinfo)
|
||||
}
|
||||
}
|
||||
|
||||
struct script_code *script = nullptr;
|
||||
|
||||
if (script_hasdata(st, 4)) {
|
||||
const char *str = script_getstr(st, 4);
|
||||
|
||||
@ -19798,13 +19799,18 @@ BUILDIN_FUNC(questinfo)
|
||||
}
|
||||
}
|
||||
|
||||
qi.nd = nd;
|
||||
qi.icon = static_cast<e_questinfo_types>(icon);
|
||||
qi.color = static_cast<e_questinfo_markcolor>(color);
|
||||
qi.condition = script;
|
||||
std::shared_ptr<s_questinfo> qi = std::make_shared<s_questinfo>();
|
||||
|
||||
qi->icon = static_cast<e_questinfo_types>(icon);
|
||||
qi->color = static_cast<e_questinfo_markcolor>(color);
|
||||
qi->condition = script;
|
||||
|
||||
nd->qi_data.push_back(qi);
|
||||
|
||||
struct map_data *mapdata = map_getmapdata(nd->bl.m);
|
||||
mapdata->qi_data.push_back(qi);
|
||||
|
||||
if (mapdata && !util::vector_exists(mapdata->qi_npc, nd->bl.id))
|
||||
mapdata->qi_npc.push_back(nd->bl.id);
|
||||
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
@ -3397,11 +3397,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
|
||||
sd->num_quests = sd->avail_quests = 0;
|
||||
}
|
||||
|
||||
if (sd->qi_display) {
|
||||
aFree(sd->qi_display);
|
||||
sd->qi_display = NULL;
|
||||
}
|
||||
sd->qi_count = 0;
|
||||
sd->qi_display.clear();
|
||||
|
||||
#if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
|
||||
sd->hatEffects.clear();
|
||||
|
Loading…
x
Reference in New Issue
Block a user