From df1108923a13b6b10c121a4f972bee1747438b7a Mon Sep 17 00:00:00 2001 From: Matej Pristak Date: Tue, 22 Mar 2016 20:55:34 +0100 Subject: [PATCH 1/8] Fixing venders being stuck when map->char connection gets reset. --- src/map/chrif.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/map/chrif.c b/src/map/chrif.c index 8e728fa7e9..077629f1d2 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -30,6 +30,7 @@ static int check_connect_char_server(int tid, unsigned int tick, int id, intptr_ static struct eri *auth_db_ers; //For reutilizing player login structures. static DBMap* auth_db; // int id -> struct auth_node* +static bool char_init_done = false; //server already initialized? Used for InterInitOnce and vending loadings 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 @@ -484,8 +485,6 @@ int chrif_changemapserverack(uint32 account_id, int login_id1, int login_id2, ui * 0x2af9 B */ int chrif_connectack(int fd) { - static bool char_init_done = false; - if (RFIFOB(fd,2)) { ShowFatalError("Connection to char-server failed %d, please check conf/import/map_conf userid and passwd.\n", RFIFOB(fd,2)); exit(EXIT_FAILURE); @@ -499,7 +498,6 @@ int chrif_connectack(int fd) { ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit")); if( !char_init_done ) { - char_init_done = true; ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce")); guild_castle_map_init(); } @@ -564,8 +562,12 @@ void chrif_on_ready(void) { guild_castle_reconnect(-1, 0, 0); // Charserver is ready for loading autotrader - do_init_buyingstore_autotrade(); - do_init_vending_autotrade(); + if (!char_init_done) + { + do_init_buyingstore_autotrade(); + do_init_vending_autotrade(); + char_init_done = true; + } } From 5ea873b8b2a8f6169875e6a73b349b47fb4c7033 Mon Sep 17 00:00:00 2001 From: Cem YILMAZ Date: Fri, 26 Aug 2016 17:33:02 +0300 Subject: [PATCH 2/8] Added guild/party checks for character deletion process #1480 --- src/char/char_clif.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/char/char_clif.c b/src/char/char_clif.c index bc40d06818..0a3e14ae35 100644 --- a/src/char/char_clif.c +++ b/src/char/char_clif.c @@ -468,7 +468,7 @@ void chclif_char_delete2_cancel_ack(int fd, uint32 char_id, uint32 result) { int chclif_parse_char_delete2_req(int fd, struct char_session_data* sd) { FIFOSD_CHECK(6) { - uint32 char_id, i; + uint32 char_id, i, guild_id, party_id; char* data; time_t delete_date; @@ -482,7 +482,7 @@ int chclif_parse_char_delete2_req(int fd, struct char_session_data* sd) { return 1; } - if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `delete_date` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `delete_date`,`party_id`,`guild_id` FROM `%s` WHERE `char_id`='%d'", schema_config.char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) { Sql_ShowDebug(sql_handle); chclif_char_delete2_ack(fd, char_id, 3, 0); @@ -490,28 +490,26 @@ int chclif_parse_char_delete2_req(int fd, struct char_session_data* sd) { } Sql_GetData(sql_handle, 0, &data, NULL); delete_date = strtoul(data, NULL, 10); + Sql_GetData(sql_handle, 1, &data, NULL); party_id = strtoul(data, NULL, 10); + Sql_GetData(sql_handle, 2, &data, NULL); guild_id = strtoul(data, NULL, 10); if( delete_date ) {// character already queued for deletion chclif_char_delete2_ack(fd, char_id, 0, 0); return 1; } - /* - // Aegis imposes these checks probably to avoid dead member - // entries in guilds/parties, otherwise they are not required. - // TODO: Figure out how these are enforced during waiting. - if( guild_id ) - {// character in guild + if (guild_id) // character is in guild + { chclif_char_delete2_ack(fd, char_id, 4, 0); return 1; } - if( party_id ) - {// character in party + if (party_id) // character is in party + { chclif_char_delete2_ack(fd, char_id, 5, 0); return 1; } - */ + // success delete_date = time(NULL)+(charserv_config.char_config.char_del_delay); From ce9e623e47e696090fe1de45a08ba15ba6172d76 Mon Sep 17 00:00:00 2001 From: Lemongrass3110 Date: Mon, 10 Oct 2016 09:43:54 +0200 Subject: [PATCH 3/8] Added a configuration for deletion restriction Additionally added the checks to char_delete_char_sql so it is triggered on deletion itself and from older packets(chclif_parse_delchar) too. --- conf/char_athena.conf | 7 +++++++ src/char/char.c | 15 +++++++++++++++ src/char/char.h | 7 +++++++ src/char/char_clif.c | 4 ++-- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/conf/char_athena.conf b/conf/char_athena.conf index 232af01cc8..89460b92c4 100644 --- a/conf/char_athena.conf +++ b/conf/char_athena.conf @@ -182,6 +182,13 @@ char_del_delay: 86400 // - Clients that are not using 0x0068 or 0x01fb, only use birthdate (YYMMDD) as default. char_del_option: 2 +// Restrict character deletion as long as he is still in a party or guild +// 0: No restriction is applied +// 1: Character cannot be deleted as long as he remains in a party +// 2: Character cannot be deleted as long as he remains in a guild +// 3: Character cannot be deleted as long as he remains in a party or guild(default) +char_del_restriction: 3 + // What folder the DB files are in (item_db.txt, etc.) db_path: db diff --git a/src/char/char.c b/src/char/char.c index 95e63aeca7..dc8e338679 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -1678,6 +1678,18 @@ int char_delete_char_sql(uint32 char_id){ return -1; } + if (charserv_config.char_config.char_del_restriction&CHAR_DEL_RESTRICT_GUILD && guild_id) // character is in guild + { + ShowInfo("Char deletion aborted: %s, Guild ID: %i\n", name, guild_id); + return -1; + } + + if (charserv_config.char_config.char_del_restriction&CHAR_DEL_RESTRICT_PARTY && party_id) // character is in party + { + ShowInfo("Char deletion aborted: %s, Party ID: %i\n", name, party_id); + return -1; + } + /* Divorce [Wizputer] */ if( partner_id ) char_divorce_char_sql(char_id, partner_id); @@ -2720,6 +2732,7 @@ void char_set_defaults(){ #else charserv_config.char_config.char_del_option = CHAR_DEL_EMAIL; #endif + charserv_config.char_config.char_del_restriction = CHAR_DEL_RESTRICT_ALL; // charserv_config.userid[24]; // charserv_config.passwd[24]; @@ -2998,6 +3011,8 @@ bool char_config_read(const char* cfgName, bool normal){ charserv_config.char_config.char_del_delay = atoi(w2); } else if (strcmpi(w1, "char_del_option") == 0) { charserv_config.char_config.char_del_option = atoi(w2); + } else if (strcmpi(w1, "char_del_restriction") == 0) { + charserv_config.char_config.char_del_restriction = atoi(w2); } else if(strcmpi(w1,"db_path")==0) { safestrncpy(schema_config.db_path, w2, sizeof(schema_config.db_path)); } else if (strcmpi(w1, "fame_list_alchemist") == 0) { diff --git a/src/char/char.h b/src/char/char.h index 8f5a97e59c..4f89b1dd73 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -37,6 +37,12 @@ enum e_char_delete { CHAR_DEL_BIRTHDATE }; +enum e_char_delete_restriction { + CHAR_DEL_RESTRICT_PARTY = 1, + CHAR_DEL_RESTRICT_GUILD, + CHAR_DEL_RESTRICT_ALL +}; + struct Schema_Config { int db_use_sqldbs; char db_path[1024]; @@ -119,6 +125,7 @@ struct Char_Config { char char_name_letters[1024]; // list of letters/symbols allowed (or not) in a character name. by [Yor] int char_name_option; // Option to know which letters/symbols are authorised in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor] int char_del_option; // Character deletion type, email = 1, birthdate = 2 (default) + int char_del_restriction; // Character deletion restriction (0: none, 1: if the character is in a party, 2: if the character is in a guild, 3: if the character is in a party or a guild) }; #define TRIM_CHARS "\255\xA0\032\t\x0A\x0D " //The following characters are trimmed regardless because they cause confusion and problems on the servers. [Skotlex] diff --git a/src/char/char_clif.c b/src/char/char_clif.c index 0a3e14ae35..7341260a62 100644 --- a/src/char/char_clif.c +++ b/src/char/char_clif.c @@ -498,13 +498,13 @@ int chclif_parse_char_delete2_req(int fd, struct char_session_data* sd) { return 1; } - if (guild_id) // character is in guild + if (charserv_config.char_config.char_del_restriction&CHAR_DEL_RESTRICT_GUILD && guild_id) // character is in guild { chclif_char_delete2_ack(fd, char_id, 4, 0); return 1; } - if (party_id) // character is in party + if (charserv_config.char_config.char_del_restriction&CHAR_DEL_RESTRICT_PARTY && party_id) // character is in party { chclif_char_delete2_ack(fd, char_id, 5, 0); return 1; From 940c473c8824685042c28e851351541d5ee4e1f8 Mon Sep 17 00:00:00 2001 From: Lemongrass3110 Date: Thu, 29 Sep 2016 13:54:39 +0200 Subject: [PATCH 4/8] Cleaned up map property sending functions Implemented ZC_MAPPROPERTY_R2 properly --- src/map/atcommand.c | 4 --- src/map/clif.c | 66 ++++++++++++++++++--------------------------- src/map/clif.h | 3 +-- src/map/duel.c | 9 +++---- src/map/script.c | 40 +++------------------------ 5 files changed, 34 insertions(+), 88 deletions(-) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index abf6a8146b..714e988907 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -1619,7 +1619,6 @@ ACMD_FUNC(pvpoff) if (!battle_config.pk_mode){ clif_map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING); - clif_maptypeproperty2(&sd->bl,ALL_SAMEMAP); } map_foreachinmap(atcommand_pvpoff_sub,sd->bl.m, BL_PC); map_foreachinmap(atcommand_stopattack,sd->bl.m, BL_CHAR, 0); @@ -1657,7 +1656,6 @@ ACMD_FUNC(pvpon) if (!battle_config.pk_mode) {// display pvp circle and rank clif_map_property_mapall(sd->bl.m, MAPPROPERTY_FREEPVPZONE); - clif_maptypeproperty2(&sd->bl,ALL_SAMEMAP); map_foreachinmap(atcommand_pvpon_sub,sd->bl.m, BL_PC); } @@ -1680,7 +1678,6 @@ ACMD_FUNC(gvgoff) map[sd->bl.m].flag.gvg = 0; clif_map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING); - clif_maptypeproperty2(&sd->bl,ALL_SAMEMAP); map_foreachinmap(atcommand_stopattack,sd->bl.m, BL_CHAR, 0); clif_displaymessage(fd, msg_txt(sd,33)); // GvG: Off. @@ -1701,7 +1698,6 @@ ACMD_FUNC(gvgon) map[sd->bl.m].flag.gvg = 1; clif_map_property_mapall(sd->bl.m, MAPPROPERTY_AGITZONE); - clif_maptypeproperty2(&sd->bl,ALL_SAMEMAP); clif_displaymessage(fd, msg_txt(sd,34)); // GvG: On. return 0; diff --git a/src/map/clif.c b/src/map/clif.c index 94a388bbe4..9471f46452 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -6181,28 +6181,24 @@ void clif_resurrection(struct block_list *bl,int type) } -/// Sets the map property (ZC_NOTIFY_MAPPROPERTY). -/// 0199 .W -void clif_map_property(struct map_session_data* sd, enum map_property property) +/// Sets the map property +/// 0199 .W (ZC_NOTIFY_MAPPROPERTY) +/// 099b .W .L (ZC_MAPPROPERTY_R2) +void clif_map_property(struct block_list *bl, enum map_property property, enum send_target t) { - int fd; - - nullpo_retv(sd); - - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x199)); - WFIFOW(fd,0)=0x199; - WFIFOW(fd,2)=property; - WFIFOSET(fd,packet_len(0x199)); -} - - -void clif_maptypeproperty2(struct block_list *bl,enum send_target t) { #if PACKETVER >= 20121010 + short cmd = 0x99b; unsigned char buf[8]; +#else + short cmd = 0x199; + unsigned char buf[4]; +#endif + + WBUFW(buf,0)=cmd; + WBUFW(buf,2)=property; - unsigned int NotifyProperty = - ((map[bl->m].flag.pvp?1:0)<<0)| // PARTY - Show attack cursor on non-party members (PvP) +#if PACKETVER >= 20121010 + WBUFL(buf,4) = ((map[bl->m].flag.pvp?1:0)<<0)| // PARTY - Show attack cursor on non-party members (PvP) ((map[bl->m].flag.battleground || map_flag_gvg(bl->m)?1:0)<<1)|// GUILD - Show attack cursor on non-guild members (GvG) ((map[bl->m].flag.battleground || map_flag_gvg2(bl->m)?1:0)<<2)|// SIEGE - Show emblem over characters heads when in GvG (WoE castle) ((map[bl->m].flag.nomineeffect || !map_flag_gvg2(bl->m)?0:1)<<3)| // USE_SIMPLE_EFFECT - Automatically enable /mineffect @@ -6214,14 +6210,9 @@ void clif_maptypeproperty2(struct block_list *bl,enum send_target t) { ((map[bl->m].flag.nousecart?0:1)<<9)| // USECART - Allow opening cart inventory (Well force it to always allow it) ((map[bl->m].flag.nosumstarmiracle?0:1)<<10); // SUNMOONSTAR_MIRACLE - Unknown - (Guessing it blocks Star Gladiator's Miracle from activating) //(1<<11); // Unused bits. 1 - 10 is 0x1 length and 11 is 0x15 length. May be used for future settings. - - WBUFW(buf,0)=0x99b; - WBUFW(buf,2)=0x28; // Type - What is it asking for? MAPPROPERTY? MAPTYPE? I don't know. Do we even need it? [Rytech] - WBUFL(buf,4)=NotifyProperty; - WBUFW(buf,6) = 0; // sparebit [5-15], + extra[4] - - clif_send(buf,packet_len(0x99b),bl,t); #endif + + clif_send(buf,packet_len(cmd),bl,t); } /// Set the map type (ZC_NOTIFY_MAPPROPERTY2). @@ -6277,17 +6268,14 @@ void clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type) void clif_map_property_mapall(int map_idx, enum map_property property) { struct block_list bl; - unsigned char buf[16]; bl.id = 0; bl.type = BL_NUL; bl.m = map_idx; - WBUFW(buf,0)=0x199; - WBUFW(buf,2)=property; - clif_send(buf,packet_len(0x199),&bl,ALL_SAMEMAP); + + clif_map_property( &bl, property, ALL_SAMEMAP ); } - /// Notifies the client about the result of a refine attempt (ZC_ACK_ITEMREFINING). /// 0188 .W .W .W /// result: @@ -10177,15 +10165,15 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) sd->pvp_won = 0; sd->pvp_lost = 0; } - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); + clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF); } else if(sd->duel_group) // set flag, if it's a duel [LuzZza] - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); - - if (map[sd->bl.m].flag.gvg_dungeon) - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); //TODO: Figure out the real packet to send here. - - if( map_flag_gvg(sd->bl.m) ) - clif_map_property(sd, MAPPROPERTY_AGITZONE); + clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF); + else if (map[sd->bl.m].flag.gvg_dungeon) + clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF); //TODO: Figure out the real packet to send here. + else if( map_flag_gvg(sd->bl.m) ) + clif_map_property(&sd->bl, MAPPROPERTY_AGITZONE, SELF); + else + clif_map_property(&sd->bl, MAPPROPERTY_NOTHING, SELF); // info about nearby objects // must use foreachinarea (CIRCULAR_AREA interferes with foreachinrange) @@ -10376,8 +10364,6 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) mail_clear(sd); - clif_maptypeproperty2(&sd->bl,SELF); - /* Guild Aura Init */ if( sd->state.gmaster_flag ) { guild_guildaura_refresh(sd,GD_LEADERSHIP,guild_checkskill(sd->guild,GD_LEADERSHIP)); diff --git a/src/map/clif.h b/src/map/clif.h index 9672c5399b..03049c5dcb 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -785,8 +785,7 @@ void clif_broadcast(struct block_list* bl, const char* mes, int len, int type, e void clif_broadcast2(struct block_list* bl, const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target); void clif_heal(int fd,int type,int val); void clif_resurrection(struct block_list *bl,int type); -void clif_map_property(struct map_session_data* sd, enum map_property property); -void clif_maptypeproperty2(struct block_list *bl,enum send_target t); +void clif_map_property(struct block_list *bl, enum map_property property, enum send_target t); void clif_pvpset(struct map_session_data *sd, int pvprank, int pvpnum,int type); void clif_map_property_mapall(int map, enum map_property property); void clif_refine(int fd, int fail, int index, int val); diff --git a/src/map/duel.c b/src/map/duel.c index d3a5416f07..a87338cc91 100644 --- a/src/map/duel.c +++ b/src/map/duel.c @@ -130,8 +130,7 @@ int duel_create(struct map_session_data* sd, const unsigned int maxpl) strcpy(output, msg_txt(sd,372)); // " -- Duel has been created (@invite/@leave) --" clif_disp_onlyself(sd, output, strlen(output)); - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); - clif_maptypeproperty2(&sd->bl,SELF); + clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF); //clif_misceffect2(&sd->bl, 159); return i; } @@ -193,8 +192,7 @@ void duel_leave(const unsigned int did, struct map_session_data* sd) duel_set(0, sd); duel_savetime(sd); - clif_map_property(sd, MAPPROPERTY_NOTHING); - clif_maptypeproperty2(&sd->bl,SELF); + clif_map_property(&sd->bl, MAPPROPERTY_NOTHING, SELF); } /* @@ -215,8 +213,7 @@ void duel_accept(const unsigned int did, struct map_session_data* sd) sprintf(output, msg_txt(sd,376), sd->status.name); clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS); - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); - clif_maptypeproperty2(&sd->bl,SELF); + clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF); //clif_misceffect2(&sd->bl, 159); } diff --git a/src/map/script.c b/src/map/script.c index 8d435d9383..9a709ca73d 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -11851,8 +11851,7 @@ static int script_mapflag_pvp_sub(struct block_list *bl,va_list ap) { sd->pvp_won = 0; sd->pvp_lost = 0; } - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); - clif_maptypeproperty2(&sd->bl,SELF); + clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE,SELF); return 0; } @@ -11882,14 +11881,9 @@ BUILDIN_FUNC(setmapflag) break; case MF_PVP_NOPARTY: map[m].flag.pvp_noparty = 1; break; case MF_PVP_NOGUILD: map[m].flag.pvp_noguild = 1; break; - case MF_GVG: { - struct block_list bl; + case MF_GVG: map[m].flag.gvg = 1; clif_map_property_mapall(m, MAPPROPERTY_AGITZONE); - bl.type = BL_NUL; - bl.m = m; - clif_maptypeproperty2(&bl,ALL_SAMEMAP); - } break; case MF_GVG_NOPARTY: map[m].flag.gvg_noparty = 1; break; case MF_NOTRADE: map[m].flag.notrade = 1; break; @@ -11992,25 +11986,15 @@ BUILDIN_FUNC(removemapflag) case MF_NOBRANCH: map[m].flag.nobranch = 0; break; case MF_NOPENALTY: map[m].flag.noexppenalty = 0; map[m].flag.nozenypenalty = 0; break; case MF_NOZENYPENALTY: map[m].flag.nozenypenalty = 0; break; - case MF_PVP: { - struct block_list bl; - bl.type = BL_NUL; - bl.m = m; + case MF_PVP: map[m].flag.pvp = 0; clif_map_property_mapall(m, MAPPROPERTY_NOTHING); - clif_maptypeproperty2(&bl,ALL_SAMEMAP); - } break; case MF_PVP_NOPARTY: map[m].flag.pvp_noparty = 0; break; case MF_PVP_NOGUILD: map[m].flag.pvp_noguild = 0; break; - case MF_GVG: { - struct block_list bl; - bl.type = BL_NUL; - bl.m = m; + case MF_GVG: map[m].flag.gvg = 0; clif_map_property_mapall(m, MAPPROPERTY_NOTHING); - clif_maptypeproperty2(&bl,ALL_SAMEMAP); - } break; case MF_GVG_NOPARTY: map[m].flag.gvg_noparty = 0; break; case MF_NOTRADE: map[m].flag.notrade = 0; break; @@ -12097,7 +12081,6 @@ BUILDIN_FUNC(pvpon) const char *str; TBL_PC* sd = NULL; struct s_mapiterator* iter; - struct block_list bl; str = script_getstr(st,2); m = map_mapname2mapid(str); @@ -12106,9 +12089,6 @@ BUILDIN_FUNC(pvpon) map[m].flag.pvp = 1; clif_map_property_mapall(m, MAPPROPERTY_FREEPVPZONE); - bl.type = BL_NUL; - bl.m = m; - clif_maptypeproperty2(&bl,ALL_SAMEMAP); if(battle_config.pk_mode) // disable ranking functions if pk_mode is on [Valaris] return SCRIPT_CMD_SUCCESS; @@ -12145,7 +12125,6 @@ BUILDIN_FUNC(pvpoff) { int16 m; const char *str; - struct block_list bl; str=script_getstr(st,2); m = map_mapname2mapid(str); @@ -12154,9 +12133,6 @@ BUILDIN_FUNC(pvpoff) map[m].flag.pvp = 0; clif_map_property_mapall(m, MAPPROPERTY_NOTHING); - bl.type = BL_NUL; - bl.m = m; - clif_maptypeproperty2(&bl,ALL_SAMEMAP); if(battle_config.pk_mode) // disable ranking options if pk_mode is on [Valaris] return SCRIPT_CMD_SUCCESS; @@ -12169,16 +12145,12 @@ BUILDIN_FUNC(gvgon) { int16 m; const char *str; - struct block_list bl; str=script_getstr(st,2); m = map_mapname2mapid(str); if(m >= 0 && !map[m].flag.gvg) { map[m].flag.gvg = 1; clif_map_property_mapall(m, MAPPROPERTY_AGITZONE); - bl.type = BL_NUL; - bl.m = m; - clif_maptypeproperty2(&bl,ALL_SAMEMAP); } return SCRIPT_CMD_SUCCESS; } @@ -12191,12 +12163,8 @@ BUILDIN_FUNC(gvgoff) str=script_getstr(st,2); m = map_mapname2mapid(str); if(m >= 0 && map[m].flag.gvg) { - struct block_list bl; map[m].flag.gvg = 0; clif_map_property_mapall(m, MAPPROPERTY_NOTHING); - bl.type = BL_NUL; - bl.m = m; - clif_maptypeproperty2(&bl,ALL_SAMEMAP); } return SCRIPT_CMD_SUCCESS; } From f51a1c74baae5bfcd39d1e730a7ad7b616d601b9 Mon Sep 17 00:00:00 2001 From: Jittapan Pluemsumran Date: Sat, 1 Oct 2016 22:06:37 +0700 Subject: [PATCH 5/8] Removed additional clif_maptypeproperty2 calls --- src/map/script.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/src/map/script.c b/src/map/script.c index 9a709ca73d..b42486cf07 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -11939,14 +11939,8 @@ BUILDIN_FUNC(setmapflag) case MF_NOCOSTUME: map[m].flag.nocostume = 1; break; case MF_GVG_TE_CASTLE: map[m].flag.gvg_te_castle = 1; break; case MF_GVG_TE: - { - struct block_list bl; - map[m].flag.gvg_te = 1; - clif_map_property_mapall(m, MAPPROPERTY_AGITZONE); - bl.type = BL_NUL; - bl.m = m; - clif_maptypeproperty2(&bl,ALL_SAMEMAP); - } + map[m].flag.gvg_te = 1; + clif_map_property_mapall(m, MAPPROPERTY_AGITZONE); break; #ifdef ADJUST_SKILL_DAMAGE case MF_SKILL_DAMAGE: @@ -12052,14 +12046,8 @@ BUILDIN_FUNC(removemapflag) case MF_NOCOSTUME: map[m].flag.nocostume = 0; break; case MF_GVG_TE_CASTLE: map[m].flag.gvg_te_castle = 0; break; case MF_GVG_TE: - { - struct block_list bl; - bl.type = BL_NUL; - bl.m = m; - map[m].flag.gvg_te = 0; - clif_map_property_mapall(m, MAPPROPERTY_NOTHING); - clif_maptypeproperty2(&bl,ALL_SAMEMAP); - } + map[m].flag.gvg_te = 0; + clif_map_property_mapall(m, MAPPROPERTY_NOTHING); break; #ifdef ADJUST_SKILL_DAMAGE case MF_SKILL_DAMAGE: @@ -12173,16 +12161,12 @@ BUILDIN_FUNC(gvgon3) { int16 m; const char *str; - struct block_list bl; str = script_getstr(st,2); m = map_mapname2mapid(str); if (m >= 0 && !map[m].flag.gvg_te) { map[m].flag.gvg_te = 1; clif_map_property_mapall(m, MAPPROPERTY_AGITZONE); - bl.type = BL_NUL; - bl.m = m; - clif_maptypeproperty2(&bl,ALL_SAMEMAP); } return SCRIPT_CMD_SUCCESS; } @@ -12195,12 +12179,8 @@ BUILDIN_FUNC(gvgoff3) str = script_getstr(st,2); m = map_mapname2mapid(str); if (m >= 0 && map[m].flag.gvg_te) { - struct block_list bl; map[m].flag.gvg_te = 0; clif_map_property_mapall(m, MAPPROPERTY_NOTHING); - bl.type = BL_NUL; - bl.m = m; - clif_maptypeproperty2(&bl,ALL_SAMEMAP); } return SCRIPT_CMD_SUCCESS; } From 6663df344b17f15bdf54214bf4872678d1d784fa Mon Sep 17 00:00:00 2001 From: aleos89 Date: Tue, 11 Oct 2016 14:23:15 -0400 Subject: [PATCH 6/8] Corrected script command statusup2 documentation (fixes #1612) * Corrected the documentation referencing the wrong script command. * Removed some trailing white spaces. * Prettified some text. Thanks to @lucasoli! --- doc/script_commands.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/script_commands.txt b/doc/script_commands.txt index fa882833c2..eef5d93392 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -5321,8 +5321,8 @@ behavior of the command. *statusup {,}; -This command will bump a specified stat of the invoking character up by one -permanently. Stats are to be given as number, but you can use these constants to +This command will change a specified stat of the invoking character up by one +permanently. Stats are to be given as number, but you can use these constants to replace them: bStr - Strength @@ -5336,11 +5336,11 @@ bLuk - Luck *statusup2 ,{,}; -This command will bump a specified stat of the invoking character up by the +This command will change a specified stat of the invoking character by the specified amount permanently. The amount can be negative. See 'statusup'. -// This will decrease a character's Vit forever. - statusup bVit,-1; + // This will decrease a character's Vit forever. + statusup2 bVit,-1; --------------------------------------- From 8f3599b0e3c7b8ec95bfb4cf26a1a24c684919aa Mon Sep 17 00:00:00 2001 From: Cydh Ramdh Date: Wed, 12 Oct 2016 06:26:30 +0700 Subject: [PATCH 7/8] Fixed VIP char selection window (#1598) * Char selection window went crazy when `VIP_ENABLE` is defined * Fixed #628 Signed-off-by: Cydh Ramdh --- conf/login_athena.conf | 4 ++-- src/char/char_clif.c | 14 +++++++------- src/char/char_logif.c | 4 ++++ src/login/login.c | 9 +++++++-- src/login/loginchrif.c | 5 +++-- 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/conf/login_athena.conf b/conf/login_athena.conf index 8529a3e014..a5bbd2917b 100644 --- a/conf/login_athena.conf +++ b/conf/login_athena.conf @@ -98,8 +98,8 @@ chars_per_account: 0 // Increase the value of MAX_CHARS if you want to increase vip_char_increase. // Note: The amount of VIP characters = MAX_CHARS - chars_per_account. // Note 2: This setting must be set after chars_per_account. -// Default: 6 -vip_char_increase: 6 +// -1 will default to MAX_CHAR_VIP (src/config/core.h) +vip_char_increase: -1 // Create accounts with limited time? // -1: new accounts are created with unlimited time (default) diff --git a/src/char/char_clif.c b/src/char/char_clif.c index 7341260a62..d7f0373444 100644 --- a/src/char/char_clif.c +++ b/src/char/char_clif.c @@ -336,8 +336,8 @@ int chclif_mmo_send006b(int fd, struct char_session_data* sd){ WFIFOW(fd,0) = 0x6b; if(newvers){ //20100413 WFIFOB(fd,4) = MAX_CHARS; // Max slots. - WFIFOB(fd,5) = sd->char_slots; // Available slots. (PremiumStartSlot) - WFIFOB(fd,6) = MAX_CHARS; // Premium slots. (Any existent chars past sd->char_slots but within MAX_CHARS will show a 'Premium Service' in red) + WFIFOB(fd,5) = MIN_CHARS; // Available slots. (PremiumStartSlot) + WFIFOB(fd,6) = MIN_CHARS+sd->chars_vip; // Premium slots. (Any existent chars past sd->char_slots but within MAX_CHARS will show a 'Premium Service' in red) } memset(WFIFOP(fd,4 + offset), 0, 20); // unknown bytes j+=char_mmo_chars_fromsql(sd, WFIFOP(fd,j)); @@ -356,11 +356,11 @@ void chclif_mmo_send082d(int fd, struct char_session_data* sd) { WFIFOHEAD(fd,29); WFIFOW(fd,0) = 0x82d; WFIFOW(fd,2) = 29; - WFIFOB(fd,4) = sd->char_slots; - WFIFOB(fd,5) = MAX_CHARS - sd->char_slots; - WFIFOB(fd,6) = MAX_CHARS - sd->char_slots; - WFIFOB(fd,7) = sd->char_slots; - WFIFOB(fd,8) = sd->char_slots; + WFIFOB(fd,4) = MIN_CHARS; // normal_slot + WFIFOB(fd,5) = sd->chars_vip; // premium_slot + WFIFOB(fd,6) = sd->chars_billing; // billing_slot + WFIFOB(fd,7) = sd->char_slots; // producible_slot + WFIFOB(fd,8) = MAX_CHARS; // valid_slot memset(WFIFOP(fd,9), 0, 20); // unused bytes WFIFOSET(fd,29); } diff --git a/src/char/char_logif.c b/src/char/char_logif.c index a4e4748739..a1206ff20a 100644 --- a/src/char/char_logif.c +++ b/src/char/char_logif.c @@ -332,6 +332,10 @@ int chlogif_parse_ackaccreq(int fd, struct char_session_data* sd){ return 1; } +/** + * Receive account data from login-server + * AH 0x2717 .L .40B .L .B .11B .5B .L .B .B .B + **/ int chlogif_parse_reqaccdata(int fd, struct char_session_data* sd){ int u_fd; //user fd if (RFIFOREST(fd) < 75) diff --git a/src/login/login.c b/src/login/login.c index 8060f30eb8..39b5e38e0d 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -655,10 +655,15 @@ bool login_config_read(const char* cfgName, bool normal) { else if(strcmpi(w1,"vip_group")==0) login_config.vip_sys.group = cap_value(atoi(w2),0,99); else if(strcmpi(w1,"vip_char_increase")==0) { - if(login_config.vip_sys.char_increase > (unsigned int) MAX_CHARS-login_config.char_per_account) + if (atoi(w2) == -1) + login_config.vip_sys.char_increase = MAX_CHAR_VIP; + else + login_config.vip_sys.char_increase = atoi(w2); + if (login_config.vip_sys.char_increase > (unsigned int) MAX_CHARS-login_config.char_per_account) { ShowWarning("vip_char_increase too high, can only go up to %d, according to your char_per_account config %d\n", MAX_CHARS-login_config.char_per_account,login_config.char_per_account); - login_config.vip_sys.char_increase = cap_value(atoi(w2),0,MAX_CHARS-login_config.char_per_account); + login_config.vip_sys.char_increase = MAX_CHARS-login_config.char_per_account; + } } #endif else if(!strcmpi(w1, "import")) diff --git a/src/login/loginchrif.c b/src/login/loginchrif.c index 6a8373b81e..5f674a6484 100644 --- a/src/login/loginchrif.c +++ b/src/login/loginchrif.c @@ -163,7 +163,7 @@ int logchrif_send_accdata(int fd, uint32 aid) { char birthdate[10+1] = ""; char pincode[PINCODE_LENGTH+1]; char isvip = false; - uint8 char_slots = MIN_CHARS, char_vip = 0; + uint8 char_slots = MIN_CHARS, char_vip = 0, char_billing = 0; AccountDB* accounts = login_get_accounts_db(); memset(pincode,0,PINCODE_LENGTH+1); @@ -183,6 +183,7 @@ int logchrif_send_accdata(int fd, uint32 aid) { char_slots = login_config.char_per_account + char_vip; } else char_slots = login_config.char_per_account; + char_billing = MAX_CHAR_BILLING; //TODO create a config for this #endif } @@ -198,7 +199,7 @@ int logchrif_send_accdata(int fd, uint32 aid) { WFIFOL(fd,68) = (uint32)acc.pincode_change; WFIFOB(fd,72) = isvip; WFIFOB(fd,73) = char_vip; - WFIFOB(fd,74) = MAX_CHAR_BILLING; //TODO create a config for this + WFIFOB(fd,74) = char_billing; WFIFOSET(fd,75); return 1; } From b2c4178209eeb408eddf237c1dc8932a81d20a18 Mon Sep 17 00:00:00 2001 From: Cydh Ramdh Date: Fri, 14 Oct 2016 06:04:09 +0700 Subject: [PATCH 8/8] Corrected 'VIP' personal info notification (#1613) * Only displayed when map-server is changed or when changing map that has different base rate with previous map's rate, should not when map changed/warped. * Updated some packet that related with VIP and its doc. Signed-off-by: Cydh Ramdh --- doc/packet_interserv.txt | 22 +++++++-------- src/char/char_logif.c | 21 +++++++-------- src/char/char_logif.h | 2 +- src/char/char_mapif.c | 11 ++++---- src/char/char_mapif.h | 2 +- src/login/loginchrif.c | 28 ++++++++++--------- src/map/atcommand.c | 2 -- src/map/chrif.c | 58 +++++++++++++++++++++++----------------- src/map/clif.c | 23 ++++++++++------ src/map/pc.c | 2 +- 10 files changed, 93 insertions(+), 78 deletions(-) diff --git a/doc/packet_interserv.txt b/doc/packet_interserv.txt index baaf043281..6a9cdef1a4 100644 --- a/doc/packet_interserv.txt +++ b/doc/packet_interserv.txt @@ -454,13 +454,13 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket. 0x2742: Type: HA - Structure: .W .L .B .L .L + Structure: .W .L .B .L .L index: 0,2,6,7,11 len: 15 parameter: - cmd : packet identification (0x2742) - aid: account identification - - type: &1 ack vip data to char-serv, &2 add duration + - flag: 0x1 ack vip data to char-serv, 0x2 add duration, 0x8 First request on player login - timediff: tick to add to viptime - mapfd: map-serv link to ack if type&1 desc: @@ -468,16 +468,15 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket. 0x2743: Type: AH - Structure: .W .L .L .B .L .L .B - index: 0,2,6,10,11,15,16 - len: 20 + Structure: .W .L .L .B .L .L + index: 0,2,6,10,11,15 + len: 19 parameter: - cmd : packet identification (0x2743) - aid: account identification - vip_time: timestamp of vip_time if he is vip - - isvip: is this account in vip mode atm + - flag: 0x1: isvip, is this account in vip mode atm, 0x2: isgm, 0x4: show rates on player - groupid: group id of account - - isgm: is he a gm - mapfd: map-serv link to ack desc: - Transmit vip specific data to char-serv (will be transfered to mapserv) @@ -2501,16 +2500,15 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket. 0x2b2b Type: AZ - Structure: .W .L .L .B .B .L - index: 0,2,6,10,11,12 - len: 16 + Structure: .W .L .L .L .B + index: 0,2,6,10,11 + len: 15 parameter: - cmd : packet identification (0x2b2b) - aid - vip_time - - isvip - - isgm - groupid + - flag : 0x1: isvip, is this account in vip mode atm, 0x2: isgm, 0x4: show rates on player desc: - Received vip-data from char-serv, fill map-serv data diff --git a/src/char/char_logif.c b/src/char/char_logif.c index a1206ff20a..97a8ab852c 100644 --- a/src/char/char_logif.c +++ b/src/char/char_logif.c @@ -621,38 +621,37 @@ int chlogif_parse_updip(int fd, struct char_session_data* sd){ */ int chlogif_parse_vipack(int fd) { #ifdef VIP_ENABLE - if (RFIFOREST(fd) < 20) + if (RFIFOREST(fd) < 19) return 0; else { uint32 aid = RFIFOL(fd,2); //aid uint32 vip_time = RFIFOL(fd,6); //vip_time - uint8 isvip = RFIFOB(fd,10); //isvip + uint8 flag = RFIFOB(fd,10); uint32 groupid = RFIFOL(fd,11); //new group id - uint8 isgm = RFIFOB(fd,15); //isgm - int mapfd = RFIFOL(fd,16); //link to mapserv for ack - RFIFOSKIP(fd,20); - chmapif_vipack(mapfd,aid,vip_time,isvip,isgm,groupid); + int mapfd = RFIFOL(fd,15); //link to mapserv for ack + RFIFOSKIP(fd,19); + chmapif_vipack(mapfd,aid,vip_time,groupid,flag); } #endif return 1; } /** - * HZ 0x2b2b - * Request vip data from loginserv + * HA 0x2742 + * Request vip data to loginserv * @param aid : account_id to request the vip data - * @param type : &2 define new duration, &1 load info + * @param flag : 0x1 Select info and update old_groupid, 0x2 VIP duration is changed by atcommand or script, 0x8 First request on player login * @param add_vip_time : tick to add to vip timestamp * @param mapfd: link to mapserv for ack * @return 0 if success */ -int chlogif_reqvipdata(uint32 aid, uint8 type, int32 timediff, int mapfd) { +int chlogif_reqvipdata(uint32 aid, uint8 flag, int32 timediff, int mapfd) { loginif_check(-1); #ifdef VIP_ENABLE WFIFOHEAD(login_fd,15); WFIFOW(login_fd,0) = 0x2742; WFIFOL(login_fd,2) = aid; //aid - WFIFOB(login_fd,6) = type; //type + WFIFOB(login_fd,6) = flag; //flag WFIFOL(login_fd,7) = timediff; //req_inc_duration WFIFOL(login_fd,11) = mapfd; //req_inc_duration WFIFOSET(login_fd,15); diff --git a/src/char/char_logif.h b/src/char/char_logif.h index d7c9f650ef..cc19c52620 100644 --- a/src/char/char_logif.h +++ b/src/char/char_logif.h @@ -44,7 +44,7 @@ int chlogif_parse_askkick(int fd, struct char_session_data* sd); int chlogif_parse_updip(int fd, struct char_session_data* sd); int chlogif_parse_vipack(int fd); -int chlogif_reqvipdata(uint32 aid, uint8 type, int32 timediff, int mapfd); +int chlogif_reqvipdata(uint32 aid, uint8 flag, int32 timediff, int mapfd); int chlogif_req_accinfo(int fd, int u_fd, int u_aid, int u_group, int account_id, int8 type); int chlogif_parse(int fd); diff --git a/src/char/char_mapif.c b/src/char/char_mapif.c index 9d2669f482..b6ee3b2a61 100644 --- a/src/char/char_mapif.c +++ b/src/char/char_mapif.c @@ -1206,16 +1206,15 @@ int chmapif_parse_updfamelist(int fd){ * HZ 0x2b2b * Transmist vip data to mapserv */ -int chmapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint8 isgm, uint32 groupid) { +int chmapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint32 groupid, uint8 flag) { #ifdef VIP_ENABLE - uint8 buf[16]; + uint8 buf[15]; WBUFW(buf,0) = 0x2b2b; WBUFL(buf,2) = aid; WBUFL(buf,6) = vip_time; - WBUFB(buf,10) = isvip; - WBUFB(buf,11) = isgm; - WBUFL(buf,12) = groupid; - chmapif_send(mapfd,buf,16); // inform the mapserv back + WBUFL(buf,10) = groupid; + WBUFB(buf,14) = flag; + chmapif_send(mapfd,buf,15); // inform the mapserv back #endif return 0; } diff --git a/src/char/char_mapif.h b/src/char/char_mapif.h index 526f81de1f..141f4ac5c2 100644 --- a/src/char/char_mapif.h +++ b/src/char/char_mapif.h @@ -47,7 +47,7 @@ int chmapif_parse_reqauth(int fd, int id); int chmapif_parse_updmapip(int fd, int id); int chmapif_parse_fw_configstats(int fd); -int chmapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint8 isgm, uint32 groupid); +int chmapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint32 groupid, uint8 flag); int chmapif_parse_reqcharban(int fd); int chmapif_parse_reqcharunban(int fd); int chmapif_bonus_script_get(int fd); diff --git a/src/login/loginchrif.c b/src/login/loginchrif.c index 5f674a6484..a64a69ef88 100644 --- a/src/login/loginchrif.c +++ b/src/login/loginchrif.c @@ -206,18 +206,21 @@ int logchrif_send_accdata(int fd, uint32 aid) { /** * Transmit vip specific data to char-serv (will be transfered to mapserv) + * @param fd + * @param acc + * @param flag 0x1: VIP, 0x2: GM, 0x4: Show rates on player + * @param mapfd */ -int logchrif_sendvipdata(int fd, struct mmo_account acc, char isvip, char isgm, int mapfd) { +int logchrif_sendvipdata(int fd, struct mmo_account acc, unsigned char flag, int mapfd) { #ifdef VIP_ENABLE WFIFOHEAD(fd,19); WFIFOW(fd,0) = 0x2743; WFIFOL(fd,2) = acc.account_id; WFIFOL(fd,6) = (int)acc.vip_time; - WFIFOB(fd,10) = isvip; + WFIFOB(fd,10) = flag; WFIFOL(fd,11) = acc.group_id; //new group id - WFIFOL(fd,15) = isgm; - WFIFOL(fd,16) = mapfd; //link to mapserv - WFIFOSET(fd,20); + WFIFOL(fd,15) = mapfd; //link to mapserv + WFIFOSET(fd,19); logchrif_send_accdata(fd,acc.account_id); //refresh char with new setting #endif return 1; @@ -649,8 +652,9 @@ int logchrif_parse_pincode_authfail(int fd){ /** * Received a vip data reqest from char * type is the query to perform - * &1 : Select info and update old_groupid - * &2 : Update vip time + * 0x1 : Select info and update old_groupid + * 0x2 : VIP duration is changed by atcommand or script + * 0x8 : First request on player login * @param fd link to charserv * @return 0 missing data, 1 succeeded */ @@ -662,7 +666,7 @@ int logchrif_parse_reqvipdata(int fd) { struct mmo_account acc; AccountDB* accounts = login_get_accounts_db(); int aid = RFIFOL(fd,2); - int8 type = RFIFOB(fd,6); + int8 flag = RFIFOB(fd,6); int32 timediff = RFIFOL(fd,7); int mapfd = RFIFOL(fd,11); RFIFOSKIP(fd,15); @@ -673,10 +677,10 @@ int logchrif_parse_reqvipdata(int fd) { bool isvip = false; if( acc.group_id > login_config.vip_sys.group ) { //Don't change group if it's higher. - logchrif_sendvipdata(fd,acc,false,true,mapfd); + logchrif_sendvipdata(fd,acc,0x2|((flag&0x8)?0x4:0),mapfd); return 1; } - if( type&2 ) { + if( flag&2 ) { if(!vip_time) vip_time = now; //new entry vip_time += timediff; // set new duration @@ -696,8 +700,8 @@ int logchrif_parse_reqvipdata(int fd) { } acc.vip_time = vip_time; accounts->save(accounts,&acc); - if( type&1 ) - logchrif_sendvipdata(fd,acc,isvip,false,mapfd); + if( flag&1 ) + logchrif_sendvipdata(fd,acc,((isvip)?0x1:0)|((flag&0x8)?0x4:0),mapfd); } } #endif diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 714e988907..b837410d0c 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -9549,8 +9549,6 @@ ACMD_FUNC(vip) { pl_sd->vip.time += vipdifftime; //increase or reduce VIP duration if (pl_sd->vip.time <= now) { - pl_sd->vip.time = 0; - pl_sd->vip.enabled = 0; clif_displaymessage(pl_sd->fd, msg_txt(pl_sd,703)); // GM has removed your VIP time. clif_displaymessage(fd, msg_txt(sd,704)); // Player is no longer VIP. } else { diff --git a/src/map/chrif.c b/src/map/chrif.c index e596413944..f26d136e11 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -39,7 +39,7 @@ static const int packet_len_table[0x3d] = { // U - used, F - free 11,10,10, 0,11, -1,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, U->2b15, U->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 -1,10, 8, 2, 2,14,19,19, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27 - -1, 0, 6,16, 0, 6,-1,-1, // 2b28-2b2f: U->2b28, F->2b29, U->2b2a, U->2b2b, F->2b2c, U->2b2d, U->2b2e, U->2b2f + -1, 0, 6,15, 0, 6,-1,-1, // 2b28-2b2f: U->2b28, F->2b29, U->2b2a, U->2b2b, F->2b2c, U->2b2d, U->2b2e, U->2b2f }; //Used Packets: @@ -849,6 +849,10 @@ int chrif_changeemail(int id, const char *actual_email, const char *new_email) { * @operation_type : see chrif_req_op * @timediff : tick to add or remove to unixtimestamp * @val1 : extra data value to transfer for operation + * CHRIF_OP_LOGIN_VIP: 0x1 : Select info and update old_groupid + * 0x2 : VIP duration is changed by atcommand or script + * 0x4 : Show status reply by char-server through 0x2b0f + * 0x8 : First request on player login * @val2 : extra data value to transfer for operation */ int chrif_req_login_operation(int aid, const char* character_name, enum chrif_req_op operation_type, int32 timediff, int val1, int val2) { @@ -1575,38 +1579,44 @@ void chrif_parse_ack_vipActive(int fd) { #ifdef VIP_ENABLE int aid = RFIFOL(fd,2); uint32 vip_time = RFIFOL(fd,6); - bool isvip = RFIFOB(fd,10); - bool isgm = RFIFOB(fd,11); - uint32 groupid = RFIFOL(fd,12); + uint32 groupid = RFIFOL(fd,10); + uint8 flag = RFIFOB(fd,14); TBL_PC *sd = map_id2sd(aid); + bool changed = false; if(sd == NULL) return; sd->group_id = groupid; pc_group_pc_load(sd); - if(isgm) { + if ((flag&0x2)) //isgm clif_displaymessage(sd->fd,msg_txt(sd,437)); - return; - } - if(isvip) { - sd->vip.enabled = 1; - sd->vip.time = vip_time; - // Increase storage size for VIP. - sd->storage_size = battle_config.vip_storage_increase + MIN_STORAGE; - if (sd->storage_size > MAX_STORAGE) { - ShowError("intif_parse_ack_vipActive: Storage size for player %s (%d:%d) is larger than MAX_STORAGE. Storage size has been set to MAX_STORAGE.\n", sd->status.name, sd->status.account_id, sd->status.char_id); - sd->storage_size = MAX_STORAGE; + else { + changed = (sd->vip.enabled != (flag&0x1)); + if((flag&0x1)) { //isvip + sd->vip.enabled = 1; + sd->vip.time = vip_time; + // Increase storage size for VIP. + sd->storage_size = battle_config.vip_storage_increase + MIN_STORAGE; + if (sd->storage_size > MAX_STORAGE) { + ShowError("intif_parse_ack_vipActive: Storage size for player %s (%d:%d) is larger than MAX_STORAGE. Storage size has been set to MAX_STORAGE.\n", sd->status.name, sd->status.account_id, sd->status.char_id); + sd->storage_size = MAX_STORAGE; + } + // Magic Stone requirement avoidance for VIP. + if (battle_config.vip_gemstone) + sd->special_state.no_gemstone = 2; // need to be done after status_calc_bl(bl,first); + } else if (sd->vip.enabled) { + sd->vip.enabled = 0; + sd->vip.time = 0; + sd->storage_size = MIN_STORAGE; + sd->special_state.no_gemstone = 0; + clif_displaymessage(sd->fd,msg_txt(sd,438)); } - // Magic Stone requirement avoidance for VIP. - if (battle_config.vip_gemstone) - sd->special_state.no_gemstone = 2; // need to be done after status_calc_bl(bl,first); - } else if (sd->vip.enabled) { - sd->vip.enabled = 0; - sd->vip.time = 0; - sd->storage_size = MIN_STORAGE; - sd->special_state.no_gemstone = 0; - clif_displaymessage(sd->fd,msg_txt(sd,438)); + } + // Show info if status changed + if (((flag&0x4) || changed) && !sd->vip.disableshowrate) { + clif_display_pinfo(sd,ZC_PERSONAL_INFOMATION); + //clif_vip_display_info(sd,ZC_PERSONAL_INFOMATION_CHN); } #endif } diff --git a/src/map/clif.c b/src/map/clif.c index 9471f46452..c18919193f 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -10232,7 +10232,6 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if(sd->state.connect_new) { int lv; guild_notice = true; - sd->state.connect_new = 0; clif_skillinfoblock(sd); clif_hotkeys_send(sd); clif_updatestatus(sd,SP_BASEEXP); @@ -10303,12 +10302,6 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) clif_partyinvitationstate(sd); clif_equipcheckbox(sd); #endif -#ifdef VIP_ENABLE - if (!sd->vip.disableshowrate) { - clif_display_pinfo(sd,ZC_PERSONAL_INFOMATION); - //clif_vip_display_info(sd,ZC_PERSONAL_INFOMATION_CHN); - } -#endif if (sd->guild && battle_config.guild_notice_changemap == 1) clif_guild_notice(sd, sd->guild); // Displays after VIP @@ -10353,7 +10346,18 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) status_change_clear_onChangeMap(&sd->bl, &sd->sc); map_iwall_get(sd); // Updates Walls Info on this Map to Client status_calc_pc(sd, SCO_NONE); // Some conditions are map-dependent so we must recalculate - sd->state.changemap = false; + +#ifdef VIP_ENABLE + if (!sd->state.connect_new && + !sd->vip.disableshowrate && + sd->state.pmap != sd->bl.m && + map[sd->state.pmap].adjust.bexp != map[sd->bl.m].adjust.bexp + ) + { + clif_display_pinfo(sd,ZC_PERSONAL_INFOMATION); + //clif_vip_display_info(sd,ZC_PERSONAL_INFOMATION_CHN); + } +#endif // Instances do not need their own channels if( channel_config.map_enable && channel_config.map_autojoin && !map[sd->bl.m].flag.chmautojoin && !map[sd->bl.m].instance_id ) @@ -10420,6 +10424,9 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) pc_show_questinfo_reinit(sd); pc_show_questinfo(sd); + + sd->state.connect_new = 0; + sd->state.changemap = false; } diff --git a/src/map/pc.c b/src/map/pc.c index 28c76a4fd1..c5f30c7338 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1443,7 +1443,7 @@ void pc_reg_received(struct map_session_data *sd) #ifdef VIP_ENABLE sd->vip.time = 0; sd->vip.enabled = 0; - chrif_req_login_operation(sd->status.account_id, sd->status.name, CHRIF_OP_LOGIN_VIP, 0, 1, 0); // request VIP information + chrif_req_login_operation(sd->status.account_id, sd->status.name, CHRIF_OP_LOGIN_VIP, 0, 1|8, 0); // request VIP information #endif intif_Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox intif_request_questlog(sd);