summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/char.c25
-rw-r--r--src/common/mmo.h5
-rw-r--r--src/map/battle.c10
-rw-r--r--src/map/battle.h1
-rw-r--r--src/map/clif.c84
-rw-r--r--src/map/clif.h22
-rw-r--r--src/map/log.c1
-rw-r--r--src/map/log.h1
-rw-r--r--src/map/packets.h15
-rw-r--r--src/map/packets_struct.h35
-rw-r--r--src/map/pc.c48
-rw-r--r--src/map/pc.h3
12 files changed, 249 insertions, 1 deletions
diff --git a/src/char/char.c b/src/char/char.c
index 7a948398c..5a51130de 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -70,6 +70,7 @@ char mercenary_owner_db[256] = "mercenary_owner";
char ragsrvinfo_db[256] = "ragsrvinfo";
char elemental_db[256] = "elemental";
char interreg_db[32] = "interreg";
+char account_data_db[256] = "account_data";
// show loading/saving messages
int save_log = 1;
@@ -497,6 +498,14 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
} else
strcat(save_status, " status");
}
+
+ if( p->bank_vault != cp->bank_vault ) {
+ if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`bank_vault`) VALUES ('%d','%d')",account_data_db,p->account_id,p->bank_vault) ) {
+ Sql_ShowDebug(sql_handle);
+ errors++;
+ } else
+ strcat(save_status, " bank");
+ }
//Values that will seldom change (to speed up saving)
if (
@@ -675,6 +684,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
strcat(save_status, " hotkeys");
}
#endif
+
StrBuf->Destroy(&buf);
if (save_status[0]!='\0' && save_log)
ShowInfo("Saved char %d - %s:%s.\n", char_id, p->name, save_status);
@@ -1085,6 +1095,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
int hotkey_num;
#endif
unsigned int opt;
+ int account_id;
memset(p, 0, sizeof(struct mmo_charstatus));
@@ -1174,6 +1185,9 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
SQL->StmtFree(stmt);
return 0;
}
+
+ account_id = p->account_id;
+
p->last_point.map = mapindex_name2id(last_map);
p->save_point.map = mapindex_name2id(save_map);
@@ -1338,6 +1352,15 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
mercenary_owner_fromsql(char_id, p);
strcat(t_msg, " mercenary");
+ //`account_data` (`account_id`,`bank_vault`)
+ if( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `bank_vault` FROM `%s` WHERE `account_id`=? LIMIT 1", account_data_db)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &account_id, 0)
+ || SQL_ERROR == SQL->StmtExecute(stmt)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &p->bank_vault, 0, NULL, NULL) )
+ SqlStmt_ShowDebug(stmt);
+
+ if( SQL_SUCCESS == SQL->StmtNextRow(stmt) )
+ strcat(t_msg, " bank");
if (save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfuly!
SQL->StmtFree(stmt);
@@ -4721,6 +4744,8 @@ void sql_config_read(const char* cfgName)
safestrncpy(elemental_db,w2,sizeof(elemental_db));
else if(!strcmpi(w1,"interreg_db"))
safestrncpy(interreg_db,w2,sizeof(interreg_db));
+ else if(!strcmpi(w1,"account_data_db"))
+ safestrncpy(account_data_db,w2,sizeof(account_data_db));
//support the import command, just like any other config
else if(!strcmpi(w1,"import"))
sql_config_read(w2);
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 205cf8425..ccba0fa7f 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -90,6 +90,10 @@
//Max amount of a single stacked item
#define MAX_AMOUNT 30000
#define MAX_ZENY 1000000000
+
+//Official Limit: 2.1b ( the var that stores the money doesn't go much higher than this by default )
+#define MAX_BANK_ZENY 2100000000
+
#define MAX_FAME 1000000000
#define MAX_CART 100
#define MAX_SKILL 1478
@@ -366,6 +370,7 @@ struct mmo_charstatus {
unsigned int base_exp,job_exp;
int zeny;
+ int bank_vault;
short class_;
unsigned int status_point,skill_point;
diff --git a/src/map/battle.c b/src/map/battle.c
index 928d14c22..a0e4e7ebc 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -6474,6 +6474,8 @@ static const struct _battle_data {
{ "client_accept_chatdori", &battle_config.client_accept_chatdori, 0, 0, INT_MAX, },
{ "snovice_call_type", &battle_config.snovice_call_type, 0, 0, 1, },
{ "guild_notice_changemap", &battle_config.guild_notice_changemap, 2, 0, 2, },
+ { "feature.banking", &battle_config.feature_banking, 1, 0, 1, },
+
};
#ifndef STATS_OPT_OUT
/**
@@ -6695,6 +6697,14 @@ void battle_adjust_conf(void) {
battle_config.feature_search_stores = 0;
}
#endif
+
+#if PACKETVER < 20130724
+ if( battle_config.feature_banking ) {
+ ShowWarning("conf/battle/feature.conf banking is enabled but it requires PACKETVER 2013-07-24 or newer, disabling...\n");
+ battle_config.feature_banking = 0;
+ }
+#endif
+
#ifndef CELL_NOSTACK
if (battle_config.cell_stack_limit != 1)
diff --git a/src/map/battle.h b/src/map/battle.h
index 6d5d5f186..f1fa6ddc1 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -461,6 +461,7 @@ struct Battle_Config {
int snovice_call_type;
int guild_notice_changemap;
+ int feature_banking;
} battle_config;
// Dammage delayed info
diff --git a/src/map/clif.c b/src/map/clif.c
index 8fd2a60c2..57830478d 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -61,7 +61,7 @@ struct clif_interface clif_s;
//Converts item type in case of pet eggs.
static inline int itemtype(int type) {
- switch( type ){
+ switch( type ) {
#if PACKETVER >= 20080827
case IT_WEAPON: return IT_ARMOR;
case IT_ARMOR:
@@ -17726,6 +17726,79 @@ void clif_cart_additem_ack(struct map_session_data *sd, int flag) {
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
+/* Bank System [Yommy/Hercules] */
+void clif_parse_BankDeposit(int fd, struct map_session_data* sd) {
+ struct packet_banking_deposit_req *p = P2PTR(fd);
+ int money;
+
+ if( !battle_config.feature_banking ) {
+ clif->colormes(fd,COLOR_RED,msg_txt(1483));
+ return;
+ }
+
+ money = (int)cap_value(p->Money,0,INT_MAX);
+
+ pc->bank_deposit(sd,money);
+}
+
+void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) {
+ struct packet_banking_withdraw_req *p = P2PTR(fd);
+ int money;
+
+ if( !battle_config.feature_banking ) {
+ clif->colormes(fd,COLOR_RED,msg_txt(1483));
+ return;
+ }
+
+ money = (int)cap_value(p->Money,0,INT_MAX);
+
+ pc->bank_withdraw(sd,money);
+}
+
+void clif_parse_BankCheck(int fd, struct map_session_data* sd) {
+ struct packet_banking_check p;
+
+ if( !battle_config.feature_banking ) {
+ clif->colormes(fd,COLOR_RED,msg_txt(1483));
+ return;
+ }
+
+ p.PacketType = banking_checkType;
+ p.Money = (int)sd->status.bank_vault;
+ p.Reason = (short)0;
+
+ clif->send(&p,sizeof(p), &sd->bl, SELF);
+}
+
+void clif_parse_BankOpen(int fd, struct map_session_data* sd) {
+ return;
+}
+
+void clif_parse_BankClose(int fd, struct map_session_data* sd) {
+ return;
+}
+
+void clif_bank_deposit(struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK reason) {
+ struct packet_banking_deposit_ack p;
+
+ p.PacketType = banking_deposit_ackType;
+ p.Balance = sd->status.zeny;/* how much zeny char has after operation */
+ p.Money = (int64)sd->status.bank_vault;/* money in the bank */
+ p.Reason = (short)reason;
+
+ clif->send(&p,sizeof(p), &sd->bl, SELF);
+}
+void clif_bank_withdraw(struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK reason) {
+ struct packet_banking_withdraw_ack p;
+
+ p.PacketType = banking_withdraw_ackType;
+ p.Balance = sd->status.zeny;/* how much zeny char has after operation */
+ p.Money = (int64)sd->status.bank_vault;/* money in the bank */
+ p.Reason = (short)reason;
+
+ clif->send(&p,sizeof(p), &sd->bl, SELF);
+}
+
/* */
unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) {
if( sd ) {
@@ -18524,6 +18597,9 @@ void clif_defaults(void) {
clif->chsys_quitg = clif_hercules_chsys_quitg;
clif->chsys_gjoin = clif_hercules_chsys_gjoin;
clif->chsys_gleave = clif_hercules_chsys_gleave;
+ /* Bank System [Yommy/Hercules] */
+ clif->bank_deposit = clif_bank_deposit;
+ clif->bank_withdraw = clif_bank_withdraw;
/*------------------------
*- Parse Incoming Packet
*------------------------*/
@@ -18746,4 +18822,10 @@ void clif_defaults(void) {
clif->pPartyBookingReqVolunteer = clif_parse_PartyBookingReqVolunteer;
clif->pPartyBookingRefuseVolunteer = clif_parse_PartyBookingRefuseVolunteer;
clif->pPartyBookingCancelVolunteer = clif_parse_PartyBookingCancelVolunteer;
+ /* Bank System [Yommy/Hercules] */
+ clif->pBankDeposit = clif_parse_BankDeposit;
+ clif->pBankWithdraw = clif_parse_BankWithdraw;
+ clif->pBankCheck = clif_parse_BankCheck;
+ clif->pBankOpen = clif_parse_BankOpen;
+ clif->pBankClose = clif_parse_BankClose;
}
diff --git a/src/map/clif.h b/src/map/clif.h
index 1a2748353..2baca2aaf 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -414,6 +414,19 @@ enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED {
BGQND_FAIL_NOT_QUEUING = 11,
};
+enum e_BANKING_DEPOSIT_ACK {
+ BDA_SUCCESS = 0x0,
+ BDA_ERROR = 0x1,
+ BDA_NO_MONEY = 0x2,
+ BDA_OVERFLOW = 0x3,
+};
+enum e_BANKING_WITHDRAW_ACK {
+ BWA_SUCCESS = 0x0,
+ BWA_NO_MONEY = 0x1,
+ BWA_UNKNOWN_ERROR = 0x2,
+};
+
+
/**
* Structures
**/
@@ -964,6 +977,9 @@ struct clif_interface {
void (*chsys_quitg) (struct map_session_data *sd);
void (*chsys_gjoin) (struct guild *g1,struct guild *g2);
void (*chsys_gleave) (struct guild *g1,struct guild *g2);
+ /* Bank System [Yommy/Hercules] */
+ void (*bank_deposit) (struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK reason);
+ void (*bank_withdraw) (struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK reason);
/*------------------------
*- Parse Incoming Packet
*------------------------*/
@@ -1184,6 +1200,12 @@ struct clif_interface {
void (*pPartyBookingReqVolunteer) (int fd, struct map_session_data *sd);
void (*pPartyBookingRefuseVolunteer) (int fd, struct map_session_data *sd);
void (*pPartyBookingCancelVolunteer) (int fd, struct map_session_data *sd);
+ /* Bank System [Yommy/Hercules] */
+ void (*pBankDeposit) (int fd, struct map_session_data *sd);
+ void (*pBankWithdraw) (int fd, struct map_session_data *sd);
+ void (*pBankCheck) (int fd, struct map_session_data *sd);
+ void (*pBankOpen) (int fd, struct map_session_data *sd);
+ void (*pBankClose) (int fd, struct map_session_data *sd);
};
struct clif_interface *clif;
diff --git a/src/map/log.c b/src/map/log.c
index e33240505..19a98f34b 100644
--- a/src/map/log.c
+++ b/src/map/log.c
@@ -40,6 +40,7 @@ char log_picktype2char(e_log_pick_type type) {
case LOG_TYPE_AUCTION: return 'I'; // Auct(I)on
case LOG_TYPE_BUYING_STORE: return 'B'; // (B)uying Store
case LOG_TYPE_LOOT: return 'L'; // (L)oot (consumed monster pick/drop)
+ case LOG_TYPE_BANK: return 'K'; // Ban(K) Transactions
case LOG_TYPE_OTHER: return 'X'; // Other
}
diff --git a/src/map/log.h b/src/map/log.h
index 07606c8ef..9864a54d7 100644
--- a/src/map/log.h
+++ b/src/map/log.h
@@ -60,6 +60,7 @@ typedef enum e_log_pick_type {
LOG_TYPE_AUCTION = 0x04000,
LOG_TYPE_BUYING_STORE = 0x08000,
LOG_TYPE_OTHER = 0x10000,
+ LOG_TYPE_BANK = 0x20000,
// combinations
LOG_TYPE_LOOT = LOG_TYPE_PICKDROP_MONSTER|LOG_TYPE_CONSUME,
// all
diff --git a/src/map/packets.h b/src/map/packets.h
index c91b5d50c..918f0a10f 100644
--- a/src/map/packets.h
+++ b/src/map/packets.h
@@ -2375,6 +2375,21 @@ packet(0x020d,-1);
packet(0x0930,36,clif->pStoragePassword,0);
#endif
+/* Bank System [Yommy/Hercules] */
+#if PACKETVER >= 20130724
+ packet(0x09A6,12); // ZC_BANKING_CHECK
+ packet(0x09A7,10,clif->pBankDeposit,2,4,6);
+ packet(0x09A8,16); // ZC_ACK_BANKING_DEPOSIT
+ packet(0x09A9,10,clif->pBankWithdraw,2,4,6);
+ packet(0x09AA,16); // ZC_ACK_BANKING_WITHDRAW
+ packet(0x09AB,6,clif->pBankCheck,2,4);
+ ////
+ packet(0x09B6,6,clif->pBankOpen,2,4);
+ packet(0x09B7,4); // ZC_ACK_OPEN_BANKING
+ packet(0x09B8,6,clif->pBankClose,2,4);
+ packet(0x09B9,4); // ZC_ACK_CLOSE_BANKING
+#endif
+
//2013-07-03Ragexe (Shakto)
#if PACKETVER >= 20130703
packet(0x0930,5,clif->pChangeDir,2,4);
diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h
index f39b4a55b..9d7282c92 100644
--- a/src/map/packets_struct.h
+++ b/src/map/packets_struct.h
@@ -18,6 +18,9 @@ struct EQUIPSLOTINFO {
*
**/
enum packet_headers {
+ banking_withdraw_ackType = 0x9aa,
+ banking_deposit_ackType = 0x9a8,
+ banking_checkType = 0x9a6,
cart_additem_ackType = 0x12c,
sc_notickType = 0x196,
#if PACKETVER < 20061218
@@ -543,6 +546,38 @@ struct packet_cart_additem_ack {
char result;
} __attribute__((packed));
+struct packet_banking_check {
+ short PacketType;
+ int64 Money;
+ short Reason;
+} __attribute__((packed));
+
+struct packet_banking_deposit_req {
+ short PacketType;
+ unsigned int AID;
+ int Money;
+} __attribute__((packed));
+
+struct packet_banking_withdraw_req {
+ short PacketType;
+ unsigned int AID;
+ int Money;
+} __attribute__((packed));
+
+struct packet_banking_deposit_ack {
+ short PacketType;
+ short Reason;
+ int64 Money;
+ int Balance;
+} __attribute__((packed));
+
+struct packet_banking_withdraw_ack {
+ short PacketType;
+ short Reason;
+ int64 Money;
+ int Balance;
+} __attribute__((packed));
+
#pragma pack(pop)
#endif /* _PACKETS_STRUCT_H_ */
diff --git a/src/map/pc.c b/src/map/pc.c
index 6b7d6c735..ffc3427c7 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -10079,6 +10079,51 @@ void pc_itemcd_do(struct map_session_data *sd, bool load) {
return;
}
+void pc_bank_deposit(struct map_session_data *sd, int money) {
+ unsigned int limit_check = money+sd->status.bank_vault;
+
+ if( money <= 0 || limit_check > MAX_BANK_ZENY ) {
+ clif->bank_deposit(sd,BDA_OVERFLOW);
+ return;
+ } else if ( money > sd->status.zeny ) {
+ clif->bank_deposit(sd,BDA_NO_MONEY);
+ return;
+ }
+
+ if( pc->payzeny(sd,money, LOG_TYPE_BANK, NULL) )
+ clif->bank_deposit(sd,BDA_NO_MONEY);
+ else {
+ sd->status.bank_vault += money;
+ if( map->save_settings&256 )
+ chrif->save(sd,0);
+ clif->bank_deposit(sd,BDA_SUCCESS);
+ }
+}
+void pc_bank_withdraw(struct map_session_data *sd, int money) {
+ unsigned int limit_check = money+sd->status.zeny;
+
+ if( money <= 0 ) {
+ clif->bank_withdraw(sd,BWA_UNKNOWN_ERROR);
+ return;
+ } else if ( money > sd->status.bank_vault ) {
+ clif->bank_withdraw(sd,BWA_NO_MONEY);
+ return;
+ } else if ( limit_check > MAX_ZENY ) {
+ /* no official response for this scenario exists. */
+ clif->colormes(sd->fd,COLOR_RED,msg_txt(1482));
+ return;
+ }
+
+ if( pc->getzeny(sd,money, LOG_TYPE_BANK, NULL) )
+ clif->bank_withdraw(sd,BWA_NO_MONEY);
+ else {
+ sd->status.bank_vault -= money;
+ if( map->save_settings&256 )
+ chrif->save(sd,0);
+ clif->bank_withdraw(sd,BWA_SUCCESS);
+ }
+}
+
/*==========================================
* pc Init/Terminate
*------------------------------------------*/
@@ -10402,4 +10447,7 @@ void pc_defaults(void) {
pc->checkcombo = pc_checkcombo;
pc->calcweapontype = pc_calcweapontype;
pc->removecombo = pc_removecombo;
+
+ pc->bank_withdraw = pc_bank_withdraw;
+ pc->bank_deposit = pc_bank_deposit;
}
diff --git a/src/map/pc.h b/src/map/pc.h
index fadb922b5..f770818c2 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -961,6 +961,9 @@ struct pc_interface {
int (*checkcombo) (struct map_session_data *sd, struct item_data *data );
int (*calcweapontype) (struct map_session_data *sd);
int (*removecombo) (struct map_session_data *sd, struct item_data *data );
+
+ void (*bank_deposit) (struct map_session_data *sd, int money);
+ void (*bank_withdraw) (struct map_session_data *sd, int money);
};
struct pc_interface *pc;