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 /src/map | |
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
Diffstat (limited to 'src/map')
-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 |
9 files changed, 263 insertions, 40 deletions
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 ) |