diff options
author | zephyrus <zephyrus@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2008-11-16 16:14:30 +0000 |
---|---|---|
committer | zephyrus <zephyrus@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2008-11-16 16:14:30 +0000 |
commit | 8d5fe8a2562df4eb5e6eca2fb161514d9f6a7e9d (patch) | |
tree | 8d024104aa15ed6c2aa5070bd03ed7790a2afd90 | |
parent | 9b1e41499d17bb424414a7821e74a53c6d3e3f74 (diff) | |
download | hercules-8d5fe8a2562df4eb5e6eca2fb161514d9f6a7e9d.tar.gz hercules-8d5fe8a2562df4eb5e6eca2fb161514d9f6a7e9d.tar.bz2 hercules-8d5fe8a2562df4eb5e6eca2fb161514d9f6a7e9d.tar.xz hercules-8d5fe8a2562df4eb5e6eca2fb161514d9f6a7e9d.zip |
- Item Rental System.
Script Usage:
- rentitem <itemid>,<seconds>;
- rentitem <itemname>,<seconds>;
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@13370 54d463be-8e91-2dee-dedb-b68131a5f0ec
-rw-r--r-- | npc/guild/payg_cas05.txt | 3 | ||||
-rw-r--r-- | sql-files/main.sql | 4 | ||||
-rw-r--r-- | sql-files/upgrade_svn13370_inventory.sql | 6 | ||||
-rw-r--r-- | src/char_sql/char.c | 75 | ||||
-rw-r--r-- | src/common/mmo.h | 1 | ||||
-rw-r--r-- | src/map/clif.c | 45 | ||||
-rw-r--r-- | src/map/clif.h | 4 | ||||
-rw-r--r-- | src/map/mail.c | 14 | ||||
-rw-r--r-- | src/map/pc.c | 115 | ||||
-rw-r--r-- | src/map/pc.h | 6 | ||||
-rw-r--r-- | src/map/script.c | 76 | ||||
-rw-r--r-- | src/map/storage.c | 35 | ||||
-rw-r--r-- | src/map/trade.c | 7 | ||||
-rw-r--r-- | src/map/unit.c | 1 |
14 files changed, 317 insertions, 75 deletions
diff --git a/npc/guild/payg_cas05.txt b/npc/guild/payg_cas05.txt index acf5eb2c2..b0f48616f 100644 --- a/npc/guild/payg_cas05.txt +++ b/npc/guild/payg_cas05.txt @@ -50,7 +50,8 @@ pay_gld,208,268,4 script Bamboo Grove Hill#f5-3::BambooGroveHill2 722,{ if (select("Return to the guild castle.:Quit.") == 1) { if (getcharid(2) == GetCastleData("payg_cas05",1)) { warp "payg_cas05",276,227; - //warp "payg_cas05",243;27; end; + //warp "payg_cas05",243;27; + end; } } close; diff --git a/sql-files/main.sql b/sql-files/main.sql index 2e2ea2cda..f62b65baf 100644 --- a/sql-files/main.sql +++ b/sql-files/main.sql @@ -41,6 +41,7 @@ CREATE TABLE IF NOT EXISTS `cart_inventory` ( `card1` int(11) NOT NULL default '0', `card2` int(11) NOT NULL default '0', `card3` int(11) NOT NULL default '0', + `expire_time` int(11) unsigned NOT NULL default '0', PRIMARY KEY (`id`), KEY `char_id` (`char_id`) ) ENGINE=MyISAM; @@ -309,6 +310,7 @@ CREATE TABLE IF NOT EXISTS `guild_storage` ( `card1` smallint(11) NOT NULL default '0', `card2` smallint(11) NOT NULL default '0', `card3` smallint(11) NOT NULL default '0', + `expire_time` int(11) unsigned NOT NULL default '0', PRIMARY KEY (`id`), KEY `guild_id` (`guild_id`) ) ENGINE=MyISAM; @@ -369,6 +371,7 @@ CREATE TABLE IF NOT EXISTS `inventory` ( `card1` smallint(11) NOT NULL default '0', `card2` smallint(11) NOT NULL default '0', `card3` smallint(11) NOT NULL default '0', + `expire_time` int(11) unsigned NOT NULL default '0', PRIMARY KEY (`id`), KEY `char_id` (`char_id`) ) ENGINE=MyISAM; @@ -634,6 +637,7 @@ CREATE TABLE IF NOT EXISTS `storage` ( `card1` smallint(11) NOT NULL default '0', `card2` smallint(11) NOT NULL default '0', `card3` smallint(11) NOT NULL default '0', + `expire_time` int(11) unsigned NOT NULL default '0', PRIMARY KEY (`id`), KEY `account_id` (`account_id`) ) ENGINE=MyISAM; diff --git a/sql-files/upgrade_svn13370_inventory.sql b/sql-files/upgrade_svn13370_inventory.sql new file mode 100644 index 000000000..dc4d5ff8a --- /dev/null +++ b/sql-files/upgrade_svn13370_inventory.sql @@ -0,0 +1,6 @@ +-- Creates expire_time column on Inventory
+
+ALTER TABLE `inventory` ADD COLUMN `expire_time` INT(11) UNSIGNED NOT NULL DEFAULT '0';
+ALTER TABLE `cart_inventory` ADD COLUMN `expire_time` INT(11) UNSIGNED NOT NULL DEFAULT '0';
+ALTER TABLE `storage` ADD COLUMN `expire_time` INT(11) UNSIGNED NOT NULL DEFAULT '0';
+ALTER TABLE `guild_storage` ADD COLUMN `expire_time` INT(11) UNSIGNED NOT NULL DEFAULT '0';
diff --git a/src/char_sql/char.c b/src/char_sql/char.c index 16392eef5..edfc19498 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -529,6 +529,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) (p->sword_calls != cp->sword_calls) || (p->sword_faith != cp->sword_faith) ) { mercenary_owner_tosql(char_id, p); + strcat(save_status, " mercenary"); } //memo points @@ -697,7 +698,7 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit // it significantly reduces cpu load on the database server. StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`"); + StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`"); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`", j); StringBuf_Printf(&buf, " FROM `%s` WHERE `%s`='%d'", tablename, selectoption, id); @@ -712,15 +713,16 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit return 1; } - SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 1, SQLDT_SHORT, &item.nameid, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 3, SQLDT_USHORT, &item.equip, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &item.identify, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &item.refine, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 1, SQLDT_SHORT, &item.nameid, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 3, SQLDT_USHORT, &item.equip, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &item.identify, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &item.refine, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, 0, NULL, NULL); for( j = 0; j < MAX_SLOTS; ++j ) - SqlStmt_BindColumn(stmt, 7+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 8+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL); // bit array indicating which inventory items have already been matched flag = (bool*) aCallocA(max, sizeof(bool)); @@ -746,14 +748,15 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit items[i].equip == item.equip && items[i].identify == item.identify && items[i].refine == item.refine && - items[i].attribute == item.attribute ) + items[i].attribute == item.attribute && + items[i].expire_time == item.expire_time ) ; //Do nothing. else { // update all fields. StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d'", - tablename, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute); + StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u'", + tablename, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`=%d", j, items[i].card[j]); StringBuf_Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id); @@ -775,7 +778,7 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit SqlStmt_Free(stmt); StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`", tablename, selectoption); + StringBuf_Printf(&buf, "INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`", tablename, selectoption); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`", j); StringBuf_AppendStr(&buf, ") VALUES "); @@ -793,8 +796,8 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit else found = true; - StringBuf_Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d'", - id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute); + StringBuf_Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u'", + id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", '%d'", items[i].card[j]); StringBuf_AppendStr(&buf, ")"); @@ -1017,7 +1020,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything //read inventory //`inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`) StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`"); + StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`"); for( i = 0; i < MAX_SLOTS; ++i ) StringBuf_Printf(&buf, ", `card%d`", i); StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", inventory_db, MAX_INVENTORY); @@ -1025,26 +1028,28 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_SHORT, &tmp_item.nameid, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 3, SQLDT_USHORT, &tmp_item.equip, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL) ) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_SHORT, &tmp_item.nameid, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 3, SQLDT_USHORT, &tmp_item.equip, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL) ) SqlStmt_ShowDebug(stmt); for( i = 0; i < MAX_SLOTS; ++i ) - if( SQL_ERROR == SqlStmt_BindColumn(stmt, 7+i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) ) + if( SQL_ERROR == SqlStmt_BindColumn(stmt, 8+i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) ) SqlStmt_ShowDebug(stmt); for( i = 0; i < MAX_INVENTORY && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) memcpy(&p->inventory[i], &tmp_item, sizeof(tmp_item)); + strcat(t_msg, " inventory"); //read cart //`cart_inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`) StringBuf_Clear(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`"); + StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`"); for( j = 0; j < MAX_SLOTS; ++j ) StringBuf_Printf(&buf, ", `card%d`", j); StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", cart_db, MAX_CART); @@ -1052,16 +1057,17 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_SHORT, &tmp_item.nameid, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 3, SQLDT_USHORT, &tmp_item.equip, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL) ) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_SHORT, &tmp_item.nameid, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_item.amount, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 3, SQLDT_USHORT, &tmp_item.equip, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &tmp_item.identify, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &tmp_item.refine, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &tmp_item.attribute, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &tmp_item.expire_time, 0, NULL, NULL) ) SqlStmt_ShowDebug(stmt); for( i = 0; i < MAX_SLOTS; ++i ) - if( SQL_ERROR == SqlStmt_BindColumn(stmt, 7+i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) ) + if( SQL_ERROR == SqlStmt_BindColumn(stmt, 8+i, SQLDT_SHORT, &tmp_item.card[i], 0, NULL, NULL) ) SqlStmt_ShowDebug(stmt); for( i = 0; i < MAX_CART && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) @@ -1125,11 +1131,12 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything ShowWarning("mmo_char_fromsql: ignoring invalid hotkey (hotkey=%d,type=%u,id=%u,lv=%u) of character %s (AID=%d,CID=%d)\n", hotkey_num, tmp_hotkey.type, tmp_hotkey.id, tmp_hotkey.lv, p->name, p->account_id, p->char_id); } strcat(t_msg, " hotkeys"); +#endif /* Mercenary Owner DataBase */ mercenary_owner_fromsql(char_id, p); + strcat(t_msg, " mercenary"); -#endif if (save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfuly! SqlStmt_Free(stmt); diff --git a/src/common/mmo.h b/src/common/mmo.h index 94c72690f..3ba9d7264 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -155,6 +155,7 @@ struct item { char refine; char attribute; short card[MAX_SLOTS]; + unsigned int expire_time; }; struct point { diff --git a/src/map/clif.c b/src/map/clif.c index 0a4200396..81902f4e4 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1419,17 +1419,22 @@ int clif_selllist(struct map_session_data *sd) fd=sd->fd; WFIFOHEAD(fd, MAX_INVENTORY * 10 + 4); WFIFOW(fd,0)=0xc7; - for(i=0;i<MAX_INVENTORY;i++) { - if(sd->status.inventory[i].nameid > 0 && sd->inventory_data[i]) { - if (!itemdb_cansell(&sd->status.inventory[i], pc_isGM(sd))) + for( i = 0; i < MAX_INVENTORY; i++ ) + { + if( sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] ) + { + if( !itemdb_cansell(&sd->status.inventory[i], pc_isGM(sd)) ) continue; + if( sd->status.inventory[i].expire_time ) + continue; // Cannot Sell Rental Items + val=sd->inventory_data[i]->value_sell; - if (val < 0) + if( val < 0 ) continue; WFIFOW(fd,4+c*10)=i+2; WFIFOL(fd,6+c*10)=val; - if (!sd->inventory_data[i]->flag.value_notoc) + if( !sd->inventory_data[i]->flag.value_notoc ) val=pc_modifysellvalue(sd,val); WFIFOL(fd,10+c*10)=val; c++; @@ -11992,12 +11997,12 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd) return; } - if( !pc_candrop(sd, &sd->status.inventory[idx]) || !sd->status.inventory[idx].identify ) + if( !pc_candrop(sd, &sd->status.inventory[idx]) || !sd->status.inventory[idx].identify || sd->status.inventory[idx].expire_time ) { // Quest Item or something else clif_Auction_setitem(sd->fd, idx, true); return; } - + sd->auction.index = idx; sd->auction.amount = amount; clif_Auction_setitem(fd, idx + 2, false); @@ -12207,7 +12212,10 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) amount = RFIFOW(fd,4); points = RFIFOL(fd,6); // Not Implemented. Should be 0 - fail = npc_cashshop_buy(sd, nameid, amount, points); + if( sd->state.trading || !sd->npc_shopid ) + fail = 1; + else + fail = npc_cashshop_buy(sd, nameid, amount, points); WFIFOHEAD(fd,12); WFIFOW(fd,0) = 0x289; @@ -12636,6 +12644,27 @@ void clif_mercenary_message(int fd, int message) WFIFOSET(fd,4); } +/*------------------------------------------ + * Rental System Messages + *------------------------------------------*/ +void clif_rental_time(int fd, int nameid, int seconds) +{ // '<ItemName>' item will disappear in <seconds/60> minutes. + WFIFOHEAD(fd,8); + WFIFOW(fd,0) = 0x0298; + WFIFOW(fd,2) = nameid; + WFIFOL(fd,4) = seconds; + WFIFOSET(fd,8); +} + +void clif_rental_expired(int fd, int nameid) +{ // '<ItemName>' item has been deleted from the Inventory + WFIFOHEAD(fd,6); + WFIFOW(fd,0) = 0x0299; + WFIFOW(fd,2) = 0; + WFIFOW(fd,4) = nameid; + WFIFOSET(fd,6); +} + /*========================================== * パケットデバッグ *------------------------------------------*/ diff --git a/src/map/clif.h b/src/map/clif.h index 5c28d65a2..1f79445ee 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -445,4 +445,8 @@ void clif_mercenary_skillblock(struct map_session_data *sd); void clif_mercenary_message(int fd, int message); void clif_mercenary_updatestatus(struct map_session_data *sd, int type); +// RENTAL SYSTEM +void clif_rental_time(int fd, int nameid, int seconds); +void clif_rental_expired(int fd, int nameid); + #endif /* _CLIF_H_ */ diff --git a/src/map/mail.c b/src/map/mail.c index d77dbe6b4..072368838 100644 --- a/src/map/mail.c +++ b/src/map/mail.c @@ -69,16 +69,14 @@ int mail_removezeny(struct map_session_data *sd, short flag) unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) { - if (idx == 0) + if( idx == 0 ) { // Zeny Transfer - if( amount < 0 ) - return 0; + if( amount < 0 || !pc_can_give_items(pc_isGM(sd)) ) + return 1; + if( amount > sd->status.zeny ) amount = sd->status.zeny; - if( !pc_can_give_items(pc_isGM(sd)) ) - amount = 0; - sd->mail.zeny = amount; // clif_updatestatus(sd, SP_ZENY); return 0; @@ -94,6 +92,8 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) return 1; if( !pc_candrop(sd, &sd->status.inventory[idx]) ) return 1; + if( sd->status.inventory[idx].expire_time ) + return 1; // Rental System sd->mail.index = idx; sd->mail.nameid = sd->status.inventory[idx].nameid; @@ -174,7 +174,7 @@ void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg) nullpo_retv(sd); nullpo_retv(msg); - // Item recieve (due to failure) + // Item recieve (due to failure) if(log_config.enable_logs&0x2000) log_pick_pc(sd, "E", msg->item.nameid, msg->item.amount, &msg->item); diff --git a/src/map/pc.c b/src/map/pc.c index 62a875e13..4efdff069 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -281,6 +281,88 @@ int pc_setrestartvalue(struct map_session_data *sd,int type) } /*========================================== + Rental System + *------------------------------------------*/ +static int pc_inventory_rental_end(int tid, unsigned int tick, int id, intptr data) +{ + struct map_session_data *sd = map_id2sd(id); + if( sd == NULL ) + return 0; + if( tid != sd->rental_timer ) + { + ShowError("pc_inventory_rental_end: invalid timer id.\n"); + return 0; + } + + pc_inventory_rentals(sd); + return 1; +} + +int pc_inventory_rental_clear(struct map_session_data *sd) +{ + if( sd->rental_timer != INVALID_TIMER ) + { + delete_timer(sd->rental_timer, pc_inventory_rental_end); + sd->rental_timer = -1; + } + + return 1; +} + +void pc_inventory_rentals(struct map_session_data *sd) +{ + int i, c = 0; + unsigned int expire_tick, next_tick = UINT_MAX; + + for( i = 0; i < MAX_INVENTORY; i++ ) + { + if( sd->status.inventory[i].nameid == 0 ) + continue; // Nothing here + if( sd->status.inventory[i].expire_time == 0 ) + continue; + + if( sd->status.inventory[i].expire_time <= time(NULL) ) + { + clif_rental_expired(sd->fd, sd->status.inventory[i].nameid); + pc_delitem(sd, i, sd->status.inventory[i].amount, 0); + } + else + { + expire_tick = (unsigned int)(sd->status.inventory[i].expire_time - time(NULL)) * 1000; + clif_rental_time(sd->fd, sd->status.inventory[i].nameid, (int)(expire_tick / 1000)); + next_tick = min(expire_tick, next_tick); + c++; + } + } + + if( c > 0 ) + sd->rental_timer = add_timer(gettick() + next_tick, pc_inventory_rental_end, sd->bl.id, 0); + else + sd->rental_timer = -1; +} + +void pc_inventory_rental_add(struct map_session_data *sd, int seconds) +{ + const struct TimerData * td; + int tick = seconds * 1000; + + if( sd == NULL ) + return; + + if( sd->rental_timer != INVALID_TIMER ) + { + td = get_timer(sd->rental_timer); + if( DIFF_TICK(td->tick, gettick()) > tick ) + { // Update Timer as this one ends first than the current one + pc_inventory_rental_clear(sd); + sd->rental_timer = add_timer(gettick() + tick, pc_inventory_rental_end, sd->bl.id, 0); + } + } + else + sd->rental_timer = add_timer(gettick() + tick, pc_inventory_rental_end, sd->bl.id, 0); +} + +/*========================================== Determines if the GM can give / drop / trade / vend items Args: GM Level (current player GM level) *------------------------------------------*/ @@ -732,7 +814,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim // アイテムチェック pc_setinventorydata(sd); pc_checkitem(sd); - + status_change_init(&sd->bl); if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) && (pc_isGM(sd) >= get_atcommand_level(atcommand_hide))) sd->status.option &= (OPTION_MASK | OPTION_INVISIBLE); @@ -747,11 +829,13 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sd->guild_x = -1; sd->guild_y = -1; - // イベント?係の初期化 - for(i = 0; i < MAX_EVENTTIMER; i++) + // Event Timers + for( i = 0; i < MAX_EVENTTIMER; i++ ) sd->eventtimer[i] = -1; + // Rental Timer + sd->rental_timer = -1; - for (i = 0; i < 3; i++) + for( i = 0; i < 3; i++ ) sd->hate_mob[i] = -1; // 位置の設定 @@ -873,7 +957,7 @@ int pc_reg_received(struct map_session_data *sd) sd->kafraPoints = pc_readaccountreg(sd,"#KAFRAPOINTS"); if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) - { //Better check for class rather than skill to prevent "skill resets" from unsetting this + { // Better check for class rather than skill to prevent "skill resets" from unsetting this sd->mission_mobid = pc_readglobalreg(sd,"TK_MISSION_ID"); sd->mission_count = pc_readglobalreg(sd,"TK_MISSION_COUNT"); } @@ -940,6 +1024,10 @@ int pc_reg_received(struct map_session_data *sd) sd->state.connect_new = 1; clif_parse_LoadEndAck(sd->fd, sd); } + +#ifndef TXT_ONLY + pc_inventory_rentals(sd); +#endif return 1; } @@ -2982,12 +3070,14 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount) ) return 0; - if (map[sd->bl.m].flag.nodrop) { + if( map[sd->bl.m].flag.nodrop ) + { clif_displaymessage (sd->fd, msg_txt(271)); return 0; //Can't drop items in nodrop mapflag maps. } - if (!pc_candrop(sd,&sd->status.inventory[n])) { + if( !pc_candrop(sd,&sd->status.inventory[n]) || sd->status.inventory[n].expire_time ) + { clif_displaymessage (sd->fd, msg_txt(263)); return 0; } @@ -3291,17 +3381,17 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun return 1; data = itemdb_search(item_data->nameid); - if(!itemdb_cancartstore(item_data, pc_isGM(sd))) - { //Check item trade restrictions [Skotlex] + if( item_data->expire_time || !itemdb_cancartstore(item_data, pc_isGM(sd)) ) + { // Check item trade restrictions [Skotlex] clif_displaymessage (sd->fd, msg_txt(264)); return 1; } - if((w=data->weight*amount) + sd->cart_weight > battle_config.max_cart_weight) + if( (w = data->weight*amount) + sd->cart_weight > battle_config.max_cart_weight ) return 1; - i=MAX_CART; - if(itemdb_isstackable2(data)) + i = MAX_CART; + if( itemdb_isstackable2(data) ) { ARR_FIND( 0, MAX_CART, i, sd->status.cart[i].nameid == item_data->nameid && @@ -7562,6 +7652,7 @@ int do_init_pc(void) add_timer_func_list(pc_invincible_timer, "pc_invincible_timer"); add_timer_func_list(pc_eventtimer, "pc_eventtimer"); + add_timer_func_list(pc_inventory_rental_end, "pc_inventory_rental_end"); add_timer_func_list(pc_calc_pvprank_timer, "pc_calc_pvprank_timer"); add_timer_func_list(pc_autosave, "pc_autosave"); add_timer_func_list(pc_spiritball_timer, "pc_spiritball_timer"); diff --git a/src/map/pc.h b/src/map/pc.h index 16ee1936b..aae1e6550 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -340,6 +340,7 @@ struct map_session_data { char away_message[128]; // [LuzZza] int cashPoints, kafraPoints; + int rental_timer; // Auction System [Zephyrus] struct { @@ -711,6 +712,11 @@ extern int night_timer_tid; int map_day_timer(int tid, unsigned int tick, int id, intptr data); // by [yor] int map_night_timer(int tid, unsigned int tick, int id, intptr data); // by [yor] +// Rental System +void pc_inventory_rentals(struct map_session_data *sd); +int pc_inventory_rental_clear(struct map_session_data *sd); +void pc_inventory_rental_add(struct map_session_data *sd, int seconds); + //Duel functions // [LuzZza] int duel_create(struct map_session_data* sd, const unsigned int maxpl); int duel_invite(const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd); diff --git a/src/map/script.c b/src/map/script.c index 1736b7f05..f56d388c3 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -5239,6 +5239,77 @@ BUILDIN_FUNC(getitem2) } /*========================================== + * rentitem <item id> + * rentitem "<item name>" + *------------------------------------------*/ +BUILDIN_FUNC(rentitem) +{ + struct map_session_data *sd; + struct script_data *data; + struct item it; + int seconds; + int nameid = 0, flag; + + data = script_getdata(st,2); + get_val(st,data); + + if( (sd = script_rid2sd(st)) == NULL ) + return 0; + + if( data_isstring(data) ) + { + const char *name = conv_str(st,data); + struct item_data *itd = itemdb_searchname(name); + if( itd == NULL ) + { + ShowError("buildin_rentitem: Nonexistant item %s requested.\n", name); + return 1; + } + nameid = itd->nameid; + } + else if( data_isint(data) ) + { + nameid = conv_num(st,data); + if( nameid <= 0 || !itemdb_exists(nameid) ) + { + ShowError("buildin_rentitem: Nonexistant item %d requested.\n", nameid); + return 1; + } + } + else + { + ShowError("buildin_rentitem: invalid data type for argument #1 (%d).\n", data->type); + return 1; + } + + if( itemdb_isstackable(nameid) ) + { + ShowError("buildin_rentitem: invalid rental item %d requested.\n", nameid); + return 1; + } + + seconds = script_getnum(st,3); + memset(&it, 0, sizeof(it)); + it.nameid = nameid; + it.identify = 1; + it.expire_time = (unsigned int)(time(NULL) + seconds); + + if( (flag = pc_additem(sd, &it, 1)) ) + { + clif_additem(sd, 0, 0, flag); + return 1; + } + + clif_rental_time(sd->fd, nameid, seconds); + pc_inventory_rental_add(sd, seconds); + + if( log_config.enable_logs&LOG_SCRIPT_TRANSACTIONS ) + log_pick_pc(sd, "N", nameid, 1, NULL); + + return 0; +} + +/*========================================== * gets an item with someone's name inscribed [Skotlex] * getinscribeditem item_num, character_name * Returned Qty is always 1, only works on equip-able @@ -9580,8 +9651,8 @@ BUILDIN_FUNC(mapwarp) // Added by RoVeRT static int buildin_mobcount_sub(struct block_list *bl,va_list ap) // Added by RoVeRT { char *event=va_arg(ap,char *); - struct mob_data *md = ((struct mob_data *)bl); - if(strcmp(event,md->npc_event)==0 && md->status.hp > 0) + struct mob_data *md = ((struct mob_data *)bl); + if(strcmp(event,md->npc_event)==0 && md->status.hp > 0) return 1; return 0; } @@ -13186,6 +13257,7 @@ struct script_function buildin_func[] = { BUILDIN_DEF(deletearray,"r?"), BUILDIN_DEF(getelementofarray,"ri"), BUILDIN_DEF(getitem,"vi?"), + BUILDIN_DEF(rentitem,"vi"), BUILDIN_DEF(getitem2,"iiiiiiiii*"), BUILDIN_DEF(getnameditem,"is"), BUILDIN_DEF2(grouprandomitem,"groupranditem","i"), diff --git a/src/map/storage.c b/src/map/storage.c index e4bdfe414..33a72d0d7 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -112,10 +112,11 @@ int storage_storageopen(struct map_session_data *sd) // helper function int compare_item(struct item *a, struct item *b) { - if (a->nameid == b->nameid && + if( a->nameid == b->nameid && a->identify == b->identify && a->refine == b->refine && - a->attribute == b->attribute) + a->attribute == b->attribute && + a->expire_time == b->expire_time ) { int i; for (i = 0; i < MAX_SLOTS && (a->card[i] == b->card[i]); i++); @@ -215,7 +216,10 @@ int storage_storageadd(struct map_session_data* sd, int index, int amount) return 0; if( sd->status.inventory[index].nameid <= 0 ) - return 0; //No item on that spot + return 0; // No item on that spot + + if( sd->status.inventory[index].expire_time ) + return 0; // Cannot Store Rental Items if( amount < 1 || amount > sd->status.inventory[index].amount ) return 0; @@ -266,6 +270,9 @@ int storage_storageaddfromcart(struct map_session_data* sd, int index, int amoun if( sd->status.cart[index].nameid <= 0 ) return 0; //No item there. + if( sd->status.inventory[index].expire_time ) + return 0; // Cannot Store Rental Items + if( amount < 1 || amount > sd->status.cart[index].amount ) return 0; @@ -462,16 +469,19 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount) nullpo_retr(0, sd); nullpo_retr(0, stor=guild2storage2(sd->status.guild_id)); - if (!stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE) + if( !stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE ) return 0; - if(index<0 || index>=MAX_INVENTORY) + if( index<0 || index>=MAX_INVENTORY ) return 0; - if(sd->status.inventory[index].nameid <= 0) + if( sd->status.inventory[index].nameid <= 0 ) return 0; - if(amount < 1 || amount > sd->status.inventory[index].amount) + if( amount < 1 || amount > sd->status.inventory[index].amount ) + return 0; + + if( sd->status.inventory[index].expire_time ) return 0; // log_tostorage(sd, index, 1); @@ -517,16 +527,19 @@ int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int nullpo_retr(0, sd); nullpo_retr(0, stor=guild2storage2(sd->status.guild_id)); - if(!stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE) + if( !stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE ) return 0; - if(index<0 || index>=MAX_CART) + if( index < 0 || index >= MAX_CART ) return 0; - if(sd->status.cart[index].nameid <= 0) + if( sd->status.cart[index].nameid <= 0 ) return 0; - if(amount < 1 || amount > sd->status.cart[index].amount) + if( amount < 1 || amount > sd->status.cart[index].amount ) + return 0; + + if( sd->status.inventory[index].expire_time ) return 0; if(guild_storage_additem(sd,stor,&sd->status.cart[index],amount)==0) diff --git a/src/map/trade.c b/src/map/trade.c index aca08872a..7d6a4c8b2 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -354,6 +354,13 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) return; } + if( item->expire_time ) + { // Rental System + clif_displaymessage (sd->fd, msg_txt(260)); + clif_tradeitemok(sd, index+2, 1); + return; + } + //Locate a trade position ARR_FIND( 0, 10, trade_i, sd->deal.item[trade_i].index == index || sd->deal.item[trade_i].amount == 0 ); if( trade_i == 10 ) //No space left diff --git a/src/map/unit.c b/src/map/unit.c index 3049f0457..7373ebab1 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1941,6 +1941,7 @@ int unit_free(struct block_list *bl, int clrtype) party_send_logout(sd); guild_send_memberinfoshort(sd,0); pc_cleareventtimer(sd); + pc_inventory_rental_clear(sd); pc_delspiritball(sd,sd->spiritball,1); if( sd->reg ) |