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 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) (limited to 'src/map/clif.c') 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; } -- cgit v1.2.3-60-g2f50