diff options
author | Haru <haru@dotalux.com> | 2020-06-28 03:32:35 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-28 03:32:35 +0200 |
commit | 92022a5728dbd3a2e95b007276cd4eb926885bac (patch) | |
tree | 942830c72893a6041d693371a1147a9023cec0bc | |
parent | 9b22213254d64b2c155c6700030303852fd5b912 (diff) | |
parent | ddf679b3808e56309a7352eead2cd1f93c9f99c9 (diff) | |
download | hercules-92022a5728dbd3a2e95b007276cd4eb926885bac.tar.gz hercules-92022a5728dbd3a2e95b007276cd4eb926885bac.tar.bz2 hercules-92022a5728dbd3a2e95b007276cd4eb926885bac.tar.xz hercules-92022a5728dbd3a2e95b007276cd4eb926885bac.zip |
Merge pull request #2757 from Kenpachi2k13/server_messages
Adjust server messages on login and map change
-rw-r--r-- | conf/map/battle/client.conf | 36 | ||||
-rw-r--r-- | conf/map/battle/guild.conf | 12 | ||||
-rw-r--r-- | conf/map/battle/party.conf | 27 | ||||
-rw-r--r-- | src/map/battle.c | 7 | ||||
-rw-r--r-- | src/map/battle.h | 5 | ||||
-rw-r--r-- | src/map/clif.c | 409 | ||||
-rw-r--r-- | src/map/clif.h | 9 | ||||
-rw-r--r-- | src/map/packets_struct.h | 18 | ||||
-rw-r--r-- | src/map/party.c | 33 | ||||
-rw-r--r-- | src/map/party.h | 2 | ||||
-rw-r--r-- | src/map/pc.c | 1 |
11 files changed, 447 insertions, 112 deletions
diff --git a/conf/map/battle/client.conf b/conf/map/battle/client.conf index 5601dbc9e..d4c0f3e1a 100644 --- a/conf/map/battle/client.conf +++ b/conf/map/battle/client.conf @@ -202,3 +202,39 @@ ping_time: 20 // Drop or not connection after client send disconnect request packet // Official is false drop_connection_on_quit: false + +// When to display the rate modifier messages? +// 0x0 - Never display rate modifier messages. +// 0x1 - Display rate modifier messages upon login. +// 0x2 - Display rate modifier messages upon map change. +// 0x4 - Display rate modifier messages upon teleporting (regardless of changing maps). +// Default: 0x1 (Official behavior.) +display_rate_messages: 0x1 + +// When to display the configuration messages and which? (Note 3) +// +// Flags for when to display the configuration messages: +// 0x000 - Never display configuration messages. +// 0x001 - Display configuration messages upon login. (Default. Should always be set.) +// 0x002 - Display configuration messages upon map change. +// 0x004 - Display configuration messages upon teleporting (regardless of changing maps). +// +// Flags for which configuration messages are displayed: +// 0x010 - Character's party invitation state. (Default.) +// 0x020 - Character's view equipment state. (Default.) +// 0x040 - Character's Urgent Call state. (Default.) +// 0x080 - Character's pet auto-feed state. (Default.) +// 0x100 - Character's homunculus auto-feed state. (Default.) +// +// Default: 0x1F1 (Official behavior.) +display_config_messages: 0x1F1 + +// When to display the overweight messages? +// 0x0 - Never display overweight messages. +// 0x1 - Display overweight messages upon login. (Default.) +// 0x2 - Display overweight messages upon map change. (Default.) +// Default: 0x3 (Official behavior.) +display_overweight_messages: 0x3 + +// Show tip of the day window upon login? +show_tip_window: true diff --git a/conf/map/battle/guild.conf b/conf/map/battle/guild.conf index 781f6555b..204c295c3 100644 --- a/conf/map/battle/guild.conf +++ b/conf/map/battle/guild.conf @@ -59,11 +59,13 @@ require_glory_guild: false // Default is 3 max_guild_alliance: 3 -// When to re-display the guild notice -// Upon teleporting (regardless of changing maps): 2 (official) -// Upon changing maps: 1 -// Do not re-display: 0 (disabled) -guild_notice_changemap: 2 +// When to display the guild notice? +// 0x0 - Never display guild notice. +// 0x1 - Display guild notice upon login. +// 0x2 - Display guild notice upon map change. +// 0x4 - Display guild notice upon teleporting (regardless of changing maps). +// Default: 0x7 (Official behavior.) +guild_notice_changemap: 0x7 // Can guild members invite/expel members inside guild castles in WoE/GvG? (Note 1) // default: false diff --git a/conf/map/battle/party.conf b/conf/map/battle/party.conf index e27a709fd..7713d5376 100644 --- a/conf/map/battle/party.conf +++ b/conf/map/battle/party.conf @@ -80,3 +80,30 @@ party_even_share_bonus: 0 // Display party name regardless if player is in a guild. // Official servers do not display party name unless the user is in a guild. (Note 1) display_party_name: false + +// When and how to send the party options? (Note 3) +// +// Flags for when to display the party options: +// 0x00000 - Never send party options. +// 0x00001 - Send party options upon login. (Default. Should always be set.) +// 0x00002 - Send party options upon map change. +// 0x00004 - Send party options upon teleporting (regardless of changing maps). +// 0x00008 - Send party options upon successfully changing options manually. (Default. Should always be set.) +// 0x00010 - Send party options upon unsuccessfully changing options manually. (Tried to enable EXP sharing if not allowed.) (Default.) +// 0x00020 - Send party options upon changing options automatically. (Default. Should always be set.) +// 0x00040 - Send party options upon joining party. (Default. Should always be set.) +// 0x00080 - Send party options upon leaving party. (Default.) +// +// Flags for how to send the party options: +// 0x00100 - Send party options to all party members upon unsuccessfully changing options manually. (Tried to enable EXP sharing if not allowed.) (Default.) +// 0x00200 - Send all party options upon login. +// 0x00400 - Send all party options upon map change. +// 0x00800 - Send all party options upon teleporting (regardless of changing maps). +// 0x01000 - Send all party options upon successfully changing options manually. (Default.) +// 0x02000 - Send all party options upon unsuccessfully changing options manually. (Tried to enable EXP sharing if not allowed.) (Default.) +// 0x04000 - Send all party options upon changing options automatically. +// 0x08000 - Send all party options upon joining party. +// 0x10000 - Send all party options upon leaving party. +// +// Default: 0x31F9 (Official behavior.) +send_party_options: 0x31F9 diff --git a/src/map/battle.c b/src/map/battle.c index 40a7c4b09..bea1c7ab2 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -7346,6 +7346,7 @@ static const struct battle_data { { "searchstore_querydelay", &battle_config.searchstore_querydelay, 10, 0, INT_MAX, }, { "searchstore_maxresults", &battle_config.searchstore_maxresults, 30, 1, INT_MAX, }, { "display_party_name", &battle_config.display_party_name, 0, 0, 1, }, + { "send_party_options", &battle_config.send_party_options, 0x31F9, 0, 0x1FFFF, }, { "cashshop_show_points", &battle_config.cashshop_show_points, 0, 0, 1, }, { "mail_show_status", &battle_config.mail_show_status, 0, 0, 2, }, { "client_limit_unit_lv", &battle_config.client_limit_unit_lv, 0, 0, BL_ALL, }, @@ -7384,7 +7385,7 @@ static const struct battle_data { { "packet_obfuscation", &battle_config.packet_obfuscation, 1, 0, 3, }, { "client_accept_chatdori", &battle_config.client_accept_chatdori, 0, 0, INT_MAX, }, { "snovice_call_type", &battle_config.snovice_call_type, 0, 0, 1, }, - { "guild_notice_changemap", &battle_config.guild_notice_changemap, 2, 0, 2, }, + { "guild_notice_changemap", &battle_config.guild_notice_changemap, 7, 0, 7, }, { "features/banking", &battle_config.feature_banking, 1, 0, 1, }, { "features/auction", &battle_config.feature_auction, 0, 0, 2, }, { "idletime_criteria", &battle_config.idletime_criteria, 0x25, 1, INT_MAX, }, @@ -7432,6 +7433,10 @@ static const struct battle_data { { "ping_time", &battle_config.ping_time, 20, 0, 99999999, }, { "option_drop_max_loop", &battle_config.option_drop_max_loop, 10, 1, 100000, }, { "drop_connection_on_quit", &battle_config.drop_connection_on_quit, 0, 0, 1, }, + { "display_rate_messages", &battle_config.display_rate_messages, 1, 0, 7, }, + { "display_config_messages", &battle_config.display_config_messages, 0x1F1, 0, 0x1F7, }, + { "display_overweight_messages", &battle_config.display_overweight_messages, 3, 0, 3, }, + { "show_tip_window", &battle_config.show_tip_window, 1, 0, 1, }, { "features/enable_refinery_ui", &battle_config.enable_refinery_ui, 1, 0, 1, }, { "features/replace_refine_npcs", &battle_config.replace_refine_npcs, 1, 0, 1, }, { "batk_min_limit", &battle_config.batk_min, 0, 0, INT_MAX, }, diff --git a/src/map/battle.h b/src/map/battle.h index 2db890a42..f648718ff 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -472,6 +472,7 @@ struct Battle_Config { int searchstore_querydelay; int searchstore_maxresults; int display_party_name; + int send_party_options; int cashshop_show_points; int mail_show_status; int client_limit_unit_lv; @@ -591,6 +592,10 @@ struct Battle_Config { int option_drop_max_loop; int drop_connection_on_quit; + int display_rate_messages; + int display_config_messages; + int display_overweight_messages; + int show_tip_window; int enable_refinery_ui; int replace_refine_npcs; diff --git a/src/map/clif.c b/src/map/clif.c index 6a6fc5a90..bf737b4e7 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -7295,46 +7295,101 @@ static void clif_party_inviteack(struct map_session_data *sd, const char *nick, #endif } -/// Updates party settings. -/// 0101 <exp option>.L (ZC_GROUPINFO_CHANGE) -/// 07d8 <exp option>.L <item pick rule>.B <item share rule>.B (ZC_REQ_GROUPINFO_CHANGE_V2) -/// exp option: -/// 0 = exp sharing disabled -/// 1 = exp sharing enabled -/// 2 = cannot change exp sharing -/// -/// flag: -/// 0 = send to party -/// 1 = send to sd +/** + * Sends party settings to the client. + * + * 0101 <exp option>.L (ZC_GROUPINFO_CHANGE) + * 07d8 <exp option>.L <item pick rule>.B <item share rule>.B (ZC_REQ_GROUPINFO_CHANGE_V2) + * <exp option>: + * 0 = EXP sharing disabled. + * 1 = EXP sharing enabled. + * 2 = Cannot change EXP sharing. + * + * @param p The related party. + * @param sd The related character. + * @param flag Reason for sending. + * @parblock + * Possible flags: + * 0x01 = Cannot change EXP sharing. (Only set when tried to change options manually.) + * 0x02 = Options changed manually. + * 0x04 = Options changed automatically. + * 0x08 = Member added. + * 0x10 = Member removed. + * 0x20 = Character logged in. + * 0x40 = Character changed map. + * 0x80 = Character teleported. + * @endparblock + * + **/ static void clif_party_option(struct party_data *p, struct map_session_data *sd, int flag) { - unsigned char buf[16]; + nullpo_retv(p); + + if (sd == NULL && (flag & 0x01) == 0) { + for (int i = 0; i < MAX_PARTY; i++) { + if (p->data[i].sd != NULL) { + sd = p->data[i].sd; + break; + } + } + } + + if (sd == NULL) + return; + + int conf = battle_config.send_party_options; + + if (((flag & 0x01) != 0 && (conf & 0x10) == 0) + || ((flag & 0x02) != 0 && (conf & 0x08) == 0) + || ((flag & 0x04) != 0 && (conf & 0x20) == 0) + || ((flag & 0x08) != 0 && (conf & 0x40) == 0) + || ((flag & 0x10) != 0 && (conf & 0x80) == 0) + || ((flag & 0x20) != 0 && (conf & 0x01) == 0) + || ((flag & 0x40) != 0 && (conf & 0x02) == 0) + || ((flag & 0x80) != 0 && (conf & 0x04) == 0)) { + return; + } + + enum send_target target = SELF; + + if (((flag & 0x01) != 0 && (conf & 0x100) != 0) + || ((flag & 0x01) == 0 && (flag & 0x02) != 0) + || (flag & 0x04) != 0) { + target = PARTY; + } + + int cmd = 0x101; + + if (((flag & 0x01) != 0 && (conf & 0x02000) != 0) + || ((flag & 0x02) != 0 && (conf & 0x01000) != 0) + || ((flag & 0x04) != 0 && (conf & 0x04000) != 0) + || ((flag & 0x08) != 0 && (conf & 0x08000) != 0) + || ((flag & 0x10) != 0 && (conf & 0x10000) != 0) + || ((flag & 0x20) != 0 && (conf & 0x00200) != 0) + || ((flag & 0x40) != 0 && (conf & 0x00400) != 0) + || ((flag & 0x80) != 0 && (conf & 0x00800) != 0)) { + cmd = 0x7d8; + } + #if PACKETVER < 20090603 - const int cmd = 0x101; -#else - const int cmd = 0x7d8; + if (cmd == 0x7d8) + cmd = 0x101; #endif - nullpo_retv(p); + unsigned char buf[16]; - if(!sd && flag==0){ - int i; - for(i=0;i<MAX_PARTY && !p->data[i].sd;i++) - ; - if (i < MAX_PARTY) - sd = p->data[i].sd; + WBUFW(buf, 0) = cmd; + WBUFL(buf, 2) = ((flag & 0x10) != 0) ? 0 : (((flag & 0x01) != 0) ? 2 : p->party.exp); + + if (cmd == 0x7d8) { + WBUFB(buf, 6) = ((flag & 0x10) != 0) ? 0 : (((p->party.item & 1) != 0) ? 1 : 0); + WBUFB(buf, 7) = ((flag & 0x10) != 0) ? 0 : (((p->party.item & 2) != 0) ? 1 : 0); } - if(!sd) return; - WBUFW(buf,0)=cmd; - WBUFL(buf,2)=((flag&0x01)?2:p->party.exp); -#if PACKETVER >= 20090603 - WBUFB(buf,6)=(p->party.item&1)?1:0; - WBUFB(buf,7)=(p->party.item&2)?1:0; -#endif - if(flag==0) - clif->send(buf,packet_len(cmd),&sd->bl,PARTY); - else - clif->send(buf,packet_len(cmd),&sd->bl,SELF); + + clif->send(buf, packet_len(cmd), &sd->bl, target); + + if ((flag & 0x04) != 0) + p->state.option_auto_changed = 0; } /// 0105 <account id>.L <char name>.24B <result>.B (ZC_DELETE_MEMBER_FROM_GROUP). @@ -10616,6 +10671,97 @@ static void clif_parse_WantToConnection(int fd, struct map_session_data *sd) } /** + * Displays the common server messages upon login, chaning maps or teleporting to a character. + * + * @param sd The character who should receive the messages. + * @param connect_new Whether the character is logging in. + * @param change_map Whether the character is changing maps. + * + **/ +static void clif_load_end_ack_sub_messages(struct map_session_data *sd, bool connect_new, bool change_map) +{ + nullpo_retv(sd); + + /** Display overweight messages. **/ + if (((battle_config.display_overweight_messages & 0x1) != 0 && connect_new) + || ((battle_config.display_overweight_messages & 0x2) != 0 && !connect_new && change_map)) { + // Send the character's weight to the client. (With displaying overweight messages.) + clif->updatestatus(sd, SP_MAXWEIGHT); + clif->updatestatus(sd, SP_WEIGHT); + } else { + // Send the character's weight to the client. (Without displaying overweight messages.) + clif->updatestatus(sd, SP_WEIGHT); + clif->updatestatus(sd, SP_MAXWEIGHT); + } + + /** Display configuration messages. **/ + if (((battle_config.display_config_messages & 0x1) != 0 && connect_new) + || ((battle_config.display_config_messages & 0x2) != 0 && !connect_new && change_map) + || (battle_config.display_config_messages & 0x4) != 0) { +#if PACKETVER >= 20070918 + if ((battle_config.display_config_messages & 0x10) != 0) + clif->partyinvitationstate(sd); + + if ((battle_config.display_config_messages & 0x20) != 0) + clif->equpcheckbox(sd); +#endif + +#if PACKETVER_MAIN_NUM >= 20171025 || PACKETVER_RE_NUM >= 20170920 + if ((battle_config.display_config_messages & 0x40) != 0) + clif->zc_config(sd, CZ_CONFIG_CALL, sd->status.allow_call); + + if ((battle_config.display_config_messages & 0x80) != 0) { + if (sd->pd != NULL) + clif->zc_config(sd, CZ_CONFIG_PET_AUTOFEEDING, sd->pd->pet.autofeed); + else + clif->zc_config(sd, CZ_CONFIG_PET_AUTOFEEDING, false); + } + + if ((battle_config.display_config_messages & 0x100) != 0) { + if (sd->hd != NULL) + clif->zc_config(sd, CZ_CONFIG_HOMUNCULUS_AUTOFEEDING, sd->hd->homunculus.autofeed); + else + clif->zc_config(sd, CZ_CONFIG_HOMUNCULUS_AUTOFEEDING, false); + } +#endif + } + + /** Display party options. **/ + struct party_data *p = NULL; + + if (sd->status.party_id != 0 && (p = party->search(sd->status.party_id)) != NULL) { + int flag; + + if (p->state.option_auto_changed != 0) + flag = 0x04; + else if (connect_new) + flag = 0x20; + else if (change_map) + flag = 0x40; + else + flag = 0x80; + + clif->party_option(p, sd, flag); + } + + /** Display rate modifier messages. **/ + if (((battle_config.display_rate_messages & 0x1) != 0 && connect_new) + || ((battle_config.display_rate_messages & 0x2) != 0 && !connect_new && change_map) + || (battle_config.display_rate_messages & 0x4) != 0) { + clif->show_modifiers(sd); + } + + /** Display guild notice. **/ + if (sd->guild != NULL) { + if (((battle_config.guild_notice_changemap & 0x1) != 0 && connect_new) + || ((battle_config.guild_notice_changemap & 0x2) != 0 && !connect_new && change_map) + || (battle_config.guild_notice_changemap & 0x4) != 0) { + clif->guild_notice(sd, sd->guild); + } + } +} + +/** * Notification from the client, that it has finished map loading and is about to display player's character. (CZ_NOTIFY_ACTORINIT) * * @code @@ -10738,10 +10884,6 @@ static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) // Check for and delete unavailable/disabled items. pc->checkitem(sd); - // Send the character's weight to the client. - clif->updatestatus(sd, SP_WEIGHT); - clif->updatestatus(sd, SP_MAXWEIGHT); - // Send character's guild info to the client. Call this before clif->spawn() to show guild emblems correctly. if (sd->status.guild_id != 0) guild->send_memberinfoshort(sd, 1); @@ -10770,9 +10912,18 @@ static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) map->addblock(&sd->bl); // Add the character to the map. clif->spawn(&sd->bl); // Spawn character client side. + clif_load_end_ack_sub_messages(sd, (sd->state.connect_new != 0), (sd->state.changemap != 0)); + + struct party_data *p = NULL; + + if (sd->status.party_id != 0) + p = party->search(sd->status.party_id); + // Send character's party info to the client. Call this after clif->spawn() to show HP bars correctly. - if (sd->status.party_id != 0) { - party->send_movemap(sd); + if (p != NULL) { + if (sd->state.connect_new == 0) // Login is handled in party_member_joined(). + party->send_movemap(sd); + clif->party_hp(sd); // Show HP after displacement. [LuzZza] } @@ -10852,10 +11003,7 @@ static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) status_calc_bl(&sd->ed->bl, SCB_SPEED); // Elementals mimic their master's speed on each map change. } - bool first_time = false; - if (sd->state.connect_new != 0) { - first_time = true; sd->state.connect_new = 0; clif->skillinfoblock(sd); clif->hotkeysAll(sd); @@ -10920,6 +11068,11 @@ static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) // Notify everyone that this character logged in. [Skotlex] map->foreachpc(clif->friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 1); +#if PACKETVER >= 20171122 + if (battle_config.show_tip_window != 0) + clif->open_ui_send(sd, ZC_TIPBOX_UI); +#endif + // Run OnPCLoginEvent labels. npc->script_event(sd, NPCE_LOGIN); } else { @@ -10941,26 +11094,9 @@ static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) } else { sd->state.warp_clean = 1; } - - if (sd->guild != NULL && ((battle_config.guild_notice_changemap == 1 && sd->state.changemap != 0) - || battle_config.guild_notice_changemap == 2)) { - clif->guild_notice(sd, sd->guild); - } } if (sd->state.changemap != 0) { // Restore information that gets lost on map-change. -#if PACKETVER >= 20070918 - clif->partyinvitationstate(sd); - clif->equpcheckbox(sd); -#endif - -#if PACKETVER_MAIN_NUM >= 20171025 || PACKETVER_RE_NUM >= 20170920 - if (sd->hd != NULL) - clif->zc_config(sd, CZ_CONFIG_HOMUNCULUS_AUTOFEEDING, sd->hd->homunculus.autofeed); - else - clif->zc_config(sd, CZ_CONFIG_HOMUNCULUS_AUTOFEEDING, false); -#endif - bool flee_penalty = (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100); bool is_gvg = (map_flag_gvg2(sd->state.pmap) || map_flag_gvg2(sd->bl.m)); bool is_bg = (map->list[sd->state.pmap].flag.battleground != 0 || map->list[sd->bl.m].flag.battleground != 0); @@ -11009,12 +11145,14 @@ static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) mail->clear(sd); clif->maptypeproperty2(&sd->bl, SELF); - // Init guild aura. - if (sd->state.gmaster_flag != 0) { - guild->aura_refresh(sd, GD_LEADERSHIP, guild->checkskill(sd->guild, GD_LEADERSHIP)); - guild->aura_refresh(sd, GD_GLORYWOUNDS, guild->checkskill(sd->guild, GD_GLORYWOUNDS)); - guild->aura_refresh(sd, GD_SOULCOLD, guild->checkskill(sd->guild, GD_SOULCOLD)); - guild->aura_refresh(sd, GD_HAWKEYES, guild->checkskill(sd->guild, GD_HAWKEYES)); + if (sd->guild != NULL) { + // Init guild aura. + if (sd->state.gmaster_flag != 0) { + guild->aura_refresh(sd, GD_LEADERSHIP, guild->checkskill(sd->guild, GD_LEADERSHIP)); + guild->aura_refresh(sd, GD_GLORYWOUNDS, guild->checkskill(sd->guild, GD_GLORYWOUNDS)); + guild->aura_refresh(sd, GD_SOULCOLD, guild->checkskill(sd->guild, GD_SOULCOLD)); + guild->aura_refresh(sd, GD_HAWKEYES, guild->checkskill(sd->guild, GD_HAWKEYES)); + } } if (sd->state.vending != 0) { // Character is vending. @@ -11039,10 +11177,6 @@ static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) clif->weather_check(sd); - // This should be displayed last. - if (sd->guild != NULL && first_time) - clif->guild_notice(sd, sd->guild); - // For automatic triggering of NPCs after map loading. (So you don't need to walk 1 step first.) if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNPC) != 0) npc->touch_areanpc(sd, sd->bl.m, sd->bl.x, sd->bl.y); @@ -20949,20 +21083,57 @@ static void clif_bank_withdraw(struct map_session_data *sd, enum e_BANKING_WITHD #endif } -/* TODO: official response packet (tried 0x8cb/0x97b but the display was quite screwed up.) */ -/* currently mimicing */ +/** + * Sends EXP, drop and death-penalty rates. + * 0x097b <packet len>.W <exp>.L <death>.L <drop>.L <DETAIL_EXP_INFO>13B (ZC_PERSONAL_INFOMATION2) + * <InfoType>.B <Exp>.L <Death>.L <Drop>.L (DETAIL_EXP_INFO) + * + * @param sd The character which should receive the messages. + * + **/ static void clif_show_modifiers(struct map_session_data *sd) { nullpo_retv(sd); - if( sd->status.mod_exp != 100 || sd->status.mod_drop != 100 || sd->status.mod_death != 100 ) { +#if PACKETVER_MAIN_NUM >= 20120503 || PACKETVER_RE_NUM >= 20120502 || defined(PACKETVER_ZERO) + int length = sizeof(struct PACKET_ZC_PERSONAL_INFOMATION) + 4 * sizeof(struct PACKET_ZC_PERSONAL_INFOMATION_SUB); + WFIFOHEAD(sd->fd, length); + struct PACKET_ZC_PERSONAL_INFOMATION *p = WFIFOP(sd->fd, 0); + + p->packetType = HEADER_ZC_PERSONAL_INFOMATION; + p->length = length; + // Single values. + p->details[0].type = PC_EXP_INFO; + p->details[0].exp = 0; + p->details[0].death = 0; + p->details[0].drop = 0; + p->details[1].type = TPLUS_EXP_INFO; + p->details[1].exp = 0; + p->details[1].death = 0; + p->details[1].drop = 0; + p->details[2].type = PREMIUM_EXP_INFO; + p->details[2].exp = (sd->status.mod_exp - 100) * 1000; + p->details[2].death = (sd->status.mod_death - 100) * 1000; + p->details[2].drop = (sd->status.mod_drop - 100) * 1000; + p->details[3].type = SERVER_EXP_INFO; + p->details[3].exp = battle_config.base_exp_rate * 1000; + p->details[3].death = battle_config.death_penalty_base * 10; + p->details[3].drop = battle_config.item_rate_common * 1000; + // Total values. + p->total_exp = (battle_config.base_exp_rate * sd->status.mod_exp / 100) * 1000; + p->total_death = (battle_config.base_exp_rate * sd->status.mod_death / 100) * 10; + p->total_drop = (battle_config.base_exp_rate * sd->status.mod_drop / 100) * 1000; + + WFIFOSET(sd->fd, length); +#else + if (sd->status.mod_exp != 100 || sd->status.mod_drop != 100 || sd->status.mod_death != 100) { char output[128]; - snprintf(output,128, msg_sd(sd, 896), // Base EXP : %d%% | Base Drop: %d%% | Base Death Penalty: %d%% - sd->status.mod_exp,sd->status.mod_drop,sd->status.mod_death); + // Base EXP : %d%% | Base Drop: %d%% | Base Death Penalty: %d%% + safesnprintf(output, sizeof(output), msg_sd(sd, 896), sd->status.mod_exp, sd->status.mod_drop, sd->status.mod_death); clif->broadcast2(&sd->bl, output, (int)strlen(output) + 1, 0xffbc90, 0x190, 12, 0, 0, SELF); } - +#endif // PACKETVER_MAIN_NUM >= 20120503 || PACKETVER_RE_NUM >= 20120502 || defined(PACKETVER_ZERO) } static void clif_notify_bounditem(struct map_session_data *sd, unsigned short index) @@ -22988,61 +23159,65 @@ static void clif_parse_open_ui_request(int fd, struct map_session_data *sd) clif->open_ui(sd, p->UIType); } -static void clif_open_ui(struct map_session_data *sd, enum cz_ui_types uiType) +/** + * Does the actual packet sending for clif_open_ui(). + * + * @param sd The character who opens the UI. + * @param ui_type The UI which should be opened. + * + **/ +static void clif_open_ui_send(struct map_session_data *sd, enum zc_ui_types ui_type) { + nullpo_retv(sd); + #if PACKETVER >= 20150128 struct PACKET_ZC_OPEN_UI p; -#if PACKETVER_RE_NUM >= 20180307 || PACKETVER_MAIN_NUM >= 20180404 || PACKETVER_ZERO_NUM >= 20180411 - int claimed = 0; -#endif - - nullpo_retv(sd); p.PacketType = openUiType; - switch (uiType) { - case CZ_STYLIST_UI: - p.UIType = ZC_STYLIST_UI; -#if PACKETVER >= 20171122 - p.data = 0; -#endif - break; - case CZ_MACRO_REGISTER_UI: - p.UIType = ZC_CAPTCHA_UI; + p.UIType = ui_type; + + switch (ui_type) { + case ZC_BANK_UI: + case ZC_STYLIST_UI: + case ZC_CAPTCHA_UI: + case ZC_MACRO_UI: #if PACKETVER >= 20171122 p.data = 0; #endif break; - case CZ_MACRO_DETECTOR_UI: - p.UIType = ZC_MACRO_UI; #if PACKETVER >= 20171122 + case ZC_TIPBOX_UI: + case ZC_RENEWQUEST_UI: p.data = 0; -#endif break; - case CZ_ATTENDANCE_UI: - { + case ZC_ATTENDANCE_UI: + if (battle_config.feature_enable_attendance_system == 0) + return; + if (clif->attendance_getendtime() < time(NULL)) { #if PACKETVER >= 20180207 clif->msgtable_color(sd, MSG_ATTENDANCE_UNAVAILABLE, COLOR_RED); #endif return; } - if (battle_config.feature_enable_attendance_system != 1) - return; + #if PACKETVER_RE_NUM >= 20180307 || PACKETVER_MAIN_NUM >= 20180404 || PACKETVER_ZERO_NUM >= 20180411 - if (clif->attendance_timediff(sd) != true) + int claimed = 0; + + if (!clif->attendance_timediff(sd)) ++claimed; else if (sd->status.attendance_count >= VECTOR_LENGTH(clif->attendance_data)) sd->status.attendance_count = 0; - p.UIType = ZC_ATTENDANCE_UI; + p.data = sd->status.attendance_count * 10 + claimed; #else ShowWarning("Attendance System available only for PACKETVER_RE_NUM >= 20180307 || PACKETVER_MAIN_NUM >= 20180404 || PACKETVER_ZERO_NUM >= 20180411.\n"); return; #endif break; - } +#endif default: - ShowWarning("clif_open_ui: Requested UI (%u) is not implemented yet.\n", uiType); + ShowWarning("clif_open_ui_send: Requested UI (%u) is not implemented yet.\n", ui_type); return; } @@ -23050,6 +23225,37 @@ static void clif_open_ui(struct map_session_data *sd, enum cz_ui_types uiType) #endif } +static void clif_open_ui(struct map_session_data *sd, enum cz_ui_types uiType) +{ + nullpo_retv(sd); + + enum zc_ui_types send_ui_type; + + switch (uiType) { +#if PACKETVER >= 20150128 + case CZ_STYLIST_UI: + send_ui_type = ZC_STYLIST_UI; + break; + case CZ_MACRO_REGISTER_UI: + send_ui_type = ZC_CAPTCHA_UI; + break; + case CZ_MACRO_DETECTOR_UI: + send_ui_type = ZC_MACRO_UI; + break; +#endif +#if PACKETVER >= 20171122 + case CZ_ATTENDANCE_UI: + send_ui_type = ZC_ATTENDANCE_UI; + break; +#endif + default: + ShowWarning("clif_open_ui: Requested UI (%u) is not implemented yet.\n", uiType); + return; + } + + clif->open_ui_send(sd, send_ui_type); +} + static void clif_parse_attendance_reward_request(int fd, struct map_session_data *sd) __attribute__((nonnull(2))); static void clif_parse_attendance_reward_request(int fd, struct map_session_data *sd) { @@ -25160,6 +25366,7 @@ void clif_defaults(void) clif->attendance_timediff = clif_attendance_timediff; clif->attendance_getendtime = clif_attendance_getendtime; clif->pOpenUIRequest = clif_parse_open_ui_request; + clif->open_ui_send = clif_open_ui_send; clif->open_ui = clif_open_ui; clif->pAttendanceRewardRequest = clif_parse_attendance_reward_request; clif->ui_action = clif_ui_action; diff --git a/src/map/clif.h b/src/map/clif.h index e43aad808..ee76e62e8 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -750,6 +750,14 @@ enum removeGear_flag { REMOVE_MOUNT_CART = 6, }; +/** Info types for PACKET_ZC_PERSONAL_INFOMATION (0x097b). **/ +enum detail_exp_info_type { + PC_EXP_INFO = 0x0, //!< PCBang internet cafe modifiers. (http://pcbang.gnjoy.com/) (Unused.) + PREMIUM_EXP_INFO = 0x1, //!< Premium user modifiers. Values aren't displayed in 20161207+ clients. + SERVER_EXP_INFO = 0x2, //!< Server rates. + TPLUS_EXP_INFO = 0x3, //!< Unknown. Values are displayed as "TPLUS" in kRO. (Unused.) +}; + /** * Clif.c Interface **/ @@ -1650,6 +1658,7 @@ struct clif_interface { bool (*attendance_timediff) (struct map_session_data *sd); time_t (*attendance_getendtime) (void); void (*pOpenUIRequest) (int fd, struct map_session_data *sd); + void (*open_ui_send) (struct map_session_data *sd, enum zc_ui_types ui_type); void (*open_ui) (struct map_session_data *sd, enum cz_ui_types uiType); void (*pAttendanceRewardRequest) (int fd, struct map_session_data *sd); void (*ui_action) (struct map_session_data *sd, int32 UIType, int32 data); diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 3129a05d9..031a23b6d 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -3927,6 +3927,24 @@ struct PACKET_CZ_LAPINEUPGRADE_MAKE_ITEM { DEFINE_PACKET_HEADER(CZ_LAPINEUPGRADE_MAKE_ITEM, 0x0ab6); #endif // PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO) +#if PACKETVER_MAIN_NUM >= 20120503 || PACKETVER_RE_NUM >= 20120502 || defined(PACKETVER_ZERO) +struct PACKET_ZC_PERSONAL_INFOMATION_SUB { + int8 type; + int32 exp; + int32 death; + int32 drop; +} __attribute__((packed)); +struct PACKET_ZC_PERSONAL_INFOMATION { + int16 packetType; + int16 length; + int32 total_exp; + int32 total_death; + int32 total_drop; + struct PACKET_ZC_PERSONAL_INFOMATION_SUB details[]; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_PERSONAL_INFOMATION, 0x097b); +#endif // PACKETVER_MAIN_NUM >= 20120503 || PACKETVER_RE_NUM >= 20120502 || defined(PACKETVER_ZERO) + #if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute #pragma pack(pop) #endif // not NetBSD < 6 / Solaris diff --git a/src/map/party.c b/src/map/party.c index a6f6b7774..5eecd3fe6 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -330,6 +330,8 @@ static int party_recv_info(const struct party *sp, int char_id) party->member_withdraw(sp->party_id, sd->status.account_id, sd->status.char_id); } + int option_auto_changed = p->state.option_auto_changed; // Preserve state. + memcpy(&p->party, sp, sizeof(struct party)); memset(&p->state, 0, sizeof(p->state)); memset(&p->data, 0, sizeof(p->data)); @@ -342,6 +344,7 @@ static int party_recv_info(const struct party *sp, int char_id) p->party.member[member_id].leader = 1; } party->check_state(p); + p->state.option_auto_changed = option_auto_changed; while( added_count > 0 ) { // new in party member_id = added[--added_count]; sd = p->data[member_id].sd; @@ -349,7 +352,6 @@ static int party_recv_info(const struct party *sp, int char_id) continue;// not online clif->charnameupdate(sd); //Update other people's display. [Skotlex] clif->party_member_info(p,sd); - clif->party_option(p,sd,0x100); clif->party_info(p,NULL); for( j = 0; j < p->instances; j++ ) { if( p->instance[j] >= 0 ) { @@ -492,6 +494,8 @@ static void party_member_joined(struct map_session_data *sd) } } else sd->status.party_id = 0; //He does not belongs to the party really? + + party->send_movemap(sd); } /// Invoked (from char-server) when a new member is added to the party. @@ -532,6 +536,11 @@ static int party_member_added(int party_id, int account_id, int char_id, int fla clif->party_member_info(p,sd); clif->party_info(p,sd); + if (p->state.option_auto_changed != 0) + clif->party_option(p, sd, 0x04); + else + clif->party_option(p, sd, 0x08); + if( sd2 != NULL ) clif->party_inviteack(sd2,sd->status.name,2); @@ -616,6 +625,7 @@ static int party_member_withdraw(int party_id, int account_id, int char_id) prev_leader_accountId = p->party.member[i].account_id; } + clif->party_option(p, sd, 0x10); clif->party_withdraw(p,sd,account_id,p->party.member[i].name,0x0); memset(&p->party.member[i], 0, sizeof(p->party.member[0])); memset(&p->data[i], 0, sizeof(p->data[0])); @@ -723,8 +733,17 @@ static int party_optionchanged(int party_id, int account_id, int exp, int item, //Flag&0x1: Exp change denied. Flag&0x10: Item change denied. if(!(flag&0x01) && p->party.exp != exp) p->party.exp=exp; - if(!(flag&0x10) && p->party.item != item) { + if (p->party.item != item) p->party.item=item; + + if (account_id == 0) { + flag |= 0x04; + p->state.option_auto_changed = 1; + + if (p->state.member_level_changed == 0) + return 0; // clif_party_option() is handled in clif_parse_LoadEndAck(). + } else { + flag |= 0x02; } clif->party_option(p,sd,flag); @@ -805,7 +824,8 @@ static int party_recv_movemap(int party_id, int account_id, int char_id, unsigne ShowError("party_recv_movemap: char %d/%d not found in party %s (id:%d)",account_id,char_id,p->party.name,party_id); return 0; } - + + p->state.member_level_changed = 0; m = &p->party.member[i]; m->map = mapid; m->online = online; @@ -854,7 +874,12 @@ static void party_send_movemap(struct map_session_data *sd) static void party_send_levelup(struct map_session_data *sd) { - intif->party_changemap(sd,1); + struct party_data *p = party->search(sd->status.party_id); + + if (p != NULL) + p->state.member_level_changed = 1; + + intif->party_changemap(sd, 1); } static int party_send_logout(struct map_session_data *sd) diff --git a/src/map/party.h b/src/map/party.h index c2306b7a8..5f3458cd4 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -51,6 +51,8 @@ struct party_data { unsigned sg : 1; ///< There's at least one Star Gladiator in party? unsigned snovice :1; ///< There's a Super Novice unsigned tk : 1; ///< There's a taekwon + unsigned option_auto_changed : 1; ///< Party options were changed automatically. (inter_party_check_lv()) + unsigned member_level_changed : 1; ///< A party member's level has changed. } state; struct hplugin_data_store *hdata; ///< HPM Plugin Data Store }; diff --git a/src/map/pc.c b/src/map/pc.c index 9b5764bd6..64e52848f 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -12128,7 +12128,6 @@ static void pc_scdata_received(struct map_session_data *sd) { nullpo_retv(sd); pc->inventory_rentals(sd); - clif->show_modifiers(sd); if (sd->expiration_time != 0) { // don't display if it's unlimited or unknow value time_t exp_time = sd->expiration_time; |