diff options
Diffstat (limited to 'src/map/clif.c')
-rw-r--r-- | src/map/clif.c | 423 |
1 files changed, 419 insertions, 4 deletions
diff --git a/src/map/clif.c b/src/map/clif.c index 82f7aaa6f..956a5751e 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -36,6 +36,7 @@ #include "log.h" #include "irc.h" #include "clif.h" +#include "mail.h" #include <stdio.h> #include <stdlib.h> @@ -2500,7 +2501,7 @@ int clif_updatestatus(struct map_session_data *sd,int type) case SP_ZENY: WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=sd->status.zeny; + WFIFOL(fd,4)=sd->status.zeny - sd->mail.zeny; break; case SP_BASEEXP: WFIFOW(fd,0)=0xb1; @@ -11294,6 +11295,409 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd) pc_delitem(sd, item_position, 1, 0); } +#ifndef TXT_ONLY + +/*========================================== + * MAIL SYSTEM + * By Zephyrus + *------------------------------------------ + * Opens Mail Window on Client + *------------------------------------------*/ +void clif_Mail_openmail(int fd) +{ + WFIFOHEAD(fd,packet_len(0x260)); + WFIFOW(fd,0) = 0x260; + WFIFOL(fd,2) = 0; + WFIFOSET(fd,packet_len(0x260)); +} +/*------------------------------------------ + * Send Inbox Data to Client + *------------------------------------------*/ +void clif_Mail_refreshinbox(struct map_session_data *sd) +{ + int fd = sd->fd; + struct mail_data *md = &sd->mail.inbox; + struct mail_message *msg; + int len, i, j; + + len = 8 + (73 * md->amount); + + WFIFOHEAD(fd,len); + WFIFOW(fd,0) = 0x240; + WFIFOW(fd,2) = len; + WFIFOL(fd,4) = md->amount; + for( i = j = 0; i < MAX_MAIL_INBOX && j < md->amount; i++ ) + { + msg = &md->msg[i]; + if (msg->id < 1) + continue; // Deleted Message + + WFIFOL(fd,8+73*j) = msg->id; + memcpy(WFIFOP(fd,12+73*j), msg->title, MAIL_TITLE_LENGTH); + WFIFOB(fd,52+73*j) = msg->read; + memcpy(WFIFOP(fd,53+73*j), msg->send_name, NAME_LENGTH); + WFIFOL(fd,77+73*j) = msg->timestamp; + j++; + } + WFIFOSET(fd,len); +} +/*------------------------------------------ + * Client Request Inbox List + *------------------------------------------*/ +void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd) +{ + struct mail_data *md; + + nullpo_retv(sd); + md = &sd->mail.inbox; + + if( md->amount < MAX_MAIL_INBOX && (md->satured || md->changed) ) + intif_Mail_requestinbox(sd->status.char_id, 1); + else + clif_Mail_refreshinbox(sd); + + mail_removeitem(sd, 0); + mail_removezeny(sd, 0); +} + +/*------------------------------------------ + * Read Message + *------------------------------------------*/ +void clif_Mail_read(struct map_session_data *sd, int mail_id) +{ + int i, fd = sd->fd; + + ARR_FIND(0, MAX_MAIL_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if (i < MAX_MAIL_INBOX) + { + struct mail_message *msg = &sd->mail.inbox.msg[i]; + struct item *item = &msg->item; + struct item_data *data; + int msg_len = strlen(msg->body), len; + + if( msg_len == 0 ) { + strcpy(msg->body, "(no message)"); + msg_len = strlen(msg->body); + } + + len = 101 + msg_len; + + WFIFOHEAD(fd,len); + WFIFOW(fd,0) = 0x242; + WFIFOW(fd,2) = len; + WFIFOL(fd,4) = msg->id; + memcpy(WFIFOP(fd, 8), msg->title, MAIL_TITLE_LENGTH); + memcpy(WFIFOP(fd,48), msg->send_name, NAME_LENGTH); + WFIFOL(fd,72) = 0; + WFIFOL(fd,76) = msg->zeny; + + if (item->nameid) + { + WFIFOL(fd,80) = item->amount; + if ((data = itemdb_search(item->nameid)) != NULL) + WFIFOW(fd,84) = (data->view_id)?data->view_id:item->nameid; + else + ShowWarning("clif_parse_Mail_read: Invalid attachment on message %d.\n", msg->id); + + WFIFOW(fd,86) = data->type; + } + else + { + WFIFOL(fd,80) = 0; + WFIFOW(fd,84) = 0; + WFIFOW(fd,86) = 0; + } + + WFIFOB(fd,88) = item->identify; + WFIFOB(fd,89) = item->attribute; + WFIFOB(fd,90) = item->refine; + WFIFOW(fd,91) = item->card[0]; + WFIFOW(fd,93) = item->card[1]; + WFIFOW(fd,95) = item->card[2]; + WFIFOW(fd,97) = item->card[3]; + WFIFOB(fd,99) = (unsigned char)msg_len; + memcpy(WFIFOP(fd,100), msg->body, msg_len); + WFIFOB(fd,len - 1) = 0x00; + WFIFOSET(fd,len); + + if (!msg->read) { + msg->read = 1; + intif_Mail_read(mail_id); + clif_parse_Mail_refreshinbox(fd, sd); + } + } + else + ShowWarning("clif_parse_Mail_read: account %d trying to read a message not the inbox.\n", sd->status.account_id); +} + +void clif_parse_Mail_read(int fd, struct map_session_data *sd) +{ + nullpo_retv(sd); + clif_Mail_read(sd, RFIFOL(fd,2)); +} + +/*------------------------------------------ + * Get Attachment from Message + *------------------------------------------*/ +void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) +{ + int i, mail_id = RFIFOL(fd,2); + nullpo_retv(sd); + + ARR_FIND(0, MAX_MAIL_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if (i < MAX_MAIL_INBOX) + { + if (sd->mail.inbox.msg[i].zeny < 1 && (sd->mail.inbox.msg[i].item.nameid < 1 || sd->mail.inbox.msg[i].item.amount < 1)) + return; + + if (sd->mail.inbox.msg[i].item.nameid > 0) + { + struct item_data *data; + unsigned int weight; + + if ((data = itemdb_search(sd->mail.inbox.msg[i].item.nameid)) == NULL) + return; + + weight = data->weight * sd->mail.inbox.msg[i].item.amount; + if (weight > sd->max_weight - sd->weight) + { + clif_displaymessage(fd, "Attachment to heavy for you..."); + return; + } + } + + sd->mail.inbox.msg[i].zeny = 0; + memset(&sd->mail.inbox.msg[i].item, 0, sizeof(struct item)); + clif_Mail_read(sd, mail_id); + + // Send the request for Char Server to delete the attachment + // If it is done, the client will receive it. + intif_Mail_getattach(sd->status.char_id, mail_id); + } +} +/*------------------------------------------ + * Delete Message + *------------------------------------------*/ +void clif_Mail_delete(struct map_session_data *sd, int mail_id, short flag) +{ + int fd = sd->fd; + + if (!flag) + { + int i; + ARR_FIND(0, MAX_MAIL_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if( i < MAX_MAIL_INBOX ) + { + memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); + sd->mail.inbox.amount--; + } + } + + WFIFOHEAD(fd, packet_len(0x257)); + WFIFOW(fd,0) = 0x257; + WFIFOL(fd,2) = mail_id; + WFIFOW(fd,6) = flag; + WFIFOSET(fd, packet_len(0x257)); + + if( !flag && sd->mail.inbox.satured ) + intif_Mail_requestinbox(sd->status.char_id, 1); // Reload the Mail Inbox +} + +void clif_parse_Mail_delete(int fd, struct map_session_data *sd) +{ + int i, mail_id = RFIFOL(fd,2); + nullpo_retv(sd); + + ARR_FIND(0, MAX_MAIL_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if (i < MAX_MAIL_INBOX) + { + struct mail_message *msg = &sd->mail.inbox.msg[i]; + + if( (msg->item.nameid > 0 && msg->item.amount > 0) || msg->zeny > 0 ) + { + clif_Mail_delete(sd, mail_id, 1); + return; + } + + intif_Mail_delete(sd->status.char_id, mail_id); + } +} +/*------------------------------------------ + * You have Mail Message + *------------------------------------------*/ +void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title) +{ + WFIFOHEAD(fd,packet_len(0x24a)); + WFIFOW(fd,0) = 0x24a; + WFIFOL(fd,2) = mail_id; + memcpy(WFIFOP(fd,6), sender, NAME_LENGTH); + memcpy(WFIFOP(fd,30), title, MAIL_TITLE_LENGTH); + WFIFOSET(fd,packet_len(0x24a)); +} + +/*------------------------------------------ + * Return Mail Message + *------------------------------------------*/ +void clif_parse_Mail_return(int fd, struct map_session_data *sd) +{ + int i, mail_id = RFIFOL(fd,2); + nullpo_retv(sd); + + ARR_FIND(0, MAX_MAIL_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if (i < MAX_MAIL_INBOX) + intif_Mail_return(sd->status.char_id, mail_id); +} + +void clif_Mail_return(struct map_session_data *sd, int mail_id, int new_mail) +{ + int fd = sd->fd; + + if (new_mail > 0) + { + int i; + ARR_FIND(0, MAX_MAIL_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if (i < MAX_MAIL_INBOX) + { + struct map_session_data *rd = map_charid2sd(sd->mail.inbox.msg[i].send_id); + if (rd) + { + char title[MAIL_TITLE_LENGTH]; + snprintf(title, MAIL_TITLE_LENGTH, "RE:%s", sd->mail.inbox.msg[i].title); + + rd->mail.inbox.changed = 1; + clif_Mail_new(rd->fd, new_mail, sd->status.name, title); + } + + memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); + sd->mail.inbox.amount--; + } + } + + WFIFOHEAD(fd,packet_len(0x274)); + WFIFOW(fd,0) = 0x274; + WFIFOL(fd,2) = mail_id; + WFIFOW(fd,6) = (new_mail > 0)?0:1; + WFIFOSET(fd,packet_len(0x274)); +} + +/*------------------------------------------ + * Set Attachment + *------------------------------------------*/ +void clif_parse_Mail_setattach(int fd, struct map_session_data *sd) +{ + int idx = RFIFOW(fd,2), amount = RFIFOL(fd,4); + char flag; + + nullpo_retv(sd); + if (idx < 0 || amount < 0) + return; + + flag = mail_setitem(sd, idx, amount); + if (flag > -1) + { + WFIFOHEAD(fd,packet_len(0x245)); + WFIFOW(fd,0) = 0x245; + WFIFOB(fd,2) = flag; + WFIFOSET(fd,packet_len(0x245)); + } +} + +/*------------------------------------------ + * Mail Window Operation + *------------------------------------------*/ +void clif_parse_Mail_winopen(int fd, struct map_session_data *sd) +{ + int flag = RFIFOW(fd,2); + nullpo_retv(sd); + + if (!flag || flag == 1) + mail_removeitem(sd, 0); + if (!flag || flag == 2) + mail_removezeny(sd, 0); +} + +/*------------------------------------------ + * Send Mail + *------------------------------------------*/ +void clif_Mail_send(int fd, unsigned char flag) +{ + WFIFOHEAD(fd,packet_len(0x249)); + WFIFOW(fd,0) = 0x249; + WFIFOB(fd,2) = flag; + WFIFOSET(fd,packet_len(0x249)); +} + +void clif_parse_Mail_send(int fd, struct map_session_data *sd) +{ + struct map_session_data *rd; + struct mail_message *msg; + int body_len; + nullpo_retv(sd); + + if( RFIFOW(fd,2) < 69 ) { + ShowWarning("Invalid Msg Len from account %d.\n", sd->status.account_id); + return; + } + + if( DIFF_TICK(sd->cansendmail_tick, gettick()) > 0 ) + { + clif_displaymessage(sd->fd,"Cannot send mails too fast!!."); + clif_Mail_send(fd, 1); + return; + } + + body_len = RFIFOB(fd,68); + rd = map_nick2sd_nocase(RFIFOP(fd,4)); + + if (rd && rd == sd) { + clif_Mail_send(fd, 1); + mail_removeitem(sd,0); + mail_removezeny(sd,0); + return; + } + + if (body_len > MAIL_BODY_LENGTH) + body_len = MAIL_BODY_LENGTH; + + msg = (struct mail_message*)aCalloc(sizeof(struct mail_message), 1); + + if (mail_getattach(sd, msg)) + { + msg->send_id = sd->status.char_id; + safestrncpy(msg->send_name, sd->status.name, NAME_LENGTH); + + if (rd) { + msg->dest_id = rd->status.char_id; + safestrncpy(msg->dest_name, rd->status.name, NAME_LENGTH); + } else { + msg->dest_id = 0; + safestrncpy(msg->dest_name, RFIFOP(fd,4), NAME_LENGTH); + } + + memcpy(msg->title, RFIFOP(fd,28), MAIL_TITLE_LENGTH); + + if (body_len) + memcpy(msg->body, RFIFOP(fd,69), body_len); + else + memset(msg->body, 0x00, MAIL_BODY_LENGTH); + + msg->timestamp = (int)mail_calctimes(); + intif_Mail_send(sd->status.account_id, msg); + + sd->cansendmail_tick = gettick() + 1000; // 5 Seconds flood Protection + } + else + { + mail_removeitem(sd,0); + mail_removezeny(sd,0); + clif_Mail_send(sd->fd, 1); // Fail + } + + aFree(msg); +} + +#endif + /*========================================== * パケットデバッグ *------------------------------------------*/ @@ -11551,10 +11955,10 @@ static int packetdb_readdb(void) //#0x0240 -1, -1, -1, -1, -1, 3, 4, 8, -1, 3, 70, 4, 8, 12, 4, 10, 3, 32, -1, 3, 3, 5, 5, 8, 2, 3, -1, -1, 4, -1, 4, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //#0x0280 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 0, 0, 0, 0, 0, 0, @@ -11705,6 +12109,17 @@ static int packetdb_readdb(void) {clif_parse_StoragePassword,"storagepassword"}, {clif_parse_Hotkey,"hotkey"}, {clif_parse_AutoRevive,"autorevive"}, +#ifndef TXT_ONLY + // MAIL SYSTEM + {clif_parse_Mail_refreshinbox,"mailrefresh"}, + {clif_parse_Mail_read,"mailread"}, + {clif_parse_Mail_getattach,"mailgetattach"}, + {clif_parse_Mail_delete,"maildelete"}, + {clif_parse_Mail_return,"mailreturn"}, + {clif_parse_Mail_setattach,"mailsetattach"}, + {clif_parse_Mail_winopen,"mailwinopen"}, + {clif_parse_Mail_send,"mailsend"}, +#endif {NULL,NULL} }; |