Quellcode durchsuchen

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>

Cydh Ramdh vor 10 Jahren
Ursprung
Commit
fa75733cc1
12 geänderte Dateien mit 89 neuen und 77 gelöschten Zeilen
  1. 1 1
      db/import-tmpl/item_db.txt
  2. 1 1
      db/pre-re/item_db.txt
  3. 1 1
      db/re/item_db.txt
  4. 4 0
      doc/item_db.txt
  5. 14 17
      src/map/clif.c
  6. 20 1
      src/map/clif.h
  7. 1 6
      src/map/itemdb.c
  8. 1 1
      src/map/itemdb.h
  9. 2 2
      src/map/map.c
  10. 42 45
      src/map/pc.c
  11. 1 1
      src/map/pc.h
  12. 1 1
      src/map/pet.c

+ 1 - 1
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
 //=============================================================

+ 1 - 1
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
 //=============================================================

+ 1 - 1
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
 //=============================================================

+ 4 - 0
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.

+ 14 - 17
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;
 	}
 

+ 20 - 1
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

+ 1 - 6
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]);
 

+ 1 - 1
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;

+ 2 - 2
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

+ 42 - 45
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;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;
 

+ 1 - 1
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);
 

+ 1 - 1
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;
 	}