Fixed quest information icons not displaying properly on NPC. (bugreport:8156, bugreport:8157) (Hercules 1ab0017)
This commit is contained in:
parent
0239b612f4
commit
5e02af25af
10
db/const.txt
10
db/const.txt
@ -4515,6 +4515,16 @@ HAVEQUEST 0
|
||||
PLAYTIME 1
|
||||
HUNTING 2
|
||||
|
||||
QTYPE_NONE 0x270f
|
||||
QTYPE_QUEST 0x00
|
||||
QTYPE_QUEST2 0x01
|
||||
QTYPE_JOB 0x02
|
||||
QTYPE_JOB2 0x03
|
||||
QTYPE_EVENT 0x04
|
||||
QTYPE_EVENT2 0x05
|
||||
QTYPE_WARG 0x06
|
||||
QTYPE_WARG2 0x08
|
||||
|
||||
FW_DONTCARE 0
|
||||
FW_THIN 100
|
||||
FW_EXTRALIGHT 200
|
||||
|
@ -7633,10 +7633,56 @@ if (instance_check_party(getcharid(1),2,2,149)) {
|
||||
=========================
|
||||
---------------------------------------
|
||||
|
||||
*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
|
||||
checked if it has been started yet.
|
||||
|
||||
For Icon, use one of the following:
|
||||
|
||||
No Icon : QTYPE_NONE
|
||||
! Quest Icon : QTYPE_QUEST
|
||||
? Quest Icon : QTYPE_QUEST2
|
||||
! Job Icon : QTYPE_JOB
|
||||
? Job Icon : QTYPE_JOB2
|
||||
! Event Icon : QTYPE_EVENT
|
||||
? Event Icon : QTYPE_EVENT2
|
||||
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.
|
||||
|
||||
Optionally, you can also specify a Job Class if the quest bubble should only appear for a certain class.
|
||||
|
||||
Example
|
||||
izlude,100,100,4 script Test 844,{
|
||||
mes "[Test]";
|
||||
mes "Hello World.";
|
||||
close;
|
||||
|
||||
OnInit:
|
||||
questinfo 1001, QTYPE_QUEST, 0, Job_Novice;
|
||||
end;
|
||||
}
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*setquest <ID>;
|
||||
|
||||
Place quest of <ID> in the users quest log, the state of which is "active".
|
||||
|
||||
If *questinfo is set, and the same ID is specified here, the icon will be cleared when the quest is set.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*completequest <ID>;
|
||||
@ -7689,23 +7735,30 @@ Return the state of the quest:
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*showevent <state>, <color>;
|
||||
*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 certain players.
|
||||
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.
|
||||
|
||||
state can be:
|
||||
0 = disable (Used to disable and remove the mark and the emotion from the NPC.)
|
||||
1 = exclamation emotion (Used to show an important quest event to certain player.)
|
||||
2 = interrogation emotion (Used to show an non-important quest event to certain player.)
|
||||
Other values may cause client crashes.
|
||||
Available Icons:
|
||||
|
||||
color can be:
|
||||
0 = yellow "Quest"
|
||||
1 = orange "Job"
|
||||
2 = green "Event"
|
||||
3 = an MVP flag
|
||||
Other values show a transparent mark in the mini-map.
|
||||
Remove Icon : QTYPE_NONE
|
||||
! Quest Icon : QTYPE_QUEST
|
||||
? Quest Icon : QTYPE_QUEST2
|
||||
! Job Icon : QTYPE_JOB
|
||||
? Job Icon : QTYPE_JOB2
|
||||
! Event Icon : QTYPE_EVENT
|
||||
? Event Icon : QTYPE_EVENT2
|
||||
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
|
||||
|
||||
---------------------------------------
|
||||
|
||||
|
@ -9450,6 +9450,8 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd)
|
||||
/// 007d
|
||||
void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(sd->bl.prev != NULL)
|
||||
return;
|
||||
|
||||
@ -9775,9 +9777,24 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
|
||||
clif_changed_dir(&sd->bl, SELF);
|
||||
}
|
||||
|
||||
// Trigger skill effects if you appear standing on them
|
||||
// Trigger skill effects if you appear standing on them
|
||||
if(!battle_config.pc_invincible_time)
|
||||
skill_unit_move(&sd->bl,gettick(),1);
|
||||
|
||||
// NPC Quest / Event Icon Check [Kisuka]
|
||||
#if PACKETVER >= 20090218
|
||||
for(i = 0; i < map[sd->bl.m].qi_count; i++) {
|
||||
struct questinfo *qi = &map[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
|
||||
}
|
||||
|
||||
|
||||
|
@ -2260,6 +2260,13 @@ int map_addinstancemap(const char *name, int id)
|
||||
snprintf(map[dst_m].name, sizeof(map[dst_m].name),"%.3d%s", id, iname);
|
||||
map[dst_m].name[MAP_NAME_LENGTH-1] = '\0';
|
||||
|
||||
// Mimic questinfo
|
||||
if( map[src_m].qi_count ) {
|
||||
map[dst_m].qi_count = map[src_m].qi_count;
|
||||
CREATE( map[dst_m].qi_data, struct questinfo, map[dst_m].qi_count );
|
||||
memcpy( map[dst_m].qi_data, map[src_m].qi_data, map[dst_m].qi_count * sizeof(struct questinfo) );
|
||||
}
|
||||
|
||||
map[dst_m].m = dst_m;
|
||||
map[dst_m].instance_id = id;
|
||||
map[dst_m].users = 0;
|
||||
@ -2356,6 +2363,9 @@ int map_delinstancemap(int m)
|
||||
map_removemapdb(&map[m]);
|
||||
memset(&map[m], 0x00, sizeof(map[0]));
|
||||
|
||||
if( map[m].qi_data )
|
||||
aFree(map[m].qi_data);
|
||||
|
||||
// Make delete timers invalid to avoid errors
|
||||
map[m].mob_delete_timer = INVALID_TIMER;
|
||||
|
||||
@ -3102,6 +3112,12 @@ void map_flags_init(void)
|
||||
// adjustments
|
||||
if( battle_config.pk_mode )
|
||||
map[i].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris]
|
||||
|
||||
if( map[i].qi_data )
|
||||
aFree(map[i].qi_data);
|
||||
|
||||
map[i].qi_data = NULL;
|
||||
map[i].qi_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3678,6 +3694,37 @@ int log_sql_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void map_add_questinfo(int m, struct questinfo *qi) {
|
||||
unsigned short i;
|
||||
|
||||
/* duplicate, override */
|
||||
for(i = 0; i < map[m].qi_count; i++) {
|
||||
if( map[m].qi_data[i].nd == qi->nd )
|
||||
break;
|
||||
}
|
||||
|
||||
if( i == map[m].qi_count )
|
||||
RECREATE(map[m].qi_data, struct questinfo, ++map[m].qi_count);
|
||||
|
||||
memcpy(&map[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[m].qi_count; i++) {
|
||||
struct questinfo *qi = &map[m].qi_data[i];
|
||||
if( qi->nd == nd ) {
|
||||
memset(&map[m].qi_data[i], 0, sizeof(struct questinfo));
|
||||
if( i != --map[m].qi_count )
|
||||
memmove(&map[m].qi_data[i],&map[m].qi_data[i+1],sizeof(struct questinfo)*(map[m].qi_count-i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DBApply
|
||||
*/
|
||||
@ -3813,6 +3860,7 @@ void do_final(void)
|
||||
if(map[i].cell) aFree(map[i].cell);
|
||||
if(map[i].block) aFree(map[i].block);
|
||||
if(map[i].block_mob) aFree(map[i].block_mob);
|
||||
if(map[i].qi_data) aFree(map[i].qi_data);
|
||||
if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random]
|
||||
if(map[i].mob_delete_timer != INVALID_TIMER)
|
||||
delete_timer(map[i].mob_delete_timer, map_removemobs_timer);
|
||||
|
@ -580,6 +580,15 @@ struct s_skill_damage {
|
||||
#define MAX_MAP_SKILL_MODIFIER 5
|
||||
#endif
|
||||
|
||||
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.
|
||||
@ -688,6 +697,10 @@ struct map_data {
|
||||
|
||||
/* rAthena Local Chat */
|
||||
struct Channel *channel;
|
||||
|
||||
/* ShowEvent Data Cache */
|
||||
struct questinfo *qi_data;
|
||||
unsigned short qi_count;
|
||||
|
||||
/* speeds up clif_updatestatus processing by causing hpmeter to run only when someone with the permission can view it */
|
||||
unsigned short hpmeter_visible;
|
||||
@ -806,6 +819,9 @@ struct mob_data * map_id2boss(int id);
|
||||
// reload config file looking only for npcs
|
||||
void map_reloadnpc(bool clear);
|
||||
|
||||
void map_add_questinfo(int m, struct questinfo *qi);
|
||||
bool map_remove_questinfo(int m, struct npc_data *nd);
|
||||
|
||||
/// Bitfield of flags for the iterator.
|
||||
enum e_mapitflags
|
||||
{
|
||||
|
@ -1945,6 +1945,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->subtype == ITEMSHOP || nd->subtype == POINTSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao]
|
||||
aFree(nd->u.shop.shop_item);
|
||||
|
104
src/map/script.c
104
src/map/script.c
@ -16545,12 +16545,82 @@ BUILDIN_FUNC(readbook)
|
||||
Questlog script commands
|
||||
*******************/
|
||||
|
||||
BUILDIN_FUNC(questinfo)
|
||||
{
|
||||
TBL_NPC* nd = map_id2nd(st->oid);
|
||||
int quest_id, icon, job, color = 0;
|
||||
struct questinfo qi;
|
||||
|
||||
if( nd == NULL || nd->bl.m == -1 )
|
||||
return true;
|
||||
|
||||
quest_id = script_getnum(st, 2);
|
||||
icon = script_getnum(st, 3);
|
||||
|
||||
#if PACKETVER >= 20120410
|
||||
if(icon < 0 || (icon > 8 && icon != 9999) || icon == 7)
|
||||
icon = 9999; // Default to nothing if icon id is invalid.
|
||||
#else
|
||||
if(icon < 0 || icon > 7)
|
||||
icon = 0;
|
||||
else
|
||||
icon = icon + 1;
|
||||
#endif
|
||||
|
||||
qi.quest_id = quest_id;
|
||||
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, 5)) {
|
||||
job = script_getnum(st, 5);
|
||||
|
||||
if (!pcdb_checkid(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;
|
||||
}
|
||||
|
||||
BUILDIN_FUNC(setquest)
|
||||
{
|
||||
struct map_session_data *sd = script_rid2sd(st);
|
||||
nullpo_ret(sd);
|
||||
int i, quest_id;
|
||||
|
||||
quest_add(sd, script_getnum(st, 2));
|
||||
nullpo_ret(sd);
|
||||
|
||||
quest_id = script_getnum(st, 2);
|
||||
|
||||
quest_add(sd, quest_id);
|
||||
|
||||
// If questinfo is set, remove quest bubble once quest is set.
|
||||
for(i = 0; i < map[sd->bl.m].qi_count; i++) {
|
||||
struct questinfo *qi = &map[sd->bl.m].qi_data[i];
|
||||
if( qi->quest_id == quest_id ) {
|
||||
#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 SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -16613,17 +16683,32 @@ BUILDIN_FUNC(showevent)
|
||||
{
|
||||
TBL_PC *sd = script_rid2sd(st);
|
||||
struct npc_data *nd = map_id2nd(st->oid);
|
||||
int state, color;
|
||||
int icon, color = 0;
|
||||
|
||||
if( sd == NULL || nd == NULL )
|
||||
return 0;
|
||||
state = script_getnum(st, 2);
|
||||
color = script_getnum(st, 3);
|
||||
|
||||
if( color < 0 || color > 3 )
|
||||
color = 0; // set default color
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
clif_quest_show_event(sd, &nd->bl, state, color);
|
||||
#if PACKETVER >= 20120410
|
||||
if(icon < 0 || (icon > 8 && icon != 9999) || icon == 7)
|
||||
icon = 9999; // Default to nothing if icon id is invalid.
|
||||
#else
|
||||
if(icon < 0 || icon > 7)
|
||||
icon = 0;
|
||||
else
|
||||
icon = icon + 1;
|
||||
#endif
|
||||
|
||||
clif_quest_show_event(sd, &nd->bl, icon, color);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -19150,13 +19235,14 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(useatcmd, "s"),
|
||||
|
||||
//Quest Log System [Inkfish]
|
||||
BUILDIN_DEF(questinfo, "ii??"),
|
||||
BUILDIN_DEF(setquest, "i"),
|
||||
BUILDIN_DEF(erasequest, "i"),
|
||||
BUILDIN_DEF(completequest, "i"),
|
||||
BUILDIN_DEF(checkquest, "i?"),
|
||||
BUILDIN_DEF(isbegin_quest,"i"),
|
||||
BUILDIN_DEF(changequest, "ii"),
|
||||
BUILDIN_DEF(showevent, "ii"),
|
||||
BUILDIN_DEF(showevent, "i?"),
|
||||
|
||||
//Bound items [Xantara] & [Akinari]
|
||||
BUILDIN_DEF2(getitem,"getitembound","vii?"),
|
||||
|
Loading…
x
Reference in New Issue
Block a user