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
This commit is contained in:
Akinari1087
2013-07-26 03:55:28 -04:00
parent 0fba5cb4a1
commit 6572a9fc72
4 changed files with 141 additions and 8 deletions

View File

@@ -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>)

View File

@@ -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;
}

View File

@@ -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"),

View File

@@ -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];