summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2018-06-03 22:51:08 +0200
committerGitHub <noreply@github.com>2018-06-03 22:51:08 +0200
commitb5ee7e4863f60a43d6c44c93104d4df4146fdd84 (patch)
treec9eb881ba40f8c9b4acb45945a5dcbbed82b79ca
parent1670e2b6e5eca660d73aafb8cbb4830bd453e79e (diff)
parentec527a6a2d2d915fb23ebb9b62c684eb7ad9b0b4 (diff)
downloadhercules-b5ee7e4863f60a43d6c44c93104d4df4146fdd84.tar.gz
hercules-b5ee7e4863f60a43d6c44c93104d4df4146fdd84.tar.bz2
hercules-b5ee7e4863f60a43d6c44c93104d4df4146fdd84.tar.xz
hercules-b5ee7e4863f60a43d6c44c93104d4df4146fdd84.zip
Merge pull request #2004 from Asheraf/stylist
Implementation of stylist ui
-rw-r--r--conf/messages.conf6
-rw-r--r--db/pre-re/item_db.conf39
-rw-r--r--db/re/item_db.conf39
-rw-r--r--db/stylist_db.conf309
-rw-r--r--doc/script_commands.txt6
-rw-r--r--src/map/clif.c204
-rw-r--r--src/map/clif.h23
-rw-r--r--src/map/itemdb.c4
-rw-r--r--src/map/map.h4
-rw-r--r--src/map/packets.h8
-rw-r--r--src/map/packets_struct.h15
-rw-r--r--src/map/script.c12
12 files changed, 665 insertions, 4 deletions
diff --git a/conf/messages.conf b/conf/messages.conf
index 0c238d0fe..a7a11b969 100644
--- a/conf/messages.conf
+++ b/conf/messages.conf
@@ -378,7 +378,11 @@
363: Duel: The duel invitation has been rejected.
364: Duel: You can't invite %s because he/she isn't in the same map.
365: Duel: Can't use %s in duel.
-//366-369 FREE
+// Stylist Shop
+366: Styling Shop
+367: <MSG>2949</MSG>
+368: <MSG>2950</MSG>
+//369 FREE
370: -- Duels: %d/%d, Members: %d/%d, Max players: %d --
371: -- Duels: %d/%d, Members: %d/%d --
372: -- Duel has been created (Use @invite/@leave) --
diff --git a/db/pre-re/item_db.conf b/db/pre-re/item_db.conf
index d62bbf19c..dfe27f428 100644
--- a/db/pre-re/item_db.conf
+++ b/db/pre-re/item_db.conf
@@ -55829,6 +55829,12 @@ item_db: (
Weight: 1
},
{
+ Id: 6707
+ AegisName: "Cash_Hair_Coupon"
+ Name: "Cash Hair Coupon"
+ Weight: 10
+},
+{
Id: 7001
AegisName: "Mould_Powder"
Name: "Mould Powder"
@@ -93981,7 +93987,38 @@ item_db: (
Weight: 10
Script: <" getitem 12581,50; ">
},
-
+{
+ Id: 16843
+ AegisName: "Beauty_Gift_Box"
+ Name: "Beauty Gift Box"
+ Type: "IT_USABLE"
+ Weight: 10
+ Script: <" getitem(New_Style_Coupon, 1); ">
+},
+{
+ Id: 16854
+ AegisName: "Clothing_Dye_Box"
+ Name: "Clothing Dye Box"
+ Type: "IT_USABLE"
+ Weight: 10
+ Script: <" getitem(Clothing_Dye_Coupon, 1); ">
+},
+{
+ Id: 16855
+ AegisName: "Clothing_Dye_Orig_Box"
+ Name: "Clothing Dye Orig Box"
+ Type: "IT_USABLE"
+ Weight: 10
+ Script: <" getitem(Clothing_Dye_Coupon2, 1); ">
+},
+{
+ Id: 17336
+ AegisName: "Jeremy_Beauty_Coupon_Box"
+ Name: "Jeremy's Beauty Coupon Box"
+ Type: "IT_USABLE"
+ Weight: 10
+ Script: <" getitem(Cash_Hair_Coupon, 1); ">
+},
//== Mechanic / Geneticist Cannon Balls ====================
{
Id: 18000
diff --git a/db/re/item_db.conf b/db/re/item_db.conf
index 6c4e820e8..bc3470fd9 100644
--- a/db/re/item_db.conf
+++ b/db/re/item_db.conf
@@ -74438,6 +74438,12 @@ item_db: (
}
},
{
+ Id: 6707
+ AegisName: "Cash_Hair_Coupon"
+ Name: "Cash Hair Coupon"
+ Weight: 10
+},
+{
Id: 6712
AegisName: "Lovely_Stick"
Name: "Love Wand"
@@ -128151,6 +128157,30 @@ item_db: (
Script: <" packageitem(); ">
},
{
+ Id: 16843
+ AegisName: "Beauty_Gift_Box"
+ Name: "Beauty Gift Box"
+ Type: "IT_USABLE"
+ Weight: 10
+ Script: <" getitem(New_Style_Coupon, 1); ">
+},
+{
+ Id: 16854
+ AegisName: "Clothing_Dye_Box"
+ Name: "Clothing Dye Box"
+ Type: "IT_USABLE"
+ Weight: 10
+ Script: <" getitem(Clothing_Dye_Coupon, 1); ">
+},
+{
+ Id: 16855
+ AegisName: "Clothing_Dye_Orig_Box"
+ Name: "Clothing Dye Orig Box"
+ Type: "IT_USABLE"
+ Weight: 10
+ Script: <" getitem(Clothing_Dye_Coupon2, 1); ">
+},
+{
Id: 16972
AegisName: "Weather_Report_Box"
Name: "Weather Forecast Box"
@@ -130037,7 +130067,14 @@ item_db: (
}
Script: <" getitem LUK_Biscuit_Stick,20; ">
},
-
+{
+ Id: 17336
+ AegisName: "Jeremy_Beauty_Coupon_Box"
+ Name: "Jeremy's Beauty Coupon Box"
+ Type: "IT_USABLE"
+ Weight: 10
+ Script: <" getitem(Cash_Hair_Coupon, 1); ">
+},
//== Mechanic / Geneticist Cannon Balls ====================
{
Id: 18000
diff --git a/db/stylist_db.conf b/db/stylist_db.conf
new file mode 100644
index 000000000..f11bf016a
--- /dev/null
+++ b/db/stylist_db.conf
@@ -0,0 +1,309 @@
+//================= Hercules Database =====================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2018 Hercules Dev Team
+//= Copyright (C) 2018 Asheraf
+//=
+//= 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/>.
+//=========================================================================
+//= Stylist Database
+//=========================================================================
+
+stylist_db: (
+ /**************************************************************************
+ ************* Entry structure ********************************************
+ **************************************************************************
+{
+ // ================ Mandatory fields ==============================
+ Type: TYPE (int)
+ Id: ID (int)
+ // ================ Optional fields ===============================
+ Zeny: zeny (int, defaults to 0)
+ ItemID: ItemID (int, defaults to 0)
+ BoxItemID: BoxItemID (int, defaults to 0)
+},
+**************************************************************************/
+{
+ Type: "LOOK_HAIR_COLOR"
+ Id: 1
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR_COLOR"
+ Id: 2
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR_COLOR"
+ Id: 3
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR_COLOR"
+ Id: 4
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR_COLOR"
+ Id: 5
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR_COLOR"
+ Id: 6
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR_COLOR"
+ Id: 7
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR_COLOR"
+ Id: 8
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 1
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 2
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 3
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 4
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 5
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 6
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 7
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 8
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 9
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 10
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 11
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 12
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 13
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 14
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 15
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 16
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 17
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 18
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 19
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 20
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 21
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 22
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 23
+ Zeny: 100000
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 24
+ ItemID: "New_Style_Coupon"
+ BoxItemID: "Beauty_Gift_Box"
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 25
+ ItemID: "New_Style_Coupon"
+ BoxItemID: "Beauty_Gift_Box"
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 26
+ ItemID: "New_Style_Coupon"
+ BoxItemID: "Beauty_Gift_Box"
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 27
+ ItemID: "New_Style_Coupon"
+ BoxItemID: "Beauty_Gift_Box"
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 28
+ ItemID: "Cash_Hair_Coupon"
+ BoxItemID: "Jeremy_Beauty_Coupon_Box"
+},
+{
+ Type: "LOOK_HAIR"
+ Id: 29
+ ItemID: "Cash_Hair_Coupon"
+ BoxItemID: "Jeremy_Beauty_Coupon_Box"
+},
+{
+ Type: "LOOK_CLOTHES_COLOR"
+ Id: 1
+ ItemID: "Clothing_Dye_Coupon2"
+ BoxItemID: "Clothing_Dye_Orig_Box"
+},
+{
+ Type: "LOOK_CLOTHES_COLOR"
+ Id: 2
+ ItemID: "Clothing_Dye_Coupon"
+ BoxItemID: "Clothing_Dye_Box"
+},
+{
+ Type: "LOOK_CLOTHES_COLOR"
+ Id: 3
+ ItemID: "Clothing_Dye_Coupon"
+ BoxItemID: "Clothing_Dye_Box"
+},
+{
+ Type: "LOOK_HEAD_TOP"
+ Id: "Hat"
+ Zeny: 1000
+},
+{
+ Type: "LOOK_HEAD_TOP"
+ Id: "Ribbon"
+ Zeny: 800
+},
+{
+ Type: "LOOK_HEAD_TOP"
+ Id: "Bandana"
+ Zeny: 400
+},
+{
+ Type: "LOOK_HEAD_MID"
+ Id: "One_Eyed_Glass"
+ Zeny: 10000
+},
+{
+ Type: "LOOK_HEAD_MID"
+ Id: "Sunglasses"
+ Zeny: 5000
+},
+{
+ Type: "LOOK_HEAD_MID"
+ Id: "Luxury_Sunglasses"
+ Zeny: 24000
+},
+{
+ Type: "LOOK_HEAD_MID"
+ Id: "Spinning_Eyes"
+ Zeny: 20000
+},
+{
+ Type: "LOOK_HEAD_MID"
+ Id: "Divers_Goggles"
+ Zeny: 3500
+},
+{
+ Type: "LOOK_HEAD_MID"
+ Id: "Glasses"
+ Zeny: 4000
+},
+{
+ Type: "LOOK_HEAD_MID"
+ Id: "Eye_Bandage"
+ Zeny: 1000
+},
+{
+ Type: "LOOK_HEAD_BOTTOM"
+ Id: "Granpa_Beard"
+ Zeny: 5000
+},
+)
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index c8fa056d4..36c4da35a 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -10063,3 +10063,9 @@ the available flags are:
P_AIRSHIP_ITEM_INVALID
---------------------------------------
+
+*openstylist()
+
+Opens the styling shop on client
+
+--------------------------------------- \ No newline at end of file
diff --git a/src/map/clif.c b/src/map/clif.c
index 3bdea3f7f..a4d2f62b1 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -20541,6 +20541,10 @@ void clif_open_ui(struct map_session_data *sd, int8 UIType)
p.PacketType = 0xAE2;
switch (UIType) {
+ case STYLIST_UI:
+ p.UIType = STYLIST_UI;
+ p.data = 0;
+ break;
case 5: // client will send 5 for the request but requires to receive ATTENDANCE_UI (7) to open the correct ui.
if (clif->attendance_timediff(sd) != true)
++claimed;
@@ -20672,6 +20676,196 @@ void clif_private_airship_response(struct map_session_data *sd, uint32 flag)
#endif
}
+void clif_stylist_vector_init(void)
+{
+ int i;
+ for (i = 0; i < MAX_STYLIST_TYPE; i++) {
+ VECTOR_INIT(stylist_data[i]);
+ }
+}
+
+void clif_stylist_vector_clear(void)
+{
+ int i;
+ for (i = 0; i < MAX_STYLIST_TYPE; i++) {
+ VECTOR_CLEAR(stylist_data[i]);
+ }
+}
+
+bool clif_stylist_read_db_libconfig(void)
+{
+ struct config_t stylist_conf;
+ struct config_setting_t *stylist = NULL, *it = NULL;
+ const char *config_filename = "db/stylist_db.conf"; // FIXME hardcoded name
+ int i = 0;
+
+ if (!libconfig->load_file(&stylist_conf, config_filename))
+ return false;
+
+ if ((stylist = libconfig->setting_get_member(stylist_conf.root, "stylist_db")) == NULL) {
+ ShowError("can't read %s\n", config_filename);
+ return false;
+ }
+
+ clif->stylist_vector_clear();
+
+ while ((it = libconfig->setting_get_elem(stylist, i++))) {
+ clif->stylist_read_db_libconfig_sub(it, i - 1, config_filename);
+ }
+
+ libconfig->destroy(&stylist_conf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, config_filename);
+ return true;
+}
+
+bool clif_stylist_read_db_libconfig_sub(struct config_setting_t *it, int idx, const char *source)
+{
+ struct stylist_data_entry entry = { 0 };
+ int i32 = 0, type = 0;
+ int64 i64 = 0;
+
+ nullpo_ret(it);
+ nullpo_ret(source);
+
+ if (!itemdb->lookup_const(it, "Type", &type) || type >= MAX_STYLIST_TYPE || type < 0) {
+ ShowWarning("clif_stylist_read_db_libconfig_sub: Invalid or missing Type (%d) in \"%s\", entry #%d, skipping.\n", type, source, idx);
+ return false;
+ }
+ if (!itemdb->lookup_const(it, "Id", &i32) || i32 <= 0) {
+ ShowWarning("clif_stylist_read_db_libconfig_sub: Invalid or missing Id (%d) in \"%s\", entry #%d, skipping.\n", i32, source, idx);
+ return false;
+ }
+ entry.id = i32;
+
+ if (libconfig->setting_lookup_int64(it, "Zeny", &i64)) {
+ if (i64 > MAX_ZENY) {
+ ShowWarning("clif_stylist_read_db_libconfig_sub: zeny is too big in \"%s\", entry #%d, capping to MAX_ZENY.\n", source, idx);
+ entry.zeny = MAX_ZENY;
+ } else {
+ entry.zeny = (int)i64;
+ }
+ }
+
+ if (itemdb->lookup_const(it, "ItemID", &i32))
+ entry.itemid = i32;
+
+ if (itemdb->lookup_const(it, "BoxItemID", &i32))
+ entry.boxid = i32;
+
+ VECTOR_ENSURE(stylist_data[type], 1, 1);
+ VECTOR_PUSH(stylist_data[type], entry);
+ return true;
+}
+
+bool clif_style_change_validate_requirements(struct map_session_data *sd, int type, int16 idx)
+{
+ struct item it;
+ struct stylist_data_entry *entry;
+
+ nullpo_retr(false, sd);
+ Assert_retr(false, type >= 0 && type < MAX_STYLIST_TYPE);
+ Assert_retr(false, idx >= 0 && idx < VECTOR_LENGTH(stylist_data[type]));
+
+ entry = &VECTOR_INDEX(stylist_data[type], idx);
+
+ if (entry->id != 0) {
+ if (entry->zeny != 0) {
+ if (sd->status.zeny < entry->zeny)
+ return false;
+
+ sd->status.zeny -= entry->zeny;
+ clif->updatestatus(sd, SP_ZENY);
+ } else if (entry->itemid != 0) {
+ it.nameid = entry->itemid;
+ it.amount = 1;
+ return script->buildin_delitem_search(sd, &it, false);
+ } else if (entry->boxid != 0) {
+ it.nameid = entry->boxid;
+ it.amount = 1;
+ return script->buildin_delitem_search(sd, &it, false);
+ }
+ return true;
+ }
+ return false;
+}
+void clif_stylist_send_rodexitem(struct map_session_data *sd, int16 itemid)
+{
+ struct rodex_message msg = { 0 };
+
+ nullpo_retv(sd);
+
+ msg.receiver_id = sd->status.char_id;
+ msg.items[0].item.nameid = itemid;
+ msg.items[0].item.amount = 1;
+ msg.items[0].item.identify = 1;
+ msg.type = MAIL_TYPE_NPC | MAIL_TYPE_ITEM;
+
+ safestrncpy(msg.sender_name, msg_txt(366), NAME_LENGTH);
+ safestrncpy(msg.title, msg_txt(367), RODEX_TITLE_LENGTH);
+ safestrncpy(msg.body, msg_txt(368), MAIL_BODY_LENGTH);
+ msg.send_date = (int)time(NULL);
+ msg.expire_date = (int)time(NULL) + RODEX_EXPIRE;
+
+ intif->rodex_sendmail(&msg);
+}
+
+void clif_parse_cz_req_style_change(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+void clif_parse_cz_req_style_change(int fd, struct map_session_data *sd)
+{
+ const struct PACKET_CZ_REQ_STYLE_CHANGE *p = RP2PTR(fd);
+
+ if (p->HeadStyle > 0)
+ clif->cz_req_style_change_sub(sd, LOOK_HAIR, p->HeadStyle, false);
+ if (p->HeadPalette > 0)
+ clif->cz_req_style_change_sub(sd, LOOK_HAIR_COLOR, p->HeadPalette, false);
+ if (p->BodyPalette > 0)
+ clif->cz_req_style_change_sub(sd, LOOK_CLOTHES_COLOR, p->BodyPalette, false);
+ if (p->TopAccessory > 0)
+ clif->cz_req_style_change_sub(sd, LOOK_HEAD_TOP, p->TopAccessory, true);
+ if (p->MidAccessory > 0)
+ clif->cz_req_style_change_sub(sd, LOOK_HEAD_MID, p->MidAccessory, true);
+ if (p->BottomAccessory > 0)
+ clif->cz_req_style_change_sub(sd, LOOK_HEAD_BOTTOM, p->BottomAccessory, true);
+
+ clif->style_change_response(sd, true);
+ return;
+}
+
+void clif_cz_req_style_change_sub(struct map_session_data *sd, int type, int16 idx, bool isitem)
+{
+ struct stylist_data_entry *entry;
+
+ nullpo_retv(sd);
+ Assert_retv(idx > 0);
+ Assert_retv(type >= 0 && type < MAX_STYLIST_TYPE);
+
+ if ((idx - 1) < VECTOR_LENGTH(stylist_data[type])) {
+ entry = &VECTOR_INDEX(stylist_data[type], idx - 1);
+ if (clif->style_change_validate_requirements(sd, type, idx - 1)) {
+ if (isitem == false)
+ pc->changelook(sd, type, entry->id);
+ else
+ clif->stylist_send_rodexitem(sd, entry->id);
+ }
+ }
+}
+
+void clif_style_change_response(struct map_session_data *sd, int8 flag)
+{
+#if PACKETVER >= 20151104
+ struct PACKET_ZC_STYLE_CHANGE_RES p;
+
+ nullpo_retv(sd);
+
+ p.PacketType = 0x0a47;
+ p.flag = flag;
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#else
+ ShowWarning("clif_style_change_response: unsupported client version is being used.");
+#endif
+}
+
/*==========================================
* Main client packet processing function
*------------------------------------------*/
@@ -21780,4 +21974,14 @@ void clif_defaults(void) {
clif->ui_action = clif_ui_action;
clif->pPrivateAirshipRequest = clif_parse_private_airship_request;
clif->PrivateAirshipResponse = clif_private_airship_response;
+
+ clif->stylist_vector_init = clif_stylist_vector_init;
+ clif->stylist_vector_clear = clif_stylist_vector_clear;
+ clif->stylist_read_db_libconfig = clif_stylist_read_db_libconfig;
+ clif->stylist_read_db_libconfig_sub = clif_stylist_read_db_libconfig_sub;
+ clif->style_change_validate_requirements = clif_style_change_validate_requirements;
+ clif->stylist_send_rodexitem = clif_stylist_send_rodexitem;
+ clif->pReqStyleChange = clif_parse_cz_req_style_change;
+ clif->cz_req_style_change_sub = clif_cz_req_style_change_sub;
+ clif->style_change_response = clif_style_change_response;
}
diff --git a/src/map/clif.h b/src/map/clif.h
index 5281c68cf..20ecf8e8d 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -67,6 +67,10 @@ enum clif_messages;
#define MAX_ROULETTE_COLUMNS 9 /** client-defined value **/
#define RGB2BGR(c) (((c) & 0x0000FF) << 16 | ((c) & 0x00FF00) | ((c) & 0xFF0000) >> 16)
+#ifndef MAX_STYLIST_TYPE
+#define MAX_STYLIST_TYPE LOOK_MAX
+#endif
+
#define COLOR_CYAN 0x00ffffU
#define COLOR_RED 0xff0000U
#define COLOR_GREEN 0x00ff00U
@@ -602,6 +606,15 @@ struct attendance_entry {
int qty;
};
+/* Stylist data [Asheraf/Hercules]*/
+struct stylist_data_entry {
+ int16 id;
+ int32 zeny;
+ int16 itemid;
+ int16 boxid;
+};
+VECTOR_DECL(struct stylist_data_entry) stylist_data[MAX_STYLIST_TYPE];
+
/**
* Clif.c Interface
**/
@@ -1436,6 +1449,16 @@ struct clif_interface {
void (*ui_action) (struct map_session_data *sd, int32 UIType, int32 data);
void (*pPrivateAirshipRequest) (int fd, struct map_session_data *sd);
void (*PrivateAirshipResponse) (struct map_session_data *sd, uint32 flag);
+
+ void (*stylist_vector_init) (void);
+ void (*stylist_vector_clear) (void);
+ bool (*stylist_read_db_libconfig) (void);
+ bool (*stylist_read_db_libconfig_sub) (struct config_setting_t *it, int idx, const char *source);
+ bool (*style_change_validate_requirements) (struct map_session_data *sd, int type, int16 idx);
+ void (*stylist_send_rodexitem) (struct map_session_data *sd, int16 itemid);
+ void (*pReqStyleChange) (int fd, struct map_session_data *sd);
+ void (*cz_req_style_change_sub) (struct map_session_data *sd, int type, int16 idx, bool isitem);
+ void (*style_change_response) (struct map_session_data *sd, int8 flag);
};
#ifdef HERCULES_CORE
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 2ab3f2b05..d958d03d2 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -2394,7 +2394,7 @@ void itemdb_read(bool minimal) {
itemdb->read_chains();
itemdb->read_packages();
itemdb->read_options();
-
+ clif->stylist_read_db_libconfig();
}
/**
@@ -2622,6 +2622,7 @@ void do_final_itemdb(void) {
itemdb->destroy_item_data(&itemdb->dummy, 0);
db_destroy(itemdb->names);
VECTOR_CLEAR(clif->attendance_data);
+ clif->stylist_vector_clear();
}
void do_init_itemdb(bool minimal) {
@@ -2630,6 +2631,7 @@ void do_init_itemdb(bool minimal) {
itemdb->options = idb_alloc(DB_OPT_RELEASE_DATA);
itemdb->names = strdb_alloc(DB_OPT_BASE,ITEM_NAME_LENGTH);
itemdb->create_dummy_data(); //Dummy data item.
+ clif->stylist_vector_init();
itemdb->read(minimal);
if (minimal)
diff --git a/src/map/map.h b/src/map/map.h
index 276bc5d37..494f93cfe 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -625,6 +625,10 @@ enum look {
LOOK_FLOOR,
LOOK_ROBE,
LOOK_BODY2,
+
+#ifndef LOOK_MAX
+ LOOK_MAX
+#endif
};
// used by map_setcell()
diff --git a/src/map/packets.h b/src/map/packets.h
index ce93ef36c..72d775dd3 100644
--- a/src/map/packets.h
+++ b/src/map/packets.h
@@ -3384,6 +3384,14 @@ packet(0x96e,-1,clif->ackmergeitems);
packet(0x0a45,-1);
#endif
+// 2015-11-04aRagexeRE
+#if PACKETVER >= 20151104
+// new packets
+ packet(0x0a46,14,clif->pReqStyleChange);
+ packet(0x0a47,3);
+ packet(0x0a48,2,clif->pDull/*,XXX*/);
+#endif
+
// 2015-11-18aRagexeRE
#if PACKETVER >= 20151118
// new packets
diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h
index cae794e92..971e7c330 100644
--- a/src/map/packets_struct.h
+++ b/src/map/packets_struct.h
@@ -1740,6 +1740,21 @@ struct PACKET_ZC_PRIVATE_AIRSHIP_RESPONSE {
uint32 flag;
} __attribute__((packed));
+struct PACKET_CZ_REQ_STYLE_CHANGE {
+ int16 PacketType;
+ int16 HeadPalette;
+ int16 HeadStyle;
+ int16 BodyPalette;
+ int16 TopAccessory;
+ int16 MidAccessory;
+ int16 BottomAccessory;
+} __attribute__((packed));
+
+struct PACKET_ZC_STYLE_CHANGE_RES {
+ int16 PacketType;
+ int8 flag;
+} __attribute__((packed));
+
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
#pragma pack(pop)
#endif // not NetBSD < 6 / Solaris
diff --git a/src/map/script.c b/src/map/script.c
index e127c4f4f..d9350081a 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -24161,6 +24161,17 @@ BUILDIN(hateffect)
return true;
}
+BUILDIN(openstylist)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+
+ if (sd == NULL)
+ return false;
+
+ clif->open_ui(sd, STYLIST_UI);
+ return true;
+}
+
/**
* Adds a built-in script function.
*
@@ -24877,6 +24888,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(rodex_sendmail2, "isss?????????????????????????????????????????"),
BUILDIN_DEF2(rodex_sendmail2, "rodex_sendmail_acc2", "isss?????????????????????????????????????????"),
BUILDIN_DEF(airship_respond, "i"),
+ BUILDIN_DEF(openstylist,""),
BUILDIN_DEF(_,"s"),
BUILDIN_DEF2(_, "_$", "s"),