summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2013-10-25 09:32:22 -0200
committershennetsind <ind@henn.et>2013-10-25 09:32:22 -0200
commitbf27a9e0cf1bfe9be298c4191010ba6876457d64 (patch)
tree5a7e85a639423109b6e8cf935f2f4c8ddf1bb595
parent94b7b25456aa8a9de1e0f2a147d58dba6e5976dd (diff)
downloadhercules-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.txt25
-rw-r--r--src/map/clif.c31
-rw-r--r--src/map/instance.c10
-rw-r--r--src/map/map.c47
-rw-r--r--src/map/map.h17
-rw-r--r--src/map/npc.c3
-rw-r--r--src/map/npc.h6
-rw-r--r--src/map/script.c80
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]