From fa75733cc109f926b1df4156ccdf1292c78f8f79 Mon Sep 17 00:00:00 2001 From: Cydh Ramdh Date: Thu, 15 Jan 2015 01:17:54 +0700 Subject: [PATCH] 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 --- db/import-tmpl/item_db.txt | 2 +- db/pre-re/item_db.txt | 2 +- db/re/item_db.txt | 2 +- doc/item_db.txt | 4 ++ src/map/clif.c | 31 ++++++-------- src/map/clif.h | 21 ++++++++- src/map/itemdb.c | 7 +-- src/map/itemdb.h | 2 +- src/map/map.c | 4 +- src/map/pc.c | 87 ++++++++++++++++++-------------------- src/map/pc.h | 2 +- src/map/pet.c | 2 +- 12 files changed, 89 insertions(+), 77 deletions(-) diff --git a/db/import-tmpl/item_db.txt b/db/import-tmpl/item_db.txt index f06740c54c..eb24248723 100644 --- a/db/import-tmpl/item_db.txt +++ b/db/import-tmpl/item_db.txt @@ -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 //============================================================= diff --git a/db/pre-re/item_db.txt b/db/pre-re/item_db.txt index 3258f62c26..8bcdfbf91c 100644 --- a/db/pre-re/item_db.txt +++ b/db/pre-re/item_db.txt @@ -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 //============================================================= diff --git a/db/re/item_db.txt b/db/re/item_db.txt index cffdfb141d..19e2afc448 100644 --- a/db/re/item_db.txt +++ b/db/re/item_db.txt @@ -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 //============================================================= diff --git a/doc/item_db.txt b/doc/item_db.txt index 1247466b6f..2591a33f93 100644 --- a/doc/item_db.txt +++ b/doc/item_db.txt @@ -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. diff --git a/src/map/clif.c b/src/map/clif.c index 4b4ca2cfe7..3b7f24329e 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -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; } diff --git a/src/map/clif.h b/src/map/clif.h index 7b71305a78..4a7cc2f77a 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -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 diff --git a/src/map/itemdb.c b/src/map/itemdb.c index de81edcb92..9af6b72456 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -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]); diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 8a8223fbb6..4956786b60 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -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; diff --git a/src/map/map.c b/src/map/map.c index a3f5150597..37cd783faf 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -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 diff --git a/src/map/pc.c b/src/map/pc.c index 7e99d80886..7bba12728b 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -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;iequip_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;iequip_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; diff --git a/src/map/pc.h b/src/map/pc.h index eb2619c365..a7b098f999 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -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); diff --git a/src/map/pet.c b/src/map/pet.c index f7b8eeae23..71c332adfc 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -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; }