From 0c458a4976ea392a71ccfa8d86f2ebf86d03e1b4 Mon Sep 17 00:00:00 2001 From: Dastgir Date: Thu, 17 Dec 2015 16:10:19 +0530 Subject: Added Support for BodyStyle Closes #974 as merged --- conf/battle/client.conf | 7 +++ conf/messages.conf | 2 +- db/const.txt | 1 + sql-files/main.sql | 2 + sql-files/upgrades/2015-12-17--15-58.sql | 22 ++++++++ sql-files/upgrades/index.txt | 3 +- src/char/char.c | 94 ++++++++++++++++---------------- src/common/mmo.h | 2 +- src/map/atcommand.c | 29 +++++++++- src/map/battle.c | 3 + src/map/battle.h | 9 ++- src/map/clif.c | 30 +++++++++- src/map/map.h | 1 + src/map/pc.c | 17 ++++++ src/map/script.c | 1 + src/map/status.c | 27 +++++++++ src/map/status.h | 3 + src/map/unit.h | 3 +- 18 files changed, 201 insertions(+), 55 deletions(-) create mode 100644 sql-files/upgrades/2015-12-17--15-58.sql diff --git a/conf/battle/client.conf b/conf/battle/client.conf index e10f03d82..6ca2f67e0 100644 --- a/conf/battle/client.conf +++ b/conf/battle/client.conf @@ -26,6 +26,8 @@ min_hair_color: 0 max_hair_color: 8 min_cloth_color: 0 max_cloth_color: 4 +min_body_style: 0 +max_body_style: 4 // 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 @@ -75,6 +77,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 costume? // 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/messages.conf b/conf/messages.conf index 6be8c7221..6e671b83b 100644 --- a/conf/messages.conf +++ b/conf/messages.conf @@ -1035,7 +1035,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 in this map. diff --git a/db/const.txt b/db/const.txt index 93ac21e79..361af4972 100644 --- a/db/const.txt +++ b/db/const.txt @@ -633,6 +633,7 @@ LOOK_SHOES 9 LOOK_BODY 10 LOOK_FLOOR 11 LOOK_ROBE 12 +LOOK_BODY2 13 Eff_Stone 0 Eff_Freeze 1 diff --git a/sql-files/main.sql b/sql-files/main.sql index 864b86865..7adac433d 100644 --- a/sql-files/main.sql +++ b/sql-files/main.sql @@ -169,6 +169,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', @@ -821,6 +822,7 @@ INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1414975503); -- 2014-11-0 INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1435860840); -- 2015-07-02--18-14.sql INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1436360978); -- 2015-07-08--13-08.sql INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1440688342); -- 2015-08-27--20-42.sql +INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1450367880); -- 2015-12-17--15-58.sql -- -- Table structure for table `storage` diff --git a/sql-files/upgrades/2015-12-17--15-58.sql b/sql-files/upgrades/2015-12-17--15-58.sql new file mode 100644 index 000000000..8d3dc51a3 --- /dev/null +++ b/sql-files/upgrades/2015-12-17--15-58.sql @@ -0,0 +1,22 @@ +#1450367880 + +-- This file is part of Hercules. +-- http://herc.ws - http://github.com/HerculesWS/Hercules +-- +-- Copyright (C) 2015 Hercules Dev Team +-- +-- Hercules is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + +ALTER TABLE `char` ADD `body` smallint(5) unsigned NOT NULL default '0' AFTER `clothes_color`; +INSERT INTO `sql_updates` (`timestamp`) VALUES (1450367880); diff --git a/sql-files/upgrades/index.txt b/sql-files/upgrades/index.txt index 5f6aed963..e73a8659d 100644 --- a/sql-files/upgrades/index.txt +++ b/sql-files/upgrades/index.txt @@ -27,4 +27,5 @@ 2014-11-03--00-45.sql 2015-07-02--18-14.sql 2015-07-08--13-08.sql -2015-08-27--20-42.sql \ No newline at end of file +2015-08-27--20-42.sql +2015-12-17--15-58.sql diff --git a/src/char/char.c b/src/char/char.c index e991aafcc..09f74034c 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -508,7 +508,8 @@ int char_mmo_char_tosql(int 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->hair != cp->hair) || (p->hair_color != cp->hair_color) || + (p->clothes_color != cp->clothes_color) || (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) || @@ -517,12 +518,12 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p) ) { if( SQL_ERROR == SQL->Query(inter->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`='%d', `father`='%d', `mother`='%d', `child`='%d'," - "`karma`='%d',`manner`='%d', `fame`='%d'" + "`karma`='%d', `manner`='%d', `fame`='%d'" " WHERE `account_id`='%d' AND `char_id` = '%d'", 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) ) @@ -1070,7 +1071,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`,`slotchange`,`unban_time`,`sex`" " FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", char_db, sd->account_id, MAX_CHARS) || SQL_ERROR == SQL->StmtExecute(stmt) @@ -1101,18 +1102,19 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) || SQL_ERROR == SQL->StmtBindColumn(stmt, 24, SQLDT_SHORT, &p.hair, 0, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 25, SQLDT_SHORT, &p.hair_color, 0, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 26, SQLDT_SHORT, &p.clothes_color, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 27, SQLDT_SHORT, &p.weapon, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 28, SQLDT_SHORT, &p.shield, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 29, SQLDT_SHORT, &p.head_top, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 30, SQLDT_SHORT, &p.head_mid, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 31, SQLDT_SHORT, &p.head_bottom, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 32, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 33, SQLDT_USHORT, &p.rename, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 34, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 35, SQLDT_SHORT, &p.robe, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 36, SQLDT_USHORT, &p.slotchange, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 37, SQLDT_LONG, &unban_time, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 38, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 27, SQLDT_SHORT, &p.body, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 28, SQLDT_SHORT, &p.weapon, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 29, SQLDT_SHORT, &p.shield, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 30, SQLDT_SHORT, &p.head_top, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 31, SQLDT_SHORT, &p.head_mid, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 32, SQLDT_SHORT, &p.head_bottom, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 33, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 34, SQLDT_USHORT, &p.rename, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 35, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 36, SQLDT_SHORT, &p.robe, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 37, SQLDT_USHORT, &p.slotchange, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 38, SQLDT_LONG, &unban_time, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 39, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL) ) { SqlStmt_ShowDebug(stmt); SQL->StmtFree(stmt); @@ -1176,7 +1178,7 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every "`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`,`slotchange`," "`char_opt`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`" " FROM `%s` WHERE `char_id`=? LIMIT 1", char_db) @@ -1215,31 +1217,32 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every || SQL_ERROR == SQL->StmtBindColumn(stmt, 30, SQLDT_SHORT, &p->hair, 0, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 31, SQLDT_SHORT, &p->hair_color, 0, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 32, SQLDT_SHORT, &p->clothes_color, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 33, SQLDT_SHORT, &p->weapon, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 34, SQLDT_SHORT, &p->shield, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 35, SQLDT_SHORT, &p->head_top, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 36, SQLDT_SHORT, &p->head_mid, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 37, SQLDT_SHORT, &p->head_bottom, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 38, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 39, SQLDT_SHORT, &p->last_point.x, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 40, SQLDT_SHORT, &p->last_point.y, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 41, SQLDT_STRING, &save_map, sizeof(save_map), NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 42, SQLDT_SHORT, &p->save_point.x, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 43, SQLDT_SHORT, &p->save_point.y, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 44, SQLDT_INT, &p->partner_id, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 45, SQLDT_INT, &p->father, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 46, SQLDT_INT, &p->mother, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 47, SQLDT_INT, &p->child, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 48, SQLDT_INT, &p->fame, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 49, SQLDT_USHORT, &p->rename, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 50, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 51, SQLDT_SHORT, &p->robe, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 52, SQLDT_USHORT, &p->slotchange, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 53, SQLDT_UINT, &opt, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 54, SQLDT_UCHAR, &p->font, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 55, SQLDT_UINT, &p->uniqueitem_counter, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 56, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 57, SQLDT_UCHAR, &p->hotkey_rowshift, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 33, SQLDT_SHORT, &p->body, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 34, SQLDT_SHORT, &p->weapon, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 35, SQLDT_SHORT, &p->shield, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 36, SQLDT_SHORT, &p->head_top, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 37, SQLDT_SHORT, &p->head_mid, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 38, SQLDT_SHORT, &p->head_bottom, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 39, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 40, SQLDT_SHORT, &p->last_point.x, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 41, SQLDT_SHORT, &p->last_point.y, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 42, SQLDT_STRING, &save_map, sizeof(save_map), NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 43, SQLDT_SHORT, &p->save_point.x, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 44, SQLDT_SHORT, &p->save_point.y, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 45, SQLDT_INT, &p->partner_id, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 46, SQLDT_INT, &p->father, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 47, SQLDT_INT, &p->mother, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 48, SQLDT_INT, &p->child, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 49, SQLDT_INT, &p->fame, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 50, SQLDT_USHORT, &p->rename, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 51, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 52, SQLDT_SHORT, &p->robe, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 53, SQLDT_USHORT, &p->slotchange, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 54, SQLDT_UINT, &opt, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 55, SQLDT_UCHAR, &p->font, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 56, SQLDT_UINT, &p->uniqueitem_counter, 0, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 57, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 58, SQLDT_UCHAR, &p->hotkey_rowshift, 0, NULL, NULL) ) { SqlStmt_ShowDebug(stmt); SQL->StmtFree(stmt); @@ -1998,12 +2001,11 @@ 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 3c556636c..eb1d7cc8e 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -501,7 +501,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 e18b81f44..ffd09caeb 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -1702,6 +1702,32 @@ ACMD(model) return true; } +/*========================================== + * @bodystyle [Rytech] + *------------------------------------------*/ +ACMD(bodystyle) +{ + int body_style = 0; + + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + if (!*message || sscanf(message, "%d", &body_style) < 1) { + sprintf(atcmd_output, "Please, enter a body style (usage: @bodystyle ).", MIN_BODY_STYLE, MAX_BODY_STYLE); + clif->message(fd, atcmd_output); + return false; + } + + if (body_style >= MIN_BODY_STYLE && body_style <= MAX_BODY_STYLE) { + pc->changelook(sd, LOOK_BODY2, body_style); + clif->message(fd, msg_txt(36)); // Appearence changed. + } else { + clif->message(fd, msg_txt(37)); // An invalid number was specified. + return false; + } + + return true; +} + /*========================================== * @dye && @ccolor *------------------------------------------*/ @@ -5484,7 +5510,7 @@ ACMD(divorce) ACMD(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, "%12d %12d", &j, &k)) < 1) { clif->message(fd, msg_fd(fd,1177)); // Usage: @changelook {} @@ -9648,6 +9674,7 @@ void atcommand_basecommands(void) { ACMD_DEF(skdebug), ACMD_DEF(cddebug), ACMD_DEF(lang), + ACMD_DEF(bodystyle), }; int i; diff --git a/src/map/battle.c b/src/map/battle.c index 317b2d98a..7ceefcf49 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -7196,6 +7196,9 @@ static const struct battle_data { { "costume_refine_def", &battle_config.costume_refine_def, 1, 0, 1, }, { "shadow_refine_def", &battle_config.shadow_refine_def, 1, 0, 1, }, { "shadow_refine_atk", &battle_config.shadow_refine_atk, 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 37d78436c..49abdc730 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -43,6 +43,8 @@ struct status_data; #define MAX_HAIR_COLOR (battle->bc->max_hair_color) #define MIN_CLOTH_COLOR (battle->bc->min_cloth_color) #define MAX_CLOTH_COLOR (battle->bc->max_cloth_color) +#define MIN_BODY_STYLE (battle->bc->min_body_style) +#define MAX_BODY_STYLE (battle->bc->max_body_style) #define is_boss(bl) (status_get_mode(bl)&MD_BOSS) // Can refine later [Aru] @@ -529,9 +531,14 @@ struct Battle_Config { int show_monster_hp_bar; // [Frost] int fix_warp_hit_delay_abuse; - + + // Refine Def/Atk int costume_refine_def, shadow_refine_def; int shadow_refine_atk; + + // BodyStyle + int min_body_style, max_body_style; + int save_body_style; }; /* criteria for battle_config.idletime_critera */ diff --git a/src/map/clif.c b/src/map/clif.c index a26fece79..053017a4a 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1059,7 +1059,7 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu } #endif #if PACKETVER >= 20150513 - p.body = 0; + p.body = vd->body_style; #endif clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target); @@ -1198,7 +1198,7 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) { } #endif #if PACKETVER >= 20150513 - p.body = 0; + p.body = vd->body_style; #endif if( disguised(bl) ) { nullpo_retv(sd); @@ -1288,7 +1288,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, } #endif #if PACKETVER >= 20150513 - p.body = 0; + p.body = vd->body_style; #endif clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target); @@ -1417,6 +1417,8 @@ bool 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) { case BL_PC: @@ -1681,6 +1683,8 @@ void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *u 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: @@ -3120,6 +3124,11 @@ void clif_changelook(struct block_list *bl,int type,int val) vd->cloth_color = 0; if (sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */) 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: vd->hair_style = val; @@ -3177,6 +3186,14 @@ void clif_changelook(struct block_list *bl,int type,int val) vd->robe = val; #endif break; + case LOOK_BODY2: + 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; + break; } // prevent leaking the presence of GM-hidden objects @@ -4160,6 +4177,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: { @@ -8281,6 +8301,8 @@ void clif_refresh(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); if(homun_alive(sd->hd)) clif->send_homdata(sd,SP_ACK,0); if( sd->md ) { @@ -9124,6 +9146,8 @@ 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); diff --git a/src/map/map.h b/src/map/map.h index 896c12f23..7047feab6 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -486,6 +486,7 @@ enum look { LOOK_BODY, LOOK_FLOOR, LOOK_ROBE, + LOOK_BODY2, }; // used by map_setcell() diff --git a/src/map/pc.c b/src/map/pc.c index 1045a25be..b6b6787e9 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -596,6 +596,10 @@ int pc_makesavestatus(struct map_session_data *sd) if(!battle_config.save_clothcolor) sd->status.clothes_color=0; + 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] #ifdef NEW_CARTS @@ -1067,6 +1071,9 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim if( sd->status.clothes_color < MIN_CLOTH_COLOR || sd->status.clothes_color > MAX_CLOTH_COLOR ) { sd->status.clothes_color = MIN_CLOTH_COLOR; } + if (sd->status.body < MIN_BODY_STYLE || sd->status.body > MAX_BODY_STYLE) { + sd->status.body = MIN_BODY_STYLE; + } //Initializations to null/0 unneeded since map_session_data was filled with 0 upon allocation. if(!sd->status.hp) pc_setdead(sd); @@ -8450,6 +8457,8 @@ int pc_jobchange(struct map_session_data *sd,int job, int 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); @@ -8546,6 +8555,8 @@ int pc_changelook(struct map_session_data *sd,int type,int val) 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 0; break; @@ -8594,6 +8605,10 @@ int pc_changelook(struct map_session_data *sd,int type,int val) 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); return 0; @@ -8690,6 +8705,8 @@ int 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. return 0; diff --git a/src/map/script.c b/src/map/script.c index 3fa0f1fd8..04b4b6a32 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -14109,6 +14109,7 @@ BUILDIN(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); diff --git a/src/map/status.c b/src/map/status.c index d88d163f0..e96b881dd 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -6525,6 +6525,7 @@ void status_set_viewdata(struct block_list *bl, int class_) 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.robe = sd->status.robe; + sd->vd.body_style = sd->status.body; sd->vd.sex = sd->status.sex; if ( sd->vd.cloth_color ) { @@ -6539,6 +6540,11 @@ void status_set_viewdata(struct block_list *bl, int class_) if( sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */ ) 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 @@ -9464,6 +9470,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t 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; case SC_KAAHI: val4 = INVALID_TIMER; @@ -9869,6 +9876,17 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t calc_flag&=~SCB_DYE; } +#if 0 //Currently No SC's use this + if (calc_flag&SCB_BODY) { + //Reset Body Style + if (vd && vd->body_style) { + val4 = vd->body_style; + clif->changelook(bl,LOOK_BODY2,0); + } + calc_flag&=~SCB_BODY; + } +#endif + if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->dbs->DisplayType[type])) clif->status_change(bl,status->dbs->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); @@ -10752,6 +10770,14 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const calc_flag&=~SCB_DYE; } +#if 0 // Currently No SC's use this + if (calc_flag&SCB_BODY) { // Restore Body color + if (vd && !vd->body_style && sce->val4) + clif->changelook(bl,LOOK_BODY2,sce->val4); + calc_flag&=~SCB_BODY; + } +#endif + //On Aegis, when turning off a status change, first goes the sc packet, then the option packet. clif->sc_end(bl,bl->id,AREA,status->dbs->IconChangeTable[type]); @@ -10765,6 +10791,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)); } } diff --git a/src/map/status.h b/src/map/status.h index 90b05c71c..55df4cdab 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -1923,6 +1923,9 @@ enum scb_flag SCB_RANGE = 0x10000000, SCB_REGEN = 0x20000000, SCB_DYE = 0x40000000, // force cloth-dye change to 0 to avoid client crashes. +#if 0 // Currently No SC use it. Also, when this will be implemented, there will be need to change to 64bit variable + SCB_BODY = 0x80000000, // Force bodysStyle change to 0 +#endif SCB_BATTLE = 0x3FFFFFFE, SCB_ALL = 0x3FFFFFFF diff --git a/src/map/unit.h b/src/map/unit.h index f0933aa9a..0279d73c1 100644 --- a/src/map/unit.h +++ b/src/map/unit.h @@ -93,7 +93,8 @@ struct view_data { head_bottom, hair_style, hair_color, - cloth_color; + cloth_color, + body_style; char sex; unsigned dead_sit : 2; }; -- cgit v1.2.3-60-g2f50