ソースを参照

* Small cleanup in friend_auto_add config to now note auto-deletion.
* Updated the Secure NPC Timeout feature to work as it does on official servers and enabled by default. (bugreport:1721) (Hercules e671397)
* Fixed disable_items not working when the close button appears in NPC dialog while keeping close/close2/end backwards compatibility. (bugreport:7307 / bugreport:7469)

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

aleos 12 年 前
コミット
ae5e899822
11 ファイル変更109 行追加21 行削除
  1. 1 1
      conf/battle/player.conf
  2. 8 2
      src/config/const.h
  3. 20 4
      src/config/secure.h
  4. 2 2
      src/map/battle.c
  5. 2 2
      src/map/clif.c
  6. 15 3
      src/map/npc.c
  7. 1 1
      src/map/npc.h
  8. 2 1
      src/map/pc.c
  9. 9 1
      src/map/pc.h
  10. 48 4
      src/map/script.c
  11. 1 0
      src/map/script.h

+ 1 - 1
conf/battle/player.conf

@@ -114,7 +114,7 @@ show_hp_sp_gain: yes
 
 // If set, when A accepts B as a friend, B will also be added to A's friend 
 // list, otherwise, only A appears in B's friend list.
-// NOTE: this setting only enables friend auto-adding; auto-deletion does not work yet
+// NOTE: this setting enables friend auto-adding and auto-deletion
 friend_auto_add: yes
 
 // Are simultaneous trade/party/guild invite requests automatically rejected?

+ 8 - 2
src/config/const.h

@@ -18,8 +18,14 @@
 #if SECURE_NPCTIMEOUT_INTERVAL <= 0
 	#error SECURE_NPCTIMEOUT_INTERVAL should be at least 1 (1s)
 #endif
-#if SECURE_NPCTIMEOUT < 0
-	#error SECURE_NPCTIMEOUT cannot be lower than 0
+#if NPC_SECURE_TIMEOUT_INPUT < 0
+	#error NPC_SECURE_TIMEOUT_INPUT cannot be lower than 0
+#endif
+#if NPC_SECURE_TIMEOUT_MENU < 0
+	#error NPC_SECURE_TIMEOUT_MENU cannot be lower than 0
+#endif
+#if NPC_SECURE_TIMEOUT_NEXT < 0
+	#error NPC_SECURE_TIMEOUT_NEXT cannot be lower than 0
 #endif
 
 /**

+ 20 - 4
src/config/secure.h

@@ -16,11 +16,27 @@
  * Optional NPC Dialog Timer
  * When enabled all npcs dialog will 'timeout' if user is on idle for longer than the amount of seconds allowed
  * - On 'timeout' the npc dialog window changes its next/menu to a 'close' button
- * @values
- * - ? : Desired idle time in seconds (e.g. 10)
- * - 0 : Disabled
+ * Comment to disable the timer.
  **/
-#define SECURE_NPCTIMEOUT 0
+#define SECURE_NPCTIMEOUT
+
+/**
+ * number of seconds to 'timeout' if the user is on idle for longer than the value allowed after a 'input' field is displayed.
+ * default: 180
+ **/
+#define NPC_SECURE_TIMEOUT_INPUT 180
+
+/**
+ * number of seconds to 'timeout' if the user is on idle for longer than the value allowed after a 'menu' is displayed.
+ * default: 60
+ **/
+#define NPC_SECURE_TIMEOUT_MENU 60
+
+/**
+ * number of seconds to 'timeout' if the user is on idle for longer than the value allowed after a 'next' button is displayed.
+ * default: 60
+ **/
+#define NPC_SECURE_TIMEOUT_NEXT 60
 
 /**
  * (Secure) Optional NPC Dialog Timer

+ 2 - 2
src/map/battle.c

@@ -6027,10 +6027,10 @@ void rAthena_report(char* date, char *time_c) {
 	config |= C_RENEWAL_ASPD;
 #endif
 
-/* not a ifdef because SECURE_NPCTIMEOUT is always defined, but either as 0 or higher */
-#if SECURE_NPCTIMEOUT
+#ifdef SECURE_NPCTIMEOUT
 	config |= C_SECURE_NPCTIMEOUT;
 #endif
+
 	/* non-define part */
 	if( db_use_sqldbs )
 		config |= C_SQL_DBS;

+ 2 - 2
src/map/clif.c

@@ -11373,13 +11373,13 @@ void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd)
 	uint8 select = RFIFOB(fd,6);
 
 	if( (select > sd->npc_menu && select != 0xff) || select == 0 ) {
-#if SECURE_NPCTIMEOUT
+#ifdef SECURE_NPCTIMEOUT
 		if( sd->npc_idle_timer != INVALID_TIMER ) {
 #endif
 			TBL_NPC* nd = map_id2nd(npc_id);
 			ShowWarning("Invalid menu selection on npc %d:'%s' - got %d, valid range is [%d..%d] (player AID:%d, CID:%d, name:'%s')!\n", npc_id, (nd)?nd->name:"invalid npc id", select, 1, sd->npc_menu, sd->bl.id, sd->status.char_id, sd->status.name);
 			clif_GM_kick(NULL,sd);
-#if SECURE_NPCTIMEOUT
+#ifdef SECURE_NPCTIMEOUT
 		}
 #endif
 		return;

+ 15 - 3
src/map/npc.c

@@ -239,17 +239,29 @@ struct npc_data* npc_name2id(const char* name)
 /**
  * For the Secure NPC Timeout option (check config/Secure.h) [RR]
  **/
-#if SECURE_NPCTIMEOUT
+#ifdef SECURE_NPCTIMEOUT
 /**
  * Timer to check for idle time and timeout the dialog if necessary
  **/
 int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t data) {
 	struct map_session_data* sd = NULL;
+	unsigned int timeout = NPC_SECURE_TIMEOUT_NEXT;
 	if( (sd = map_id2sd(id)) == NULL || !sd->npc_id ) {
 		if( sd ) sd->npc_idle_timer = INVALID_TIMER;
 		return 0;//Not logged in anymore OR no longer attached to a npc
 	}
-	if( DIFF_TICK(tick,sd->npc_idle_tick) > (SECURE_NPCTIMEOUT*1000) ) {
+
+	switch( sd->npc_idle_type ) {
+		case NPCT_INPUT:
+			timeout = NPC_SECURE_TIMEOUT_INPUT;
+			break;
+		case NPCT_MENU:
+			timeout = NPC_SECURE_TIMEOUT_MENU;
+			break;
+		//case NPCT_WAIT: var starts with this value
+	}
+
+	if( DIFF_TICK(tick,sd->npc_idle_tick) > (timeout*1000) ) {
 		/**
 		 * If we still have the NPC script attached, tell it to stop.
 		 **/
@@ -1239,7 +1251,7 @@ int npc_scriptcont(struct map_session_data* sd, int id, bool closing)
 	/**
 	 * For the Secure NPC Timeout option (check config/Secure.h) [RR]
 	 **/
-#if SECURE_NPCTIMEOUT
+#ifdef SECURE_NPCTIMEOUT
 	/**
 	 * Update the last NPC iteration
 	 **/

+ 1 - 1
src/map/npc.h

@@ -178,7 +178,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns
 /**
  * For the Secure NPC Timeout option (check config/Secure.h) [RR]
  **/
-#if SECURE_NPCTIMEOUT
+#ifdef SECURE_NPCTIMEOUT
 	int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t data);
 #endif
 

+ 2 - 1
src/map/pc.c

@@ -967,12 +967,13 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
 	/**
 	 * For the Secure NPC Timeout option (check config/Secure.h) [RR]
 	 **/
-#if SECURE_NPCTIMEOUT
+#ifdef SECURE_NPCTIMEOUT
 	/**
 	 * Initialize to defaults/expected
 	 **/
 	sd->npc_idle_timer = INVALID_TIMER;
 	sd->npc_idle_tick = tick;
+	sd->npc_idle_type = NPCT_INPUT;
 #endif
 
 	sd->canuseitem_tick = tick;

+ 9 - 1
src/map/pc.h

@@ -108,6 +108,12 @@ struct s_autobonus {
 	unsigned short pos;
 };
 
+enum npc_timeout_type {
+	NPCT_INPUT = 0,
+	NPCT_MENU  = 1,
+	NPCT_WAIT  = 2,
+};
+
 struct map_session_data {
 	struct block_list bl;
 	struct unit_data ud;
@@ -469,7 +475,7 @@ struct map_session_data {
 	/**
 	 * For the Secure NPC Timeout option (check config/Secure.h) [RR]
 	 **/
-#if SECURE_NPCTIMEOUT
+#ifdef SECURE_NPCTIMEOUT
 	/**
 	 * ID of the timer
 	 * @info
@@ -483,6 +489,8 @@ struct map_session_data {
 	 * - It is updated on every NPC iteration as mentioned above
 	 **/
 	unsigned int npc_idle_tick;
+	/* */
+	enum npc_timeout_type npc_idle_type;
 #endif
 
 	struct {

+ 48 - 4
src/map/script.c

@@ -49,6 +49,7 @@
 #include "script.h"
 #include "quest.h"
 #include "elemental.h"
+#include "../config/core.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -3602,7 +3603,7 @@ static void script_detach_state(struct script_state* st, bool dequeue_event)
 			/**
 			 * For the Secure NPC Timeout option (check config/Secure.h) [RR]
 			 **/
-#if SECURE_NPCTIMEOUT
+#ifdef SECURE_NPCTIMEOUT
 			/**
 			 * We're done with this NPC session, so we cancel the timer (if existent) and move on
 			 **/
@@ -3648,7 +3649,7 @@ static void script_attach_state(struct script_state* st)
 /**
  * For the Secure NPC Timeout option (check config/Secure.h) [RR]
  **/
-#if SECURE_NPCTIMEOUT
+#ifdef SECURE_NPCTIMEOUT
 		if( sd->npc_idle_timer == INVALID_TIMER )
 			sd->npc_idle_timer = add_timer(gettick() + (SECURE_NPCTIMEOUT_INTERVAL*1000),npc_rr_secure_timeout_timer,sd->bl.id,0);
 		sd->npc_idle_tick = gettick();
@@ -4361,6 +4362,8 @@ BUILDIN_FUNC(mes)
 		}
 	}
 
+	st->mes_active = 1; // Invoking character has a NPC dialog box open.
+
 	return 0;
 }
 
@@ -4375,7 +4378,9 @@ BUILDIN_FUNC(next)
 	sd = script_rid2sd(st);
 	if( sd == NULL )
 		return 0;
-
+#ifdef SECURE_NPCTIMEOUT
+	sd->npc_idle_type = NPCT_WAIT;
+#endif
 	st->state = STOP;
 	clif_scriptnext(sd, st->oid);
 	return 0;
@@ -4393,7 +4398,15 @@ BUILDIN_FUNC(close)
 	if( sd == NULL )
 		return 0;
 
-	st->state = END; //Should be CLOSE, but breaks backwards compatibility.
+	if( !st->mes_active ) {
+		TBL_NPC* nd = map_id2nd(st->oid);
+		st->state = END; // Keep backwards compatibility.
+		ShowWarning("Incorrect use of 'close'! (source:%s / path:%s)\n",nd?nd->name:"Unknown",nd?nd->path:"Unknown");
+	} else {
+		st->state = CLOSE;
+		st->mes_active = 0;
+	}
+
 	clif_scriptclose(sd, st->oid);
 	return 0;
 }
@@ -4411,6 +4424,10 @@ BUILDIN_FUNC(close2)
 		return 0;
 
 	st->state = STOP;
+
+	if( st->mes_active )
+		st->mes_active = 0;
+
 	clif_scriptclose(sd, st->oid);
 	return 0;
 }
@@ -4477,6 +4494,10 @@ BUILDIN_FUNC(menu)
 	if( sd == NULL )
 		return 0;
 
+#ifdef SECURE_NPCTIMEOUT
+	sd->npc_idle_type = NPCT_MENU;
+#endif
+
 	// TODO detect multiple scripts waiting for input at the same time, and what to do when that happens
 	if( sd->state.menu_or_input == 0 )
 	{
@@ -4602,6 +4623,10 @@ BUILDIN_FUNC(select)
 	if( sd == NULL )
 		return 0;
 
+#ifdef SECURE_NPCTIMEOUT
+	sd->npc_idle_type = NPCT_MENU;
+#endif
+
 	if( sd->state.menu_or_input == 0 ) {
 		struct StringBuf buf;
 
@@ -4677,6 +4702,10 @@ BUILDIN_FUNC(prompt)
 	if( sd == NULL )
 		return 0;
 
+#ifdef SECURE_NPCTIMEOUT
+	sd->npc_idle_type = NPCT_MENU;
+#endif
+
 	if( sd->state.menu_or_input == 0 )
 	{
 		struct StringBuf buf;
@@ -5418,6 +5447,10 @@ BUILDIN_FUNC(input)
 	min = (script_hasdata(st,3) ? script_getnum(st,3) : script_config.input_min_value);
 	max = (script_hasdata(st,4) ? script_getnum(st,4) : script_config.input_max_value);
 
+#ifdef SECURE_NPCTIMEOUT
+	sd->npc_idle_type = NPCT_WAIT;
+#endif
+
 	if( !sd->state.menu_or_input )
 	{	// first invocation, display npc input box
 		sd->state.menu_or_input = 1;
@@ -8209,7 +8242,18 @@ BUILDIN_FUNC(getgroupid)
 /// end
 BUILDIN_FUNC(end)
 {
+	TBL_PC* sd;
+
+	sd = map_id2sd(st->rid);
+
 	st->state = END;
+
+	if( st->mes_active )
+		st->mes_active = 0;
+
+	if( sd )
+		clif_scriptclose(sd, st->oid); // If a menu/select/prompt is active, close it.
+
 	return 0;
 }
 

+ 1 - 0
src/map/script.h

@@ -133,6 +133,7 @@ struct script_state {
 	unsigned freeloop : 1;// used by buildin_freeloop
 	unsigned op2ref : 1;// used by op_2
 	unsigned npc_item_flag : 1;
+	unsigned mes_active : 1;  // Store if invoking character has a NPC dialog box open.
 };
 
 struct script_reg {