From d70b1734c8bff8a27d8251b2d16d43e7b309cb64 Mon Sep 17 00:00:00 2001 From: Napster Date: Tue, 12 Jan 2016 01:54:58 +0700 Subject: [PATCH] Add support body style implementation * This feature require the client support before 2015-05-13 or newer Make sure you data&lub support for this note : read info to https://rathena.org/board/topic/104205-2015-client-support/ Special Thanks you to Rytech, @aleos89 --- conf/battle/client.conf | 7 ++ conf/msg_conf/map_msg.conf | 8 +- doc/script_commands.txt | 22 ++++++ sql-files/main.sql | 3 +- sql-files/upgrades/upgrade_20160112.sql | 1 + src/char/char.c | 100 ++++++++++++------------ src/common/mmo.h | 4 +- src/map/atcommand.c | 40 +++++++++- src/map/battle.c | 3 + src/map/battle.h | 5 ++ src/map/clif.c | 47 +++++++++-- src/map/clif.h | 2 +- src/map/map.h | 3 +- src/map/pc.c | 91 ++++++++++++--------- src/map/script.c | 43 ++++++++++ src/map/script_constants.h | 1 + src/map/status.c | 25 ++++++ src/map/unit.h | 3 +- 18 files changed, 305 insertions(+), 103 deletions(-) create mode 100644 sql-files/upgrades/upgrade_20160112.sql diff --git a/conf/battle/client.conf b/conf/battle/client.conf index 6ff1133572..528a097530 100644 --- a/conf/battle/client.conf +++ b/conf/battle/client.conf @@ -72,6 +72,8 @@ min_hair_color: 0 max_hair_color: 8 min_cloth_color: 0 max_cloth_color: 4 +min_body_style: 0 +max_body_style: 1 // When set to yes, the damage field in packets sent from woe maps will be set // to -1, making it impossible for GMs, Bots and Hexed clients to know the @@ -120,6 +122,11 @@ wedding_modifydisplay: no // Save Clothes color. (This will degrade performance) (Note 1) save_clothcolor: yes +// Save body styles. (Note 1) +// Note: Don't turn this on unless you know what your doing. +// Sprites are not released officially. +save_body_style: no + // Do not display cloth colors for the wedding class? // Note: Both save_clothcolor and wedding_modifydisplay have to be enabled // for this option to take effect. Set this to yes if your cloth palettes diff --git a/conf/msg_conf/map_msg.conf b/conf/msg_conf/map_msg.conf index 5732b2fa2a..e5bcd6a765 100644 --- a/conf/msg_conf/map_msg.conf +++ b/conf/msg_conf/map_msg.conf @@ -777,7 +777,11 @@ 737: '%s' (%d) cannot be cloned, limit (%d). 738: Clone '%s' is done. -//739-899 free +// @bodystyle +739: Please enter a body style (usage: @bodystyle ). +740: This job has no alternate body styles. + +//741-899 free //------------------------------------ // More atcommands message @@ -1112,7 +1116,7 @@ // @changelook 1177: Usage: @changelook {} -1178: Position: 1-Top 2-Middle 3-Bottom 4-Weapon 5-Shield 6-Shoes 7-Robe +1178: Position: 1-Top 2-Middle 3-Bottom 4-Weapon 5-Shield 6-Shoes 7-Robe 8-Body // @autotrade 1179: Autotrade is not allowed on this map. diff --git a/doc/script_commands.txt b/doc/script_commands.txt index d95d4fae35..ca5d20ef68 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -8998,5 +8998,27 @@ The command returns 1 upon success, and these values upon failure: --------------------------------------- +*opendressroom({}); + +This will open the Dress Room window on the client connected to the invoking character. + + mes "Close this window to open the Dress Room window."; + close2; + opendressroom; + end; + +--------------------------------------- + +*closedressroom({}); + +This will close an open Dress Room window on the client connected to the invoking character. + + mes "Close this window to close the Dress Room window."; + close2; + closedressroom; + end; + +--------------------------------------- + Whew. That's about all of them. diff --git a/sql-files/main.sql b/sql-files/main.sql index 1b4d3fc2c7..64e1a4f5a8 100644 --- a/sql-files/main.sql +++ b/sql-files/main.sql @@ -172,6 +172,7 @@ CREATE TABLE IF NOT EXISTS `char` ( `hair` tinyint(4) unsigned NOT NULL default '0', `hair_color` smallint(5) unsigned NOT NULL default '0', `clothes_color` smallint(5) unsigned NOT NULL default '0', + `body` smallint(5) unsigned NOT NULL default '0', `weapon` smallint(6) unsigned NOT NULL default '0', `shield` smallint(6) unsigned NOT NULL default '0', `head_top` smallint(6) unsigned NOT NULL default '0', @@ -197,7 +198,7 @@ CREATE TABLE IF NOT EXISTS `char` ( `font` tinyint(3) unsigned NOT NULL default '0', `uniqueitem_counter` int(11) unsigned NOT NULL default '0', `sex` ENUM('M','F','U') NOT NULL default 'U', - `hotkey_rowshift` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `hotkey_rowshift` tinyint(3) unsigned NOT NULL default '0', PRIMARY KEY (`char_id`), UNIQUE KEY `name_key` (`name`), KEY `account_id` (`account_id`), diff --git a/sql-files/upgrades/upgrade_20160112.sql b/sql-files/upgrades/upgrade_20160112.sql new file mode 100644 index 0000000000..8abc2a8345 --- /dev/null +++ b/sql-files/upgrades/upgrade_20160112.sql @@ -0,0 +1 @@ +ALTER TABLE `char` ADD `body`smallint(5) unsigned NOT NULL default '0' AFTER `clothes_color`; diff --git a/src/char/char.c b/src/char/char.c index 3950732514..7240373675 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -351,7 +351,7 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y, mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename, (unsigned long)p->delete_date, // FIXME: platform-dependent size - p->robe,p->character_moves,p->font, p->uniqueitem_counter, + p->robe, p->character_moves, p->font, p->uniqueitem_counter, p->hotkey_rowshift, p->account_id, p->char_id) ) { @@ -364,7 +364,7 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ //Values that will seldom change (to speed up saving) if ( (p->hair != cp->hair) || (p->hair_color != cp->hair_color) || (p->clothes_color != cp->clothes_color) || - (p->class_ != cp->class_) || + (p->body != cp->body) || (p->class_ != cp->class_) || (p->partner_id != cp->partner_id) || (p->father != cp->father) || (p->mother != cp->mother) || (p->child != cp->child) || (p->karma != cp->karma) || (p->manner != cp->manner) || @@ -372,12 +372,12 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ ) { if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d'," - "`hair`='%d',`hair_color`='%d',`clothes_color`='%d'," + "`hair`='%d', `hair_color`='%d', `clothes_color`='%d', `body`='%d'," "`partner_id`='%u', `father`='%u', `mother`='%u', `child`='%u'," "`karma`='%d',`manner`='%d', `fame`='%d'" " WHERE `account_id`='%d' AND `char_id` = '%d'", schema_config.char_db, p->class_, - p->hair, p->hair_color, p->clothes_color, + p->hair, p->hair_color, p->clothes_color, p->body, p->partner_id, p->father, p->mother, p->child, p->karma, p->manner, p->fame, p->account_id, p->char_id) ) @@ -921,7 +921,7 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) { "`char_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`," "`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`," "`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`," - "`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`," + "`clothes_color`,`body`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`," "`robe`,`moves`,`unban_time`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`" " FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", schema_config.char_db, sd->account_id, MAX_CHARS) || SQL_ERROR == SqlStmt_Execute(stmt) @@ -952,21 +952,22 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) { || SQL_ERROR == SqlStmt_BindColumn(stmt, 24, SQLDT_SHORT, &p.hair, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 25, SQLDT_SHORT, &p.hair_color, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 26, SQLDT_SHORT, &p.clothes_color, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 27, SQLDT_SHORT, &p.weapon, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 28, SQLDT_SHORT, &p.shield, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 29, SQLDT_SHORT, &p.head_top, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT, &p.head_mid, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT, &p.head_bottom, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_SHORT, &p.rename, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_SHORT, &p.robe, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 36, SQLDT_UINT, &p.character_moves, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 37, SQLDT_LONG, &p.unban_time, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 38, SQLDT_UCHAR, &p.font, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 39, SQLDT_UINT, &p.uniqueitem_counter, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 40, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 41, SQLDT_UCHAR, &p.hotkey_rowshift, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 27, SQLDT_SHORT, &p.body, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 28, SQLDT_SHORT, &p.weapon, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 29, SQLDT_SHORT, &p.shield, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT, &p.head_top, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT, &p.head_mid, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_SHORT, &p.head_bottom, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_SHORT, &p.rename, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 36, SQLDT_SHORT, &p.robe, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 37, SQLDT_UINT, &p.character_moves, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 38, SQLDT_LONG, &p.unban_time, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 39, SQLDT_UCHAR, &p.font, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 40, SQLDT_UINT, &p.uniqueitem_counter, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 41, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 42, SQLDT_UCHAR, &p.hotkey_rowshift, 0, NULL, NULL) ) { SqlStmt_ShowDebug(stmt); @@ -1030,7 +1031,7 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev "`char_id`,`account_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`," "`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`," "`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`," - "`hair_color`,`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`," + "`hair_color`,`clothes_color`,`body`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`," "`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`" " FROM `%s` WHERE `char_id`=? LIMIT 1", schema_config.char_db) @@ -1069,31 +1070,32 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev || SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT, &p->hair, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT, &p->hair_color, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_SHORT, &p->clothes_color, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_SHORT, &p->weapon, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_SHORT, &p->shield, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_SHORT, &p->head_top, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 36, SQLDT_SHORT, &p->head_mid, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 37, SQLDT_SHORT, &p->head_bottom, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 38, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 39, SQLDT_SHORT, &p->last_point.x, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 40, SQLDT_SHORT, &p->last_point.y, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 41, SQLDT_STRING, &save_map, sizeof(save_map), NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 42, SQLDT_SHORT, &p->save_point.x, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 43, SQLDT_SHORT, &p->save_point.y, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 44, SQLDT_UINT32, &p->partner_id, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 45, SQLDT_UINT32, &p->father, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 46, SQLDT_UINT32, &p->mother, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 47, SQLDT_UINT32, &p->child, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 48, SQLDT_INT, &p->fame, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 49, SQLDT_SHORT, &p->rename, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 50, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 51, SQLDT_SHORT, &p->robe, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 52, SQLDT_UINT32, &p->character_moves, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 53, SQLDT_LONG, &p->unban_time, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 54, SQLDT_UCHAR, &p->font, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 55, SQLDT_UINT, &p->uniqueitem_counter, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 56, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 57, SQLDT_UCHAR, &p->hotkey_rowshift, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_SHORT, &p->body, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_SHORT, &p->weapon, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_SHORT, &p->shield, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 36, SQLDT_SHORT, &p->head_top, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 37, SQLDT_SHORT, &p->head_mid, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 38, SQLDT_SHORT, &p->head_bottom, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 39, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 40, SQLDT_SHORT, &p->last_point.x, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 41, SQLDT_SHORT, &p->last_point.y, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 42, SQLDT_STRING, &save_map, sizeof(save_map), NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 43, SQLDT_SHORT, &p->save_point.x, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 44, SQLDT_SHORT, &p->save_point.y, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 45, SQLDT_UINT32, &p->partner_id, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 46, SQLDT_UINT32, &p->father, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 47, SQLDT_UINT32, &p->mother, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 48, SQLDT_UINT32, &p->child, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 49, SQLDT_INT, &p->fame, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 50, SQLDT_SHORT, &p->rename, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 51, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 52, SQLDT_SHORT, &p->robe, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 53, SQLDT_UINT32, &p->character_moves, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 54, SQLDT_LONG, &p->unban_time, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 55, SQLDT_UCHAR, &p->font, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 56, SQLDT_UINT, &p->uniqueitem_counter, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 57, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 58, SQLDT_UCHAR, &p->hotkey_rowshift, 0, NULL, NULL) ) { SqlStmt_ShowDebug(stmt); @@ -1733,12 +1735,12 @@ int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) WBUFW(buf,48) = min(p->max_sp, INT16_MAX); WBUFW(buf,50) = DEFAULT_WALK_SPEED; // p->speed; WBUFW(buf,52) = p->class_; + WBUFW(buf,54) = p->hair; + #if PACKETVER >= 20141022 - WBUFL(buf,54) = p->hair; + WBUFW(buf,56) = p->body; offset+=2; buf = WBUFP(buffer,offset); -#else - WBUFW(buf,54) = p->hair; #endif //When the weapon is sent and your option is riding, the client crashes on login!? diff --git a/src/common/mmo.h b/src/common/mmo.h index 8aac2f82f1..a4ba0ef6b9 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -21,7 +21,7 @@ // see conf/battle/client.conf for other version #ifndef PACKETVER - #define PACKETVER 20130807 + #define PACKETVER 20150513 //#define PACKETVER 20120410 #endif @@ -390,7 +390,7 @@ struct mmo_charstatus { unsigned int option; short manner; // Defines how many minutes a char will be muted, each negative point is equivalent to a minute. unsigned char karma; - short hair,hair_color,clothes_color; + short hair,hair_color,clothes_color,body; int party_id,guild_id,pet_id,hom_id,mer_id,ele_id; int fame; diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 7a19bc2e44..233148592d 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -1727,6 +1727,39 @@ ACMD_FUNC(model) return 0; } +/*========================================== + * @bodystyle [Rytech] + *------------------------------------------*/ +ACMD_FUNC(bodystyle) +{ + int body_style = 0; + nullpo_retr(-1, sd); + + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + // Limit body styles to certain jobs since not all of them are released yet. + if (!((sd->class_&MAPID_THIRDMASK) == MAPID_GUILLOTINE_CROSS || (sd->class_&MAPID_THIRDMASK) == MAPID_GENETIC)) { + clif_displaymessage(fd, msg_txt(sd,770)); // This job has no alternate body styles. + return -1; + } + + if (!message || !*message || sscanf(message, "%d", &body_style) < 1) { + sprintf(atcmd_output, msg_txt(sd,739), MIN_BODY_STYLE, MAX_BODY_STYLE); // Please enter a body style (usage: @bodystyle ). + clif_displaymessage(fd, atcmd_output); + return -1; + } + + if (body_style >= MIN_BODY_STYLE && body_style <= MAX_BODY_STYLE) { + pc_changelook(sd, LOOK_BODY2, body_style); + clif_displaymessage(fd, msg_txt(sd,36)); // Appearence changed. + } else { + clif_displaymessage(fd, msg_txt(sd,37)); // An invalid number was specified. + return -1; + } + + return 0; +} + /*========================================== * @dye && @ccolor *------------------------------------------*/ @@ -5736,14 +5769,14 @@ ACMD_FUNC(divorce) ACMD_FUNC(changelook) { int i, j = 0, k = 0; - int pos[7] = { LOOK_HEAD_TOP,LOOK_HEAD_MID,LOOK_HEAD_BOTTOM,LOOK_WEAPON,LOOK_SHIELD,LOOK_SHOES,LOOK_ROBE }; + int pos[8] = { LOOK_HEAD_TOP,LOOK_HEAD_MID,LOOK_HEAD_BOTTOM,LOOK_WEAPON,LOOK_SHIELD,LOOK_SHOES,LOOK_ROBE, LOOK_BODY2 }; if((i = sscanf(message, "%11d %11d", &j, &k)) < 1) { clif_displaymessage(fd, msg_txt(sd,1177)); // Usage: @changelook {} - clif_displaymessage(fd, msg_txt(sd,1178)); // Position: 1-Top 2-Middle 3-Bottom 4-Weapon 5-Shield 6-Shoes 7-Robe + clif_displaymessage(fd, msg_txt(sd,1178)); // Position: 1-Top 2-Middle 3-Bottom 4-Weapon 5-Shield 6-Shoes 7-Robe 8-Body return -1; } else if ( i == 2 ) { - if (j < 1 || j > 7) + if (j < 1 || j > 8) j = 1; j = pos[j - 1]; } else if( i == 1 ) { // position not defined, use HEAD_TOP as default @@ -10036,6 +10069,7 @@ void atcommand_basecommands(void) { ACMD_DEF(costume), ACMD_DEF(cloneequip), ACMD_DEF(clonestat), + ACMD_DEF(bodystyle), }; AtCommandInfo* atcommand; int i; diff --git a/src/map/battle.c b/src/map/battle.c index a13eceb789..f2ea5dc60c 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -8171,6 +8171,9 @@ static const struct _battle_data { { "monster_loot_search_type", &battle_config.monster_loot_search_type, 1, 0, 1, }, { "feature.roulette", &battle_config.feature_roulette, 1, 0, 1, }, { "monster_hp_bars_info", &battle_config.monster_hp_bars_info, 1, 0, 1, }, + { "min_body_style", &battle_config.min_body_style, 0, 0, SHRT_MAX, }, + { "max_body_style", &battle_config.max_body_style, 4, 0, SHRT_MAX, }, + { "save_body_style", &battle_config.save_body_style, 0, 0, 1, }, }; #ifndef STATS_OPT_OUT diff --git a/src/map/battle.h b/src/map/battle.h index 20f585241d..dd6cf52d03 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -126,6 +126,8 @@ bool is_infinite_defense(struct block_list *target, int flag); #define MAX_HAIR_COLOR battle_config.max_hair_color #define MIN_CLOTH_COLOR battle_config.min_cloth_color #define MAX_CLOTH_COLOR battle_config.max_cloth_color +#define MIN_BODY_STYLE battle_config.min_body_style +#define MAX_BODY_STYLE battle_config.max_body_style extern struct Battle_Config { @@ -592,6 +594,9 @@ extern struct Battle_Config int monster_loot_search_type; int feature_roulette; int monster_hp_bars_info; + int min_body_style; + int max_body_style; + int save_body_style; } battle_config; void do_init_battle(void); diff --git a/src/map/clif.c b/src/map/clif.c index c0c02c1eb4..38e96961d4 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1123,7 +1123,7 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool WBUFB(buf,63) = ( bl->type == BL_MOB && (((TBL_MOB*)bl)->db->mexp > 0) ) ? 1 : 0; // isBoss #endif #if PACKETVER >= 20150513 - WBUFW(buf,64) = 0; // body + WBUFW(buf,64) = vd->body_style; // body offset+= 2; buf = WBUFP(buffer,offset); #endif @@ -1266,7 +1266,7 @@ static int clif_set_unit_walking(struct block_list* bl, struct unit_data* ud, un WBUFB(buf,70) = ( bl->type == BL_MOB && (((TBL_MOB*)bl)->db->mexp > 0) ) ? 1 : 0; // isBoss #endif #if PACKETVER >= 20150513 - WBUFW(buf,71) = 0; // body + WBUFW(buf,71) = vd->body_style; // body offset+= 2; buf = WBUFP(buffer,offset); #endif @@ -1423,6 +1423,8 @@ int clif_spawn(struct block_list *bl) if (vd->cloth_color) clif_refreshlook(bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,AREA_WOS); + if (vd->body_style) + clif_refreshlook(bl,bl->id,LOOK_BODY2,vd->body_style,AREA_WOS); switch (bl->type) { @@ -1696,6 +1698,8 @@ static void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_ if(vd->cloth_color) clif_refreshlook(bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,AREA_WOS); + if(vd->body_style) + clif_refreshlook(bl,bl->id,LOOK_BODY2,vd->body_style,AREA_WOS); switch(bl->type) { case BL_PC: @@ -3400,6 +3404,11 @@ void clif_changelook(struct block_list *bl,int type,int val) vd->cloth_color = 0; if (sd->sc.option&OPTION_OKTOBERFEST && battle_config.oktoberfest_ignorepalette) vd->cloth_color = 0; + if (vd->body_style && ( + sd->sc.option&OPTION_WEDDING || sd->sc.option&OPTION_XMAS || + sd->sc.option&OPTION_SUMMER || sd->sc.option&OPTION_HANBOK || + sd->sc.option&OPTION_OKTOBERFEST)) + vd->body_style = 0; } break; case LOOK_HAIR: @@ -3455,6 +3464,18 @@ void clif_changelook(struct block_list *bl,int type,int val) return; #else vd->robe = val; +#endif + break; + case LOOK_BODY2: +#if PACKETVER < 20150513 + return; +#else + if (val && ( + sd->sc.option&OPTION_WEDDING || sd->sc.option&OPTION_XMAS || + sd->sc.option&OPTION_SUMMER || sd->sc.option&OPTION_HANBOK || + sd->sc.option&OPTION_OKTOBERFEST)) + val = 0; + vd->body_style = val; #endif break; } @@ -4534,6 +4555,9 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) if (vd->cloth_color) clif_refreshlook(&sd->bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,SELF); + if (vd->body_style) + clif_refreshlook(&sd->bl,bl->id,LOOK_BODY2,vd->body_style,SELF); + switch (bl->type) { case BL_PC: @@ -9165,6 +9189,8 @@ void clif_refresh(struct map_session_data *sd) clif_spiritcharm_single(sd->fd, sd); if (sd->vd.cloth_color) clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); + if (sd->vd.body_style) + clif_refreshlook(&sd->bl,sd->bl.id,LOOK_BODY2,sd->vd.body_style,SELF); if(hom_is_active(sd->hd)) clif_send_homdata(sd,SP_ACK,0); if( sd->md ) { @@ -10027,6 +10053,9 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if(sd->vd.cloth_color) clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); + if(sd->vd.body_style) + clif_refreshlook(&sd->bl,sd->bl.id,LOOK_BODY2,sd->vd.body_style,SELF); + // item clif_inventorylist(sd); // inventory list first, otherwise deleted items in pc_checkitem show up as 'unknown item' pc_checkitem(sd); @@ -18597,16 +18626,22 @@ void clif_broadcast_obtain_special_item(const char *char_name, unsigned short na clif_send(buf, WBUFW(buf, 2), NULL, ALL_CLIENT); } -void clif_dressing_room(struct map_session_data *sd, int view) { - int fd; +/// Show body view windows (ZC_DRESSROOM_OPEN). +/// 0A02 .W +/// Value has the following effects: +/// 0: Close an open Dress Room window. +/// 1: Open a Dress Room window. +void clif_dressing_room(struct map_session_data *sd, int flag) { +#if PACKETVER >= 20150513 + int fd = sd->fd; nullpo_retv(sd); - fd = sd->fd; WFIFOHEAD(fd, packet_len(0xa02)); WFIFOW(fd,0) = 0xa02; - WFIFOW(fd,2) = view; + WFIFOW(fd,2) = flag; WFIFOSET(fd, packet_len(0xa02)); +#endif } /// Parsing a request from the client item identify oneclick (CZ_REQ_ONECLICK_ITEMIDENTIFY). diff --git a/src/map/clif.h b/src/map/clif.h index c74a0cd60e..c59cca27d5 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -968,7 +968,7 @@ void clif_merge_item_open(struct map_session_data *sd); void clif_broadcast_obtain_special_item(const char *char_name, unsigned short nameid, unsigned short container, enum BROADCASTING_SPECIAL_ITEM_OBTAIN type, const char *srcname); -void clif_dressing_room(struct map_session_data *sd, int view); +void clif_dressing_room(struct map_session_data *sd, int flag); void clif_SelectCart(struct map_session_data *sd); #endif /* _CLIF_H_ */ diff --git a/src/map/map.h b/src/map/map.h index 2260bf1cdc..88ff96a9f6 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -533,7 +533,8 @@ enum _look { LOOK_BODY, //Purpose Unknown. Doesen't appear to do anything. LOOK_RESET_COSTUMES,//Makes all headgear sprites on player vanish when activated. LOOK_ROBE, - LOOK_FLOOR + // LOOK_FLOOR, // TODO : fix me!! offcial use this ? + LOOK_BODY2 }; // used by map_setcell() diff --git a/src/map/pc.c b/src/map/pc.c index 2a94abdce1..4342eb41e5 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -616,12 +616,16 @@ bool pc_can_give_bounded_items(struct map_session_data *sd) * Prepares character for saving. * @param sd *------------------------------------------*/ -void pc_makesavestatus(struct map_session_data *sd) -{ +void pc_makesavestatus(struct map_session_data *sd) { nullpo_retv(sd); if(!battle_config.save_clothcolor) - sd->status.clothes_color=0; + sd->status.clothes_color = 0; + + // Since this is currently not officially released, + // its best to have a forced option to not save body styles. + if(!battle_config.save_body_style) + sd->status.body = 0; //Only copy the Cart/Peco/Falcon options, the rest are handled via //status change load/saving. [Skotlex] @@ -632,7 +636,7 @@ void pc_makesavestatus(struct map_session_data *sd) #endif if (sd->sc.data[SC_JAILED]) { //When Jailed, do not move last point. if(pc_isdead(sd)){ - pc_setrestartvalue(sd,0); + pc_setrestartvalue(sd, 0); } else { sd->status.hp = sd->battle_status.hp; sd->status.sp = sd->battle_status.sp; @@ -643,8 +647,8 @@ void pc_makesavestatus(struct map_session_data *sd) return; } - if(pc_isdead(sd)){ - pc_setrestartvalue(sd,0); + if(pc_isdead(sd)) { + pc_setrestartvalue(sd, 0); memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point)); } else { sd->status.hp = sd->battle_status.hp; @@ -654,7 +658,7 @@ void pc_makesavestatus(struct map_session_data *sd) sd->status.last_point.y = sd->bl.y; } - if(map[sd->bl.m].flag.nosave){ + if(map[sd->bl.m].flag.nosave) { struct map_data *m=&map[sd->bl.m]; if(m->save.map) memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point)); @@ -666,20 +670,19 @@ void pc_makesavestatus(struct map_session_data *sd) /*========================================== * Off init ? Connection? *------------------------------------------*/ -void pc_setnewpc(struct map_session_data *sd, uint32 account_id, uint32 char_id, int login_id1, unsigned int client_tick, int sex, int fd) -{ +void pc_setnewpc(struct map_session_data *sd, uint32 account_id, uint32 char_id, int login_id1, unsigned int client_tick, int sex, int fd) { nullpo_retv(sd); - sd->bl.id = account_id; - sd->status.account_id = account_id; - sd->status.char_id = char_id; - sd->status.sex = sex; - sd->login_id1 = login_id1; - sd->login_id2 = 0; // at this point, we can not know the value :( - sd->client_tick = client_tick; + sd->bl.id = account_id; + sd->status.account_id = account_id; + sd->status.char_id = char_id; + sd->status.sex = sex; + sd->login_id1 = login_id1; + sd->login_id2 = 0; // at this point, we can not know the value :( + sd->client_tick = client_tick; sd->state.active = 0; //to be set to 1 after player is fully authed and loaded. - sd->bl.type = BL_PC; - sd->canlog_tick = gettick(); + sd->bl.type = BL_PC; + sd->canlog_tick = gettick(); //Required to prevent homunculus copuing a base speed of 0. sd->battle_status.speed = sd->base_status.speed = DEFAULT_WALK_SPEED; } @@ -1120,6 +1123,7 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_ sd->status.hair = cap_value(sd->status.hair,MIN_HAIR_STYLE,MAX_HAIR_STYLE); sd->status.hair_color = cap_value(sd->status.hair_color,MIN_HAIR_COLOR,MAX_HAIR_COLOR); sd->status.clothes_color = cap_value(sd->status.clothes_color,MIN_CLOTH_COLOR,MAX_CLOTH_COLOR); + sd->status.body = cap_value(sd->status.body,MIN_BODY_STYLE,MAX_BODY_STYLE); //Initializations to null/0 unneeded since map_session_data was filled with 0 upon allocation. if(!sd->status.hp) pc_setdead(sd); @@ -8204,6 +8208,11 @@ bool pc_jobchange(struct map_session_data *sd,int job, char upper) pc_resetfeel(sd); } + // Reset body style to 0 before changing job to avoid + // errors since not every job has a alternate outfit. + sd->status.body = 0; + clif_changelook(&sd->bl,LOOK_BODY2,0); + sd->status.class_ = job; fame_flag = pc_famerank(sd->status.char_id,sd->class_&MAPID_UPPERMASK); sd->class_ = (unsigned short)b_class; @@ -8239,7 +8248,10 @@ bool pc_jobchange(struct map_session_data *sd,int job, char upper) clif_changelook(&sd->bl,LOOK_BASE,sd->vd.class_); // move sprite update to prevent client crashes with incompatible equipment [Valaris] if(sd->vd.cloth_color) clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); - + /* + if(sd->vd.body_style) + clif_changelook(&sd->bl,LOOK_BODY2,sd->vd.body_style); + */ //Update skill tree. pc_calc_skilltree(sd); clif_skillinfoblock(sd); @@ -8325,59 +8337,62 @@ void pc_equiplookall(struct map_session_data *sd) /*========================================== * Tell client player sd has change look (hair,equip...) *------------------------------------------*/ -void pc_changelook(struct map_session_data *sd,int type,int val) -{ +void pc_changelook(struct map_session_data *sd,int type,int val) { nullpo_retv(sd); - switch(type){ + switch(type) { case LOOK_HAIR: //Use the battle_config limits! [Skotlex] val = cap_value(val, MIN_HAIR_STYLE, MAX_HAIR_STYLE); - if (sd->status.hair != val) - { - sd->status.hair=val; + if (sd->status.hair != val) { + sd->status.hair = val; if (sd->status.guild_id) //Update Guild Window. [Skotlex] - intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, - GMI_HAIR,&sd->status.hair,sizeof(sd->status.hair)); + intif_guild_change_memberinfo(sd->status.guild_id, sd->status.account_id, sd->status.char_id, + GMI_HAIR, &sd->status.hair, sizeof(sd->status.hair)); } break; case LOOK_WEAPON: - sd->status.weapon=val; + sd->status.weapon = val; break; case LOOK_HEAD_BOTTOM: - sd->status.head_bottom=val; + sd->status.head_bottom = val; break; case LOOK_HEAD_TOP: - sd->status.head_top=val; + sd->status.head_top = val; break; case LOOK_HEAD_MID: - sd->status.head_mid=val; + sd->status.head_mid = val; break; case LOOK_HAIR_COLOR: //Use the battle_config limits! [Skotlex] val = cap_value(val, MIN_HAIR_COLOR, MAX_HAIR_COLOR); if (sd->status.hair_color != val) { - sd->status.hair_color=val; + sd->status.hair_color = val; if (sd->status.guild_id) //Update Guild Window. [Skotlex] - intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, - GMI_HAIR_COLOR,&sd->status.hair_color,sizeof(sd->status.hair_color)); + intif_guild_change_memberinfo(sd->status.guild_id, sd->status.account_id, sd->status.char_id, + GMI_HAIR_COLOR, &sd->status.hair_color, sizeof(sd->status.hair_color)); } break; case LOOK_CLOTHES_COLOR: //Use the battle_config limits! [Skotlex] val = cap_value(val, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); - sd->status.clothes_color=val; + sd->status.clothes_color = val; break; case LOOK_SHIELD: - sd->status.shield=val; + sd->status.shield = val; break; case LOOK_SHOES: break; case LOOK_ROBE: sd->status.robe = val; break; + case LOOK_BODY2: + val = cap_value(val, MIN_BODY_STYLE, MAX_BODY_STYLE); + + sd->status.body = val; + break; } - clif_changelook(&sd->bl,type,val); + clif_changelook(&sd->bl, type, val); } /*========================================== @@ -8470,6 +8485,8 @@ void pc_setoption(struct map_session_data *sd,int type) clif_changelook(&sd->bl,LOOK_BASE,new_look); if (sd->vd.cloth_color) clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); + if( sd->vd.body_style ) + clif_changelook(&sd->bl,LOOK_BODY2,sd->vd.body_style); clif_skillinfoblock(sd); // Skill list needs to be updated after base change. } diff --git a/src/map/script.c b/src/map/script.c index 65e5ab2898..ddcf58bd6f 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -11207,6 +11207,8 @@ BUILDIN_FUNC(changebase) clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); if (sd->vd.cloth_color) clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); + if (sd->vd.body_style) + clif_changelook(&sd->bl,LOOK_BODY2,sd->vd.body_style); clif_skillinfoblock(sd); } return SCRIPT_CMD_SUCCESS; @@ -14335,6 +14337,7 @@ BUILDIN_FUNC(getlook) case LOOK_SHIELD: val=sd->status.shield; break; //8 case LOOK_SHOES: break; //9 case LOOK_ROBE: val=sd->status.robe; break; //12 + case LOOK_BODY2: val=sd->status.body; break; //13 } script_pushint(st,val); @@ -21020,6 +21023,44 @@ BUILDIN_FUNC(setquestinfo_job) { return SCRIPT_CMD_SUCCESS; } +/** + * opendressroom({}); + */ +BUILDIN_FUNC(opendressroom) +{ +#if PACKETVER >= 20150513 + TBL_PC* sd; + + if (!script_charid2sd(2, sd)) + return SCRIPT_CMD_FAILURE; + + clif_dressing_room(sd, 1); + + return SCRIPT_CMD_SUCCESS; +#else + return SCRIPT_CMD_FAILURE; +#endif +} + +/** + * closedressroom({}); + */ +BUILDIN_FUNC(closedressroom) +{ +#if PACKETVER >= 20150513 + TBL_PC* sd; + + if (!script_charid2sd(2, sd)) + return SCRIPT_CMD_FAILURE; + + clif_dressing_room(sd, 0); + + return SCRIPT_CMD_SUCCESS; +#else + return SCRIPT_CMD_FAILURE; +#endif +} + #include "../custom/script.inc" // declarations that were supposed to be exported from npc_chat.c @@ -21585,6 +21626,8 @@ struct script_function buildin_func[] = { BUILDIN_DEF(setquestinfo_level,"iii"), BUILDIN_DEF(setquestinfo_req,"iii*"), BUILDIN_DEF(setquestinfo_job,"ii*"), + BUILDIN_DEF(opendressroom,"?"), + BUILDIN_DEF(closedressroom,"?"), #include "../custom/script_def.inc" diff --git a/src/map/script_constants.h b/src/map/script_constants.h index 46b37ae275..e623c50cdf 100644 --- a/src/map/script_constants.h +++ b/src/map/script_constants.h @@ -689,6 +689,7 @@ export_constant(LOOK_BODY); export_constant(LOOK_RESET_COSTUMES); export_constant(LOOK_ROBE); + export_constant(LOOK_BODY2); // TODO: check why we didnt have floor and enable it //export_constant(LOOK_FLOOR); diff --git a/src/map/status.c b/src/map/status.c index 9847da8a58..ec21292b81 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -7177,6 +7177,7 @@ void status_set_viewdata(struct block_list *bl, int class_) sd->vd.hair_style = cap_value(sd->status.hair,0,battle_config.max_hair_style); sd->vd.hair_color = cap_value(sd->status.hair_color,0,battle_config.max_hair_color); sd->vd.cloth_color = cap_value(sd->status.clothes_color,0,battle_config.max_cloth_color); + sd->vd.body_style = cap_value(sd->status.body,0,battle_config.max_body_style); sd->vd.sex = sd->status.sex; if (sd->vd.cloth_color) { @@ -7191,6 +7192,11 @@ void status_set_viewdata(struct block_list *bl, int class_) if(sd->sc.option&OPTION_OKTOBERFEST && battle_config.oktoberfest_ignorepalette) sd->vd.cloth_color = 0; } + if ( sd->vd.body_style && ( + sd->sc.option&OPTION_WEDDING || sd->sc.option&OPTION_XMAS || + sd->sc.option&OPTION_SUMMER || sd->sc.option&OPTION_HANBOK || + sd->sc.option&OPTION_OKTOBERFEST)) + sd->vd.body_style = 0; } else if (vd) memcpy(&sd->vd, vd, sizeof(struct view_data)); else @@ -10305,6 +10311,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty clif_changelook(bl,LOOK_WEAPON,0); clif_changelook(bl,LOOK_SHIELD,0); clif_changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); + clif_changelook(bl,LOOK_BODY2,0); break; } @@ -10653,6 +10660,16 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty calc_flag&=~SCB_DYE; } + /*if (calc_flag&SCB_BODY)// Might be needed in the future. [Rytech] + { //Reset body style + if (vd && vd->body_style) + { + val4 = vd->body_style; + clif_changelook(bl,LOOK_BODY2,0); + } + calc_flag&=~SCB_BODY; + }*/ + if(!(flag&SCSTART_NOICON) && !(flag&SCSTART_LOADED && StatusDisplayType[type])) clif_status_change(bl,StatusIconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); @@ -11632,6 +11649,13 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const calc_flag&=~SCB_DYE; } + /*if (calc_flag&SCB_BODY)// Might be needed in the future. [Rytech] + { //Restore body style + if (vd && !vd->body_style && sce->val4) + clif_changelook(bl,LOOK_BODY2,sce->val4); + calc_flag&=~SCB_BODY; + }*/ + // On Aegis, when turning off a status change, first goes the sc packet, then the option packet. clif_status_change(bl,StatusIconChangeTable[type],0,0,0,0,0); @@ -11645,6 +11669,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const clif_changelook(bl,LOOK_WEAPON,sd->vd.weapon); clif_changelook(bl,LOOK_SHIELD,sd->vd.shield); clif_changelook(bl,LOOK_CLOTHES_COLOR,cap_value(sd->status.clothes_color,0,battle_config.max_cloth_color)); + clif_changelook(bl,LOOK_BODY2,cap_value(sd->status.body,0,battle_config.max_body_style)); } } if (calc_flag) diff --git a/src/map/unit.h b/src/map/unit.h index 38515d0256..d78064e4a8 100644 --- a/src/map/unit.h +++ b/src/map/unit.h @@ -74,7 +74,8 @@ struct view_data { head_bottom, hair_style, hair_color, - cloth_color; + cloth_color, + body_style; char sex; unsigned dead_sit : 2; };