Sfoglia il codice sorgente

Fix map crash from reloading after an instance is destroyed - Fixes bugreport:7883
Vending immediately fails when it cannot be used - Fixes bugreport:7894
Added script command 'addrid' - Suggestion tid:84892

Akinari1087 11 anni fa
parent
commit
6572a9fc72
4 ha cambiato i file con 141 aggiunte e 8 eliminazioni
  1. 21 1
      doc/script_commands.txt
  2. 2 7
      src/map/instance.c
  3. 108 0
      src/map/script.c
  4. 10 0
      src/map/skill.c

+ 21 - 1
doc/script_commands.txt

@@ -1,4 +1,4 @@
-//===== rAthena Documentation ================================
+//===== rAthena Documentation ================================
 //= rAthena Script Commands
 //===== By: ==================================================
 //= rAthena Dev Team
@@ -3530,6 +3530,26 @@ script was never invoked by a player.
 The command returns 0 if the player cannot be attached (if the account is offline
 or does not exist), and 1 upon success.
 
+-------------------------
+
+*addrid(<type> or <rid>{,<forced>{,<parameters>}})
+
+Allows to attach multiple RIDs to one script at a time.
+
+<type>:
+	Account ID -> attach player with acc_id if he's online. Returns 1 if player is offline, 0 if online
+	0 -> attach entire server
+	1 -> attach everyone currently on the map of the player if a player runs addrid/else of the npcs map
+	2 -> attach entire party(party id has to be entered at supportid)
+	3 -> attach entire guild(guild id has to be entered at supportid)
+	4 -> attach all players in an area at the map where the person running addrid is located/no person=use npcs map
+	Note: 4 uses addrid(4,Forced,x0,y0,x1,y1)
+	
+
+<forced>:
+	0 or left out -> force attachment of the player even if he runs a script already
+	1 -> don't attach if player is currently running a script(only needed when you use things like mes"" close next so it seems
+
 ---------------------------------------
 
 *rid2name(<rid>)

+ 2 - 7
src/map/instance.c

@@ -473,14 +473,9 @@ int instance_destroy(short instance_id)
 		im->vars = NULL;
 	}
 
-	im->type = 0;
-	im->state = INSTANCE_FREE;
-	im->party_id = 0;
-	im->keep_limit = 0;
-	im->idle_limit = 0;
-	ShowInfo("[Instance] Destroyed %d.\n", instance_data[i].map);
+	ShowInfo("[Instance] Destroyed %d.\n", instance_id);
 
-	memset(instance_data[i].map, 0, sizeof(instance_data[i].map));
+	memset(&instance_data[instance_id], 0, sizeof(instance_data[instance_id]));
 
 	return 0;
 }

+ 108 - 0
src/map/script.c

@@ -10570,6 +10570,113 @@ static void script_detach_rid(struct script_state* st)
 	}
 }
 
+/*	
+	Made by digitalhamster
+	addrid(parameter{,forced{,supportid}})
+	parameter:
+	account id -> attach player with acc_id if he's online /returns 1 if he's not online, 0 if he is
+	0 -> attach entire server
+	1 -> attach everyone currently on the map of the player if a player runs addrid/else of the npcs map
+	2 -> attach entire party(party id has to be entered at supportid)
+	3 -> attach entire guild(guild id has to be entered at supportid)
+	4 -> attach all players in an area at the map where the person running addrid is located/no person=use npcs map
+	Note: 4 uses addrid(4,Forced,x0,y0,x1,y1)
+	
+
+	forced:
+	0 or left out -> force attachment of the player even if he runs a script already
+	1 -> don't attach if player is currently running a script(only needed when you use things like mes"" close next so it seems
+
+	*/
+
+static int buildin_addrid_sub(struct block_list *bl,va_list ap)
+{	
+	int forceflag;
+	struct map_session_data *sd = (TBL_PC *)bl;
+	struct script_state* st;
+
+	st=va_arg(ap,struct script_state*);
+	forceflag=va_arg(ap,int);
+	if(!forceflag||!sd->st)
+		if(sd->status.account_id!=st->rid)
+			run_script(st->script,st->pos,sd->status.account_id,st->oid);
+	return 0;
+}
+
+BUILDIN_FUNC(addrid)
+{	
+	struct s_mapiterator* iter;
+	struct block_list *bl;
+	TBL_PC *sd;
+	if(st->rid<1){
+		st->state = END; 
+		bl=map_id2bl(st->oid);
+	} else 
+		bl=map_id2bl(st->rid); //if run without rid it'd error,also oid if npc, else rid for map
+	iter = mapit_getallusers();
+	switch(script_getnum(st,2)){ 
+		case 0:
+			for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)){
+				if(!script_getnum(st,3)||!sd->st)
+					if(sd->status.account_id!=st->rid) //attached player already runs.
+						run_script(st->script,st->pos,sd->status.account_id,st->oid);
+			}
+			break;
+
+		case 1:
+			for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)){
+				if(!script_getnum(st,3)||!sd->st)
+					if((sd->bl.m == bl->m)&&(sd->status.account_id!=st->rid))
+						run_script(st->script,st->pos,sd->status.account_id,st->oid);
+			}
+			break;
+	
+		case 2:
+			if(script_getnum(st,4)==0){
+				script_pushint(st,1);
+				return 0;
+			}
+			for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)){
+				if(!script_getnum(st,3)||!sd->st)
+					if((sd->status.account_id!=st->rid)&&(sd->status.party_id==script_getnum(st,4))) //attached player already runs.
+						run_script(st->script,st->pos,sd->status.account_id,st->oid);
+			}
+			break;
+
+		case 3:
+			if(script_getnum(st,4)==0){
+				script_pushint(st,1); 
+				return 0;
+			}
+			for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)){
+				if(!script_getnum(st,3)||!sd->st)
+					if((sd->status.account_id!=st->rid)&&(sd->status.guild_id==script_getnum(st,4))) //attached player already runs.
+						run_script(st->script,st->pos,sd->status.account_id,st->oid);
+			}break;
+
+		case 4:
+			map_foreachinarea(buildin_addrid_sub,
+			bl->m,script_getnum(st,4),script_getnum(st,5),script_getnum(st,6),script_getnum(st,7),BL_PC,
+			st,script_getnum(st,3));//4-x0 , 5-y0 , 6-x1, 7-y1
+			break;
+
+		default:
+			if((map_id2sd(script_getnum(st,2)))==NULL){
+				script_pushint(st,1);
+				return 0;
+			} //player not online.
+			if(!script_getnum(st,3)||!map_id2sd(script_getnum(st,2))->st) {
+				run_script(st->script,st->pos,script_getnum(st,2),st->oid);
+				script_pushint(st,0);
+			}
+			return 0;
+	}  
+
+	mapit_free(iter);
+	script_pushint(st,0);
+	return 0;
+}
+
 /*==========================================
  * Attach sd char id to script and detach current one if any
  *------------------------------------------*/
@@ -17974,6 +18081,7 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(getwaitingroomstate,"i?"),
 	BUILDIN_DEF(warpwaitingpc,"sii?"),
 	BUILDIN_DEF(attachrid,"i"),
+	BUILDIN_DEF(addrid,"i?????"),
 	BUILDIN_DEF(detachrid,""),
 	BUILDIN_DEF(isloggedin,"i?"),
 	BUILDIN_DEF(setmapflagnosave,"ssii"),

+ 10 - 0
src/map/skill.c

@@ -578,6 +578,16 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
 			break;
 		case MC_VENDING:
 		case ALL_BUYING_STORE:
+			if( map[sd->bl.m].flag.novending ) {
+				clif_displaymessage (sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map"
+				clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+				return 1;
+			}
+			if( map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOVENDING) ) {
+				clif_displaymessage (sd->fd, msg_txt(sd,204)); // "You can't open a shop on this cell."
+				clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+				return 1;
+			}
 			if( npc_isnear(&sd->bl) ) {
 				// uncomment to send msg_txt.
 				//char output[150];