Browse Source

Removed mapindex from char-server (#7533)

Converted last_point to mapname
Converted save_point to mapname
Converted memo to mapname
Converted start point to mapname
Removed default map
Converted party member to mapname
Converted maplists to mapname
Removed mapindex loading
Fixed instance loading with multiple map-servers
Fixed castle loading with multiple map-servers
Fixed battleground loading with multiple map-servers
Fixed warping between map-servers

Thanks to @aleos89 for his help!
Lemongrass3110 2 years ago
parent
commit
14cb61d598

+ 30 - 71
src/char/char.cpp

@@ -277,8 +277,10 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){
 		(p->base_exp != cp->base_exp) || (p->base_level != cp->base_level) ||
 		(p->base_exp != cp->base_exp) || (p->base_level != cp->base_level) ||
 		(p->job_level != cp->job_level) || (p->job_exp != cp->job_exp) ||
 		(p->job_level != cp->job_level) || (p->job_exp != cp->job_exp) ||
 		(p->zeny != cp->zeny) ||
 		(p->zeny != cp->zeny) ||
-		(p->last_point.map != cp->last_point.map) ||
+		( strncmp( p->last_point.map, cp->last_point.map, sizeof( p->last_point.map ) ) != 0 ) ||
 		(p->last_point.x != cp->last_point.x) || (p->last_point.y != cp->last_point.y) ||
 		(p->last_point.x != cp->last_point.x) || (p->last_point.y != cp->last_point.y) ||
+		( strncmp( p->save_point.map, cp->save_point.map, sizeof( p->save_point.map ) ) != 0 ) ||
+		( p->save_point.x != cp->save_point.x ) || ( p->save_point.y != cp->save_point.y ) ||
 		(p->max_hp != cp->max_hp) || (p->hp != cp->hp) ||
 		(p->max_hp != cp->max_hp) || (p->hp != cp->hp) ||
 		(p->max_sp != cp->max_sp) || (p->sp != cp->sp) ||
 		(p->max_sp != cp->max_sp) || (p->sp != cp->sp) ||
 		(p->status_point != cp->status_point) || (p->skill_point != cp->skill_point) ||
 		(p->status_point != cp->status_point) || (p->skill_point != cp->skill_point) ||
@@ -316,8 +318,8 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){
 			p->str, p->agi, p->vit, p->int_, p->dex, p->luk,
 			p->str, p->agi, p->vit, p->int_, p->dex, p->luk,
 			p->option, p->party_id, p->guild_id, p->pet_id, p->hom_id, p->ele_id,
 			p->option, p->party_id, p->guild_id, p->pet_id, p->hom_id, p->ele_id,
 			p->weapon, p->shield, p->head_top, p->head_mid, p->head_bottom,
 			p->weapon, p->shield, p->head_top, p->head_mid, p->head_bottom,
-			mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y,
-			mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename,
+			p->last_point.map, p->last_point.x, p->last_point.y,
+			p->save_point.map, p->save_point.x, p->save_point.y, p->rename,
 			(unsigned long)p->delete_date, // FIXME: platform-dependent size
 			(unsigned long)p->delete_date, // FIXME: platform-dependent size
 			p->robe, p->character_moves, p->font, p->uniqueitem_counter,
 			p->robe, p->character_moves, p->font, p->uniqueitem_counter,
 			p->hotkey_rowshift, p->clan_id, p->title_id, p->show_equip, p->hotkey_rowshift2,
 			p->hotkey_rowshift, p->clan_id, p->title_id, p->show_equip, p->hotkey_rowshift2,
@@ -390,11 +392,10 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){
 		StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", schema_config.memo_db);
 		StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", schema_config.memo_db);
 		for( i = 0, count = 0; i < MAX_MEMOPOINTS; ++i )
 		for( i = 0, count = 0; i < MAX_MEMOPOINTS; ++i )
 		{
 		{
-			if( p->memo_point[i].map )
-			{
+			if( strcmp( "", p->memo_point[i].map ) != 0 ){
 				if( count )
 				if( count )
 					StringBuf_AppendStr(&buf, ",");
 					StringBuf_AppendStr(&buf, ",");
-				Sql_EscapeString(sql_handle, esc_mapname, mapindex_id2name(p->memo_point[i].map));
+				Sql_EscapeString( sql_handle, esc_mapname, p->memo_point[i].map );
 				StringBuf_Printf(&buf, "('%d', '%s', '%d', '%d')", char_id, esc_mapname, p->memo_point[i].x, p->memo_point[i].y);
 				StringBuf_Printf(&buf, "('%d', '%s', '%d', '%d')", char_id, esc_mapname, p->memo_point[i].x, p->memo_point[i].y);
 				++count;
 				++count;
 			}
 			}
@@ -910,7 +911,6 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf, uint8* coun
 	SqlStmt* stmt;
 	SqlStmt* stmt;
 	struct mmo_charstatus p;
 	struct mmo_charstatus p;
 	int j = 0, i;
 	int j = 0, i;
-	char last_map[MAP_NAME_LENGTH_EXT];
 	char sex[2];
 	char sex[2];
 
 
 	stmt = SqlStmt_Malloc(sql_handle);
 	stmt = SqlStmt_Malloc(sql_handle);
@@ -970,7 +970,7 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf, uint8* coun
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT,  &p.head_top, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT,  &p.head_top, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT,  &p.head_mid, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT,  &p.head_mid, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_SHORT,  &p.head_bottom, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_SHORT,  &p.head_bottom, 0, NULL, NULL)
-	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL)
+	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_STRING, &p.last_point.map, sizeof(p.last_point.map), NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_SHORT,	&p.rename, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_SHORT,	&p.rename, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 36, SQLDT_SHORT,  &p.robe, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 36, SQLDT_SHORT,  &p.robe, 0, NULL, NULL)
@@ -1004,7 +1004,6 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf, uint8* coun
 
 
 	for( i = 0; i < MAX_CHARS && SQL_SUCCESS == SqlStmt_NextRow(stmt); i++ )
 	for( i = 0; i < MAX_CHARS && SQL_SUCCESS == SqlStmt_NextRow(stmt); i++ )
 	{
 	{
-		p.last_point.map = mapindex_name2id(last_map);
 		sd->found_char[p.slot] = p.char_id;
 		sd->found_char[p.slot] = p.char_id;
 		sd->unban_time[p.slot] = p.unban_time;
 		sd->unban_time[p.slot] = p.unban_time;
 		p.sex = char_mmo_gender(sd, &p, sex[0]);
 		p.sex = char_mmo_gender(sd, &p, sex[0]);
@@ -1029,10 +1028,7 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf, uint8* coun
 int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_everything) {
 int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_everything) {
 	int i;
 	int i;
 	SqlStmt* stmt;
 	SqlStmt* stmt;
-	char last_map[MAP_NAME_LENGTH_EXT];
-	char save_map[MAP_NAME_LENGTH_EXT];
-	char point_map[MAP_NAME_LENGTH_EXT];
-	struct point tmp_point;
+	struct s_point_str tmp_point;
 	struct s_skill tmp_skill;
 	struct s_skill tmp_skill;
 	uint16 skill_count = 0;
 	uint16 skill_count = 0;
 	struct s_friend tmp_friend;
 	struct s_friend tmp_friend;
@@ -1106,10 +1102,10 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 36, SQLDT_SHORT,  &p->head_top, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 36, SQLDT_SHORT,  &p->head_top, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 37, SQLDT_SHORT,  &p->head_mid, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 37, SQLDT_SHORT,  &p->head_mid, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 38, SQLDT_SHORT,  &p->head_bottom, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 38, SQLDT_SHORT,  &p->head_bottom, 0, NULL, NULL)
-	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 39, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL)
+	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 39, SQLDT_STRING, &p->last_point.map, sizeof(p->last_point.map), NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 40, SQLDT_SHORT,  &p->last_point.x, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 40, SQLDT_SHORT,  &p->last_point.x, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 41, SQLDT_SHORT,  &p->last_point.y, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 41, SQLDT_SHORT,  &p->last_point.y, 0, NULL, NULL)
-	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 42, SQLDT_STRING, &save_map, sizeof(save_map), NULL, NULL)
+	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 42, SQLDT_STRING, &p->save_point.map, sizeof(p->save_point.map), NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 43, SQLDT_SHORT,  &p->save_point.x, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 43, SQLDT_SHORT,  &p->save_point.x, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 44, SQLDT_SHORT,  &p->save_point.y, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 44, SQLDT_SHORT,  &p->save_point.y, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 45, SQLDT_UINT32,    &p->partner_id, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 45, SQLDT_UINT32,    &p->partner_id, 0, NULL, NULL)
@@ -1155,20 +1151,6 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev
 		return 0;
 		return 0;
 	}
 	}
 	p->sex = char_mmo_gender(NULL, p, sex[0]);
 	p->sex = char_mmo_gender(NULL, p, sex[0]);
-	p->last_point.map = mapindex_name2id(last_map);
-	p->save_point.map = mapindex_name2id(save_map);
-
-	if( p->last_point.map == 0 ) {
-		p->last_point.map = mapindex_name2id(charserv_config.default_map);
-		p->last_point.x = charserv_config.default_map_x;
-		p->last_point.y = charserv_config.default_map_y;
-	}
-
-	if( p->save_point.map == 0 ) {
-		p->save_point.map = mapindex_name2id(charserv_config.default_map);
-		p->save_point.x = charserv_config.default_map_x;
-		p->save_point.y = charserv_config.default_map_y;
-	}
 
 
 	StringBuf_Init(&msg_buf);
 	StringBuf_Init(&msg_buf);
 	StringBuf_AppendStr(&msg_buf, " status");
 	StringBuf_AppendStr(&msg_buf, " status");
@@ -1185,14 +1167,13 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev
 	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`=? ORDER by `memo_id` LIMIT %d", schema_config.memo_db, MAX_MEMOPOINTS)
 	if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`=? ORDER by `memo_id` LIMIT %d", schema_config.memo_db, MAX_MEMOPOINTS)
 	||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
 	||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0)
 	||	SQL_ERROR == SqlStmt_Execute(stmt)
 	||	SQL_ERROR == SqlStmt_Execute(stmt)
-	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &point_map, sizeof(point_map), NULL, NULL)
+	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &tmp_point.map, sizeof(tmp_point.map), NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_SHORT,  &tmp_point.x, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_SHORT,  &tmp_point.x, 0, NULL, NULL)
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT,  &tmp_point.y, 0, NULL, NULL) )
 	||	SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT,  &tmp_point.y, 0, NULL, NULL) )
 		SqlStmt_ShowDebug(stmt);
 		SqlStmt_ShowDebug(stmt);
 
 
 	for( i = 0; i < MAX_MEMOPOINTS && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i )
 	for( i = 0; i < MAX_MEMOPOINTS && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i )
 	{
 	{
-		tmp_point.map = mapindex_name2id(point_map);
 		memcpy(&p->memo_point[i], &tmp_point, sizeof(tmp_point));
 		memcpy(&p->memo_point[i], &tmp_point, sizeof(tmp_point));
 	}
 	}
 	StringBuf_AppendStr(&msg_buf, " memo");
 	StringBuf_AppendStr(&msg_buf, " memo");
@@ -1426,7 +1407,7 @@ int char_check_char_name(char * name, char * esc_name)
 int char_make_new_char( struct char_session_data* sd, char* name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style, short start_job, int sex ){
 int char_make_new_char( struct char_session_data* sd, char* name_, int str, int agi, int vit, int int_, int dex, int luk, int slot, int hair_color, int hair_style, short start_job, int sex ){
 	char name[NAME_LENGTH];
 	char name[NAME_LENGTH];
 	char esc_name[NAME_LENGTH*2+1];
 	char esc_name[NAME_LENGTH*2+1];
-	struct point tmp_start_point[MAX_STARTPOINT];
+	struct s_point_str tmp_start_point[MAX_STARTPOINT];
 	struct startitem tmp_start_items[MAX_STARTITEM];
 	struct startitem tmp_start_items[MAX_STARTITEM];
 	uint32 char_id;
 	uint32 char_id;
 	int flag, k, start_point_idx = rnd() % charserv_config.start_point_count;
 	int flag, k, start_point_idx = rnd() % charserv_config.start_point_count;
@@ -1436,9 +1417,9 @@ int char_make_new_char( struct char_session_data* sd, char* name_, int str, int
 	normalize_name(name,TRIM_CHARS);
 	normalize_name(name,TRIM_CHARS);
 	Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
 	Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
 
 
-	memset(tmp_start_point, 0, MAX_STARTPOINT * sizeof(struct point));
+	memset( tmp_start_point, 0, sizeof( tmp_start_point ) );
 	memset(tmp_start_items, 0, MAX_STARTITEM * sizeof(struct startitem));
 	memset(tmp_start_items, 0, MAX_STARTITEM * sizeof(struct startitem));
-	memcpy(tmp_start_point, charserv_config.start_point, MAX_STARTPOINT * sizeof(struct point));
+	memcpy( tmp_start_point, charserv_config.start_point, sizeof( tmp_start_point ) );
 	memcpy(tmp_start_items, charserv_config.start_items, MAX_STARTITEM * sizeof(struct startitem));
 	memcpy(tmp_start_items, charserv_config.start_items, MAX_STARTITEM * sizeof(struct startitem));
 
 
 	flag = char_check_char_name(name,esc_name);
 	flag = char_check_char_name(name,esc_name);
@@ -1524,9 +1505,9 @@ int char_make_new_char( struct char_session_data* sd, char* name_, int str, int
 
 
 	// Check for Doram based information.
 	// Check for Doram based information.
 	if (start_job == JOB_SUMMONER) { // Check for just this job for now.
 	if (start_job == JOB_SUMMONER) { // Check for just this job for now.
-		memset(tmp_start_point, 0, MAX_STARTPOINT * sizeof(struct point));
+		memset( tmp_start_point, 0, sizeof( tmp_start_point ) );
 		memset(tmp_start_items, 0, MAX_STARTITEM * sizeof(struct startitem));
 		memset(tmp_start_items, 0, MAX_STARTITEM * sizeof(struct startitem));
-		memcpy(tmp_start_point, charserv_config.start_point_doram, MAX_STARTPOINT * sizeof(struct point));
+		memcpy( tmp_start_point, charserv_config.start_point_doram, sizeof( tmp_start_point ) );
 		memcpy(tmp_start_items, charserv_config.start_items_doram, MAX_STARTITEM * sizeof(struct startitem));
 		memcpy(tmp_start_items, charserv_config.start_items_doram, MAX_STARTITEM * sizeof(struct startitem));
 		start_point_idx = rnd() % charserv_config.start_point_count_doram;
 		start_point_idx = rnd() % charserv_config.start_point_count_doram;
 	}
 	}
@@ -1538,7 +1519,7 @@ int char_make_new_char( struct char_session_data* sd, char* name_, int str, int
 		"'%d', '%d', '%s', '%d', '%d',  '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%u', '%u', '%u', '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d', '%c')",
 		"'%d', '%d', '%s', '%d', '%d',  '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%u', '%u', '%u', '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d', '%c')",
 		schema_config.char_db, sd->account_id , slot, esc_name, start_job, charserv_config.start_zeny, status_points, str, agi, vit, int_, dex, luk,
 		schema_config.char_db, sd->account_id , slot, esc_name, start_job, charserv_config.start_zeny, status_points, str, agi, vit, int_, dex, luk,
 		(40 * (100 + vit)/100) , (40 * (100 + vit)/100 ),  (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color,
 		(40 * (100 + vit)/100) , (40 * (100 + vit)/100 ),  (11 * (100 + int_)/100), (11 * (100 + int_)/100), hair_style, hair_color,
-		mapindex_id2name(tmp_start_point[start_point_idx].map), tmp_start_point[start_point_idx].x, tmp_start_point[start_point_idx].y, mapindex_id2name(tmp_start_point[start_point_idx].map), tmp_start_point[start_point_idx].x, tmp_start_point[start_point_idx].y, sex) )
+		tmp_start_point[start_point_idx].map, tmp_start_point[start_point_idx].x, tmp_start_point[start_point_idx].y, tmp_start_point[start_point_idx].map, tmp_start_point[start_point_idx].x, tmp_start_point[start_point_idx].y, sex ) )
 	{
 	{
 		Sql_ShowDebug(sql_handle);
 		Sql_ShowDebug(sql_handle);
 		return -2; //No, stop the procedure!
 		return -2; //No, stop the procedure!
@@ -1863,7 +1844,7 @@ int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p){
 	info->hairColor = (uint8)u16min( p->hair_color, UINT8_MAX );
 	info->hairColor = (uint8)u16min( p->hair_color, UINT8_MAX );
 	info->bIsChangedCharName = ( p->rename > 0 ) ? 0 : 1;
 	info->bIsChangedCharName = ( p->rename > 0 ) ? 0 : 1;
 #if (PACKETVER >= 20100720 && PACKETVER <= 20100727) || PACKETVER >= 20100803
 #if (PACKETVER >= 20100720 && PACKETVER <= 20100727) || PACKETVER >= 20100803
-	mapindex_getmapname_ext( mapindex_id2name( p->last_point.map ), info->mapName );
+	mapindex_getmapname_ext( p->last_point.map, info->mapName );
 #endif
 #endif
 #if PACKETVER >= 20100803
 #if PACKETVER >= 20100803
 #if PACKETVER_CHAR_DELETEDATE
 #if PACKETVER_CHAR_DELETEDATE
@@ -2114,16 +2095,18 @@ int char_loadName(uint32 char_id, char* name){
 
 
 // Searches for the mapserver that has a given map (and optionally ip/port, if not -1).
 // Searches for the mapserver that has a given map (and optionally ip/port, if not -1).
 // If found, returns the server's index in the 'server' array (otherwise returns -1).
 // If found, returns the server's index in the 'server' array (otherwise returns -1).
-int char_search_mapserver(unsigned short map, uint32 ip, uint16 port){
+int char_search_mapserver( const std::string& map, uint32 ip, uint16 port ){
 	for(int i = 0; i < ARRAYLENGTH(map_server); i++)
 	for(int i = 0; i < ARRAYLENGTH(map_server); i++)
 	{
 	{
 		if (session_isValid(map_server[i].fd)
 		if (session_isValid(map_server[i].fd)
 		&& (ip == (uint32)-1 || map_server[i].ip == ip)
 		&& (ip == (uint32)-1 || map_server[i].ip == ip)
 		&& (port == (uint16)-1 || map_server[i].port == port))
 		&& (port == (uint16)-1 || map_server[i].port == port))
 		{
 		{
-			for (int j = 0; map_server[i].map[j]; j++)
-				if (map_server[i].map[j] == map)
+			for( std::string& m : map_server[i].maps ){
+				if( m == map ){
 					return i;
 					return i;
+				}
+			}
 		}
 		}
 	}
 	}
 
 
@@ -2774,13 +2757,13 @@ void char_set_defaults(){
 	charserv_config.char_check_db =1;
 	charserv_config.char_check_db =1;
 
 
 	// See const.hpp to change the default values
 	// See const.hpp to change the default values
-	charserv_config.start_point[0].map = mapindex_name2id(MAP_DEFAULT_NAME); 
+	safestrncpy( charserv_config.start_point[0].map, MAP_DEFAULT_NAME, sizeof( charserv_config.start_point[0].map ) ); 
 	charserv_config.start_point[0].x = MAP_DEFAULT_X;
 	charserv_config.start_point[0].x = MAP_DEFAULT_X;
 	charserv_config.start_point[0].y = MAP_DEFAULT_Y;
 	charserv_config.start_point[0].y = MAP_DEFAULT_Y;
 	charserv_config.start_point_count = 1;
 	charserv_config.start_point_count = 1;
 
 
 #if PACKETVER >= 20151001
 #if PACKETVER >= 20151001
-	charserv_config.start_point_doram[0].map = mapindex_name2id(MAP_DEFAULT_NAME);
+	safestrncpy( charserv_config.start_point_doram[0].map, MAP_DEFAULT_NAME, sizeof( charserv_config.start_point_doram[0].map ) );
 	charserv_config.start_point_doram[0].x = MAP_DEFAULT_X;
 	charserv_config.start_point_doram[0].x = MAP_DEFAULT_X;
 	charserv_config.start_point_doram[0].y = MAP_DEFAULT_Y;
 	charserv_config.start_point_doram[0].y = MAP_DEFAULT_Y;
 	charserv_config.start_point_count_doram = 1;
 	charserv_config.start_point_count_doram = 1;
@@ -2811,10 +2794,6 @@ void char_set_defaults(){
 	charserv_config.start_zeny = 0;
 	charserv_config.start_zeny = 0;
 	charserv_config.guild_exp_rate = 100;
 	charserv_config.guild_exp_rate = 100;
 
 
-	safestrncpy(charserv_config.default_map, "prontera", MAP_NAME_LENGTH);
-	charserv_config.default_map_x = 156;
-	charserv_config.default_map_y = 191;
-
 	charserv_config.clan_remove_inactive_days = 14;
 	charserv_config.clan_remove_inactive_days = 14;
 	charserv_config.mail_return_days = 14;
 	charserv_config.mail_return_days = 14;
 	charserv_config.mail_delete_days = 14;
 	charserv_config.mail_delete_days = 14;
@@ -2836,8 +2815,7 @@ void char_set_defaults(){
  * @param start: Start point reference
  * @param start: Start point reference
  * @param count: Start point count reference
  * @param count: Start point count reference
  */
  */
-void char_config_split_startpoint(char *w1_value, char *w2_value, struct point start_point[MAX_STARTPOINT], short *count)
-{
+void char_config_split_startpoint( char* w1_value, char* w2_value, struct s_point_str start_point[MAX_STARTPOINT], short* count ){
 	char *lineitem, **fields;
 	char *lineitem, **fields;
 	int i = 0, fields_length = 3 + 1;
 	int i = 0, fields_length = 3 + 1;
 
 
@@ -2857,16 +2835,9 @@ void char_config_split_startpoint(char *w1_value, char *w2_value, struct point s
 			continue;
 			continue;
 		}
 		}
 
 
-		start_point[i].map = mapindex_name2id(fields[1]);
-		if (!start_point[i].map) {
-			ShowError("Start point %s not found in map-index cache. Setting to default location.\n", fields[1]);
-			start_point[i].map = mapindex_name2id(MAP_DEFAULT_NAME);
-			start_point[i].x = MAP_DEFAULT_X;
-			start_point[i].y = MAP_DEFAULT_Y;
-		} else {
-			start_point[i].x = max(0, atoi(fields[2]));
-			start_point[i].y = max(0, atoi(fields[3]));
-		}
+		safestrncpy( start_point[i].map, fields[1], sizeof( start_point[i].map ) );
+		start_point[i].x = max( 0, atoi( fields[2] ) );
+		start_point[i].y = max( 0, atoi( fields[3] ) );
 		(*count)++;
 		(*count)++;
 
 
 		lineitem = strtok(NULL, ":"); //next lineitem
 		lineitem = strtok(NULL, ":"); //next lineitem
@@ -3098,12 +3069,6 @@ bool char_config_read(const char* cfgName, bool normal){
 			charserv_config.charmove_config.char_moves_unlimited = config_switch(w2);
 			charserv_config.charmove_config.char_moves_unlimited = config_switch(w2);
 		} else if (strcmpi(w1, "char_checkdb") == 0) {
 		} else if (strcmpi(w1, "char_checkdb") == 0) {
 			charserv_config.char_check_db = config_switch(w2);
 			charserv_config.char_check_db = config_switch(w2);
-		} else if (strcmpi(w1, "default_map") == 0) {
-			safestrncpy(charserv_config.default_map, w2, MAP_NAME_LENGTH);
-		} else if (strcmpi(w1, "default_map_x") == 0) {
-			charserv_config.default_map_x = atoi(w2);
-		} else if (strcmpi(w1, "default_map_y") == 0) {
-			charserv_config.default_map_y = atoi(w2);
 		} else if (strcmpi(w1, "clan_remove_inactive_days") == 0) {
 		} else if (strcmpi(w1, "clan_remove_inactive_days") == 0) {
 			charserv_config.clan_remove_inactive_days = atoi(w2);
 			charserv_config.clan_remove_inactive_days = atoi(w2);
 		} else if (strcmpi(w1, "mail_return_days") == 0) {
 		} else if (strcmpi(w1, "mail_return_days") == 0) {
@@ -3176,7 +3141,6 @@ void CharacterServer::finalize(){
 	}
 	}
 
 
 	Sql_Free(sql_handle);
 	Sql_Free(sql_handle);
-	mapindex_final();
 
 
 	ShowStatus("Finished.\n");
 	ShowStatus("Finished.\n");
 }
 }
@@ -3191,9 +3155,6 @@ void CharacterServer::handle_shutdown(){
 }
 }
 
 
 bool CharacterServer::initialize( int argc, char *argv[] ){
 bool CharacterServer::initialize( int argc, char *argv[] ){
-	//Read map indexes
-	mapindex_init();
-
 	// Init default value
 	// Init default value
 	CHAR_CONF_NAME =   "conf/char_athena.conf";
 	CHAR_CONF_NAME =   "conf/char_athena.conf";
 	LAN_CONF_NAME =    "conf/subnet_athena.conf";
 	LAN_CONF_NAME =    "conf/subnet_athena.conf";
@@ -3295,8 +3256,6 @@ bool CharacterServer::initialize( int argc, char *argv[] ){
 	}
 	}
 
 
 	do_init_chcnslif();
 	do_init_chcnslif();
-	mapindex_check_mapdefault(charserv_config.default_map);
-	ShowInfo("Default map: '" CL_WHITE "%s %d,%d" CL_RESET "'\n", charserv_config.default_map, charserv_config.default_map_x, charserv_config.default_map_y);
 
 
 	ShowStatus("The char-server is " CL_GREEN "ready" CL_RESET " (Server is listening on the port %d).\n\n", charserv_config.char_port);
 	ShowStatus("The char-server is " CL_GREEN "ready" CL_RESET " (Server is listening on the port %d).\n\n", charserv_config.char_port);
 
 

+ 3 - 7
src/char/char.hpp

@@ -186,7 +186,7 @@ struct CharServ_Config {
 	int log_inter;	// loggin inter or not [devil]
 	int log_inter;	// loggin inter or not [devil]
 	int char_check_db;	///cheking sql-table at begining ?
 	int char_check_db;	///cheking sql-table at begining ?
 
 
-	struct point start_point[MAX_STARTPOINT], start_point_doram[MAX_STARTPOINT]; // Initial position the player will spawn on the server
+	struct s_point_str start_point[MAX_STARTPOINT], start_point_doram[MAX_STARTPOINT]; // Initial position the player will spawn on the server
 	short start_point_count, start_point_count_doram; // Number of positions read
 	short start_point_count, start_point_count_doram; // Number of positions read
 	struct startitem start_items[MAX_STARTITEM], start_items_doram[MAX_STARTITEM]; // Initial items the player with spawn with on the server
 	struct startitem start_items[MAX_STARTITEM], start_items_doram[MAX_STARTITEM]; // Initial items the player with spawn with on the server
 	uint32 start_status_points;
 	uint32 start_status_points;
@@ -197,10 +197,6 @@ struct CharServ_Config {
 	int start_zeny;
 	int start_zeny;
 	int guild_exp_rate;
 	int guild_exp_rate;
 
 
-	char default_map[MAP_NAME_LENGTH];
-	unsigned short default_map_x;
-	unsigned short default_map_y;
-
 	int clan_remove_inactive_days;
 	int clan_remove_inactive_days;
 	int mail_return_days;
 	int mail_return_days;
 	int mail_delete_days;
 	int mail_delete_days;
@@ -218,7 +214,7 @@ struct mmo_map_server {
 	uint32 ip;
 	uint32 ip;
 	uint16 port;
 	uint16 port;
 	int users;
 	int users;
-	std::vector<uint16> map;
+	std::vector<std::string> maps;
 };
 };
 extern struct mmo_map_server map_server[MAX_MAP_SERVERS];
 extern struct mmo_map_server map_server[MAX_MAP_SERVERS];
 
 
@@ -292,7 +288,7 @@ extern struct fame_list taekwon_fame_list[MAX_FAME_LIST];
 #define DEFAULT_AUTOSAVE_INTERVAL 300*1000
 #define DEFAULT_AUTOSAVE_INTERVAL 300*1000
 #define MAX_CHAR_BUF sizeof( struct CHARACTER_INFO ) //Max size (for WFIFOHEAD calls)
 #define MAX_CHAR_BUF sizeof( struct CHARACTER_INFO ) //Max size (for WFIFOHEAD calls)
 
 
-int char_search_mapserver(unsigned short map, uint32 ip, uint16 port);
+int char_search_mapserver( const std::string& map, uint32 ip, uint16 port );
 int char_lan_subnetcheck(uint32 ip);
 int char_lan_subnetcheck(uint32 ip);
 
 
 int char_count_users(void);
 int char_count_users(void);

+ 30 - 28
src/char/char_clif.cpp

@@ -5,6 +5,7 @@
 
 
 #include <memory>
 #include <memory>
 #include <unordered_map>
 #include <unordered_map>
+#include <vector>
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
@@ -29,6 +30,15 @@
 
 
 using namespace rathena;
 using namespace rathena;
 
 
+std::vector<struct s_point_str> accessible_maps{
+	s_point_str{ MAP_PRONTERA, 273, 354 },
+	s_point_str{ MAP_GEFFEN, 120, 100 },
+	s_point_str{ MAP_MORROC, 160, 94 },
+	s_point_str{ MAP_ALBERTA, 116, 57 },
+	s_point_str{ MAP_PAYON, 87, 117 },
+	s_point_str{ MAP_IZLUDE, 94, 103 }
+};
+
 #if PACKETVER_SUPPORTS_PINCODE
 #if PACKETVER_SUPPORTS_PINCODE
 bool pincode_allowed( char* pincode );
 bool pincode_allowed( char* pincode );
 #endif
 #endif
@@ -693,7 +703,7 @@ int chclif_parse_maplogin(int fd){
 			map_server[i].ip = ntohl(RFIFOL(fd,54));
 			map_server[i].ip = ntohl(RFIFOL(fd,54));
 			map_server[i].port = ntohs(RFIFOW(fd,58));
 			map_server[i].port = ntohs(RFIFOW(fd,58));
 			map_server[i].users = 0;
 			map_server[i].users = 0;
-			map_server[i].map = {};
+			map_server[i].maps = {};
 			session[fd]->func_parse = chmapif_parse;
 			session[fd]->func_parse = chmapif_parse;
 			session[fd]->flag.server = 1;
 			session[fd]->flag.server = 1;
 			realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
 			realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
@@ -796,7 +806,7 @@ void chclif_send_map_data( int fd, std::shared_ptr<struct mmo_charstatus> cd, ui
 	WFIFOHEAD(fd,size);
 	WFIFOHEAD(fd,size);
 	WFIFOW(fd,0) = cmd;
 	WFIFOW(fd,0) = cmd;
 	WFIFOL(fd,2) = cd->char_id;
 	WFIFOL(fd,2) = cd->char_id;
-	mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), WFIFOCP(fd,6));
+	mapindex_getmapname_ext( cd->last_point.map, WFIFOCP( fd, 6 ) );
 	uint32 subnet_map_ip = char_lan_subnetcheck(ipl); // Advanced subnet check [LuzZza]
 	uint32 subnet_map_ip = char_lan_subnetcheck(ipl); // Advanced subnet check [LuzZza]
 	WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : map_server[map_server_index].ip);
 	WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : map_server[map_server_index].ip);
 	WFIFOW(fd,26) = ntows(htons(map_server[map_server_index].port)); // [!] LE byte order here [!]
 	WFIFOW(fd,26) = ntows(htons(map_server[map_server_index].port)); // [!] LE byte order here [!]
@@ -817,7 +827,7 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){
 		int slot = RFIFOB(fd,2);
 		int slot = RFIFOB(fd,2);
 		RFIFOSKIP(fd,3);
 		RFIFOSKIP(fd,3);
 
 
-		ARR_FIND( 0, ARRAYLENGTH(map_server), server_id, session_isValid(map_server[server_id].fd) && !map_server[server_id].map.empty() );
+		ARR_FIND( 0, ARRAYLENGTH(map_server), server_id, session_isValid(map_server[server_id].fd) && !map_server[server_id].maps.empty() );
 		// Map-server not available, tell the client to wait (client wont close, char select will respawn)
 		// Map-server not available, tell the client to wait (client wont close, char select will respawn)
 		if (server_id == ARRAYLENGTH(map_server)) {
 		if (server_id == ARRAYLENGTH(map_server)) {
 			WFIFOHEAD(fd, 24);
 			WFIFOHEAD(fd, 24);
@@ -877,43 +887,35 @@ int chclif_parse_charselect(int fd, struct char_session_data* sd,uint32 ipl){
 		ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name);
 		ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name);
 
 
 		// searching map server
 		// searching map server
-		i = char_search_mapserver(cd->last_point.map, -1, -1);
+		i = char_search_mapserver( cd->last_point.map, -1, -1 );
 
 
 		// if map is not found, we check major cities
 		// if map is not found, we check major cities
-		if (i < 0 || !cd->last_point.map) {
+		if( i < 0 ){
 			unsigned short j;
 			unsigned short j;
 			//First check that there's actually a map server online.
 			//First check that there's actually a map server online.
-			ARR_FIND( 0, ARRAYLENGTH(map_server), j, session_isValid(map_server[j].fd) && !map_server[j].map.empty() );
+			ARR_FIND( 0, ARRAYLENGTH(map_server), j, session_isValid(map_server[j].fd) && !map_server[j].maps.empty() );
 			if (j == ARRAYLENGTH(map_server)) {
 			if (j == ARRAYLENGTH(map_server)) {
 				ShowInfo("Connection Closed. No map servers available.\n");
 				ShowInfo("Connection Closed. No map servers available.\n");
 				chclif_send_auth_result(fd,1); // 01 = Server closed
 				chclif_send_auth_result(fd,1); // 01 = Server closed
 				return 1;
 				return 1;
 			}
 			}
-			if ((i = char_search_mapserver((j=mapindex_name2id(MAP_PRONTERA)),-1,-1)) >= 0) {
-				cd->last_point.x = 273;
-				cd->last_point.y = 354;
-			} else if ((i = char_search_mapserver((j=mapindex_name2id(MAP_GEFFEN)),-1,-1)) >= 0) {
-				cd->last_point.x = 120;
-				cd->last_point.y = 100;
-			} else if ((i = char_search_mapserver((j=mapindex_name2id(MAP_MORROC)),-1,-1)) >= 0) {
-				cd->last_point.x = 160;
-				cd->last_point.y = 94;
-			} else if ((i = char_search_mapserver((j=mapindex_name2id(MAP_ALBERTA)),-1,-1)) >= 0) {
-				cd->last_point.x = 116;
-				cd->last_point.y = 57;
-			} else if ((i = char_search_mapserver((j=mapindex_name2id(MAP_PAYON)),-1,-1)) >= 0) {
-				cd->last_point.x = 87;
-				cd->last_point.y = 117;
-			} else if ((i = char_search_mapserver((j=mapindex_name2id(MAP_IZLUDE)),-1,-1)) >= 0) {
-				cd->last_point.x = 94;
-				cd->last_point.y = 103;
-			} else {
-				ShowInfo("Connection Closed. No map server available that has a major city, and unable to find map-server for '%s'.\n", mapindex_id2name(cd->last_point.map));
+
+			for( struct s_point_str& accessible_map : accessible_maps ){
+				i = char_search_mapserver( accessible_map.map, -1, -1 );
+
+				// Found a map-server for a map
+				if( i >= 0 ){
+					ShowWarning( "Unable to find map-server for '%s', sending to major city '%s'.\n", cd->last_point.map, accessible_map.map );
+					memcpy( &cd->last_point, &accessible_map, sizeof( cd->last_point ) );
+					break;
+				}
+			}
+
+			if( i < 0 ){
+				ShowInfo( "Connection Closed. No map server available that has a major city, and unable to find map-server for '%s'.\n", cd->last_point.map );
 				chclif_send_auth_result(fd,1); // 01 = Server closed
 				chclif_send_auth_result(fd,1); // 01 = Server closed
 				return 1;
 				return 1;
 			}
 			}
-			ShowWarning("Unable to find map-server for '%s', sending to major city '%s'.\n", mapindex_id2name(cd->last_point.map), mapindex_id2name(j));
-			cd->last_point.map = j;
 		}
 		}
 
 
 		//Send NEW auth packet [Kevin]
 		//Send NEW auth packet [Kevin]

+ 1 - 1
src/char/char_logif.cpp

@@ -823,7 +823,7 @@ void chlogif_on_ready(void)
 	chlogif_send_acc_tologin(INVALID_TIMER, gettick(), 0, 0);
 	chlogif_send_acc_tologin(INVALID_TIMER, gettick(), 0, 0);
 
 
 	// if no map-server already connected, display a message...
 	// if no map-server already connected, display a message...
-	ARR_FIND( 0, ARRAYLENGTH(map_server), i, session_isValid(map_server[i].fd) && !map_server[i].map.empty() );
+	ARR_FIND( 0, ARRAYLENGTH(map_server), i, session_isValid(map_server[i].fd) && !map_server[i].maps.empty() );
 	if( i == ARRAYLENGTH(map_server) )
 	if( i == ARRAYLENGTH(map_server) )
 		ShowStatus("Awaiting maps from map-server.\n");
 		ShowStatus("Awaiting maps from map-server.\n");
 }
 }

+ 48 - 40
src/char/char_mapif.cpp

@@ -167,25 +167,21 @@ void chmapif_sendall_playercount(int users){
  * Send some misc info to new map-server.
  * Send some misc info to new map-server.
  * - Server name for whisper name
  * - Server name for whisper name
  * - Default map
  * - Default map
- * HZ 0x2afb <size>.W <status>.B <whisper name>.24B <mapname>.11B <map_x>.W <map_y>.W <server name>.24B
+ * HZ 0x2afb <size>.W <status>.B <whisper name>.24B <server name>.24B
  * @param fd
  * @param fd
  **/
  **/
 void chmapif_send_misc(int fd) {
 void chmapif_send_misc(int fd) {
 	uint16 offs = 5;
 	uint16 offs = 5;
-	unsigned char buf[45+NAME_LENGTH];
+	unsigned char buf[5+NAME_LENGTH+NAME_LENGTH];
 
 
 	memset(buf, '\0', sizeof(buf));
 	memset(buf, '\0', sizeof(buf));
 	WBUFW(buf, 0) = 0x2afb;
 	WBUFW(buf, 0) = 0x2afb;
 	// 0 succes, 1:failure
 	// 0 succes, 1:failure
 	WBUFB(buf, 4) = 0;
 	WBUFB(buf, 4) = 0;
 	// Send name for wisp to player
 	// Send name for wisp to player
-	safestrncpy( WBUFCP( buf, 5 ), charserv_config.wisp_server_name, NAME_LENGTH );
-	// Default map
-	safestrncpy( WBUFCP( buf, ( offs += NAME_LENGTH ) ), charserv_config.default_map, MAP_NAME_LENGTH ); // 29
-	WBUFW(buf, (offs+=MAP_NAME_LENGTH)) = charserv_config.default_map_x; // 41
-	WBUFW(buf, (offs+=2)) = charserv_config.default_map_y; // 43
-	offs+=2;
-	safestrncpy( WBUFCP( buf, offs ), charserv_config.server_name, sizeof( charserv_config.server_name ) ); // 45
+	safestrncpy( WBUFCP( buf, offs ), charserv_config.wisp_server_name, NAME_LENGTH );
+	offs += NAME_LENGTH;
+	safestrncpy( WBUFCP( buf, offs ), charserv_config.server_name, sizeof( charserv_config.server_name ) );
 	offs += NAME_LENGTH;
 	offs += NAME_LENGTH;
 
 
 	// Length
 	// Length
@@ -207,29 +203,31 @@ void chmapif_send_maps(int fd, int map_id, int count, unsigned char *mapbuf) {
 		ShowWarning("Map-server %d has NO maps.\n", map_id);
 		ShowWarning("Map-server %d has NO maps.\n", map_id);
 	}
 	}
 	else {
 	else {
-		unsigned char buf[16384];
+		unsigned char buf[INT16_MAX];
 		// Transmitting maps information to the other map-servers
 		// Transmitting maps information to the other map-servers
 		WBUFW(buf,0) = 0x2b04;
 		WBUFW(buf,0) = 0x2b04;
-		WBUFW(buf,2) = count * 4 + 10;
+		WBUFW( buf, 2 ) = count * MAP_NAME_LENGTH_EXT + 10;
 		WBUFL(buf,4) = htonl(map_server[map_id].ip);
 		WBUFL(buf,4) = htonl(map_server[map_id].ip);
 		WBUFW(buf,8) = htons(map_server[map_id].port);
 		WBUFW(buf,8) = htons(map_server[map_id].port);
-		memcpy(WBUFP(buf,10), mapbuf, count * 4);
+		memcpy( WBUFP( buf, 10 ), mapbuf, count * MAP_NAME_LENGTH_EXT );
 		chmapif_sendallwos(fd, buf, WBUFW(buf,2));
 		chmapif_sendallwos(fd, buf, WBUFW(buf,2));
 	}
 	}
 
 
 	// Transmitting the maps of the other map-servers to the new map-server
 	// Transmitting the maps of the other map-servers to the new map-server
 	for (x = 0; x < ARRAYLENGTH(map_server); x++) {
 	for (x = 0; x < ARRAYLENGTH(map_server); x++) {
 		if (session_isValid(map_server[x].fd) && x != map_id) {
 		if (session_isValid(map_server[x].fd) && x != map_id) {
-			WFIFOHEAD(fd,10 +4*map_server[x].map.size());
+			WFIFOHEAD( fd, 10 + MAP_NAME_LENGTH_EXT * map_server[x].maps.size() );
 			WFIFOW(fd,0) = 0x2b04;
 			WFIFOW(fd,0) = 0x2b04;
 			WFIFOL(fd,4) = htonl(map_server[x].ip);
 			WFIFOL(fd,4) = htonl(map_server[x].ip);
 			WFIFOW(fd,8) = htons(map_server[x].port);
 			WFIFOW(fd,8) = htons(map_server[x].port);
 			uint16 j = 0;
 			uint16 j = 0;
-			for(size_t i = 0; i < map_server[x].map.size(); i++)
-				if (map_server[x].map[i])
-					WFIFOW(fd,10+(j++)*4) = map_server[x].map[i];
+			for( std::string& map : map_server[x].maps ){
+				safestrncpy( WFIFOCP( fd, 10 + j * MAP_NAME_LENGTH_EXT ), map.c_str(), MAP_NAME_LENGTH_EXT );
+				j++;
+			}
+
 			if (j > 0) {
 			if (j > 0) {
-				WFIFOW(fd,2) = j * 4 + 10;
+				WFIFOW( fd, 2 ) = j * MAP_NAME_LENGTH_EXT + 10;
 				WFIFOSET(fd,WFIFOW(fd,2));
 				WFIFOSET(fd,WFIFOW(fd,2));
 			}
 			}
 		}
 		}
@@ -252,20 +250,26 @@ int chmapif_parse_getmapname(int fd, int id){
 		return 0;
 		return 0;
 
 
 	//Retain what map-index that map-serv contains
 	//Retain what map-index that map-serv contains
-	map_server[id].map = {};
-	for(i = 4; i < RFIFOW(fd,2); i += 4)
-		map_server[id].map.push_back(RFIFOW(fd, i));
+	map_server[id].maps.clear();
+
+	for( int i = 4; i < RFIFOW( fd, 2 ); i += MAP_NAME_LENGTH_EXT ){
+		char mapname[MAP_NAME_LENGTH_EXT];
+
+		safestrncpy( mapname, RFIFOCP( fd, i ), sizeof( mapname ) );
+
+		map_server[id].maps.push_back( mapname );
+	}
 
 
 	mapbuf = RFIFOP(fd,4);
 	mapbuf = RFIFOP(fd,4);
 	RFIFOSKIP(fd,RFIFOW(fd,2));
 	RFIFOSKIP(fd,RFIFOW(fd,2));
 
 
 	ShowStatus("Map-Server %d connected: %" PRIuPTR " maps, from IP %d.%d.%d.%d port %d.\n",
 	ShowStatus("Map-Server %d connected: %" PRIuPTR " maps, from IP %d.%d.%d.%d port %d.\n",
-				id, map_server[id].map.size(), CONVIP(map_server[id].ip), map_server[id].port);
+				id, map_server[id].maps.size(), CONVIP(map_server[id].ip), map_server[id].port);
 	ShowStatus("Map-server %d loading complete.\n", id);
 	ShowStatus("Map-server %d loading complete.\n", id);
 
 
 	chmapif_send_misc(fd);
 	chmapif_send_misc(fd);
 	chmapif_send_fame_list(fd); //Send fame list.
 	chmapif_send_fame_list(fd); //Send fame list.
-	chmapif_send_maps(fd, id, map_server[id].map.size(), mapbuf);
+	chmapif_send_maps(fd, id, map_server[id].maps.size(), mapbuf);
 
 
 	return 1;
 	return 1;
 }
 }
@@ -589,12 +593,13 @@ int chmapif_parse_req_skillcooldown(int fd){
  * @param nok : 0=accepted or no=1
  * @param nok : 0=accepted or no=1
  */
  */
 void chmapif_changemapserv_ack(int fd, bool nok){
 void chmapif_changemapserv_ack(int fd, bool nok){
-    WFIFOHEAD(fd,30);
+	// TODO: Refactor... You crazy *** [Lemongrass]
+    WFIFOHEAD( fd, 28 + MAP_NAME_LENGTH_EXT );
     WFIFOW(fd,0) = 0x2b06;
     WFIFOW(fd,0) = 0x2b06;
-    memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28);
+    memcpy( WFIFOP( fd, 2 ), RFIFOP( fd, 2 ), 26 + MAP_NAME_LENGTH_EXT );
     if(nok) 
     if(nok) 
 	WFIFOL(fd,6) = 0; //Set login1 to 0.(not ok)
 	WFIFOL(fd,6) = 0; //Set login1 to 0.(not ok)
-    WFIFOSET(fd,30);
+    WFIFOSET( fd, 28 + MAP_NAME_LENGTH_EXT );
 }
 }
 
 
 /**
 /**
@@ -603,13 +608,15 @@ void chmapif_changemapserv_ack(int fd, bool nok){
  * @return : 0 not enough data received, 1 success
  * @return : 0 not enough data received, 1 success
  */
  */
 int chmapif_parse_reqchangemapserv(int fd){
 int chmapif_parse_reqchangemapserv(int fd){
-	if (RFIFOREST(fd) < 39)
+	if( RFIFOREST( fd ) < ( 37 + MAP_NAME_LENGTH_EXT ) ){
 		return 0;
 		return 0;
+	}
 	else {
 	else {
 		int map_id, map_fd = -1;
 		int map_id, map_fd = -1;
 		struct mmo_charstatus char_dat;
 		struct mmo_charstatus char_dat;
+		int offset = 18 + MAP_NAME_LENGTH_EXT;
 
 
-		map_id = char_search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port.
+		map_id = char_search_mapserver( RFIFOCP( fd, 18 ), ntohl( RFIFOL( fd, offset + 4 ) ), ntohs( RFIFOW( fd, offset + 8 ) ) ); //Locate mapserver by ip and port.
 		if (map_id >= 0)
 		if (map_id >= 0)
 			map_fd = map_server[map_id].fd;
 			map_fd = map_server[map_id].fd;
 
 
@@ -631,10 +638,10 @@ int chmapif_parse_reqchangemapserv(int fd){
 			uint32 aid = RFIFOL( fd, 2 );
 			uint32 aid = RFIFOL( fd, 2 );
 
 
 			//Update the "last map" as this is where the player must be spawned on the new map server.
 			//Update the "last map" as this is where the player must be spawned on the new map server.
-			char_data->last_point.map = RFIFOW(fd,18);
-			char_data->last_point.x = RFIFOW(fd,20);
-			char_data->last_point.y = RFIFOW(fd,22);
-			char_data->sex = RFIFOB(fd,30);
+			safestrncpy( char_data->last_point.map, RFIFOCP( fd, 18 ), MAP_NAME_LENGTH_EXT );
+			char_data->last_point.x = RFIFOW( fd, offset + 0 );
+			char_data->last_point.y = RFIFOW( fd, offset + 2 );
+			char_data->sex = RFIFOB( fd, offset + 10 );
 
 
 			// create temporary auth entry
 			// create temporary auth entry
 			std::shared_ptr<struct auth_node> node = std::make_shared<struct auth_node>();
 			std::shared_ptr<struct auth_node> node = std::make_shared<struct auth_node>();
@@ -643,10 +650,10 @@ int chmapif_parse_reqchangemapserv(int fd){
 			node->char_id = char_id;
 			node->char_id = char_id;
 			node->login_id1 = RFIFOL(fd,6);
 			node->login_id1 = RFIFOL(fd,6);
 			node->login_id2 = RFIFOL(fd,10);
 			node->login_id2 = RFIFOL(fd,10);
-			node->sex = RFIFOB(fd,30);
+			node->sex = char_data->sex;
 			node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing)
 			node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing)
-			node->ip = ntohl(RFIFOL(fd,31));
-			node->group_id = RFIFOL(fd,35);
+			node->ip = ntohl( RFIFOL( fd, offset + 11 ) );
+			node->group_id = RFIFOL( fd, offset + 15 );
 			node->changing_mapservers = 1;
 			node->changing_mapservers = 1;
 
 
 			char_get_authdb()[node->account_id] = node;
 			char_get_authdb()[node->account_id] = node;
@@ -665,7 +672,7 @@ int chmapif_parse_reqchangemapserv(int fd){
 		} else { //Reply with nak
 		} else { //Reply with nak
 			chmapif_changemapserv_ack(fd,1);
 			chmapif_changemapserv_ack(fd,1);
 		}
 		}
-		RFIFOSKIP(fd,39);
+		RFIFOSKIP( fd, 37 + MAP_NAME_LENGTH_EXT );
 	}
 	}
 	return 1;
 	return 1;
 }
 }
@@ -1503,18 +1510,19 @@ void do_init_chmapif(void){
  */
  */
 void chmapif_server_reset(int id){
 void chmapif_server_reset(int id){
 	int j = 0;
 	int j = 0;
-	unsigned char buf[16384];
+	unsigned char buf[INT16_MAX];
 	int fd = map_server[id].fd;
 	int fd = map_server[id].fd;
 
 
 	//Notify other map servers that this one is gone. [Skotlex]
 	//Notify other map servers that this one is gone. [Skotlex]
 	WBUFW(buf,0) = 0x2b20;
 	WBUFW(buf,0) = 0x2b20;
 	WBUFL(buf,4) = htonl(map_server[id].ip);
 	WBUFL(buf,4) = htonl(map_server[id].ip);
 	WBUFW(buf,8) = htons(map_server[id].port);
 	WBUFW(buf,8) = htons(map_server[id].port);
-	for(size_t i = 0; i < map_server[id].map.size(); i++)
-		if (map_server[id].map[i])
-			WBUFW(buf,10+(j++)*4) = map_server[id].map[i];
+	for( std::string& map : map_server[id].maps ){
+		safestrncpy( WBUFCP( buf, 10 + j * MAP_NAME_LENGTH_EXT ), map.c_str(), MAP_NAME_LENGTH_EXT );
+		j++;
+	}
 	if (j > 0) {
 	if (j > 0) {
-		WBUFW(buf,2) = j * 4 + 10;
+		WBUFW(buf,2) = j * MAP_NAME_LENGTH_EXT + 10;
 		chmapif_sendallwos(fd, buf, WBUFW(buf,2));
 		chmapif_sendallwos(fd, buf, WBUFW(buf,2));
 	}
 	}
 
 

+ 18 - 14
src/char/int_party.cpp

@@ -11,7 +11,6 @@
 
 
 #include "../common/cbasetypes.hpp"
 #include "../common/cbasetypes.hpp"
 #include "../common/malloc.hpp"
 #include "../common/malloc.hpp"
-#include "../common/mapindex.hpp"
 #include "../common/mmo.hpp"
 #include "../common/mmo.hpp"
 #include "../common/showmsg.hpp"
 #include "../common/showmsg.hpp"
 #include "../common/socket.hpp"
 #include "../common/socket.hpp"
@@ -244,7 +243,7 @@ std::shared_ptr<struct party_data> inter_party_fromsql( int party_id ){
 		Sql_GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data);
 		Sql_GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data);
 		Sql_GetData(sql_handle, 2, &data, &len); memcpy(m->name, data, zmin(len, NAME_LENGTH));
 		Sql_GetData(sql_handle, 2, &data, &len); memcpy(m->name, data, zmin(len, NAME_LENGTH));
 		Sql_GetData(sql_handle, 3, &data, NULL); m->lv = atoi(data);
 		Sql_GetData(sql_handle, 3, &data, NULL); m->lv = atoi(data);
-		Sql_GetData(sql_handle, 4, &data, NULL); m->map = mapindex_name2id(data);
+		Sql_GetData(sql_handle, 4, &data, &len); memcpy(m->map, data, zmin(len, sizeof(m->map)));
 		Sql_GetData(sql_handle, 5, &data, NULL); m->online = (atoi(data) ? 1 : 0);
 		Sql_GetData(sql_handle, 5, &data, NULL); m->online = (atoi(data) ? 1 : 0);
 		Sql_GetData(sql_handle, 6, &data, NULL); m->class_ = atoi(data);
 		Sql_GetData(sql_handle, 6, &data, NULL); m->class_ = atoi(data);
 		m->leader = (m->account_id == leader_id && m->char_id == leader_char ? 1 : 0);
 		m->leader = (m->account_id == leader_id && m->char_id == leader_char ? 1 : 0);
@@ -301,7 +300,7 @@ std::shared_ptr<struct party_data> search_partyname( char* str ){
 
 
 int party_check_family_share( std::shared_ptr<struct party_data> p ){
 int party_check_family_share( std::shared_ptr<struct party_data> p ){
 	int i;
 	int i;
-	unsigned short map = 0;
+	const char* map = nullptr;
 	if (!p->family)
 	if (!p->family)
 		return 0;
 		return 0;
 	for (i = 0; i < MAX_PARTY; i++) {
 	for (i = 0; i < MAX_PARTY; i++) {
@@ -311,6 +310,10 @@ int party_check_family_share( std::shared_ptr<struct party_data> p ){
 		}
 		}
 	}
 	}
 
 
+	if( map == nullptr ){
+		return 0;
+	}
+
 	for (i = 0; i < MAX_PARTY; i++) {
 	for (i = 0; i < MAX_PARTY; i++) {
 		struct party_member * mem = &(p->party.member[i]);
 		struct party_member * mem = &(p->party.member[i]);
 		if (mem->lv == 0)
 		if (mem->lv == 0)
@@ -322,7 +325,7 @@ int party_check_family_share( std::shared_ptr<struct party_data> p ){
 			//everyone should be online to share
 			//everyone should be online to share
 			return 0;
 			return 0;
 		}
 		}
-		if (mem->map != map) {
+		if( strncmp( mem->map, map, sizeof( mem->map ) ) != 0 ){
 			//everyone should be on the same map
 			//everyone should be on the same map
 			return 0;
 			return 0;
 		}
 		}
@@ -455,16 +458,18 @@ int mapif_party_withdraw(int party_id, uint32 account_id, uint32 char_id, char *
 //Party map update notification
 //Party map update notification
 int mapif_party_membermoved(struct party *p,int idx)
 int mapif_party_membermoved(struct party *p,int idx)
 {
 {
-	unsigned char buf[20];
+	unsigned char buf[17+MAP_NAME_LENGTH_EXT];
 
 
 	WBUFW(buf,0) = 0x3825;
 	WBUFW(buf,0) = 0x3825;
 	WBUFL(buf,2) = p->party_id;
 	WBUFL(buf,2) = p->party_id;
 	WBUFL(buf,6) = p->member[idx].account_id;
 	WBUFL(buf,6) = p->member[idx].account_id;
 	WBUFL(buf,10) = p->member[idx].char_id;
 	WBUFL(buf,10) = p->member[idx].char_id;
-	WBUFW(buf,14) = p->member[idx].map;
-	WBUFB(buf,16) = p->member[idx].online;
-	WBUFW(buf,17) = p->member[idx].lv;
-	chmapif_sendall(buf, 19);
+	WBUFB(buf,14) = p->member[idx].online;
+	WBUFW(buf,15) = p->member[idx].lv;
+	safestrncpy( WBUFCP( buf, 17 ), p->member[idx].map, sizeof( p->member[idx].map ) );
+
+	chmapif_sendall( buf, sizeof( buf ) );
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -679,8 +684,7 @@ int mapif_parse_PartyLeave(int fd, int party_id, uint32 account_id, uint32 char_
 	return 0;
 	return 0;
 }
 }
 // When member goes to other map or levels up.
 // When member goes to other map or levels up.
-int mapif_parse_PartyChangeMap(int fd, int party_id, uint32 account_id, uint32 char_id, unsigned short map, int online, unsigned int lv)
-{
+int mapif_parse_PartyChangeMap( int fd, int party_id, uint32 account_id, uint32 char_id, int online, unsigned int lv, const char* map ){
 	int i;
 	int i;
 
 
 	std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
 	std::shared_ptr<struct party_data> p = inter_party_fromsql( party_id );
@@ -729,8 +733,8 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, uint32 account_id, uint32 c
 		//since they do nothing with it.
 		//since they do nothing with it.
 	}
 	}
 
 
-	if (p->party.member[i].map != map) {
-		p->party.member[i].map = map;
+	if( strncmp( p->party.member[i].map, map, sizeof( p->party.member[i].map ) ) != 0 ){
+		safestrncpy( p->party.member[i].map, map, sizeof( p->party.member[i].map ) );
 		mapif_party_membermoved(&p->party, i);
 		mapif_party_membermoved(&p->party, i);
 		int_party_check_lv(p);
 		int_party_check_lv(p);
 	}
 	}
@@ -814,7 +818,7 @@ int inter_party_parse_frommap(int fd)
 	case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,4), (struct party_member*)RFIFOP(fd,8)); break;
 	case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,4), (struct party_member*)RFIFOP(fd,8)); break;
 	case 0x3023: mapif_parse_PartyChangeOption(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOW(fd,10), RFIFOW(fd,12)); break;
 	case 0x3023: mapif_parse_PartyChangeOption(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOW(fd,10), RFIFOW(fd,12)); break;
 	case 0x3024: mapif_parse_PartyLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOCP(fd,14), (enum e_party_member_withdraw)RFIFOB(fd,14+NAME_LENGTH)); break;
 	case 0x3024: mapif_parse_PartyLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOCP(fd,14), (enum e_party_member_withdraw)RFIFOB(fd,14+NAME_LENGTH)); break;
-	case 0x3025: mapif_parse_PartyChangeMap(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOW(fd,14), RFIFOB(fd,16), RFIFOW(fd,17)); break;
+	case 0x3025: mapif_parse_PartyChangeMap( fd, RFIFOL( fd, 2 ), RFIFOL( fd, 6 ), RFIFOL( fd, 10 ), RFIFOB( fd, 14 ), RFIFOW( fd, 15 ), RFIFOCP( fd, 17 ) ); break;
 	case 0x3026: mapif_parse_BreakParty(fd, RFIFOL(fd,2)); break;
 	case 0x3026: mapif_parse_BreakParty(fd, RFIFOL(fd,2)); break;
 	case 0x3027: mapif_parse_PartyMessage(fd, RFIFOL(fd,4), RFIFOL(fd,8), RFIFOCP(fd,12), RFIFOW(fd,2)-12); break;
 	case 0x3027: mapif_parse_PartyMessage(fd, RFIFOL(fd,4), RFIFOL(fd,8), RFIFOCP(fd,12), RFIFOW(fd,2)-12); break;
 	case 0x3029: mapif_parse_PartyLeaderChange(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;
 	case 0x3029: mapif_parse_PartyLeaderChange(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;

+ 1 - 1
src/char/inter.cpp

@@ -58,7 +58,7 @@ unsigned int party_share_level = 10;
 int inter_recv_packet_length[] = {
 int inter_recv_packet_length[] = {
 	-1,-1, 7,-1, -1,13,36, (2+4+4+4+1+NAME_LENGTH),  0,-1, 0, 0,  0, 0,  0, 0,	// 3000-
 	-1,-1, 7,-1, -1,13,36, (2+4+4+4+1+NAME_LENGTH),  0,-1, 0, 0,  0, 0,  0, 0,	// 3000-
 	 6,-1, 0, 0,  0, 0, 0, 0, 10,-1, 0, 0,  0, 0,  0, 0,	// 3010-
 	 6,-1, 0, 0,  0, 0, 0, 0, 10,-1, 0, 0,  0, 0,  0, 0,	// 3010-
-	-1,10,-1,14, 15+NAME_LENGTH,19, 6,-1, 14,14, 6, 0,  0, 0,  0, 0,	// 3020- Party
+	-1,10,-1,14, 15+NAME_LENGTH,17+MAP_NAME_LENGTH_EXT, 6,-1, 14,14, 6, 0,  0, 0,  0, 0,	// 3020- Party
 	-1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1,	// 3030-
 	-1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1,	// 3030-
 	-1, 9,10, 0,  0, 0, 0, 0,  8, 6,11,10, 10,-1,6+NAME_LENGTH, 0,	// 3040-
 	-1, 9,10, 0,  0, 0, 0, 0,  8, 6,11,10, 10,-1,6+NAME_LENGTH, 0,	// 3040-
 	-1,-1,10,10,  0,-1,12, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3050-  Auction System [Zephyrus]
 	-1,-1,10,10,  0,-1,12, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3050-  Auction System [Zephyrus]

+ 9 - 2
src/common/mmo.hpp

@@ -363,6 +363,11 @@ struct point {
 	uint16 x,y;
 	uint16 x,y;
 };
 };
 
 
+struct s_point_str{
+	char map[MAP_NAME_LENGTH_EXT];
+	uint16 x,y;
+};
+
 struct startitem {
 struct startitem {
 	t_itemid nameid;
 	t_itemid nameid;
 	unsigned short amount;
 	unsigned short amount;
@@ -589,7 +594,9 @@ struct mmo_charstatus {
 	uint32 mapip;
 	uint32 mapip;
 	uint16 mapport;
 	uint16 mapport;
 
 
-	struct point last_point,save_point,memo_point[MAX_MEMOPOINTS];
+	struct s_point_str last_point;
+	struct s_point_str save_point;
+	struct s_point_str memo_point[MAX_MEMOPOINTS];
 	struct s_skill skill[MAX_SKILL];
 	struct s_skill skill[MAX_SKILL];
 
 
 	struct s_friend friends[MAX_FRIENDS]; //New friend system [Skotlex]
 	struct s_friend friends[MAX_FRIENDS]; //New friend system [Skotlex]
@@ -684,7 +691,7 @@ struct party_member {
 	uint32 char_id;
 	uint32 char_id;
 	char name[NAME_LENGTH];
 	char name[NAME_LENGTH];
 	unsigned short class_;
 	unsigned short class_;
-	unsigned short map;
+	char map[MAP_NAME_LENGTH_EXT];
 	unsigned short lv;
 	unsigned short lv;
 	unsigned leader : 1,
 	unsigned leader : 1,
 	         online : 1;
 	         online : 1;

+ 8 - 8
src/map/atcommand.cpp

@@ -962,13 +962,13 @@ ACMD_FUNC(save)
 /*==========================================
 /*==========================================
  *
  *
  *------------------------------------------*/
  *------------------------------------------*/
-ACMD_FUNC(load)
-{
-	int16 m;
-
+ACMD_FUNC(load){
 	nullpo_retr(-1, sd);
 	nullpo_retr(-1, sd);
 
 
-	m = map_mapindex2mapid(sd->status.save_point.map);
+	uint16 mapindex = mapindex_name2id( sd->status.save_point.map );
+
+	int16 m = map_mapindex2mapid( mapindex );
+
 	if (m >= 0 && map_getmapflag(m, MF_NOWARPTO) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
 	if (m >= 0 && map_getmapflag(m, MF_NOWARPTO) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
 		clif_displaymessage(fd, msg_txt(sd,249));	// You are not authorized to warp to your save map.
 		clif_displaymessage(fd, msg_txt(sd,249));	// You are not authorized to warp to your save map.
 		return -1;
 		return -1;
@@ -978,7 +978,7 @@ ACMD_FUNC(load)
 		return -1;
 		return -1;
 	}
 	}
 
 
-	pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_OUTSIGHT);
+	pc_setpos( sd, mapindex, sd->status.save_point.x, sd->status.save_point.y, CLR_OUTSIGHT );
 	clif_displaymessage(fd, msg_txt(sd,7)); // Warping to save point..
 	clif_displaymessage(fd, msg_txt(sd,7)); // Warping to save point..
 
 
 	return 0;
 	return 0;
@@ -2580,8 +2580,8 @@ ACMD_FUNC(memo)
 		clif_displaymessage(sd->fd,  msg_txt(sd,668)); // Your actual memo positions are:
 		clif_displaymessage(sd->fd,  msg_txt(sd,668)); // Your actual memo positions are:
 		for( i = 0; i < MAX_MEMOPOINTS; i++ )
 		for( i = 0; i < MAX_MEMOPOINTS; i++ )
 		{
 		{
-			if( sd->status.memo_point[i].map )
-				sprintf(atcmd_output, "%d - %s (%d,%d)", i, mapindex_id2name(sd->status.memo_point[i].map), sd->status.memo_point[i].x, sd->status.memo_point[i].y);
+			if( strcmp( "", sd->status.memo_point[i].map ) != 0 )
+				sprintf( atcmd_output, "%d - %s (%d,%d)", i, sd->status.memo_point[i].map, sd->status.memo_point[i].x, sd->status.memo_point[i].y );
 			else
 			else
 				sprintf(atcmd_output, msg_txt(sd,171), i); // %d - void
 				sprintf(atcmd_output, msg_txt(sd,171), i); // %d - void
 			clif_displaymessage(sd->fd, atcmd_output);
 			clif_displaymessage(sd->fd, atcmd_output);

+ 6 - 1
src/map/battleground.cpp

@@ -261,6 +261,11 @@ uint64 BattlegroundDatabase::parseBodyNode(const ryml::NodeRef& node) {
 					this->invalidWarning(location["Map"], "Invalid battleground map name %s, skipping.\n", map_name.c_str());
 					this->invalidWarning(location["Map"], "Invalid battleground map name %s, skipping.\n", map_name.c_str());
 					return 0;
 					return 0;
 				}
 				}
+
+				if( map_mapindex2mapid( map_entry.mapindex ) < 0 ){
+					// Ignore silently, the map is on another mapserver
+					return 0;
+				}
 			}
 			}
 
 
 			if (this->nodeExists(location, "StartEvent")) {
 			if (this->nodeExists(location, "StartEvent")) {
@@ -579,7 +584,7 @@ int bg_team_leave(map_session_data *sd, bool quit, bool deserter)
 					if (member->entry_point.map != 0 && !map_getmapflag(map_mapindex2mapid(member->entry_point.map), MF_NOSAVE))
 					if (member->entry_point.map != 0 && !map_getmapflag(map_mapindex2mapid(member->entry_point.map), MF_NOSAVE))
 						pc_setpos(sd, member->entry_point.map, member->entry_point.x, member->entry_point.y, CLR_TELEPORT);
 						pc_setpos(sd, member->entry_point.map, member->entry_point.x, member->entry_point.y, CLR_TELEPORT);
 					else
 					else
-						pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); // Warp to save point if the entry map has no save flag.
+						pc_setpos( sd, mapindex_name2id( sd->status.save_point.map ), sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT ); // Warp to save point if the entry map has no save flag.
 
 
 					bgteam->members.erase(member);
 					bgteam->members.erase(member);
 					break;
 					break;

+ 28 - 47
src/map/chrif.cpp

@@ -41,7 +41,7 @@ static bool char_init_done = false; //server already initialized? Used for Inter
 
 
 static const int packet_len_table[0x3d] = { // U - used, F - free
 static const int packet_len_table[0x3d] = { // U - used, F - free
 	60, 3,-1,-1,10,-1, 6,-1,	// 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
 	60, 3,-1,-1,10,-1, 6,-1,	// 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
-	 6,-1,18, 7,-1,39,30, 10,	// 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07
+	 6,-1,18, 7,-1, -1, 28 + MAP_NAME_LENGTH_EXT, 10,	// 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07
 	 6,30, 10, -1,86, 7,44,34,	// 2b08-2b0f: U->2b08, U->2b09, U->2b0a, U->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
 	 6,30, 10, -1,86, 7,44,34,	// 2b08-2b0f: U->2b08, U->2b09, U->2b0a, U->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
 	11,10,10, 0,11, -1, 0,10,	// 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, U->2b15, F->2b16, U->2b17
 	11,10,10, 0,11, -1, 0,10,	// 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, U->2b15, F->2b16, U->2b17
 	 2,10, 2,-1,-1,-1, 2, 7,	// 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f
 	 2,10, 2,-1,-1,-1, 2, 7,	// 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f
@@ -53,7 +53,7 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
 //2af8: Outgoing, chrif_connect -> 'connect to charserver / auth @ charserver'
 //2af8: Outgoing, chrif_connect -> 'connect to charserver / auth @ charserver'
 //2af9: Incoming, chrif_connectack -> 'answer of the 2af8 login(ok / fail)'
 //2af9: Incoming, chrif_connectack -> 'answer of the 2af8 login(ok / fail)'
 //2afa: Outgoing, chrif_sendmap -> 'sending our maps'
 //2afa: Outgoing, chrif_sendmap -> 'sending our maps'
-//2afb: Incoming, chrif_sendmapack -> 'Maps received successfully / or not .. also received server name & default map'
+//2afb: Incoming, chrif_sendmapack -> 'Maps received successfully / or not .. also received server name'
 //2afc: Outgoing, chrif_scdata_request -> request sc_data for pc_authok'ed char. <- new command reuses previous one.
 //2afc: Outgoing, chrif_scdata_request -> request sc_data for pc_authok'ed char. <- new command reuses previous one.
 //2afd: Incoming, chrif_authok -> 'client authentication ok'
 //2afd: Incoming, chrif_authok -> 'client authentication ok'
 //2afe: Outgoing, send_usercount_tochar -> 'sends player count of this map server to charserver'
 //2afe: Outgoing, send_usercount_tochar -> 'sends player count of this map server to charserver'
@@ -322,20 +322,8 @@ int chrif_save(map_session_data *sd, int flag) {
 	WFIFOL(char_fd,8) = sd->status.char_id;
 	WFIFOL(char_fd,8) = sd->status.char_id;
 	WFIFOB(char_fd,12) = (flag&CSAVE_QUIT) ? 1 : 0; //Flag to tell char-server this character is quitting.
 	WFIFOB(char_fd,12) = (flag&CSAVE_QUIT) ? 1 : 0; //Flag to tell char-server this character is quitting.
 
 
-	// If the user is on a instance map, we have to fake his current position
-	if( map_getmapdata(sd->bl.m)->instance_id ){
-		struct mmo_charstatus status;
-
-		// Copy the whole status
-		memcpy( &status, &sd->status, sizeof( struct mmo_charstatus ) );
-		// Change his current position to his savepoint
-		memcpy( &status.last_point, &status.save_point, sizeof( struct point ) );
-		// Copy the copied status into the packet
-		memcpy( WFIFOP( char_fd, 13 ), &status, sizeof( struct mmo_charstatus ) );
-	} else {
-		// Copy the whole status into the packet
-		memcpy( WFIFOP( char_fd, 13 ), &sd->status, sizeof( struct mmo_charstatus ) );
-	}
+	// Copy the whole status into the packet
+	memcpy( WFIFOP( char_fd, 13 ), &sd->status, sizeof( struct mmo_charstatus ) );
 
 
 	WFIFOSET(char_fd, WFIFOW(char_fd,2));
 	WFIFOSET(char_fd, WFIFOW(char_fd,2));
 
 
@@ -380,11 +368,11 @@ int chrif_sendmap(int fd) {
 	ShowStatus("Sending maps to char server...\n");
 	ShowStatus("Sending maps to char server...\n");
 
 
 	// Sending normal maps, not instances
 	// Sending normal maps, not instances
-	WFIFOHEAD(fd, 4 + instance_start * 4);
+	WFIFOHEAD( fd, 4 + instance_start * MAP_NAME_LENGTH_EXT );
 	WFIFOW(fd,0) = 0x2afa;
 	WFIFOW(fd,0) = 0x2afa;
 	for (int i = 0; i < instance_start; i++)
 	for (int i = 0; i < instance_start; i++)
-		WFIFOW(fd, 4 + i * 4) = map[i].index;
-	WFIFOW(fd, 2) = 4 + instance_start * 4;
+		safestrncpy( WFIFOCP( fd, 4 + i * MAP_NAME_LENGTH_EXT ), map[i].name, MAP_NAME_LENGTH_EXT );
+	WFIFOW( fd, 2 ) = 4 + instance_start * MAP_NAME_LENGTH_EXT;
 	WFIFOSET(fd, WFIFOW(fd, 2));
 	WFIFOSET(fd, WFIFOW(fd, 2));
 
 
 	return 0;
 	return 0;
@@ -396,8 +384,8 @@ int chrif_recvmap(int fd) {
 	uint32 ip = ntohl(RFIFOL(fd,4));
 	uint32 ip = ntohl(RFIFOL(fd,4));
 	uint16 port = ntohs(RFIFOW(fd,8));
 	uint16 port = ntohs(RFIFOW(fd,8));
 
 
-	for(i = 10, j = 0; i < RFIFOW(fd,2); i += 4, j++) {
-		map_setipport(RFIFOW(fd,i), ip, port);
+	for( i = 10, j = 0; i < RFIFOW( fd, 2 ); i += MAP_NAME_LENGTH_EXT, j++ ){
+		map_setipport( mapindex_name2id( RFIFOCP( fd, i ) ), ip, port );
 	}
 	}
 
 
 	if (battle_config.etc_log)
 	if (battle_config.etc_log)
@@ -414,8 +402,9 @@ int chrif_removemap(int fd) {
 	uint32 ip =  RFIFOL(fd,4);
 	uint32 ip =  RFIFOL(fd,4);
 	uint16 port = RFIFOW(fd,8);
 	uint16 port = RFIFOW(fd,8);
 
 
-	for(i = 10, j = 0; i < RFIFOW(fd, 2); i += 4, j++)
-		map_eraseipport(RFIFOW(fd, i), ip, port);
+	for( i = 10, j = 0; i < RFIFOW( fd, 2 ); i += MAP_NAME_LENGTH_EXT, j++ ){
+		map_eraseipport( mapindex_name2id( RFIFOCP( fd, i ) ), ip, port );
+	}
 
 
 	other_mapserver_count--;
 	other_mapserver_count--;
 
 
@@ -441,28 +430,29 @@ int chrif_changemapserver(map_session_data* sd, uint32 ip, uint16 port) {
 
 
 	chrif_check(-1);
 	chrif_check(-1);
 
 
-	WFIFOHEAD(char_fd,39);
+	WFIFOHEAD( char_fd, 37 + MAP_NAME_LENGTH_EXT );
 	WFIFOW(char_fd, 0) = 0x2b05;
 	WFIFOW(char_fd, 0) = 0x2b05;
 	WFIFOL(char_fd, 2) = sd->bl.id;
 	WFIFOL(char_fd, 2) = sd->bl.id;
 	WFIFOL(char_fd, 6) = sd->login_id1;
 	WFIFOL(char_fd, 6) = sd->login_id1;
 	WFIFOL(char_fd,10) = sd->login_id2;
 	WFIFOL(char_fd,10) = sd->login_id2;
 	WFIFOL(char_fd,14) = sd->status.char_id;
 	WFIFOL(char_fd,14) = sd->status.char_id;
-	WFIFOW(char_fd,18) = sd->mapindex;
-	WFIFOW(char_fd,20) = sd->bl.x;
-	WFIFOW(char_fd,22) = sd->bl.y;
-	WFIFOL(char_fd,24) = htonl(ip);
-	WFIFOW(char_fd,28) = htons(port);
-	WFIFOB(char_fd,30) = sd->status.sex;
-	WFIFOL(char_fd,31) = htonl(session[sd->fd]->client_addr);
-	WFIFOL(char_fd,35) = sd->group_id;
-	WFIFOSET(char_fd,39);
+	safestrncpy( WFIFOCP( char_fd, 18 ), mapindex_id2name( sd->mapindex ), MAP_NAME_LENGTH_EXT );
+	int offset = 18 + MAP_NAME_LENGTH_EXT;
+	WFIFOW( char_fd, offset + 0 ) = sd->bl.x;
+	WFIFOW( char_fd, offset + 2 ) = sd->bl.y;
+	WFIFOL( char_fd, offset + 4 ) = htonl( ip );
+	WFIFOW( char_fd, offset + 8 ) = htons( port );
+	WFIFOB( char_fd, offset + 10 ) = sd->status.sex;
+	WFIFOL( char_fd, offset + 11 ) = htonl( session[sd->fd]->client_addr );
+	WFIFOL( char_fd, offset + 15 ) = sd->group_id;
+	WFIFOSET( char_fd, 37 + MAP_NAME_LENGTH_EXT );
 
 
 	return 0;
 	return 0;
 }
 }
 
 
 /// map-server change (mapserv) request acknowledgement (positive or negative)
 /// map-server change (mapserv) request acknowledgement (positive or negative)
-/// R 2b06 <account_id>.L <login_id1>.L <login_id2>.L <char_id>.L <map_index>.W <x>.W <y>.W <ip>.L <port>.W
-int chrif_changemapserverack(uint32 account_id, int login_id1, int login_id2, uint32 char_id, short map_index, short x, short y, uint32 ip, uint16 port) {
+/// R 2b06 <account_id>.L <login_id1>.L <login_id2>.L <char_id>.L <map>.16B <x>.W <y>.W <ip>.L <port>.W
+int chrif_changemapserverack(uint32 account_id, int login_id1, int login_id2, uint32 char_id, const char* map, short x, short y, uint32 ip, uint16 port) {
 	struct auth_node *node;
 	struct auth_node *node;
 
 
 	if ( !( node = chrif_auth_check(account_id, char_id, ST_MAPCHANGE) ) )
 	if ( !( node = chrif_auth_check(account_id, char_id, ST_MAPCHANGE) ) )
@@ -473,7 +463,7 @@ int chrif_changemapserverack(uint32 account_id, int login_id1, int login_id2, ui
 		clif_authfail_fd(node->fd, 0);
 		clif_authfail_fd(node->fd, 0);
 		chrif_char_offline(node->sd);
 		chrif_char_offline(node->sd);
 	} else
 	} else
-		clif_changemapserver(node->sd, map_index, x, y, ntohl(ip), ntohs(port));
+		clif_changemapserver(node->sd, map, x, y, ntohl(ip), ntohs(port));
 
 
 	//Player has been saved already, remove him from memory. [Skotlex]
 	//Player has been saved already, remove him from memory. [Skotlex]
 	chrif_auth_delete(account_id, char_id, ST_MAPCHANGE);
 	chrif_auth_delete(account_id, char_id, ST_MAPCHANGE);
@@ -578,7 +568,6 @@ void chrif_on_ready(void) {
 /**
 /**
  * Maps are sent, then received misc info from char-server
  * Maps are sent, then received misc info from char-server
  * - Server name
  * - Server name
- * - Default map
  * HZ 0x2afb
  * HZ 0x2afb
  **/
  **/
 int chrif_sendmapack(int fd) {
 int chrif_sendmapack(int fd) {
@@ -592,19 +581,11 @@ int chrif_sendmapack(int fd) {
 	// Whisper name
 	// Whisper name
 	safestrncpy( wisp_server_name, RFIFOCP( fd, offs ), NAME_LENGTH );
 	safestrncpy( wisp_server_name, RFIFOCP( fd, offs ), NAME_LENGTH );
 
 
-	// Default map
-	safestrncpy( map_default.mapname, RFIFOCP( fd, ( offs += NAME_LENGTH ) ), MAP_NAME_LENGTH );
-	map_default.x = RFIFOW(fd, (offs+=MAP_NAME_LENGTH));
-	map_default.y = RFIFOW(fd, (offs+=2));
-
 	// Server name
 	// Server name
-	safestrncpy( charserver_name, RFIFOCP( fd, ( offs += 2 ) ), NAME_LENGTH );
+	safestrncpy( charserver_name, RFIFOCP( fd, offs + NAME_LENGTH ), NAME_LENGTH );
 
 
 	ShowStatus( "Map-server connected to char-server '" CL_WHITE "%s" CL_RESET "' (whispername: %s).\n", charserver_name, wisp_server_name );
 	ShowStatus( "Map-server connected to char-server '" CL_WHITE "%s" CL_RESET "' (whispername: %s).\n", charserver_name, wisp_server_name );
 
 
-	if (battle_config.etc_log)
-		ShowInfo("Received default map from char-server '" CL_WHITE "%s %d,%d" CL_RESET "'.\n", map_default.mapname, map_default.x, map_default.y);
-
 	chrif_on_ready();
 	chrif_on_ready();
 
 
 	return 0;
 	return 0;
@@ -1784,7 +1765,7 @@ int chrif_parse(int fd) {
 			case 0x2b00: map_setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break;
 			case 0x2b00: map_setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break;
 			case 0x2b03: clif_charselectok(RFIFOL(fd,2), RFIFOB(fd,6)); break;
 			case 0x2b03: clif_charselectok(RFIFOL(fd,2), RFIFOB(fd,6)); break;
 			case 0x2b04: chrif_recvmap(fd); break;
 			case 0x2b04: chrif_recvmap(fd); break;
-			case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break;
+			case 0x2b06: chrif_changemapserverack( RFIFOL( fd, 2 ), RFIFOL( fd, 6 ), RFIFOL( fd, 10 ), RFIFOL( fd, 14 ), RFIFOCP( fd, 18 ), RFIFOW( fd, 18 + MAP_NAME_LENGTH_EXT ), RFIFOW( fd, 18 + MAP_NAME_LENGTH_EXT + 2 ), RFIFOL( fd, 18 + MAP_NAME_LENGTH_EXT + 4 ), RFIFOW( fd, 18 + MAP_NAME_LENGTH_EXT + 8 ) ); break;
 			case 0x2b09: map_addnickdb(RFIFOL(fd,2), RFIFOCP(fd,6)); break;
 			case 0x2b09: map_addnickdb(RFIFOL(fd,2), RFIFOCP(fd,6)); break;
 			case 0x2b0b: chrif_skillcooldown_load(fd); break;
 			case 0x2b0b: chrif_skillcooldown_load(fd); break;
 			case 0x2b0d: chrif_changedsex(fd); break;
 			case 0x2b0d: chrif_changedsex(fd); break;

+ 16 - 11
src/map/clif.cpp

@@ -2115,7 +2115,7 @@ void clif_changemap(map_session_data *sd, short m, int x, int y)
 /// Notifies the client of a position change to coordinates on given map, which is on another map-server.
 /// Notifies the client of a position change to coordinates on given map, which is on another map-server.
 /// 0092 <map name>.16B <x>.W <y>.W <ip>.L <port>.W (ZC_NPCACK_SERVERMOVE)
 /// 0092 <map name>.16B <x>.W <y>.W <ip>.L <port>.W (ZC_NPCACK_SERVERMOVE)
 /// 0ac7 <map name>.16B <x>.W <y>.W <ip>.L <port>.W <unknown>.128B (ZC_NPCACK_SERVERMOVE2)
 /// 0ac7 <map name>.16B <x>.W <y>.W <ip>.L <port>.W <unknown>.128B (ZC_NPCACK_SERVERMOVE2)
-void clif_changemapserver(map_session_data* sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port)
+void clif_changemapserver(map_session_data* sd, const char* map, int x, int y, uint32 ip, uint16 port)
 {
 {
 	int fd;
 	int fd;
 #if PACKETVER >= 20170315
 #if PACKETVER >= 20170315
@@ -2128,7 +2128,7 @@ void clif_changemapserver(map_session_data* sd, unsigned short map_index, int x,
 
 
 	WFIFOHEAD(fd,packet_len(cmd));
 	WFIFOHEAD(fd,packet_len(cmd));
 	WFIFOW(fd,0) = cmd;
 	WFIFOW(fd,0) = cmd;
-	mapindex_getmapname_ext(mapindex_id2name(map_index), WFIFOCP(fd,2));
+	mapindex_getmapname_ext( map, WFIFOCP( fd, 2 ) );
 	WFIFOW(fd,18) = x;
 	WFIFOW(fd,18) = x;
 	WFIFOW(fd,20) = y;
 	WFIFOW(fd,20) = y;
 	WFIFOL(fd,22) = htonl(ip);
 	WFIFOL(fd,22) = htonl(ip);
@@ -6245,8 +6245,7 @@ void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,i
 
 
 /// Presents a list of available warp destinations (ZC_WARPLIST).
 /// Presents a list of available warp destinations (ZC_WARPLIST).
 /// 011c <skill id>.W { <map name>.16B }*4
 /// 011c <skill id>.W { <map name>.16B }*4
-void clif_skill_warppoint(map_session_data* sd, uint16 skill_id, uint16 skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4)
-{
+void clif_skill_warppoint( map_session_data* sd, uint16 skill_id, uint16 skill_lv, const char* map1, const char* map2, const char* map3, const char* map4 ){
 	int fd;
 	int fd;
 	nullpo_retv(sd);
 	nullpo_retv(sd);
 	fd = sd->fd;
 	fd = sd->fd;
@@ -6255,12 +6254,18 @@ void clif_skill_warppoint(map_session_data* sd, uint16 skill_id, uint16 skill_lv
 	WFIFOW(fd,0) = 0x11c;
 	WFIFOW(fd,0) = 0x11c;
 	WFIFOW(fd,2) = skill_id;
 	WFIFOW(fd,2) = skill_id;
 	memset(WFIFOP(fd,4), 0x00, 4*MAP_NAME_LENGTH_EXT);
 	memset(WFIFOP(fd,4), 0x00, 4*MAP_NAME_LENGTH_EXT);
-	if (map1 == (unsigned short)-1) strcpy(WFIFOCP(fd,4), "Random");
-	else // normal map name
-	if (map1 > 0) mapindex_getmapname_ext(mapindex_id2name(map1), WFIFOCP(fd,4));
-	if (map2 > 0) mapindex_getmapname_ext(mapindex_id2name(map2), WFIFOCP(fd,20));
-	if (map3 > 0) mapindex_getmapname_ext(mapindex_id2name(map3), WFIFOCP(fd,36));
-	if (map4 > 0) mapindex_getmapname_ext(mapindex_id2name(map4), WFIFOCP(fd,52));
+	if( strcmp( "", map1 ) != 0 ){
+		mapindex_getmapname_ext( map1, WFIFOCP( fd, 4 ) );
+	}
+	if( strcmp( "", map2 ) != 0 ){
+		mapindex_getmapname_ext( map2, WFIFOCP( fd, 20 ) );
+	}
+	if( strcmp( "", map3 ) != 0 ){
+		mapindex_getmapname_ext( map3, WFIFOCP( fd, 36 ) );
+	}
+	if( strcmp( "", map4 ) != 0 ){
+		mapindex_getmapname_ext( map4, WFIFOCP( fd, 52 ) );
+	}
 	WFIFOSET(fd,packet_len(0x11c));
 	WFIFOSET(fd,packet_len(0x11c));
 
 
 	sd->menuskill_id = skill_id;
 	sd->menuskill_id = skill_id;
@@ -7979,7 +7984,7 @@ void clif_party_info( struct party_data& party, map_session_data* sd ){
 		member.GID = m.char_id;
 		member.GID = m.char_id;
 #endif
 #endif
 		safestrncpy( member.playerName, m.name, sizeof( member.playerName ) );
 		safestrncpy( member.playerName, m.name, sizeof( member.playerName ) );
-		mapindex_getmapname_ext( mapindex_id2name( m.map ), member.mapName );
+		mapindex_getmapname_ext( m.map, member.mapName );
 		member.leader = ( m.leader ) ? 0 : 1;
 		member.leader = ( m.leader ) ? 0 : 1;
 		member.offline = ( m.online ) ? 0 : 1;
 		member.offline = ( m.online ) ? 0 : 1;
 #if PACKETVER_MAIN_NUM >= 20170524 || PACKETVER_RE_NUM >= 20170502 || defined(PACKETVER_ZERO)
 #if PACKETVER_MAIN_NUM >= 20170524 || PACKETVER_RE_NUM >= 20170502 || defined(PACKETVER_ZERO)

+ 2 - 2
src/map/clif.hpp

@@ -639,7 +639,7 @@ int clif_spawn(struct block_list *bl, bool walking = false);	//area
 void clif_walkok(map_session_data *sd);	// self
 void clif_walkok(map_session_data *sd);	// self
 void clif_move(struct unit_data *ud); //area
 void clif_move(struct unit_data *ud); //area
 void clif_changemap(map_session_data *sd, short m, int x, int y);	//self
 void clif_changemap(map_session_data *sd, short m, int x, int y);	//self
-void clif_changemapserver(map_session_data* sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port);	//self
+void clif_changemapserver( map_session_data* sd, const char* map, int x, int y, uint32 ip, uint16 port );
 void clif_blown(struct block_list *bl); // area
 void clif_blown(struct block_list *bl); // area
 void clif_slide(struct block_list *bl, int x, int y); // area
 void clif_slide(struct block_list *bl, int x, int y); // area
 void clif_fixpos(struct block_list *bl);	// area
 void clif_fixpos(struct block_list *bl);	// area
@@ -746,7 +746,7 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,t_tick tick,
 bool clif_skill_nodamage(struct block_list *src,struct block_list *dst,uint16 skill_id,int heal,t_tick tick);
 bool clif_skill_nodamage(struct block_list *src,struct block_list *dst,uint16 skill_id,int heal,t_tick tick);
 void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,int y,t_tick tick);
 void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,int y,t_tick tick);
 void clif_skill_estimation(map_session_data *sd,struct block_list *dst);
 void clif_skill_estimation(map_session_data *sd,struct block_list *dst);
-void clif_skill_warppoint(map_session_data* sd, uint16 skill_id, uint16 skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4);
+void clif_skill_warppoint( map_session_data* sd, uint16 skill_id, uint16 skill_lv, const char* map1, const char* map2 = "", const char* map3 = "", const char* map4 = "" );
 void clif_skill_memomessage(map_session_data* sd, int type);
 void clif_skill_memomessage(map_session_data* sd, int type);
 void clif_skill_teleportmessage(map_session_data *sd, int type);
 void clif_skill_teleportmessage(map_session_data *sd, int type);
 void clif_skill_produce_mix_list(map_session_data *sd, int skill_id, int trigger);
 void clif_skill_produce_mix_list(map_session_data *sd, int skill_id, int trigger);

+ 8 - 8
src/map/guild.cpp

@@ -299,7 +299,7 @@ uint64 CastleDatabase::parseBodyNode(const ryml::NodeRef& node) {
 
 
 		uint16 mapindex = mapindex_name2idx(map_name.c_str(), nullptr);
 		uint16 mapindex = mapindex_name2idx(map_name.c_str(), nullptr);
 
 
-		if (map_mapindex2mapid(mapindex) < 0) {
+		if( mapindex == 0 ){
 			this->invalidWarning(node["Map"], "Map %s doesn't exist, skipping.\n", map_name.c_str());
 			this->invalidWarning(node["Map"], "Map %s doesn't exist, skipping.\n", map_name.c_str());
 			return 0;
 			return 0;
 		}
 		}
@@ -394,7 +394,8 @@ uint64 CastleDatabase::parseBodyNode(const ryml::NodeRef& node) {
 
 
 		map_data* md = map_getmapdata( map_mapindex2mapid( gc->mapindex ) );
 		map_data* md = map_getmapdata( map_mapindex2mapid( gc->mapindex ) );
 
 
-		if( warp_x >= md->xs ){
+		// If the map is on another map-server, we cannot verify the bounds
+		if( md != nullptr && warp_x >= md->xs ){
 			this->invalidWarning( node["WarpX"], "WarpX has to be smaller than %hu.\n", md->xs );
 			this->invalidWarning( node["WarpX"], "WarpX has to be smaller than %hu.\n", md->xs );
 			return 0;
 			return 0;
 		}
 		}
@@ -420,7 +421,8 @@ uint64 CastleDatabase::parseBodyNode(const ryml::NodeRef& node) {
 
 
 		map_data* md = map_getmapdata( map_mapindex2mapid( gc->mapindex ) );
 		map_data* md = map_getmapdata( map_mapindex2mapid( gc->mapindex ) );
 
 
-		if( warp_y >= md->ys ){
+		// If the map is on another map-server, we cannot verify the bounds
+		if( md != nullptr && warp_y >= md->ys ){
 			this->invalidWarning( node["WarpY"], "WarpY has to be smaller than %hu.\n", md->ys );
 			this->invalidWarning( node["WarpY"], "WarpY has to be smaller than %hu.\n", md->ys );
 			return 0;
 			return 0;
 		}
 		}
@@ -1218,11 +1220,9 @@ int guild_member_withdraw(int guild_id, uint32 account_id, uint32 char_id, int f
 		if (g->instance_id) {
 		if (g->instance_id) {
 			struct map_data *mapdata = map_getmapdata(sd->bl.m);
 			struct map_data *mapdata = map_getmapdata(sd->bl.m);
 
 
-			if (mapdata->instance_id) { // User was on the instance map
-				if (mapdata->save.map)
-					pc_setpos(sd, mapdata->save.map, mapdata->save.x, mapdata->save.y, CLR_TELEPORT);
-				else
-					pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
+			// User was on the instance map of the guild
+			if( g->instance_id == mapdata->instance_id ){
+				pc_setpos_savepoint( *sd );
 			}
 			}
 		}
 		}
 
 

+ 10 - 3
src/map/instance.cpp

@@ -167,14 +167,21 @@ uint64 InstanceDatabase::parseBodyNode(const ryml::NodeRef& node) {
 			if (!this->asString(enterNode, "Map", map))
 			if (!this->asString(enterNode, "Map", map))
 				return 0;
 				return 0;
 
 
-			int16 m = map_mapname2mapid(map.c_str());
+			uint16 mapindex = mapindex_name2idx( map.c_str(), nullptr );
 
 
-			if (m == -1) {
+			if( mapindex == 0 ){
 				this->invalidWarning(enterNode["Map"], "Map %s is not a valid map, skipping.\n", map.c_str());
 				this->invalidWarning(enterNode["Map"], "Map %s is not a valid map, skipping.\n", map.c_str());
 				return 0;
 				return 0;
 			}
 			}
 
 
-			instance->enter.map = m;
+			int16 mapid = map_mapindex2mapid( mapindex );
+
+			if( mapid < 0 ){
+				// Ignore silently, the map is on another mapserver
+				return 0;
+			}
+
+			instance->enter.map = mapid;
 		}
 		}
 
 
 		if (this->nodeExists(enterNode, "X")) {
 		if (this->nodeExists(enterNode, "X")) {

+ 7 - 7
src/map/intif.cpp

@@ -37,7 +37,7 @@
 static const int packet_len_table[] = {
 static const int packet_len_table[] = {
 	-1,-1,27,-1, -1, 0,37,-1, 10+NAME_LENGTH,-1, 0, 0,  0, 0,  0, 0, //0x3800-0x380f
 	-1,-1,27,-1, -1, 0,37,-1, 10+NAME_LENGTH,-1, 0, 0,  0, 0,  0, 0, //0x3800-0x380f
 	 0, 0, 0, 0,  0, 0, 0, 0, -1,11, 0, 0,  0, 0,  0, 0, //0x3810
 	 0, 0, 0, 0,  0, 0, 0, 0, -1,11, 0, 0,  0, 0,  0, 0, //0x3810
-	39,-1,15,15, 15+NAME_LENGTH,19, 7,-1,  0, 0, 0, 0,  0, 0,  0, 0, //0x3820
+	39,-1,15,15, 15+NAME_LENGTH,17+MAP_NAME_LENGTH_EXT, 7,-1,  0, 0, 0, 0,  0, 0,  0, 0, //0x3820
 	10,-1,15, 0, 79,19, 7,-1,  0,-1,-1,-1, 14,67,186,-1, //0x3830
 	10,-1,15, 0, 79,19, 7,-1,  0,-1,-1,-1, 14,67,186,-1, //0x3830
 	-1,10, 0,18,  0, 0, 0, 0, -1,75,-1,11, 11,-1, 38, 0, //0x3840
 	-1,10, 0,18,  0, 0, 0, 0, -1,75,-1,11, 11,-1, 38, 0, //0x3840
 	-1,-1, 7, 7,  7,11, 8,-1,  0, 0, 0, 0,  0, 0,  0, 0, //0x3850  Auctions [Zephyrus] itembound[Akinari]
 	-1,-1, 7, 7,  7,11, 8,-1,  0, 0, 0, 0,  0, 0,  0, 0, //0x3850  Auctions [Zephyrus] itembound[Akinari]
@@ -709,15 +709,15 @@ int intif_party_changemap(map_session_data *sd,int online)
 	} else
 	} else
 		mapindex = sd->mapindex;
 		mapindex = sd->mapindex;
 
 
-	WFIFOHEAD(inter_fd,19);
+	WFIFOHEAD( inter_fd, 17 + MAP_NAME_LENGTH_EXT );
 	WFIFOW(inter_fd,0)=0x3025;
 	WFIFOW(inter_fd,0)=0x3025;
 	WFIFOL(inter_fd,2)=sd->status.party_id;
 	WFIFOL(inter_fd,2)=sd->status.party_id;
 	WFIFOL(inter_fd,6)=sd->status.account_id;
 	WFIFOL(inter_fd,6)=sd->status.account_id;
 	WFIFOL(inter_fd,10)=sd->status.char_id;
 	WFIFOL(inter_fd,10)=sd->status.char_id;
-	WFIFOW(inter_fd,14)=mapindex;
-	WFIFOB(inter_fd,16)=online;
-	WFIFOW(inter_fd,17)=sd->status.base_level;
-	WFIFOSET(inter_fd,19);
+	WFIFOB(inter_fd,14)=online;
+	WFIFOW(inter_fd,15)=sd->status.base_level;
+	safestrncpy( WFIFOCP( inter_fd, 17 ), mapindex_id2name( mapindex ), MAP_NAME_LENGTH_EXT );
+	WFIFOSET( inter_fd, 17 + MAP_NAME_LENGTH_EXT );
 	return 1;
 	return 1;
 }
 }
 
 
@@ -1628,7 +1628,7 @@ int intif_parse_PartyBroken(int fd)
  */
  */
 int intif_parse_PartyMove(int fd)
 int intif_parse_PartyMove(int fd)
 {
 {
-	party_recv_movemap(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOW(fd,14),RFIFOB(fd,16),RFIFOW(fd,17));
+	party_recv_movemap( RFIFOL( fd, 2 ), RFIFOL( fd, 6 ), RFIFOL( fd, 10 ), RFIFOB( fd, 14 ), RFIFOW( fd, 15 ), RFIFOCP( fd, 17 ) );
 	return 1;
 	return 1;
 }
 }
 
 

+ 1 - 25
src/map/map.cpp

@@ -182,8 +182,6 @@ const char *MSG_CONF_NAME_THA;
 
 
 char wisp_server_name[NAME_LENGTH] = "Server"; // can be modified in char-server configuration file
 char wisp_server_name[NAME_LENGTH] = "Server"; // can be modified in char-server configuration file
 
 
-struct s_map_default map_default;
-
 int console = 0;
 int console = 0;
 int enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex]
 int enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex]
 int enable_grf = 0;	//To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89]
 int enable_grf = 0;	//To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89]
@@ -2146,23 +2144,6 @@ int map_quit(map_session_data *sd) {
 
 
 	unit_remove_map_pc(sd,CLR_RESPAWN);
 	unit_remove_map_pc(sd,CLR_RESPAWN);
 
 
-	if( mapdata->instance_id > 0 ) { // Avoid map conflicts and warnings on next login
-		int16 m;
-		struct point *pt;
-		if( mapdata->save.map )
-			pt = &mapdata->save;
-		else
-			pt = &sd->status.save_point;
-
-		if( (m=map_mapindex2mapid(pt->map)) >= 0 )
-		{
-			sd->bl.m = m;
-			sd->bl.x = pt->x;
-			sd->bl.y = pt->y;
-			sd->mapindex = pt->map;
-		}
-	}
-
 	if (sd->state.vending)
 	if (sd->state.vending)
 		idb_remove(vending_getdb(), sd->status.char_id);
 		idb_remove(vending_getdb(), sd->status.char_id);
 
 
@@ -2751,7 +2732,7 @@ static int map_instancemap_leave(struct block_list *bl, va_list ap)
 	nullpo_retr(0, bl);
 	nullpo_retr(0, bl);
 	nullpo_retr(0, sd = (map_session_data *)bl);
 	nullpo_retr(0, sd = (map_session_data *)bl);
 
 
-	pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
+	pc_setpos_savepoint( *sd );
 
 
 	return 1;
 	return 1;
 }
 }
@@ -5153,11 +5134,6 @@ bool MapServer::initialize( int argc, char *argv[] ){
 	MSG_CONF_NAME_THA = "conf/msg_conf/map_msg_tha.conf";	// Thai
 	MSG_CONF_NAME_THA = "conf/msg_conf/map_msg_tha.conf";	// Thai
 	/* Multilanguage */
 	/* Multilanguage */
 
 
-	// Default map
-	safestrncpy(map_default.mapname, "prontera", MAP_NAME_LENGTH);
-	map_default.x = 156;
-	map_default.y = 191;
-
 	// default inter_config
 	// default inter_config
 	inter_config.start_status_points = 48;
 	inter_config.start_status_points = 48;
 	inter_config.emblem_woe_change = true;
 	inter_config.emblem_woe_change = true;

+ 0 - 7
src/map/map.hpp

@@ -1051,13 +1051,6 @@ extern char channel_conf[];
 
 
 extern char wisp_server_name[];
 extern char wisp_server_name[];
 
 
-struct s_map_default {
-	char mapname[MAP_NAME_LENGTH];
-	unsigned short x;
-	unsigned short y;
-};
-extern struct s_map_default map_default;
-
 /// Type of 'save_settings'
 /// Type of 'save_settings'
 enum save_settings_type {
 enum save_settings_type {
 	CHARSAVE_NONE		= 0x000, /// Never
 	CHARSAVE_NONE		= 0x000, /// Never

+ 8 - 11
src/map/party.cpp

@@ -46,7 +46,7 @@ static void party_fill_member(struct party_member* member, map_session_data* sd,
 	member->char_id    = sd->status.char_id;
 	member->char_id    = sd->status.char_id;
 	safestrncpy(member->name, sd->status.name, NAME_LENGTH);
 	safestrncpy(member->name, sd->status.name, NAME_LENGTH);
 	member->class_     = sd->status.class_;
 	member->class_     = sd->status.class_;
-	member->map        = sd->mapindex;
+	safestrncpy( member->map, mapindex_id2name( sd->mapindex ), sizeof( member->map ) );
 	member->lv         = sd->status.base_level;
 	member->lv         = sd->status.base_level;
 	member->online     = 1;
 	member->online     = 1;
 	member->leader     = leader;
 	member->leader     = leader;
@@ -780,14 +780,12 @@ int party_member_withdraw(int party_id, uint32 account_id, uint32 char_id, char
 		clif_name_area(&sd->bl); //Update name display [Skotlex]
 		clif_name_area(&sd->bl); //Update name display [Skotlex]
 		//TODO: hp bars should be cleared too
 		//TODO: hp bars should be cleared too
 
 
-		if( p->instance_id ) {
+		if( p != nullptr && p->instance_id ){
 			struct map_data *mapdata = map_getmapdata(sd->bl.m);
 			struct map_data *mapdata = map_getmapdata(sd->bl.m);
 
 
-			if( mapdata->instance_id ) { // User was on the instance map
-				if( mapdata->save.map )
-					pc_setpos(sd, mapdata->save.map, mapdata->save.x, mapdata->save.y, CLR_TELEPORT);
-				else
-					pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
+			// User was on the instance map of the party
+			if( mapdata != nullptr && p->instance_id == mapdata->instance_id ){
+				pc_setpos_savepoint( *sd );
 			}
 			}
 		}
 		}
 	}
 	}
@@ -918,7 +916,7 @@ int party_changeleader(map_session_data *sd, map_session_data *tsd, struct party
 		if (tmi == MAX_PARTY)
 		if (tmi == MAX_PARTY)
 			return 0; // Shouldn't happen
 			return 0; // Shouldn't happen
 
 
-		if (battle_config.change_party_leader_samemap && p->party.member[mi].map != p->party.member[tmi].map) {
+		if( battle_config.change_party_leader_samemap && strncmp( p->party.member[mi].map, p->party.member[tmi].map, sizeof( p->party.member[mi].map ) ) != 0 ){
 			clif_msg(sd, PARTY_MASTER_CHANGE_SAME_MAP);
 			clif_msg(sd, PARTY_MASTER_CHANGE_SAME_MAP);
 			return 0;
 			return 0;
 		}
 		}
@@ -953,8 +951,7 @@ int party_changeleader(map_session_data *sd, map_session_data *tsd, struct party
 /// - changes maps
 /// - changes maps
 /// - logs in or out
 /// - logs in or out
 /// - gains a level (disabled)
 /// - gains a level (disabled)
-int party_recv_movemap(int party_id,uint32 account_id,uint32 char_id, unsigned short map_idx,int online,int lv)
-{
+int party_recv_movemap( int party_id, uint32 account_id, uint32 char_id, int online, int lv, const char* map ){
 	struct party_member* m;
 	struct party_member* m;
 	struct party_data* p;
 	struct party_data* p;
 	int i;
 	int i;
@@ -971,7 +968,7 @@ int party_recv_movemap(int party_id,uint32 account_id,uint32 char_id, unsigned s
 	}
 	}
 
 
 	m = &p->party.member[i];
 	m = &p->party.member[i];
-	m->map = map_idx;
+	safestrncpy( m->map, map, sizeof( m->map ) );
 	m->online = online;
 	m->online = online;
 	m->lv = lv;
 	m->lv = lv;
 	//Check if they still exist on this map server
 	//Check if they still exist on this map server

+ 1 - 1
src/map/party.hpp

@@ -79,7 +79,7 @@ int party_reply_invite(map_session_data *sd,int party_id,int flag);
 #define party_add_member(party_id,sd) party_reply_invite(sd,party_id,1)
 #define party_add_member(party_id,sd) party_reply_invite(sd,party_id,1)
 int party_recv_noinfo(int party_id, uint32 char_id);
 int party_recv_noinfo(int party_id, uint32 char_id);
 int party_recv_info(struct party* sp, uint32 char_id);
 int party_recv_info(struct party* sp, uint32 char_id);
-int party_recv_movemap(int party_id,uint32 account_id,uint32 char_id, unsigned short map,int online,int lv);
+int party_recv_movemap( int party_id, uint32 account_id, uint32 char_id, int online, int lv, const char* map );
 int party_broken(int party_id);
 int party_broken(int party_id);
 int party_optionchanged(int party_id,uint32 account_id,int exp,int item,int flag);
 int party_optionchanged(int party_id,uint32 account_id,int exp,int item,int flag);
 int party_changeoption(map_session_data *sd,int exp,int item);
 int party_changeoption(map_session_data *sd,int exp,int item);

+ 55 - 22
src/map/pc.cpp

@@ -1315,31 +1315,51 @@ void pc_makesavestatus(map_session_data *sd) {
 			sd->status.sp = sd->battle_status.sp;
 			sd->status.sp = sd->battle_status.sp;
 			sd->status.ap = sd->battle_status.ap;
 			sd->status.ap = sd->battle_status.ap;
 		}
 		}
-		sd->status.last_point.map = sd->mapindex;
+		mapindex_getmapname( mapindex_id2name( sd->mapindex ), sd->status.last_point.map );
 		sd->status.last_point.x = sd->bl.x;
 		sd->status.last_point.x = sd->bl.x;
 		sd->status.last_point.y = sd->bl.y;
 		sd->status.last_point.y = sd->bl.y;
 		return;
 		return;
 	}
 	}
 
 
-	if(pc_isdead(sd)) {
-		pc_setrestartvalue(sd, 0);
-		memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point));
-	} else {
+	if( pc_isdead( sd ) ){
+		pc_setrestartvalue( sd, 0 );
+
+		// Return to save point
+		safestrncpy( sd->status.last_point.map, sd->status.save_point.map, sizeof( sd->status.last_point.map ) );
+		sd->status.last_point.x = sd->status.save_point.x;
+		sd->status.last_point.y = sd->status.save_point.y;
+	}else{
 		sd->status.hp = sd->battle_status.hp;
 		sd->status.hp = sd->battle_status.hp;
 		sd->status.sp = sd->battle_status.sp;
 		sd->status.sp = sd->battle_status.sp;
 		sd->status.ap = sd->battle_status.ap;
 		sd->status.ap = sd->battle_status.ap;
-		sd->status.last_point.map = sd->mapindex;
-		sd->status.last_point.x = sd->bl.x;
-		sd->status.last_point.y = sd->bl.y;
-	}
 
 
-	if(map_getmapflag(sd->bl.m, MF_NOSAVE)) {
-		struct map_data *mapdata = map_getmapdata(sd->bl.m);
+		struct map_data* mapdata = map_getmapdata( sd->bl.m );
 
 
-		if(mapdata->save.map)
-			memcpy(&sd->status.last_point,&mapdata->save,sizeof(sd->status.last_point));
-		else
-			memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point));
+		// If saving is not allowed on the map, we return the player to the designated point
+		if( mapdata->flag[MF_NOSAVE] ){
+			// The map has a specific return point
+			if( mapdata->save.map ){
+				safestrncpy( sd->status.last_point.map, mapindex_id2name( mapdata->save.map ), sizeof( sd->status.last_point.map ) );
+				sd->status.last_point.x = mapdata->save.x;
+				sd->status.last_point.y = mapdata->save.y;
+			// Return the user to his save point
+			}else{
+				safestrncpy( sd->status.last_point.map, sd->status.save_point.map, sizeof( sd->status.last_point.map ) );
+				sd->status.last_point.x = sd->status.save_point.x;
+				sd->status.last_point.y = sd->status.save_point.y;
+			}
+		// If the user is on a instance map, we return him to his save point
+		}else if( mapdata->instance_id ){
+			// Return the user to his save point
+			safestrncpy( sd->status.last_point.map, sd->status.save_point.map, sizeof( sd->status.last_point.map ) );
+			sd->status.last_point.x = sd->status.save_point.x;
+			sd->status.last_point.y = sd->status.save_point.y;
+		}else{
+			// Save normally
+			mapindex_getmapname( mapindex_id2name( sd->mapindex ), sd->status.last_point.map );
+			sd->status.last_point.x = sd->bl.x;
+			sd->status.last_point.y = sd->bl.y;
+		}
 	}
 	}
 }
 }
 
 
@@ -2011,9 +2031,9 @@ bool pc_authok(map_session_data *sd, uint32 login_id2, time_t expiration_time, i
 	sd->vars_received = 0x0;
 	sd->vars_received = 0x0;
 
 
 	//warp player
 	//warp player
-	enum e_setpos setpos_result = pc_setpos( sd, sd->status.last_point.map, sd->status.last_point.x, sd->status.last_point.y, CLR_OUTSIGHT );
+	enum e_setpos setpos_result = pc_setpos( sd, mapindex_name2id( sd->status.last_point.map ), sd->status.last_point.x, sd->status.last_point.y, CLR_OUTSIGHT );
 	if( setpos_result != SETPOS_OK ){
 	if( setpos_result != SETPOS_OK ){
-		ShowError( "Last_point_map %s - id %d not found (error code %d)\n", mapindex_id2name(sd->status.last_point.map), sd->status.last_point.map, setpos_result );
+		ShowError( "Last_point_map %s not found (error code %d)\n", sd->status.last_point.map, setpos_result );
 
 
 		// try warping to a default map instead (church graveyard)
 		// try warping to a default map instead (church graveyard)
 		if (pc_setpos(sd, mapindex_name2id(MAP_PRONTERA), 273, 354, CLR_OUTSIGHT) != SETPOS_OK) {
 		if (pc_setpos(sd, mapindex_name2id(MAP_PRONTERA), 273, 354, CLR_OUTSIGHT) != SETPOS_OK) {
@@ -6892,6 +6912,16 @@ enum e_setpos pc_setpos(map_session_data* sd, unsigned short mapindex, int x, in
 	return SETPOS_OK;
 	return SETPOS_OK;
 }
 }
 
 
+enum e_setpos pc_setpos_savepoint( map_session_data& sd, clr_type clrtype ){
+	struct map_data *mapdata = map_getmapdata( sd.bl.m );
+
+	if( mapdata != nullptr && mapdata->flag[MF_NOSAVE] && mapdata->save.map ){
+		return pc_setpos( &sd, mapdata->save.map, mapdata->save.x, mapdata->save.y, clrtype );
+	}else{
+		return pc_setpos( &sd, mapindex_name2id( sd.status.save_point.map ), sd.status.save_point.x, sd.status.save_point.y, clrtype );
+	}
+}
+
 /*==========================================
 /*==========================================
  * Warp player sd to random location on current map.
  * Warp player sd to random location on current map.
  * May fail if no walkable cell found (1000 attempts).
  * May fail if no walkable cell found (1000 attempts).
@@ -6955,9 +6985,11 @@ bool pc_memo(map_session_data* sd, int pos)
 	if( pos == -1 )
 	if( pos == -1 )
 	{
 	{
 		uint8 i;
 		uint8 i;
+		const char* mapname = map_mapid2mapname( sd->bl.m );
+
 		// prevent memo-ing the same map multiple times
 		// prevent memo-ing the same map multiple times
-		ARR_FIND( 0, MAX_MEMOPOINTS, i, sd->status.memo_point[i].map == map_id2index(sd->bl.m) );
-		memmove(&sd->status.memo_point[1], &sd->status.memo_point[0], (u8min(i,MAX_MEMOPOINTS-1))*sizeof(struct point));
+		ARR_FIND( 0, MAX_MEMOPOINTS, i, strncmp( sd->status.memo_point[i].map, mapname, sizeof( sd->status.memo_point[i].map ) ) == 0 );
+		memmove( &sd->status.memo_point[1], &sd->status.memo_point[0], ( u8min( i, MAX_MEMOPOINTS - 1 ) ) * sizeof( struct s_point_str ) );
 		pos = 0;
 		pos = 0;
 	}
 	}
 
 
@@ -6966,7 +6998,7 @@ bool pc_memo(map_session_data* sd, int pos)
 		return false;
 		return false;
 	}
 	}
 
 
-	sd->status.memo_point[pos].map = map_id2index(sd->bl.m);
+	safestrncpy( sd->status.memo_point[pos].map, map_mapid2mapname( sd->bl.m ), sizeof( sd->status.memo_point[pos].map ) );
 	sd->status.memo_point[pos].x = sd->bl.x;
 	sd->status.memo_point[pos].x = sd->bl.x;
 	sd->status.memo_point[pos].y = sd->bl.y;
 	sd->status.memo_point[pos].y = sd->bl.y;
 
 
@@ -9340,8 +9372,9 @@ void pc_respawn(map_session_data* sd, clr_type clrtype)
 
 
 	pc_setstand(sd, true);
 	pc_setstand(sd, true);
 	pc_setrestartvalue(sd,3);
 	pc_setrestartvalue(sd,3);
-	if( pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, clrtype) != SETPOS_OK )
+	if( pc_setpos( sd, mapindex_name2id( sd->status.save_point.map ), sd->status.save_point.x, sd->status.save_point.y, clrtype ) != SETPOS_OK ){
 		clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet.
 		clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet.
+	}
 }
 }
 
 
 static TIMER_FUNC(pc_respawn_timer){
 static TIMER_FUNC(pc_respawn_timer){
@@ -12645,7 +12678,7 @@ void pc_setsavepoint(map_session_data *sd, short mapindex,int x,int y)
 {
 {
 	nullpo_retv(sd);
 	nullpo_retv(sd);
 
 
-	sd->status.save_point.map = mapindex;
+	safestrncpy( sd->status.save_point.map, mapindex_id2name( mapindex ), sizeof( sd->status.save_point.map ) );
 	sd->status.save_point.x = x;
 	sd->status.save_point.x = x;
 	sd->status.save_point.y = y;
 	sd->status.save_point.y = y;
 }
 }

+ 1 - 0
src/map/pc.hpp

@@ -1408,6 +1408,7 @@ enum e_setpos{
 };
 };
 
 
 enum e_setpos pc_setpos(map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype);
 enum e_setpos pc_setpos(map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype);
+enum e_setpos pc_setpos_savepoint( map_session_data& sd, clr_type clrtype = CLR_TELEPORT );
 void pc_setsavepoint(map_session_data *sd, short mapindex,int x,int y);
 void pc_setsavepoint(map_session_data *sd, short mapindex,int x,int y);
 char pc_randomwarp(map_session_data *sd,clr_type type,bool ignore_mapflag = false);
 char pc_randomwarp(map_session_data *sd,clr_type type,bool ignore_mapflag = false);
 bool pc_memo(map_session_data* sd, int pos);
 bool pc_memo(map_session_data* sd, int pos);

+ 10 - 10
src/map/script.cpp

@@ -5612,7 +5612,7 @@ BUILDIN_FUNC(warp)
 	if(strcmp(str,"Random")==0)
 	if(strcmp(str,"Random")==0)
 		ret = pc_randomwarp(sd,CLR_TELEPORT,true);
 		ret = pc_randomwarp(sd,CLR_TELEPORT,true);
 	else if(strcmp(str,"SavePoint")==0 || strcmp(str,"Save")==0)
 	else if(strcmp(str,"SavePoint")==0 || strcmp(str,"Save")==0)
-		ret = pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
+		ret = pc_setpos( sd, mapindex_name2id( sd->status.save_point.map ), sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT );
 	else
 	else
 		ret = pc_setpos(sd,mapindex_name2id(str),x,y,CLR_OUTSIGHT);
 		ret = pc_setpos(sd,mapindex_name2id(str),x,y,CLR_OUTSIGHT);
 
 
@@ -5851,11 +5851,11 @@ BUILDIN_FUNC(warpparty)
 		break;
 		break;
 		case WARPPARTY_SAVEPOINTALL:
 		case WARPPARTY_SAVEPOINTALL:
 			if (!mapdata->flag[MF_NORETURN])
 			if (!mapdata->flag[MF_NORETURN])
-				ret = pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT);
+				ret = pc_setpos( pl_sd, mapindex_name2id( pl_sd->status.save_point.map ), pl_sd->status.save_point.x, pl_sd->status.save_point.y, CLR_TELEPORT );
 		break;
 		break;
 		case WARPPARTY_SAVEPOINT:
 		case WARPPARTY_SAVEPOINT:
 			if (!mapdata->flag[MF_NORETURN])
 			if (!mapdata->flag[MF_NORETURN])
-				ret = pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
+				ret = pc_setpos( pl_sd, mapindex_name2id( sd->status.save_point.map ),sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT );
 		break;
 		break;
 		case WARPPARTY_LEADER:
 		case WARPPARTY_LEADER:
 			if (p->party.member[i].leader)
 			if (p->party.member[i].leader)
@@ -5957,11 +5957,11 @@ BUILDIN_FUNC(warpguild)
 		break;
 		break;
 		case 1: // SavePointAll
 		case 1: // SavePointAll
 			if(!map_getmapflag(pl_sd->bl.m, MF_NORETURN))
 			if(!map_getmapflag(pl_sd->bl.m, MF_NORETURN))
-				pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT);
+				pc_setpos( pl_sd, mapindex_name2id( pl_sd->status.save_point.map ), pl_sd->status.save_point.x, pl_sd->status.save_point.y, CLR_TELEPORT );
 		break;
 		break;
 		case 2: // SavePoint
 		case 2: // SavePoint
 			if(!map_getmapflag(pl_sd->bl.m, MF_NORETURN))
 			if(!map_getmapflag(pl_sd->bl.m, MF_NORETURN))
-				pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
+				pc_setpos( pl_sd, mapindex_name2id( sd->status.save_point.map ),sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT );
 		break;
 		break;
 		case 3: // m,x,y
 		case 3: // m,x,y
 			if(!map_getmapflag(pl_sd->bl.m, MF_NORETURN) && !map_getmapflag(pl_sd->bl.m, MF_NOWARP) && pc_job_can_entermap((enum e_job)pl_sd->status.class_, m, pc_get_group_level(pl_sd)))
 			if(!map_getmapflag(pl_sd->bl.m, MF_NORETURN) && !map_getmapflag(pl_sd->bl.m, MF_NOWARP) && pc_job_can_entermap((enum e_job)pl_sd->status.class_, m, pc_get_group_level(pl_sd)))
@@ -8986,7 +8986,7 @@ BUILDIN_FUNC(getpartyleader)
 		case 1: script_pushint(st,p->party.member[i].account_id); break;
 		case 1: script_pushint(st,p->party.member[i].account_id); break;
 		case 2: script_pushint(st,p->party.member[i].char_id); break;
 		case 2: script_pushint(st,p->party.member[i].char_id); break;
 		case 3: script_pushint(st,p->party.member[i].class_); break;
 		case 3: script_pushint(st,p->party.member[i].class_); break;
-		case 4: script_pushstrcopy(st,mapindex_id2name(p->party.member[i].map)); break;
+		case 4: script_pushstrcopy( st, p->party.member[i].map ); break;
 		case 5: script_pushint(st,p->party.member[i].lv); break;
 		case 5: script_pushint(st,p->party.member[i].lv); break;
 		default: script_pushstrcopy(st,p->party.member[i].name); break;
 		default: script_pushstrcopy(st,p->party.member[i].name); break;
 	}
 	}
@@ -13126,7 +13126,7 @@ BUILDIN_FUNC(warpwaitingpc)
 		if( strcmp(map_name,"Random") == 0 )
 		if( strcmp(map_name,"Random") == 0 )
 			pc_randomwarp(sd,CLR_TELEPORT,true);
 			pc_randomwarp(sd,CLR_TELEPORT,true);
 		else if( strcmp(map_name,"SavePoint") == 0 )
 		else if( strcmp(map_name,"SavePoint") == 0 )
-			pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
+			pc_setpos( sd, mapindex_name2id( sd->status.save_point.map ), sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT );
 		else
 		else
 			pc_setpos(sd, mapindex_name2id(map_name), x, y, CLR_OUTSIGHT);
 			pc_setpos(sd, mapindex_name2id(map_name), x, y, CLR_OUTSIGHT);
 	}
 	}
@@ -13620,7 +13620,7 @@ static int buildin_maprespawnguildid_sub_pc(map_session_data* sd, va_list ap)
 		(sd->status.guild_id != g_id && flag&2) || //Warp out outsiders
 		(sd->status.guild_id != g_id && flag&2) || //Warp out outsiders
 		(sd->status.guild_id == 0 && flag&2)	// Warp out players not in guild
 		(sd->status.guild_id == 0 && flag&2)	// Warp out players not in guild
 	)
 	)
-		pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
+		pc_setpos( sd, mapindex_name2id( sd->status.save_point.map ), sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT );
 	return 1;
 	return 1;
 }
 }
 
 
@@ -15506,7 +15506,7 @@ int atcommand_sub(struct script_state* st,int type) {
 			memcpy(&dummy_sd.bl, bl, sizeof(struct block_list));
 			memcpy(&dummy_sd.bl, bl, sizeof(struct block_list));
 			if (bl->type == BL_NPC)
 			if (bl->type == BL_NPC)
 				safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);
 				safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);
-			sd->mapindex = (bl->m > 0) ? map_id2index(bl->m) : mapindex_name2id(map_default.mapname);
+			sd->mapindex = (bl->m > 0) ? map_id2index(bl->m) : 0;
 		}
 		}
 
 
 		// Init Group ID, Level, & permissions
 		// Init Group ID, Level, & permissions
@@ -16090,7 +16090,7 @@ BUILDIN_FUNC(getsavepoint)
 	type = script_getnum(st,2);
 	type = script_getnum(st,2);
 
 
 	switch(type) {
 	switch(type) {
-		case 0: script_pushstrcopy(st,mapindex_id2name(sd->status.save_point.map)); break;
+		case 0: script_pushstrcopy( st, sd->status.save_point.map ); break;
 		case 1: script_pushint(st,sd->status.save_point.x); break;
 		case 1: script_pushint(st,sd->status.save_point.x); break;
 		case 2: script_pushint(st,sd->status.save_point.y); break;
 		case 2: script_pushint(st,sd->status.save_point.y); break;
 		default:
 		default:

+ 9 - 9
src/map/skill.cpp

@@ -9057,15 +9057,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				if( skill_lv == 1 )
 				if( skill_lv == 1 )
 					pc_randomwarp(sd,CLR_TELEPORT);
 					pc_randomwarp(sd,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, mapindex_name2id( sd->status.save_point.map ), sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT );
 				break;
 				break;
 			}
 			}
 
 
 			clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
 			clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
 			if( skill_lv == 1 && skill_id != ALL_ODINS_RECALL )
 			if( skill_lv == 1 && skill_id != ALL_ODINS_RECALL )
-				clif_skill_warppoint(sd,skill_id,skill_lv, (unsigned short)-1,0,0,0);
+				clif_skill_warppoint( sd, skill_id, skill_lv, "Random" );
 			else
 			else
-				clif_skill_warppoint(sd,skill_id,skill_lv, (unsigned short)-1,sd->status.save_point.map,0,0);
+				clif_skill_warppoint( sd, skill_id, skill_lv, "Random", sd->status.save_point.map );
 		} else
 		} else
 			unit_warp(bl,-1,-1,-1,CLR_TELEPORT);
 			unit_warp(bl,-1,-1,-1,CLR_TELEPORT);
 		break;
 		break;
@@ -13604,9 +13604,9 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
 		if(sd)
 		if(sd)
 		{
 		{
 			clif_skill_warppoint(sd, skill_id, skill_lv, sd->status.save_point.map,
 			clif_skill_warppoint(sd, skill_id, skill_lv, sd->status.save_point.map,
-				(skill_lv >= 2) ? sd->status.memo_point[0].map : 0,
-				(skill_lv >= 3) ? sd->status.memo_point[1].map : 0,
-				(skill_lv >= 4) ? sd->status.memo_point[2].map : 0
+				(skill_lv >= 2) ? sd->status.memo_point[0].map : "",
+				(skill_lv >= 3) ? sd->status.memo_point[1].map : "",
+				(skill_lv >= 4) ? sd->status.memo_point[2].map : ""
 			);
 			);
 		}
 		}
 		if( sc && sc->getSCE(SC_CURSEDCIRCLE_ATKER) ) //Should only remove after the skill has been casted.
 		if( sc && sc->getSCE(SC_CURSEDCIRCLE_ATKER) ) //Should only remove after the skill has been casted.
@@ -14243,14 +14243,14 @@ int skill_castend_map (map_session_data *sd, uint16 skill_id, const char *mapnam
 		if(strcmp(mapname,"Random") == 0)
 		if(strcmp(mapname,"Random") == 0)
 			pc_randomwarp(sd,CLR_TELEPORT);
 			pc_randomwarp(sd,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, mapindex_name2id( sd->status.save_point.map ),sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT );
 
 
 		clif_refresh_storagewindow(sd);
 		clif_refresh_storagewindow(sd);
 		break;
 		break;
 
 
 	case AL_WARP:
 	case AL_WARP:
 		{
 		{
-			const struct point *p[4];
+			const struct s_point_str *p[4];
 			std::shared_ptr<s_skill_unit_group> group;
 			std::shared_ptr<s_skill_unit_group> group;
 			int i, lv, wx, wy;
 			int i, lv, wx, wy;
 			int maxcount=0;
 			int maxcount=0;
@@ -14286,7 +14286,7 @@ int skill_castend_map (map_session_data *sd, uint16 skill_id, const char *mapnam
 			if( lv > 4 ) lv = 4; // crash prevention
 			if( lv > 4 ) lv = 4; // crash prevention
 
 
 			// check if the chosen map exists in the memo list
 			// check if the chosen map exists in the memo list
-			ARR_FIND( 0, lv, i, mapindex == p[i]->map );
+			ARR_FIND( 0, lv, i, strncmp( p[i]->map, mapname, sizeof( p[i]->map ) ) == 0 );
 			if( i < lv ) {
 			if( i < lv ) {
 				x=p[i]->x;
 				x=p[i]->x;
 				y=p[i]->y;
 				y=p[i]->y;

+ 1 - 1
src/map/status.cpp

@@ -11305,7 +11305,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 					val3 = map_idx;
 					val3 = map_idx;
 					val4 = pos;
 					val4 = pos;
 				} else if (!val3 || val3 == sd->mapindex) { // Use save point.
 				} else if (!val3 || val3 == sd->mapindex) { // Use save point.
-					val3 = sd->status.save_point.map;
+					val3 = mapindex_name2id( sd->status.save_point.map );
 					val4 = (sd->status.save_point.x&0xFFFF)
 					val4 = (sd->status.save_point.x&0xFFFF)
 						|(sd->status.save_point.y<<16);
 						|(sd->status.save_point.y<<16);
 				}
 				}