From bf27a9e0cf1bfe9be298c4191010ba6876457d64 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Fri, 25 Oct 2013 09:32:22 -0200 Subject: Quest Bubbles Update - Introduced questinfo cache, memory & processing speed improvement - Fixed mini-map marker support Special Thanks to Haruna Signed-off-by: shennetsind --- src/map/clif.c | 31 ++++++++------------- src/map/instance.c | 10 +++++++ src/map/map.c | 47 +++++++++++++++++++++++++++++++- src/map/map.h | 17 ++++++++++++ src/map/npc.c | 3 ++ src/map/npc.h | 6 ---- src/map/script.c | 80 ++++++++++++++++++++++++++++++++++-------------------- 7 files changed, 138 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/map/clif.c b/src/map/clif.c index 3dba530f4..e47bd2bf4 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -9631,28 +9631,19 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { skill->unit_move(&sd->bl,timer->gettick(),1); // NPC Quest / Event Icon Check [Kisuka] - #if PACKETVER >= 20090218 - for(i = 0; i < map->list[sd->bl.m].npc_num; i++) { - TBL_NPC *nd = map->list[sd->bl.m].npc[i]; - - // Make sure NPC exists and is not a warp - if(nd != NULL) - { - // Check if NPC has quest attached to it - if(nd->quest.quest_id > 0) - if(quest->check(sd, nd->quest.quest_id, HAVEQUEST) == -1) // Check if quest is not started - // Check if quest is job-specific, check is user is said job class. - if(nd->quest.hasJob == true) - { - if(sd->class_ == nd->quest.job) - clif->quest_show_event(sd, &nd->bl, nd->quest.icon, 0); - } - else { - clif->quest_show_event(sd, &nd->bl, nd->quest.icon, 0); - } +#if PACKETVER >= 20090218 + for(i = 0; i < map->list[sd->bl.m].qi_count; i++) { + struct questinfo *qi = &map->list[sd->bl.m].qi_data[i]; + if( quest->check(sd, qi->quest_id, HAVEQUEST) == -1 ) {// Check if quest is not started + if( qi->hasJob ) { // Check if quest is job-specific, check is user is said job class. + if( sd->class_ == qi->job ) + clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color); + } else { + clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color); } } - #endif + } +#endif } diff --git a/src/map/instance.c b/src/map/instance.c index 045be5431..83b538ffc 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -242,6 +242,13 @@ int instance_add_map(const char *name, int instance_id, bool usebasename, const } } + //Mimic questinfo + if( map->list[m].qi_count ) { + map->list[im].qi_count = map->list[m].qi_count; + CREATE( map->list[im].qi_data, struct questinfo, map->list[im].qi_count ); + memcpy( map->list[im].qi_data, map->list[m].qi_data, map->list[im].qi_count * sizeof(struct questinfo) ); + } + map->list[im].m = im; map->list[im].instance_id = instance_id; map->list[im].instance_src_map = m; @@ -443,6 +450,9 @@ void instance_del_map(int16 m) { aFree(map->list[m].zone_mf); } + if( map->list[m].qi_data ) + aFree(map->list[m].qi_data); + // Remove from instance for( i = 0; i < instance->list[map->list[m].instance_id].num_map; i++ ) { if( instance->list[map->list[m].instance_id].map[i] == m ) { diff --git a/src/map/map.c b/src/map/map.c index 749b9de81..412a266fc 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -3112,6 +3112,10 @@ void do_final_maps(void) { if( map->list[i].channel ) clif->chsys_delete(map->list[i].channel); + + if( map->list[i].qi_data ) + aFree(map->list[i].qi_data); + } map->zone_db_clear(); @@ -3177,6 +3181,12 @@ void map_flags_init(void) { map->list[i].misc_damage_rate = 100; map->list[i].short_damage_rate = 100; map->list[i].long_damage_rate = 100; + + if( map->list[i].qi_data ) + aFree(map->list[i].qi_data); + + map->list[i].qi_data = NULL; + map->list[i].qi_count = 0; } } @@ -4958,6 +4968,38 @@ int map_get_new_bonus_id (void) { return map->bonus_id++; } +void map_add_questinfo(int m, struct questinfo *qi) { + unsigned short i; + + /* duplicate, override */ + for(i = 0; i < map->list[m].qi_count; i++) { + if( map->list[m].qi_data[i].nd == qi->nd ) + break; + } + + if( i == map->list[m].qi_count ) + RECREATE(map->list[m].qi_data, struct questinfo, ++map->list[m].qi_count); + + memcpy(&map->list[m].qi_data[i], qi, sizeof(struct questinfo)); +} + +bool map_remove_questinfo(int m, struct npc_data *nd) { + unsigned short i; + + for(i = 0; i < map->list[m].qi_count; i++) { + struct questinfo *qi = &map->list[m].qi_data[i]; + if( qi->nd == nd ) { + memset(&map->list[m].qi_data[i], 0, sizeof(struct questinfo)); + if( i != --map->list[m].qi_count ) { + memmove(&map->list[m].qi_data[i],&map->list[m].qi_data[i+1],sizeof(struct questinfo)*(map->list[m].qi_count-i)); + } + return true; + } + } + + return false; +} + /** * @see DBApply */ @@ -5824,7 +5866,10 @@ void map_defaults(void) { map->delblcell = map_delblcell; map->get_new_bonus_id = map_get_new_bonus_id; - + + map->add_questinfo = map_add_questinfo; + map->remove_questinfo = map_remove_questinfo; + /** * mapit interface **/ diff --git a/src/map/map.h b/src/map/map.h index 83d5aa5a8..053d7ff2e 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -557,6 +557,17 @@ struct map_drop_list { int drop_per; }; + +struct questinfo { + struct npc_data *nd; + unsigned short icon; + unsigned char color; + int quest_id; + bool hasJob; + unsigned short job;/* perhaps a mapid mask would be most flexible? */ +}; + + struct map_data { char name[MAP_NAME_LENGTH]; uint16 index; // The map index used by the mapindex* functions. @@ -690,6 +701,10 @@ struct map_data { int (*getcellp)(struct map_data* m,int16 x,int16 y,cell_chk cellchk); void (*setcell) (int16 m, int16 x, int16 y, cell_t cell, bool flag); char *cellPos; + + /* ShowEvent Data Cache */ + struct questinfo *qi_data; + unsigned short qi_count; }; /// Stores information about a remote map (for multi-mapserver setups). @@ -1029,6 +1044,8 @@ struct map_interface { void (*addblcell) (struct block_list *bl); void (*delblcell) (struct block_list *bl); int (*get_new_bonus_id) (void); + void (*add_questinfo) (int m, struct questinfo *qi); + bool (*remove_questinfo) (int m, struct npc_data *nd); }; struct map_interface *map; diff --git a/src/map/npc.c b/src/map/npc.c index c536dc856..79e976bb3 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -1790,6 +1790,9 @@ int npc_unload(struct npc_data* nd, bool single) { aFree(nd->path);/* remove now that no other instances exist */ } } + + if( single && nd->bl.m != -1 ) + map->remove_questinfo(nd->bl.m,nd); if( (nd->subtype == SHOP || nd->subtype == CASHSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao] aFree(nd->u.shop.shop_item); diff --git a/src/map/npc.h b/src/map/npc.h index c9184b22d..f809cb19c 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -48,12 +48,6 @@ struct npc_data { char* path;/* path dir */ enum npc_subtype subtype; int src_id; - struct { - int icon; - int quest_id; - bool hasJob; - int job; - } quest; union { struct { struct script_code *script; diff --git a/src/map/script.c b/src/map/script.c index cf2ddd812..c1281bf59 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -15456,9 +15456,10 @@ BUILDIN(readbook) BUILDIN(questinfo) { struct npc_data *nd = map->id2nd(st->oid); - int quest, icon, job; - - if( nd == NULL ) + int quest, icon, job, color = 0; + struct questinfo qi; + + if( nd == NULL || nd->bl.m == -1 ) return true; quest = script_getnum(st, 2); @@ -15474,24 +15475,34 @@ BUILDIN(questinfo) icon = icon + 1; #endif - nd->quest.quest_id = quest; - nd->quest.icon = icon; - nd->quest.hasJob = false; + qi.quest_id = quest; + qi.icon = (unsigned char)icon; + qi.nd = nd; + + if( script_hasdata(st, 4) ) { + color = script_getnum(st, 4); + if( color < 0 || color > 3 ) { + ShowWarning("buildin_questinfo: invalid color '%d', changing to 0\n",color); + script->reportfunc(st); + color = 0; + } + qi.color = (unsigned char)color; + } + + qi.hasJob = false; - if(script_hasdata(st, 4)) - { - job = script_getnum(st, 4); + if(script_hasdata(st, 5)) { + job = script_getnum(st, 5); if (!pcdb_checkid(job)) - { - ShowError("questinfo: Nonexistant Job Class.\n"); - } - else - { - nd->quest.hasJob = true; - nd->quest.job = job; + ShowError("buildin_questinfo: Nonexistant Job Class.\n"); + else { + qi.hasJob = true; + qi.job = (unsigned short)job; } } + + map->add_questinfo(nd->bl.m,&qi); return true; } @@ -15499,21 +15510,24 @@ BUILDIN(questinfo) BUILDIN(setquest) { struct map_session_data *sd = script->rid2sd(st); - struct npc_data *nd = map->id2nd(st->oid); - nullpo_retr(false,sd); + unsigned short i; - if (!nd) + if (!sd) return false; quest->add(sd, script_getnum(st, 2)); // If questinfo is set, remove quest bubble once quest is set. - if(nd->quest.quest_id > 0) - #if PACKETVER >= 20120410 - clif->quest_show_event(sd, &nd->bl, 9999, 0); - #else - clif->quest_show_event(sd, &nd->bl, 0, 0); - #endif + for(i = 0; i < map->list[sd->bl.m].qi_count; i++) { + struct questinfo *qi = &map->list[sd->bl.m].qi_data[i]; + if( qi->quest_id == script_getnum(st, 2) ) { +#if PACKETVER >= 20120410 + clif->quest_show_event(sd, &qi->nd->bl, 9999, 0); +#else + clif->quest_show_event(sd, &qi->nd->bl, 0, 0); +#endif + } + } return true; } @@ -15563,12 +15577,20 @@ BUILDIN(checkquest) BUILDIN(showevent) { TBL_PC *sd = script->rid2sd(st); struct npc_data *nd = map->id2nd(st->oid); - int icon; + int icon, color = 0; if( sd == NULL || nd == NULL ) return true; icon = script_getnum(st, 2); + if( script_hasdata(st, 3) ) { + color = script_getnum(st, 3); + if( color < 0 || color > 3 ) { + ShowWarning("buildin_showevent: invalid color '%d', changing to 0\n",color); + script->reportfunc(st); + color = 0; + } + } #if PACKETVER >= 20120410 if(icon < 0 || (icon > 8 && icon != 9999) || icon == 7) @@ -15580,7 +15602,7 @@ BUILDIN(showevent) { icon = icon + 1; #endif - clif->quest_show_event(sd, &nd->bl, icon, 0); + clif->quest_show_event(sd, &nd->bl, icon, color); return true; } @@ -18086,13 +18108,13 @@ void script_parse_builtin(void) { BUILDIN_DEF(useatcmd, "s"), //Quest Log System [Inkfish] - BUILDIN_DEF(questinfo, "ii?"), + BUILDIN_DEF(questinfo, "ii??"), BUILDIN_DEF(setquest, "i"), BUILDIN_DEF(erasequest, "i"), BUILDIN_DEF(completequest, "i"), BUILDIN_DEF(checkquest, "i?"), BUILDIN_DEF(changequest, "ii"), - BUILDIN_DEF(showevent, "i"), + BUILDIN_DEF(showevent, "i?"), /** * hQueue [Ind/Hercules] -- cgit v1.2.3-70-g09d2