From a879388b0af8354bf8dec199de215b206cacb9ac Mon Sep 17 00:00:00 2001 From: cannelle Date: Tue, 8 Oct 2013 23:55:30 -0500 Subject: Added WE_BABY distance check. --- src/map/skill.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'src/map') diff --git a/src/map/skill.c b/src/map/skill.c index 248e19e77..2b531c3ec 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -6971,21 +6971,23 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui if(sd) { struct map_session_data *f_sd = pc->get_father(sd); struct map_session_data *m_sd = pc->get_mother(sd); - // if neither was found - if(!f_sd && !m_sd) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - map->freeblock_unlock(); - return 0; + bool we_baby_parents; + if(m_sd && check_distance_bl(bl,&m_sd->bl,AREA_SIZE)) { + sc_start(&m_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + clif->specialeffect(&m_sd->bl,408,AREA); + we_baby_parents = 1; } - status->change_start(bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),8); - if (f_sd) { + if(f_sd && check_distance_bl(bl,&f_sd->bl,AREA_SIZE)) { sc_start(&f_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); clif->specialeffect(&f_sd->bl,408,AREA); + we_baby_parents = 1; } - if (m_sd) { - sc_start(&m_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); - clif->specialeffect(&m_sd->bl,408,AREA); + if (!we_baby_parents) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map->freeblock_unlock(); + return 0; } + else status->change_start(bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),8); } break; -- cgit v1.2.3-70-g09d2 From 40f62c2626766cbd0b70776f42e69b5a8f98455e Mon Sep 17 00:00:00 2001 From: shennetsind Date: Wed, 9 Oct 2013 17:56:18 -0300 Subject: Fixed Bug #7749 Fixed Pet Items from ending up in the weapon tab of storage instead of armor. http://hercules.ws/board/tracker/issue-7749-storage-problem/ Thanks to malufett, Frost. Signed-off-by: shennetsind --- src/map/clif.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/map') diff --git a/src/map/clif.c b/src/map/clif.c index 357c4dc6a..8fd2a60c2 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -65,6 +65,7 @@ static inline int itemtype(int 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; -- cgit v1.2.3-70-g09d2 From c5c3381b0b8b0b59c669d474acf749db82d7edb1 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 10 Oct 2013 12:25:22 -0300 Subject: Introducing Bank Support http://hercules.ws/board/topic/2455-introducing-bank-support/ Thanks to Yommy, Haru! Signed-off-by: shennetsind --- conf/battle/feature.conf | 4 ++ conf/inter-server.conf | 1 + conf/logs.conf | 1 + conf/map-server.conf | 3 +- conf/messages.conf | 4 ++ sql-files/main.sql | 16 ++++++ sql-files/upgrades/2013-10-09--21-38.sql | 3 ++ sql-files/upgrades/index.txt | 1 + src/char/char.c | 25 ++++++++++ src/common/mmo.h | 5 ++ src/map/battle.c | 10 ++++ src/map/battle.h | 1 + src/map/clif.c | 84 +++++++++++++++++++++++++++++++- src/map/clif.h | 22 +++++++++ src/map/log.c | 1 + src/map/log.h | 1 + src/map/packets.h | 15 ++++++ src/map/packets_struct.h | 35 +++++++++++++ src/map/pc.c | 48 ++++++++++++++++++ src/map/pc.h | 3 ++ 20 files changed, 281 insertions(+), 2 deletions(-) create mode 100644 sql-files/upgrades/2013-10-09--21-38.sql (limited to 'src/map') diff --git a/conf/battle/feature.conf b/conf/battle/feature.conf index 440dbb31a..2f60f1fff 100644 --- a/conf/battle/feature.conf +++ b/conf/battle/feature.conf @@ -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 \ No newline at end of file diff --git a/conf/inter-server.conf b/conf/inter-server.conf index 09ac15f82..db94494f1 100644 --- a/conf/inter-server.conf +++ b/conf/inter-server.conf @@ -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 diff --git a/conf/logs.conf b/conf/logs.conf index f036cbccf..6933e84fe 100644 --- a/conf/logs.conf +++ b/conf/logs.conf @@ -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 diff --git a/conf/map-server.conf b/conf/map-server.conf index fb4614ca3..a3afde66c 100644 --- a/conf/map-server.conf +++ b/conf/map-server.conf @@ -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 diff --git a/conf/messages.conf b/conf/messages.conf index fc8599f5b..4b0549bf6 100644 --- a/conf/messages.conf +++ b/conf/messages.conf @@ -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 diff --git a/sql-files/main.sql b/sql-files/main.sql index 0e9dc5b67..dcb735129 100644 --- a/sql-files/main.sql +++ b/sql-files/main.sql @@ -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; + diff --git a/sql-files/upgrades/2013-10-09--21-38.sql b/sql-files/upgrades/2013-10-09--21-38.sql new file mode 100644 index 000000000..fee85c40b --- /dev/null +++ b/sql-files/upgrades/2013-10-09--21-38.sql @@ -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); \ No newline at end of file diff --git a/sql-files/upgrades/index.txt b/sql-files/upgrades/index.txt index 984898b22..bffc42f99 100644 --- a/sql-files/upgrades/index.txt +++ b/sql-files/upgrades/index.txt @@ -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 \ No newline at end of file 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; -- cgit v1.2.3-70-g09d2 From 1e7918769778b2be98daa754ce02dbe0eae53fd9 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 10 Oct 2013 15:59:58 -0300 Subject: Fixed Bug #7570 Thanks to frenzmu06. Added code into the item db parser to throw a warning when there is more than one version of a item from within the same file, thanks to EvilPuncker. Closes #183 Signed-off-by: shennetsind --- db/re/item_db.txt | 2 -- src/map/itemdb.c | 19 +++++++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'src/map') diff --git a/db/re/item_db.txt b/db/re/item_db.txt index b4c2ca654..7385672d9 100644 --- a/db/re/item_db.txt +++ b/db/re/item_db.txt @@ -8011,7 +8011,6 @@ 18572,Korean_Judge_Hat,Judges Hat,5,20,,300,,2,,1,0xFFFFFFFF,63,2,256,,0,1,377,{ bonus bMdef,2; },{},{} 18573,White_Feather,White Feather,5,20,,500,,2,,1,0xFFFFFFFF,63,2,256,,30,1,741,{},{},{} 18574,Lord_of_Death,Lord of the Dead Helm,5,20,,1000,,10,,1,0xFFFFFFFF,63,2,768,,70,1,742,{ bonus bMdef,5; },{},{} -18574,Lord_of_Death,Lord of the Dead Helm,5,20,,1000,,10,,1,0xFFFFFFFF,63,2,768,,70,1,742,{ bonus bMdef,5; },{},{} 18575,Wunderkammer,Wunderkammer,5,20,,500,,10,,1,0xFFFFFFFF,7,2,769,,20,0,743,{ bonus bMdef,10; },{},{} 18576,YinYang_Earring,Yin Yang Earrings,5,20,,100,,0,,0,0xFFFFFFFF,63,2,512,,50,0,744,{},{},{} 18577,24_Bolt,Screw Stuck Head,5,20,,200,,0,,0,0xFFFFFFFF,63,2,512,,10,0,696,{},{},{} @@ -8042,7 +8041,6 @@ 18602,Watermelon_Slice,Watermelon Bite,5,20,,100,,0,,0,0xFFFFFFFF,63,2,1,,30,0,763,{ bonus bUnbreakableHelm,0; bonus bMdef,4; bonus2 bAddEle,Ele_Fire,4; },{},{} 18603,Black_Devil_Mask_,Black Devil's Mask,5,20,,100,,0,,1,0xFFFFFFFF,63,2,512,,0,0,760,{ bonus bAllStats,1; },{},{} 18604,Falcon_Mask,Falcon Mask,5,10,,30,,0,,1,0xFFFFFFFF,63,2,513,,50,0,782,{},{},{} -18604,Falcon_Mask,Falcon Mask,5,10,,30,,0,,1,0xFFFFFFFF,63,2,513,,50,0,782,{},{},{} 18605,Dark_Age,Dark Age,5,20,,200,,3,,1,0xFFFFFFFF,63,2,256,,10,1,766,{ bonus bMdef,3; },{},{} 18606,Tear_Drop,Tear drop,5,20,,100,,1,,0,0xFFFFFFFF,63,2,513,,30,0,767,{},{},{} 18607,Blush_,Blush,5,20,,100,,0,,1,0xFFFFFFFF,63,2,512,,0,0,125,{},{},{} 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; } -- cgit v1.2.3-70-g09d2 From 0cf17827ac0e8b025ce22fea716a5185c5092ad7 Mon Sep 17 00:00:00 2001 From: cannelle Date: Thu, 10 Oct 2013 15:51:55 -0500 Subject: Added WE_BABY distance check. --- src/map/skill.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/map') diff --git a/src/map/skill.c b/src/map/skill.c index 2b531c3ec..ab937fadd 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -6971,16 +6971,16 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui if(sd) { struct map_session_data *f_sd = pc->get_father(sd); struct map_session_data *m_sd = pc->get_mother(sd); - bool we_baby_parents; + bool we_baby_parents = false; if(m_sd && check_distance_bl(bl,&m_sd->bl,AREA_SIZE)) { sc_start(&m_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); clif->specialeffect(&m_sd->bl,408,AREA); - we_baby_parents = 1; + we_baby_parents = true; } if(f_sd && check_distance_bl(bl,&f_sd->bl,AREA_SIZE)) { sc_start(&f_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); clif->specialeffect(&f_sd->bl,408,AREA); - we_baby_parents = 1; + we_baby_parents = true; } if (!we_baby_parents) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); -- cgit v1.2.3-70-g09d2 From a2e01e40c9e60b8b2d75e4faf41d80a7041e8f93 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 10 Oct 2013 18:19:16 -0300 Subject: Homun-S Quest Updated Partial Merge of 0b68607 Quest Changelog: - 1.2 Replaced with official script. [Euphy] Closes #177 Closes #178 Signed-off-by: shennetsind --- npc/re/quests/homu_s.txt | 144 ----- npc/re/quests/homun_s.txt | 1362 +++++++++++++++++++++++++++++++++++++++++++++ npc/re/scripts.conf | 2 +- src/map/atcommand.c | 2 +- src/map/clif.c | 2 +- src/map/homunculus.c | 22 +- src/map/homunculus.h | 10 +- src/map/itemdb.h | 1 + src/map/pc.c | 6 +- src/map/script.c | 124 +++-- src/map/skill.c | 2 +- src/map/status.c | 2 +- 12 files changed, 1474 insertions(+), 205 deletions(-) delete mode 100644 npc/re/quests/homu_s.txt create mode 100644 npc/re/quests/homun_s.txt (limited to 'src/map') diff --git a/npc/re/quests/homu_s.txt b/npc/re/quests/homu_s.txt deleted file mode 100644 index 66e2b5c3d..000000000 --- a/npc/re/quests/homu_s.txt +++ /dev/null @@ -1,144 +0,0 @@ -//===== Hercules Script ====================================== -//= Homunculus S Quest -//===== By: ================================================== -//= Masao -//===== Current Version: ===================================== -//= 1.1 -//===== Compatible With: ===================================== -//= Hercules -//===== Description: ========================================= -//= Evolves an Homunculus which is at least Level 99 to the -//= new Homunculus S Class. -//===== Additional Comments: ================================= -//= 1.0 First Version. The actual changing dialog is currently -//= customized. [Masao] -//= 1.1 Cleaning. [Euphy] -//============================================================ - -job3_gen01,12,44,4 script Viorel#job3_gen01 542,{ - - if((Class != Job_Genetic) && (Class != Job_Genetic_T) && (Class != Job_Baby_Genetic)){ - mes "[Viorel]"; - mes "^FF4800Homunculus^000000 research requires a lot of time and funding."; - mes "However, I believe passion is the most important factor."; - next; - switch(select("End conversation.:What are you talking about?:Why are you always standing there?")) { - case 1: - mes "[Viorel]"; - mes "So long~!"; - close; - case 2: - mes "[Viorel]"; - mes "You see, ^006400Alchemists^000000 have an inquisitive nature."; - mes "People like me, especially, even think of creating life itself."; - next; - mes "[Viorel]"; - mes "You'd have to research ^FF4800Homunculus^000000 to understand."; - mes "Now, if you'll excuse me~!"; - close; - case 3: - emotion 4,0; - mes "[Viorel]"; - mes "What, is it so strange to see an Alchemist in their own lab?"; - mes "How so?"; - close; - } - } - mes "[Viorel]"; - mes "Hello "+strcharinfo(0)+","; - mes "what can I do for a fellow Alchemist like you?"; - next; - switch(select("I want to evolve my Homunculus:About Homunculus S:Cancel")){ - case 1: - mes "[Viorel]"; - if(!getskilllv("AM_BIOETHICS")){ - mes "I'm sorry, but you must know the Skill Bioethics! Otherwise I can't let your Homunculus evolve into a Homunculus S."; - close; - } - if(!gethominfo(1)){ - mes "You don't even have a Homunculus!"; - close; - } - if(gethominfo(1) < 6009){ - mes "You must have an evolved Homunculus, or you can't turn it into the new Homunculus S."; - close; - } - if(gethominfo(6) < 99){ - mes "Your Homunculus must be level 99 to evolve into a Homuculus S!"; - mes "Come back after you've trained your Homunculus a little bit more."; - close; - } - if(gethominfo(1) == 6048 || gethominfo(1) == 6049 || gethominfo(1) == 6050 || gethominfo(1) == 6051 || gethominfo(1) == 6052){ - mes "Your Homunculus S looks great!"; - mes "I hope you will experience many great adventures with it!"; - close; - } - mes "Great, it seems like you're all ready to get your Homunculus to the next level!"; - next; - mes "[Viorel]"; - mes "Now you can either directly change your Homunculus to a random Homunculus S or you can donate a little fee of 50,000z"; - mes "to the Alchemist Guild. For this you'll be able to change your Homunculus into your desired Homunculus S Class!"; - mes "So, what do you think?"; - next; - switch(Select("I want to donate.:I don't want to donate.:Cancel")){ - case 1: - if(Zeny < 50000){ - mes "[Viorel]"; - mes "Haha, nice try my friend! But you don't even have the 50,000z to donate!"; - mes "Come back if you have the Zeny."; - close; - } - mes "[Viorel]"; - mes "Alright, now please tell me which Homunculus you'd like to have:"; - next; - set .@i, select("Eira:Bayeri:Sera:Dieter:Elanor:Cancel"); - if (.@i == 6) { - mes "[Viorel]"; - mes "So long~!"; - close; - } - case 2: - mes "[Viorel]"; - mes "Ok, it's all set! Now just give me a moment!"; - next; - mes "[Viorel]"; - mes "Abra..."; - next; - mes "[Viorel]"; - mes "Kadabra..."; - next; - mes "[Viorel]"; - mes "Simsala!"; - mes "..."; - mes "Oh, sorry... wrong game!"; - next; - mes "[Viorel]"; - mes "Here you go! Your new Homunculus S!"; - if (.@i) { - hommutate 6047+.@i; - set Zeny,Zeny - 50000; - } - else hommutate; - close; - case 3: - mes "[Viorel]"; - mes "So long~!"; - close; - } - case 2: - mes "[Viorel]"; - mes "The Homunculus S are the new and improved versions of the current Homunculus you know."; - mes "These new Homunculus have been made because the monsters in our world keep getting stronger and"; - mes "stronger, and our current Homunculus are just not able to keep up with them anymore."; - next; - mes "[Viorel]"; - mes "But since we're Alchemists and we don't want to abandon our precious Homunculus, we've discovered a way"; - mes "to improve their skills and strength in order to keep them by our side, and joining us once more"; - mes "in battle! Isn't that great?"; - close; - case 3: - mes "[Viorel]"; - mes "So long~!"; - close; - } -} diff --git a/npc/re/quests/homun_s.txt b/npc/re/quests/homun_s.txt new file mode 100644 index 000000000..66b7537c9 --- /dev/null +++ b/npc/re/quests/homun_s.txt @@ -0,0 +1,1362 @@ +//===== Hercules Script ====================================== +//= Homunculus S Quest +//===== By: ================================================== +//= Masao +//===== Current Version: ===================================== +//= 1.2 +//===== Compatible With: ===================================== +//= Hercules +//===== Description: ========================================= +//= Evolves an Homunculus which is at least Level 99 to the +//= new Homunculus S Class. +//===== Additional Comments: ================================= +//= 1.0 First Version. The actual changing dialog is currently +//= customized. [Masao] +//= 1.1 Cleaning. [Euphy] +//= 1.2 Replaced with official script. [Euphy] +//============================================================ + +// Main NPCs +//============================================================ +job3_gen01,12,44,3 script Viorel#job3_gen01 542,{ + if (countitem(6415)) { + if (Class == Job_Genetic || Class == Job_Genetic_T || Class == Job_Baby_Genetic) { + disable_items; + if (checkquest(4159) == -1 && checkquest(4160) == -1) { + mes "[Viorel]"; + mes "Why are you here?"; + mes "Shouldn't you be at ^005DFFJeyna^000000's house?"; + close2; + for(set .@i,4154; .@i<=4160; set .@i,.@i+1) { + if (checkquest(.@i) > -1) + erasequest .@i; + } + setquest 4154; + setquest 4159; + morphembryo; + if (countitem(6415) == 0) + getitem 6415,1; //Strange_Embryo + else if (countitem(6415) > 1) + delitem 6415, (countitem(6415) - 1); //Strange_Embryo + warp "que_house_s",63,41; + end; + } + enable_items; + } else if (Class == Job_Novice_High || Class == Job_Merchant_High || Class == Job_Alchemist || Class == Job_Creator) { + emotion e_what; + mes "[Viorel]"; + mes "I don't know what's going on, but the way I remember it you were supposed to be qualified to research ^FF4800Homunculus^000000."; + next; + mes "[Viorel]"; + mes "Whatever the reason, you're not able to continue the research on ^FF4800Homunculus^000000."; + mes "Come back after you become a ^005DFFGenetic^000000 and have obtained a ^0000FFBioethics^000000."; + close; + } else { + delitem 6415, countitem(6415); //Strange_Embryo + mes "[Viorel]"; + mes "Wait, that embryo you have seems a little strange."; + next; + mes "[Viorel]"; + mes "Unless you have a job researching ^FF4800Homunculus^000000...."; + mes "It will be of no help to you what so ever."; + next; + mes "[Viorel]"; + mes "I'm in charge of managing ^0000FFStrange Embryo^000000 so I'll take care of that for you."; + mes "No offense, and I'm not doing anything bad here."; + close; + } + } + if ((Class == Job_Genetic || Class == Job_Genetic_T || Class == Job_Baby_Genetic) && (checkquest(4154) > -1)) { + if ((checkquest(4155) > -1) || (checkquest(4160) > -1)) { + mes "[Viorel]"; + mes "Weather's great."; + next; + callsub L_CheckHomunculus; + mes "[Viorel]"; + mes "Ready to go to my house?"; + next; + switch(select("Go to ^005DFFViorel^000000's house.:Don't go.")) { + case 1: + mes "[Viorel]"; + mes "Good choice."; + mes "Now, close your eyes for a second..."; + close2; + warp "que_house_s",19,42; + end; + case 2: + mes "[Viorel]"; + mes "Come back when you're ready."; + mes "You must come with the ^FF4800Homunculus^000000."; + close; + } + } else { + mes "[Viorel]"; + mes "Why are you here?"; + mes "Shouldn't you be at ^005DFFJeyna^000000's house?"; + next; + callsub L_CheckHomunculus; + mes "[Viorel]"; + mes "Now, ready to go to ^005DFFJeyna^000000?"; + next; + switch(select("Go to ^005DFFJeyna^000000's room.:Don't go.")) { + case 1: + mes "[Viorel]"; + mes "Good choice."; + mes "Now, close your eyes for a second..."; + close2; + warp "que_house_s",63,41; + end; + case 2: + mes "[Viorel]"; + mes "Come back when you're ready."; + mes "You must come with the ^FF4800Homunculus^000000."; + close; + } + } + } + if (BaseJob == Job_Merchant) { + mes "[Viorel]"; + mes "I used to be a merchant once, just like you."; + mes "I'm researching on ^FF4800Homunculus^000000."; + next; + mes "[Viorel]"; + mes "If you're interested in ^FF4800Homunculus^000000, become an ^005DFFAlchemist^000000 or a ^005DFFCreator^000000."; + close; + } else if (BaseJob == Job_Alchemist && Class < Job_Genetic) { + mes "[Viorel]"; + mes "I've spent lots of time and energy on Homunculus."; + mes "If you feel like you're at a dead end, come back next time with a ^FF4800Homunculus^000000."; + next; + mes "[Viorel]"; + mes "Oh. Of course you need to have the suitable potentials. You could probably prove yourself once you become a ^FF4800Genetic^000000."; + close; + } else if (Class == Job_Genetic || Class == Job_Genetic_T || Class == Job_Baby_Genetic) { + if (gethominfo(6) >= 99 && (gethominfo(1) >= 6009 && gethominfo(1) <= 6016)) { // Level 99+ evolved Homunculus + mes "[Viorel]"; + mes "Oh, great~!"; + mes "You have a ^FF4800Homunculus^000000."; + mes "With passion invested in its research we can make them better."; + next; + mes "[Viorel]"; + mes "I must speak to you in private. Would you mind going to my house with me?"; + next; + switch(select("Go to ^005DFFViorel^000000's home.:Stay here.")) { + case 1: + mes "[Viorel]"; + mes "Good choice."; + mes "Now, close your eyes for a second..."; + close2; + setquest 4154; + setquest 4155; + warp "que_house_s",19,42; + end; + case 2: + mes "[Viorel]"; + mes "If you feel like you're at a dead end, come back next time with a ^FF4800Homunculus^000000."; + close; + } + } else if (gethominfo(6) >= 99 && (gethominfo(1) >= 6048 && gethominfo(1) <= 6052)) { // Level 99+ mutated Homunculus-S + mes "[Viorel]"; + mes "Hello again."; + mes "Perhaps you may be interested"; + mes "in the newly created ^FF4800Homunculus^000000,"; + mes "born from the new ^006400Homunculus Mutation System^000000?"; + next; + switch(select("Nope. Good bye.:Please, I'm busy.:That's exactly what I wanted to hear.:Why are you always standing there?")) { + case 1: + emotion e_heh; + mes "[Viorel]"; + mes "Okay."; + mes "Good seeing you."; + mes "Good bye then~!"; + close; + case 2: + emotion e_omg; + mes "[Viorel]"; + mes "!!!!"; + mes "I... I see."; + mes "I thought you were here to see me."; + close; + case 3: + emotion e_ic; + mes "[Viorel]"; + mes "Just as I thought."; + mes "Let's have a look at the notes my dear friend Jeyna left."; + next; + playbgm "30.mp3"; // One Step Closer + callfunc "F_HomMutateInfo","[Memo Pad Notes]"; + mes "[Viorel]"; + mes "Hmm."; + mes "Well, that's all there is to it."; + mes "It's up to you to find out more."; + close2; + playbgm "08.mp3"; // Theme of Prontera + end; + case 4: + emotion e_swt; + mes "[Viorel]"; + mes "No, I do not stand here every day."; + mes "But why do YOU stand there every day?"; + next; + mes "[Viorel]"; + mes "What?"; + mes "No, the way I see it"; + mes "you seem to be here every time I'm here."; + close; + } + } else { + if (gethominfo(1) >= 6009) { // Evolved Homunculus + mes "[Viorel]"; + mes "Hmm, you seem to have a special bond with your ^FF4800Homunculus^000000."; + next; + mes "[Viorel]"; + mes "Come back to me when that ^FF4800Homunculus^000000 reaches ^0000FFlevel 99^000000."; + close; + } else { + mes "[Viorel]"; + mes "You do not yet possess an evolved ^FF4800Homunculus^000000..."; + mes "As you may well know about evolution:"; + next; + mes "[Viorel]"; + mes "Using the ^0000FFStone of Sage^000000 when intimacy level is above ^006400Intimate^000000, the ^FF4800Homunculus^000000 goes through ^006400Evolution^000000."; + close; + } + } + } + mes "[Viorel]"; + mes "^FF4800Homunculus^000000 research requires a lot of time and funding."; + mes "However, I believe passion is the most important factor."; + next; + switch(select("End conversation.:What are you talking about?:Why are you always standing there?")) { + case 1: + mes "[Viorel]"; + mes "So long~!"; + close; + case 2: + mes "[Viorel]"; + mes "You see, ^006400Alchemists^000000 have an inquisitive nature."; + mes "People like me, especially, even think of creating life itself."; + next; + mes "[Viorel]"; + mes "You'd have to research ^FF4800Homunculus^000000 to understand."; + mes "Now, if you'll excuse me~!"; + close; + case 3: + emotion e_swt; + mes "[Viorel]"; + mes "What, is it so strange to see an Alchemist in their own lab?"; + mes "How so?"; + close; + } + end; +L_CheckHomunculus: + if (gethominfo(6) < 99 || (gethominfo(1) < 6009 || gethominfo(1) > 6016)) { // Not level 99+ evolved Homunculus + mes "[Viorel]"; + mes "Huh?"; + mes "Where's the ^FF4800Homunculus^000000 you used to have?"; + mes "Perhaps I've mistaken it for something else..."; + next; + mes "[Viorel]"; + mes "......."; + mes " "; + mes "(Seems to be thinking about something.)"; + next; + emotion e_heh; + mes "[Viorel]"; + mes "Ha ha~"; + mes "I think I've mistaken you for someone else."; + mes "If you'll excuse me."; + close; + } + return; +} + +que_house_s,24,47,3 script Viorel#homun_s 542,{ + if (checkquest(4155) > -1) { + emotion e_dum; + mes "[Viorel]"; + mes "Good."; + mes "I see that you mean business."; + next; + playbgm "33.mp3"; // Yuna Song + mes "[Viorel]"; + mes "Maybe you'll agree."; + mes "Currently, your ^FF4800Homunculus^000000 is not in its perfect state."; + next; + mes "[Viorel]"; + mes "These days, studies on the growth of the ^FF4800Homunculus^000000 are actively taking place."; + mes "But, I do believe that I have found something special."; + next; + mes "[Viorel]"; + mes "In order to break the current limitations of the ^FF4800Homunculus^000000, mutations need to happen."; + next; + switch(select("Like, biological experiments...?!:Well, yeah, naturally.:I don't want to hurt my Homunculus!")) { + case 1: + emotion e_swt2; + mes "[Viorel]"; + mes "Don't look so surprised."; + mes "Ethics in biology are kind of blurry right now, right?"; + mes "I mean..."; + next; + mes "[Viorel]"; + mes "It's my duty to study the true potential of the ^FF4800Homunculus^000000."; + next; + mes "[Viorel]"; + mes "So far, Homunculus haven't demonstrated their full potential, but I know that I am close to a breakthrough."; + next; + break; + case 2: + emotion e_sigh; + mes "[Viorel]"; + mes "Yes."; + mes "I'm glad you're not upset."; + mes "Mutation,"; + mes "a word that sparks evil in the minds of the ordinary,"; + mes "which made my research very difficult to proceed with."; + next; + mes "[Viorel]"; + mes "Do you remember?"; + mes "^005DFFKellasus^000000 of ^8B4513Lighthalzen^000000, the pioneer of ^FF4800Homunculus^000000 research."; + next; + mes "[Viorel]"; + mes "I believe that this research fulfills the promise made with ^005DFFKellasus^000000, the giver of knowledge and belief."; + next; + break; + case 3: + emotion e_swt; + mes "[Viorel]"; + mes "I understand your concern."; + mes "But I want to assure you that this Mutation does not harm or hurt your ^FF4800Homunculus^000000."; + next; + mes "[Viorel]"; + mes "On the contrary, the ^FF4800Homunculus^000000 of today are in pain from imperfection, unable to live up to their supposed potentials."; + mes "Moreover, those ^FF4800Homunculus^000000 were often abandoned."; + next; + mes "[Viorel]"; + mes "Don't get me wrong, I study the ^FF4800Homunculus^000000 because I love them."; + next; + break; + } + mes "[Viorel]"; + mes "Well, by the way..."; + mes "I have found this new mutation to be quite stable."; + next; + mes "[Viorel]"; + mes "^006400The technology exists,"; + mes "and they will likely have new"; + mes "skills when mutated...^000000"; + next; + mes "[Viorel]"; + mes "The minor side effect..."; + mes "^006400Their appearance will change^000000."; + mes "But I think you'll find that pretty satisfying."; + next; + mes "[Viorel]"; + mes "I quote from ^005DFFKassibian^000000, an expert in ^FF4800Homunculus^000000 techniques,"; + mes "^006400The truth is not in a single form~!^000000"; + mes "Ha ha."; + next; + emotion e_flash; + mes "[Viorel]"; + mes "I know it's a little abrupt, but..."; + mes "How about changing your ^FF4800Homunculus^000000 into something incredible with my marvelous achievement, the ^006400Homunculus Mutation System^000000?"; + next; + switch(select("Explore the ^006400Homunculus Mutation System^000000.:Cancel.")) { + case 1: + emotion e_no1; + mes "[Viorel]"; + mes "Good choice."; + mes "Success lurks outside the box of conventional thinking, right?"; + next; + mes "[Viorel]"; + mes "The first person to help with the research is ^005DFFJeyna^000000."; + mes "I'll send you to ^005DFFJeyna^000000."; + mes "There, you'll learn more about the new ^0000FFHomunculus^000000."; + close2; + setquest 4156; + erasequest 4155; + warp "que_house_s",63,41; + end; + case 2: + emotion e_dots; + mes "[Viorel]"; + mes "I don't see why you hesitate."; + mes "I am not trying to deceive you."; + mes "Maybe you need some time to think about it?"; + next; + switch(select("Think about it.:I'm just going to walk away.")) { + case 1: + mes "[Viorel]"; + mes "We'll talk in a bit then."; + close; + case 2: + emotion e_otl; + mes "[Viorel]"; + mes "Shame."; + mes "However, I respect your opinion."; + mes "I'll send you back to the ^8B4513Laboratory^000000."; + close2; + erasequest 4154; + erasequest 4155; + warp "job3_gen01",12,47; + end; + } + } + } else if (checkquest(4160) > -1) { + playbgm "33.mp3"; // Yuna Song + mes "[Viorel]"; + mes "The ^FF4800Homunculus^000000 I saw before has returned to its ^0000FFembryo^000000 state."; + mes "A little strange, but..."; + mes "You don't have to worry about it."; + next; + mes "[Viorel]"; + mes "By the way..."; + mes "I forgot to tell you something."; + mes "In order to stabilize the Mutation process, I need some materials first."; + next; + mes "[Viorel]"; + mes "Fortunately, you don't have to find them yourself because I have them here already.."; + mes "But, I'll need ^FF000050,000 zeny^000000, you know, as a service fee."; + next; + mes "[Viorel]"; + mes "I wish that I could do it for free but I'm not exactly made of money, you know."; + mes "That and I lack any investors to support my research at the moment."; + next; + mes "[Viorel]"; + mes "In fact, if I had enough zeny to continue my research, then I could solve a lot of my problems..."; + next; + mes "[Viorel]"; + mes "Anyways, you can try to do this with or without the stabilization process. It's all up to you."; + next; + mes "[Viorel]"; + mes "If you choose the unstable"; + mes "mutation, I can't guarentee what kind of Homunculus you're going to get."; + mes "Anyways, it's up to you."; + next; + switch(select("Mutation stabilization (50,000 zeny):Unstable mutation")) { + case 1: + if (Zeny < 50000) { + mes "[Viorel]"; + mes "I don't think you have ^FF000050 thousand Zeny^000000 with you right now."; + mes "Please bring enough Zeny."; + mes "I'll be waiting."; + mes "Want me to send you back to the ^8B4513Laboratory^000000?"; + next; + switch(select("No thanks.:Yes. Send me back to the Lab.")) { + case 1: + mes "[Viorel]"; + mes "Alright."; + mes "I'll see you in a bit."; + close; + case 2: + mes "[Viorel]"; + mes "Alright."; + mes "I'll be waiting at the ^8B4513Laboratory^000000."; + close2; + warp "job3_gen01",12,47; + end; + } + } + emotion e_no1; + playbgm "19.mp3"; // Under the Ground + mes "[Viorel]"; + mes "Good choice."; + mes "Choose from the different types of ^0000FFHomunculus^000000."; + next; + switch(select("Eira:Sera:Dieter:Bayeri:Eleanor")) { + case 1: + cutin "Mer_Eira_Card",3; + set .@Homunculus,6048; //MER_EIRA + break; + case 2: + cutin "Mer_Sera_Card",3; + set .@Homunculus,6050; //MER_SERA + break; + case 3: + cutin "Mer_Dieter_Card",3; + set .@Homunculus,6051; //MER_DIETER + break; + case 4: + cutin "Mer_Bayeri_Card",3; + set .@Homunculus,6049; //MER_BAYERI + break; + case 5: + cutin "Mer_Eleanor_Card",3; + set .@Homunculus,6052; //MER_ELEANOR + break; + } + mes "[Viorel]"; + mes "Are you sure?"; + next; + if(select("Yes.:No.") == 2) { + cutin "",255; + playbgm "33.mp3"; // Yuna Song + mes "[Viorel]"; + mes "I see."; + mes "Give it more time to think."; + close; + } + cutin "",255; + mes "[Viorel]"; + mes "Excellent!"; + mes "Let's get on with it."; + next; + specialeffect2 EF_BASH; + mes "[Viorel]"; + mes "Now focus~!"; + mes "You... need..."; + mes "... concentration."; + next; + specialeffect2 EF_PROVIDENCE; + mes "[Viorel]"; + mes "Good. Almost done!"; + next; + specialeffect2 EF_SUI_EXPLOSION; + set Zeny, Zeny - 50000; + hommutate .@Homunculus; + break; + case 2: + emotion e_hmm; + mes "[Viorel]"; + mes "So, your choice is the Unstable Mutation Process."; + mes "You believe in destiny?"; + mes "Seriously..."; + mes "Do you really wish to proceed"; + mes "with the process of random outcome?"; + next; + if(select("Go ahead. (Random Mutation):Cancel.") == 2) { + playbgm "33.mp3"; // Yuna Song + mes "[Viorel]"; + mes "I see."; + mes "Give it more time to think."; + close; + } + emotion e_dots; + mes "[Viorel]"; + mes "Hmm..."; + mes "The exploration of knowledge"; + mes "is full of surprises."; + mes "......."; + next; + emotion e_heh; + mes "[Viorel]"; + mes "Ha ha."; + mes "Hey, I feel like a Blacksmith!"; + mes "Now let's get on with it."; + next; + specialeffect2 EF_BASH; + mes "[Viorel]"; + mes "Now focus~!"; + mes "You... need..."; + mes "... concentration."; + next; + specialeffect2 EF_PRESSURE; + mes "[Viorel]"; + mes "Concentrate a little more!"; + next; + specialeffect2 EF_PROVIDENCE; + mes "[Viorel]"; + mes "Good. Almost done!"; + next; + specialeffect2 EF_SUI_EXPLOSION; + hommutate; + break; + } + erasequest 4160; + erasequest 4154; + emotion e_ho; + playbgm "64.mp3"; // One Fine Day + mes "[Viorel]"; + mes "Okay, Mutation Complete."; + mes "Phew... Didn't skip a heartbeat, did you?"; + next; + mes "[Viorel]"; + mes "Remember what ^005DFFKellasus^000000 said?"; + mes "To the doorstep of the truth..."; + mes "We must see for ourselves"; + mes "the path that leads to it."; + next; + mes "[Viorel]"; + mes "^0000FF" + strcharinfo(0) + "^000000,"; + mes "I haven't known you"; + mes "for a very long time,"; + mes "but I get the feeling that"; + mes "you'll achieve great things."; + next; + mes "[Viorel]"; + mes "Good luck on you adventures."; + mes "I hope that your new ^FF4800Homunculus^000000 will excel under your care."; + next; + mes "[Viorel]"; + mes "And don't you forget."; + mes "Our research"; + mes "has only just begun~!"; + close; + } else { + for(set .@i,4154; .@i<=4160; set .@i,.@i+1) { + if (checkquest(.@i) > -1) + erasequest .@i; + } + mes "[Viorel]"; + mes "Now that all the work is done, I ask you to take your leave."; + mes "I need to recuperate."; + close2; + warp "job3_gen01",12,47; + end; + } +} + +que_house_s,80,42,3 script Jeyna#homun_s 558,{ + if (checkquest(4156) > -1) { + playbgm "28.mp3"; // You're in Ruins + emotion e_gasp; + mes "[Jeyna]"; + mes "Welcome."; + mes "I just got word from ^005DFFViorel^000000 that you were coming."; + next; + emotion e_hmm; + mes "[Jeyna]"; + mes "By the way..."; + mes "Did he convince you to do something...?"; + mes "He does have a way with words."; + next; + mes "[Jeyna]"; + mes "He needs them because Alchemists are such awkward people."; + emotion e_sigh; + next; + mes "[Jeyna]"; + mes "Anyways~"; + mes "^0000FF"+strcharinfo(0)+"^000000 and ^005DFFViorel^000000 seem like two peas in a pod."; + next; + emotion e_heh; + mes "[Jeyna]"; + mes "Hahaha~ No offense."; + mes "I think it's a good thing."; + mes "Oh, yes."; + mes "You're here for the ^FF4800Homunculus^000000 Mutation."; + next; + mes "[Jeyna]"; + mes "While I do some preparation,"; + mes "why don't you take a look at that board?"; + mes "The ^006400Homunculus Mutation System^000000 has ^0000FF5 different types^000000 of new mutations."; + next; + emotion e_gasp,0,"Magic Board#homun_s"; + mes "[Jeyna]"; + mes "Your ^FF4800Homunculus^000000 can mutate into any of the 5 different forms."; + next; + emotion e_ic; + mes "[Jeyna]"; + mes "Let's see..."; + mes "The ^006400Homunculus Mutation System^000000 includes new evolutions of the normal ^0000FFHomunculus^000000."; + mes "After they mutate, all previously learned skills will also remain."; + next; + mes "[Jeyna]"; + mes "In other words..."; + mes "Even if you change the magic wielder ^FF4800Vanilmirth^000000 to a fighter type,"; + mes "skills such as Caprice will be"; + mes "^006400retained and usable even after Mutation^000000."; + next; + emotion e_gasp,0,"Magic Board#homun_s"; + mes "[Jeyna]"; + mes "Take a look at the Magic Board behind me and decide for yourself."; + close2; + setquest 4157; + erasequest 4156; + end; + } else if (checkquest(4157) > -1) { + emotion e_what; + mes "[Jeyna]"; + mes "Take a look at the board behind me, on the right."; + close2; + emotion e_gasp,0,"Magic Board#homun_s"; + end; + } else if (checkquest(4158) > -1) { + playbgm "28.mp3"; // You're in Ruins + disable_items; + mes "[Jeyna]"; + mes "Okay, I'm ready too."; + mes "In order to revert the process now, I need the Homunculus in its embryo form."; + next; + callsub L_CheckHomunculus; + if (checkweight(6415,1) == 0) { + mes "[Jeyna]"; + mes "But,"; + mes "You don't have enough space to carry an ^0000FFembryo^000000."; + mes "Please come back with enough space in your bag."; + next; + mes "[Jeyna]"; + mes "Please return to the ^8B4513Laboratory^000000."; + mes "You can find ^005DFFViorel^000000 at the ^8B4513Laboratory^000000 once you empty your bag."; + next; + mes "[Jeyna]"; + mes "When you're done with emptying your bag, ask ^005DFFViorel^000000 to send you back here."; + mes "Go on and empty your bag~!"; + close2; + warp "job3_gen01",12,47; + end; + } + mes "[Jeyna]"; + mes "Now's about time for a decision."; + mes "To go through the Mutation to the new ^0000FFHomunculus^000000 with the Homunculus Mutation System,"; + mes "you need to go through the process of regression to turn the Homunculus back to its ^0000FFembryo^000000 state."; + next; + mes "[Jeyna]"; + mes "And..."; + mes "^006400You cannot use the ability Call Homunculus until the process is complete.^000000"; + mes "It won't take long, so don't wander off."; + next; + mes "[Jeyna]"; + mes "So, please decide."; + mes "Do you want to proceed with the new ^0000FFHomunculus Mutation System^000000?"; + next; + switch(select("Yes, I do.:I need to think more.")) { + case 1: + if (checkhomcall() == 1) { + mes "[Jeyna]"; + mes "Oh, wait a minute."; + mes "To proceed with the Mutation, you need to wake up the Homunculus from the state of Vaporization."; + next; + mes "[Jeyna]"; + mes "Come back after you've done that."; + close; + } + emotion e_no1; + mes "[Jeyna]"; + mes "Good thinking."; + mes "It is unacceptable for Alchemists like us to fear challenge."; + next; + playbgm "01.mp3"; // Title + mes "[Jeyna]"; + mes "Now I need you to focus."; + next; + specialeffect2 EF_ABSORBSPIRITS; + mes "[Jeyna]"; + mes "We need to..."; + mes "Stabilize a little more."; + mes "......."; + next; + specialeffect2 EF_CURE; + mes "[Jeyna]"; + mes "In a few moments, the ^FF4800Homunculus^000000 will return to its embryo state."; + next; + specialeffect2 EF_HOLYHIT; + mes "[Jeyna]"; + mes "Into a special embryo..."; + next; + callsub L_CheckHomunculus; + specialeffect2 EF_BLESSING; + morphembryo; + setquest 4159; + erasequest 4158; + emotion e_ho; + mes "[Jeyna]"; + mes "Phew~ All done."; + mes "Hmm, its state is a little strange."; + next; + emotion e_heh; + mes "[Jeyna]"; + mes "I guess it'll be just fine."; + mes "Don't lose that ^0000FFStrange Embryo^000000."; + mes "Also..."; + next; + mes "[Jeyna]"; + mes "Don't do anything like changing jobs or anything like that before the process is over."; + mes "If so, you, ^0000FF"+strcharinfo(0)+"^000000 might lose all the abilities you have over the Homunculus."; + next; + mes "[Jeyna]"; + mes "All that concentration made me tired."; + mes "I'll just take a glass of water."; + close; + case 2: + playbgm "28.mp3"; // You're in Ruins + emotion e_sigh; + mes "[Jeyna]"; + mes "Maybe I shouldn't have asked in the first place."; + close; + } + } else if (checkquest(4159) > -1 || checkquest(4160) > -1) { + playbgm "28.mp3"; // You're in Ruins + mes "[Jeyna]"; + mes "^005DFFViorel^000000 will finish the mutation process."; + mes "Now it's my time to say good bye."; + next; + mes "[Jeyna]"; + mes "It was short, but it was nice to meet you."; + mes "We'll see each other again some time."; + next; + mes "[Jeyna]"; + mes "Best of luck~!"; + close2; + setquest 4160; + erasequest 4159; + warp "que_house_s",19,42; + end; + } else { + if (checkquest(4154) > -1) + erasequest 4154; + mes "[Jeyna]"; + mes "Hey, how did you get in here?"; + mes "Please get out. I'm changing~!"; + close2; + warp "job3_gen01",12,47; + end; + } + end; +L_CheckHomunculus: + if (gethominfo(6) < 99 || (gethominfo(1) < 6009 || gethominfo(1) > 6016)) { // Not level 99+ evolved Homunculus + mes "[Jeyna]"; + mes "Hey, wait."; + mes "The condition of the ^FF4800Homunculus^000000 is not suitable."; + mes "That was close."; + next; + mes "[Jeyna]"; + mes "To use the Homunculus Mutation System"; + mes "to change to the new"; + mes "^FF4800Homunculus^000000,"; + mes "the ^006400Homunculus must be above level 99 and evolved^000000."; + next; + mes "[Jeyna]"; + mes "Come back to ^005DFFViorel^000000 when you're ready."; + mes "I'll see you later then~!"; + close2; + erasequest 4154; + erasequest 4158; + warp "job3_gen01",12,47; + end; + } + return; +} + +// Magic Board +//============================================================ +que_house_s,83,47,3 script Magic Board#homun_s 857,{ + playbgm "26.mp3"; // Everlasting Wanderers + callfunc "F_HomMutateInfo","[Magic Board Posts]"; + mes "[Magic Board Posts]"; + mes ":: ^0000FFHomunculus^000000 research is"; + mes ":: so much fun."; + mes ":: Be an Alchemist"; + mes ":: who always enjoys"; + mes ":: one's research."; + next; + mes "[Magic Board Posts]"; + mes ":: Oh, and Viorel..."; + mes ":: About what you said"; + mes ":: yesterday..."; + mes "::"; + mes "::"; + next; + mes "--------------------------"; + mes "The rest is sealed because it seems to be a private message."; + close2; + if (checkquest(4157) > -1) { + setquest 4158; + erasequest 4157; + } + end; +} + +function script F_HomMutateInfo { + mes getarg(0); + mes ":: The ability of the mutated"; + mes ":: ^0000FFHomunculus^000000 clearly goes"; + mes ":: beyond the previous state."; + mes ":: In addition, its appearance"; + mes ":: will evolve as well."; + next; + mes getarg(0); + mes ":: ^0000FFHomunculus^000000 appearances of the"; + mes ":: new types can be classified"; + mes ":: based on different species."; + mes ":: Creatures of the same species"; + mes ":: generally have a similar"; + mes ":: appearance."; + next; + mes getarg(0); + mes ":: The category, appearance and"; + mes ":: ability of the ^0000FFHomunculus^000000"; + mes ":: via the Homunculus Mutation"; + mes ":: System are as follows:"; + next; + cutin "Mer_Eira_Card",3; + mes getarg(0); + mes ":: The first of the five"; + mes ":: is called ^FF4800Eira^000000."; + mes ":: Beautiful and graceful."; + next; + mes getarg(0); + mes ":: ^FF4800Eira^000000 uses"; + mes ":: ^006400Wind Element^000000 Magic Attacks and"; + mes ":: Support Skills."; + mes ":: It even has the ability"; + mes ":: to revive its"; + mes ":: fallen master."; + next; + mes getarg(0); + mes ":: ^FF4800Eira^000000 eats"; + mes ":: ^0000FFSmall Snow Flower^000000."; + mes ":: Surprising how it survives on"; + mes ":: such a small amount."; + mes ":: ^0000FFSmall Snow Flower^000000 can be bought"; + mes ":: from ^005DFFTaming Merchants^000000."; + next; + cutin "",255; + cutin "Mer_Sera_Card",3; + mes getarg(0); + mes ":: The second of the five"; + mes ":: is known as ^FF4800Sera^000000."; + mes ":: It looks just like ^FF0000Mistress^000000 but"; + mes ":: it doesn't run away."; + next; + mes getarg(0); + mes ":: ^FF4800Sera^000000"; + mes ":: specializes in ^006400Poison Attacks^000000."; + mes ":: Also, it uses distinct"; + mes ":: Support Skills using poisons."; + next; + mes getarg(0); + mes ":: ^FF4800Sera^000000 eats"; + mes ":: ^0000FFApple Pudding^000000."; + mes ":: It prefers sweet food."; + mes ":: ^0000FFApple Pudding^000000 can be bought"; + mes ":: from ^005DFFTaming Merchants^000000."; + next; + cutin "",255; + cutin "Mer_Dieter_Card",3; + mes getarg(0); + mes ":: The third of the five"; + mes ":: is ^FF4800Dieter^000000."; + mes ":: It looks unusual but it"; + mes ":: has a good demeanor."; + next; + mes getarg(0); + mes ":: ^FF4800Dieter^000000 uses"; + mes ":: ^FF0000Fire^000000 based Attacks and"; + mes ":: Support Skills."; + mes ":: It is just as fragile..."; + mes ":: ah, reliable, as it looks."; + next; + mes getarg(0); + mes ":: ^FF4800Dieter^000000 eats"; + mes ":: ^0000FFBig Cell^000000."; + mes ":: ^0000FFBig Cell^000000 can be bought"; + mes ":: from ^005DFFTaming Merchants^000000."; + next; + cutin "",255; + cutin "Mer_Bayeri_Card",3; + mes getarg(0); + mes ":: The fourth of the five"; + mes ":: is ^FF4800Bayeri^000000."; + mes ":: Bayeri has the form of a"; + mes ":: unicorn."; + next; + mes getarg(0); + mes ":: It has a powerful dash skill"; + mes ":: and uses ^006400Holy Element^000000 magic."; + mes ":: Unfortunately,"; + mes ":: they won't let you ride them."; + mes ":: Not all four-legged creatures"; + mes ":: can be ridden."; + next; + mes getarg(0); + mes ":: ^FF4800Bayeri^000000 eats"; + mes ":: ^0000FFFresh Plant^000000."; + mes ":: No matter how hungry it"; + mes ":: never feeds on rotten greens."; + mes ":: ^0000FFFresh Plant^000000 can be bought"; + mes ":: from ^005DFFTaming Merchants^000000."; + next; + cutin "",255; + cutin "Mer_Eleanor_Card",3; + mes getarg(0); + mes ":: The last of the five"; + mes ":: is ^FF4800Eleanor^000000."; + mes ":: It has a feminine appearance"; + mes ":: and outstanding physical skill."; + next; + mes getarg(0); + mes ":: ^FF4800Eleanor^000000"; + mes ":: uses ^006400Strike or Grapple Attacks^000000"; + mes ":: sequentially in battle."; + mes ":: Absolutely stunning."; + next; + mes getarg(0); + mes ":: ^FF4800Eleanor^000000 eats"; + mes ":: ^0000FFKid's Dumpling^000000."; + mes ":: Don't confuse it with a normal"; + mes ":: dumpling."; + mes ":: ^0000FFKid's Dumpling^000000 can be bought"; + mes ":: from ^005DFFTaming Merchants^000000."; + next; + cutin "",255; + return; +} + +// Books +//============================================================ +que_house_s,13,52,3 script Open Book#01homun_s 111,{ + switch(rand(1,7)) { + case 1: + mes "[Bookcase Notes]"; + mes "Insanity and Genius are the same in concept in that they are both abnormal phenomenon."; + mes "Observing the chemist ^005DFFMorgenstein^000000 of ^8B4513Geffen^000000, I consider them equal."; + next; + mes "[Bookcase Notes]"; + mes "Once I had to visit..."; + mes "the strange ^005DFFMorgenstein^000000 for research purposes."; + next; + mes "[Bookcase Notes]"; + mes "I had a meat stew before I met ^005DFFMorgenstein^000000,"; + mes "surprisingly enough, he muttered that he smelled meat even before I was close."; + next; + mes "[Bookcase Notes]"; + mes "I never thought that chemists had a great sense of smell."; + mes "The next time I give"; + mes "^005DFFMorgenstein^000000 a visit,"; + mes "I'll eat some other meal."; + close; + case 2: + mes "[Bookcase Notes]"; + mes "^005DFFDe Bris^000000 thinks the enthusiasm of Alchemists has lately dropped ..."; + next; + mes "[Bookcase Notes]"; + mes "He especially didn't like the fact that I was bound tightly to ^FF4800Homunculus^000000 research."; + mes "He didn't say such a thing when we studied together in ^8B4513Rune Midgarts^000000."; + next; + mes "[Bookcase Notes]"; + mes "One day, I'll show ^005DFFDe Bris^000000 my ^FF4800Homunculus^000000 research data."; + mes "I love watching him jump out of his skin.... I look forward to the day."; + close; + case 3: + mes "[Bookcase Notes]"; + mes "^005DFFDe Bris^000000' passion for the ^57007FGenetic^000000 arts is amazing."; + next; + mes "[Bookcase Notes]"; + mes "Recently, the Alchemist Union offered me the chance to join the ^57007FGenetic^000000 through a letter."; + mes "I wonder what ^005DFFDe Bris^000000 said to the union..."; + next; + mes "[Bookcase Notes]"; + mes "Well, I appreciate it..."; + mes "However, for me right now"; + mes "my research is of utmost priority."; + close; + case 4: + mes "[Bookcase Notes]"; + mes "There's something funny ^005DFFDarcia^000000 said to me."; + mes "It was about when ^005DFFJeyna^000000 first came to learn about potion combination......"; + next; + mes "[Bookcase Notes]"; + mes "She did good up to the stage of pouring water into the mixture."; + mes "She just had to put it into an empty bottle..."; + next; + mes "[Bookcase Notes]"; + mes "^005DFFDarcia^000000 watched what she would do with the last stage,"; + mes "and the confused ^005DFFJeyna^000000 drank the mixture out of the bowl and told her that it healed well."; + next; + mes "[Bookcase Notes]"; + mes "To think that even ^005DFFJeyna^000000,"; + mes "now a master of potion combination,"; + mes "had her rookie mistakes"; + mes "shows how hard it is to imagine"; + mes "and forecast one's past and future."; + close; + case 5: + mes "[Bookcase Notes]"; + mes "^005DFFVincent^000000, I think I did it."; + mes "I will never forget your words of courage "; + mes "and I am grateful that I now get to pay you back."; + next; + mes "[Bookcase Notes]"; + mes "It was indeed a long process."; + mes "When many of the union"; + mes "considered my research insignificant"; + mes "... Though I did not lose my belief"; + mes "it did heart deep inside."; + next; + mes "[Bookcase Notes]"; + mes "The few friends who believed me"; + mes "especially ^005DFFJeyna^000000"; + mes "and you ^005DFFVincent^000000 ..."; + mes "I am sincerely thankful with all my soul."; + next; + mes "[Bookcase Notes]"; + mes "They say that,"; + mes "the end justifies the means."; + mes "At first,"; + mes "I did not know what it meant..."; + next; + mes "[Bookcase Notes]"; + mes "Now I know."; + mes "I know how important it is"; + mes "to follow one's heart."; + next; + mes "[Bookcase Notes]"; + mes "I'll drop by very soon."; + mes "Be well until then."; + close; + case 6: + mes "[Bookcase Notes]"; + mes "A game called ^0000FFThe Epic Battle 2^000000, similar to chess, was intriguing."; + next; + mes "[Bookcase Notes]"; + mes "Some time ago, I met a ^0000FFFruit Seller^000000 who excelled in The Epic Battle 2."; + mes "He even overcame the infamous ^006400Grizzly Shockwave Strategy^000000 and ^006400God of Death Terror^000000 with ease."; + next; + mes "[Bookcase Notes]"; + mes "To overcome those in the early stages of the battle of the ^0000FFPriest Faction^000000..."; + mes "It is difficult for me, since I need to combine the pieces and use some luring skills."; + next; + mes "[Bookcase Notes]"; + mes "I wonder when I'll become a 3 Carat Diamond level player."; + close; + case 7: + mes "[Bookcase Notes]"; + mes "There are many Alchemists who like the ^FF4800Vanilmirth^000000."; + next; + mes "[Bookcase Notes]"; + mes "But I prefer the ^FF4800Amistr^000000."; + mes "It's cute when it wags its tale with those shiny eyes."; + next; + mes "[Bookcase Notes]"; + mes "My Amistr Jonathan is clever and mellow, making it ever so lovable."; + mes "We're good friends, aren't we Jonathan?"; + close; + } +} + +que_house_s,16,52,3 script Open Book#02homun_s 111,{ + switch(rand(1,8)) { + case 1: + mes "[Bookcase Notes]"; + mes "What should I write to ^005DFFDe Bris^000000."; + mes ":: To my noted "; + mes ":: Genetic friend De Bris."; + mes ":: How's Lighthalzen?"; + mes ":: Do they have enough of those"; + mes ":: cookies you oh so love?"; + next; + mes "[Bookcase Notes]"; + mes ":: I'll drop by soon"; + mes ":: with some cookies."; + mes ":: When we meet,"; + mes ":: I'll introduce you to my"; + mes ":: ^006400New Homunculus^000000."; + next; + mes "[Bookcase Notes]"; + mes ":: No need to be alert."; + mes ":: Unlike you,"; + mes ":: they aren't interested in "; + mes ":: what others have to eat."; + mes ":: I'll see you soon~!"; + mes ":: Dare close the door on me."; + close; + case 2: + mes "[Bookcase Notes]"; + mes "The last time I visited the Alchemist Union, there was an interesting debate on the table."; + mes "I think it was something to do with ^006400Negligence of Homunculus in public places^000000."; + next; + mes "[Bookcase Notes]"; + mes "While the master dozed off,"; + mes "one of the ^FF4800Homunculus^000000 off its leash"; + mes "caused some sort of problem."; + next; + mes "[Bookcase Notes]"; + mes "I will make sure that my Homunculus Jonathan..."; + mes "is trained well not to cause trouble around other people."; + close; + case 3: + mes "[Bookcase Notes]"; + mes "There's a new toy me and ^005DFFJeyna^000000 have grown fond of."; + mes "It's relatively new,"; + mes "called... ^0000FF'Helo'^000000, I think?"; + next; + mes "[Bookcase Notes]"; + mes "There was a related song to it, sung by some ^57007FMinstrel^000000."; + mes "The lyrics were something like ^006400'Ahhh~Ahh~Ahhhhhhhh'^000000."; + next; + mes "[Bookcase Notes]"; + mes "The entertainment itself is fun,"; + mes "but the music is also excellent,"; + mes "and when I listen to it"; + mes "it feels like my SP is restored significantly."; + next; + mes "[Bookcase Notes]"; + mes "I must say,"; + mes "entertainment is crucial when resting"; + mes "to boost morale for research."; + mes "^006400For Homunculus~!^000000"; + close; + case 4: + mes "[Bookcase Notes]"; + mes "From what I heard from the union member"; + mes "^005DFFParmy^000000,"; + mes "^005DFFRaspuchin^000000 is still his own weird self."; + next; + mes "[Bookcase Notes]"; + mes "It may not be such a good idea"; + mes "to drive those energetic souls"; + mes "coming to change jobs"; + mes "with such enthusiasm."; + close; + case 5: + mes "[Bookcase Notes]"; + mes "A friend of mine who was into painting,"; + mes "suggested making a called"; + mes "^0000FFMUTATIONER^000000"; + mes "after he heard about my research"; + mes "and my works."; + next; + mes "[Bookcase Notes]"; + mes "The story begins..."; + mes "With an alien"; + mes "^FF4800Homunculus^000000"; + mes "visiting our world."; + next; + mes "[Bookcase Notes]"; + mes "The visiting alien"; + mes "^FF4800Homunculus^000000 can survive"; + mes "without a master"; + mes "and it could change into"; + mes "various creatures that"; + mes "roam our world."; + next; + mes "[Bookcase Notes]"; + mes "These alien^FF4800Homunculus^000000"; + mes "have two opposing factions"; + mes "divided by political differences."; + mes "In our world, we call them"; + mes "^006400Aut-homun^000000 and "; + mes "^006400Decept-homun^000000"; + next; + mes "[Bookcase Notes]"; + mes "The ^006400Aut-homun^000000 are our friends."; + mes "Their leader,"; + mes "called ^005DFFOptimus Poring^000000,"; + mes "is built and so cool"; + mes "for a poring,"; + mes "and it summons a cart at will!"; + next; + mes "[Bookcase Notes]"; + mes "The opposing side, the ^006400Decept-homun^000000,"; + mes "is led by ^005DFFMegatroll^000000"; + mes "and they use all means "; + mes "to destroy our world."; + next; + mes "[Bookcase Notes]"; + mes "The hero of this story"; + mes "is one from ^8B4513Alberta^000000 called ^005DFFJam Wicky^000000,"; + mes "who meets ^005DFFOptimus Poring^000000"; + mes "while shopping for a cart,"; + mes "as if it was his destiny."; + next; + mes "[Bookcase Notes]"; + mes "And so thus"; + mes "unfolds an epic battle"; + mes "in the ^8B4513Moroc Desert^000000"; + mes "where the fate of our world"; + mes "lies in his hands..."; + next; + mes "[Bookcase Notes]"; + mes "Enough of that~!"; + mes "The rest of the story can be"; + mes "checked in the published copy."; + mes "^0000FFMUTATIONER^000000"; + mes "It's going to be awesome~!"; + close; + case 6: + mes "[Bookcase Notes]"; + mes "The Union sent a special gift to its members."; + mes "It's called a ^0000FFHigh Clip 4^000000."; + next; + mes "[Bookcase Notes]"; + mes "It is originally used as a tool to allow easy whispering between members, but it also has other useful functions."; + next; + mes "[Bookcase Notes]"; + mes "A guild invented this. I recall that their emblem had an image of an apple."; + close; + case 7: + mes "[Bookcase Notes]"; + mes "Homunculus is indeed worthy."; + mes "However, like everyone else, I sometimes question its meaning and future."; + next; + mes "[Bookcase Notes]"; + mes "I believe that life given by nature was supposed to be used for oneself."; + mes "However..."; + next; + mes "[Bookcase Notes]"; + mes "The research to give the Homunculus life is, in reality, for the benefit of man."; + mes "Perhaps mankind is not ready ethically to create life."; + close; + case 8: + mes "[Bookcase Notes]"; + mes "Some time ago, ^005DFFJeyna^000000 introduced me to someone."; + mes "She is from ^8B4513Geffen^000000,"; + mes "and she introduced herself as a ^005DFFChicken Researcher^000000."; + next; + mes "[Bookcase Notes]"; + mes "She is an expert on something called the ^006400Legendary Bijofnil^000000."; + mes "She finds it offensive that people think that the Bijofnil is a hawk."; + next; + mes "[Bookcase Notes]"; + mes "She said something about somewhere in ^8B4513Hvergilmir's Fountain^000000"; + mes "there exists a ^005DFFtalking chicken^000000 and other stories..."; + mes "Well, it went on like that"; + mes "and it was interesting."; + close; + } +} + +// Notifiers +//============================================================ +que_house_s,11,52,3 script #03homun_s 111,{ + end; +OnInit: + initnpctimer; + end; +OnTimer6000: + emotion e_gasp; + end; +OnTimer7000: + emotion e_gasp,0,"#04homun_s"; + stopnpctimer; + initnpctimer; + end; +} + +que_house_s,14,52,3 script #04homun_s 111,{ + end; +} + +// Researcher's Pet +//============================================================ +que_house_s,24,46,3 script Jonathan#homun_s 6002,{ + end; +} + +que_house_s,23,46,3 script #05homun_s 111,{ + emotion e_no,0,"Jonathan#homun_s"; + if (gethominfo(1) < 6048 || gethominfo(1) > 6052) { // Not mutated Homunculus-S + mes "[Jonathan]"; + mes "Hwang~ Hwang!"; + next; + mes ":: It seems to be Viorel's"; + mes ":: Homunculus."; + mes ":: It is wearing a small necklace"; + mes ":: with the name Jonathan engraved"; + mes ":: on it."; + close; + } else { + mes "[Jonathan]"; + mes "Hwang~?!"; + next; + emotion e_swt2,0,"Jonathan#homun_s"; + mes "[Jonathan]"; + mes "*Sniff* ..."; + next; + mes ":: This Amistr"; + mes ":: called Jonathan"; + mes ":: seems to be surprised by my"; + mes ":: new Homunculus."; + close; + } +} \ No newline at end of file diff --git a/npc/re/scripts.conf b/npc/re/scripts.conf index e3b683a34..86cf10d28 100644 --- a/npc/re/scripts.conf +++ b/npc/re/scripts.conf @@ -88,7 +88,7 @@ npc: npc/re/quests/eden/eden_service.txt npc: npc/re/quests/eden/eden_tutorial.txt // -------------------------------------------------------------- //npc: npc/re/quests/cupet.txt -npc: npc/re/quests/homu_s.txt +npc: npc/re/quests/homun_s.txt npc: npc/re/quests/magic_books.txt npc: npc/re/quests/mrsmile.txt npc: npc/re/quests/pile_bunker.txt 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/clif.c b/src/map/clif.c index 57830478d..0c21c796c 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1379,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) ; 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.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/pc.c b/src/map/pc.c index ffc3427c7..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); 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 248e19e77..82a584ce2 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -7516,7 +7516,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; -- cgit v1.2.3-70-g09d2 From 646f7e2f4ea4bd6b07e66d2949817ebdc18f3484 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 10 Oct 2013 18:59:10 -0300 Subject: Added code to disable auction for clients it is no longer stable Regarding http://hercules.ws/board/topic/414-auction-feature-all-screwed-up Signed-off-by: shennetsind --- conf/battle/feature.conf | 6 +++++- conf/messages.conf | 3 +++ src/map/atcommand.c | 8 ++++++-- src/map/battle.c | 10 ++++++++++ src/map/battle.h | 1 + src/map/clif.c | 16 ++++++++++++++++ 6 files changed, 41 insertions(+), 3 deletions(-) (limited to 'src/map') diff --git a/conf/battle/feature.conf b/conf/battle/feature.conf index 2f60f1fff..352163c8e 100644 --- a/conf/battle/feature.conf +++ b/conf/battle/feature.conf @@ -21,4 +21,8 @@ feature.atcommand_suggestions: off // Banking (Note 1) // Requires: 2013-07-24aRagexe or later -feature.banking: on \ No newline at end of file +feature.banking: on + +// Auction (Note 1) +// Feature became unstable on clients 2012 onwards (exact date not known) +feature.auction: off \ No newline at end of file diff --git a/conf/messages.conf b/conf/messages.conf index 4b0549bf6..4a08c0893 100644 --- a/conf/messages.conf +++ b/conf/messages.conf @@ -1523,5 +1523,8 @@ 1482: You can't withdraw that much money 1483: Banking is disabled +//src/map/atcommand.c::ACMD(auction) +1484: Auction is disabled + //Custom translations import: conf/import/msg_conf.txt diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 4933256a2..10c96e317 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -7956,10 +7956,14 @@ ACMD(feelreset) /*========================================== * AUCTION SYSTEM *------------------------------------------*/ -ACMD(auction) -{ +ACMD(auction) { nullpo_ret(sd); + if( !battle_config.feature_auction ) { + clif->colormes(sd->fd,COLOR_RED,msg_txt(1484)); + return false; + } + clif->auction_openwindow(sd); return true; diff --git a/src/map/battle.c b/src/map/battle.c index a0e4e7ebc..91cb98d14 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -6475,6 +6475,8 @@ static const struct _battle_data { { "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, }, + { "feature.auction", &battle_config.feature_auction, 0, 0, 2, }, + }; #ifndef STATS_OPT_OUT @@ -6705,6 +6707,14 @@ void battle_adjust_conf(void) { } #endif +#if PACKETVER > 20120000 /* exact date not known */ + if( battle_config.feature_auction == 1 ) { + ShowWarning("conf/battle/feature.conf:feature.auction is enabled but it is not stable on PACKETVER "EXPAND_AND_QUOTE(PACKETVER)", disabling...\n"); + ShowWarning("conf/battle/feature.conf:feature.auction change value to '2' to silence this warning and maintain it enabled\n"); + battle_config.feature_auction = 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 f1fa6ddc1..533fa40b0 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -462,6 +462,7 @@ struct Battle_Config { int guild_notice_changemap; int feature_banking; + int feature_auction; } battle_config; // Dammage delayed info diff --git a/src/map/clif.c b/src/map/clif.c index 0c21c796c..d1f416146 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -14988,6 +14988,9 @@ void clif_Auction_openwindow(struct map_session_data *sd) if( sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading ) return; + if( !battle_config.feature_auction ) + return; + WFIFOHEAD(fd,packet_len(0x25f)); WFIFOW(fd,0) = 0x25f; WFIFOL(fd,2) = 0; @@ -15077,6 +15080,9 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd) int amount = RFIFOL(fd,4); // Always 1 struct item_data *item; + if( !battle_config.feature_auction ) + return; + if( sd->auction.amount > 0 ) sd->auction.amount = 0; @@ -15152,6 +15158,9 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) struct auction_data auction; struct item_data *item; + if( !battle_config.feature_auction ) + return; + auction.price = RFIFOL(fd,2); auction.buynow = RFIFOL(fd,6); auction.hours = RFIFOW(fd,10); @@ -15283,6 +15292,9 @@ void clif_parse_Auction_search(int fd, struct map_session_data* sd) short type = RFIFOW(fd,2), page = RFIFOW(fd,32); int price = RFIFOL(fd,4); // FIXME: bug #5071 + if( !battle_config.feature_auction ) + return; + clif->pAuction_cancelreg(fd, sd); safestrncpy(search_text, (char*)RFIFOP(fd,8), sizeof(search_text)); @@ -15298,6 +15310,10 @@ void clif_parse_Auction_search(int fd, struct map_session_data* sd) void clif_parse_Auction_buysell(int fd, struct map_session_data* sd) { short type = RFIFOW(fd,2) + 6; + + if( !battle_config.feature_auction ) + return; + clif->pAuction_cancelreg(fd, sd); intif->Auction_requestlist(sd->status.char_id, type, 0, "", 1); -- cgit v1.2.3-70-g09d2 From df68a8cecdb52de34a348ba63f27862678a446a7 Mon Sep 17 00:00:00 2001 From: Haru Date: Fri, 11 Oct 2013 02:03:52 +0200 Subject: Fixed the 'Received unsupported packet' message when using obfuscation - Now it reports the correctly decoded packet instead of 0x0000 - Follow-up to 38b8bf02b69f3841fd496f8d628bf71040c99709, thanks to Ind for bringing this up Signed-off-by: Haru --- src/map/clif.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'src/map') diff --git a/src/map/clif.c b/src/map/clif.c index d1f416146..823a44956 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -17825,10 +17825,6 @@ unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) { unsigned short clif_parse_cmd_normal( int fd, struct map_session_data *sd ) { unsigned short cmd = RFIFOW(fd,0); - // filter out invalid / unsupported packets - if( cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packet_db[cmd].len == 0 ) - return 0; - return cmd; } unsigned short clif_parse_cmd_decrypt( int fd, struct map_session_data *sd ) { @@ -17836,10 +17832,6 @@ unsigned short clif_parse_cmd_decrypt( int fd, struct map_session_data *sd ) { cmd = clif->decrypt_cmd(cmd, sd); - // filter out invalid / unsupported packets - if( cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packet_db[cmd].len == 0 ) - return 0; - return cmd; } unsigned short clif_parse_cmd_optional( int fd, struct map_session_data *sd ) { @@ -17914,7 +17906,10 @@ int clif_parse(int fd) { else parse_cmd_func = clif->parse_cmd; - if( !( cmd = parse_cmd_func(fd,sd) ) ) { + cmd = parse_cmd_func(fd,sd); + + // filter out invalid / unsupported packets + if( cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packet_db[cmd].len == 0 ) { ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x (0x%04x), %d bytes received), disconnecting session #%d.\n", cmd, RFIFOW(fd,0), RFIFOREST(fd), fd); #ifdef DUMP_INVALID_PACKET ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); -- cgit v1.2.3-70-g09d2 From cb3c97b72bb6a2aad6e87922facdf7e2dc157492 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Fri, 11 Oct 2013 13:20:07 -0300 Subject: Follow up 646f7e2f4ea4bd6b07e66d2949817ebdc18f3484 Adjusted range, thanks to haruna realising the feature had been fixed on recent clients. Special Thanks to ossi0110 for testing the feature on multiple 2013 clients, which allowed us to restrict the date range more accurately. Signed-off-by: shennetsind --- conf/battle/feature.conf | 3 ++- src/map/battle.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/map') diff --git a/conf/battle/feature.conf b/conf/battle/feature.conf index 352163c8e..37b05c657 100644 --- a/conf/battle/feature.conf +++ b/conf/battle/feature.conf @@ -24,5 +24,6 @@ feature.atcommand_suggestions: off feature.banking: on // Auction (Note 1) -// Feature became unstable on clients 2012 onwards (exact date not known) +// Feature became unstable on clients 2012 onwards (exact date not known), +// it has been fixed on clients 2013-05-15 onwards however. feature.auction: off \ No newline at end of file diff --git a/src/map/battle.c b/src/map/battle.c index 91cb98d14..ef62eb1d2 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -6707,7 +6707,7 @@ void battle_adjust_conf(void) { } #endif -#if PACKETVER > 20120000 /* exact date not known */ +#if PACKETVER > 20120000 && PACKETVER < 20130515 /* exact date (when it started) not known */ if( battle_config.feature_auction == 1 ) { ShowWarning("conf/battle/feature.conf:feature.auction is enabled but it is not stable on PACKETVER "EXPAND_AND_QUOTE(PACKETVER)", disabling...\n"); ShowWarning("conf/battle/feature.conf:feature.auction change value to '2' to silence this warning and maintain it enabled\n"); -- cgit v1.2.3-70-g09d2