Browse Source

* Fixed some typos on skill_copyable_db.txt that causing Shadow Slash (and other skill?) cannot be copied, bugreport:8500 http://rathena.org/board/tracker/issue-8500-plagi-buggi/
* Follow up f3bb209 also remove unused check of INF3_DIS_PLAGIA since using skill_copyable_db.txt now
* Follow up 96443cd

Signed-off-by: Cydh Ramdh <house.bad@gmail.com>

Cydh Ramdh 11 years ago
parent
commit
f4eb33e176
6 changed files with 108 additions and 105 deletions
  1. 9 9
      db/re/skill_db.txt
  2. 13 12
      db/skill_copyable_db.txt
  3. 35 31
      src/map/pc.c
  4. 2 1
      src/map/pc.h
  5. 48 51
      src/map/skill.c
  6. 1 1
      src/map/skill.h

+ 9 - 9
db/re/skill_db.txt

@@ -59,7 +59,7 @@
 //    0x0200- spell range affected by NJ_SHADOWJUMP
 //    0x0400- spell range affected by WL_RADIUS
 //    0x0800- spell range affected by RA_RESEARCHTRAP
-//    0x1000- spell that can't be copied
+//    0x1000- free
 //    0x2000- spell that can be using while riding warg
 //    0x4000- spell that can't be used while in mado
 // 17 Name
@@ -101,12 +101,12 @@
 26,0,6,4,0,0x1,0,2,1,yes,0,0,0,magic,0,0x60,		AL_TELEPORT,Teleport
 27,9,6,2,0,0x1,0,4,1,yes,0,0,3,magic,0,0x20,		AL_WARP,Warp Portal
 28,9,6,16,6,0x21,0,10,1,yes,0,0,0,magic,0,0x20,	AL_HEAL,Heal
-29,9,6,16,0,0x1,0,10,1,yes,0,0,0,magic,0,0x1020,	AL_INCAGI,Increase AGI
+29,9,6,16,0,0x1,0,10,1,yes,0,0,0,magic,0,0x20,	AL_INCAGI,Increase AGI
 30,9,6,1,0,0x1,0,10,1,yes,0,0,0,magic,0,0x0,		AL_DECAGI,Decrease AGI
 31,0,6,4,0,0x1,0,1,1,yes,0,0,0,magic,0,0x20,		AL_HOLYWATER,Aqua Benedicta
 32,0,6,4,0,0x3,15,10,1,yes,0,0,0,magic,0,0x0,	AL_CRUCIS,Signum Crucis
 33,0,6,4,0,0x3,-1,10,1,yes,0,0,0,magic,0,0x0,	AL_ANGELUS,Angelus
-34,9,6,16,0,0x1,0,10,1,yes,0,0,0,magic,0,0x1020,	AL_BLESSING,Blessing
+34,9,6,16,0,0x1,0,10,1,yes,0,0,0,magic,0,0x20,	AL_BLESSING,Blessing
 35,9,6,16,0,0x1,0,1,1,yes,0,0,0,magic,0,0x0,		AL_CURE,Cure
 
 //****
@@ -812,8 +812,8 @@
 //****
 // Additional Skill (??)
 688,9,6,16,0,0x1,0,10,0,no,0,0x200,0,none,0,0x0,	GM_SANDMAN,GM Sandman
-689,0,6,4,0,0x3,-1,10,1,yes,0,0x2,0,magic,0,0x1000,	CASH_BLESSING,Party Blessing
-690,0,6,4,0,0x3,-1,10,1,yes,0,0x2,0,magic,0,0x1000,	CASH_INCAGI,Party Increase AGI
+689,0,6,4,0,0x3,-1,10,1,yes,0,0x2,0,magic,0,0x0,	CASH_BLESSING,Party Blessing
+690,0,6,4,0,0x3,-1,10,1,yes,0,0x2,0,magic,0,0x0,	CASH_INCAGI,Party Increase AGI
 691,0,6,4,0,0x3,-1,5,1,yes,0,0x2,0,magic,0,0x0,	CASH_ASSUMPTIO,Party Assumptio
 //692,0,0,0,0,0,0,9,0,no,0,0x2,0,none,0,0x0,		ALL_CATCRY,Cat Cry
 693,0,6,4,0,0x3,-1,1,1,yes,0,0x2,0,magic,0,0x0,	ALL_PARTYFLEE,Party Flee
@@ -1192,8 +1192,8 @@
 2480,11,6,1,0,0x1,0,5,1,yes,0,0,3,misc,0,0x0,		GN_BLOOD_SUCKER,Blood Sucker //CHECK Data says its a magic attack. Hmmmm....
 2481,11,6,1,-1,0x2,1:2:3:4:5,5,1,yes,0,0,0,weapon,0,0x0,	GN_SPORE_EXPLOSION,Spore Explosion //CHECK Data says its element is set to neutral. Need to confirm.
 2482,11,6,16,0,0,0,5,1,yes,0,0,1,weapon,2,0x0,	GN_WALLOFTHORN,Wall of Thorns
-2483,11,6,2,0,0x3,4,10,1,yes,0,0x2000,0,weapon,0,0x0,	GN_CRAZYWEED,Crazy Weed
-2484,0,6,2,2,0x2,2,10,1,no,0,0x2000,0,weapon,0,0x0,	GN_CRAZYWEED_ATK,Crazy Weed Attack
+2483,11,6,2,0,0x3,4,10,1,yes,0,0x0,0,weapon,0,0x1,	GN_CRAZYWEED,Crazy Weed
+2484,0,6,2,2,0x2,2,10,1,no,0,0x0,0,weapon,0,0x1,	GN_CRAZYWEED_ATK,Crazy Weed Attack
 2485,9,6,2,3,0,0,5,1,yes,0,0,0,magic,0,0x0,		GN_DEMONIC_FIRE,Demonic Fire
 2486,9,6,2,0,0,0,5,1,yes,0,0,0,none,0,0x0,		GN_FIRE_EXPANSION,Fire Expansion //CHECK FIX ME!!!! Level 1 is reducing the damage. Should increase it by 50%
 2487,9,6,2,0,0,0,1,1,no,0,0,0,none,0,0x0,		GN_FIRE_EXPANSION_SMOKE_POWDER,Fire Expansion Smoke Powder
@@ -1404,8 +1404,8 @@
 8236,5,6,1,0,0x1,0,10,0,yes,0,0,0,magic,0,0x0,	MER_LEXDIVINA,Lex_Divina
 8237,9,6,1,0,0x1,0,1,1,yes,0,0,0,magic,0,0x0,	MER_ESTIMATION,Sense
 8238,9,6,16,0,0x1,0,10,1,yes,0,0,0,magic,0,0x0,	MER_KYRIE,Kyrie Eleison
-8239,9,6,16,0,0x1,0,10,1,yes,0,0,0,magic,0,0x1000,	MER_BLESSING,Blessing
-8240,9,6,16,0,0x1,0,10,1,yes,0,0,0,magic,0,0x1000,	MER_INCAGI,Increase Agility
+8239,9,6,16,0,0x1,0,10,1,yes,0,0,0,magic,0,0x0,	MER_BLESSING,Blessing
+8240,9,6,16,0,0x1,0,10,1,yes,0,0,0,magic,0,0x0,	MER_INCAGI,Increase Agility
 //8241,2,6,2,0,0,0,1,1,no,0,0,0,none,0,0x0,		MER_INVINCIBLEOFF2,Mind Blaster
 
 //****

+ 13 - 12
db/skill_copyable_db.txt

@@ -146,17 +146,18 @@ TK_JUMPKICK,3 // Flying Kick
 
 // Ninja
 NJ_ZENYNAGE,3     // Throw Zeny
-NJ_TATAMIGAESHI,3 // Flip Tatami
-NJ_KASUMIKIRI,3   // Haze Slasher
-NJ_SHADOWJUMP,3   // Shadow Slash
-NJ_UTSUSEMI,3     // Blaze Shield
-NJ_KOUENKA,3      // Flaming Petals
-NJ_BAKUENRYU,3    // Exploding Dragon
-NJ_HYOUSENSOU,3   // Freezing Spear
-NJ_HYOUSYOURAKU,3 // Snow Flake Draft
+NJ_TATAMIGAESHI,3 // Improvised Defense
+NJ_KASUMIKIRI,3   // Vanishing Slash
+NJ_SHADOWJUMP,3   // Shadow Leap
+NJ_KIRIKAGE,3     // Shadow Slash
+NJ_UTSUSEMI,3     // Cicada Skin Sheeding
+NJ_KOUENKA,3      // Crimson Fire Petal
+NJ_BAKUENRYU,3    // Raging Fire Dragon
+NJ_HYOUSENSOU,3   // Spear of Ice
+NJ_HYOUSYOURAKU,3 // Ice Meteor
 NJ_HUUJIN,3       // Wind Blade
-NJ_RAIGEKISAI,3   // Lightning Jolt
-NJ_KAMAITACHI,3   // First Wind
+NJ_RAIGEKISAI,3   // Lightning Strike of Destruction
+NJ_KAMAITACHI,3   // Kamaitachi
 
 // 2nd Job Quest Skills
 KN_CHARGEATK,3     // Charge Attack
@@ -167,8 +168,8 @@ MO_KITRANSLATION,3 // Excruciating Palm
 
 // Rune Knight
 RK_SONICWAVE,2     // Sonic Wave
-RK_WINDCUTTER,2    // Ignition Break
-RK_IGNITIONBREAK,2 // Wind Cutter
+RK_WINDCUTTER,2    // Wind Cutter
+RK_IGNITIONBREAK,2 // Ignition Break
 
 // Guillotine Cross
 GC_CROSSIMPACT,2   // Cross Impact

+ 35 - 31
src/map/pc.c

@@ -1243,23 +1243,23 @@ int pc_reg_received(struct map_session_data *sd)
 	}
 
 	if ((i = pc_checkskill(sd,RG_PLAGIARISM)) > 0) {
-		sd->cloneskill_id = pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM);
-		if (sd->cloneskill_id > 0) {
-			sd->status.skill[sd->cloneskill_id].id = sd->cloneskill_id;
-			sd->status.skill[sd->cloneskill_id].lv = pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM_LV);
-			if (sd->status.skill[sd->cloneskill_id].lv > i)
-				sd->status.skill[sd->cloneskill_id].lv = i;
-			sd->status.skill[sd->cloneskill_id].flag = SKILL_FLAG_PLAGIARIZED;
+		sd->cloneskill_idx = skill_get_index(pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM));
+		if (sd->cloneskill_idx >= 0) {
+			sd->status.skill[sd->cloneskill_idx].id = pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM);
+			sd->status.skill[sd->cloneskill_idx].lv = pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM_LV);
+			if (sd->status.skill[sd->cloneskill_idx].lv > i)
+				sd->status.skill[sd->cloneskill_idx].lv = i;
+			sd->status.skill[sd->cloneskill_idx].flag = SKILL_FLAG_PLAGIARIZED;
 		}
 	}
 	if ((i = pc_checkskill(sd,SC_REPRODUCE)) > 0) {
-		sd->reproduceskill_id = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE);
-		if( sd->reproduceskill_id > 0) {
-			sd->status.skill[sd->reproduceskill_id].id = sd->reproduceskill_id;
-			sd->status.skill[sd->reproduceskill_id].lv = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE_LV);
-			if( i < sd->status.skill[sd->reproduceskill_id].lv)
-				sd->status.skill[sd->reproduceskill_id].lv = i;
-			sd->status.skill[sd->reproduceskill_id].flag = SKILL_FLAG_PLAGIARIZED;
+		sd->reproduceskill_idx = skill_get_index(pc_readglobalreg(sd,SKILL_VAR_REPRODUCE));
+		if( sd->reproduceskill_idx >= 0) {
+			sd->status.skill[sd->reproduceskill_idx].id = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE);
+			sd->status.skill[sd->reproduceskill_idx].lv = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE_LV);
+			if( i < sd->status.skill[sd->reproduceskill_idx].lv)
+				sd->status.skill[sd->reproduceskill_idx].lv = i;
+			sd->status.skill[sd->reproduceskill_idx].flag = SKILL_FLAG_PLAGIARIZED;
 		}
 	}
 	//Weird... maybe registries were reloaded?
@@ -7629,26 +7629,26 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
 		pc_setglobalreg (sd, "jobchange_level_3rd", sd->change_level_3rd);
 	}
 
-	if(sd->cloneskill_id) {
-		if( sd->status.skill[sd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED ) {
-			sd->status.skill[sd->cloneskill_id].id = 0;
-			sd->status.skill[sd->cloneskill_id].lv = 0;
-			sd->status.skill[sd->cloneskill_id].flag = SKILL_FLAG_PERMANENT;
-			clif_deleteskill(sd,sd->cloneskill_id);
+	if(sd->cloneskill_idx >= 0) {
+		if( sd->status.skill[sd->cloneskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) {
+			sd->status.skill[sd->cloneskill_idx].id = 0;
+			sd->status.skill[sd->cloneskill_idx].lv = 0;
+			sd->status.skill[sd->cloneskill_idx].flag = SKILL_FLAG_PERMANENT;
+			clif_deleteskill(sd,pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM));
 		}
-		sd->cloneskill_id = 0;
+		sd->cloneskill_idx = -1;
 		pc_setglobalreg(sd,SKILL_VAR_PLAGIARISM, 0);
 		pc_setglobalreg(sd,SKILL_VAR_PLAGIARISM_LV, 0);
 	}
 
-	if(sd->reproduceskill_id) {
-		if( sd->status.skill[sd->reproduceskill_id].flag == SKILL_FLAG_PLAGIARIZED ) {
-			sd->status.skill[sd->reproduceskill_id].id = 0;
-			sd->status.skill[sd->reproduceskill_id].lv = 0;
-			sd->status.skill[sd->reproduceskill_id].flag = SKILL_FLAG_PERMANENT;
-			clif_deleteskill(sd,sd->reproduceskill_id);
+	if(sd->reproduceskill_idx >= 0) {
+		if( sd->status.skill[sd->reproduceskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) {
+			sd->status.skill[sd->reproduceskill_idx].id = 0;
+			sd->status.skill[sd->reproduceskill_idx].lv = 0;
+			sd->status.skill[sd->reproduceskill_idx].flag = SKILL_FLAG_PERMANENT;
+			clif_deleteskill(sd,pc_readglobalreg(sd,SKILL_VAR_REPRODUCE));
 		}
-		sd->reproduceskill_id = 0;
+		sd->reproduceskill_idx = -1;
 		pc_setglobalreg(sd,SKILL_VAR_REPRODUCE,0);
 		pc_setglobalreg(sd,SKILL_VAR_REPRODUCE_LV,0);
 	}
@@ -9966,6 +9966,8 @@ static bool pc_readdb_job_exp(char* fields[], int columns, int current)
 	for(i=0; i<maxlvl; i++) {
 		job_info[idx].exp_table[type][i] = ((uint32) atoi(fields[3+i]));
 		//Place the BaseHP/SP calculation here, so we can use the maxlevel from job_exp
+		if (type != 0)
+			continue;
 		job_info[idx].base_hp[i] = pc_calc_basehp(i+1,idx);
 		job_info[idx].base_sp[i] = 10 + ((i+1) * (job_info[idx].sp_factor/100));
 	}
@@ -9995,14 +9997,16 @@ static bool pc_readdb_job_exp(char* fields[], int columns, int current)
 		idx = pc_class2idx(job_id);
 		memcpy(job_info[idx].exp_table[type], job_info[pc_class2idx(jobs[0])].exp_table[type], sizeof(job_info[pc_class2idx(jobs[0])].exp_table[type]));
 
+		job_info[idx].max_level[type] = maxlvl;
+//		ShowInfo("%s - Class %d: %u\n", type?"Job":"Base", job_id, job_info[idx].max_level[type]);
+
 		//Place the BaseHP/SP calculation here, so we can use the maxlevel from job_exp
+		if (type != 0)
+			continue;
 		for (j = 0; j < maxlvl; j++) {
 			job_info[idx].base_hp[j] = pc_calc_basehp(j+1,idx);
 			job_info[idx].base_sp[j] = 10 + ((j+1) * (job_info[idx].sp_factor/100));
 		}
-
-		job_info[idx].max_level[type] = maxlvl;
-//		ShowInfo("%s - Class %d: %u\n", type?"Job":"Base", job_id, job_info[idx].max_level[type]);
 	}
 	return true;
 }

+ 2 - 1
src/map/pc.h

@@ -265,7 +265,8 @@ struct map_session_data {
 	uint16 skill_id_dance,skill_lv_dance;
 	short cook_mastery; // range: [0,1999] [Inkfish]
 	struct skill_cooldown_entry * scd[MAX_SKILLCOOLDOWN]; // Skill Cooldown
-	int cloneskill_id, reproduceskill_id;
+	int cloneskill_idx, ///Stores index of copied skill by Intimidate/Plagiarism
+		reproduceskill_idx; ///Stores index of copied skill by Reproduce
 	int menuskill_id, menuskill_val, menuskill_val2;
 
 	int invincible_timer;

+ 48 - 51
src/map/skill.c

@@ -445,7 +445,8 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
 	return hp;
 }
 
-/** Making plagiarize check its own function
+/** Making Plagiarism and Reproduce check their own function
+* Previous prevention for NPC skills, Wedding skills, and INF3_DIS_PLAGIA are removed since we use skill_copyable_db.txt [Cydh]
 * @param sd: Player who will copy the skill
 * @param skill_id: Target skill
 * @return 0 - Cannot be copied; 1 - Can be copied by Plagiarism 2 - Can be copied by Reproduce
@@ -458,19 +459,9 @@ static char skill_isCopyable(struct map_session_data *sd, uint16 skill_id) {
 	if (sd->status.skill[idx].id != 0 && sd->status.skill[idx].flag != SKILL_FLAG_PLAGIARIZED)
 		return 0;
 
-	// Never copy NPC/Wedding Skills
-	if (skill_get_inf2(skill_id)&(INF2_NPC_SKILL|INF2_WEDDING_SKILL))
-		return 0;
-
-	// Added so plagarize can't copy agi/bless if you're undead since it damages you
-	// NOTE: Is this still needed since we use skill_copyable_db now?
-	if (skill_get_inf3(skill_id)&INF3_DIS_PLAGIA)
-		return 0;
-
 	// Check if the skill is copyable by class
 	if (!pc_has_permission(sd,PC_PERM_ALL_SKILL)) {
-		uint16 job_allowed;
-		job_allowed = skill_db[idx].copyable.joballowed;
+		uint16 job_allowed = skill_db[idx].copyable.joballowed;
 		while (1) {
 			if (job_allowed&0x01 && sd->status.class_ == JOB_ROGUE) break;
 			if (job_allowed&0x02 && sd->status.class_ == JOB_STALKER) break;
@@ -2490,7 +2481,8 @@ static void skill_do_copy(struct block_list* src,struct block_list *bl, uint16 s
 	else if (&tsd->sc && tsd->sc.data[SC_PRESERVE] && !tsd->sc.data[SC__REPRODUCE])
 		return;
 	else {
-		short copy_flag;
+		short idx;
+		unsigned char lv;
 
 		// Copy Referal: dummy skills should point to their source upon copying
 		switch (skill_id) {
@@ -2520,49 +2512,52 @@ static void skill_do_copy(struct block_list* src,struct block_list *bl, uint16 s
 				break;
 		}
 
-		copy_flag = skill_isCopyable(tsd,skill_id);
-		if (copy_flag != 1 && copy_flag != 2) //Skill cannot be copied
+		//Use skill index, avoiding out-of-bound array [Cydh]
+		if ((idx = skill_get_index(skill_id)) < 0)
 			return;
-		else {
-			uint8 lv;
-			if (copy_flag == 2) { //Copied by Reproduce
-				struct status_change *tsc = status_get_sc(bl);
-				lv = (tsc) ? tsc->data[SC__REPRODUCE]->val1 : 1; //Already did this SC check on skill_isCopyable()
-				if( tsd->reproduceskill_id && tsd->status.skill[tsd->reproduceskill_id].flag == SKILL_FLAG_PLAGIARIZED ) {
-					tsd->status.skill[tsd->reproduceskill_id].id = 0;
-					tsd->status.skill[tsd->reproduceskill_id].lv = 0;
-					tsd->status.skill[tsd->reproduceskill_id].flag = SKILL_FLAG_PERMANENT;
-					clif_deleteskill(tsd,tsd->reproduceskill_id);
-				}
 
-				lv = min(lv,skill_get_max(skill_id)); //Level dependent and limitation.
+		switch (skill_isCopyable(tsd,skill_id)) {
+			case 1: //Copied by Plagiarism
+				{
+					if (tsd->cloneskill_idx >= 0 && tsd->status.skill[tsd->cloneskill_idx].flag == SKILL_FLAG_PLAGIARIZED) {
+						clif_deleteskill(tsd,tsd->status.skill[tsd->cloneskill_idx].id);
+						tsd->status.skill[tsd->cloneskill_idx].id = 0;
+						tsd->status.skill[tsd->cloneskill_idx].lv = 0;
+						tsd->status.skill[tsd->cloneskill_idx].flag = SKILL_FLAG_PERMANENT;
+					}
 
-				tsd->reproduceskill_id = skill_id;
-				pc_setglobalreg(tsd,SKILL_VAR_REPRODUCE,skill_id);
-				pc_setglobalreg(tsd,SKILL_VAR_REPRODUCE_LV,lv);
-			}
-			else if (copy_flag == 1) { //Copied by Plagiarism
-				if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED) {
-					tsd->status.skill[tsd->cloneskill_id].id = 0;
-					tsd->status.skill[tsd->cloneskill_id].lv = 0;
-					tsd->status.skill[tsd->cloneskill_id].flag = SKILL_FLAG_PERMANENT;
-					clif_deleteskill(tsd,tsd->cloneskill_id);
-				}
+					if ((lv = pc_checkskill(tsd,RG_PLAGIARISM)) < skill_lv)
+						skill_lv = lv;
 
-				if ((lv = pc_checkskill(tsd,RG_PLAGIARISM)) < skill_lv)
-					skill_lv = lv;
+					tsd->cloneskill_idx = idx;
+					pc_setglobalreg(tsd,SKILL_VAR_PLAGIARISM,skill_id);
+					pc_setglobalreg(tsd,SKILL_VAR_PLAGIARISM_LV,lv);
+				}
+				break;
+			case 2: //Copied by Reproduce
+				{
+					struct status_change *tsc = status_get_sc(bl);
+					//Already did SC check
+					//Skill level copied depends on Reproduce skill that used
+					lv = (tsc) ? tsc->data[SC__REPRODUCE]->val1 : 1;
+					if( tsd->reproduceskill_idx >= 0 && tsd->status.skill[tsd->reproduceskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) {
+						clif_deleteskill(tsd,tsd->status.skill[tsd->reproduceskill_idx].id);
+						tsd->status.skill[tsd->reproduceskill_idx].id = 0;
+						tsd->status.skill[tsd->reproduceskill_idx].lv = 0;
+						tsd->status.skill[tsd->reproduceskill_idx].flag = SKILL_FLAG_PERMANENT;
+					}
 
-				tsd->cloneskill_id = skill_id;
-				pc_setglobalreg(tsd,SKILL_VAR_PLAGIARISM,skill_id);
-				pc_setglobalreg(tsd,SKILL_VAR_PLAGIARISM_LV,lv);
-			}
-			else
-				return;
-			tsd->status.skill[skill_id].id = skill_id;
-			tsd->status.skill[skill_id].lv = lv;
-			tsd->status.skill[skill_id].flag = SKILL_FLAG_PLAGIARIZED;
-			clif_addskill(tsd,skill_id);
+					tsd->reproduceskill_idx = idx;
+					pc_setglobalreg(tsd,SKILL_VAR_REPRODUCE,skill_id);
+					pc_setglobalreg(tsd,SKILL_VAR_REPRODUCE_LV,lv);
+				}
+				break;
+			default: return;
 		}
+		tsd->status.skill[idx].id = skill_id;
+		tsd->status.skill[idx].lv = lv;
+		tsd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;
+		clif_addskill(tsd,skill_id);
 	}
 }
 /*
@@ -8823,7 +8818,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		break;
 	case SC_AUTOSHADOWSPELL:
 		if( sd ) {
-			if( sd->status.skill[sd->reproduceskill_id].id || sd->status.skill[sd->cloneskill_id].id ) {
+			if( (sd->reproduceskill_idx >= 0 && sd->status.skill[sd->reproduceskill_idx].id) ||
+				(sd->cloneskill_idx >= 0 && sd->status.skill[sd->cloneskill_idx].id) )
+			{
 				sc_start(src,src,SC_STOP,100,skill_lv,-1);// The skill_lv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax]
 				clif_autoshadowspell_list(sd);
 				clif_skill_nodamage(src,bl,skill_id,1,1);

+ 1 - 1
src/map/skill.h

@@ -86,7 +86,7 @@ enum e_skill_inf3 {
 	INF3_EFF_SHADOWJUMP		= 0x0200,	// spell range affected by NJ_SHADOWJUMP
 	INF3_EFF_RADIUS			= 0x0400,	// spell range affected by WL_RADIUS
 	INF3_EFF_RESEARCHTRAP	= 0x0800,	// spell range affected by RA_RESEARCHTRAP
-	INF3_DIS_PLAGIA			= 0x1000,	// spell that can't be copied
+	//INF3_ = 0x1000, // free
 	INF3_USABLE_WARG		= 0x2000,	// spell that can be use while riding warg
 	INF3_DIS_MADO			= 0x4000,	// spell that can't be used while in mado
 	//... add other spell list option here