فهرست منبع

- A bit more work on Ticket #41.
- Added 'r' (variable reference) to the script argument definitions.
- Added a simple define for suspitious actions. (empty at the moment)
- Added clif_clearcart and moved sending cart packets to pc_setoption.
- clif_parse_ChangeCart checking the player level.

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

FlavioJS 18 سال پیش
والد
کامیت
781fa7bb72
7فایلهای تغییر یافته به همراه144 افزوده شده و 89 حذف شده
  1. 5 0
      Changelog-Trunk.txt
  2. 4 8
      src/map/atcommand.c
  3. 21 1
      src/map/clif.c
  4. 1 0
      src/map/clif.h
  5. 3 0
      src/map/map.h
  6. 17 19
      src/map/pc.c
  7. 93 61
      src/map/script.c

+ 5 - 0
Changelog-Trunk.txt

@@ -4,6 +4,11 @@ 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.
 
 2007/02/12
+	* A bit more work on Ticket #41.
+	* Added 'r' (variable reference) to the script argument definitions.
+	* Added a simple define for suspitious actions. (empty at the moment)
+	* Added clif_clearcart and moved sending cart packets to pc_setoption.
+	* clif_parse_ChangeCart checking the player level. [FlavioJS]
 	* Fixed clif_parse_GMmessage cutting off messages randomly [ultramage]
 	  (due to a typo in revision r9778)
 	* Fixed Wand of Hermod

+ 4 - 8
src/map/atcommand.c

@@ -2218,10 +2218,6 @@ int atcommand_option(const int fd, struct map_session_data* sd, const char* comm
 
 	sd->sc.opt1 = param1;
 	sd->sc.opt2 = param2;
-	if (!(sd->sc.option & OPTION_CART) && param3 & OPTION_CART) {
-		clif_cartlist(sd);
-		clif_updatestatus(sd, SP_CARTINFO);
-	}
 	pc_setoption(sd, param3);
 	
 	clif_displaymessage(fd, msg_txt(9)); // Options changed.
@@ -5666,14 +5662,14 @@ int atcommand_mount_peco(const int fd, struct map_session_data* sd, const char*
 
 	if (!pc_isriding(sd)) { // if actually no peco
 		if (pc_checkskill(sd, KN_RIDING)) {
-			pc_setoption(sd, sd->sc.option | 0x0020);
+			pc_setoption(sd, sd->sc.option | OPTION_RIDING);
 			clif_displaymessage(fd, msg_txt(102)); // Mounted Peco.
 		} else {
 			clif_displaymessage(fd, msg_txt(213)); // You can not mount a peco with your job.
 			return -1;
 		}
 	} else {	//Dismount
-		pc_setoption(sd, sd->sc.option & ~0x0020);
+		pc_setoption(sd, sd->sc.option & ~OPTION_RIDING);
 		clif_displaymessage(fd, msg_txt(214)); // Unmounted Peco.
 	}
 
@@ -5700,14 +5696,14 @@ int atcommand_char_mount_peco(const int fd, struct map_session_data* sd, const c
 
 		if (!pc_isriding(pl_sd)) { // if actually no peco
 			if (pc_checkskill(pl_sd, KN_RIDING)) {
-				pc_setoption(pl_sd, pl_sd->sc.option | 0x0020);
+				pc_setoption(pl_sd, pl_sd->sc.option | OPTION_RIDING);
 				clif_displaymessage(fd, msg_txt(216)); // Mounted Peco.
 			} else {
 				clif_displaymessage(fd, msg_txt(217)); // You can not mount a peco with your job.
 				return -1;
 			}
 		} else {	//Dismount
-			pc_setoption(pl_sd, pl_sd->sc.option & ~0x0020);
+			pc_setoption(pl_sd, pl_sd->sc.option & ~OPTION_RIDING);
 			clif_displaymessage(fd, msg_txt(218)); // Unmounted Peco.
 		}
 	} else {

+ 21 - 1
src/map/clif.c

@@ -2391,6 +2391,15 @@ void clif_cartlist(struct map_session_data *sd)
 	return;
 }
 
+/// Client behaviour:
+/// Closes the cart storage and removes all it's items from memory.
+/// The Num & Weight values of the cart are left untouched and the cart is NOT removed.
+void clif_clearcart(int fd)
+{
+	WFIFOHEAD(fd, packet_len(0x12b));
+	WFIFOW(fd,0) = 0x12b;
+}
+
 // Guild XY locators [Valaris]
 int clif_guild_xy(struct map_session_data *sd)
 {
@@ -9612,8 +9621,19 @@ void clif_parse_RemoveOption(int fd,struct map_session_data *sd)
  */
 void clif_parse_ChangeCart(int fd,struct map_session_data *sd)
 {
+	int type;
+
 	RFIFOHEAD(fd);
-	pc_setcart(sd,RFIFOW(fd,2));
+	type = (int)RFIFOW(fd,2);
+
+	if( (type == 5 && sd->status.base_level <= 90) ||
+		(type == 4 && sd->status.base_level <= 80) ||
+		(type == 3 && sd->status.base_level <= 65) ||
+		(type == 2 && sd->status.base_level <= 40) ||
+		pc_setcart(sd,type) )
+	{
+		LOG_SUSPICIOUS(sd,"clif_parse_ChangeCart: player doesn't have the required level");
+	}
 }
 
 /*==========================================

+ 1 - 0
src/map/clif.h

@@ -225,6 +225,7 @@ void clif_equiplist(struct map_session_data *sd);
 int clif_cart_additem(struct map_session_data*,int,int,int);
 int clif_cart_delitem(struct map_session_data*,int,int);
 void clif_cartlist(struct map_session_data *sd);
+void clif_clearcart(int fd);
 
 int clif_item_identify_list(struct map_session_data *sd);
 int clif_item_identified(struct map_session_data *sd,int idx,int flag);

+ 3 - 0
src/map/map.h

@@ -546,6 +546,9 @@ struct homunculus_db;	//[orn]
 struct item_data;
 struct square;
 
+// The player performed a suspicious action (not used right now) [FlavioJS]
+#define LOG_SUSPICIOUS(sd,msg)
+
 struct map_session_data {
 	struct block_list bl;
 	struct unit_data ud;

+ 17 - 19
src/map/pc.c

@@ -5737,15 +5737,18 @@ int pc_setoption(struct map_session_data *sd,int type)
 	}
 	if(type&OPTION_CART && !(p_type&OPTION_CART))
   	{ //Cart On
+		clif_cartlist(sd);
+		clif_updatestatus(sd, SP_CARTINFO);
 		if(pc_checkskill(sd, MC_PUSHCART) < 10)
 			status_calc_pc(sd,0); //Apply speed penalty.
 	} else
 	if(!(type&OPTION_CART) && p_type&OPTION_CART)
 	{ //Cart Off
+		clif_clearcart(sd->fd);
 		if(pc_checkskill(sd, MC_PUSHCART) < 10)
 			status_calc_pc(sd,0); //Remove speed penalty.
 	}
-			
+
 	if (type&OPTION_FALCON && !(p_type&OPTION_FALCON)) //Falcon ON
 		clif_status_load(&sd->bl,SI_FALCON,1);
 	else if (!(type&OPTION_FALCON) && p_type&OPTION_FALCON) //Falcon OFF
@@ -5784,27 +5787,22 @@ int pc_setoption(struct map_session_data *sd,int type)
  */
 int pc_setcart(struct map_session_data *sd,int type)
 {
-	int cart[6]={0x0000,OPTION_CART1,OPTION_CART2,OPTION_CART3,OPTION_CART4,OPTION_CART5};
+	int cart[6] = {0x0000,OPTION_CART1,OPTION_CART2,OPTION_CART3,OPTION_CART4,OPTION_CART5};
 	int option;
+
 	nullpo_retr(0, sd);
-	
-	if (type < 0 || type > 5)
-		return 0; //Never trust the values sent by the client! [Skotlex]
 
-	if(pc_checkskill(sd,MC_PUSHCART)>0){ // プッシュカ?トスキル所持
-		option = sd->sc.option;
-		//This should preserve the current option, only modifying the cart bit.
-		option&=~OPTION_CART;
-		option|=cart[type];
-		if(!pc_iscarton(sd)){ // カ?トを付けていない
-			pc_setoption(sd,option);
-			clif_cartlist(sd);
-			clif_updatestatus(sd,SP_CARTINFO);
-		}
-		else{
-			pc_setoption(sd,option);
-		}
-	}
+	if( type < 0 || type > 5 )
+		return 1;// Never trust the values sent by the client! [Skotlex]
+
+	if( pc_checkskill(sd,MC_PUSHCART) <= 0 )
+		return 1;// Push cart is required
+
+	// Update option
+	option = sd->sc.option;
+	option &= ~OPTION_CART;// clear cart bits
+	option |= cart[type]; // set cart
+	pc_setoption(sd, option);
 
 	return 0;
 }

+ 93 - 61
src/map/script.c

@@ -52,9 +52,10 @@
 #include <time.h>
 #include <setjmp.h>
 
+//
+// struct script_state* st;
+//
 
-
-///////////////////////////////////////////////////////////////////////////////
 /// Returns the stack_data at the target index
 #define script_getdata(st,i) &((st)->stack->stack_data[(st)->start+(i)])
 /// Returns if the stack contains data at the target index
@@ -63,10 +64,17 @@
 #define script_lastdata(st) ( (st)->end - (st)->start - 1 )
 /// Pushes an int into the stack
 #define script_pushint(st,val) push_val((st)->stack, C_INT, (val))
-/// Returns if the stack data is a string
-#define script_isstring(data) ( (data)->type == C_STR || (data)->type == C_CONSTSTR )
-/// Returns if the stack data is an int
-#define script_isint(data) ( (data)->type == C_INT )
+
+//
+// struct script_data* data;
+//
+
+/// Returns if the script data is a string
+#define data_isstring(data) ( (data)->type == C_STR || (data)->type == C_CONSTSTR )
+/// Returns if the script data is an int
+#define data_isint(data) ( (data)->type == C_INT )
+/// Returns if the script data is a reference
+#define data_isreference(data) ( (data)->type == C_NAME )
 
 #define FETCH(n, t) \
 		if( script_hasdata(st,n) ) \
@@ -1567,15 +1575,16 @@ static void add_buildin_func(void)
 	int i,n;
 	const char* p;
 	for( i=0; buildin_func[i].func; i++ ){
-		/// arg must follow the pattern: (v|s|i|l)*\?*\*?
-		/// 'v' - value (either string or int)
-		/// 's' - string
-		/// 'i' - int
-		/// 'l' - label
-		/// '?' - one optional parameter
-		/// '*' - unknown number of optional parameters
+		// arg must follow the pattern: (v|s|i|r|l)*\?*\*?
+		// 'v' - value (either string or int or reference)
+		// 's' - string
+		// 'i' - int
+		// 'r' - reference (of a variable)
+		// 'l' - label
+		// '?' - one optional parameter
+		// '*' - unknown number of optional parameters
 		p=buildin_func[i].arg;
-		while( *p == 'v' || *p == 's' || *p == 'i' || *p == 'l' ) ++p;
+		while( *p == 'v' || *p == 's' || *p == 'i' || *p == 'r' || *p == 'l' ) ++p;
 		while( *p == '?' ) ++p;
 		if( *p == '*' ) ++p;
 		if( *p != 0){
@@ -3355,6 +3364,7 @@ static int do_final_userfunc_sub (DBKey key,void *data,va_list ap)
  */
 int do_final_script()
 {
+#ifdef DEBUG_RUN
 	if (battle_config.etc_log)
 	{
 		FILE *fp = fopen("hash_dump.txt","wt");
@@ -3408,6 +3418,7 @@ int do_final_script()
 			fclose(fp);
 		}
 	}
+#endif
 
 	if(mapreg_dirty>=0)
 		script_save_mapreg();
@@ -4138,7 +4149,7 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(sleep,"i"),
 	BUILDIN_DEF(sleep2,"i"),
 	BUILDIN_DEF(awake,"s"),
-	BUILDIN_DEF(getvariableofnpc,"is"),
+	BUILDIN_DEF(getvariableofnpc,"rs"),
 	// [blackhole89] -->
 	BUILDIN_DEF(warpportal,"iisii"),
 	// <--- [blackhole89]
@@ -5346,7 +5357,7 @@ BUILDIN_FUNC(getitem)
 
 	data=script_getdata(st,2);
 	get_val(st,data);
-	if( script_isstring(data) )
+	if( data_isstring(data) )
 	{// "<item name>"
 		const char *name=conv_str(st,data);
 		struct item_data *item_data = itemdb_searchname(name);
@@ -5356,7 +5367,7 @@ BUILDIN_FUNC(getitem)
 			return 1; //No item created.
 		}
 		nameid=item_data->nameid;
-	} else if( script_isint(data) )
+	} else if( data_isint(data) )
 	{// <item id>
 		nameid=conv_num(st,data);
 		//Violet Box, Blue Box, etc - random item pick
@@ -9665,10 +9676,10 @@ BUILDIN_FUNC(guardian)
 	} else if( script_hasdata(st,8) ){
 		data=script_getdata(st,8);
 		get_val(st,data);
-		if( script_isstring(data) )
+		if( data_isstring(data) )
 		{// "<event label>"
 			evt=conv_str(st,script_getdata(st,8));
-		} else if( script_isint(data) )
+		} else if( data_isint(data) )
 		{// <guardian index>
 			guardian=conv_num(st,script_getdata(st,8));
 		} else {
@@ -12860,63 +12871,84 @@ BUILDIN_FUNC(awake)
 	return 0;
 }
 
-// getvariableofnpc(<param>, <npc name>);
+/// Returns a reference to a variable of the target NPC.
+/// Returns 0 if an error occurs.
+///
+/// getvariableofnpc(<variable>, "<npc name>") -> <reference>
 BUILDIN_FUNC(getvariableofnpc)
 {
-	if( st->stack->stack_data[st->start+2].type != C_NAME ) {
-		// 第一引数が変数名じゃない
-		printf("getvariableofnpc: param not name\n");
-		push_val(st->stack,C_INT,0);
-	} else {
-		int num = st->stack->stack_data[st->start+2].u.num;
-		char *var_name = str_buf+str_data[num&0x00ffffff].str;
-		char *npc_name = conv_str(st,& (st->stack->stack_data[st->start+3]));
-		struct npc_data *nd = npc_name2id(npc_name);
-		if( var_name[0] != '.' || var_name[1] == '@' ) {
-			// ' 変数以外はダメ
-			printf("getvariableofnpc: invalid scope %s\n", var_name);
-			push_val(st->stack,C_INT,0);
-		} else if( nd == NULL || nd->bl.subtype != SCRIPT || !nd->u.scr.script) {
-			// NPC が見つからない or SCRIPT以外のNPC
-			printf("getvariableofnpc: can't find npc %s\n", npc_name);
-			push_val(st->stack,C_INT,0);
-		} else {
-			push_val2(st->stack,C_NAME,num, &nd->u.scr.script->script_vars );
+	struct script_data* data;
+
+	data = script_getdata(st,2);
+	if( !data_isreference(data) )
+	{// Not a reference (aka varaible name)
+		ShowError("script: getvariableofnpc: first argument is not a variable name\n");
+		st->state = END;
+		return 1;
+	}
+	else
+	{
+		int num = data->u.num;
+		char* var_name = str_buf + str_data[num&0x00ffffff].str;
+		char* npc_name = conv_str(st, script_getdata(st,3));
+		struct npc_data* nd = npc_name2id(npc_name);
+		if( var_name[0] != '.' || var_name[1] == '@' )
+		{// not a npc variable
+			ShowError("script: getvariableofnpc: invalid scope %s (not npc variable)\n", var_name);
+			st->state = END;
+			return 1;
+		}
+		else if( nd == NULL || nd->bl.subtype != SCRIPT || nd->u.scr.script == NULL )
+		{// NPC not found or has no script
+			ShowError("script: getvariableofnpc: can't find npc %s\n", npc_name);
+			st->state = END;
+			return 1;
+		}
+		else
+		{// push variable reference
+			push_val2(st->stack, C_NAME, num, &nd->u.scr.script->script_vars );
 		}
 	}
 	return 0;
 }
 
-// [blackhole89] --->
-
-// Set a warp portal.
+/// Opens a warp portal.
+/// Has no "portal opening" effect/sound, it opens the portal immediately.
+///
+/// warpportal(<src x>,<src y>,"<target map>",<target x>,<target y>);
+///
+/// @author blackhole89
 BUILDIN_FUNC(warpportal)
 {
-	struct skill_unit_group *group;
+	int spx;
+	int spy;
 	unsigned short mapindex;
-	long spx,spy,tpx,tpy;
-	struct block_list *bl=map_id2bl(st->oid);
-
-	nullpo_retr(0,bl);
+	int tpx;
+	int tpy;
+	struct skill_unit_group* group;
+	struct block_list* bl;
 
-	spx=conv_num(st, & (st->stack->stack_data[st->start+2]));
-	spy=conv_num(st, & (st->stack->stack_data[st->start+3]));
-	mapindex  = mapindex_name2id((char*)conv_str(st,& (st->stack->stack_data[st->start+4])));
-	printf("mapindex: %d\n",mapindex);
-	tpx=conv_num(st, & (st->stack->stack_data[st->start+5]));
-	tpy=conv_num(st, & (st->stack->stack_data[st->start+6]));
+	bl = map_id2bl(st->oid);
+	if( bl == NULL )
+	{
+		ShowError("script: warpportal: npc is needed");
+		return 1;
+	}
 
-	if(!mapindex) return 0;
+	spx = conv_num(st, script_getdata(st,2));
+	spy = conv_num(st, script_getdata(st,3));
+	mapindex = mapindex_name2id(conv_str(st, script_getdata(st,4)));
+	tpx = conv_num(st, script_getdata(st,5));
+	tpy = conv_num(st, script_getdata(st,6));
 
-	if((group=skill_unitsetting(bl,AL_WARP,4,spx,spy,1))==NULL) {
-		return 0;
-	}
+	if( mapindex == 0 )
+		return 0;// map not found
 
-	group->val2=(tpx<<16)|tpy;
+	group = skill_unitsetting(bl, AL_WARP, 4, spx, spy, 1);
+	if( group == NULL )
+		return 0;// failed
+	group->val2 = (tpx<<16) | tpy;
 	group->val3 = mapindex;
 
 	return 0;
 }
-
-// <-- [blackhole89]
-