- 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; 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++ ) 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; clif_displaymessage(fd,line_buff);
cur = line_buff;
if( gm_lvl < atcommand_info[i].level && stristr(command,"commands") ) memset(line_buff,' ',CHATBOX_SIZE);
continue; line_buff[CHATBOX_SIZE-1] = 0;
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++;
} }
memcpy(cur,atcommand_info[i].command,slen);
cur += slen+(10-slen%10);
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;
} }

View File

@ -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,

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_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);

View File

@ -349,10 +349,10 @@ void pc_inventory_rentals(struct map_session_data *sd)
} }
} }
if( c > 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() + next_tick, pc_inventory_rental_end, sd->bl.id, 0); 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)) if( itemdb_isstackable2(data) && item_data->serial == 0 && item_data->expire_time == 0 )
{ //Stackable { // Stackable | Non Serialized (non unique) | Non Rental
for (i = 0; i < MAX_INVENTORY; i++) for( i = 0; i < MAX_INVENTORY; i++ )
{ {
if(sd->status.inventory[i].nameid == item_data->nameid && if( sd->status.inventory[i].nameid == item_data->nameid && memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 )
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 || if( sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount <= 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 { else
clif_useitemack(sd,n,amount-1,1); {
//Logs (C)onsumable items [Lupus] if( sd->status.inventory[n].expire_time == 0 )
if(log_config.enable_logs&0x100) {
log_pick_pc(sd, "C", sd->status.inventory[n].nameid, -1, &sd->status.inventory[n]); clif_useitemack(sd,n,amount-1,1);
//Logs
pc_delitem(sd,n,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])

View File

@ -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;

View File

@ -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)) if( num > 0 && num <= ARRAYLENGTH(equip) )
i=pc_checkequip(sd,equip[num-1]); i = pc_checkequip(sd,equip[num-1]);
if(i >= 0 && sd->inventory_data[i] && !sd->inventory_data[i]->flag.no_refine) 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,""),

View File

@ -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 && if( skill == WZ_EARTHSPIKE && sc && sc->data[SC_EARTHSCROLL] && rand()%100 > sc->data[SC_EARTHSCROLL]->val2 ) // [marquis007]
sc->data[SC_EARTHSCROLL] && rand()%100 > sc->data[SC_EARTHSCROLL]->val2) // [marquis007]
; //Do not consume item. ; //Do not consume item.
else else if( sd->status.inventory[i].expire_time == 0 )
pc_delitem(sd,i,1,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;

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! //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;