diff --git a/conf/battle/feature.conf b/conf/battle/feature.conf index d40ac5070f..aa08ec4dde 100644 --- a/conf/battle/feature.conf +++ b/conf/battle/feature.conf @@ -168,3 +168,10 @@ feature.mesitemlink_dbname: no // Stylist UI (Note 1) // Requires: 2015-11-04 or later feature.stylist: on + +// Are players allowed to reconnect into instances? (Note 1) +// This is enabled by default in Renewal mode and +// disabled by default in Pre-Renewal mode. +// If this is allowed the "nosave" mapflag is still being respected +// and may prevent players from warping back into the instance. +//feature.instance_allow_reconnect: yes diff --git a/npc/mapflag/nosave.txt b/npc/mapflag/nosave.txt index fdbb7bdebb..f8f99aca26 100644 --- a/npc/mapflag/nosave.txt +++ b/npc/mapflag/nosave.txt @@ -7,6 +7,7 @@ //= 1.7 Updated. [Lupus] //= 1.8 Updated. [L0ne_W0lf] //= 1.9 Renewal split. [Euphy] +//= 2.0 Moved instances to pre-renewal. [Lemongrass] //============================================================ //============================================================ @@ -268,23 +269,6 @@ que_qaru03 mapflag nosave SavePoint que_qaru04 mapflag nosave SavePoint que_qaru05 mapflag nosave SavePoint -//============================================================ -// Sealed Shrine -//============================================================ -1@cata mapflag nosave SavePoint -2@cata mapflag nosave SavePoint - -//============================================================ -// Endless Tower -//============================================================ -e_tower mapflag nosave SavePoint -1@tower mapflag nosave SavePoint -2@tower mapflag nosave SavePoint -3@tower mapflag nosave SavePoint -4@tower mapflag nosave SavePoint -5@tower mapflag nosave SavePoint -6@tower mapflag nosave SavePoint - //============================================================ // Battlegrounds //============================================================ @@ -307,18 +291,6 @@ schg_dun01 mapflag nosave SavePoint arug_que01 mapflag nosave SavePoint arug_dun01 mapflag nosave SavePoint -//============================================================ -// Orc's Memory -//============================================================ -1@orcs mapflag nosave SavePoint -2@orcs mapflag nosave SavePoint - -//============================================================ -// Nidhoggr's Instance -//============================================================ -1@nyd mapflag nosave SavePoint -2@nyd mapflag nosave SavePoint - //============================================================ // RWC //============================================================ diff --git a/npc/pre-re/mapflag/nosave.txt b/npc/pre-re/mapflag/nosave.txt new file mode 100644 index 0000000000..393a143509 --- /dev/null +++ b/npc/pre-re/mapflag/nosave.txt @@ -0,0 +1,37 @@ +//===== rAthena Script ======================================= +//= Mapflag: Disable auto-save. +//===== Description: ========================================= +//= Characters logging out on the specified map will be warped +//= to the map specified in the last field, or "SavePoint". +//===== Additional Comments: ================================= +//= 1.0 Renewal Split. [Lemongrass] +//============================================================ + +//============================================================ +// Endless Tower +//============================================================ +e_tower mapflag nosave SavePoint +1@tower mapflag nosave SavePoint +2@tower mapflag nosave SavePoint +3@tower mapflag nosave SavePoint +4@tower mapflag nosave SavePoint +5@tower mapflag nosave SavePoint +6@tower mapflag nosave SavePoint + +//============================================================ +// Sealed Shrine +//============================================================ +1@cata mapflag nosave SavePoint +2@cata mapflag nosave SavePoint + +//============================================================ +// Orc's Memory +//============================================================ +1@orcs mapflag nosave SavePoint +2@orcs mapflag nosave SavePoint + +//============================================================ +// Nidhoggr's Instance +//============================================================ +1@nyd mapflag nosave SavePoint +2@nyd mapflag nosave SavePoint diff --git a/npc/re/mapflag/nosave.txt b/npc/re/mapflag/nosave.txt index 9db6a6d90d..4fb6f7d2fe 100644 --- a/npc/re/mapflag/nosave.txt +++ b/npc/re/mapflag/nosave.txt @@ -6,6 +6,7 @@ //===== Changelogs: ========================================== //= 1.0 Renewal split. [Euphy] //= 1.1 Added GVG TE Guild Dungeons. [Capuche] +//= 1.2 Removed instances. [Lemongrass] //============================================================ //============================================================ @@ -60,27 +61,10 @@ te_aldecas3 mapflag nosave SavePoint te_aldecas4 mapflag nosave SavePoint te_aldecas5 mapflag nosave SavePoint -//============================================================ -// Misty Forest Labyrinth -//============================================================ -1@mist mapflag nosave SavePoint - -//============================================================ -// Octopus Cave -//============================================================ -1@cash mapflag nosave SavePoint - -//============================================================ -// Drain -//============================================================ -1@pump mapflag nosave SavePoint -2@pump mapflag nosave SavePoint - //============================================================ // Somatology Laboratory //============================================================ que_lhz mapflag nosave SavePoint -1@lhz mapflag nosave SavePoint //============================================================ // Port Malaya @@ -95,246 +79,22 @@ ma_zif07 mapflag nosave SavePoint ma_zif08 mapflag nosave SavePoint ma_zif09 mapflag nosave SavePoint -//============================================================ -// Bangungot Hospital F2 -//============================================================ -1@ma_h mapflag nosave SavePoint - -//============================================================ -// Buwaya Cave -//============================================================ -1@ma_c mapflag nosave SavePoint - -//============================================================ -// Bakonawa Hideout -//============================================================ -1@ma_b mapflag nosave SavePoint - //============================================================ // Inside Eclage //============================================================ que_avan01 mapflag nosave SavePoint -1@ecl mapflag nosave SavePoint - -//============================================================ -// Glastheim Memorial Dungeon -//============================================================ -1@gl_k mapflag nosave SavePoint -2@gl_k mapflag nosave SavePoint - -//============================================================ -// Wave Mode Memorial Dungeon -//============================================================ -1@def01 mapflag nosave SavePoint -1@def02 mapflag nosave SavePoint -1@def03 mapflag nosave SavePoint - -//============================================================ -// Heroes' Trail - Part 1 -//============================================================ -1@face mapflag nosave SavePoint -1@sara mapflag nosave SavePoint - -//============================================================ -// Heroes' Trail - Part 2 -//============================================================ -1@ge_st mapflag nosave SavePoint -1@gef mapflag nosave SavePoint -1@gef_in mapflag nosave SavePoint -1@spa mapflag nosave SavePoint -1@tnm1 mapflag nosave SavePoint -1@tnm2 mapflag nosave SavePoint -1@tnm3 mapflag nosave SavePoint - -//============================================================ -// Horror Toy Factory Memorial Dungeon -//============================================================ -1@xm_d mapflag nosave SavePoint - -//============================================================ -// Heroes' Trail - Part 3 -//============================================================ -1@glast mapflag nosave SavePoint -1@air1 mapflag nosave SavePoint -1@air2 mapflag nosave SavePoint - -//============================================================ -// Decisive Battle - Part 1 -//============================================================ -1@dth1 mapflag nosave SavePoint -1@dth2 mapflag nosave SavePoint -1@dth3 mapflag nosave SavePoint -1@rev mapflag nosave SavePoint - -//============================================================ -// Decisive Battle - Part 2 -//============================================================ -1@eom mapflag nosave SavePoint -1@jtb mapflag nosave SavePoint //============================================================ // Episode 15 - Phantasmagorica //============================================================ -1@lab mapflag nosave SavePoint -1@uns mapflag nosave SavePoint un_myst mapflag nosave SavePoint -1@mcd mapflag nosave SavePoint - -//============================================================ -// Infinite Space -//============================================================ -1@infi mapflag nosave //============================================================ // Episode 16.1 - Banquet of Heroes //============================================================ que_swat mapflag nosave SavePoint -1@mir mapflag nosave SavePoint -2@mir mapflag nosave SavePoint -1@sthb mapflag nosave SavePoint -1@sthc mapflag nosave SavePoint -1@sthd mapflag nosave SavePoint -1@slw mapflag nosave SavePoint -1@swat mapflag nosave SavePoint //============================================================ // Rockridge //============================================================ rockmi2 mapflag nosave SavePoint - -//============================================================ -// Memorial day -//============================================================ -1@md_gef mapflag nosave SavePoint -1@md_pay mapflag nosave SavePoint - -//============================================================ -// Chicken Mode - Nightmare Glastheim -//============================================================ -1@gl_k2 mapflag nosave SavePoint -2@gl_k2 mapflag nosave SavePoint - -//============================================================ -// Chicken Mode - Horror Toy Factory -//============================================================ -1@xm_d2 mapflag nosave SavePoint - -//============================================================ -// Suspicious Shipwreck -//============================================================ -1@tre mapflag nosave SavePoint - -//============================================================ -// Poring Village -//============================================================ -1@begi mapflag nosave SavePoint - -//============================================================ -// Volcanic Island Korodo -//============================================================ -1@crd mapflag nosave SavePoint - -//============================================================ -// Noodles Festival July -//============================================================ -1@drdo mapflag nosave SavePoint - -//============================================================ -// Soul Reaper Job Change -//============================================================ -1@soul mapflag nosave SavePoint - -//============================================================ -// Episode 17.1 -//============================================================ -1@cor mapflag nosave SavePoint -1@os_a mapflag nosave SavePoint -1@os_b mapflag nosave SavePoint -1@rgsr mapflag nosave SavePoint - -//============================================================ -// Episode 17.2 -//============================================================ -1@bamn mapflag nosave SavePoint -1@bamq mapflag nosave SavePoint -1@ghg mapflag nosave SavePoint -1@herbs mapflag nosave SavePoint -1@lost mapflag nosave SavePoint -1@odin mapflag nosave SavePoint - -//============================================================ -// 4th Jobs Change -//============================================================ -1@4win mapflag nosave SavePoint -1@4mag mapflag nosave SavePoint -1@4mst mapflag nosave SavePoint -1@4sac mapflag nosave SavePoint -1@4tro mapflag nosave SavePoint -1@4inq mapflag nosave SavePoint -1@4cdn mapflag nosave SavePoint -1@4igd mapflag nosave SavePoint -1@4drk mapflag nosave SavePoint - -//============================================================ -// Geffen Night Arena -//============================================================ -1@ge_sn mapflag nosave SavePoint - -//============================================================ -// Traces of Heroes -//============================================================ -1@mjo1 mapflag nosave SavePoint -1@mjo2 mapflag nosave SavePoint -1@spa2 mapflag nosave SavePoint - -//============================================================ -// Thanatos Tower Memorial Dungeon -//============================================================ -1@thts mapflag nosave SavePoint -2@thts mapflag nosave SavePoint -3@thts mapflag nosave SavePoint -4@thts mapflag nosave SavePoint -5@thts mapflag nosave SavePoint -6@thts mapflag nosave SavePoint -7@thts mapflag nosave SavePoint -8@thts mapflag nosave SavePoint - -//============================================================ -// Glastheim Challenge Mode -//============================================================ -1@gl_he mapflag nosave SavePoint -1@gl_he2 mapflag nosave SavePoint - -//============================================================ -// EDDA -//============================================================ -1@gl_prq mapflag nosave SavePoint -1@gol1 mapflag nosave SavePoint -1@gol2 mapflag nosave SavePoint - -//============================================================ -// 2018 Halloween -//============================================================ -1@halo mapflag nosave SavePoint - -//============================================================ -// Constellation Tower -//============================================================ -1@ch_t mapflag nosave SavePoint -2@ch_t mapflag nosave SavePoint -3@ch_t mapflag nosave SavePoint - -//============================================================ -// Episode 18 - Direction of Prayer -//============================================================ -1@adv mapflag nosave SavePoint -1@advs mapflag nosave SavePoint -1@nyr mapflag nosave SavePoint -1@oz mapflag nosave SavePoint -1@tcamp mapflag nosave SavePoint -2@nyr mapflag nosave SavePoint - -//============================================================ -// Sunken Tower -//============================================================ -1@ch_u mapflag nosave SavePoint diff --git a/sql-files/main.sql b/sql-files/main.sql index f9b7b49529..95cdbf23a6 100644 --- a/sql-files/main.sql +++ b/sql-files/main.sql @@ -259,6 +259,7 @@ CREATE TABLE IF NOT EXISTS `char` ( `last_map` varchar(11) NOT NULL default '', `last_x` smallint(4) unsigned NOT NULL default '53', `last_y` smallint(4) unsigned NOT NULL default '111', + `last_instanceid` int(11) unsigned NOT NULL default '0', `save_map` varchar(11) NOT NULL default '', `save_x` smallint(4) unsigned NOT NULL default '53', `save_y` smallint(4) unsigned NOT NULL default '111', diff --git a/sql-files/upgrades/upgrade_20230224.sql b/sql-files/upgrades/upgrade_20230224.sql new file mode 100644 index 0000000000..01e2ba5291 --- /dev/null +++ b/sql-files/upgrades/upgrade_20230224.sql @@ -0,0 +1,3 @@ +ALTER TABLE `char` + ADD COLUMN `last_instanceid` int(11) unsigned NOT NULL default '0' AFTER `last_y` +; diff --git a/src/char/char.cpp b/src/char/char.cpp index b104ca026d..07d2f4b161 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -279,7 +279,7 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ (p->job_level != cp->job_level) || (p->job_exp != cp->job_exp) || (p->zeny != cp->zeny) || ( 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) || (p->last_point_instanceid != cp->last_point_instanceid) || ( 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) || @@ -307,7 +307,8 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ "`str`='%d',`agi`='%d',`vit`='%d',`int`='%d',`dex`='%d',`luk`='%d'," "`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d',`elemental_id`='%d'," "`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d'," - "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d'," + "`last_map`='%s',`last_x`='%d',`last_y`='%d',`last_instanceid`='%d'," + "`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d'," "`delete_date`='%lu',`robe`='%d',`moves`='%d',`font`='%u',`uniqueitem_counter`='%u'," "`hotkey_rowshift`='%d', `clan_id`='%d', `title_id`='%lu', `show_equip`='%d', `hotkey_rowshift2`='%d'," "`max_ap`='%u',`ap`='%u',`trait_point`='%d'," @@ -319,7 +320,7 @@ 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->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->last_point.map, p->last_point.x, p->last_point.y, + p->last_point.map, p->last_point.x, p->last_point.y, p->last_point_instanceid, p->save_point.map, p->save_point.x, p->save_point.y, p->rename, (unsigned long)p->delete_date, // FIXME: platform-dependent size p->robe, p->character_moves, p->font, p->uniqueitem_counter, @@ -1060,7 +1061,7 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev "`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`, `moves`," "`unban_time`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`,`clan_id`,`title_id`,`show_equip`,`hotkey_rowshift2`," "`max_ap`,`ap`,`trait_point`,`pow`,`sta`,`wis`,`spl`,`con`,`crt`," - "`inventory_slots`,`body_direction`,`disable_call`" + "`inventory_slots`,`body_direction`,`disable_call`,`last_instanceid`" " FROM `%s` WHERE `char_id`=? LIMIT 1", schema_config.char_db) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) @@ -1138,7 +1139,8 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev || SQL_ERROR == SqlStmt_BindColumn(stmt, 71, SQLDT_SHORT, &p->crt, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 72, SQLDT_UINT16, &p->inventory_slots, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 73, SQLDT_UINT8, &p->body_direction, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 74, SQLDT_UINT16, &p->disable_call, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 74, SQLDT_UINT8, &p->disable_call, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 75, SQLDT_INT, &p->last_point_instanceid, 0, NULL, NULL) ) { SqlStmt_ShowDebug(stmt); @@ -1516,8 +1518,8 @@ int char_make_new_char( struct char_session_data* sd, char* name_, int str, int //Insert the new char entry to the database if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `class`, `zeny`, `status_point`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`," - "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`, `sex`) VALUES (" - "'%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')", + "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`, `sex`, `last_instanceid`) VALUES (" + "'%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', '0')", 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, 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 ) ) @@ -2330,7 +2332,7 @@ bool char_checkdb(void){ "`moves`,`unban_time`,`font`,`sex`,`hotkey_rowshift`,`clan_id`,`last_login`,`title_id`,`show_equip`," "`hotkey_rowshift2`," "`max_ap`,`ap`,`trait_point`,`pow`,`sta`,`wis`,`spl`,`con`,`crt`," - "`inventory_slots`,`body_direction`,`disable_call`" + "`inventory_slots`,`body_direction`,`disable_call`,`last_instanceid`" " FROM `%s` LIMIT 1;", schema_config.char_db) ){ Sql_ShowDebug(sql_handle); return false; diff --git a/src/common/mmo.hpp b/src/common/mmo.hpp index fddbe5893c..f88555b328 100644 --- a/src/common/mmo.hpp +++ b/src/common/mmo.hpp @@ -595,6 +595,7 @@ struct mmo_charstatus { uint16 mapport; struct s_point_str last_point; + int32 last_point_instanceid; struct s_point_str save_point; struct s_point_str memo_point[MAX_MEMOPOINTS]; struct s_skill skill[MAX_SKILL]; diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 9e3dd2d5e0..ea358a9a39 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -10458,6 +10458,11 @@ static const struct _battle_data { { "feature.stylist", &battle_config.feature_stylist, 1, 0, 1, }, { "feature.banking_state_enforce", &battle_config.feature_banking_state_enforce, 0, 0, 1, }, +#ifdef RENEWAL + { "feature.instance_allow_reconnect", &battle_config.instance_allow_reconnect, 1, 0, 1, }, +#else + { "feature.instance_allow_reconnect", &battle_config.instance_allow_reconnect, 0, 0, 1, }, +#endif #include }; diff --git a/src/map/battle.hpp b/src/map/battle.hpp index 9e3a33d7b2..600e62775b 100644 --- a/src/map/battle.hpp +++ b/src/map/battle.hpp @@ -730,6 +730,7 @@ struct Battle_Config int feature_stylist; int feature_banking_state_enforce; + int instance_allow_reconnect; #include }; diff --git a/src/map/pc.cpp b/src/map/pc.cpp index dc76f0d340..a99705383b 100755 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -1307,6 +1307,10 @@ void pc_makesavestatus(map_session_data *sd) { #else sd->status.option = sd->sc.option&(OPTION_INVISIBLE|OPTION_CART|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR); #endif + + // Mark last point as not instance related by default + sd->status.last_point_instanceid = 0; + if (sd->sc.getSCE(SC_JAILED)) { //When Jailed, do not move last point. if(pc_isdead(sd)){ pc_setrestartvalue(sd, 0); @@ -1348,12 +1352,22 @@ void pc_makesavestatus(map_session_data *sd) { 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 + // If the user is on a instance map, special handling is needed }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; + if( battle_config.instance_allow_reconnect ){ + // Store the original mapname + struct map_data* mapdata_source = map_getmapdata( mapdata->instance_src_map ); + + mapindex_getmapname( mapindex_id2name( mapdata_source->index ), sd->status.last_point.map ); + sd->status.last_point.x = sd->bl.x; + sd->status.last_point.y = sd->bl.y; + sd->status.last_point_instanceid = mapdata->instance_id; + }else{ + // 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 ); @@ -1890,6 +1904,106 @@ uint8 pc_isequip(map_session_data *sd,int n) return ITEM_EQUIP_ACK_OK; } +/** + * Performs some special modifications to a player's last point location, + * if the map has a nosave mapflag or if the map was an instance. + * @param sd: Player data + * @return True if the player should be returned to his savepoint or false if not + */ +bool pc_lastpoint_special( map_session_data& sd ){ + int16 mapid = map_mapname2mapid( sd.status.last_point.map ); + + // Should not happen because otherwise the char-server would have sent the player to another map-server + if( mapid < 0 ){ + // Return the player to his savepoint + return true; + } + + struct map_data* mapdata = map_getmapdata( mapid ); + + if( mapdata == nullptr ){ + // Return the player to his savepoint + return true; + } + + // Maybe since the player's logout the nosave mapflag was added to the map + 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 false; + }else{ + // Return the user to his save point + return true; + } + } + + // Check if the last point was an instance + if( sd.status.last_point_instanceid == 0 ){ + // Nothing to do + return false; + } + + // Check if returning to the instance is allowed in general + if( !battle_config.instance_allow_reconnect ){ + // Return the player to his savepoint + return true; + } + + std::shared_ptr instance_data = util::umap_find( instances, sd.status.last_point_instanceid ); + + if( instance_data == nullptr ){ + // Instance does not exist anymore, return the player to his savepoint + return true; + } + + switch( instance_data->mode ){ + case IM_NONE: + // Cannot validate + break; + case IM_CHAR: + if( sd.status.char_id != instance_data->owner_id ){ + // It is a character bound instance and the player is not the owner, return the player to his savepoint + return true; + } + break; + case IM_PARTY: + if( sd.status.party_id != instance_data->owner_id ){ + // It is a party bound instance and the player is not in the party, return the player to his savepoint + return true; + } + break; + case IM_GUILD: + if( sd.status.guild_id != instance_data->owner_id ){ + // It is a guild bound instance and the player is not in the guild, return the player to his savepoint + return true; + } + break; + case IM_CLAN: + if( sd.status.clan_id != instance_data->owner_id ){ + // It is a clan bound instance and the player is not in the clan, return the player to his savepoint + return true; + } + break; + } + + int16 imapid = instance_mapid( mapid, sd.status.last_point_instanceid ); + + if( imapid < 0 ){ + // Instance does not contain this map anymore, return the player to his savepoint + return true; + } + + // Overwrite the stored "source mapname" with the real mapname + instance_generate_mapname( mapid, sd.status.last_point_instanceid, sd.status.last_point.map ); + // X/Y coordinates are already correct and do not need to be modified + + // Dont warp the player back to his savepoint + return false; +} + /*========================================== * No problem with the session id * set the status that has been sent from char server @@ -2030,6 +2144,14 @@ bool pc_authok(map_session_data *sd, uint32 login_id2, time_t expiration_time, i sd->vars_ok = false; sd->vars_received = 0x0; + // Check if the player's last point requires special handling and if conditions apply to return the player to his savepoint + if( pc_lastpoint_special( *sd ) ){ + // The player should be warped back to his savepoint + 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; + } + //warp player 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 ){