summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/battle/client.conf7
-rw-r--r--conf/messages.conf2
-rw-r--r--db/const.txt1
-rw-r--r--sql-files/main.sql2
-rw-r--r--sql-files/upgrades/2015-12-17--15-58.sql22
-rw-r--r--sql-files/upgrades/index.txt3
-rw-r--r--src/char/char.c94
-rw-r--r--src/common/mmo.h2
-rw-r--r--src/map/atcommand.c29
-rw-r--r--src/map/battle.c3
-rw-r--r--src/map/battle.h9
-rw-r--r--src/map/clif.c30
-rw-r--r--src/map/map.h1
-rw-r--r--src/map/pc.c17
-rw-r--r--src/map/script.c1
-rw-r--r--src/map/status.c27
-rw-r--r--src/map/status.h3
-rw-r--r--src/map/unit.h3
18 files changed, 201 insertions, 55 deletions
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 {<position>} <view id>
-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 <http://www.gnu.org/licenses/>.
+
+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
@@ -1703,6 +1703,32 @@ ACMD(model)
}
/*==========================================
+ * @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 <body ID: %d-%d>).", 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
*------------------------------------------*/
ACMD(dye)
@@ -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 {<position>} <view id>
@@ -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;
};