Browse Source

- Updated the Dancer job quest to attach a player to the main timer script.
- Updated script commands startnpctimer, stopnpctimer, initnpctimer so you can attach a player to them, this is done because the attach/detach functions can't be used to attach to a different script than the one currently running.
- Some script code cleaning
- Updated the script_command reference with the new flag values of [start/stop/init]npctimer.


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

skotlex 18 years ago
parent
commit
5ed686f6a8
5 changed files with 140 additions and 56 deletions
  1. 6 0
      Changelog-Trunk.txt
  2. 23 14
      doc/script_commands.txt
  3. 2 1
      npc/Changelog.txt
  4. 4 3
      npc/jobs/2-2/dancer.txt
  5. 105 38
      src/map/script.c

+ 6 - 0
Changelog-Trunk.txt

@@ -4,6 +4,12 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 
 2007/02/16
 2007/02/16
+	* Updated script commands startnpctimer, stopnpctimer, initnpctimer so you
+	  can attach a player to them, this is done because the attach/detach
+	  functions can't be used to attach to a different script than the one
+	  currently running.
+	* Updated the script_command reference with the new flag values of
+	  [start/stop/init]npctimer.
 	* Modified the "guardian" spawn script command, it no longer receives a
 	* Modified the "guardian" spawn script command, it no longer receives a
 	  "amount" argument (since that only leads to trouble), if the class is
 	  "amount" argument (since that only leads to trouble), if the class is
 	  negative, it'll pick a random class the same way the monster spawn script
 	  negative, it'll pick a random class the same way the monster spawn script

+ 23 - 14
doc/script_commands.txt

@@ -59,6 +59,10 @@
 //= 3.02.20070209
 //= 3.02.20070209
 //=       Corrected/updated info on Xor/setd/getd/callfunc/callsub/return and 
 //=       Corrected/updated info on Xor/setd/getd/callfunc/callsub/return and 
 //=       updated some examples to use "better" code. [FlavioJS]
 //=       updated some examples to use "better" code. [FlavioJS]
+//= 3.03.20070216
+//=       Expanded/clarified information on npc timers, added info about the
+//=       new attach flag for script commands startnpctimer/ stopnpctimer/ 
+//=       initnpctimer [Skotlex]
 //===== Compatible With ===================================
 //===== Compatible With ===================================
 //= LOL, can be used by anyone hopefully
 //= LOL, can be used by anyone hopefully
 //===== Description =======================================
 //===== Description =======================================
@@ -4815,9 +4819,12 @@ is.
 
 
 ---------------------------------------
 ---------------------------------------
 
 
-*initnpctimer{ "<NPC object name>"};
-*stopnpctimer{ "<NPC object name>"};
-*startnpctimer{ "<NPC object name>"};
+*initnpctimer{ "<NPC object name>" {, <Attach Flag>} } |
+             {"<NPC object name>" | <Attach Flag> };
+*stopnpctimer{ "<NPC object name>" {, <Detach Flag>}  } |
+             { "<NPC object name>" | <Detach Flag> };
+*startnpctimer{ "<NPC object name>" {, <Attach Flag>} } |
+              { "<NPC object name>" | <Attach Flag> };
 *setnpctimer <tick>{,"<NPC object name>"};
 *setnpctimer <tick>{,"<NPC object name>"};
 *getnpctimer(<type of information>{,"<NPC object name>"});
 *getnpctimer(<type of information>{,"<NPC object name>"});
 *attachnpctimer {"<character name>"};
 *attachnpctimer {"<character name>"};
@@ -4844,17 +4851,19 @@ To create the timer, use the 'initnpctimer', which will start it running.
 'stopnpctimer' will pause the timer, without clearing the current tick, while 
 'stopnpctimer' will pause the timer, without clearing the current tick, while 
 'startnpctimer' will let the paused timer continue.
 'startnpctimer' will let the paused timer continue.
 
 
-It is not quite clear whether the new invocations will always have a RID. 
-Apparently, the RID that was in effect when the timer was initialised will still 
-be attached to these executions in some cases, but it's not quite clear -
-experiment with RID-dependent commands, like 'mes', and tell us what happens and 
-who gets the message, if anyone.
-
-Even if they don't have a RID by default, 'attachnpctimer' will allow you to 
-explicitly attach a character's RID to the timer, which will make them the 
-target for all character-referencing commands and functions, not to mention 
-variables. 'detachnpctimer' will make the RID zero, making all character-
-referencing functions fail with an error.
+By default timers do not have a RID attached, which lets the timers continue even
+if the player that started them logs off. To attach a RID to a timer, you can
+either use the "attach flag" optional value when using initnpctimer/startnpctimer, 
+likewise, the optional flag of stopnpctimer detaches any RID after stopping
+the timer. One a player is attached to a timer, it stays attached to all
+timers from that script until detached manually. You can have multiple
+npctimers going on at the same time as long as each one has a different player
+attached (think of each RID being used as an independant timer).
+
+The other method to attach/detach a RID is through the script commands
+'attachnpctimer' and 'detachnpctimer'. Once attached, that will make the
+character the target for all character-referencing commands and functions,
+not to mention variables.
 
 
 'setnpctimer' will explicitly set the timer to a given tick. To make it useful, 
 '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 
 you will need the 'getnpctimer' function, which the type of information argument 

+ 2 - 1
npc/Changelog.txt

@@ -26,7 +26,8 @@ KarLaeda
 
 
 Date		Added
 Date		Added
 ======
 ======
-2007/02/17
+2007/02/16
+	* Updated the Dancer job quest to attach a player to the main timer script.
 	* Updated WoE scripts since the "guardian" script command no longer has a
 	* Updated WoE scripts since the "guardian" script command no longer has a
 	  "amount" argument. [Skotlex]
 	  "amount" argument. [Skotlex]
 2007/02/15
 2007/02/15

+ 4 - 3
npc/jobs/2-2/dancer.txt

@@ -4,7 +4,7 @@
 //= Kalen - Original jAthena
 //= Kalen - Original jAthena
 //= Fredzilla - Converted
 //= Fredzilla - Converted
 //===== Current Version: ===================================== 
 //===== Current Version: ===================================== 
-//= 2.2
+//= 2.3
 //===== Compatible With: ===================================== 
 //===== Compatible With: ===================================== 
 //= eAthena Final
 //= eAthena Final
 //===== Description: ========================================= 
 //===== Description: ========================================= 
@@ -24,6 +24,7 @@
 //= 2.0 Changed numbers to constants. [Vicious]
 //= 2.0 Changed numbers to constants. [Vicious]
 //= 2.1 Script check #1. [Lance]
 //= 2.1 Script check #1. [Lance]
 //= 2.2 Fixed unpassable part, thx2 Alis [Lupus]
 //= 2.2 Fixed unpassable part, thx2 Alis [Lupus]
+//= 2.3 Updated initnpctimer to attach player to jobDq script [Skotlex]
 //============================================================
 //============================================================
 
 
 //= Warning Warp to escape the quest if need be
 //= Warning Warp to escape the quest if need be
@@ -689,7 +690,7 @@ job_duncer.gat,32,152,6	script	Guide::dancew	69,{
 	OnWarp:
 	OnWarp:
 	warpwaitingpc "job_duncer.gat",70,112,1;
 	warpwaitingpc "job_duncer.gat",70,112,1;
 	disablewaitingroomevent;
 	disablewaitingroomevent;
-	       initnpctimer "jobDq";
+	       initnpctimer "jobDq",1;
 	end;
 	end;
 OnInit:
 OnInit:
 	waitingroom "Dance lesson waiting room",20,"dancew::OnWarp",1;
 	waitingroom "Dance lesson waiting room",20,"dancew::OnWarp",1;
@@ -1052,6 +1053,6 @@ OnInit:
 //		close;
 //		close;
 //Lgo:
 //Lgo:
 //	warp "job_duncer.gat",70,112;
 //	warp "job_duncer.gat",70,112;
-//	initnpctimer "jobDq";
+//	initnpctimer "jobDq",1;
 //	end;
 //	end;
 //}
 //}

+ 105 - 38
src/map/script.c

@@ -3922,13 +3922,13 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(addtimer,"is"),
 	BUILDIN_DEF(addtimer,"is"),
 	BUILDIN_DEF(deltimer,"s"),
 	BUILDIN_DEF(deltimer,"s"),
 	BUILDIN_DEF(addtimercount,"si"),
 	BUILDIN_DEF(addtimercount,"si"),
-	BUILDIN_DEF(initnpctimer,"*"),
-	BUILDIN_DEF(stopnpctimer,"*"),
-	BUILDIN_DEF(startnpctimer,"*"),
-	BUILDIN_DEF(setnpctimer,"*"),
-	BUILDIN_DEF(getnpctimer,"i*"),
-	BUILDIN_DEF(attachnpctimer,"*"), // attached the player id to the npc timer [Celest]
-	BUILDIN_DEF(detachnpctimer,"*"), // detached the player id from the npc timer [Celest]
+	BUILDIN_DEF(initnpctimer,"??"),
+	BUILDIN_DEF(stopnpctimer,"??"),
+	BUILDIN_DEF(startnpctimer,"??"),
+	BUILDIN_DEF(setnpctimer,"i?"),
+	BUILDIN_DEF(getnpctimer,"i?"),
+	BUILDIN_DEF(attachnpctimer,"?"), // attached the player id to the npc timer [Celest]
+	BUILDIN_DEF(detachnpctimer,"?"), // detached the player id from the npc timer [Celest]
 	BUILDIN_DEF(playerattached,""), // returns id of the current attached player. [Skotlex]
 	BUILDIN_DEF(playerattached,""), // returns id of the current attached player. [Skotlex]
 	BUILDIN_DEF(announce,"si*"),
 	BUILDIN_DEF(announce,"si*"),
 	BUILDIN_DEF(mapannounce,"ssi*"),
 	BUILDIN_DEF(mapannounce,"ssi*"),
@@ -7342,8 +7342,8 @@ BUILDIN_FUNC(addtimer)
 {
 {
 	char *event;
 	char *event;
 	int tick;
 	int tick;
-	tick=conv_num(st,& (st->stack->stack_data[st->start+2]));
-	event=conv_str(st,& (st->stack->stack_data[st->start+3]));
+	tick=conv_num(st, script_getdata(st,2));
+	event=conv_str(st, script_getdata(st,3));
 	check_event(st, event);
 	check_event(st, event);
 	pc_addeventtimer(script_rid2sd(st),tick,event);
 	pc_addeventtimer(script_rid2sd(st),tick,event);
 	return 0;
 	return 0;
@@ -7355,7 +7355,7 @@ BUILDIN_FUNC(addtimer)
 BUILDIN_FUNC(deltimer)
 BUILDIN_FUNC(deltimer)
 {
 {
 	char *event;
 	char *event;
-	event=conv_str(st,& (st->stack->stack_data[st->start+2]));
+	event=conv_str(st, script_getdata(st,2));
 	check_event(st, event);
 	check_event(st, event);
 	pc_deleventtimer(script_rid2sd(st),event);
 	pc_deleventtimer(script_rid2sd(st),event);
 	return 0;
 	return 0;
@@ -7368,8 +7368,8 @@ BUILDIN_FUNC(addtimercount)
 {
 {
 	char *event;
 	char *event;
 	int tick;
 	int tick;
-	event=conv_str(st,& (st->stack->stack_data[st->start+2]));
-	tick=conv_num(st,& (st->stack->stack_data[st->start+3]));
+	event=conv_str(st, script_getdata(st,2));
+	tick=conv_num(st, script_getdata(st,3));
 	check_event(st, event);
 	check_event(st, event);
 	pc_addeventtimercount(script_rid2sd(st),event,tick);
 	pc_addeventtimercount(script_rid2sd(st),event,tick);
 	return 0;
 	return 0;
@@ -7382,11 +7382,35 @@ BUILDIN_FUNC(addtimercount)
 BUILDIN_FUNC(initnpctimer)
 BUILDIN_FUNC(initnpctimer)
 {
 {
 	struct npc_data *nd;
 	struct npc_data *nd;
-	if( st->end > st->start+2 )
-		nd=npc_name2id(conv_str(st,& (st->stack->stack_data[st->start+2])));
-	else
+	int flag = 0;
+	if( script_hasdata(st,3) )
+	{	//Two arguments: NPC name and attach flag.
+		nd = npc_name2id(conv_str(st, script_getdata(st,2)));
+		flag = conv_num(st, script_getdata(st,3));
+	} else
+	if( script_hasdata(st,2) )
+	{	//Check if argument is numeric (flag) or string (npc name)
+		struct script_data *data;
+		data = script_getdata(st,2);
+		get_val(st,data);
+		if( data_isstring(data) ) //NPC name
+			nd = npc_name2id(conv_str(st, script_getdata(st,2)));
+		else if( data_isint(data) ) {	//Flag
+			nd = (struct npc_data *)map_id2bl(st->oid);
+			flag = conv_num(st, script_getdata(st,3));
+		} else {
+			ShowError("initnpctimer: invalid argument type #1 (needs be int or string)).\n");
+			return 1;
+		}
+	} else
 		nd=(struct npc_data *)map_id2bl(st->oid);
 		nd=(struct npc_data *)map_id2bl(st->oid);
 
 
+	if (!nd) return 0;
+	if (flag) { //Attach
+		TBL_PC* sd = script_rid2sd(st);
+		if (sd) nd->u.scr.rid = sd->bl.id;
+	}
+
 	npc_settimerevent_tick(nd,0);
 	npc_settimerevent_tick(nd,0);
 	npc_timerevent_start(nd, st->rid);
 	npc_timerevent_start(nd, st->rid);
 	return 0;
 	return 0;
@@ -7398,11 +7422,35 @@ BUILDIN_FUNC(initnpctimer)
 BUILDIN_FUNC(startnpctimer)
 BUILDIN_FUNC(startnpctimer)
 {
 {
 	struct npc_data *nd;
 	struct npc_data *nd;
-	if( st->end > st->start+2 )
-		nd=npc_name2id(conv_str(st,& (st->stack->stack_data[st->start+2])));
-	else
+	int flag = 0;
+	if( script_hasdata(st,3) )
+	{	//Two arguments: NPC name and attach flag.
+		nd = npc_name2id(conv_str(st, script_getdata(st,2)));
+		flag = conv_num(st, script_getdata(st,3));
+	} else
+	if( script_hasdata(st,2) )
+	{	//Check if argument is numeric (flag) or string (npc name)
+		struct script_data *data;
+		data = script_getdata(st,2);
+		get_val(st,data);
+		if( data_isstring(data) ) //NPC name
+			nd = npc_name2id(conv_str(st, script_getdata(st,2)));
+		else if( data_isint(data) ) {	//Flag
+			nd = (struct npc_data *)map_id2bl(st->oid);
+			flag = conv_num(st, script_getdata(st,3));
+		} else {
+			ShowError("startnpctimer: invalid argument type #1 (needs be int or string)).\n");
+			return 1;
+		}
+	} else
 		nd=(struct npc_data *)map_id2bl(st->oid);
 		nd=(struct npc_data *)map_id2bl(st->oid);
 
 
+	if (!nd) return 0;
+	if (flag) { //Attach
+		TBL_PC* sd = script_rid2sd(st);
+		if (sd) nd->u.scr.rid = sd->bl.id;
+	}
+
 	npc_timerevent_start(nd, st->rid);
 	npc_timerevent_start(nd, st->rid);
 	return 0;
 	return 0;
 }
 }
@@ -7413,11 +7461,33 @@ BUILDIN_FUNC(startnpctimer)
 BUILDIN_FUNC(stopnpctimer)
 BUILDIN_FUNC(stopnpctimer)
 {
 {
 	struct npc_data *nd;
 	struct npc_data *nd;
-	if( st->end > st->start+2 )
-		nd=npc_name2id(conv_str(st,& (st->stack->stack_data[st->start+2])));
-	else
+	int flag = 0;
+	if( script_hasdata(st,3) )
+	{	//Two arguments: NPC name and attach flag.
+		nd = npc_name2id(conv_str(st, script_getdata(st,2)));
+		flag = conv_num(st, script_getdata(st,3));
+	} else
+	if( script_hasdata(st,2) )
+	{	//Check if argument is numeric (flag) or string (npc name)
+		struct script_data *data;
+		data = script_getdata(st,2);
+		get_val(st,data);
+		if( data_isstring(data) ) //NPC name
+			nd = npc_name2id(conv_str(st, script_getdata(st,2)));
+		else if( data_isint(data) ) {	//Flag
+			nd = (struct npc_data *)map_id2bl(st->oid);
+			flag = conv_num(st, script_getdata(st,3));
+		} else {
+			ShowError("stopnpctimer: invalid argument type #1 (needs be int or string)).\n");
+			return 1;
+		}
+	} else
 		nd=(struct npc_data *)map_id2bl(st->oid);
 		nd=(struct npc_data *)map_id2bl(st->oid);
 
 
+	if (!nd) return 0;
+	if (flag) //Detach
+		nd->u.scr.rid = 0;
+
 	npc_timerevent_stop(nd);
 	npc_timerevent_stop(nd);
 	return 0;
 	return 0;
 }
 }
@@ -7429,12 +7499,12 @@ BUILDIN_FUNC(getnpctimer)
 {
 {
 	struct npc_data *nd;
 	struct npc_data *nd;
 	struct map_session_data *sd;
 	struct map_session_data *sd;
-	int type=conv_num(st,& (st->stack->stack_data[st->start+2]));
+	int type=conv_num(st, script_getdata(st,2));
 	int val=0;
 	int val=0;
-	if( st->end > st->start+3 )
-		nd=npc_name2id(conv_str(st,& (st->stack->stack_data[st->start+3])));
+	if( script_hasdata(st,3) )
+		nd = npc_name2id(conv_str(st,script_getdata(st,3)));
 	else
 	else
-		nd=(struct npc_data *)map_id2bl(st->oid);
+		nd = (struct npc_data *)map_id2bl(st->oid);
 	
 	
 	if (!nd || nd->bl.type != BL_NPC)
 	if (!nd || nd->bl.type != BL_NPC)
 	{
 	{
@@ -7471,9 +7541,9 @@ BUILDIN_FUNC(setnpctimer)
 {
 {
 	int tick;
 	int tick;
 	struct npc_data *nd;
 	struct npc_data *nd;
-	tick=conv_num(st,& (st->stack->stack_data[st->start+2]));
-	if( st->end > st->start+3 )
-		nd=npc_name2id(conv_str(st,& (st->stack->stack_data[st->start+3])));
+	tick=conv_num(st,script_getdata(st,2));
+	if( script_hasdata(st,3) )
+		nd=npc_name2id(conv_str(st,script_getdata(st,3)));
 	else
 	else
 		nd=(struct npc_data *)map_id2bl(st->oid);
 		nd=(struct npc_data *)map_id2bl(st->oid);
 
 
@@ -7491,12 +7561,10 @@ BUILDIN_FUNC(attachnpctimer)
 	struct npc_data *nd;
 	struct npc_data *nd;
 
 
 	nd=(struct npc_data *)map_id2bl(st->oid);
 	nd=(struct npc_data *)map_id2bl(st->oid);
-	if( st->end > st->start+2 ) {
-		char *name = conv_str(st,& (st->stack->stack_data[st->start+2]));
-		sd=map_nick2sd(name);
-	} else {
+	if( script_hasdata(st,2) )
+		sd=map_nick2sd(conv_str(st,script_getdata(st,2)));
+	else
 		sd = script_rid2sd(st);
 		sd = script_rid2sd(st);
-	}
 
 
 	if (sd==NULL)
 	if (sd==NULL)
 		return 0;
 		return 0;
@@ -7512,8 +7580,8 @@ BUILDIN_FUNC(attachnpctimer)
 BUILDIN_FUNC(detachnpctimer)
 BUILDIN_FUNC(detachnpctimer)
 {
 {
 	struct npc_data *nd;
 	struct npc_data *nd;
-	if( st->end > st->start+2 )
-		nd=npc_name2id(conv_str(st,& (st->stack->stack_data[st->start+2])));
+	if( script_hasdata(st,2) )
+		nd=npc_name2id(conv_str(st,script_getdata(st,2)));
 	else
 	else
 		nd=(struct npc_data *)map_id2bl(st->oid);
 		nd=(struct npc_data *)map_id2bl(st->oid);
 
 
@@ -7524,13 +7592,12 @@ BUILDIN_FUNC(detachnpctimer)
 /*==========================================
 /*==========================================
  * To avoid "player not attached" script errors, this function is provided,
  * To avoid "player not attached" script errors, this function is provided,
  * it checks if there is a player attached to the current script. [Skotlex]
  * it checks if there is a player attached to the current script. [Skotlex]
- * If no, returns 0, if yes, returns the char_id of the attached player.
+ * If no, returns 0, if yes, returns the account_id of the attached player.
  *------------------------------------------
  *------------------------------------------
  */
  */
 BUILDIN_FUNC(playerattached)
 BUILDIN_FUNC(playerattached)
 {
 {
-	struct map_session_data *sd;
-	if (st->rid == 0 || (sd = map_id2sd(st->rid)) == NULL)
+	if(st->rid == 0 || map_id2sd(st->rid) == NULL)
 		push_val(st->stack,C_INT,0);
 		push_val(st->stack,C_INT,0);
 	else
 	else
 		push_val(st->stack,C_INT,st->rid);
 		push_val(st->stack,C_INT,st->rid);