Переглянути джерело

* NPC event code cleanups.
- 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_.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@14173 54d463be-8e91-2dee-dedb-b68131a5f0ec

Inkfish 15 роки тому
батько
коміт
5485daa6df
8 змінених файлів з 91 додано та 132 видалено
  1. 5 0
      Changelog-Trunk.txt
  2. 0 3
      doc/script_commands.txt
  3. 66 108
      src/map/npc.c
  4. 2 2
      src/map/npc.h
  5. 2 6
      src/map/pc.h
  6. 7 5
      src/map/skill.c
  7. 4 1
      src/map/status.c
  8. 5 7
      src/map/unit.c

+ 5 - 0
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

+ 0 - 3
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 

+ 66 - 108
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;
 }

+ 2 - 2
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);

+ 2 - 6
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]
 

+ 7 - 5
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.

+ 4 - 1
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;

+ 5 - 7
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;