diff options
author | shennetsind <ind@henn.et> | 2013-10-25 09:32:22 -0200 |
---|---|---|
committer | shennetsind <ind@henn.et> | 2013-10-25 09:32:22 -0200 |
commit | bf27a9e0cf1bfe9be298c4191010ba6876457d64 (patch) | |
tree | 5a7e85a639423109b6e8cf935f2f4c8ddf1bb595 | |
parent | 94b7b25456aa8a9de1e0f2a147d58dba6e5976dd (diff) | |
download | hercules-bf27a9e0cf1bfe9be298c4191010ba6876457d64.tar.gz hercules-bf27a9e0cf1bfe9be298c4191010ba6876457d64.tar.bz2 hercules-bf27a9e0cf1bfe9be298c4191010ba6876457d64.tar.xz hercules-bf27a9e0cf1bfe9be298c4191010ba6876457d64.zip |
Quest Bubbles Update
- Introduced questinfo cache, memory & processing speed improvement
- Fixed mini-map marker support
Special Thanks to Haruna
Signed-off-by: shennetsind <ind@henn.et>
-rw-r--r-- | doc/script_commands.txt | 25 | ||||
-rw-r--r-- | src/map/clif.c | 31 | ||||
-rw-r--r-- | src/map/instance.c | 10 | ||||
-rw-r--r-- | src/map/map.c | 47 | ||||
-rw-r--r-- | src/map/map.h | 17 | ||||
-rw-r--r-- | src/map/npc.c | 3 | ||||
-rw-r--r-- | src/map/npc.h | 6 | ||||
-rw-r--r-- | src/map/script.c | 80 |
8 files changed, 158 insertions, 61 deletions
diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 751db221a..bd0b032f1 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -7886,7 +7886,7 @@ that fails, the command returns an empty string instead. ========================= --------------------------------------- -*questinfo <Quest ID>, <Icon>{, <Job Class>}; +*questinfo <Quest ID>, <Icon> {, <Map Mark Color>{, <Job Class>}}; This is esentially a combination of checkquest and showevent. Use this only in an OnInit label. For the Quest ID, specify the quest ID that you want @@ -7904,6 +7904,14 @@ No Icon : QTYPE_NONE Warg : QTYPE_WARG Warg Face : QTYPE_WARG2 (Only for packetver >= 20120410) +Map Mark Color, when used, creates a mark in the user's mini map on the position of the NPC, +the available color values are: + +0 - No Marker +1 - Yellow Marker +2 - Green Marker +3 - Purple Marker + When a user shows up on a map, each NPC is checked for questinfo that has been set. If questinfo is present, it will check if the quest has been started, if it has not, the bubble will appear. @@ -7916,7 +7924,7 @@ izlude,100,100,4 script Test 844,{ close; OnInit: - questinfo 1001, QTYPE_QUEST, Job_Novice; + questinfo 1001, QTYPE_QUEST, 0, Job_Novice; end; } @@ -7975,10 +7983,11 @@ If parameter "HUNTING" is supplied: --------------------------------------- -*showevent <icon>; +*showevent <icon>{,<mark color>} -Show a colored mark in the mini-map like "viewpoint" and an emotion on top -of a NPC. This is used to indicate that a NPC has a quest or an event to +Show an emotion on top of a NPC, and optionally, +a colored mark in the mini-map like "viewpoint". +This is used to indicate that a NPC has a quest or an event to a certain player. Available Icons: @@ -7993,6 +8002,12 @@ Remove Icon : QTYPE_NONE Warg : QTYPE_WARG Warg Face : QTYPE_WARG2 (Only for packetver >= 20120410) +Mark Color: +0 - No Mark +1 - Yellow Mark +2 - Green Mark +3 - Purple Mark + ---------------------------------------- ============================ 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] |