diff --git a/code/ryzom/client/src/interface_v3/action_phrase_faber.cpp b/code/ryzom/client/src/interface_v3/action_phrase_faber.cpp
index 81ae893bc..a1506bd8b 100644
--- a/code/ryzom/client/src/interface_v3/action_phrase_faber.cpp
+++ b/code/ryzom/client/src/interface_v3/action_phrase_faber.cpp
@@ -1688,29 +1688,30 @@ void	CActionPhraseFaber::updateItemResult()
 			craftSuccessModifier = nodeCSM->getValue32();
 		}
 		// With the faber plan skill
-		sint		success= pPM->getCraftPhraseSuccessRate(pPM->getPhrase(phraseSlot), _ExecuteFromItemPlanBrick->getSkill(), minLevel);
+		sint		success= pPM->getCraftPhraseSuccessRate(pPM->getPhrase(phraseSlot), _ExecuteFromItemPlanBrick->getSkill(), minLevel, 0);
+		sint		bonus = pPM->getCraftPhraseSuccessRate(pPM->getPhrase(phraseSlot), _ExecuteFromItemPlanBrick->getSkill(), minLevel, (sint) craftSuccessModifier) - success;
 		string		successStr;
-		if( craftSuccessModifier == 0 )
+		if( bonus == 0 )
 		{
 			successStr = toString("@{FFFF}") + toString(success);
 		}
 		else
-		if( craftSuccessModifier > 0 ) // bonus
+		if( bonus > 0 ) // bonus
 		{
-			successStr = "@{0F0F}" + toString(success+craftSuccessModifier)
+			successStr = "@{0F0F}" + toString(success + bonus)
 							+ "@{FFFF}("
 							+ toString( success )
 							+ "@{0F0F} + "
-							+ toString( craftSuccessModifier )
+							+ toString( bonus )
 							+ "@{FFFF})";
 		}
 		else
 		{
-			successStr = "@{E42F}" + toString(success+craftSuccessModifier)
+			successStr = "@{E42F}" + toString(success + bonus)
 				+ "@{FFFF}("
 				+ toString( success )
 				+ "@{E42F} - "
-				+ toString( craftSuccessModifier )
+				+ toString( abs(bonus) )
 				+ "@{FFFF})";
 		}
 		strFindReplace(text, "%success", successStr );
diff --git a/code/ryzom/client/src/interface_v3/sphrase_manager.cpp b/code/ryzom/client/src/interface_v3/sphrase_manager.cpp
index 7ef59dc1c..790657e2e 100644
--- a/code/ryzom/client/src/interface_v3/sphrase_manager.cpp
+++ b/code/ryzom/client/src/interface_v3/sphrase_manager.cpp
@@ -1428,7 +1428,7 @@ sint				CSPhraseManager::getPhraseSuccessRate(const CSPhraseCom &phrase)
 }
 
 // ***************************************************************************
-sint				CSPhraseManager::getCraftPhraseSuccessRate(const CSPhraseCom &phrase, SKILLS::ESkills skill, uint minMpLevel)
+sint				CSPhraseManager::getCraftPhraseSuccessRate(const CSPhraseCom &phrase, SKILLS::ESkills skill, uint minMpLevel, sint successModifier)
 {
 	CSkillManager	*pSM= CSkillManager::getInstance();
 
@@ -1438,6 +1438,9 @@ sint				CSPhraseManager::getCraftPhraseSuccessRate(const CSPhraseCom &phrase, SK
 	// take skill value of the skill
 	sint	skillValue= pSM->getBestSkillValue(skill);
 
+	// apply success rate modifier from server
+	skillValue += successModifier;
+
 	// return the sr according to this skill
 	return getPhraseSuccessRate(STCraft, phrase, skillValue, minMpLevel);
 }
diff --git a/code/ryzom/client/src/interface_v3/sphrase_manager.h b/code/ryzom/client/src/interface_v3/sphrase_manager.h
index c14b584ab..d4c1b2092 100644
--- a/code/ryzom/client/src/interface_v3/sphrase_manager.h
+++ b/code/ryzom/client/src/interface_v3/sphrase_manager.h
@@ -338,7 +338,7 @@ public:
 	// Get the Phrase Success Rate %
 	sint				getPhraseSuccessRate(const CSPhraseCom &phrase);
 	// Get the Phrase Success Rate %. Manually gives the Skill to do the comparison (for craft)
-	sint				getCraftPhraseSuccessRate(const CSPhraseCom &phrase, SKILLS::ESkills skill, uint minMpLevel);
+	sint				getCraftPhraseSuccessRate(const CSPhraseCom &phrase, SKILLS::ESkills skill, uint minMpLevel, sint successModifier);
 	// Get the Phrase Success Rate %. Manually gives the Skill to do the comparison (for Forage Extraction)
 	sint				getForageExtractionPhraseSuccessRate(const CSPhraseCom &phrase, SKILLS::ESkills skill);
 	// return the fmt according to forage terrain specializing