From e2482462571a0c26d4394c0cd116218f8ed3e690 Mon Sep 17 00:00:00 2001 From: aleos Date: Wed, 21 Jun 2017 18:37:31 -0400 Subject: [PATCH] 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! --- doc/script_commands.txt | 9 ++- src/common/mmo.h | 2 + src/map/pc.c | 64 ++++++-------------- src/map/pc.h | 10 ++-- src/map/script.c | 125 +++++++++++++++++----------------------- src/map/skill.c | 6 +- 6 files changed, 85 insertions(+), 131 deletions(-) diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 3f4a82af94..38951f33e6 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -3917,6 +3917,8 @@ There are also three special 'map names' you can use. "Random" will warp the player randomly on the current map. "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'. --------------------------------------- @@ -3971,9 +3973,9 @@ warpguild "prontera",x,y,Guild_ID; *warppartner("",,); -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 -0 if the partner is not online, the character is not married, or if there's no +This function will find the invoking character's marriage partner, if any, and +warp them to the map and coordinates given. It will return true upon success and +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. 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 1 - Guild 2 - Party + 3 - Clan Example: diff --git a/src/common/mmo.h b/src/common/mmo.h index 4a3c6a6c27..43ca903468 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -162,6 +162,8 @@ #define EL_CLASS_BASE 2114 #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 { IT_HEALING = 0, IT_UNKNOWN, //1 diff --git a/src/map/pc.c b/src/map/pc.c index 4b9d8e2eae..b8f6fbba3f 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -5351,19 +5351,20 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *target) return 0; } -/*========================================== +/** * Set's a player position. - * @param sd - * @param mapindex - * @param x - * @param y - * @param clrtype + * @param sd: Player's data + * @param mapindex: Map index of destination + * @param x: X location + * @param y: Y location + * @param clrtype: Warp type * @return SETPOS_OK Success * SETPOS_MAPINDEX Invalid map index * SETPOS_NO_MAPSERVER Map not in this map-server, and failed to locate alternate map-server. * SETPOS_AUTOTRADE Player is in autotrade state - *------------------------------------------*/ -enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype) + * SETPOS_MAX_ATTEMPTS Maximum number of warp attempts met + */ +enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, int16 x, int16 y, clr_type clrtype) { 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 - int c=0; + int c = 0; + do { x = rnd()%(map[m].xs-2)+1; y = rnd()%(map[m].ys-2)+1; - c++; - - if(c > (map[m].xs * map[m].ys)*3){ //force out - 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)); - return SETPOS_OK; //preventing warp - //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))); + } 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 == MAX_WARP_ATTEMPTS) { + 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_MAX_ATTEMPTS; + } } 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; } -/*========================================== - * 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 * pos - entry to replace, (-1: shift oldest entry out) diff --git a/src/map/pc.h b/src/map/pc.h index fa3303b237..2487d0c054 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -1014,14 +1014,14 @@ void pc_clean_skilltree(struct map_session_data *sd); enum e_setpos{ SETPOS_OK = 0, - SETPOS_MAPINDEX = 1, - SETPOS_NO_MAPSERVER = 2, - SETPOS_AUTOTRADE = 3 + SETPOS_MAPINDEX, + SETPOS_NO_MAPSERVER, + 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); -char pc_randomwarp(struct map_session_data *sd,clr_type type); bool pc_memo(struct map_session_data* sd, int pos); char pc_checkadditem(struct map_session_data *sd, unsigned short nameid, int amount); diff --git a/src/map/script.c b/src/map/script.c index dcd86acf1f..4db3643065 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -5641,30 +5641,23 @@ BUILDIN_FUNC(rand) * @param map: Map name/Warp type * @param x: X 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) { - int ret = 0; - - nullpo_retr(1, sd); +static enum e_setpos buildin_warp_sub(struct map_session_data *sd, const char *map, int16 x, int16 y) { + nullpo_retr(SETPOS_OK, sd); 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) - 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 { - int16 index = 0; + int16 index; 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) { - int x,y; + int16 x, y; const char* str; struct map_session_data* sd; @@ -5698,39 +5691,35 @@ BUILDIN_FUNC(warp) */ 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; const char *str; index = va_arg(ap,unsigned int); - x2 = va_arg(ap,int); - y2 = va_arg(ap,int); - x3 = va_arg(ap,int); - y3 = va_arg(ap,int); - str = va_arg(ap,char *); + x2 = va_arg(ap,int16); + y2 = va_arg(ap,int16); + x3 = va_arg(ap,int16); + y3 = va_arg(ap,int16); + str = va_arg(ap, char *); - if (index == 0) - pc_randomwarp((TBL_PC *)bl, CLR_TELEPORT); - else if(x3 && y3) { - int max, tx, ty, j = 0; - int16 m; + if (x3 && y3) { // Warp within given area + int16 max, tx, ty, j = 0, m; m = map_mapindex2mapid(index); // choose a suitable max number of attempts - if( (max = (y3-y2+1)*(x3-x2+1)*3) > 1000 ) - max = 1000; + if( (max = (y3-y2+1)*(x3-x2+1)*3) > MAX_WARP_ATTEMPTS ) + max = MAX_WARP_ATTEMPTS; // find a suitable map cell do { tx = rnd()%(x3-x2+1)+x2; 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)) return 1; - } else { + } else { // Warp to set location if (buildin_warp_sub((TBL_PC *)bl, str, x2, y2)) return 1; } @@ -5744,7 +5733,6 @@ static int buildin_areawarp_sub(struct block_list *bl,va_list ap) BUILDIN_FUNC(areawarp) { int16 m, x0,y0,x1,y1, x2,y2,x3=0,y3=0; - unsigned int index; const char *str; 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; - if( strcmp(str,"Random") == 0 ) - 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); + map_foreachinallarea(buildin_areawarp_sub, m, x0, y0, x1, y1, BL_PC, mapindex_name2id(str), x2, y2, x3, y3, str); return SCRIPT_CMD_SUCCESS; } @@ -5888,7 +5871,7 @@ BUILDIN_FUNC(warpparty) { case 0: // Random 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; case 1: // SavePointAll if(!map[pl_sd->bl.m].flag.noreturn) @@ -5972,7 +5955,7 @@ BUILDIN_FUNC(warpguild) { case 0: // Random 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; case 1: // SavePointAll if(!map[pl_sd->bl.m].flag.noreturn) @@ -11965,10 +11948,7 @@ BUILDIN_FUNC(getwaitingroomstate) /// warpwaitingpc "",,; BUILDIN_FUNC(warpwaitingpc) { - int x; - int y; - int i; - int n; + int16 x, y, i, n; const char* map_name; struct npc_data* nd; struct chat_data* cd; @@ -11989,10 +11969,8 @@ BUILDIN_FUNC(warpwaitingpc) { TBL_PC* sd = cd->usersd[0]; - if( strcmp(map_name,"SavePoint") == 0 && map[sd->bl.m].flag.noteleport ) - {// can't teleport on this map + if ((strcmp(map_name, "SavePoint") == 0 || strcmp(map_name, "Save") == 0) && map[sd->bl.m].flag.noteleport) // Can't teleport on the current map break; - } if( cd->zeny ) {// fee set @@ -13154,11 +13132,12 @@ BUILDIN_FUNC(failedremovecards) { */ 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 party_data *p = NULL; + struct clan *c = NULL; const char *str, *mapname; - unsigned int index; mapname = script_getstr(st, 2); str = script_getstr(st, 3); @@ -13166,19 +13145,16 @@ BUILDIN_FUNC(mapwarp) y = script_getnum(st, 5); if (script_hasdata(st, 7)){ - check_val = script_getnum(st, 6); - check_ID = script_getnum(st, 7); + type = script_getnum(st, 6); + type_id = script_getnum(st, 7); } if ((m = map_mapname2mapid(mapname)) < 0) return SCRIPT_CMD_FAILURE; - if (!(index = mapindex_name2id(str))) - return SCRIPT_CMD_FAILURE; - - switch (check_val) { + switch (type) { case 1: - g = guild_search(check_ID); + g = guild_search(type_id); if (g) { for (i = 0; i < g->max_member; i++) { if (g->member[i].sd && g->member[i].sd->bl.m == m) @@ -13187,7 +13163,7 @@ BUILDIN_FUNC(mapwarp) } break; case 2: - p = party_search(check_ID); + p = party_search(type_id); if (p) { for (i = 0; i < MAX_PARTY; i++) { if (p->data[i].sd && p->data[i].sd->bl.m == m) @@ -13195,8 +13171,17 @@ BUILDIN_FUNC(mapwarp) } } 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: - 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; } return SCRIPT_CMD_SUCCESS; @@ -13370,11 +13355,9 @@ BUILDIN_FUNC(getfatherid) */ BUILDIN_FUNC(warppartner) { - int x,y; - unsigned short mapindex; + int16 x, y; const char *str; - TBL_PC *sd; - TBL_PC *p_sd; + TBL_PC *sd, *p_sd; if(!script_rid2sd(sd) || !pc_ismarried(sd) || (p_sd=map_charid2sd(sd->status.partner_id)) == NULL) { @@ -13386,16 +13369,12 @@ BUILDIN_FUNC(warppartner) x=script_getnum(st,3); y=script_getnum(st,4); - mapindex = mapindex_name2id(str); - if (mapindex) { - if (buildin_warp_sub(p_sd, str, x, y)) - script_pushint(st, 0); - else { - script_pushint(st, 1); - return SCRIPT_CMD_SUCCESS; - } + if (buildin_warp_sub(p_sd, str, x, y) == SETPOS_OK) { + script_pushint(st, true); + return SCRIPT_CMD_SUCCESS; } else - script_pushint(st,0); + script_pushint(st, false); + return SCRIPT_CMD_FAILURE; } diff --git a/src/map/skill.c b/src/map/skill.c index b273963709..6c5b06a7e6 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -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( skill_lv == 1 ) - pc_randomwarp(sd,CLR_TELEPORT); + pc_setpos(sd, sd->bl.m, 0, 0, CLR_TELEPORT); else pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); 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 //bugreport:8027 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. 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: 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 ) unit_warp(bl,-1,-1,-1,CLR_TELEPORT); break;