From ec527a6a2d2d915fb23ebb9b62c684eb7ad9b0b4 Mon Sep 17 00:00:00 2001 From: Asheraf Date: Fri, 30 Mar 2018 00:02:14 +0100 Subject: Implementation of stylist ui --- src/map/clif.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++ src/map/clif.h | 23 ++++++ src/map/itemdb.c | 4 +- src/map/map.h | 4 + src/map/packets.h | 8 ++ src/map/packets_struct.h | 15 ++++ src/map/script.c | 12 +++ 7 files changed, 269 insertions(+), 1 deletion(-) (limited to 'src/map') 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 b9a826b93..e92286324 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -24159,6 +24159,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. * @@ -24875,6 +24886,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"), -- cgit v1.2.3-60-g2f50