Преглед на файлове

* Follow-up 15074d8
- Fix item restriction check that should only prevent the item script. ATK, DEF, and MATK for RE should be calculated (Thank Euphy)
- Added item restriction check for combo items
- Added some missing item restriction checks

Cahyadi Ramadhan Togihon преди 11 години
родител
ревизия
7d72060430
променени са 6 файла, в които са добавени 65 реда и са изтрити 25 реда
  1. 7 7
      src/map/itemdb.h
  2. 1 1
      src/map/map.h
  3. 18 5
      src/map/pc.c
  4. 8 0
      src/map/pc.h
  5. 1 1
      src/map/skill.h
  6. 30 11
      src/map/status.c

+ 7 - 7
src/map/itemdb.h

@@ -40,7 +40,7 @@ enum item_itemid {
  * Rune Knight
  **/
 
-enum {
+enum rune_list {
 	ITEMID_NAUTHIZ = 12725,
 	ITEMID_RAIDO,
 	ITEMID_BERKANA,
@@ -50,12 +50,12 @@ enum {
 	ITEMID_THURISAZ,
 	ITEMID_WYRD,
 	ITEMID_HAGALAZ,
-} rune_list;
+};
 
 /**
  * Mechanic
  **/
-enum {
+enum mecha_item_list {
 	ITEMID_ACCELERATOR = 2800,
 	ITEMID_HOVERING_BOOSTER,
 	ITEMID_SUICIDAL_DEVICE,
@@ -67,11 +67,11 @@ enum {
 	ITEMID_CAMOUFLAGE_GENERATOR,
 	ITEMID_HIGH_QUALITY_COOLER,
 	ITEMID_SPECIAL_COOLER,
-} mecha_item_list;
+};
 
-enum {
+enum item_nouse_list {
 	NOUSE_SITTING = 0x01,
-} item_nouse_list;
+};
 
 enum e_item_job {
 	ITEMJ_NORMAL      = 0x01,
@@ -137,7 +137,7 @@ struct item_data {
 	struct script_code *unequip_script;//Script executed once when unequipping.
 	struct {
 		unsigned available : 1;
-		short no_equip;
+		uint32 no_equip;
 		unsigned no_refine : 1;	// [celest]
 		unsigned delay_consume : 1;	// Signifies items that are not consumed immediately upon double-click [Skotlex]
 		unsigned trade_restriction : 9;	//Item restrictions mask [Skotlex]

+ 1 - 1
src/map/map.h

@@ -612,7 +612,7 @@ struct map_data {
 
 	struct spawn_data *moblist[MAX_MOB_LIST_PER_MAP]; // [Wizputer]
 	int mob_delete_timer;	// [Skotlex]
-	int zone;	// zone number (for item/skill restrictions)
+	uint32 zone;	// zone number (for item/skill restrictions)
 	int nocommand; //Blocks @/# commands for non-gms. [Skotlex]
 	struct {
 		int jexp;	// map experience multiplicator

+ 18 - 5
src/map/pc.c

@@ -8458,6 +8458,8 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
 	int index, idx, success = 0;
 
 	for( i = 0; i < data->combos_count; i++ ) {
+		struct s_combo_pair *pair;
+		uint8 pair_idx = 0;
 
 		/* ensure this isn't a duplicate combo */
 		if( sd->combos.bonus != NULL ) {
@@ -8469,6 +8471,7 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
 				continue;
 		}
 
+		CREATE(pair,struct s_combo_pair,1);
 		for( j = 0; j < data->combos[i]->count; j++ ) {
 			int id = data->combos[i]->nameid[j];
 			bool found = false;
@@ -8488,6 +8491,8 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
 						continue;
 
 					found = true;
+					pair->nameid[pair_idx] = id;
+					pair_idx ++;
 					break;
 				} else { //Cards
 					if ( sd->inventory_data[index]->slot == 0 || itemdb_isspecial(sd->status.inventory[index].card[0]) )
@@ -8500,6 +8505,8 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
 
 						// We have found a match
 						found = true;
+						pair->nameid[pair_idx] = id;
+						pair_idx ++;
 						break;
 					}
 				}
@@ -8515,22 +8522,24 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
 			continue;
 
 		/* we got here, means all items in the combo are matching */
-
 		idx = sd->combos.count;
-
 		if( sd->combos.bonus == NULL ) {
 			CREATE(sd->combos.bonus, struct script_code *, 1);
 			CREATE(sd->combos.id, unsigned short, 1);
 			sd->combos.count = 1;
+			CREATE(sd->combos.pair, struct s_combo_pair *, 1);
 		} else {
 			RECREATE(sd->combos.bonus, struct script_code *, ++sd->combos.count);
 			RECREATE(sd->combos.id, unsigned short, sd->combos.count);
+			RECREATE(sd->combos.pair, struct s_combo_pair *, sd->combos.count);
 		}
-
 		/* we simply copy the pointer */
 		sd->combos.bonus[idx] = data->combos[i]->script;
 		/* save this combo's id */
 		sd->combos.id[idx] = data->combos[i]->id;
+		/* store the items id that trigger this combo */
+		memcpy(&sd->combos.pair[idx], pair, sizeof(pair));
+		aFree(pair);
 
 		success++;
 	}
@@ -8553,7 +8562,10 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
 
 		sd->combos.bonus[x] = NULL;
 		sd->combos.id[x] = 0;
+		sd->combos.pair[x] = NULL;
 		retval++;
+
+		/* move next value to empty slot */
 		for( j = 0, cursor = 0; j < sd->combos.count; j++ ) {
 			if( sd->combos.bonus[j] == NULL )
 				continue;
@@ -8561,8 +8573,8 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
 			if( cursor != j ) {
 				sd->combos.bonus[cursor] = sd->combos.bonus[j];
 				sd->combos.id[cursor]    = sd->combos.id[j];
+				sd->combos.pair[cursor]  = sd->combos.pair[j];
 			}
-
 			cursor++;
 		}
 
@@ -8574,11 +8586,12 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
 		if( (sd->combos.count = cursor) == 0 ) {
 			aFree(sd->combos.bonus);
 			aFree(sd->combos.id);
+			aFree(sd->combos.pair);
 			sd->combos.bonus = NULL;
 			sd->combos.id = NULL;
+			sd->combos.pair = NULL;
 			return retval; /* we also can return at this point for we have no more combos to check */
 		}
-
 	}
 
 	return retval;

+ 8 - 0
src/map/pc.h

@@ -121,6 +121,13 @@ enum npc_timeout_type {
 	NPCT_WAIT  = 2,
 };
 
+/*
+ * Combo's items
+ */
+struct s_combo_pair {
+	uint16 nameid[MAX_ITEMS_PER_COMBO];
+};
+
 struct map_session_data {
 	struct block_list bl;
 	struct unit_data ud;
@@ -504,6 +511,7 @@ struct map_session_data {
 		struct script_code **bonus;/* the script */
 		unsigned short *id;/* array of combo ids */
 		unsigned char count;
+		struct s_combo_pair **pair;
 	} combos;
 
 	/**

+ 1 - 1
src/map/skill.h

@@ -126,7 +126,7 @@ struct s_skill_db {
 	int weapon,ammo,ammo_qty[MAX_SKILL_LEVEL],state,spiritball[MAX_SKILL_LEVEL];
 	int itemid[MAX_SKILL_ITEM_REQUIRE],amount[MAX_SKILL_ITEM_REQUIRE];
 	int castnodex[MAX_SKILL_LEVEL], delaynodex[MAX_SKILL_LEVEL];
-	int nocast;
+	int32 nocast;
 	int unit_id[2];
 	int unit_layout_type[MAX_SKILL_LEVEL];
 	int unit_range[MAX_SKILL_LEVEL];

+ 30 - 11
src/map/status.c

@@ -2461,12 +2461,10 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 		if(!sd->inventory_data[index])
 			continue;
 
-		if(!pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) && itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m)) // Items may be equipped, their effects however are nullified.
-			continue;
-
 		status->def += sd->inventory_data[index]->def;
 
-		if(first && sd->inventory_data[index]->equip_script)
+		// Items may be equipped, their effects however are nullified.
+		if(first && sd->inventory_data[index]->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m)))
 	  	{	//Execute equip-script on login
 			run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
 			if (!calculating)
@@ -2506,7 +2504,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 				wd->overrefine = refine_info[wlv].randombonus_max[r-1] / 100;
 
 			wa->range += sd->inventory_data[index]->range;
-			if(sd->inventory_data[index]->script) {
+			if(sd->inventory_data[index]->script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) {
 				if (wd == &sd->left_weapon) {
 					sd->state.lr_flag = 1;
 					run_script(sd->inventory_data[index]->script,0,sd->bl.id,0);
@@ -2532,7 +2530,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 			int r;
 			if ( (r = sd->status.inventory[index].refine) )
 				refinedef += refine_info[REFINE_TYPE_ARMOR].bonus[r-1];
-			if(sd->inventory_data[index]->script) {
+			if(sd->inventory_data[index]->script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) {
 				if( i == EQI_HAND_L ) //Shield
 					sd->state.lr_flag = 3;
 				run_script(sd->inventory_data[index]->script,0,sd->bl.id,0);
@@ -2557,9 +2555,31 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 		}
 	}
 
-	/* we've got combos to process */
+	/* we've got combos to process and check */
 	if( sd->combos.count ) {
-		for( i = 0; i < sd->combos.count; i++ ) {
+		for (i = 0; i < sd->combos.count; i++) {
+			uint8 j;
+			bool no_run = false;
+			struct s_combo_pair *ids;
+			if (!sd->combos.bonus[i])
+				continue;
+			/* check combo items */
+			CREATE(ids,struct s_combo_pair,1);
+			memcpy(ids, &sd->combos.pair[i], sizeof(ids));
+			for (j = 0; j < MAX_ITEMS_PER_COMBO; j++) {
+				uint16 nameid = ids->nameid[j];
+				struct item_data *id = NULL;
+				if (!nameid || !(id = itemdb_exists(nameid)))
+					continue;
+				/* don't run the script if the items has restriction */
+				if (!pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT) && itemdb_isNoEquip(id, sd->bl.m)) {
+					no_run = true;
+					break;
+				}
+			}
+			aFree(ids);
+			if (no_run)
+				continue;
 			run_script(sd->combos.bonus[i],0,sd->bl.id,0);
 			if (!calculating) //Abort, run_script retriggered this.
 				return 1;
@@ -2598,7 +2618,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 				data = itemdb_exists(c);
 				if(!data)
 					continue;
-				if(first && data->equip_script) {//Execute equip-script on login
+				if(first && data->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(data,sd->bl.m))) {//Execute equip-script on login
 					run_script(data->equip_script,0,sd->bl.id,0);
 					if (!calculating)
 						return 1;
@@ -2607,8 +2627,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 					continue;
 				if(!pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) && itemdb_isNoEquip(data,sd->bl.m)) //Card restriction checks.
 					continue;
-				if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L)
-				{	//Left hand status.
+				if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) {	//Left hand status.
 					sd->state.lr_flag = 1;
 					run_script(data->script,0,sd->bl.id,0);
 					sd->state.lr_flag = 0;