- 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
This commit is contained in:
zephyrus 2009-05-12 16:47:12 +00:00
parent 7828b01c09
commit 15a8174e29
8 changed files with 172 additions and 77 deletions

View File

@ -8586,6 +8586,42 @@ int atcommand_delitem(const int fd, struct map_session_data* sd, const char* com
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 },
{ "delitem", 60,60, atcommand_delitem },
{ "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:"
for( i = 0; i < ARRAYLENGTH(atcommand_info); i++ )
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;
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 )
{
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;
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;
}
memcpy(cur,atcommand_info[i].command,slen);
cur += slen+(10-slen%10);
count++;
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);
count++;
}
clif_displaymessage(fd,line_buff);
sprintf(atcmd_output, msg_txt(274), count); // "%d commands found."
clif_displaymessage(fd, atcmd_output);
return 0;
}

View File

@ -1062,6 +1062,8 @@ int clif_spawn(struct block_list *bl)
clif_specialeffect(bl,423,AREA);
else if(sd->state.size==1)
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 )
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);
else if(tsd->state.size==1)
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 )
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 )
{// 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
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 )
{ //Display night.
@ -13012,6 +13018,32 @@ int clif_sendbgemblem_single(int fd, struct map_session_data *sd)
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
*------------------------------------------*/
@ -13286,7 +13318,7 @@ static int packetdb_readdb(void)
//#0x02C0
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, 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,
//#0x0300
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

View File

@ -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_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
int clif_displaymessage(const int fd,const char* mes);
int clif_disp_onlyself(struct map_session_data *sd,const char *mes,int len);

View File

@ -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
sd->rental_timer = -1;
sd->rental_timer = INVALID_TIMER;
}
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++ )
sd->eventtimer[i] = -1;
// Rental Timer
sd->rental_timer = -1;
sd->rental_timer = INVALID_TIMER;
for( i = 0; i < 3; i++ )
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, item_data);
if(item_data->nameid <= 0 || amount <= 0)
if( item_data->nameid <= 0 || amount <= 0 )
return 1;
if(amount > MAX_AMOUNT)
if( amount > MAX_AMOUNT )
return 5;
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;
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;
sd->status.inventory[i].amount += amount;
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);
if(i<0) return 4;
if( i < 0 )
return 4;
memcpy(&sd->status.inventory[i], item_data, sizeof(sd->status.inventory[0]));
// 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].amount = amount;
@ -3447,18 +3449,17 @@ int pc_useitem(struct map_session_data *sd,int n)
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;
if(!pc_isUseitem(sd,n))
if( !pc_isUseitem(sd,n) )
return 0;
//Prevent mass item usage. [Skotlex]
if(DIFF_TICK(sd->canuseitem_tick, tick) > 0)
if( DIFF_TICK(sd->canuseitem_tick, tick) > 0 )
return 0;
if (sd->sc.count && (
if( sd->sc.count && (
sd->sc.data[SC_BERSERK] ||
(sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) ||
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;
script = sd->inventory_data[n]->script;
//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);
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 &&
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;
i = MAX_CART;
if( itemdb_isstackable2(data) )
if( itemdb_isstackable2(data) && !item_data->expire_time )
{
ARR_FIND( 0, MAX_CART, i,
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];
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;
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 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);
if( sd->state.changemap )
{ //Misc map-changing settings
{ // Misc map-changing settings
sd->state.pmap = sd->bl.m;
if (sd->sc.count)
{ //Cancel some map related stuff.
{ // Cancel some map related stuff.
if (sd->sc.data[SC_JAILED])
return 1; //You may not get out!
if (sd->sc.data[SC_BOSSMAPINFO])

View File

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

View File

@ -5356,12 +5356,6 @@ BUILDIN_FUNC(rentitem)
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;
@ -6268,14 +6262,12 @@ BUILDIN_FUNC(getequipisenableref)
if( sd == NULL )
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);
} else {
else
script_pushint(st,0);
}
return 0;
}
@ -13640,6 +13632,25 @@ BUILDIN_FUNC(bg_get_data)
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
#ifdef PCRE_SUPPORT
BUILDIN_FUNC(defpattern);
@ -13998,6 +14009,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(mercenary_set_calls,"ii"),
BUILDIN_DEF(mercenary_set_faith,"ii"),
BUILDIN_DEF(readbook,"ii"),
BUILDIN_DEF(setfont,"i"),
// WoE SE
BUILDIN_DEF(agitstart2,""),
BUILDIN_DEF(agitend2,""),

View File

@ -7995,11 +7995,10 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in
}
//Consume
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.
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
sd->skillitem = sd->skillitemlv = 0;

View File

@ -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!
|| !sd->status.cart[index].identify // unidentified 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
continue;