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/atcommand.c2
-rw-r--r--src/map/battle.c10
-rw-r--r--src/map/battle.h1
-rw-r--r--src/map/clif.c87
-rw-r--r--src/map/clif.h22
-rw-r--r--src/map/homunculus.c22
-rw-r--r--src/map/homunculus.h10
-rw-r--r--src/map/itemdb.c19
-rw-r--r--src/map/itemdb.h1
-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.c54
-rw-r--r--src/map/pc.h3
-rw-r--r--src/map/script.c124
-rw-r--r--src/map/skill.c2
-rw-r--r--src/map/status.c2
20 files changed, 374 insertions, 67 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/atcommand.c b/src/map/atcommand.c
index 3d04a6bff..4933256a2 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -6869,7 +6869,7 @@ ACMD(makehomun) {
homunid = atoi(message);
if( homunid == -1 && sd->status.hom_id && !homun_alive(sd->hd) ) {
- if( !sd->hd->homunculus.vaporize )
+ if( sd->hd->homunculus.vaporize )
homun->ressurect(sd, 100, sd->bl.x, sd->bl.y);
else
homun->call(sd);
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 357c4dc6a..0c21c796c 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -61,10 +61,11 @@ 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:
+ case IT_PETARMOR:
#endif
case IT_PETEGG: return IT_WEAPON;
default: return type;
@@ -1378,7 +1379,7 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag)
WBUFW(buf,0)=0x22e;
memcpy(WBUFP(buf,2),hd->homunculus.name,NAME_LENGTH);
// Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true)
- WBUFB(buf,26)=(battle_config.hom_rename?0:hd->homunculus.rename_flag) | (hd->homunculus.vaporize << 1) | (hd->homunculus.hp?0:4);
+ WBUFB(buf,26)=(battle_config.hom_rename && hd->homunculus.rename_flag ? 0x1 : 0x0) | (hd->homunculus.vaporize == HOM_ST_REST ? 0x2 : 0) | (hd->homunculus.hp > 0 ? 0x4 : 0);
WBUFW(buf,27)=hd->homunculus.level;
WBUFW(buf,29)=hd->homunculus.hunger;
WBUFW(buf,31)=(unsigned short) (hd->homunculus.intimacy / 100) ;
@@ -17725,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 ) {
@@ -18523,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
*------------------------*/
@@ -18745,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/homunculus.c b/src/map/homunculus.c
index 45e9af2b0..1e47053fe 100644
--- a/src/map/homunculus.c
+++ b/src/map/homunculus.c
@@ -134,25 +134,25 @@ int homunculus_dead(struct homun_data *hd) {
}
//Vaporize a character's homun. If flag, HP needs to be 80% or above.
-int homunculus_vaporize(struct map_session_data *sd, int flag) {
+int homunculus_vaporize(struct map_session_data *sd, enum homun_state flag) {
struct homun_data *hd;
nullpo_ret(sd);
hd = sd->hd;
- if (!hd || hd->homunculus.vaporize)
+ if (!hd || hd->homunculus.vaporize != HOM_ST_ACTIVE)
return 0;
if (status->isdead(&hd->bl))
return 0; //Can't vaporize a dead homun.
- if (flag && get_percentage(hd->battle_status.hp, hd->battle_status.max_hp) < 80)
+ if (flag == HOM_ST_REST && get_percentage(hd->battle_status.hp, hd->battle_status.max_hp) < 80)
return 0;
hd->regen.state.block = 3; //Block regen while vaporized.
//Delete timers when vaporized.
homun->hunger_timer_delete(hd);
- hd->homunculus.vaporize = 1;
+ hd->homunculus.vaporize = flag;
if(battle_config.hom_setting&0x40)
memset(hd->blockskill, 0, sizeof(hd->blockskill));
clif->hominfo(sd, sd->hd, 0);
@@ -260,7 +260,7 @@ void homunculus_skillup(struct homun_data *hd,uint16 skill_id) {
int i = 0 ;
nullpo_retv(hd);
- if(hd->homunculus.vaporize)
+ if(hd->homunculus.vaporize != HOM_ST_ACTIVE)
return;
i = skill_id - HM_SKILLBASE;
@@ -471,7 +471,7 @@ bool homunculus_mutate(struct homun_data *hd, int homun_id) {
int homunculus_gainexp(struct homun_data *hd,unsigned int exp) {
enum homun_type htype;
- if(hd->homunculus.vaporize)
+ if(hd->homunculus.vaporize != HOM_ST_ACTIVE)
return 1;
if( (htype = homun->class2type(hd->homunculus.class_)) == HT_INVALID ) {
@@ -571,7 +571,7 @@ unsigned char homunculus_menu(struct map_session_data *sd,unsigned char menu_num
bool homunculus_feed(struct map_session_data *sd, struct homun_data *hd) {
int i, foodID, emotion;
- if(hd->homunculus.vaporize)
+ if(hd->homunculus.vaporize == HOM_ST_REST)
return false;
foodID = hd->homunculusDB->foodID;
@@ -781,11 +781,11 @@ bool homunculus_call(struct map_session_data *sd) {
hd = sd->hd;
- if (!hd->homunculus.vaporize)
+ if (hd->homunculus.vaporize != HOM_ST_REST)
return false; //Can't use this if homun wasn't vaporized.
homun->init_timers(hd);
- hd->homunculus.vaporize = 0;
+ hd->homunculus.vaporize = HOM_ST_ACTIVE;
if (hd->bl.prev == NULL) { //Spawn him
hd->bl.x = sd->bl.x;
hd->bl.y = sd->bl.y;
@@ -833,7 +833,7 @@ bool homunculus_recv_data(int account_id, struct s_homunculus *sh, int flag) {
homun->create(sd, sh);
hd = sd->hd;
- if(hd && hd->homunculus.hp && !hd->homunculus.vaporize && hd->bl.prev == NULL && sd->bl.prev != NULL) {
+ if(hd && hd->homunculus.hp && hd->homunculus.vaporize == HOM_ST_ACTIVE && hd->bl.prev == NULL && sd->bl.prev != NULL) {
enum homun_type htype = homun->class2type(hd->homunculus.class_);
map->addblock(&hd->bl);
@@ -908,7 +908,7 @@ bool homunculus_ressurect(struct map_session_data* sd, unsigned char per, short
hd = sd->hd;
- if (hd->homunculus.vaporize)
+ if (hd->homunculus.vaporize != HOM_ST_ACTIVE)
return false; // vaporized homunculi need to be 'called'
if (!status->isdead(&hd->bl))
diff --git a/src/map/homunculus.h b/src/map/homunculus.h
index 9562ed5c3..2cb558930 100644
--- a/src/map/homunculus.h
+++ b/src/map/homunculus.h
@@ -11,7 +11,7 @@
#define MAX_HOM_SKILL_REQUIRE 5
#define homdb_checkid(id) (id >= HM_CLASS_BASE && id <= HM_CLASS_MAX)
-#define homun_alive(x) ((x) && (x)->homunculus.vaporize != 1 && (x)->battle_status.hp > 0)
+#define homun_alive(x) ((x) && (x)->homunculus.vaporize == HOM_ST_ACTIVE && (x)->battle_status.hp > 0)
struct h_stats {
unsigned int HP, SP;
@@ -44,6 +44,12 @@ enum {
SP_HUNGRY = 0x2,
};
+enum homun_state {
+ HOM_ST_ACTIVE = 0,/* either alive or dead */
+ HOM_ST_REST = 1,/* is resting (vaporized) */
+ HOM_ST_MORPH = 2,/* in morph state */
+};
+
struct homun_data {
struct block_list bl;
struct unit_data ud;
@@ -94,7 +100,7 @@ struct homunculus_interface {
enum homun_type (*class2type) (int class_);
void (*damaged) (struct homun_data *hd);
int (*dead) (struct homun_data *hd);
- int (*vaporize) (struct map_session_data *sd, int flag);
+ int (*vaporize) (struct map_session_data *sd, enum homun_state flag);
int (*delete) (struct homun_data *hd, int emote);
int (*checkskill) (struct homun_data *hd, uint16 skill_id);
int (*calc_skilltree) (struct homun_data *hd, int flag_evolve);
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index fe2c43fcc..09eec557d 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -1704,12 +1704,11 @@ int itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt)
* Reading item from item db
* item_db2 overwriting item_db
*------------------------------------------*/
-int itemdb_readdb(void)
-{
+int itemdb_readdb(void) {
const char* filename[] = {
DBPATH"item_db.txt",
"item_db2.txt" };
-
+ bool duplicate[MAX_ITEMDB];
int fi;
for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) {
@@ -1726,11 +1725,13 @@ int itemdb_readdb(void)
continue;
}
+ memset(&duplicate,0,sizeof(duplicate));
+
// process rows one by one
while(fgets(line, sizeof(line), fp))
{
char *str[32], *p;
- int i;
+ int i, id = 0;
lines++;
if(line[0] == '/' && line[1] == '/')
continue;
@@ -1807,9 +1808,14 @@ int itemdb_readdb(void)
}
}
- if (!itemdb->parse_dbrow(str, filepath, lines, 0))
+ if (!(id = itemdb->parse_dbrow(str, filepath, lines, 0)))
continue;
+ if( duplicate[id] ) {
+ ShowWarning("itemdb_readdb:%s: duplicate entry of ID #%d (%s/%s)\n",filename[fi],id,itemdb_name(id),itemdb_jname(id));
+ } else
+ duplicate[id] = true;
+
count++;
}
@@ -1836,7 +1842,7 @@ int itemdb_read_sqldb(void) {
for( fi = 0; fi < ARRAYLENGTH(item_db_name); ++fi ) {
uint32 count = 0;
-
+
// retrieve all rows from the item database
if( SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT * FROM `%s`", item_db_name[fi]) ) {
Sql_ShowDebug(map->mysql_handle);
@@ -1856,6 +1862,7 @@ int itemdb_read_sqldb(void) {
if (!itemdb->parse_dbrow(str, item_db_name[fi], -(atoi(str[0])), SCRIPT_IGNORE_EXTERNAL_BRACKETS))
continue;
+
++count;
}
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index fe67ebbef..0f46c1c01 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -40,6 +40,7 @@ enum item_itemid {
ITEMID_RED_GEMSTONE = 716,
ITEMID_BLUE_GEMSTONE = 717,
ITEMID_TRAP = 1065,
+ ITEMID_STRANGE_EMBRYO = 6415,
ITEMID_FACE_PAINT = 6120,
ITEMID_STONE = 7049,
ITEMID_SKULL_ = 7420,
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..157d9e28a 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -6438,7 +6438,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
pc->setoption(sd, i);
if( homun_alive(sd->hd) && pc->checkskill(sd, AM_CALLHOMUN) )
- homun->vaporize(sd, 0);
+ homun->vaporize(sd, HOM_ST_ACTIVE);
}
for( i = 1; i < MAX_SKILL; i++ ) {
@@ -6663,7 +6663,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
if (sd->status.hom_id > 0){
if(battle_config.homunculus_auto_vapor && sd->hd && !sd->hd->sc.data[SC_LIGHT_OF_REGENE])
- homun->vaporize(sd, 0);
+ homun->vaporize(sd, HOM_ST_ACTIVE);
}
if( sd->md )
@@ -7588,7 +7588,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
pc->setoption(sd, i);
if(homun_alive(sd->hd) && !pc->checkskill(sd, AM_CALLHOMUN))
- homun->vaporize(sd, 0);
+ homun->vaporize(sd, HOM_ST_ACTIVE);
if(sd->status.manner < 0)
clif->changestatus(sd,SP_MANNER,sd->status.manner);
@@ -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;
diff --git a/src/map/script.c b/src/map/script.c
index 8460b23b0..1bedb78b6 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -6780,7 +6780,7 @@ BUILDIN(strnpcinfo) {
}
/*==========================================
- * GetEquipID(Pos); Pos: 1-10
+ * GetEquipID(Pos); Pos: 1-SCRIPT_EQUIP_TABLE_SIZE
*------------------------------------------*/
BUILDIN(getequipid)
{
@@ -9564,44 +9564,82 @@ BUILDIN(homunculus_evolution)
/*==========================================
* [Xantara]
+ * Checks for vaporized morph state
+ * and deletes ITEMID_STRANGE_EMBRYO.
*------------------------------------------*/
BUILDIN(homunculus_mutate) {
int homun_id;
enum homun_type m_class, m_id;
TBL_PC *sd;
+ bool success = false;
sd = script->rid2sd(st);
if( sd == NULL || sd->hd == NULL )
return true;
-
- if( script_hasdata(st,2) )
- homun_id = script_getnum(st,2);
- else
- homun_id = 6048 + (rnd() % 4);
-
- if( homun_alive(sd->hd) ) {
+
+ if( sd->hd->homunculus.vaporize == HOM_ST_MORPH ) {
+ int i = pc->search_inventory(sd, ITEMID_STRANGE_EMBRYO);
+ if( script_hasdata(st,2) )
+ homun_id = script_getnum(st,2);
+ else
+ homun_id = 6048 + (rnd() % 4);
+
m_class = homun->class2type(sd->hd->homunculus.class_);
m_id = homun->class2type(homun_id);
- if( m_class != HT_INVALID && m_id != HT_INVALID && m_class == HT_EVO && m_id == HT_S && sd->hd->homunculus.level >= 99 )
+ if( m_class == HT_EVO && m_id == HT_S &&
+ sd->hd->homunculus.level >= 99 && i >= 0 &&
+ !pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_SCRIPT) ) {
+ sd->hd->homunculus.vaporize = HOM_ST_REST; // Remove morph state.
+ homun->call(sd); // Respawn homunculus.
homun->mutate(sd->hd, homun_id);
- else
+ success = true;
+ } else
clif->emotion(&sd->hd->bl, E_SWT);
- }
+ } else
+ clif->emotion(&sd->hd->bl, E_SWT);
+
+ script_pushint(st,success?1:0);
return true;
}
-// [Zephyrus]
-BUILDIN(homunculus_shuffle) {
+/*==========================================
+ * Puts homunculus into morph state
+ * and gives ITEMID_STRANGE_EMBRYO.
+ *------------------------------------------*/
+BUILDIN(homunculus_morphembryo) {
+ enum homun_type m_class;
+ int i = 0;
TBL_PC *sd;
+ bool success = false;
- sd=script->rid2sd(st);
- if( sd == NULL )
+ sd = script->rid2sd(st);
+ if( sd == NULL || sd->hd == NULL )
return true;
- if(homun_alive(sd->hd))
- homun->shuffle(sd->hd);
+ if( homun_alive(sd->hd) ) {
+ m_class = homun->class2type(sd->hd->homunculus.class_);
+
+ if ( m_class == HT_EVO && sd->hd->homunculus.level >= 99 ) {
+ struct item item_tmp;
+
+ memset(&item_tmp, 0, sizeof(item_tmp));
+ item_tmp.nameid = ITEMID_STRANGE_EMBRYO;
+ item_tmp.identify = 1;
+
+ if( (i = pc->additem(sd, &item_tmp, 1, LOG_TYPE_SCRIPT)) ) {
+ clif->additem(sd, 0, 0, i);
+ clif->emotion(&sd->hd->bl, E_SWT);
+ } else {
+ homun->vaporize(sd, HOM_ST_MORPH);
+ success = true;
+ }
+ } else
+ clif->emotion(&sd->hd->bl, E_SWT);
+ } else
+ clif->emotion(&sd->hd->bl, E_SWT);
+ script_pushint(st, success?1:0);
return true;
}
@@ -9612,21 +9650,29 @@ BUILDIN(homunculus_shuffle) {
* 1 = Homunculus is vaporized (rest)
* 2 = Homunculus is in morph state
*------------------------------------------*/
-BUILDIN(checkhomcall)
-{
+BUILDIN(homunculus_checkcall) {
TBL_PC *sd = script->rid2sd(st);
- TBL_HOM *hd;
- if( sd == NULL )
- return false;
-
- hd = sd->hd;
-
- if( !hd )
+ if( sd == NULL || !sd->hd )
script_pushint(st, -1);
else
- script_pushint(st, hd->homunculus.vaporize);
+ script_pushint(st, sd->hd->homunculus.vaporize);
+
+ return true;
+}
+
+// [Zephyrus]
+BUILDIN(homunculus_shuffle) {
+ TBL_PC *sd;
+
+ sd=script->rid2sd(st);
+ if( sd == NULL )
+ return true;
+
+ if(homun_alive(sd->hd))
+ homun->shuffle(sd->hd);
+
return true;
}
@@ -12166,12 +12212,9 @@ BUILDIN(getpetinfo)
BUILDIN(gethominfo)
{
TBL_PC *sd=script->rid2sd(st);
- TBL_HOM *hd;
- int type=script_getnum(st,2);
+ int type = script_getnum(st,2);
- hd = sd?sd->hd:NULL;
- if(!homun_alive(hd))
- {
+ if(!sd || !sd->hd) {
if (type == 2)
script_pushconststr(st,"null");
else
@@ -12180,13 +12223,13 @@ BUILDIN(gethominfo)
}
switch(type){
- case 0: script_pushint(st,hd->homunculus.hom_id); break;
- case 1: script_pushint(st,hd->homunculus.class_); break;
- case 2: script_pushstrcopy(st,hd->homunculus.name); break;
- case 3: script_pushint(st,hd->homunculus.intimacy); break;
- case 4: script_pushint(st,hd->homunculus.hunger); break;
- case 5: script_pushint(st,hd->homunculus.rename_flag); break;
- case 6: script_pushint(st,hd->homunculus.level); break;
+ case 0: script_pushint(st,sd->hd->homunculus.hom_id); break;
+ case 1: script_pushint(st,sd->hd->homunculus.class_); break;
+ case 2: script_pushstrcopy(st,sd->hd->homunculus.name); break;
+ case 3: script_pushint(st,sd->hd->homunculus.intimacy); break;
+ case 4: script_pushint(st,sd->hd->homunculus.hunger); break;
+ case 5: script_pushint(st,sd->hd->homunculus.rename_flag); break;
+ case 6: script_pushint(st,sd->hd->homunculus.level); break;
default:
script_pushint(st,0);
break;
@@ -17655,8 +17698,9 @@ void script_parse_builtin(void) {
BUILDIN_DEF(warpportal,"iisii"),
BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn]
BUILDIN_DEF2(homunculus_mutate,"hommutate","?"),
+ BUILDIN_DEF2(homunculus_morphembryo,"morphembryo",""),
+ BUILDIN_DEF2(homunculus_checkcall,"checkhomcall",""),
BUILDIN_DEF2(homunculus_shuffle,"homshuffle",""), //[Zephyrus]
- BUILDIN_DEF(checkhomcall,""),
BUILDIN_DEF(eaclass,"?"), //[Skotlex]
BUILDIN_DEF(roclass,"i?"), //[Skotlex]
BUILDIN_DEF(checkvending,"?"),
diff --git a/src/map/skill.c b/src/map/skill.c
index ab937fadd..70e946119 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -7518,7 +7518,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case AM_REST:
if (sd) {
- if (homun->vaporize(sd,1))
+ if (homun->vaporize(sd,HOM_ST_REST))
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
else
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
diff --git a/src/map/status.c b/src/map/status.c
index 497d02bbf..ae900e04d 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -8230,7 +8230,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
if( pc_isridingwug(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_WUGRIDER);
if( pc_isfalcon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_FALCON);
if( sd->status.pet_id > 0 ) pet->menu(sd, 3);
- if( homun_alive(sd->hd) ) homun->vaporize(sd,1);
+ if( homun_alive(sd->hd) ) homun->vaporize(sd,HOM_ST_REST);
if( sd->md ) mercenary->delete(sd->md,3);
}
break;