summaryrefslogtreecommitdiff
path: root/src/char
diff options
context:
space:
mode:
Diffstat (limited to 'src/char')
-rw-r--r--src/char/HPMchar.c1
-rw-r--r--src/char/Makefile.in4
-rw-r--r--src/char/char.c81
-rw-r--r--src/char/char.h2
-rw-r--r--src/char/int_auction.c2
-rw-r--r--src/char/int_guild.c2
-rw-r--r--src/char/int_party.c2
-rw-r--r--src/char/int_rodex.c536
-rw-r--r--src/char/int_rodex.h47
-rw-r--r--src/char/inter.c6
-rw-r--r--src/char/mapif.c21
-rw-r--r--src/char/mapif.h9
12 files changed, 675 insertions, 38 deletions
diff --git a/src/char/HPMchar.c b/src/char/HPMchar.c
index e0f81c61f..3a74f443d 100644
--- a/src/char/HPMchar.c
+++ b/src/char/HPMchar.c
@@ -36,6 +36,7 @@
#include "char/int_party.h"
#include "char/int_pet.h"
#include "char/int_quest.h"
+#include "char/int_rodex.h"
#include "char/int_storage.h"
#include "char/loginif.h"
#include "char/mapif.h"
diff --git a/src/char/Makefile.in b/src/char/Makefile.in
index 7806ce2bb..1a7d067a4 100644
--- a/src/char/Makefile.in
+++ b/src/char/Makefile.in
@@ -42,11 +42,11 @@ MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
CHAR_C = char.c HPMchar.c loginif.c mapif.c geoip.c inter.c int_auction.c int_elemental.c int_guild.c \
int_homun.c int_mail.c int_mercenary.c int_party.c int_pet.c \
- int_quest.c int_storage.c pincode.c
+ int_quest.c int_rodex.c int_storage.c pincode.c
CHAR_OBJ = $(addprefix obj_sql/, $(patsubst %.c,%.o,$(CHAR_C)))
CHAR_H = char.h HPMchar.h loginif.h mapif.h geoip.h inter.h int_auction.h int_elemental.h int_guild.h \
int_homun.h int_mail.h int_mercenary.h int_party.h int_pet.h \
- int_quest.h int_storage.h pincode.h
+ int_quest.h int_rodex.h int_storage.h pincode.h
CHAR_PH =
HAVE_MYSQL=@HAVE_MYSQL@
diff --git a/src/char/char.c b/src/char/char.c
index f66108c00..78b2d19fa 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -34,6 +34,7 @@
#include "char/int_party.h"
#include "char/int_pet.h"
#include "char/int_quest.h"
+#include "char/int_rodex.h"
#include "char/int_storage.h"
#include "char/inter.h"
#include "char/loginif.h"
@@ -97,6 +98,8 @@ char auction_db[256] = "auction"; // Auctions System
char friend_db[256] = "friends";
char hotkey_db[256] = "hotkey";
char quest_db[256] = "quest";
+char rodex_db[256] = "rodex_mail";
+char rodex_item_db[256] = "rodex_items";
char homunculus_db[256] = "homunculus";
char skill_homunculus_db[256] = "skill_homunculus";
char mercenary_db[256] = "mercenary";
@@ -457,10 +460,10 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
(p->int_ != cp->int_) || (p->dex != cp->dex) || (p->luk != cp->luk) ||
(p->option != cp->option) ||
(p->party_id != cp->party_id) || (p->guild_id != cp->guild_id) ||
- (p->pet_id != cp->pet_id) || (p->weapon != cp->weapon) || (p->hom_id != cp->hom_id) ||
- (p->ele_id != cp->ele_id) || (p->shield != cp->shield) || (p->head_top != cp->head_top) ||
- (p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date) ||
- (p->rename != cp->rename) || (p->slotchange != cp->slotchange) || (p->robe != cp->robe) ||
+ (p->pet_id != cp->pet_id) || (p->look.weapon != cp->look.weapon) || (p->hom_id != cp->hom_id) ||
+ (p->ele_id != cp->ele_id) || (p->look.shield != cp->look.shield) || (p->look.head_top != cp->look.head_top) ||
+ (p->look.head_mid != cp->look.head_mid) || (p->look.head_bottom != cp->look.head_bottom) || (p->delete_date != cp->delete_date) ||
+ (p->rename != cp->rename) || (p->slotchange != cp->slotchange) || (p->look.robe != cp->look.robe) ||
(p->show_equip != cp->show_equip) || (p->allow_party != cp->allow_party) || (p->font != cp->font) ||
(p->uniqueitem_counter != cp->uniqueitem_counter) || (p->hotkey_rowshift != cp->hotkey_rowshift)
) {
@@ -473,7 +476,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
opt |= OPT_SHOW_EQUIP;
if( SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d',"
- "`base_exp`='%u', `job_exp`='%u', `zeny`='%d',"
+ "`base_exp`='%"PRIu64"', `job_exp`='%"PRIu64"', `zeny`='%d',"
"`max_hp`='%d',`hp`='%d',`max_sp`='%d',`sp`='%d',`status_point`='%d',`skill_point`='%d',"
"`str`='%d',`agi`='%d',`vit`='%d',`int`='%d',`dex`='%d',`luk`='%d',"
"`option`='%u',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d',`elemental_id`='%d',"
@@ -487,11 +490,11 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
p->max_hp, p->hp, p->max_sp, p->sp, p->status_point, p->skill_point,
p->str, p->agi, p->vit, p->int_, p->dex, p->luk,
p->option, p->party_id, p->guild_id, p->pet_id, p->hom_id, p->ele_id,
- p->weapon, p->shield, p->head_top, p->head_mid, p->head_bottom,
+ p->look.weapon, p->look.shield, p->look.head_top, p->look.head_mid, p->look.head_bottom,
mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y,
mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename,
(unsigned long)p->delete_date, // FIXME: platform-dependent size
- p->robe,p->slotchange,opt,p->font,p->uniqueitem_counter,
+ p->look.robe,p->slotchange,opt,p->font,p->uniqueitem_counter,
p->hotkey_rowshift,
p->account_id, p->char_id) )
{
@@ -924,7 +927,7 @@ int char_memitemdata_to_sql(const struct item *p_items, int guid, enum inventory
if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)))
Sql_ShowDebug(inter->sql_handle);
}
-
+
aFree(deletes);
}
@@ -1069,8 +1072,8 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_SHORT, &p.class, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_INT, &p.base_level, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_INT, &p.job_level, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_UINT, &p.base_exp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &p.job_exp, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_UINT64, &p.base_exp, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT64, &p.job_exp, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_INT, &p.zeny, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_SHORT, &p.str, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_SHORT, &p.agi, 0, NULL, NULL)
@@ -1091,15 +1094,15 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
|| 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.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, 28, SQLDT_SHORT, &p.look.weapon, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 29, SQLDT_SHORT, &p.look.shield, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 30, SQLDT_SHORT, &p.look.head_top, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 31, SQLDT_SHORT, &p.look.head_mid, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 32, SQLDT_SHORT, &p.look.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, 36, SQLDT_SHORT, &p.look.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)
@@ -1178,8 +1181,8 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_SHORT, &p->class, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_INT, &p->base_level, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_INT, &p->job_level, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &p->base_exp, 0, NULL, NULL)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_UINT, &p->job_exp, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_UINT64, &p->base_exp, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_UINT64, &p->job_exp, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_INT, &p->zeny, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_SHORT, &p->str, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_SHORT, &p->agi, 0, NULL, NULL)
@@ -1205,11 +1208,11 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
|| 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->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, 34, SQLDT_SHORT, &p->look.weapon, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 35, SQLDT_SHORT, &p->look.shield, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 36, SQLDT_SHORT, &p->look.head_top, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 37, SQLDT_SHORT, &p->look.head_mid, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 38, SQLDT_SHORT, &p->look.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)
@@ -1223,7 +1226,7 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
|| 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, 52, SQLDT_SHORT, &p->look.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)
@@ -1906,10 +1909,23 @@ int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) {
return 0;
buf = WBUFP(buffer,0);
+
WBUFL(buf,0) = p->char_id;
- WBUFL(buf,4) = min(p->base_exp, INT32_MAX);
+#if PACKETVER >= 20170830
+ WBUFQ(buf,4) = min(p->base_exp, INT64_MAX);
+ offset += 4;
+ buf = WBUFP(buffer, offset);
+#else
+ WBUFL(buf,4) = min((uint32)(p->base_exp), INT32_MAX);
+#endif
WBUFL(buf,8) = p->zeny;
- WBUFL(buf,12) = min(p->job_exp, INT32_MAX);
+#if PACKETVER >= 20170830
+ WBUFQ(buf,12) = min(p->job_exp, INT64_MAX);
+ offset += 4;
+ buf = WBUFP(buffer, offset);
+#else
+ WBUFL(buf,12) = min((uint32)(p->job_exp), INT32_MAX);
+#endif
WBUFL(buf,16) = p->job_level;
WBUFL(buf,20) = 0; // probably opt1
WBUFL(buf,24) = 0; // probably opt2
@@ -1939,14 +1955,14 @@ int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) {
//When the weapon is sent and your option is riding, the client crashes on login!?
// FIXME[Haru]: is OPTION_HANBOK intended to be part of this list? And if it is, should the list also include other OPTION_ costumes?
- WBUFW(buf,56) = (p->option&(OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR|OPTION_HANBOK)) ? 0 : p->weapon;
+ WBUFW(buf,56) = (p->option&(OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR|OPTION_HANBOK)) ? 0 : p->look.weapon;
WBUFW(buf,58) = p->base_level;
WBUFW(buf,60) = min(p->skill_point, INT16_MAX);
- WBUFW(buf,62) = p->head_bottom;
- WBUFW(buf,64) = p->shield;
- WBUFW(buf,66) = p->head_top;
- WBUFW(buf,68) = p->head_mid;
+ WBUFW(buf,62) = p->look.head_bottom;
+ WBUFW(buf,64) = p->look.shield;
+ WBUFW(buf,66) = p->look.head_top;
+ WBUFW(buf,68) = p->look.head_mid;
WBUFW(buf,70) = p->hair_color;
WBUFW(buf,72) = p->clothes_color;
memcpy(WBUFP(buf,74), p->name, NAME_LENGTH);
@@ -1970,7 +1986,7 @@ int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) {
offset += 4;
#endif
#if PACKETVER >= 20110111
- WBUFL(buf,128) = p->robe;
+ WBUFL(buf,128) = p->look.robe;
offset += 4;
#endif
#if PACKETVER != 20111116 //2011-11-16 wants 136, ask gravity.
@@ -6412,6 +6428,7 @@ void char_load_defaults(void)
inter_pet_defaults();
inter_quest_defaults();
inter_storage_defaults();
+ inter_rodex_defaults();
inter_defaults();
geoip_defaults();
}
diff --git a/src/char/char.h b/src/char/char.h
index 6b081e536..3689690c7 100644
--- a/src/char/char.h
+++ b/src/char/char.h
@@ -328,6 +328,8 @@ extern char pet_db[256];
extern char mail_db[256];
extern char auction_db[256];
extern char quest_db[256];
+extern char rodex_db[256];
+extern char rodex_item_db[256];
extern char homunculus_db[256];
extern char skill_homunculus_db[256];
extern char mercenary_db[256];
diff --git a/src/char/int_auction.c b/src/char/int_auction.c
index 2dd65f213..05914c3a0 100644
--- a/src/char/int_auction.c
+++ b/src/char/int_auction.c
@@ -113,7 +113,7 @@ unsigned int inter_auction_create(struct auction_data *auction)
StrBuf->Printf(&buf, ",'%d'", auction->item.card[j]);
for (j = 0; j < MAX_ITEM_OPTIONS; j++)
StrBuf->Printf(&buf, ",'%d','%d'", auction->item.option[j].index, auction->item.option[j].value);
-
+
StrBuf->AppendStr(&buf, ")");
stmt = SQL->StmtMalloc(inter->sql_handle);
diff --git a/src/char/int_guild.c b/src/char/int_guild.c
index b4b4bdde4..0102f11a0 100644
--- a/src/char/int_guild.c
+++ b/src/char/int_guild.c
@@ -138,7 +138,7 @@ int inter_guild_tosql(struct guild *g,int flag)
if (g->guild_id<=0 && g->guild_id != -1) return 0;
#ifdef NOISY
- ShowInfo("Save guild request ("CL_BOLD"%d"CL_RESET" - flag 0x%x).",g->guild_id, flag);
+ ShowInfo("Save guild request ("CL_BOLD"%d"CL_RESET" - flag 0x%x).\n",g->guild_id, flag);
#endif
SQL->EscapeStringLen(inter->sql_handle, esc_name, g->name, strnlen(g->name, NAME_LENGTH));
diff --git a/src/char/int_party.c b/src/char/int_party.c
index 4b6800699..764387981 100644
--- a/src/char/int_party.c
+++ b/src/char/int_party.c
@@ -633,7 +633,7 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
return 0; //Member not found?
mapif->party_withdraw(party_id, account_id, char_id);
-
+
j = p->party.member[i].lv;
if (p->party.member[i].online > 0)
p->party.count--;
diff --git a/src/char/int_rodex.c b/src/char/int_rodex.c
new file mode 100644
index 000000000..c45c88eb0
--- /dev/null
+++ b/src/char/int_rodex.c
@@ -0,0 +1,536 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2017 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/>.
+ */
+#define HERCULES_CORE
+
+#include "int_rodex.h"
+
+#include "char/char.h"
+#include "char/inter.h"
+#include "char/mapif.h"
+#include "common/db.h"
+#include "common/memmgr.h"
+#include "common/mmo.h"
+#include "common/nullpo.h"
+#include "common/showmsg.h"
+#include "common/socket.h"
+#include "common/sql.h"
+#include "common/strlib.h"
+#include "common/timer.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+struct inter_rodex_interface inter_rodex_s;
+struct inter_rodex_interface *inter_rodex;
+
+// Loads new mails of this char_id/account_id
+static int inter_rodex_fromsql(int char_id, int account_id, int8 opentype, int64 mail_id, struct rodex_maillist *mails)
+{
+ int i, count = 0;
+ struct rodex_message msg = { 0 };
+ struct SqlStmt *stmt;
+ struct SqlStmt *stmt_items;
+
+ nullpo_retr(-1, mails);
+
+ stmt = SQL->StmtMalloc(inter->sql_handle);
+
+ switch (opentype) {
+ case RODEX_OPENTYPE_MAIL:
+ if (SQL_ERROR == SQL->StmtPrepare(stmt,
+ "SELECT `mail_id`, `sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`,"
+ "`title`, `body`, `zeny`, `type`, `is_read`, `send_date`, `expire_date`, `weight`"
+ "FROM `%s` WHERE `expire_date` > '%d' AND `receiver_id` = '%d' AND `mail_id` > '%"PRId64"'"
+ "ORDER BY `mail_id` ASC", rodex_db, (int)time(NULL), char_id, mail_id)
+ ) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return -1;
+ }
+ break;
+
+ case RODEX_OPENTYPE_ACCOUNT:
+ if (SQL_ERROR == SQL->StmtPrepare(stmt,
+ "SELECT `mail_id`, `sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`,"
+ "`title`, `body`, `zeny`, `type`, `is_read`, `send_date`, `expire_date`, `weight`"
+ "FROM `%s` WHERE "
+ "`expire_date` > '%d' AND `receiver_accountid` = '%d' AND `mail_id` > '%"PRId64"'"
+ "ORDER BY `mail_id` ASC", rodex_db, (int)time(NULL), account_id, mail_id)
+ ) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return -1;
+ }
+ break;
+
+ case RODEX_OPENTYPE_RETURN:
+ if (SQL_ERROR == SQL->StmtPrepare(stmt,
+ "SELECT `mail_id`, `sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`,"
+ "`title`, `body`, `zeny`, `type`, `is_read`, `send_date`, `expire_date`, `weight`"
+ "FROM `%s` WHERE (`sender_id` = '%d' AND `expire_date` <= '%d' AND `send_date` + '%d' > '%d' AND `mail_id` > '%"PRId64"')"
+ "ORDER BY `mail_id` ASC", rodex_db, char_id, (int)time(NULL), 2 * RODEX_EXPIRE, (int)time(NULL), mail_id)
+ ) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return -1;
+ }
+ break;
+ }
+
+ if (SQL_ERROR == SQL->StmtExecute(stmt)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT64, &msg.id, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_STRING, &msg.sender_name, sizeof(msg.sender_name), NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_INT, &msg.sender_id, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_STRING, &msg.receiver_name, sizeof(msg.receiver_name), NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_INT, &msg.receiver_id, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_INT, &msg.receiver_accountid, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_STRING, &msg.title, sizeof(msg.title), NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_STRING, &msg.body, sizeof(msg.body), NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_INT, &msg.zeny, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_UINT8, &msg.type, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_INT8, &msg.is_read, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_INT, &msg.send_date, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 12, SQLDT_INT, &msg.expire_date, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 13, SQLDT_INT, &msg.weight, 0, NULL, NULL)
+ ) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return -1;
+ }
+
+ stmt_items = SQL->StmtMalloc(inter->sql_handle);
+ if (stmt_items == NULL) {
+ SQL->StmtFreeResult(stmt);
+ SQL->StmtFree(stmt);
+ return -1;
+ }
+
+ // Read mails
+ while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) {
+ struct item it = { 0 };
+
+ if (msg.type & MAIL_TYPE_ITEM) {
+ if (SQL_ERROR == SQL->StmtPrepare(stmt_items, "SELECT `nameid`, `amount`, `equip`, `identify`,"
+ "`refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `opt_idx0`, `opt_val0`,"
+ "`opt_idx1`, `opt_val1`, `opt_idx2`, `opt_val2`, `opt_idx3`, `opt_val3`, `opt_idx4`, `opt_val4`,"
+ "`expire_time`, `bound`, `unique_id`"
+ "FROM `%s` WHERE mail_id = '%"PRId64"' ORDER BY `mail_id` ASC", rodex_item_db, msg.id)
+ || SQL_ERROR == SQL->StmtExecute(stmt_items)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 0, SQLDT_INT, &it.nameid, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 1, SQLDT_INT, &it.amount, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 2, SQLDT_UINT, &it.equip, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 3, SQLDT_INT8, &it.identify, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 4, SQLDT_INT8, &it.refine, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 5, SQLDT_INT8, &it.attribute, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 6, SQLDT_INT16, &it.card[0], 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 7, SQLDT_INT16, &it.card[1], 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 8, SQLDT_INT16, &it.card[2], 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 9, SQLDT_INT16, &it.card[3], 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 10, SQLDT_INT16, &it.option[0].index, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 11, SQLDT_INT16, &it.option[0].value, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 12, SQLDT_INT16, &it.option[1].index, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 13, SQLDT_INT16, &it.option[1].value, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 14, SQLDT_INT16, &it.option[2].index, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 15, SQLDT_INT16, &it.option[2].value, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 16, SQLDT_INT16, &it.option[3].index, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 17, SQLDT_INT16, &it.option[3].value, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 18, SQLDT_INT16, &it.option[4].index, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 19, SQLDT_INT16, &it.option[4].value, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 20, SQLDT_INT, &it.expire_time, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 21, SQLDT_UINT8, &it.bound, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 22, SQLDT_UINT64, &it.unique_id, 0, NULL, NULL)) {
+ SqlStmt_ShowDebug(stmt_items);
+ }
+
+ for (i = 0; i < RODEX_MAX_ITEM && SQL_SUCCESS == SQL->StmtNextRow(stmt_items); ++i) {
+ msg.items[i].item = it;
+ msg.items_count++;
+ }
+ }
+
+ if (msg.items_count == 0) {
+ msg.type &= ~MAIL_TYPE_ITEM;
+ }
+
+ if (msg.zeny == 0) {
+ msg.type &= ~MAIL_TYPE_ZENY;
+ }
+
+ msg.opentype = opentype;
+#if PACKETVER < 20160601
+ // NPC Message Type isn't supported in old clients
+ msg.type &= ~MAIL_TYPE_NPC;
+#endif
+
+ ++count;
+ VECTOR_ENSURE(*mails, 1, 1);
+ VECTOR_PUSH(*mails, msg);
+ memset(&msg, 0, sizeof(struct rodex_message));
+ }
+
+ SQL->StmtFreeResult(stmt);
+ SQL->StmtFreeResult(stmt_items);
+
+ SQL->StmtFree(stmt);
+ SQL->StmtFree(stmt_items);
+
+ ShowInfo("rodex load complete from DB - id: %d (total: %d)\n", char_id, count);
+ return count;
+}
+
+// Checks if user has non-read mails
+static bool inter_rodex_hasnew(int char_id, int account_id)
+{
+ int count = 0;
+ char *data;
+
+ if (SQL_ERROR == SQL->Query(inter->sql_handle,
+ "SELECT count(*) FROM `%s` WHERE ("
+ "(`expire_date` > '%d' AND (`receiver_id` = '%d' OR `receiver_accountid` = '%d')) OR"
+ "(`sender_id` = '%d' AND `expire_date` <= '%d' AND `send_date` + '%d' > '%d')"
+ ") AND (`is_read` = 0 OR (`type` > 0 AND `type` != 8))",
+ rodex_db, (int)time(NULL), char_id, account_id,
+ char_id, (int)time(NULL), 2 * RODEX_EXPIRE, (int)time(NULL))
+ ) {
+ Sql_ShowDebug(inter->sql_handle);
+ return -1;
+ }
+
+ if (SQL_SUCCESS != SQL->NextRow(inter->sql_handle))
+ return false;
+
+ SQL->GetData(inter->sql_handle, 0, &data, NULL);
+ count = atoi(data);
+ SQL->FreeResult(inter->sql_handle);
+
+ return count > 0;
+}
+
+/// Checks player name and retrieves some data
+static bool inter_rodex_checkname(const char *name, int *target_char_id, short *target_class, int *target_level)
+{
+ char esc_name[NAME_LENGTH * 2 + 1];
+ bool found = false;
+
+ nullpo_retr(false, name);
+ nullpo_retr(false, target_char_id);
+ nullpo_retr(false, target_class);
+ nullpo_retr(false, target_level);
+
+ // Try to find the Dest Char by Name
+ SQL->EscapeStringLen(inter->sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `char_id`, `class`, `base_level` FROM `%s` WHERE `name` = '%s'", char_db, esc_name)) {
+ Sql_ShowDebug(inter->sql_handle);
+ } else {
+ if (SQL_SUCCESS == SQL->NextRow(inter->sql_handle)) {
+ char *data;
+ SQL->GetData(inter->sql_handle, 0, &data, NULL); *target_char_id = atoi(data);
+ SQL->GetData(inter->sql_handle, 1, &data, NULL); *target_class = (short)atoi(data);
+ SQL->GetData(inter->sql_handle, 2, &data, NULL); *target_level = atoi(data);
+ found = true;
+ }
+ }
+ SQL->FreeResult(inter->sql_handle);
+
+ return found;
+}
+
+/// Stores a single message in the database.
+/// Returns the message's ID if successful (or 0 if it fails).
+int64 inter_rodex_savemessage(struct rodex_message* msg)
+{
+ char sender_name[NAME_LENGTH * 2 + 1];
+ char receiver_name[NAME_LENGTH * 2 + 1];
+ char body[RODEX_BODY_LENGTH * 2 + 1];
+ char title[RODEX_TITLE_LENGTH * 2 + 1];
+ int i;
+
+ nullpo_retr(false, msg);
+
+ SQL->EscapeStringLen(inter->sql_handle, sender_name, msg->sender_name, strnlen(msg->sender_name, NAME_LENGTH));
+ SQL->EscapeStringLen(inter->sql_handle, receiver_name, msg->receiver_name, strnlen(msg->receiver_name, NAME_LENGTH));
+ SQL->EscapeStringLen(inter->sql_handle, body, msg->body, strnlen(msg->body, RODEX_BODY_LENGTH));
+ SQL->EscapeStringLen(inter->sql_handle, title, msg->title, strnlen(msg->title, RODEX_TITLE_LENGTH));
+
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "INSERT INTO `%s` (`sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`, `title`, `body`,"
+ "`zeny`, `type`, `is_read`, `send_date`, `expire_date`, `weight`) VALUES "
+ "('%s', '%d', '%s', '%d', '%d', '%s', '%s', '%"PRId64"', '%d', '%d', '%d', '%d', '%d')",
+ rodex_db, sender_name, msg->sender_id, receiver_name, msg->receiver_id, msg->receiver_accountid,
+ title, body, msg->zeny, msg->type, msg->is_read == true ? 1 : 0, msg->send_date, msg->expire_date, msg->weight)) {
+ Sql_ShowDebug(inter->sql_handle);
+ return 0;
+ }
+
+ msg->id = (int64)SQL->LastInsertId(inter->sql_handle);
+
+ for (i = 0; i < RODEX_MAX_ITEM; ++i) {
+ // Should we use statement here? [KIRIEZ]
+ struct item *it = &msg->items[i].item;
+ if (it->nameid == 0)
+ continue;
+
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "INSERT INTO `%s` (`mail_id`, `nameid`, `amount`, `equip`, `identify`,"
+ "`refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `opt_idx0`, `opt_val0`, `opt_idx1`, `opt_val1`, `opt_idx2`,"
+ "`opt_val2`, `opt_idx3`, `opt_val3`, `opt_idx4`, `opt_val4`,`expire_time`, `bound`, `unique_id`) VALUES "
+ "('%"PRId64"', '%d', '%d', '%u', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%u', '%"PRIu64"')",
+ rodex_item_db, msg->id, it->nameid, it->amount, it->equip, it->identify, it->refine, it->attribute, it->card[0], it->card[1], it->card[2], it->card[3],
+ it->option[0].index, it->option[0].value, it->option[1].index, it->option[1].value, it->option[2].index, it->option[2].value, it->option[3].index,
+ it->option[3].value, it->option[4].index, it->option[4].value, it->expire_time, it->bound, it->unique_id)
+ ) {
+ Sql_ShowDebug(inter->sql_handle);
+ continue;
+ }
+ }
+
+ return msg->id;
+}
+
+/*==========================================
+ * Inbox Request
+ *------------------------------------------*/
+void mapif_rodex_sendinbox(int fd, int char_id, int8 opentype, int8 flag, int count, struct rodex_maillist *mails)
+{
+ int per_packet = (UINT16_MAX - 15) / sizeof(struct rodex_message);
+ int sent = 0;
+ nullpo_retv(mails);
+ Assert_retv(char_id > 0);
+ Assert_retv(count >= 0);
+
+ do {
+ int i = 15, j, size, limit;
+ bool is_last = true;
+
+ if (count <= per_packet) {
+ size = count * sizeof(struct rodex_message) + 15;
+ limit = count;
+ is_last = true;
+ } else {
+ int to_send = count - sent;
+ limit = min(to_send, per_packet);
+ if (limit != to_send) {
+ is_last = false;
+ }
+ size = limit * sizeof(struct rodex_message) + 15;
+ }
+
+ WFIFOHEAD(fd, size);
+ WFIFOW(fd, 0) = 0x3895;
+ WFIFOW(fd, 2) = size;
+ WFIFOL(fd, 4) = char_id;
+ WFIFOB(fd, 8) = opentype;
+ WFIFOB(fd, 9) = flag;
+ WFIFOB(fd, 10) = is_last;
+ WFIFOL(fd, 11) = count;
+ for (j = 0; j < limit; ++j, ++sent, i += sizeof(struct rodex_message)) {
+ memcpy(WFIFOP(fd, i), &VECTOR_INDEX(*mails, sent), sizeof(struct rodex_message));
+ }
+ WFIFOSET(fd, size);
+ } while (sent < count);
+}
+
+void mapif_parse_rodex_requestinbox(int fd)
+{
+ int count;
+ int char_id = RFIFOL(fd,2);
+ int account_id = RFIFOL(fd, 6);
+ int8 flag = RFIFOB(fd, 10);
+ int8 opentype = RFIFOB(fd, 11);
+ int64 mail_id = RFIFOQ(fd, 12);
+ struct rodex_maillist mails = { 0 };
+
+ VECTOR_INIT(mails);
+ if (flag == 0)
+ count = inter_rodex->fromsql(char_id, account_id, opentype, 0, &mails);
+ else
+ count = inter_rodex->fromsql(char_id, account_id, opentype, mail_id, &mails);
+ mapif->rodex_sendinbox(fd, char_id, opentype, flag, count, &mails);
+ VECTOR_CLEAR(mails);
+}
+
+/*==========================================
+* Checks if there are new mails
+*------------------------------------------*/
+void mapif_rodex_sendhasnew(int fd, int char_id, bool has_new)
+{
+ Assert_retv(char_id > 0);
+
+ WFIFOHEAD(fd, 7);
+ WFIFOW(fd, 0) = 0x3896;
+ WFIFOL(fd, 2) = char_id;
+ WFIFOB(fd, 6) = has_new;
+ WFIFOSET(fd, 7);
+}
+
+void mapif_parse_rodex_checkhasnew(int fd)
+{
+ int char_id = RFIFOL(fd, 2);
+ int account_id = RFIFOL(fd, 6);
+ bool has_new;
+
+ Assert_retv(account_id >= START_ACCOUNT_NUM && account_id <= END_ACCOUNT_NUM);
+ Assert_retv(char_id >= START_CHAR_NUM);
+
+ has_new = inter_rodex->hasnew(char_id, account_id);
+ mapif->rodex_sendhasnew(fd, char_id, has_new);
+}
+
+/*==========================================
+ * Update/Delete mail
+ *------------------------------------------*/
+void mapif_parse_rodex_updatemail(int fd)
+{
+ int64 mail_id = RFIFOL(fd, 2);
+ int8 flag = RFIFOB(fd, 10);
+
+ Assert_retv(mail_id > 0);
+ Assert_retv(flag >= 0 && flag <= 3);
+
+ switch (flag) {
+ case 0: // Read
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `is_read` = 1 WHERE `mail_id` = '%"PRId64"'", rodex_db, mail_id))
+ Sql_ShowDebug(inter->sql_handle);
+ break;
+
+ case 1: // Get Zeny
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `zeny` = 0, `type` = `type` & (~2) WHERE `mail_id` = '%"PRId64"'", rodex_db, mail_id))
+ Sql_ShowDebug(inter->sql_handle);
+ break;
+
+ case 2: // Get Items
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `mail_id` = '%"PRId64"'", rodex_item_db, mail_id))
+ Sql_ShowDebug(inter->sql_handle);
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `zeny` = 0, `type` = `type` & (~4) WHERE `mail_id` = '%"PRId64"'", rodex_db, mail_id))
+ Sql_ShowDebug(inter->sql_handle);
+ break;
+
+ case 3: // Delete Mail
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `mail_id` = '%"PRId64"'", rodex_db, mail_id))
+ Sql_ShowDebug(inter->sql_handle);
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `mail_id` = '%"PRId64"'", rodex_item_db, mail_id))
+ Sql_ShowDebug(inter->sql_handle);
+ break;
+ }
+}
+
+/*==========================================
+ * Send Mail
+ *------------------------------------------*/
+void mapif_rodex_send(int fd, int sender_id, int receiver_id, int receiver_accountid, bool result)
+{
+ Assert_retv(sender_id >= 0);
+ Assert_retv(receiver_id + receiver_accountid > 0);
+
+ WFIFOHEAD(fd,15);
+ WFIFOW(fd,0) = 0x3897;
+ WFIFOL(fd,2) = sender_id;
+ WFIFOL(fd,6) = receiver_id;
+ WFIFOL(fd,10) = receiver_accountid;
+ WFIFOB(fd,14) = result;
+ WFIFOSET(fd,15);
+}
+
+void mapif_parse_rodex_send(int fd)
+{
+ struct rodex_message msg = { 0 };
+
+ if (RFIFOW(fd,2) != 4 + sizeof(struct rodex_message))
+ return;
+
+ memcpy(&msg, RFIFOP(fd,4), sizeof(struct rodex_message));
+ if (msg.receiver_id > 0 || msg.receiver_accountid > 0)
+ msg.id = inter_rodex->savemessage(&msg);
+
+ mapif->rodex_send(fd, msg.sender_id, msg.receiver_id, msg.receiver_accountid, msg.id > 0 ? true : false);
+}
+
+/*------------------------------------------
+ * Check Player
+ *------------------------------------------*/
+void mapif_rodex_checkname(int fd, int reqchar_id, int target_char_id, short target_class, int target_level, char *name)
+{
+ nullpo_retv(name);
+ Assert_retv(reqchar_id > 0);
+ Assert_retv(target_char_id >= 0);
+
+ WFIFOHEAD(fd, 16 + NAME_LENGTH);
+ WFIFOW(fd, 0) = 0x3898;
+ WFIFOL(fd, 2) = reqchar_id;
+ WFIFOL(fd, 6) = target_char_id;
+ WFIFOW(fd, 10) = target_class;
+ WFIFOL(fd, 12) = target_level;
+ safestrncpy(WFIFOP(fd, 16), name, NAME_LENGTH);
+ WFIFOSET(fd, 16 + NAME_LENGTH);
+}
+
+void mapif_parse_rodex_checkname(int fd)
+{
+ int reqchar_id = RFIFOL(fd, 2);
+ char name[NAME_LENGTH];
+ int target_char_id, target_level;
+ short target_class;
+
+ safestrncpy(name, RFIFOP(fd, 6), NAME_LENGTH);
+
+ if (inter_rodex->checkname(name, &target_char_id, &target_class, &target_level) == true)
+ mapif->rodex_checkname(fd, reqchar_id, target_char_id, target_class, target_level, name);
+ else
+ mapif->rodex_checkname(fd, reqchar_id, 0, 0, 0, name);
+}
+
+/*==========================================
+ * Packets From Map Server
+ *------------------------------------------*/
+int inter_rodex_parse_frommap(int fd)
+{
+ switch(RFIFOW(fd,0))
+ {
+ case 0x3095: mapif->parse_rodex_requestinbox(fd); break;
+ case 0x3096: mapif->parse_rodex_checkhasnew(fd); break;
+ case 0x3097: mapif->parse_rodex_updatemail(fd); break;
+ case 0x3098: mapif->parse_rodex_send(fd); break;
+ case 0x3099: mapif->parse_rodex_checkname(fd); break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+int inter_rodex_sql_init(void)
+{
+ return 1;
+}
+
+void inter_rodex_sql_final(void)
+{
+ return;
+}
+
+void inter_rodex_defaults(void)
+{
+ inter_rodex = &inter_rodex_s;
+
+ inter_rodex->savemessage = inter_rodex_savemessage;
+ inter_rodex->parse_frommap = inter_rodex_parse_frommap;
+ inter_rodex->sql_init = inter_rodex_sql_init;
+ inter_rodex->sql_final = inter_rodex_sql_final;
+ inter_rodex->fromsql = inter_rodex_fromsql;
+ inter_rodex->hasnew = inter_rodex_hasnew;
+ inter_rodex->checkname = inter_rodex_checkname;
+}
diff --git a/src/char/int_rodex.h b/src/char/int_rodex.h
new file mode 100644
index 000000000..801ebcb89
--- /dev/null
+++ b/src/char/int_rodex.h
@@ -0,0 +1,47 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2017 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/>.
+ */
+#ifndef CHAR_INT_RODEX_H
+#define CHAR_INT_RODEX_H
+
+#include "common/mmo.h"
+#include "common/db.h"
+
+struct item;
+
+/**
+ * inter_rodex interface
+ **/
+struct inter_rodex_interface {
+ int (*sql_init) (void);
+ void (*sql_final) (void);
+ int (*parse_frommap) (int fd);
+ int (*fromsql) (int char_id, int account_id, int8 opentype, int64 mail_id, struct rodex_maillist *mails);
+ bool (*hasnew) (int char_id, int account_id);
+ bool (*checkname) (const char *name, int *target_char_id, short *target_class, int *target_level);
+ int64 (*savemessage) (struct rodex_message* msg);
+};
+
+#ifdef HERCULES_CORE
+void inter_rodex_defaults(void);
+#endif // HERCULES_CORE
+
+HPShared struct inter_rodex_interface *inter_rodex;
+
+#endif /* CHAR_INT_RODEX_H */
diff --git a/src/char/inter.c b/src/char/inter.c
index cfbc0fd4d..557ee5313 100644
--- a/src/char/inter.c
+++ b/src/char/inter.c
@@ -33,6 +33,7 @@
#include "char/int_party.h"
#include "char/int_pet.h"
#include "char/int_quest.h"
+#include "char/int_rodex.h"
#include "char/int_storage.h"
#include "char/mapif.h"
#include "common/cbasetypes.h"
@@ -76,7 +77,7 @@ int inter_recv_packet_length[] = {
6,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3060- Quest system [Kevin] [Inkfish]
-1,10, 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, -1,10, 6,-1, // 3070- Mercenary packets [Zephyrus], Elemental packets [pakpil]
48,14,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3080-
- -1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator]
+ -1,10,-1, 6, 0, 20,10,11, -1,6 + NAME_LENGTH, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator], RoDEX packets
};
struct WisData {
@@ -974,6 +975,7 @@ int inter_init_sql(const char *file)
inter_elemental->sql_init();
inter_mail->sql_init();
inter_auction->sql_init();
+ inter_rodex->sql_init();
geoip->init();
inter->msg_config_read("conf/messages.conf", false);
@@ -994,6 +996,7 @@ void inter_final(void)
inter_elemental->sql_final();
inter_mail->sql_final();
inter_auction->sql_final();
+ inter_rodex->sql_final();
geoip->final(true);
inter->do_final_msg();
@@ -1416,6 +1419,7 @@ int inter_parse_frommap(int fd)
|| inter_mail->parse_frommap(fd)
|| inter_auction->parse_frommap(fd)
|| inter_quest->parse_frommap(fd)
+ || inter_rodex->parse_frommap(fd)
)
break;
else
diff --git a/src/char/mapif.c b/src/char/mapif.c
index 5fff96ba8..9fccd691b 100644
--- a/src/char/mapif.c
+++ b/src/char/mapif.c
@@ -26,6 +26,7 @@
#include "char/int_auction.h"
#include "char/int_guild.h"
#include "char/int_homun.h"
+#include "char/int_rodex.h"
#include "common/cbasetypes.h"
#include "common/mmo.h"
#include "common/random.h"
@@ -182,6 +183,16 @@ void mapif_quest_save_ack(int fd, int char_id, bool success);
int mapif_parse_quest_save(int fd);
void mapif_send_quests(int fd, int char_id, struct quest *tmp_questlog, int num_quests);
int mapif_parse_quest_load(int fd);
+/* RoDEX */
+int mapif_parse_rodex_requestinbox(int fd);
+void mapif_rodex_sendinbox(int fd, int char_id, int8 opentype, int8 flag, int count, struct rodex_maillist *mails);
+int mapif_parse_rodex_checkhasnew(int fd);
+void mapif_rodex_sendhasnew(int fd, int char_id, bool has_new);
+int mapif_parse_rodex_updatemail(int fd);
+int mapif_parse_rodex_send(int fd);
+void mapif_rodex_send(int fd, int sender_id, int receiver_id, int receiver_accountid, bool result);
+int mapif_parse_rodex_checkname(int fd);
+void mapif_rodex_checkname(int fd, int reqchar_id, int target_char_id, short target_class, int target_level, char *name);
int mapif_load_guild_storage(int fd,int account_id,int guild_id, char flag);
int mapif_save_guild_storage_ack(int fd, int account_id, int guild_id, int fail);
int mapif_parse_LoadGuildStorage(int fd);
@@ -363,6 +374,16 @@ void mapif_defaults(void) {
mapif->parse_quest_save = mapif_parse_quest_save;
mapif->send_quests = mapif_send_quests;
mapif->parse_quest_load = mapif_parse_quest_load;
+ /* RoDEX */
+ mapif->parse_rodex_requestinbox = mapif_parse_rodex_requestinbox;
+ mapif->rodex_sendinbox = mapif_rodex_sendinbox;
+ mapif->parse_rodex_checkhasnew = mapif_parse_rodex_checkhasnew;
+ mapif->rodex_sendhasnew = mapif_rodex_sendhasnew;
+ mapif->parse_rodex_updatemail = mapif_parse_rodex_updatemail;
+ mapif->parse_rodex_send = mapif_parse_rodex_send;
+ mapif->rodex_send = mapif_rodex_send;
+ mapif->parse_rodex_checkname = mapif_parse_rodex_checkname;
+ mapif->rodex_checkname = mapif_rodex_checkname;
mapif->load_guild_storage = mapif_load_guild_storage;
mapif->save_guild_storage_ack = mapif_save_guild_storage_ack;
mapif->parse_LoadGuildStorage = mapif_parse_LoadGuildStorage;
diff --git a/src/char/mapif.h b/src/char/mapif.h
index 07fbed6c6..a78940ba2 100644
--- a/src/char/mapif.h
+++ b/src/char/mapif.h
@@ -176,6 +176,15 @@ struct mapif_interface {
int (*parse_quest_save) (int fd);
void (*send_quests) (int fd, int char_id, struct quest *tmp_questlog, int num_quests);
int (*parse_quest_load) (int fd);
+ int(*parse_rodex_requestinbox) (int fd);
+ void(*rodex_sendinbox) (int fd, int char_id, int8 opentype, int8 flag, int count, struct rodex_maillist *mails);
+ int(*parse_rodex_checkhasnew) (int fd);
+ void(*rodex_sendhasnew) (int fd, int char_id, bool has_new);
+ int(*parse_rodex_updatemail) (int fd);
+ int(*parse_rodex_send) (int fd);
+ void(*rodex_send) (int fd, int sender_id, int receiver_id, int receiver_accountid, bool result);
+ int(*parse_rodex_checkname) (int fd);
+ void(*rodex_checkname) (int fd, int reqchar_id, int target_char_id, short target_class, int target_level, char *name);
int (*load_guild_storage) (int fd, int account_id, int guild_id, char flag);
int (*save_guild_storage_ack) (int fd, int account_id, int guild_id, int fail);
int (*parse_LoadGuildStorage) (int fd);