Item Max Level clif_equipitemack messages

* Max level to equip item now works for Pre-Renewal too, since the field is optional. 0 means no max level limit.
* Fixed fail message on clif_equipitemack when item cannot be equipped because level limitation

Signed-off-by: Cydh Ramdh <house.bad@gmail.com>
This commit is contained in:
Cydh Ramdh 2015-01-15 01:17:54 +07:00
parent 3037a1b57e
commit fa75733cc1
12 changed files with 89 additions and 77 deletions

View File

@ -1,7 +1,7 @@
// Items Additional Database
//
// Structure of Database:
// ID,Name,Name,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Class,Gender,Loc,wLV,eLV,Refineable,View,{ Script },{ OnEquip_Script },{ OnUnequip_Script }
// ID,Name,Name,Type,Price,Sell,Weight,ATK[:MATK],DEF,Range,Slot,Job,Class,Gender,Loc,wLV,eLV[:maxLevel],Refineable,View,{ Script },{ OnEquip_Script },{ OnUnequip_Script }
//
// THQ Quest Items
//=============================================================

View File

@ -1,7 +1,7 @@
// Items Database
//
// Structure of Database:
// ID,AegisName,Name,Type,Buy,Sell,Weight,ATK,DEF,Range,Slots,Job,Class,Gender,Loc,wLV,eLV,Refineable,View,{ Script },{ OnEquip_Script },{ OnUnequip_Script }
// ID,AegisName,Name,Type,Buy,Sell,Weight,ATK,DEF,Range,Slots,Job,Class,Gender,Loc,wLV,eLV[:maxLevel],Refineable,View,{ Script },{ OnEquip_Script },{ OnUnequip_Script }
//
// Healing Items
//=============================================================

View File

@ -1,7 +1,7 @@
// Items Database
//
// Structure of Database:
// ID,AegisName,Name,Type,Buy,Sell,Weight,ATK,DEF,Range,Slots,Job,Class,Gender,Loc,wLV,eLV,Refineable,View,{ Script },{ OnEquip_Script },{ OnUnequip_Script }
// ID,AegisName,Name,Type,Buy,Sell,Weight,ATK[:MATK],DEF,Range,Slots,Job,Class,Gender,Loc,wLV,eLV[:maxLevel],Refineable,View,{ Script },{ OnEquip_Script },{ OnUnequip_Script }
//
// Healing Items
//=============================================================

View File

@ -56,6 +56,8 @@ Weight: Item's weight. Each 10 is 1 weight.
ATK: Weapon's attack
MATK: Weapon's magic attack (Renewal only)
---------------------------------------
DEF: Armor's defense
@ -154,6 +156,8 @@ wLV: Weapon level.
eLV: Base level required to be able to equip.
maxLevel: Only able to equip if base level is lower than this.
---------------------------------------
Refineable: 1 if the item can be refined, 0 otherwise.

View File

@ -3388,39 +3388,36 @@ void clif_statusupack(struct map_session_data *sd,int type,int ok,int val)
/// 0 = failure
/// 1 = success
/// 2 = failure due to low level
void clif_equipitemack(struct map_session_data *sd,int n,int pos,int ok)
void clif_equipitemack(struct map_session_data *sd,int n,int pos,uint8 flag)
{
int fd,header,offs=0,success;
int fd, header, offs = 0;
#if PACKETVER < 20110824
header = 0xaa;
success = (ok==1);
#elif PACKETVER < 20120925
header = 0x8d0;
success = ok ? 0:1;
#else
header = 0x999;
success = ok ? 0:1;
#endif
nullpo_retv(sd);
fd=sd->fd;
fd = sd->fd;
WFIFOHEAD(fd,packet_len(header));
WFIFOW(fd,offs+0)=header;
WFIFOW(fd,offs+2)=n+2;
WFIFOW(fd,offs+0) = header;
WFIFOW(fd,offs+2) = n+2;
#if PACKETVER >= 20120925
WFIFOL(fd,offs+4)=pos;
offs+=2;
WFIFOL(fd,offs+4) = pos;
offs += 2;
#else
WFIFOW(fd,offs+4)=(int)pos;
WFIFOW(fd,offs+4) = (int)pos;
#endif
#if PACKETVER < 20100629
WFIFOB(fd,offs+6)=success;
WFIFOB(fd,offs+6) = flag;
#else
if (ok && sd->inventory_data[n]->equip&EQP_VISIBLE)
WFIFOW(fd,offs+6)=sd->inventory_data[n]->look;
if (flag == ITEM_EQUIP_ACK_OK && sd->inventory_data[n]->equip&EQP_VISIBLE)
WFIFOW(fd,offs+6) = sd->inventory_data[n]->look;
else
WFIFOW(fd,offs+6)=0;
WFIFOB(fd,offs+8)=success;
WFIFOW(fd,offs+6) = 0;
WFIFOB(fd,offs+8) = flag;
#endif
WFIFOSET(fd,packet_len(header));
}
@ -10743,7 +10740,7 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd)
return;
if(!sd->status.inventory[index].identify) {
clif_equipitemack(sd,index,0,0); // fail
clif_equipitemack(sd,index,0,ITEM_EQUIP_ACK_FAIL); // fail
return;
}

View File

@ -364,8 +364,27 @@ enum useskill_fail_cause
};
enum clif_messages {
/* Constant values */
ADDITEM_TO_CART_FAIL_WEIGHT = 0x0,
ADDITEM_TO_CART_FAIL_COUNT = 0x1,
// clif_equipitemack flag
#if PACKETVER < 20110824
ITEM_EQUIP_ACK_OK = 1,
ITEM_EQUIP_ACK_FAIL = 0,
ITEM_EQUIP_ACK_FAILLEVEL = 0,
#elif PACKETVER < 20120925
ITEM_EQUIP_ACK_OK = 0,
ITEM_EQUIP_ACK_FAIL = 1,
ITEM_EQUIP_ACK_FAILLEVEL = 1,
#else
ITEM_EQUIP_ACK_OK = 0,
ITEM_EQUIP_ACK_FAIL = 1,
ITEM_EQUIP_ACK_FAILLEVEL = 2,
#endif
/* -end- */
//! NOTE: These values below need client version validation
ITEM_CANT_OBTAIN_WEIGHT = 0x34, /* You cannot carry more items because you are overweight. */
ITEM_NOUSE_SITTING = 0x297,
MERC_MSG_BASE = 0x4f2,
@ -461,7 +480,7 @@ void clif_arrowequip(struct map_session_data *sd,int val); //self
void clif_arrow_fail(struct map_session_data *sd,int type); //self
void clif_arrow_create_list(struct map_session_data *sd); //self
void clif_statusupack(struct map_session_data *sd,int type,int ok,int val); // self
void clif_equipitemack(struct map_session_data *sd,int n,int pos,int ok); // self
void clif_equipitemack(struct map_session_data *sd,int n,int pos,uint8 flag); // self
void clif_unequipitemack(struct map_session_data *sd,int n,int pos,int ok); // self
void clif_misceffect(struct block_list* bl,int type); // area
void clif_changeoption(struct block_list* bl); // area

View File

@ -1095,7 +1095,6 @@ static char itemdb_gendercheck(struct item_data *id)
* For backwards compatibility, in Renewal mode, MATK from weapons comes from the atk slot
* We use a ':' delimiter which, if not found, assumes the weapon does not provide any matk.
**/
#ifdef RENEWAL
static void itemdb_re_split_atoi(char *str, int *val1, int *val2) {
int i, val[2];
@ -1120,7 +1119,7 @@ static void itemdb_re_split_atoi(char *str, int *val1, int *val2) {
*val2 = val[1];
return;
}
#endif
/**
* Processes one itemdb entry
*/
@ -1221,11 +1220,7 @@ static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scr
}
id->wlv = cap_value(atoi(str[15]), REFINE_TYPE_ARMOR, REFINE_TYPE_MAX);
#ifdef RENEWAL
itemdb_re_split_atoi(str[16],&id->elv,&id->elvmax);
#else
id->elv = atoi(str[16]);
#endif
id->flag.no_refine = atoi(str[17]) ? 0 : 1; //FIXME: verify this
id->look = atoi(str[18]);

View File

@ -386,11 +386,11 @@ struct item_data
int slot;
int look;
int elv;
int elvmax; ///< Maximum level for this item
int wlv;
int view_id;
#ifdef RENEWAL
int matk;
int elvmax;/* maximum level for this item */
#endif
int delay;

View File

@ -1813,8 +1813,8 @@ int map_quit(struct map_session_data *sd) {
for (i = 0; i < EQI_MAX; i++) {
if (sd->equip_index[i] >= 0)
if (!pc_isequip(sd,sd->equip_index[i]))
pc_unequipitem(sd,sd->equip_index[i],2);
if (pc_isequip(sd,sd->equip_index[i]) != ITEM_EQUIP_ACK_OK)
pc_unequipitem(sd,sd->equip_index[i],ITEM_EQUIP_ACK_FAIL);
}
// Return loot to owner

View File

@ -998,49 +998,46 @@ static bool pc_isItemClass (struct map_session_data *sd, struct item_data* item)
* Checks if the player can equip the item at index n in inventory.
* @param sd
* @param n Item index in inventory
* @return True - Can be equipped, False - failed
* @return ITEM_EQUIP_ACK_OK if can be equipped, or ITEM_EQUIP_ACK_FAIL/ITEM_EQUIP_ACK_FAILLEVEL if can't
*------------------------------------------------*/
bool pc_isequip(struct map_session_data *sd,int n)
uint8 pc_isequip(struct map_session_data *sd,int n)
{
struct item_data *item;
nullpo_ret(sd);
nullpo_retr(ITEM_EQUIP_ACK_FAIL, sd);
item = sd->inventory_data[n];
if(pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT))
return true;
return ITEM_EQUIP_ACK_OK;
if(item == NULL)
return false;
return ITEM_EQUIP_ACK_FAIL;
if(item->elv && sd->status.base_level < (unsigned int)item->elv)
return false;
#ifdef RENEWAL
return ITEM_EQUIP_ACK_FAILLEVEL;
if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax)
return false;
#endif
return ITEM_EQUIP_ACK_FAILLEVEL;
if(item->sex != 2 && sd->status.sex != item->sex)
return false;
return ITEM_EQUIP_ACK_FAIL;
if (sd->sc.count) {
if(item->equip & EQP_ARMS && item->type == IT_WEAPON && sd->sc.data[SC_STRIPWEAPON]) // Also works with left-hand weapons [DracoRPG]
return false;
return ITEM_EQUIP_ACK_FAIL;
if(item->equip & EQP_SHIELD && item->type == IT_ARMOR && sd->sc.data[SC_STRIPSHIELD])
return false;
return ITEM_EQUIP_ACK_FAIL;
if(item->equip & EQP_ARMOR && sd->sc.data[SC_STRIPARMOR])
return false;
return ITEM_EQUIP_ACK_FAIL;
if(item->equip & EQP_HEAD_TOP && sd->sc.data[SC_STRIPHELM])
return false;
return ITEM_EQUIP_ACK_FAIL;
if(item->equip & EQP_ACC && sd->sc.data[SC__STRIPACCESSORY])
return false;
return ITEM_EQUIP_ACK_FAIL;
if(item->equip && sd->sc.data[SC_KYOUGAKU])
return false;
return ITEM_EQUIP_ACK_FAIL;
if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SUPERNOVICE) {
//Spirit of Super Novice equip bonuses. [Skotlex]
if (sd->status.base_level > 90 && item->equip & EQP_HELM)
return true; //Can equip all helms
return ITEM_EQUIP_ACK_FAIL; //Can equip all helms
if (sd->status.base_level > 96 && item->equip & EQP_ARMS && item->type == IT_WEAPON && item->wlv == 4)
switch(item->look) { //In weapons, the look determines type of weapon.
@ -1050,23 +1047,23 @@ bool pc_isequip(struct map_session_data *sd,int n)
case W_MACE: //All level 4 - 1H Maces
case W_STAFF: //All level 4 - 1H Staves
case W_2HSTAFF: //All level 4 - 2H Staves
return true;
return ITEM_EQUIP_ACK_OK;
}
}
}
//fail to equip if item is restricted
if (!battle_config.allow_equip_restricted_item && itemdb_isNoEquip(item, sd->bl.m))
return false;
return ITEM_EQUIP_ACK_FAIL;
//Not equipable by class. [Skotlex]
if (!(1<<(sd->class_&MAPID_BASEMASK)&item->class_base[(sd->class_&JOBL_2_1)?1:((sd->class_&JOBL_2_2)?2:0)]))
return false;
return ITEM_EQUIP_ACK_FAIL;
if (!pc_isItemClass(sd,item))
return false;
return ITEM_EQUIP_ACK_FAIL;
return true;
return ITEM_EQUIP_ACK_OK;
}
/*==========================================
@ -4637,11 +4634,8 @@ bool pc_isUseitem(struct map_session_data *sd,int n)
//Required level check
if(item->elv && sd->status.base_level < (unsigned int)item->elv)
return false;
#ifdef RENEWAL
if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax)
return false;
#endif
//Not equipable by class. [Skotlex]
if (!(
@ -5207,9 +5201,9 @@ char pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int
status_change_end(&sd->bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
}
for( i = 0; i < EQI_MAX; i++ ) {
if( sd->equip_index[ i ] >= 0 )
if( !pc_isequip( sd , sd->equip_index[ i ] ) )
pc_unequipitem( sd , sd->equip_index[ i ] , 2 );
if( sd->equip_index[i] >= 0 )
if( pc_isequip(sd,sd->equip_index[i]) != ITEM_EQUIP_ACK_OK )
pc_unequipitem(sd,sd->equip_index[i],ITEM_EQUIP_ACK_FAIL );
}
if (battle_config.clear_unit_onwarp&BL_PC)
skill_clear_unitgroup(&sd->bl);
@ -6199,17 +6193,15 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
}
void pc_baselevelchanged(struct map_session_data *sd) {
#ifdef RENEWAL
int i;
uint8 i;
for( i = 0; i < EQI_MAX; i++ ) {
if( sd->equip_index[i] >= 0 ) {
if( sd->inventory_data[ sd->equip_index[i] ]->elvmax && sd->status.base_level > (unsigned int)sd->inventory_data[ sd->equip_index[i] ]->elvmax )
pc_unequipitem(sd, sd->equip_index[i], 3);
}
}
#endif
}
int pc_checkjoblevelup(struct map_session_data *sd)
{
unsigned int next = pc_nextjobexp(sd);
@ -6819,8 +6811,8 @@ int pc_resetlvl(struct map_session_data* sd,int type)
for(i=0;i<EQI_MAX;i++) { // unequip items that can't be equipped by base 1 [Valaris]
if(sd->equip_index[i] >= 0)
if(!pc_isequip(sd,sd->equip_index[i]))
pc_unequipitem(sd,sd->equip_index[i],2);
if(pc_isequip(sd,sd->equip_index[i]) != ITEM_EQUIP_ACK_OK)
pc_unequipitem(sd,sd->equip_index[i],ITEM_EQUIP_ACK_FAILLEVEL);
}
if ((type == 1 || type == 2 || type == 3) && sd->status.party_id)
@ -8096,8 +8088,8 @@ bool pc_jobchange(struct map_session_data *sd,int job, char upper)
for(i=0;i<EQI_MAX;i++) {
if(sd->equip_index[i] >= 0)
if(!pc_isequip(sd,sd->equip_index[i]))
pc_unequipitem(sd,sd->equip_index[i],2); // unequip invalid item for class
if(pc_isequip(sd,sd->equip_index[i]) != ITEM_EQUIP_ACK_OK)
pc_unequipitem(sd,sd->equip_index[i],ITEM_EQUIP_ACK_FAILLEVEL); // unequip invalid item for class
}
//Change look, if disguised, you need to undisguise
@ -9135,17 +9127,18 @@ int pc_load_combo(struct map_session_data *sd) {
*------------------------------------------*/
bool pc_equipitem(struct map_session_data *sd,short n,int req_pos)
{
int i,pos,flag=0,iflag;
int i, pos, flag = 0, iflag;
struct item_data *id;
uint8 res = ITEM_EQUIP_ACK_OK;
nullpo_retr(false,sd);
if( n < 0 || n >= MAX_INVENTORY ) {
clif_equipitemack(sd,0,0,0);
clif_equipitemack(sd,0,0,ITEM_EQUIP_ACK_FAIL);
return false;
}
if( DIFF_TICK(sd->canequip_tick,gettick()) > 0 ) {
clif_equipitemack(sd,n,0,0);
clif_equipitemack(sd,n,0,ITEM_EQUIP_ACK_FAIL);
return false;
}
@ -9156,14 +9149,18 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos)
if(battle_config.battle_log)
ShowInfo("equip %hu(%d) %x:%x\n",sd->status.inventory[n].nameid,n,id?id->equip:0,req_pos);
if(!pc_isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris]
// FIXME: pc_isequip: equip level failure uses 2 instead of 0
clif_equipitemack(sd,n,0,0); // fail
if((res = pc_isequip(sd,n)) != ITEM_EQUIP_ACK_OK) {
clif_equipitemack(sd,n,0,res); // fail
return false;
}
if (!(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris]
clif_equipitemack(sd,n,0,ITEM_EQUIP_ACK_FAIL); // fail
return false;
}
if( sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] ||
sd->sc.data[SC_KYOUGAKU] || (sd->sc.data[SC_PYROCLASTIC] && sd->inventory_data[n]->type == IT_WEAPON)) ) {
clif_equipitemack(sd,n,0,0); //Fail
clif_equipitemack(sd,n,0,ITEM_EQUIP_ACK_FAIL); //Fail
return false;
}
@ -9213,7 +9210,7 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos)
clif_arrow_fail(sd,3);
}
else
clif_equipitemack(sd,n,pos,1);
clif_equipitemack(sd,n,pos,ITEM_EQUIP_ACK_OK);
sd->status.inventory[n].equip=pos;

View File

@ -845,7 +845,7 @@ void pc_reg_received(struct map_session_data *sd);
void pc_close_npc(struct map_session_data *sd,int flag);
int pc_close_npc_timer(int tid, unsigned int tick, int id, intptr_t data);
bool pc_isequip(struct map_session_data *sd,int n);
uint8 pc_isequip(struct map_session_data *sd,int n);
int pc_equippoint(struct map_session_data *sd,int n);
void pc_setinventorydata(struct map_session_data *sd);

View File

@ -868,7 +868,7 @@ int pet_equipitem(struct map_session_data *sd,int index)
nameid = sd->status.inventory[index].nameid;
if(pd->petDB->AcceID == 0 || nameid != pd->petDB->AcceID || pd->pet.equip != 0) {
clif_equipitemack(sd,0,0,0);
clif_equipitemack(sd,0,0,ITEM_EQUIP_ACK_FAIL);
return 1;
}