Follow up to 22812b4

* Created a define for maximum warp attempts.
* Added SETPOS_MAX_ATTEMPTS for pc_setpos.
* Adjusted buildin_warp_sub to return enum e_setpos.
* Removed pc_randomwarp since it was just duplicate code and pc_setpos already contained the same exact functions.
* Fixed a few locations where a destination point would fail when searching for the map index.
* Added clan type to script command mapwarp.
* Adjusted various variable types to match.
Thanks to @Lemongrass3110's suggestions!
This commit is contained in:
aleos 2017-06-21 18:37:31 -04:00
parent 22812b4de3
commit e248246257
6 changed files with 85 additions and 131 deletions

View File

@ -3917,6 +3917,8 @@ There are also three special 'map names' you can use.
"Random" will warp the player randomly on the current map. "Random" will warp the player randomly on the current map.
"Save" and "SavePoint" will warp the player back to their save point. "Save" and "SavePoint" will warp the player back to their save point.
Use 0,0 as the x3/y3 values when using a special 'map name'.
See also 'warp'. See also 'warp'.
--------------------------------------- ---------------------------------------
@ -3972,8 +3974,8 @@ warpguild "prontera",x,y,Guild_ID;
*warppartner("<map name>",<x>,<y>); *warppartner("<map name>",<x>,<y>);
This function will find the invoking character's marriage partner, if any, and This function will find the invoking character's marriage partner, if any, and
warp them to the map and coordinates given. It will return 1 upon success and warp them to the map and coordinates given. It will return true upon success and
0 if the partner is not online, the character is not married, or if there's no false if the partner is not online, the character is not married, or if there's no
invoking character (no RID). 0,0 will, as usual, normally translate to random coordinates. invoking character (no RID). 0,0 will, as usual, normally translate to random coordinates.
There are also three special 'map names' you can use. There are also three special 'map names' you can use.
@ -6860,6 +6862,7 @@ Optionally, a type and ID can be specified. Available types are:
0 - Everyone 0 - Everyone
1 - Guild 1 - Guild
2 - Party 2 - Party
3 - Clan
Example: Example:

View File

@ -162,6 +162,8 @@
#define EL_CLASS_BASE 2114 #define EL_CLASS_BASE 2114
#define EL_CLASS_MAX (EL_CLASS_BASE+MAX_ELEMENTAL_CLASS-1) #define EL_CLASS_MAX (EL_CLASS_BASE+MAX_ELEMENTAL_CLASS-1)
#define MAX_WARP_ATTEMPTS 1000 /// Max amount of attempts to randomly warp a character onto valid coordinates
enum item_types { enum item_types {
IT_HEALING = 0, IT_HEALING = 0,
IT_UNKNOWN, //1 IT_UNKNOWN, //1

View File

@ -5351,19 +5351,20 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *target)
return 0; return 0;
} }
/*========================================== /**
* Set's a player position. * Set's a player position.
* @param sd * @param sd: Player's data
* @param mapindex * @param mapindex: Map index of destination
* @param x * @param x: X location
* @param y * @param y: Y location
* @param clrtype * @param clrtype: Warp type
* @return SETPOS_OK Success * @return SETPOS_OK Success
* SETPOS_MAPINDEX Invalid map index * SETPOS_MAPINDEX Invalid map index
* SETPOS_NO_MAPSERVER Map not in this map-server, and failed to locate alternate map-server. * SETPOS_NO_MAPSERVER Map not in this map-server, and failed to locate alternate map-server.
* SETPOS_AUTOTRADE Player is in autotrade state * SETPOS_AUTOTRADE Player is in autotrade state
*------------------------------------------*/ * SETPOS_MAX_ATTEMPTS Maximum number of warp attempts met
enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype) */
enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, int16 x, int16 y, clr_type clrtype)
{ {
int16 m; int16 m;
@ -5480,18 +5481,17 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
} }
if( x == 0 && y == 0 ) { // pick a random walkable cell if( x == 0 && y == 0 ) { // pick a random walkable cell
int c=0; int c = 0;
do { do {
x = rnd()%(map[m].xs-2)+1; x = rnd()%(map[m].xs-2)+1;
y = rnd()%(map[m].ys-2)+1; y = rnd()%(map[m].ys-2)+1;
c++; } while((map_getcell(m, x, y, CELL_CHKNOPASS) || (!battle_config.teleport_on_portal && npc_check_areanpc(1, m, x, y, 1))) && (c++) < MAX_WARP_ATTEMPTS);
if(c > (map[m].xs * map[m].ys)*3){ //force out if (c == MAX_WARP_ATTEMPTS) {
ShowError("pc_setpos: couldn't found a valid coordinates for player '%s' (%d:%d) on (%s), preventing warp\n", sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(mapindex)); ShowError("pc_setpos: Couldn't find valid coordinates for player '%s' (%d:%d) on (%s), preventing warp.\n", sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(mapindex));
return SETPOS_OK; //preventing warp return SETPOS_MAX_ATTEMPTS;
//break; //allow warp anyway
} }
} while(map_getcell(m,x,y,CELL_CHKNOPASS) || (!battle_config.teleport_on_portal && npc_check_areanpc(1,m,x,y,1)));
} }
if (sd->state.vending && map_getcell(m,x,y,CELL_CHKNOVENDING)) { if (sd->state.vending && map_getcell(m,x,y,CELL_CHKNOVENDING)) {
@ -5560,36 +5560,6 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
return SETPOS_OK; return SETPOS_OK;
} }
/*==========================================
* Warp player sd to random location on current map.
* May fail if no walkable cell found (1000 attempts).
* Return:
* 0 = Success
* 1,2,3 = Fail
*------------------------------------------*/
char pc_randomwarp(struct map_session_data *sd, clr_type type)
{
int x,y,i=0;
int16 m;
nullpo_ret(sd);
m=sd->bl.m;
if (map[sd->bl.m].flag.noteleport) //Teleport forbidden
return 3;
do {
x = rnd()%(map[m].xs-2)+1;
y = rnd()%(map[m].ys-2)+1;
} while((map_getcell(m,x,y,CELL_CHKNOPASS) || (!battle_config.teleport_on_portal && npc_check_areanpc(1,m,x,y,1))) && (i++) < 1000);
if (i < 1000)
return pc_setpos(sd,map[sd->bl.m].index,x,y,type);
return 3;
}
/*========================================== /*==========================================
* Records a memo point at sd's current position * Records a memo point at sd's current position
* pos - entry to replace, (-1: shift oldest entry out) * pos - entry to replace, (-1: shift oldest entry out)

View File

@ -1014,14 +1014,14 @@ void pc_clean_skilltree(struct map_session_data *sd);
enum e_setpos{ enum e_setpos{
SETPOS_OK = 0, SETPOS_OK = 0,
SETPOS_MAPINDEX = 1, SETPOS_MAPINDEX,
SETPOS_NO_MAPSERVER = 2, SETPOS_NO_MAPSERVER,
SETPOS_AUTOTRADE = 3 SETPOS_AUTOTRADE,
SETPOS_MAX_ATTEMPTS
}; };
enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype); enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, int16 x, int16 y, clr_type clrtype);
void pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y); void pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y);
char pc_randomwarp(struct map_session_data *sd,clr_type type);
bool pc_memo(struct map_session_data* sd, int pos); bool pc_memo(struct map_session_data* sd, int pos);
char pc_checkadditem(struct map_session_data *sd, unsigned short nameid, int amount); char pc_checkadditem(struct map_session_data *sd, unsigned short nameid, int amount);

View File

@ -5641,30 +5641,23 @@ BUILDIN_FUNC(rand)
* @param map: Map name/Warp type * @param map: Map name/Warp type
* @param x: X location * @param x: X location
* @param y: Y location * @param y: Y location
* @return 0 on success and failure otherwise * @return SETPOS_OK on success and failure otherwise (see pc.h::e_setpos)
*/ */
static int buildin_warp_sub(struct map_session_data *sd, const char *map, int x, int y) { static enum e_setpos buildin_warp_sub(struct map_session_data *sd, const char *map, int16 x, int16 y) {
int ret = 0; nullpo_retr(SETPOS_OK, sd);
nullpo_retr(1, sd);
if (strcmp(map, "Random") == 0) if (strcmp(map, "Random") == 0)
ret = pc_randomwarp(sd, CLR_TELEPORT); return pc_setpos(sd, sd->mapindex, 0, 0, CLR_TELEPORT);
else if (strcmp(map, "SavePoint") == 0 || strcmp(map, "Save") == 0) else if (strcmp(map, "SavePoint") == 0 || strcmp(map, "Save") == 0)
ret = pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); return pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
else { else {
int16 index = 0; int16 index;
if (!(index = mapindex_name2id(map))) if (!(index = mapindex_name2id(map)))
return 1; return SETPOS_MAPINDEX;
ret = pc_setpos(sd, index, x, y, CLR_OUTSIGHT); return pc_setpos(sd, index, x, y, CLR_OUTSIGHT);
} }
if (ret)
ShowError("buildin_warp_sub: Moving player '%s' to \"%s\",%d,%d failed.\n", sd->status.name, map, x, y);
return ret;
} }
/** /**
@ -5673,7 +5666,7 @@ static int buildin_warp_sub(struct map_session_data *sd, const char *map, int x,
*/ */
BUILDIN_FUNC(warp) BUILDIN_FUNC(warp)
{ {
int x,y; int16 x, y;
const char* str; const char* str;
struct map_session_data* sd; struct map_session_data* sd;
@ -5698,39 +5691,35 @@ BUILDIN_FUNC(warp)
*/ */
static int buildin_areawarp_sub(struct block_list *bl,va_list ap) static int buildin_areawarp_sub(struct block_list *bl,va_list ap)
{ {
int x2,y2,x3,y3; int16 x2,y2,x3,y3;
unsigned int index; unsigned int index;
const char *str; const char *str;
index = va_arg(ap,unsigned int); index = va_arg(ap,unsigned int);
x2 = va_arg(ap,int); x2 = va_arg(ap,int16);
y2 = va_arg(ap,int); y2 = va_arg(ap,int16);
x3 = va_arg(ap,int); x3 = va_arg(ap,int16);
y3 = va_arg(ap,int); y3 = va_arg(ap,int16);
str = va_arg(ap,char *); str = va_arg(ap, char *);
if (index == 0) if (x3 && y3) { // Warp within given area
pc_randomwarp((TBL_PC *)bl, CLR_TELEPORT); int16 max, tx, ty, j = 0, m;
else if(x3 && y3) {
int max, tx, ty, j = 0;
int16 m;
m = map_mapindex2mapid(index); m = map_mapindex2mapid(index);
// choose a suitable max number of attempts // choose a suitable max number of attempts
if( (max = (y3-y2+1)*(x3-x2+1)*3) > 1000 ) if( (max = (y3-y2+1)*(x3-x2+1)*3) > MAX_WARP_ATTEMPTS )
max = 1000; max = MAX_WARP_ATTEMPTS;
// find a suitable map cell // find a suitable map cell
do { do {
tx = rnd()%(x3-x2+1)+x2; tx = rnd()%(x3-x2+1)+x2;
ty = rnd()%(y3-y2+1)+y2; ty = rnd()%(y3-y2+1)+y2;
j++; } while (map_getcell(m, tx, ty, CELL_CHKNOPASS) && (j++) < max);
} while( map_getcell(m,tx,ty,CELL_CHKNOPASS) && j < max );
if (buildin_warp_sub((TBL_PC *)bl, str, tx, ty)) if (buildin_warp_sub((TBL_PC *)bl, str, tx, ty))
return 1; return 1;
} else { } else { // Warp to set location
if (buildin_warp_sub((TBL_PC *)bl, str, x2, y2)) if (buildin_warp_sub((TBL_PC *)bl, str, x2, y2))
return 1; return 1;
} }
@ -5744,7 +5733,6 @@ static int buildin_areawarp_sub(struct block_list *bl,va_list ap)
BUILDIN_FUNC(areawarp) BUILDIN_FUNC(areawarp)
{ {
int16 m, x0,y0,x1,y1, x2,y2,x3=0,y3=0; int16 m, x0,y0,x1,y1, x2,y2,x3=0,y3=0;
unsigned int index;
const char *str; const char *str;
const char *mapname; const char *mapname;
@ -5768,15 +5756,10 @@ BUILDIN_FUNC(areawarp)
} }
} }
if( (m = map_mapname2mapid(mapname)) < 0 ) if ((m = map_mapname2mapid(mapname)) < 0)
return SCRIPT_CMD_FAILURE; return SCRIPT_CMD_FAILURE;
if( strcmp(str,"Random") == 0 ) map_foreachinallarea(buildin_areawarp_sub, m, x0, y0, x1, y1, BL_PC, mapindex_name2id(str), x2, y2, x3, y3, str);
index = 0;
else if( !(index=mapindex_name2id(str)) )
return SCRIPT_CMD_FAILURE;
map_foreachinallarea(buildin_areawarp_sub, m,x0,y0,x1,y1, BL_PC, index,x2,y2,x3,y3,NULL);
return SCRIPT_CMD_SUCCESS; return SCRIPT_CMD_SUCCESS;
} }
@ -5888,7 +5871,7 @@ BUILDIN_FUNC(warpparty)
{ {
case 0: // Random case 0: // Random
if(!map[pl_sd->bl.m].flag.nowarp) if(!map[pl_sd->bl.m].flag.nowarp)
pc_randomwarp(pl_sd,CLR_TELEPORT); pc_setpos(pl_sd, pl_sd->bl.m, 0, 0, CLR_TELEPORT);
break; break;
case 1: // SavePointAll case 1: // SavePointAll
if(!map[pl_sd->bl.m].flag.noreturn) if(!map[pl_sd->bl.m].flag.noreturn)
@ -5972,7 +5955,7 @@ BUILDIN_FUNC(warpguild)
{ {
case 0: // Random case 0: // Random
if(!map[pl_sd->bl.m].flag.nowarp) if(!map[pl_sd->bl.m].flag.nowarp)
pc_randomwarp(pl_sd,CLR_TELEPORT); pc_setpos(pl_sd, pl_sd->bl.m, 0, 0, CLR_TELEPORT);
break; break;
case 1: // SavePointAll case 1: // SavePointAll
if(!map[pl_sd->bl.m].flag.noreturn) if(!map[pl_sd->bl.m].flag.noreturn)
@ -11965,10 +11948,7 @@ BUILDIN_FUNC(getwaitingroomstate)
/// warpwaitingpc "<map name>",<x>,<y>; /// warpwaitingpc "<map name>",<x>,<y>;
BUILDIN_FUNC(warpwaitingpc) BUILDIN_FUNC(warpwaitingpc)
{ {
int x; int16 x, y, i, n;
int y;
int i;
int n;
const char* map_name; const char* map_name;
struct npc_data* nd; struct npc_data* nd;
struct chat_data* cd; struct chat_data* cd;
@ -11989,10 +11969,8 @@ BUILDIN_FUNC(warpwaitingpc)
{ {
TBL_PC* sd = cd->usersd[0]; TBL_PC* sd = cd->usersd[0];
if( strcmp(map_name,"SavePoint") == 0 && map[sd->bl.m].flag.noteleport ) if ((strcmp(map_name, "SavePoint") == 0 || strcmp(map_name, "Save") == 0) && map[sd->bl.m].flag.noteleport) // Can't teleport on the current map
{// can't teleport on this map
break; break;
}
if( cd->zeny ) if( cd->zeny )
{// fee set {// fee set
@ -13154,11 +13132,12 @@ BUILDIN_FUNC(failedremovecards) {
*/ */
BUILDIN_FUNC(mapwarp) BUILDIN_FUNC(mapwarp)
{ {
int x, y, m, check_val = 0, check_ID = 0, i = 0; int16 x, y, m, type = 0, i = 0;
int type_id = 0;
struct guild *g = NULL; struct guild *g = NULL;
struct party_data *p = NULL; struct party_data *p = NULL;
struct clan *c = NULL;
const char *str, *mapname; const char *str, *mapname;
unsigned int index;
mapname = script_getstr(st, 2); mapname = script_getstr(st, 2);
str = script_getstr(st, 3); str = script_getstr(st, 3);
@ -13166,19 +13145,16 @@ BUILDIN_FUNC(mapwarp)
y = script_getnum(st, 5); y = script_getnum(st, 5);
if (script_hasdata(st, 7)){ if (script_hasdata(st, 7)){
check_val = script_getnum(st, 6); type = script_getnum(st, 6);
check_ID = script_getnum(st, 7); type_id = script_getnum(st, 7);
} }
if ((m = map_mapname2mapid(mapname)) < 0) if ((m = map_mapname2mapid(mapname)) < 0)
return SCRIPT_CMD_FAILURE; return SCRIPT_CMD_FAILURE;
if (!(index = mapindex_name2id(str))) switch (type) {
return SCRIPT_CMD_FAILURE;
switch (check_val) {
case 1: case 1:
g = guild_search(check_ID); g = guild_search(type_id);
if (g) { if (g) {
for (i = 0; i < g->max_member; i++) { for (i = 0; i < g->max_member; i++) {
if (g->member[i].sd && g->member[i].sd->bl.m == m) if (g->member[i].sd && g->member[i].sd->bl.m == m)
@ -13187,7 +13163,7 @@ BUILDIN_FUNC(mapwarp)
} }
break; break;
case 2: case 2:
p = party_search(check_ID); p = party_search(type_id);
if (p) { if (p) {
for (i = 0; i < MAX_PARTY; i++) { for (i = 0; i < MAX_PARTY; i++) {
if (p->data[i].sd && p->data[i].sd->bl.m == m) if (p->data[i].sd && p->data[i].sd->bl.m == m)
@ -13195,8 +13171,17 @@ BUILDIN_FUNC(mapwarp)
} }
} }
break; break;
case 3:
c = clan_search(type_id);
if (c) {
for (i = 0; i < MAX_CLAN; i++) {
if (c->members[i] && c->members[i]->bl.m == m)
buildin_warp_sub(c->members[i], str, x, y);
}
}
break;
default: default:
map_foreachinmap(buildin_areawarp_sub, m, BL_PC, index, x, y, 0, 0, str); map_foreachinmap(buildin_areawarp_sub, m, BL_PC, mapindex_name2id(str), x, y, 0, 0, str);
break; break;
} }
return SCRIPT_CMD_SUCCESS; return SCRIPT_CMD_SUCCESS;
@ -13370,11 +13355,9 @@ BUILDIN_FUNC(getfatherid)
*/ */
BUILDIN_FUNC(warppartner) BUILDIN_FUNC(warppartner)
{ {
int x,y; int16 x, y;
unsigned short mapindex;
const char *str; const char *str;
TBL_PC *sd; TBL_PC *sd, *p_sd;
TBL_PC *p_sd;
if(!script_rid2sd(sd) || !pc_ismarried(sd) || if(!script_rid2sd(sd) || !pc_ismarried(sd) ||
(p_sd=map_charid2sd(sd->status.partner_id)) == NULL) { (p_sd=map_charid2sd(sd->status.partner_id)) == NULL) {
@ -13386,16 +13369,12 @@ BUILDIN_FUNC(warppartner)
x=script_getnum(st,3); x=script_getnum(st,3);
y=script_getnum(st,4); y=script_getnum(st,4);
mapindex = mapindex_name2id(str); if (buildin_warp_sub(p_sd, str, x, y) == SETPOS_OK) {
if (mapindex) { script_pushint(st, true);
if (buildin_warp_sub(p_sd, str, x, y))
script_pushint(st, 0);
else {
script_pushint(st, 1);
return SCRIPT_CMD_SUCCESS; return SCRIPT_CMD_SUCCESS;
}
} else } else
script_pushint(st,0); script_pushint(st, false);
return SCRIPT_CMD_FAILURE; return SCRIPT_CMD_FAILURE;
} }

View File

@ -7531,7 +7531,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( sd->state.autocast || ( (sd->skillitem == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skill_lv == 1 ) || skill_lv == 3 ) if( sd->state.autocast || ( (sd->skillitem == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skill_lv == 1 ) || skill_lv == 3 )
{ {
if( skill_lv == 1 ) if( skill_lv == 1 )
pc_randomwarp(sd,CLR_TELEPORT); pc_setpos(sd, sd->bl.m, 0, 0, CLR_TELEPORT);
else else
pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
break; break;
@ -12303,7 +12303,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
//any kind of map change, so we need to restore it automatically //any kind of map change, so we need to restore it automatically
//bugreport:8027 //bugreport:8027
if(strcmp(mapname,"Random") == 0) if(strcmp(mapname,"Random") == 0)
pc_randomwarp(sd,CLR_TELEPORT); pc_setpos(sd, sd->bl.m, 0, 0, CLR_TELEPORT);
else if (sd->menuskill_val > 1 || skill_id == ALL_ODINS_RECALL) //Need lv2 to be able to warp here. else if (sd->menuskill_val > 1 || skill_id == ALL_ODINS_RECALL) //Need lv2 to be able to warp here.
pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
@ -13925,7 +13925,7 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns
case UNT_DIMENSIONDOOR: case UNT_DIMENSIONDOOR:
if( tsd && !map[bl->m].flag.noteleport ) if( tsd && !map[bl->m].flag.noteleport )
pc_randomwarp(tsd,CLR_TELEPORT); pc_setpos(tsd, tsd->bl.m, 0, 0, CLR_TELEPORT);
else if( bl->type == BL_MOB && battle_config.mob_warp&8 ) else if( bl->type == BL_MOB && battle_config.mob_warp&8 )
unit_warp(bl,-1,-1,-1,CLR_TELEPORT); unit_warp(bl,-1,-1,-1,CLR_TELEPORT);
break; break;