浏览代码

- Rental items now can be stackable items too.
- Added @font command to test kRO fonts. (Client side requires : Langtype 0 / Hex + Fonts Files on the data folder).
- Rental now announces with a maximum time to fix a problem with 1 month or more rentals.
- Reduced amount of calculations of Flee on map change (only if required).
- More security on Rental items.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@13761 54d463be-8e91-2dee-dedb-b68131a5f0ec

zephyrus 16 年之前
父节点
当前提交
15a8174e29
共有 8 个文件被更改,包括 169 次插入74 次删除
  1. 58 22
      src/map/atcommand.c
  2. 34 2
      src/map/clif.c
  3. 4 0
      src/map/clif.h
  4. 43 34
      src/map/pc.c
  5. 2 0
      src/map/pc.h
  6. 24 12
      src/map/script.c
  7. 3 4
      src/map/skill.c
  8. 1 0
      src/map/vending.c

+ 58 - 22
src/map/atcommand.c

@@ -8586,6 +8586,42 @@ int atcommand_delitem(const int fd, struct map_session_data* sd, const char* com
 	return 0;
 	return 0;
 }
 }
 
 
+/*==========================================
+ * Custom Fonts
+ *------------------------------------------*/
+int atcommand_font(const int fd, struct map_session_data *sd, const char *command, const char *message)
+{
+	int font_id;
+	nullpo_retr(-1,sd);
+
+	font_id = atoi(message);
+	if( font_id == 0 )
+	{
+		if( sd->state.user_font )
+		{
+			sd->state.user_font = 0;
+			clif_displaymessage(fd, "Returning to normal font.");
+			clif_font_area(sd);
+		}
+		else
+		{
+			clif_displaymessage(fd, "Use @font <1..9> to change your messages font.");
+			clif_displaymessage(fd, "Use 0 or no parameter to back to normal font.");
+		}
+	}
+	else if( font_id < 0 || font_id > 9 )
+		clif_displaymessage(fd, "Invalid font. Use a Value from 0 to 9.");
+	else if( font_id != sd->state.user_font )
+	{
+		sd->state.user_font = font_id;
+		clif_font_area(sd);
+		clif_displaymessage(fd, "Font changed.");
+	}
+	else
+		clif_displaymessage(fd, "Already using this font.");
+
+	return 0;
+}
 
 
 
 
 /*==========================================
 /*==========================================
@@ -8890,6 +8926,7 @@ AtCommandInfo atcommand_info[] = {
 	{ "stats",              40,40,    atcommand_stats },
 	{ "stats",              40,40,    atcommand_stats },
 	{ "delitem",            60,60,    atcommand_delitem },
 	{ "delitem",            60,60,    atcommand_delitem },
 	{ "charcommands",        1,1,     atcommand_commands },
 	{ "charcommands",        1,1,     atcommand_commands },
+	{ "font",               1,1,     atcommand_font },
 };
 };
 
 
 
 
@@ -9147,36 +9184,35 @@ int atcommand_commands(const int fd, struct map_session_data* sd, const char* co
 
 
 	clif_displaymessage(fd, msg_txt(273)); // "Commands available:"
 	clif_displaymessage(fd, msg_txt(273)); // "Commands available:"
 
 
-		for( i = 0; i < ARRAYLENGTH(atcommand_info); i++ )
-		{
-			unsigned int slen;
+	for( i = 0; i < ARRAYLENGTH(atcommand_info); i++ )
+	{
+		unsigned int slen;
 
 
-			if( gm_lvl < atcommand_info[i].level && stristr(command,"commands") )
-				continue;
-			if( gm_lvl < atcommand_info[i].level2 && stristr(command,"charcommands") )
-				continue;
+		if( gm_lvl < atcommand_info[i].level && stristr(command,"commands") )
+			continue;
+		if( gm_lvl < atcommand_info[i].level2 && stristr(command,"charcommands") )
+			continue;
 
 
-			slen = (unsigned int)strlen(atcommand_info[i].command);
+		slen = (unsigned int)strlen(atcommand_info[i].command);
 
 
-			// flush the text buffer if this command won't fit into it
-			if( slen + cur - line_buff >= CHATBOX_SIZE )
-			{
-				clif_displaymessage(fd,line_buff);
-				cur = line_buff;
-				memset(line_buff,' ',CHATBOX_SIZE);
-				line_buff[CHATBOX_SIZE-1] = 0;
-			}
+		// flush the text buffer if this command won't fit into it
+		if( slen + cur - line_buff >= CHATBOX_SIZE )
+		{
+			clif_displaymessage(fd,line_buff);
+			cur = line_buff;
+			memset(line_buff,' ',CHATBOX_SIZE);
+			line_buff[CHATBOX_SIZE-1] = 0;
+		}
 
 
-			memcpy(cur,atcommand_info[i].command,slen);
-			cur += slen+(10-slen%10);
+		memcpy(cur,atcommand_info[i].command,slen);
+		cur += slen+(10-slen%10);
 
 
-			count++;
-		}
-		
+		count++;
+	}
 	clif_displaymessage(fd,line_buff);
 	clif_displaymessage(fd,line_buff);
 
 
 	sprintf(atcmd_output, msg_txt(274), count); // "%d commands found."
 	sprintf(atcmd_output, msg_txt(274), count); // "%d commands found."
 	clif_displaymessage(fd, atcmd_output);
 	clif_displaymessage(fd, atcmd_output);
-	
+
 	return 0;
 	return 0;
 }
 }

+ 34 - 2
src/map/clif.c

@@ -1062,6 +1062,8 @@ int clif_spawn(struct block_list *bl)
 				clif_specialeffect(bl,423,AREA);
 				clif_specialeffect(bl,423,AREA);
 			else if(sd->state.size==1)
 			else if(sd->state.size==1)
 				clif_specialeffect(bl,421,AREA);
 				clif_specialeffect(bl,421,AREA);
+			if( sd->state.user_font )
+				clif_font_area(sd);
 			if( sd->state.bg_id && map[sd->bl.m].flag.battleground )
 			if( sd->state.bg_id && map[sd->bl.m].flag.battleground )
 				clif_sendbgemblem_area(sd);
 				clif_sendbgemblem_area(sd);
 		}
 		}
@@ -3486,6 +3488,8 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl)
 				clif_specialeffect_single(bl,423,sd->fd);
 				clif_specialeffect_single(bl,423,sd->fd);
 			else if(tsd->state.size==1)
 			else if(tsd->state.size==1)
 				clif_specialeffect_single(bl,421,sd->fd);
 				clif_specialeffect_single(bl,421,sd->fd);
+			if( tsd->state.user_font )
+				clif_font_single(sd->fd,tsd);
 			if( tsd->state.bg_id && map[tsd->bl.m].flag.battleground )
 			if( tsd->state.bg_id && map[tsd->bl.m].flag.battleground )
 				clif_sendbgemblem_single(sd->fd,tsd);
 				clif_sendbgemblem_single(sd->fd,tsd);
 		}
 		}
@@ -8125,8 +8129,10 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 
 
 	if( sd->state.changemap )
 	if( sd->state.changemap )
 	{// restore information that gets lost on map-change
 	{// restore information that gets lost on map-change
-		if( battle_config.gvg_flee_penalty != 100 || battle_config.bg_flee_penalty != 100 )
+		if( (map_flag_gvg(sd->state.pmap) && battle_config.gvg_flee_penalty != 100) || (map[sd->state.pmap].flag.battleground && battle_config.bg_flee_penalty != 100) )
 			status_calc_bl(&sd->bl, SCB_FLEE); //Refresh flee penalty
 			status_calc_bl(&sd->bl, SCB_FLEE); //Refresh flee penalty
+		else if( (map_flag_gvg(sd->bl.m) && battle_config.gvg_flee_penalty != 100) || (map[sd->bl.m].flag.battleground && battle_config.bg_flee_penalty != 100) )
+			status_calc_bl(&sd->bl, SCB_FLEE);
 
 
 		if( night_flag && map[sd->bl.m].flag.nightenabled )
 		if( night_flag && map[sd->bl.m].flag.nightenabled )
 		{	//Display night.
 		{	//Display night.
@@ -13012,6 +13018,32 @@ int clif_sendbgemblem_single(int fd, struct map_session_data *sd)
 	return 0;
 	return 0;
 }
 }
 
 
+/*==========================================
+ * Custom Fonts
+ * S 0x2ef <account_id>.l <font id>.w
+ *------------------------------------------*/
+int clif_font_area(struct map_session_data *sd)
+{
+	unsigned char buf[8];
+	nullpo_retr(0,sd);
+	WBUFW(buf,0) = 0x2ef;
+	WBUFL(buf,2) = sd->bl.id;
+	WBUFW(buf,6) = sd->state.user_font;
+	clif_send(buf, packet_len(0x2ef), &sd->bl, AREA);
+	return 1;
+}
+
+int clif_font_single(int fd, struct map_session_data *sd)
+{
+	nullpo_retr(0,sd);
+	WFIFOHEAD(fd,packet_len(0x2ef));
+	WFIFOW(fd,0) = 0x2ef;
+	WFIFOL(fd,2) = sd->bl.id;
+	WFIFOW(fd,6) = sd->state.user_font;
+	WFIFOSET(fd,packet_len(0x2ef));
+	return 1;
+}
+
 /*==========================================
 /*==========================================
  * ƒpƒPƒbƒgƒfƒoƒbƒO
  * ƒpƒPƒbƒgƒfƒoƒbƒO
  *------------------------------------------*/
  *------------------------------------------*/
@@ -13286,7 +13318,7 @@ static int packetdb_readdb(void)
 	//#0x02C0
 	//#0x02C0
 	    0,  0,  0,  0,  0, 30,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	    0,  0,  0,  0,  0, 30,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	    0,  0,  0,  0,  0,  0,  6, -1, 10, 10,  0,  0, -1, 32,  6,  0,
 	    0,  0,  0,  0,  0,  0,  6, -1, 10, 10,  0,  0, -1, 32,  6,  0,
-	    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  8,
 	    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	//#0x0300
 	//#0x0300
 	    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,

+ 4 - 0
src/map/clif.h

@@ -350,6 +350,10 @@ int clif_bg_updatescore_single(struct map_session_data *sd);
 int clif_sendbgemblem_area(struct map_session_data *sd);
 int clif_sendbgemblem_area(struct map_session_data *sd);
 int clif_sendbgemblem_single(int fd, struct map_session_data *sd);
 int clif_sendbgemblem_single(int fd, struct map_session_data *sd);
 
 
+// Custom Fonts
+int clif_font_area(struct map_session_data *sd);
+int clif_font_single(int fd, struct map_session_data *sd);
+
 // atcommand
 // atcommand
 int clif_displaymessage(const int fd,const char* mes);
 int clif_displaymessage(const int fd,const char* mes);
 int clif_disp_onlyself(struct map_session_data *sd,const char *mes,int len);
 int clif_disp_onlyself(struct map_session_data *sd,const char *mes,int len);

+ 43 - 34
src/map/pc.c

@@ -349,10 +349,10 @@ void pc_inventory_rentals(struct map_session_data *sd)
 		}
 		}
 	}
 	}
 
 
-	if( c > 0 )
-		sd->rental_timer = add_timer(gettick() + next_tick, pc_inventory_rental_end, sd->bl.id, 0);
+	if( c > 0 ) // min(next_tick,3600000) 1 hour each timer to keep announcing to the owner, and to avoid a but with rental time > 15 days
+		sd->rental_timer = add_timer(gettick() + min(next_tick,3600000), pc_inventory_rental_end, sd->bl.id, 0);
 	else
 	else
-		sd->rental_timer = -1;
+		sd->rental_timer = INVALID_TIMER;
 }
 }
 
 
 void pc_inventory_rental_add(struct map_session_data *sd, int seconds)
 void pc_inventory_rental_add(struct map_session_data *sd, int seconds)
@@ -848,7 +848,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
 	for( i = 0; i < MAX_EVENTTIMER; i++ )
 	for( i = 0; i < MAX_EVENTTIMER; i++ )
 		sd->eventtimer[i] = -1;
 		sd->eventtimer[i] = -1;
 	// Rental Timer
 	// Rental Timer
-	sd->rental_timer = -1;
+	sd->rental_timer = INVALID_TIMER;
 
 
 	for( i = 0; i < 3; i++ )
 	for( i = 0; i < 3; i++ )
 		sd->hate_mob[i] = -1;
 		sd->hate_mob[i] = -1;
@@ -3119,9 +3119,9 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount)
 	nullpo_retr(1, sd);
 	nullpo_retr(1, sd);
 	nullpo_retr(1, item_data);
 	nullpo_retr(1, item_data);
 
 
-	if(item_data->nameid <= 0 || amount <= 0)
+	if( item_data->nameid <= 0 || amount <= 0 )
 		return 1;
 		return 1;
-	if(amount > MAX_AMOUNT)
+	if( amount > MAX_AMOUNT )
 		return 5;
 		return 5;
 	
 	
 	data = itemdb_search(item_data->nameid);
 	data = itemdb_search(item_data->nameid);
@@ -3131,15 +3131,13 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount)
 
 
 	i = MAX_INVENTORY;
 	i = MAX_INVENTORY;
 
 
-	if (itemdb_isstackable2(data))
-	{ //Stackable
-		for (i = 0; i < MAX_INVENTORY; i++)
+	if( itemdb_isstackable2(data) && item_data->serial == 0 && item_data->expire_time == 0 )
+	{ // Stackable | Non Serialized (non unique) | Non Rental
+		for( i = 0; i < MAX_INVENTORY; i++ )
 		{
 		{
-			if(sd->status.inventory[i].nameid == item_data->nameid &&
-				memcmp(&sd->status.inventory[i].card,&item_data->card,
-					sizeof(item_data->card))==0)
+			if( sd->status.inventory[i].nameid == item_data->nameid && memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 )
 			{
 			{
-				if (amount > MAX_AMOUNT - sd->status.inventory[i].amount)
+				if( amount > MAX_AMOUNT - sd->status.inventory[i].amount )
 					return 5;
 					return 5;
 				sd->status.inventory[i].amount += amount;
 				sd->status.inventory[i].amount += amount;
 				clif_additem(sd,i,amount,0);
 				clif_additem(sd,i,amount,0);
@@ -3147,12 +3145,16 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount)
 			}
 			}
 		}
 		}
 	}
 	}
-	if (i >= MAX_INVENTORY){
+
+	if( i >= MAX_INVENTORY )
+	{
 		i = pc_search_inventory(sd,0);
 		i = pc_search_inventory(sd,0);
-		if(i<0) return 4;
+		if( i < 0 )
+			return 4;
+
 		memcpy(&sd->status.inventory[i], item_data, sizeof(sd->status.inventory[0]));
 		memcpy(&sd->status.inventory[i], item_data, sizeof(sd->status.inventory[0]));
 		// clear equips field first, just in case
 		// clear equips field first, just in case
-		if (item_data->equip)
+		if( item_data->equip )
 			sd->status.inventory[i].equip = 0;
 			sd->status.inventory[i].equip = 0;
 
 
 		sd->status.inventory[i].amount = amount;
 		sd->status.inventory[i].amount = amount;
@@ -3447,18 +3449,17 @@ int pc_useitem(struct map_session_data *sd,int n)
 
 
 	nullpo_retr(0, sd);
 	nullpo_retr(0, sd);
 
 
-	if(sd->status.inventory[n].nameid <= 0 ||
-		sd->status.inventory[n].amount <= 0)
+	if( sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount <= 0 )
 		return 0;
 		return 0;
 
 
-	if(!pc_isUseitem(sd,n))
+	if( !pc_isUseitem(sd,n) )
 		return 0;
 		return 0;
 
 
 	 //Prevent mass item usage. [Skotlex]
 	 //Prevent mass item usage. [Skotlex]
-	if(DIFF_TICK(sd->canuseitem_tick, tick) > 0)
+	if( DIFF_TICK(sd->canuseitem_tick, tick) > 0 )
 		return 0;
 		return 0;
 
 
-	if (sd->sc.count && (
+	if( sd->sc.count && (
 		sd->sc.data[SC_BERSERK] ||
 		sd->sc.data[SC_BERSERK] ||
 		(sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) ||
 		(sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) ||
 		sd->sc.data[SC_TRICKDEAD] ||
 		sd->sc.data[SC_TRICKDEAD] ||
@@ -3484,15 +3485,22 @@ int pc_useitem(struct map_session_data *sd,int n)
 	amount = sd->status.inventory[n].amount;
 	amount = sd->status.inventory[n].amount;
 	script = sd->inventory_data[n]->script;
 	script = sd->inventory_data[n]->script;
 	//Check if the item is to be consumed immediately [Skotlex]
 	//Check if the item is to be consumed immediately [Skotlex]
-	if (sd->inventory_data[n]->flag.delay_consume)
+	if( sd->inventory_data[n]->flag.delay_consume )
 		clif_useitemack(sd,n,amount,1);
 		clif_useitemack(sd,n,amount,1);
-	else {
-		clif_useitemack(sd,n,amount-1,1);
-		//Logs (C)onsumable items [Lupus]
-		if(log_config.enable_logs&0x100)
-			log_pick_pc(sd, "C", sd->status.inventory[n].nameid, -1, &sd->status.inventory[n]);
-		//Logs
-		pc_delitem(sd,n,1,1);
+	else
+	{
+		if( sd->status.inventory[n].expire_time == 0 )
+		{
+			clif_useitemack(sd,n,amount-1,1);
+
+			//Logs (C)onsumable items [Lupus]
+			if( log_config.enable_logs&0x100 )
+				log_pick_pc(sd, "C", sd->status.inventory[n].nameid, -1, &sd->status.inventory[n], sd->status.inventory[n].serial );
+
+			pc_delitem(sd,n,1,1); // Rental Usable Items are not deleted until expiration
+		}
+		else
+			clif_useitemack(sd,n,0,0);
 	}
 	}
 	if(sd->status.inventory[n].card[0]==CARD0_CREATE &&
 	if(sd->status.inventory[n].card[0]==CARD0_CREATE &&
 		pc_famerank(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST))
 		pc_famerank(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST))
@@ -3533,7 +3541,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
 		return 1;
 		return 1;
 
 
 	i = MAX_CART;
 	i = MAX_CART;
-	if( itemdb_isstackable2(data) )
+	if( itemdb_isstackable2(data) && !item_data->expire_time )
 	{
 	{
 		ARR_FIND( 0, MAX_CART, i,
 		ARR_FIND( 0, MAX_CART, i,
 			sd->status.cart[i].nameid == item_data->nameid &&
 			sd->status.cart[i].nameid == item_data->nameid &&
@@ -3606,10 +3614,10 @@ int pc_putitemtocart(struct map_session_data *sd,int idx,int amount)
 	
 	
 	item_data = &sd->status.inventory[idx];
 	item_data = &sd->status.inventory[idx];
 
 
-	if (item_data->nameid==0 || amount < 1 || item_data->amount<amount || sd->vender_id)
+	if( item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->vender_id || item_data->expire_time )
 		return 1;
 		return 1;
 
 
-	if (pc_cart_additem(sd,item_data,amount) == 0)
+	if( pc_cart_additem(sd,item_data,amount) == 0 )
 		return pc_delitem(sd,idx,amount,0);
 		return pc_delitem(sd,idx,amount,0);
 
 
 	return 1;
 	return 1;
@@ -3814,9 +3822,10 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
 
 
 	sd->state.changemap = (sd->mapindex != mapindex);
 	sd->state.changemap = (sd->mapindex != mapindex);
 	if( sd->state.changemap )
 	if( sd->state.changemap )
-	{	//Misc map-changing settings
+	{ // Misc map-changing settings
+		sd->state.pmap = sd->bl.m;
 		if (sd->sc.count)
 		if (sd->sc.count)
-		{ //Cancel some map related stuff.
+		{ // Cancel some map related stuff.
 			if (sd->sc.data[SC_JAILED])
 			if (sd->sc.data[SC_JAILED])
 				return 1; //You may not get out!
 				return 1; //You may not get out!
 			if (sd->sc.data[SC_BOSSMAPINFO])
 			if (sd->sc.data[SC_BOSSMAPINFO])

+ 2 - 0
src/map/pc.h

@@ -120,9 +120,11 @@ struct map_session_data {
 		unsigned short autolootid; // [Zephyrus]
 		unsigned short autolootid; // [Zephyrus]
 		unsigned noks : 3; // [Zeph Kill Steal Protection]
 		unsigned noks : 3; // [Zeph Kill Steal Protection]
 		bool changemap;
 		bool changemap;
+		short pmap; // Previous map on Map Change
 		struct guild *gmaster_flag;
 		struct guild *gmaster_flag;
 		unsigned int bg_id;
 		unsigned int bg_id;
 		unsigned skillonskill : 1;
 		unsigned skillonskill : 1;
+		unsigned short user_font;
 	} state;
 	} state;
 	struct {
 	struct {
 		unsigned char no_weapon_damage, no_magic_damage, no_misc_damage;
 		unsigned char no_weapon_damage, no_magic_damage, no_misc_damage;

+ 24 - 12
src/map/script.c

@@ -5356,12 +5356,6 @@ BUILDIN_FUNC(rentitem)
 		return 1;
 		return 1;
 	}
 	}
 
 
-	if( itemdb_isstackable(nameid) )
-	{
-		ShowError("buildin_rentitem: invalid rental item %d requested.\n", nameid);
-		return 1;
-	}
-
 	seconds = script_getnum(st,3);
 	seconds = script_getnum(st,3);
 	memset(&it, 0, sizeof(it));
 	memset(&it, 0, sizeof(it));
 	it.nameid = nameid;
 	it.nameid = nameid;
@@ -6268,14 +6262,12 @@ BUILDIN_FUNC(getequipisenableref)
 	if( sd == NULL )
 	if( sd == NULL )
 		return 0;
 		return 0;
 
 
-	if (num > 0 && num <= ARRAYLENGTH(equip))
-		i=pc_checkequip(sd,equip[num-1]);
-	if(i >= 0 && sd->inventory_data[i] && !sd->inventory_data[i]->flag.no_refine)
-	{
+	if( num > 0 && num <= ARRAYLENGTH(equip) )
+		i = pc_checkequip(sd,equip[num-1]);
+	if( i >= 0 && sd->inventory_data[i] && !sd->inventory_data[i]->flag.no_refine && !sd->status.inventory[i].expire_time )
 		script_pushint(st,1);
 		script_pushint(st,1);
-	} else {
+	else
 		script_pushint(st,0);
 		script_pushint(st,0);
-	}
 
 
 	return 0;
 	return 0;
 }
 }
@@ -13640,6 +13632,25 @@ BUILDIN_FUNC(bg_get_data)
 	return 0;
 	return 0;
 }
 }
 
 
+/*==========================================
+ * Custom Fonts
+ *------------------------------------------*/
+BUILDIN_FUNC(setfont)
+{
+	struct map_session_data *sd = script_rid2sd(st);
+	int font = script_getnum(st,2);
+	if( sd == NULL )
+		return 0;
+
+	if( sd->state.user_font != font )
+		sd->state.user_font = font;
+	else
+		sd->state.user_font = 0;
+	
+	clif_font_area(sd);
+	return 0;
+}
+
 // declarations that were supposed to be exported from npc_chat.c
 // declarations that were supposed to be exported from npc_chat.c
 #ifdef PCRE_SUPPORT
 #ifdef PCRE_SUPPORT
 BUILDIN_FUNC(defpattern);
 BUILDIN_FUNC(defpattern);
@@ -13998,6 +14009,7 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(mercenary_set_calls,"ii"),
 	BUILDIN_DEF(mercenary_set_calls,"ii"),
 	BUILDIN_DEF(mercenary_set_faith,"ii"),
 	BUILDIN_DEF(mercenary_set_faith,"ii"),
 	BUILDIN_DEF(readbook,"ii"),
 	BUILDIN_DEF(readbook,"ii"),
+	BUILDIN_DEF(setfont,"i"),
 	// WoE SE
 	// WoE SE
 	BUILDIN_DEF(agitstart2,""),
 	BUILDIN_DEF(agitstart2,""),
 	BUILDIN_DEF(agitend2,""),
 	BUILDIN_DEF(agitend2,""),

+ 3 - 4
src/map/skill.c

@@ -7995,11 +7995,10 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in
 			}
 			}
 			//Consume
 			//Consume
 			sd->itemid = sd->itemindex = -1;
 			sd->itemid = sd->itemindex = -1;
-			if(skill == WZ_EARTHSPIKE && sc &&
-				sc->data[SC_EARTHSCROLL] && rand()%100 > sc->data[SC_EARTHSCROLL]->val2) // [marquis007]
+			if( skill == WZ_EARTHSPIKE && sc && sc->data[SC_EARTHSCROLL] && rand()%100 > sc->data[SC_EARTHSCROLL]->val2 ) // [marquis007]
 				; //Do not consume item.
 				; //Do not consume item.
-			else
-				pc_delitem(sd,i,1,0);
+			else if( sd->status.inventory[i].expire_time == 0 )
+				pc_delitem(sd,i,1,0); // Rental usable items are not consumed until expiration
 		}
 		}
 		if (type&1) //Casting finished
 		if (type&1) //Casting finished
 			sd->skillitem = sd->skillitemlv = 0;
 			sd->skillitem = sd->skillitemlv = 0;

+ 1 - 0
src/map/vending.c

@@ -266,6 +266,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, bool
 		//NOTE: official server does not do any of the following checks!
 		//NOTE: official server does not do any of the following checks!
 		||  !sd->status.cart[index].identify // unidentified item
 		||  !sd->status.cart[index].identify // unidentified item
 		||  sd->status.cart[index].attribute == 1 // broken item
 		||  sd->status.cart[index].attribute == 1 // broken item
+		||  sd->status.cart[index].expire_time // It should not be in the cart but just in case
 		||  !itemdb_cantrade(&sd->status.cart[index], pc_isGM(sd), pc_isGM(sd)) ) // untradeable item
 		||  !itemdb_cantrade(&sd->status.cart[index], pc_isGM(sd), pc_isGM(sd)) ) // untradeable item
 			continue;
 			continue;