Introducing Bank Support

http://hercules.ws/board/topic/2455-introducing-bank-support/
Thanks to Yommy, Haru!

Signed-off-by: shennetsind <ind@henn.et>
This commit is contained in:
shennetsind 2013-10-10 12:25:22 -03:00
parent fc4ae790a3
commit c5c3381b0b
20 changed files with 281 additions and 2 deletions

View file

@ -18,3 +18,7 @@ feature.search_stores: on
// Atcommand suggestions (Note 1)
// If one type incomplete atcommand, it will suggest the complete ones.
feature.atcommand_suggestions: off
// Banking (Note 1)
// Requires: 2013-07-24aRagexe or later
feature.banking: on

View file

@ -109,6 +109,7 @@ mercenary_db: mercenary
mercenary_owner_db: mercenary_owner
ragsrvinfo_db: ragsrvinfo
elemental_db: elemental
account_data_db: account_data
// Map Database Tables
item_db_db: item_db

View file

@ -25,6 +25,7 @@
// 0x02000 - (E) Log mail system transactions.
// 0x04000 - (I) Log auction system transactions.
// 0x08000 - (B) Log buying store transactions
// 0x20000 - (K) Log account bank transactions
// 0x10000 - (X) Log all other transactions (rentals expiring/inserting cards/items removed by item_check/
// rings deleted by divorce/pet egg (un)hatching/pet armor (un)equipping/Weapon Refine skill/Remove Trap skill)
// Example: Log trades+vending+script items+created items: 1+2+32+1024 = 1059

View file

@ -97,11 +97,12 @@ minsave_time: 100
// 32: After successfully submitting an item for auction
// 64: After successfully get/delete/complete a quest
// 128: After every buying store transaction
// 256: After every bank transaction (deposit/withdraw)
// NOTE: These settings decrease the chance of dupes/lost items when there's a
// server crash at the expense of increasing the map/char server lag. If your
// server rarely crashes, but experiences interserver lag, you may want to set
// these off.
save_settings: 255
save_settings: 511
// When @help or @h is typed when you are a gm, this is displayed for helping new gms understand gm commands.
help_txt: conf/help.txt

View file

@ -1519,5 +1519,9 @@
1480: I am %s Super Novice~
1481: Help me out~ Please~ T_T
//Banking
1482: You can't withdraw that much money
1483: Banking is disabled
//Custom translations
import: conf/import/msg_conf.txt

View file

@ -657,6 +657,7 @@ INSERT INTO `sql_updates` (`timestamp`) VALUES (1362794218);
INSERT INTO `sql_updates` (`timestamp`) VALUES (1364409316);
INSERT INTO `sql_updates` (`timestamp`) VALUES (1366075474);
INSERT INTO `sql_updates` (`timestamp`) VALUES (1366078541);
INSERT INTO `sql_updates` (`timestamp`) VALUES (1381354728);
--
-- Table structure for table `sstatus`
@ -691,6 +692,10 @@ CREATE TABLE IF NOT EXISTS `storage` (
KEY `account_id` (`account_id`)
) ENGINE=MyISAM;
--
-- Table structure for table `interreg`
--
CREATE TABLE IF NOT EXISTS `interreg` (
`varname` varchar(11) NOT NULL,
`value` varchar(20) NOT NULL,
@ -698,3 +703,14 @@ CREATE TABLE IF NOT EXISTS `interreg` (
) ENGINE=InnoDB;
INSERT INTO `interreg` (`varname`, `value`) VALUES
('unique_id', '0');
--
-- Table structure for table `account_data`
--
CREATE TABLE IF NOT EXISTS `account_data` (
`account_id` int(11) unsigned NOT NULL default '0',
`bank_vault` int(11) unsigned NOT NULL default '0',
PRIMARY KEY (`account_id`)
) ENGINE=MyISAM;

View file

@ -0,0 +1,3 @@
#1381354728
ALTER TABLE `zenylog` MODIFY `type` enum('T','V','P','M','S','N','D','C','A','E','I','B','K') NOT NULL DEFAULT 'S';
INSERT INTO `sql_updates` (`timestamp`) VALUES (1381354728);

View file

@ -4,3 +4,4 @@
2013-03-06--00-00.sql
2013-03-09--01-56.sql
2013-04-16--01-24.sql
2013-10-09--21-38.sql

View file

@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -461,6 +461,7 @@ struct Battle_Config {
int snovice_call_type;
int guild_notice_changemap;
int feature_banking;
} battle_config;
// Dammage delayed info

View file

@ -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;
}

View file

@ -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;

View file

@ -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
}

View file

@ -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

View file

@ -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);

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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;