Ver Fonte

- Modified the way autospells stack to mimic official servers. Cards of the same ID cannot stack, but different cards with the same skill can each trigger indepedently of each other.
- Added battle_config autospell_stacking to enable stacking of cards of same ID.
- Moved card-specific battle options to items.conf
- Autospells triggered when hit will check the range to the target.
- Some cleaning up of status_calc_pc
- In status_change_start capped the passed success chance to 100%


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@5377 54d463be-8e91-2dee-dedb-b68131a5f0ec

skotlex há 19 anos atrás
pai
commit
90ec4f1d14

+ 11 - 0
Changelog-Trunk.txt

@@ -4,6 +4,17 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.  EVERYTHING ELSE
 GOES INTO TRUNK AND WILL BE MERGED INTO STABLE BY VALARIS AND WIZPUTER. -- VALARIS
 
+2006/02/23
+	* Modified the way autospells stack to mimic official servers. Cards of the
+	  same ID cannot stack, but different cards with the same skill can each
+	  trigger indepedently of each other. [Skotlex]
+	* Added battle_config autospell_stacking to enable stacking of cards of
+	  same ID. (see battle/item.conf) [Skotlex]
+	* Moved card-specific battle options to items.conf [Skotlex]
+	* Autospells triggered when hit will check the range to the target.
+	  [Skotlex]
+	* Some cleaning up of status_calc_pc [Skotlex]
+	* In status_change_start capped the passed success chance to 100% [Skotlex]
 2006/02/22
 	* Windwalk's flee bonus is now +1 every 2 skill lvs. [Skotlex]
 	* Changed the way equipment breaking works. Function pc_break_equip was

+ 2 - 2
Dev/todo-for-stable.txt

@@ -18,8 +18,6 @@ stable. Remove it from the list once merged.
   assassins.
 - Deleting pet eggs from inventory after the pet data has arrived, not upon
   hatching request.
-- Updated the char-SQL server to use auto-incremental IDs and retrieve them
-  from code.
 - Battle option pk_level_range, allow_es_magic_player
 - Cleanup of pc_useitem code
 - Autocasted Teleport should now show a menu.
@@ -33,3 +31,5 @@ stable. Remove it from the list once merged.
 - Send the guild/party mini-dots on map-login.
 - Updated the path-finding routines from jA
 - Replace pc_break_equip for skill_break_equip
+- Battle function autoskill_stacking
+- The new non-stackable autospell implementation.

+ 0 - 8
conf-tmpl/battle/battle.conf

@@ -144,14 +144,6 @@ delay_battle_damage: yes
 // Are arrows are consumed when used on a bow? (Note 1)
 arrow_decrement: yes
 
-// The ghostring fix makes mob attacks not be affected by ghostring armor wearing players.
-mob_ghostring_fix: yes
-
-// Does the Golden Thief Bug card only work during pvp?
-// no or 0 - gtb works all the time
-// 1 - 100 - percentage of magic damage reduced only during pvp (or gvg)
-gtb_pvp_only: no
-
 // Adjustment for the natural rate of resistance from status changes.
 // If 50, status defense is halved, and you need twice as much stats to block
 // them (eg: 200 vit to completely block stun)

+ 13 - 0
conf-tmpl/battle/items.conf

@@ -71,3 +71,16 @@ item_check: no
 // How much time must pass between item uses?
 // Only affects the delay between using items, prevents healing item abuse. Recommended ~500 ms
 item_use_interval: 0
+
+// The ghostring fix makes mob attacks not be affected by ghostring armor wearing players.
+mob_ghostring_fix: yes
+
+// Does the Golden Thief Bug card only work during pvp?
+// no or 0 - gtb works all the time
+// 1 - 100 - percentage of magic damage reduced only during pvp (or gvg)
+gtb_pvp_only: no
+
+// Enable autospell card effects to stack?
+// NOTE: Different cards that grant the same skill will both 
+// always work independently of each other regardless of setting.
+autospell_stacking: no

+ 1 - 1
conf-tmpl/battle_athena.conf

@@ -35,7 +35,7 @@ import: conf/battle/gm.conf
 //Guild and WoE settings
 import: conf/battle/guild.conf
 
-//Item-specific and crafting related options.
+//Item/card-specific and crafting related options.
 import: conf/battle/items.conf
 
 //Mob related configuration

+ 1 - 1
src/char_sql/char.c

@@ -3217,7 +3217,7 @@ int parse_char(int fd) {
 			WFIFOL(fd,2+28) = char_dat[i].karma;
 			WFIFOL(fd,2+32) = char_dat[i].manner;
 
-			WFIFOW(fd,2+40) = 0x30; 
+			WFIFOW(fd,2+40) = 0x30;
 			WFIFOW(fd,2+42) = (char_dat[i].hp > 0x7fff) ? 0x7fff : char_dat[i].hp;
 			WFIFOW(fd,2+44) = (char_dat[i].max_hp > 0x7fff) ? 0x7fff : char_dat[i].max_hp;
 			WFIFOW(fd,2+46) = (char_dat[i].sp > 0x7fff) ? 0x7fff : char_dat[i].sp;

+ 2 - 0
src/map/battle.c

@@ -3821,6 +3821,7 @@ static const struct battle_data_short {
 	{ "pc_max_status_def",					&battle_config.pc_max_sc_def },
 	{ "mob_max_status_def",					&battle_config.mob_max_sc_def },
 	{ "sg_miracle_skill_ratio",				&battle_config.sg_miracle_skill_ratio },
+	{ "autospell_stacking", 				&battle_config.autospell_stacking },
 };
 
 static const struct battle_data_int {
@@ -4220,6 +4221,7 @@ void battle_set_defaults() {
 	battle_config.mob_max_sc_def = 5000;
 	battle_config.sg_miracle_skill_ratio=1;
 	battle_config.sg_miracle_skill_duration=600000;
+	battle_config.autospell_stacking = 0;
 }
 
 void battle_validate_conf() {

+ 1 - 0
src/map/battle.h

@@ -429,6 +429,7 @@ extern struct Battle_Config {
 
 	unsigned short sg_miracle_skill_ratio;
 	int sg_miracle_skill_duration;
+	unsigned short autospell_stacking; //Enables autospell cards to stack. [Skotlex]
 
 } battle_config;
 

+ 1 - 1
src/map/clif.c

@@ -3033,7 +3033,7 @@ int clif_updatestatus(struct map_session_data *sd,int type)
 	if ( !session_isActive(fd) ) // Invalid pointer fix, by sasuke [Kevin]
 		return 0;
  
-        WFIFOHEAD(fd, 14);
+	WFIFOHEAD(fd, 14);
 	WFIFOW(fd,0)=0xb0;
 	WFIFOW(fd,2)=type;
 	switch(type){

+ 2 - 2
src/map/map.h

@@ -578,8 +578,8 @@ struct map_session_data {
   	short unequip_losesp[11];
  	// zeroed arrays end here.
 	// zeroed structures start here
-	struct {
-		short id, lv, rate;
+	struct s_autospell{
+		short id, lv, rate, card_id;
 	} autospell[MAX_PC_BONUS], autospell2[MAX_PC_BONUS];
 	struct { //skillatk raises bonus dmg% of skills, skillblown increases bonus blewcount for some skills.
 		short id, val;

+ 31 - 53
src/map/pc.c

@@ -1126,6 +1126,29 @@ int pc_checkweighticon(struct map_session_data *sd)
 	return 0;
 }
 
+static int pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, short rate, short card_id) {
+	int i;
+	for (i = 0; i < max && spell[i].id; i++) {
+		if (spell[i].card_id == card_id &&
+			spell[i].id == id && spell[i].lv == lv)
+		{
+			if (!battle_config.autospell_stacking)
+				return 0;
+			rate += spell[i].rate;
+			break;
+		}
+	}
+	if (i == max) {
+		if (battle_config.error_log)
+			ShowWarning("pc_bonus: Reached max (%d) number of autospells per character!\n", max);
+		return 0;
+	}
+	spell[i].id = id;
+	spell[i].lv = lv;
+	spell[i].rate = rate;
+	spell[i].card_id = card_id;
+	return 1;
+}
 /*==========================================
  * ? 備品による能力等のボ?ナス設定
  *------------------------------------------
@@ -2044,34 +2067,12 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
 		}
 		break;
 	case SP_AUTOSPELL:
-		if(sd->state.lr_flag != 2) {
-			for (i = 0; i < MAX_PC_BONUS; i++) {
-				if (sd->autospell[i].id == 0 ||
-					(sd->autospell[i].id == type2 && sd->autospell[i].lv < type3) ||
-					(sd->autospell[i].id == type2 && sd->autospell[i].lv == type3 && sd->autospell[i].rate < val))
-				{
-					sd->autospell[i].id = type2;
-					sd->autospell[i].lv = type3;
-					sd->autospell[i].rate = val;
-					break;
-				}
-			}
-		}
+		if(sd->state.lr_flag != 2)
+			pc_bonus_autospell(sd->autospell, MAX_PC_BONUS, type2, type3, val, current_equip_card_id);
 		break;
 	case SP_AUTOSPELL_WHENHIT:
-		if(sd->state.lr_flag != 2) {
-			for (i = 0; i < MAX_PC_BONUS; i++) {
-				if (sd->autospell2[i].id == 0 ||
-					(sd->autospell2[i].id == type2 && sd->autospell2[i].lv < type3) ||
-					(sd->autospell2[i].id == type2 && sd->autospell2[i].lv == type3 && sd->autospell2[i].rate < val))
-				{
-					sd->autospell2[i].id = type2;
-					sd->autospell2[i].lv = type3;
-					sd->autospell2[i].rate = val;
-					break;
-				}
-			}
-		}
+		if(sd->state.lr_flag != 2)
+			pc_bonus_autospell(sd->autospell2, MAX_PC_BONUS, type2, type3, val, current_equip_card_id);
 		break;
 	case SP_HP_LOSS_RATE:
 		if(sd->state.lr_flag != 2) {
@@ -2124,39 +2125,16 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
 
 int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4,int val)
 {
-	int i;
 	nullpo_retr(0, sd);
 
 	switch(type){
 	case SP_AUTOSPELL:
-		if(sd->state.lr_flag != 2) {
-			for (i = 0; i < MAX_PC_BONUS; i++) {
-				if (sd->autospell[i].id == 0 ||
-					(sd->autospell[i].id == type2 && sd->autospell[i].lv < type3) ||
-					(sd->autospell[i].id == type2 && sd->autospell[i].lv == type3 && sd->autospell[i].rate < type4))
-				{
-					sd->autospell[i].id = (val) ? type2 : -type2;		// val = 0: self, 1: enemy
-					sd->autospell[i].lv = type3;
-					sd->autospell[i].rate = type4;
-					break;
-				}
-			}
-		}			
+		if(sd->state.lr_flag != 2)
+			pc_bonus_autospell(sd->autospell, MAX_PC_BONUS, val?type2:-type2, type3, type4, current_equip_card_id);
 		break;
 	case SP_AUTOSPELL_WHENHIT:
-		if(sd->state.lr_flag != 2) {
-			for (i = 0; i < MAX_PC_BONUS; i++) {
-				if (sd->autospell2[i].id == 0 ||
-					(sd->autospell2[i].id == type2 && sd->autospell2[i].lv < type3) ||
-					(sd->autospell2[i].id == type2 && sd->autospell2[i].lv == type3 && sd->autospell2[i].rate < type4))
-				{
-					sd->autospell2[i].id = (val) ? type2 : -type2;		// val = 0: self, 1: enemy
-					sd->autospell2[i].lv = type3;
-					sd->autospell2[i].rate = type4;
-					break;
-				}
-			}
-		}
+		if(sd->state.lr_flag != 2)
+			pc_bonus_autospell(sd->autospell2, MAX_PC_BONUS, val?type2:-type2, type3, type4, current_equip_card_id);
 		break;
 	default:
 		if(battle_config.error_log)

+ 3 - 0
src/map/skill.c

@@ -1373,6 +1373,9 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 			else
 				tbl = src;
 			
+			if (tbl != src && !battle_check_range(src, tbl, skill_get_range2(src, skillid, skilllv)))
+				continue; //Autoskills DO check for target-src range. [Skotlex]
+			
 			switch (skill_get_casttype(skillid)) {
 				case CAST_GROUND:
 					skill_castend_pos2(bl, tbl->x, tbl->y, skillid, skilllv, tick, 0);

+ 64 - 98
src/map/status.c

@@ -42,6 +42,7 @@ static int atkmods[3][20];	// 
 static char job_bonus[MAX_PC_CLASS][MAX_LEVEL];
 
 int current_equip_item_index; //Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus]
+int current_equip_card_id; //To prevent card-stacking (from jA) [Skotlex]
 //we need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only
 //to avoid cards exploits
 
@@ -557,8 +558,7 @@ int status_calc_pc(struct map_session_data* sd,int first)
 	int b_base_atk;
 	struct skill b_skill[MAX_SKILL];
 	int i,bl,index;
-	int skill,wele,wele_,def_ele,refinedef=0;
-	int pele=0,pdef_ele=0;
+	int skill,refinedef=0;
 	int str,dstr,dex;
 
 	nullpo_retr(0, sd);
@@ -782,51 +782,35 @@ int status_calc_pc(struct map_session_data* sd,int first)
 			continue;
 
 		if(sd->inventory_data[index]) {
-			if(sd->inventory_data[index]->type == 4) { // Weapon cards
-				if(sd->status.inventory[index].card[0]!=0x00ff && sd->status.inventory[index].card[0]!=0x00fe && sd->status.inventory[index].card[0]!=(short)0xff00) {
-					int j;
-					for(j=0;j<sd->inventory_data[index]->slot;j++){	// カ?ド
-						int c=sd->status.inventory[index].card[j];
-						if(c>0){
-							if(i == 8 && sd->status.inventory[index].equip == 0x20)
-								sd->state.lr_flag = 1;
-							run_script(itemdb_equipscript(c),0,sd->bl.id,0);
-							sd->state.lr_flag = 0;
-							if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex]
-								return 1;
-						}
-					}
-				}
-			}
-			else if(sd->inventory_data[index]->type==5){ // Non-weapon equipment cards
-				if(sd->status.inventory[index].card[0]!=0x00ff && sd->status.inventory[index].card[0]!=0x00fe && sd->status.inventory[index].card[0]!=(short)0xff00) {
-					int j;
-					for(j=0;j<sd->inventory_data[index]->slot;j++){	// カ?ド
-						int c=sd->status.inventory[index].card[j];
-						if(c>0) {
-							run_script(itemdb_equipscript(c),0,sd->bl.id,0);
-							if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex]
-								return 1;
-						}
-					}
+			int j,c;
+			//Card script execution.
+			if(sd->status.inventory[index].card[0]==0x00ff ||
+				sd->status.inventory[index].card[0]==0x00fe ||
+				sd->status.inventory[index].card[0]==(short)0xff00)
+				continue;
+			for(j=0;j<sd->inventory_data[index]->slot;j++){	// カ?ド
+				current_equip_card_id= c= sd->status.inventory[index].card[j];
+				if(c>0){
+					if(i == 8 && sd->status.inventory[index].equip == 0x20)
+					{	//Left hand status.
+						sd->state.lr_flag = 1;
+						run_script(itemdb_equipscript(c),0,sd->bl.id,0);
+						sd->state.lr_flag = 0;
+					} else
+						run_script(itemdb_equipscript(c),0,sd->bl.id,0);
+					if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex]
+						return 1;
 				}
 			}
 		}
 	}
-	wele = sd->right_weapon.atk_ele;
-	wele_ = sd->left_weapon.atk_ele;
-	def_ele = sd->def_ele;
-
-	if(sd->status.pet_id > 0) { // Pet
+	
+	if(sd->status.pet_id > 0 && battle_config.pet_status_support && sd->pet.intimate > 0)
+	{ // Pet
 		struct pet_data *pd=sd->pd;
-		if((pd && battle_config.pet_status_support) && (!battle_config.pet_equip_required || pd->equip > 0)) {
-			if(sd->pet.intimate > 0 && pd->state.skillbonus == 1 && pd->bonus) { //Skotlex: Readjusted for pets
-				pc_bonus(sd,pd->bonus->type, pd->bonus->val);
-			}
-			pele = sd->right_weapon.atk_ele;
-			pdef_ele = sd->def_ele;
-			sd->right_weapon.atk_ele = sd->def_ele = 0;
-		}
+		if(pd && (!battle_config.pet_equip_required || pd->equip > 0) &&
+			pd->state.skillbonus == 1 && pd->bonus) //Skotlex: Readjusted for pets
+			pc_bonus(sd,pd->bonus->type, pd->bonus->val);
 	}
 	memcpy(sd->paramcard,sd->parame,sizeof(sd->paramcard));
 
@@ -841,61 +825,53 @@ int status_calc_pc(struct map_session_data* sd,int first)
 			continue;
 		if(i == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index))
 			continue;
-		if(sd->inventory_data[index]) {
-			sd->def += sd->inventory_data[index]->def;
-			if(sd->inventory_data[index]->type == 4) {
-				int r,wlv = sd->inventory_data[index]->wlv;
-				if (wlv >= MAX_REFINE_BONUS) 
-					wlv = MAX_REFINE_BONUS - 1;
-				if(i == 8 && sd->status.inventory[index].equip == 0x20) { // Left-hand weapon
-					sd->left_weapon.watk += sd->inventory_data[index]->atk;
-					sd->left_weapon.watk2 = (r=sd->status.inventory[index].refine)*	// 精?攻?力
-						refinebonus[wlv][0];
-					if( (r-=refinebonus[wlv][2])>0 )	// 過?精?ボ?ナス
-						sd->left_weapon.overrefine = r*refinebonus[wlv][1];
-
-					if(sd->status.inventory[index].card[0]==0x00ff){	// Forged weapon
-						sd->left_weapon.star = (sd->status.inventory[index].card[1]>>8);	// 星のかけら
-						if(sd->left_weapon.star >= 15) sd->left_weapon.star = 40; // 3 Star Crumbs now give +40 dmg
-						if (pc_istop10fame( MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH))
-							sd->left_weapon.star += 10;
-						wele_= (sd->status.inventory[index].card[1]&0x0f);	// ? 性
-					}
+		if(!sd->inventory_data[index])
+			continue;
+		
+		sd->def += sd->inventory_data[index]->def;
+		if(sd->inventory_data[index]->type == 4) {
+			int r,wlv = sd->inventory_data[index]->wlv;
+			struct weapon_data *wd;
+			if (wlv >= MAX_REFINE_BONUS) 
+				wlv = MAX_REFINE_BONUS - 1;
+			if(i == 8 && sd->status.inventory[index].equip == 0x20)
+				wd = &sd->left_weapon; // Left-hand weapon
+			else
+				wd = &sd->right_weapon;
+			wd->watk += sd->inventory_data[index]->atk;
+			wd->watk2 = (r=sd->status.inventory[index].refine)*refinebonus[wlv][0];
+			if((r-=refinebonus[wlv][2])>0) //Overrefine bonus.
+				wd->overrefine = r*refinebonus[wlv][1];
+
+			if(sd->status.inventory[index].card[0]==0x00ff)
+			{	// Forged weapon
+				wd->star += (sd->status.inventory[index].card[1]>>8);
+				if(wd->star >= 15) wd->star = 40; // 3 Star Crumbs now give +40 dmg
+				if(pc_istop10fame( MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH))
+					wd->star += 10;
+				
+				if (!wd->atk_ele) //Do not overwrite element from previous bonuses.
+					wd->atk_ele = (sd->status.inventory[index].card[1]&0x0f);
+
+				if (wd == &sd->left_weapon) {
 					sd->attackrange_ += sd->inventory_data[index]->range;
 					sd->state.lr_flag = 1;
 					run_script(sd->inventory_data[index]->script,0,sd->bl.id,0);
 					sd->state.lr_flag = 0;
-					if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex]
-						return 1;
-				}
-				else {	// Right-hand weapon
-					sd->right_weapon.watk += sd->inventory_data[index]->atk;
-					sd->right_weapon.watk2 += (r=sd->status.inventory[index].refine)*	// 精?攻?力
-						refinebonus[wlv][0];
-					if( (r-=refinebonus[wlv][2])>0 )	// 過?精?ボ?ナス
-						sd->right_weapon.overrefine += r*refinebonus[wlv][1];
-
-					if(sd->status.inventory[index].card[0]==0x00ff){	// Forged weapon
-						sd->right_weapon.star += (sd->status.inventory[index].card[1]>>8);	// 星のかけら
-						if(sd->right_weapon.star >= 15) sd->right_weapon.star = 40; // 3 Star Crumbs now give +40 dmg
-						if (pc_istop10fame( MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH))
-							sd->right_weapon.star += 10;
-						wele = (sd->status.inventory[index].card[1]&0x0f);	// ? 性
-					}
+				} else {
 					sd->attackrange += sd->inventory_data[index]->range;
 					run_script(sd->inventory_data[index]->script,0,sd->bl.id,0);
-					if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex]
-						return 1;
 				}
-			}
-			else if(sd->inventory_data[index]->type == 5) {
-				sd->right_weapon.watk += sd->inventory_data[index]->atk;
-				refinedef += sd->status.inventory[index].refine*refinebonus[0][0];
-				run_script(sd->inventory_data[index]->script,0,sd->bl.id,0);
 				if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex]
 					return 1;
 			}
 		}
+		else if(sd->inventory_data[index]->type == 5) {
+			refinedef += sd->status.inventory[index].refine*refinebonus[0][0];
+			run_script(sd->inventory_data[index]->script,0,sd->bl.id,0);
+			if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex]
+				return 1;
+		}
 	}
 
 	if(sd->equip_index[10] >= 0){ // 矢
@@ -915,18 +891,6 @@ int status_calc_pc(struct map_session_data* sd,int first)
 		sd->attackrange = sd->attackrange_;
 	if(sd->status.weapon == 11)
 		sd->attackrange += sd->arrow_range;
-	if(wele > 0)
-		sd->right_weapon.atk_ele = wele;
-	if(wele_ > 0)
-		sd->left_weapon.atk_ele = wele_;
-	if(def_ele > 0)
-		sd->def_ele = def_ele;
-	if(battle_config.pet_status_support) {
-		if(pele > 0 && !sd->right_weapon.atk_ele)
-			sd->right_weapon.atk_ele = pele;
-		if(pdef_ele > 0 && !sd->def_ele)
-			sd->def_ele = pdef_ele;
-	}
 	sd->double_rate += sd->double_add_rate;
 	sd->perfect_hit += sd->perfect_hit_add;
 	sd->splash_range += sd->splash_add_range;
@@ -3493,6 +3457,8 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
 	//Check rate
 	if (!(flag&(4|1))) {
 		rate*=100; //Pass to 10000 = 100%
+		if (rate > 10000) //Shouldn't let this go above 100%
+			rate = 10000;
 		race = flag&8?0:status_get_sc_def(bl, type); //recycling race to store the sc_def value.
 		//sd resistance applies even if the flag is &8
 		if(sd && SC_COMMON_MIN<=type && type<=SC_COMMON_MAX && sd->reseff[type-SC_COMMON_MIN] > 0)

+ 1 - 0
src/map/status.h

@@ -365,6 +365,7 @@ enum {
 extern int StatusIconChangeTable[];
 
 extern int current_equip_item_index;
+extern int current_equip_card_id;
 
 //Mode definitions to clear up code reading. [Skotlex]
 #define MD_CANMOVE 0x001