diff options
-rw-r--r-- | Changelog-Trunk.txt | 5 | ||||
-rw-r--r-- | doc/script_commands.txt | 3 | ||||
-rw-r--r-- | src/map/npc.c | 174 | ||||
-rw-r--r-- | src/map/npc.h | 4 | ||||
-rw-r--r-- | src/map/pc.h | 8 | ||||
-rw-r--r-- | src/map/skill.c | 12 | ||||
-rw-r--r-- | src/map/status.c | 5 | ||||
-rw-r--r-- | src/map/unit.c | 12 |
8 files changed, 91 insertions, 132 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index c443ea05b..426fe6bb6 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -5,6 +5,11 @@ IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. 2009/11/26 * Moved log_sql_init() call up in map-server-init to after after map_sql_init() call to prevent unnecessary processing before a potential quit. [Paradox924X] + * NPC event code cleanups. [Inkfish] + - removed the 'OnMyMobDead' dead code. It's never supported though documented. + - removed the 'feature' that events only trigger when the player is in the OnTouch area IF it's specified. + It's never documented and breaks official scripts. + - some cleanups and bug fixes to OnTouch_. 2009/11/25 * Fixed strnpcinfo(1) returning blank strings when NPC names did not have a hidden portion of the display name. (bugreport:3758) [Paradox924X] 2009/11/23 diff --git a/doc/script_commands.txt b/doc/script_commands.txt index c6b892311..57b777096 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -4832,9 +4832,6 @@ attached at this execution will be the RID of the killing character. monster "place",60,100,"Poring",1002,1,"NPCNAME::OnLabel"; -If you do not specify any event label, a label in the NPC object that ran this -command, called 'OnMyMobDead:' will execute anyway, if present. - The coordinates of 0,0 will spawn the monster on a random place on the map. The 'areamonster' command works much like the 'monster' command and is not diff --git a/src/map/npc.c b/src/map/npc.c index 6a3af6d40..8164054de 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -102,6 +102,29 @@ struct view_data* npc_get_viewdata(int class_) return &npc_viewdb[class_]; return NULL; } + +int npc_ontouch_event(struct map_session_data *sd, struct npc_data *nd) +{ + char name[NAME_LENGTH*2+3]; + + if( nd->touching_id || pc_ishiding(sd) ) + return 0; + + snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch_name); + return npc_event(sd,name,1); +} + +int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd) +{ + char name[NAME_LENGTH*2+3]; + + if( sd->areanpc_id == nd->bl.id ) + return 0; + + snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch2_name); + return npc_event(sd,name,2); +} + /*========================================== * NPCの無効化/有効化 * npc_enable @@ -116,22 +139,16 @@ int npc_enable_sub(struct block_list *bl, va_list ap) nullpo_retr(0, nd=va_arg(ap,struct npc_data *)); if(bl->type == BL_PC && (sd=(struct map_session_data *)bl)) { - char name[NAME_LENGTH*2+3]; + TBL_PC *sd = (TBL_PC*)bl; if (nd->sc.option&OPTION_INVISIBLE) return 1; - if(sd->areanpc_id==nd->bl.id) - return 1; - sd->areanpc_id=nd->bl.id; - - snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch_name); - if( npc_event(sd,name,0) > 0 ) - { - snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch2_name); // exname to be specific. exname is the unique identifier for script events. [Lance] - npc_event(sd,name,0); + if( npc_ontouch_event(sd,nd) > 0 && npc_ontouch2_event(sd,nd) > 0 ) + { // failed to run OnTouch event, so just click the npc + pc_stop_walking(sd,1); + npc_click(sd,nd); } - } return 0; } @@ -699,10 +716,12 @@ int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char int i; ARR_FIND( 0, MAX_EVENTQUEUE, i, sd->eventqueue[i][0] == '\0' ); if( i < MAX_EVENTQUEUE ) + { safestrncpy(sd->eventqueue[i],eventname,50); //Event enqueued. - else - ShowWarning("npc_event: player's event queue is full, can't add event '%s' !\n", eventname); - + return 0; + } + + ShowWarning("npc_event: player's event queue is full, can't add event '%s' !\n", eventname); return 1; } if( ev->nd->sc.option&OPTION_INVISIBLE ) @@ -718,80 +737,29 @@ int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char /*========================================== * イベント型のNPC処理 *------------------------------------------*/ -int npc_event(struct map_session_data* sd, const char* eventname, int mob_kill) +int npc_event(struct map_session_data* sd, const char* eventname, int ontouch) { struct event_data* ev = (struct event_data*)strdb_get(ev_db, eventname); struct npc_data *nd; - int xs,ys; - bool ontouch = false; - char mobevent[100]; - char name[NAME_LENGTH*2+3]; - if( sd == NULL ) - { - nullpo_info(NLP_MARK); - return 0; - } - - snprintf(name, ARRAYLENGTH(name), "::%s", script_config.ontouch_name); - if( eventname && strcmp(((eventname)+strlen(eventname)-strlen(script_config.ontouch_name)-2),name) == 0 ) - { - if( ev == NULL || !ev->nd ) - return 1; - if( pc_ishiding(sd) ) - return 0; - if( ev->nd->touching_id ) - return 0; - ontouch = true; - } - else - { - snprintf(name, ARRAYLENGTH(name), "::%s", script_config.ontouch2_name); - if( ev == NULL && eventname && strcmp(((eventname)+strlen(eventname)-strlen(script_config.ontouch2_name)-2),name) == 0 ) - return 1; - } + nullpo_retr(0,sd); if( ev == NULL || (nd = ev->nd) == NULL ) { - if (mob_kill) - { - strcpy(mobevent, eventname); - strcat(mobevent, "::OnMyMobDead"); - ev = (struct event_data*)strdb_get(ev_db, mobevent); - if( ev == NULL || (nd = ev->nd) == NULL ) - { - ShowError("npc_event: (mob_kill) event not found [%s]\n", mobevent); - return 0; - } - } - else - { + if( !ontouch ) ShowError("npc_event: event not found [%s]\n", eventname); - return 0; - } + return ontouch; } - xs=nd->u.scr.xs; - ys=nd->u.scr.ys; - if( xs >= 0 && ys >= 0 && strcmp(((eventname)+strlen(eventname)-6),"Global") != 0 ) - { - if( nd->bl.m >= 0 ) - {// Non-invisible npc - if( nd->bl.m != sd->bl.m ) - return 1; - if( sd->bl.x < nd->bl.x-xs || sd->bl.x > nd->bl.x+xs ) - return 1; - if( sd->bl.y < nd->bl.y-ys || sd->bl.y > nd->bl.y+ys ) - return 1; - } - } - - if( ontouch ) + switch(ontouch) { + case 1: nd->touching_id = sd->bl.id; - sd->ontouch.npc_id = nd->bl.id; - sd->ontouch.x = xs; - sd->ontouch.y = ys; + sd->touching_id = nd->bl.id; + break; + case 2: + sd->areanpc_id = nd->bl.id; + break; } return npc_event_sub(sd,ev,eventname); @@ -815,28 +783,30 @@ int npc_touch_areanpc_sub(struct block_list *bl, va_list ap) if( pc_id == sd->bl.id ) return 0; - sd->areanpc_id = npc_id; - npc_event(sd,name,0); + npc_event(sd,name,1); return 1; } -int npc_touchnext_areanpc(struct map_session_data* sd, bool logout) +int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap) { - struct npc_data *nd = map_id2nd(sd->ontouch.npc_id); - short xs = sd->ontouch.x ,ys = sd->ontouch.y; + struct npc_data *nd = map_id2nd(sd->touching_id); + short xs, ys; if( !nd || nd->touching_id != sd->bl.id ) return 1; + xs = nd->u.scr.xs; + ys = nd->u.scr.ys; + if( sd->bl.m != nd->bl.m || sd->bl.x < nd->bl.x - xs || sd->bl.x > nd->bl.x + xs || sd->bl.y < nd->bl.y - ys || sd->bl.y > nd->bl.y + ys || - pc_ishiding(sd) || logout ) + pc_ishiding(sd) || leavemap ) { char name[NAME_LENGTH*2+3]; - memset(&sd->ontouch,0,sizeof(sd->ontouch)); - nd->touching_id = 0; + + nd->touching_id = sd->touching_id = 0; snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch_name); map_forcountinarea(npc_touch_areanpc_sub,nd->bl.m,nd->bl.m - xs,nd->bl.y - ys,nd->bl.x + xs,nd->bl.y + ys,1,BL_PC,sd->bl.id,nd->bl.id,name); } @@ -854,8 +824,9 @@ int npc_touch_areanpc(struct map_session_data* sd, int m, int x, int y) nullpo_retr(1, sd); - if(sd->npc_id) - return 1; + // Why not enqueue it? [Inkfish] + //if(sd->npc_id) + // return 1; for(i=0;i<map[m].npc_num;i++) { @@ -893,31 +864,18 @@ int npc_touch_areanpc(struct map_session_data* sd, int m, int x, int y) pc_setpos(sd,map[m].npc[i]->u.warp.mapindex,map[m].npc[i]->u.warp.x,map[m].npc[i]->u.warp.y,0); break; case SCRIPT: - { - char name[NAME_LENGTH*2+3]; - - if(sd->areanpc_id == map[m].npc[i]->bl.id) - return 1; - sd->areanpc_id = map[m].npc[i]->bl.id; - - snprintf(name, ARRAYLENGTH(name), "%s::%s", map[m].npc[i]->exname, script_config.ontouch_name); - if( npc_event(sd,name,0) > 0 ) - { - snprintf(name, ARRAYLENGTH(name), "%s::%s", map[m].npc[i]->exname, script_config.ontouch2_name); // It goes here too. exname being the unique identifier. [Lance] - if( npc_event(sd,name,0) > 0 ) - {// failed to run OnTouch event, so just click the npc - struct unit_data *ud = unit_bl2ud(&sd->bl); - if( ud && ud->walkpath.path_pos < ud->walkpath.path_len ) - { // Since walktimer always == -1 at this time, we stop walking manually. [Inkfish] - clif_fixpos(&sd->bl); - ud->walkpath.path_pos = ud->walkpath.path_len; - } - npc_click(sd,map[m].npc[i]); + if( npc_ontouch_event(sd,map[m].npc[i]) > 0 && npc_ontouch2_event(sd,map[m].npc[i]) > 0 ) + { // failed to run OnTouch event, so just click the npc + struct unit_data *ud = unit_bl2ud(&sd->bl); + if( ud && ud->walkpath.path_pos < ud->walkpath.path_len ) + { // Since walktimer always == -1 at this time, we stop walking manually. [Inkfish] + clif_fixpos(&sd->bl); + ud->walkpath.path_pos = ud->walkpath.path_len; } + sd->areanpc_id = map[m].npc[i]->bl.id; + npc_click(sd,map[m].npc[i]); } - break; - } } return 0; } diff --git a/src/map/npc.h b/src/map/npc.h index 5bbb29fa4..6f705a09c 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -98,11 +98,11 @@ enum npce_event { struct view_data* npc_get_viewdata(int class_); int npc_chat_sub(struct block_list* bl, va_list ap); int npc_event_dequeue(struct map_session_data* sd); -int npc_event(struct map_session_data* sd, const char* eventname, int mob_kill); +int npc_event(struct map_session_data* sd, const char* eventname, int ontouch); int npc_touch_areanpc(struct map_session_data* sd, int m, int x, int y); int npc_touch_areanpc2(struct mob_data *md); // [Skotlex] int npc_check_areanpc(int flag, int m, int x, int y, int range); -int npc_touchnext_areanpc(struct map_session_data* sd,bool logout); +int npc_touchnext_areanpc(struct map_session_data* sd,bool leavemap); int npc_click(struct map_session_data* sd, struct npc_data* nd); int npc_scriptcont(struct map_session_data* sd, int id); struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* bl); diff --git a/src/map/pc.h b/src/map/pc.h index 19db45465..ab26721fd 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -161,11 +161,7 @@ struct map_session_data { unsigned short mapindex; unsigned char head_dir; //0: Look forward. 1: Look right, 2: Look left. unsigned int client_tick; - int npc_id,areanpc_id,npc_shopid; - struct { - int npc_id; - short x,y; - } ontouch; + int npc_id,areanpc_id,npc_shopid,touching_id; int npc_item_flag; //Marks the npc_id with which you can use items during interactions with said npc (see script command enable_itemuse) int npc_menu; // internal variable, used in npc menu handling int npc_amount; @@ -358,7 +354,7 @@ struct map_session_data { unsigned short pvp_rank, pvp_lastusers; unsigned short pvp_won, pvp_lost; - char eventqueue[MAX_EVENTQUEUE][50]; + char eventqueue[MAX_EVENTQUEUE][NAME_LENGTH*2+3]; int eventtimer[MAX_EVENTTIMER]; unsigned short eventcount; // [celest] diff --git a/src/map/skill.c b/src/map/skill.c index 8d0b1cda9..e4fad5ff8 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1541,11 +1541,13 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in if( target->type == BL_PC ) { - if( map_getcell(target->m, target->x, target->y, CELL_CHKNPC) ) - npc_touch_areanpc((TBL_PC*)target, target->m, target->x, target->y); //Invoke area NPC - - if( ((TBL_PC*)target)->ontouch.npc_id ) - npc_touchnext_areanpc(((TBL_PC*)target),false); + TBL_PC *sd = (TBL_PC*)target; + if( sd->touching_id ) + npc_touchnext_areanpc(sd,false); + if( map_getcell(target->m,target->x,target->y,CELL_CHKNPC) ) + npc_touch_areanpc(sd,target->m,target->x,target->y); + else + sd->areanpc_id=0; } return count; //Return amount of knocked back cells. diff --git a/src/map/status.c b/src/map/status.c index 9b3482d83..479e77fd0 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -6093,12 +6093,15 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val //OPTION case SC_HIDING: sc->option |= OPTION_HIDE; + opt_flag = 2; break; case SC_CLOAKING: sc->option |= OPTION_CLOAK; + opt_flag = 2; break; case SC_CHASEWALK: sc->option |= OPTION_CHASEWALK|OPTION_CLOAK; + opt_flag = 2; break; case SC_SIGHT: sc->option |= OPTION_SIGHT; @@ -6198,7 +6201,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; } - if( sd && sd->ontouch.npc_id ) + if( opt_flag&2 && sd && sd->touching_id ) npc_touchnext_areanpc(sd,false); return 1; diff --git a/src/map/unit.c b/src/map/unit.c index d828832c6..f739159fb 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -165,6 +165,8 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data) ud->walktimer = INVALID_TIMER; if(sd) { + if( sd->touching_id ) + npc_touchnext_areanpc(sd,false); if(map_getcell(bl->m,x,y,CELL_CHKNPC)) { npc_touch_areanpc(sd,bl->m,x,y); if (bl->prev == NULL) //Script could have warped char, abort remaining of the function. @@ -172,9 +174,6 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data) } else sd->areanpc_id=0; - if( sd->ontouch.npc_id ) - npc_touchnext_areanpc(sd,false); - if (sd->state.gmaster_flag && (battle_config.guild_aura&((agit_flag || agit2_flag)?2:1)) && (battle_config.guild_aura&(map_flag_gvg2(bl->m)?8:4)) @@ -518,6 +517,8 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool ud->walktimer = INVALID_TIMER; if(sd) { + if( sd->touching_id ) + npc_touchnext_areanpc(sd,false); if(map_getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) { npc_touch_areanpc(sd,bl->m,bl->x,bl->y); if (bl->prev == NULL) //Script could have warped char, abort remaining of the function. @@ -525,9 +526,6 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool } else sd->areanpc_id=0; - if( sd->ontouch.npc_id ) - npc_touchnext_areanpc(sd,false); - if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 ) { // Check if pet needs to be teleported. [Skotlex] int flag = 0; @@ -1816,7 +1814,7 @@ int unit_remove_map_(struct block_list *bl, int clrtype, const char* file, int l guild_reply_reqalliance(sd,sd->guild_alliance_account,0); if(sd->menuskill_id) sd->menuskill_id = sd->menuskill_val = 0; - if( sd->ontouch.npc_id ) + if( sd->touching_id ) npc_touchnext_areanpc(sd,true); sd->npc_shopid = 0; |