瀏覽代碼

- Now when a player logs out while it's running an attached npctimer, OnTimerQuit of that npc will be invoked.
- Updated scripts_command to add info on OnTimerQuit
- Corrected the double login check in pc_authok


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

skotlex 18 年之前
父節點
當前提交
8c52b6b21d
共有 3 個文件被更改,包括 47 次插入13 次删除
  1. 6 0
      doc/script_commands.txt
  2. 39 3
      src/map/npc.c
  3. 2 10
      src/map/pc.c

+ 6 - 0
doc/script_commands.txt

@@ -65,6 +65,8 @@
 //=       initnpctimer [Skotlex]
 //= 3.03.20070226
 //=       Updated makeitem and how to include " in strings [Lupus]
+//= 3.03.20070228
+//=       Added info on OnTimerQuit label to npctimer section. [Skotlex]
 //===== Compatible With ===================================
 //= LOL, can be used by anyone hopefully
 //===== Description =======================================
@@ -4872,6 +4874,10 @@ The other method to attach/detach a RID is through the script commands
 character the target for all character-referencing commands and functions,
 not to mention variables.
 
+If the player that is attached to the npctimer logs out, the "OnTimerQuit:"
+event label of that npc will be triggered, so you can do the appropiate
+cleanup (the player is still attached when this event is triggered).
+
 'setnpctimer' will explicitly set the timer to a given tick. To make it useful, 
 you will need the 'getnpctimer' function, which the type of information argument 
 means:

+ 39 - 3
src/map/npc.c

@@ -598,7 +598,7 @@ int npc_timerevent(int tid,unsigned int tick,int id,int data)
 	struct npc_timerevent_list *te;
 	struct timer_event_data *ted = (struct timer_event_data*)data;
 	struct map_session_data *sd=NULL;
-	
+
 	if( nd==NULL ){
 		ShowError("npc_timerevent: NPC not found??\n");
 		return 0;
@@ -743,6 +743,8 @@ int npc_timerevent_stop(struct npc_data *nd)
  */
 void npc_timerevent_quit(struct map_session_data *sd) {
 	struct TimerData *td;
+	struct npc_data* nd;
+	struct timer_event_data *ted;
 	if (sd->npc_timer_id == -1)
 		return;
 	td = get_timer(sd->npc_timer_id);
@@ -750,9 +752,43 @@ void npc_timerevent_quit(struct map_session_data *sd) {
 		sd->npc_timer_id = -1;
 		return; //??
 	}
-	delete_timer(sd->npc_timer_id,npc_timerevent);
+	nd = (struct npc_data *)map_id2bl(td->id);
+	ted = (struct timer_event_data*)td->data;
+	delete_timer(sd->npc_timer_id, npc_timerevent);
 	sd->npc_timer_id = -1;
-	ers_free(timer_event_ers, (struct event_timer_data*)td->data);
+	if (nd && nd->bl.type == BL_NPC)
+	{	//Execute OnTimerQuit
+		char buf[sizeof(nd->exname)+sizeof("::OnTimerQuit")+1];
+		struct event_data *ev;
+		sprintf(buf,"%s::OnTimerQuit",nd->exname);
+		ev = strdb_get(ev_db,(unsigned char*)buf);
+		if(ev && ev->nd != nd) {
+			ShowWarning("npc_timerevent_quit: Unable to execute \"OnTimerQuit\", two NPCs have the same event name [%s]!\n",buf);
+			ev = NULL;
+		}
+		if (ev) {
+			int old_rid,old_timer;
+			unsigned int old_tick;
+			//Set timer related info.
+			old_rid = nd->u.scr.rid;
+			nd->u.scr.rid = sd->bl.id;
+
+			old_tick = nd->u.scr.timertick;
+			nd->u.scr.timertick=ted->otick;
+
+			old_timer = nd->u.scr.timer;
+			nd->u.scr.timer=ted->time;
+		
+			//Execute label
+			run_script(nd->u.scr.script,ev->pos,sd->bl.id,nd->bl.id);
+
+			//Restore previous data.
+			nd->u.scr.rid = old_rid;
+			nd->u.scr.timer = old_timer;
+			nd->u.scr.timertick = old_tick;
+		}
+	}
+	ers_free(timer_event_ers, ted);
 }
 
 /*==========================================

+ 2 - 10
src/map/pc.c

@@ -573,9 +573,9 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t
 		return 1;
 	}
 
-	if( (old_sd=map_id2sd(sd->status.account_id)) != NULL ){
+	if( (old_sd=map_id2sd(st->account_id)) != NULL ){
 		if (old_sd->state.finalsave || !old_sd->state.auth)
-			; //Previous player is not done loading, No need to kick.
+			; //Previous player is not done loading/quiting, No need to kick.
 		else if (old_sd->fd)
 			clif_authfail_fd(old_sd->fd, 2); // same id
 		else 
@@ -583,14 +583,6 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t
 		clif_authfail_fd(sd->fd, 8); // still recognizes last connection
 		return 1;
 	}
-
-	if (map_id2sd(st->account_id) != NULL)
-	{	//Somehow a second connection has managed to go through the double-connection
-		//check in clif_parse_WantToConnection! [Skotlex]
-		clif_authfail_fd(sd->fd, 0);
-		return 1;
-	}
-
 	memcpy(&sd->status, st, sizeof(*st));
 
 	//Set the map-server used job id. [Skotlex]