Ejemplo n.º 1
0
int32 doSynthFail(CCharEntity* PChar)
{
	uint8  carrentCraft = PChar->CraftContainer->getInvSlotID(0);
	double synthDiff    = getSynthDifficulty(PChar, carrentCraft);
	double moghouseAura = 0;

	if (PChar->getZone() == 0) // неправильное условие, т.к. аура действует лишь в собственном доме
	{
		// Проверяем элемент синтеза
		switch (PChar->CraftContainer->getType())
		{
			case ELEMENT_FIRE:		moghouseAura = 0.05 * charutils::hasKeyItem(PChar,MOGHANCEMENT_FIRE);	   break;
			case ELEMENT_EARTH:		moghouseAura = 0.05 * charutils::hasKeyItem(PChar,MOGHANCEMENT_EARTH);	   break;
			case ELEMENT_WATER:		moghouseAura = 0.05 * charutils::hasKeyItem(PChar,MOGHANCEMENT_WATER);	   break;
			case ELEMENT_WIND:		moghouseAura = 0.05 * charutils::hasKeyItem(PChar,MOGHANCEMENT_WIND);	   break;
			case ELEMENT_ICE:		moghouseAura = 0.05 * charutils::hasKeyItem(PChar,MOGHANCEMENT_ICE);	   break;
			case ELEMENT_LIGHTNING:	moghouseAura = 0.05 * charutils::hasKeyItem(PChar,MOGHANCEMENT_LIGHTNING); break;
			case ELEMENT_LIGHT:		moghouseAura = 0.05 * charutils::hasKeyItem(PChar,MOGHANCEMENT_LIGHT);	   break;
			case ELEMENT_DARK:		moghouseAura = 0.05 * charutils::hasKeyItem(PChar,MOGHANCEMENT_DARK);	   break;
		}

		if (moghouseAura == 0)
		{
			switch (carrentCraft)
			{
				case SKILL_WDW:	 moghouseAura = 0.075 * charutils::hasKeyItem(PChar,MOGLIFICATION_WOODWORKING);	 break;
				case SKILL_SMT:	 moghouseAura = 0.075 * charutils::hasKeyItem(PChar,MOGLIFICATION_SMITHING);	 break;
				case SKILL_GLD:	 moghouseAura = 0.075 * charutils::hasKeyItem(PChar,MOGLIFICATION_GOLDSMITHING); break;
				case SKILL_CLT:	 moghouseAura = 0.075 * charutils::hasKeyItem(PChar,MOGLIFICATION_CLOTHCRAFT);	 break;
				case SKILL_LTH:	 moghouseAura = 0.075 * charutils::hasKeyItem(PChar,MOGLIFICATION_LEATHERCRAFT); break;
				case SKILL_BON:	 moghouseAura = 0.075 * charutils::hasKeyItem(PChar,MOGLIFICATION_BONECRAFT);	 break;
				case SKILL_ALC:	 moghouseAura = 0.075 * charutils::hasKeyItem(PChar,MOGLIFICATION_ALCHEMY);		 break;
				case SKILL_COK:	 moghouseAura = 0.075 * charutils::hasKeyItem(PChar,MOGLIFICATION_COOKING);		 break;
			}
		}

		if (moghouseAura == 0)
		{
			switch (carrentCraft)
			{
				case SKILL_WDW:	 moghouseAura = 0.1 * charutils::hasKeyItem(PChar,MEGA_MOGLIFICATION_WOODWORKING);  break;
				case SKILL_SMT:	 moghouseAura = 0.1 * charutils::hasKeyItem(PChar,MEGA_MOGLIFICATION_SMITHING);		break;
				case SKILL_GLD:	 moghouseAura = 0.1 * charutils::hasKeyItem(PChar,MEGA_MOGLIFICATION_GOLDSMITHING);	break;
				case SKILL_CLT:	 moghouseAura = 0.1 * charutils::hasKeyItem(PChar,MEGA_MOGLIFICATION_CLOTHCRAFT);	break;
				case SKILL_LTH:	 moghouseAura = 0.1 * charutils::hasKeyItem(PChar,MEGA_MOGLIFICATION_LEATHERCRAFT);	break;
				case SKILL_BON:	 moghouseAura = 0.1 * charutils::hasKeyItem(PChar,MEGA_MOGLIFICATION_BONECRAFT);	break;
				case SKILL_ALC:	 moghouseAura = 0.1 * charutils::hasKeyItem(PChar,MEGA_MOGLIFICATION_ALCHEMY);		break;
				case SKILL_COK:	 moghouseAura = 0.1 * charutils::hasKeyItem(PChar,MEGA_MOGLIFICATION_COOKING);		break;
			}
		}
	}

	uint8 invSlotID  = 0;
	uint8 nextSlotID = 0;
	uint8 lostCount  = 0;

	double random   = 0;
	double lostItem = 0.15 - moghouseAura + (synthDiff > 0 ? synthDiff/20 : 0);

	invSlotID = PChar->CraftContainer->getInvSlotID(1);

	for(uint8 slotID = 1; slotID <= 8; ++slotID)
	{
		if (slotID != 8)
			nextSlotID = PChar->CraftContainer->getInvSlotID(slotID+1);

		random = WELL512::drand();
		#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
		ShowDebug(CL_CYAN"Lost Item: %g  Random: %g\n" CL_RESET, lostItem, random);
		#endif

		if(random < lostItem) {
			PChar->CraftContainer->setQuantity(slotID, 0);
			lostCount++;
		}

		if(invSlotID != nextSlotID)
		{
			CItem* PItem = PChar->getStorage(LOC_INVENTORY)->GetItem(invSlotID);

			if (PItem != NULL)
			{
				PItem->setSubType(ITEM_UNLOCKED);

				if(lostCount > 0)
				{
					#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
					ShowDebug(CL_CYAN"Removing quantity %u from inventory slot %u\n" CL_RESET, lostCount, invSlotID);
					#endif

					charutils::UpdateItem(PChar, LOC_INVENTORY, invSlotID, -(int32)lostCount);
					lostCount = 0;
				}else{
					PChar->pushPacket(new CInventoryAssignPacket(PItem, INV_NORMAL));
				}
			}
			invSlotID  = nextSlotID;
			nextSlotID = 0;
		}
		if(invSlotID == 0xFF)
			break;
	}

    if(PChar->loc.zone->GetID() != 255 && PChar->loc.zone->GetID() != 0)
    {
		PChar->loc.zone->PushPacket(PChar, CHAR_INRANGE, new CSynthResultMessagePacket(PChar, SYNTH_FAIL));
		PChar->pushPacket(new CSynthMessagePacket(PChar, SYNTH_FAIL));
    }
    else
    {
        PChar->pushPacket(new CSynthMessagePacket(PChar, SYNTH_FAIL));
    }

	return 0;
}
Ejemplo n.º 2
0
int32 doSynthSkillUp(CCharEntity* PChar)
{
	//if (PChar->CraftContainer->getType() == ELEMENT_LIGHTNING)
	//{
	//	return 0;
	//} bad idea, you cannot synth any item with lightning crystal

//	double MoonPhase = (double)CVanaTime::getInstance()->getMoonPhase();
//	double MoonCorrection = MoonPhase / 500;
//  removed: there's no evidence that moon phase directly modifies skill up rate


	for(uint8 skillID = 49; skillID < 57; ++skillID)
	{
		if (PChar->CraftContainer->getQuantity(skillID-40) == 0)	// получаем необходимый уровень умения рецепта
		{
			continue;
		}
		
		uint16 ModID = 0;
		switch (skillID)
		{
			case SKILL_WDW: ModID = MOD_WOOD;		break;
			case SKILL_SMT: ModID = MOD_SMITH;		break;
			case SKILL_GLD: ModID = MOD_GOLDSMITH;	break;
			case SKILL_CLT: ModID = MOD_CLOTH;		break;
			case SKILL_LTH: ModID = MOD_LEATHER;	break;
			case SKILL_BON: ModID = MOD_BONE;		break;
			case SKILL_ALC: ModID = MOD_ALCHEMY;	break;
			case SKILL_COK: ModID = MOD_COOK;		break;
		}

		uint8  skillRank = PChar->RealSkills.rank[skillID];
		uint16 maxSkill  = (skillRank+1)*100;

		int32  charSkill = PChar->RealSkills.skill[skillID];
		int32  basDiff   = PChar->CraftContainer->getQuantity(skillID-40) - (charSkill/10 + PChar->getMod(ModID)); //the 5 lvl difference rule for breaks does consider the effects of image support/gear
		double synthDiff = getSynthDifficulty(PChar, skillID);

		if ((basDiff <= 0) || ((basDiff > 5) && (PChar->CraftContainer->getQuantity(0) == SYNTHESIS_FAIL)))		// результат синтеза хранится в quantity нулевой ячейки
		{
			continue;
		}

		if (charSkill < maxSkill)
		{
			double skillUpChance = (synthDiff*(map_config.craft_chance_multiplier - (log(1.2 + charSkill/100))))/10;
			skillUpChance = skillUpChance/(1 + (PChar->CraftContainer->getQuantity(0) == SYNTHESIS_FAIL));		// результат синтеза хранится в quantity нулевой ячейки

			double random = WELL512::drand();
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Skill up chance: %g  Random: %g\n" CL_RESET, skillUpChance, random);
			#endif

			if (random < skillUpChance)
			{
				int32  satier = 0;
				int32  skillAmount  = 1;
				double chance = 0;

				if((synthDiff >= 1) && (synthDiff < 3)){
					satier = 1;
				}else if((synthDiff >= 3) && (synthDiff < 5)){
					satier = 2;
				}else if((synthDiff >= 5) && (synthDiff < 8)){
					satier = 3;
				}else if((synthDiff >= 8) && (synthDiff < 10)){
					satier = 4;
				}else if (synthDiff >= 10)
					satier = 5;
				//if (skillRank > 5)
				//	satier--;

				for(uint8 i = 0; i < 4; i ++)
				{
					random = WELL512::drand();
					#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
					ShowDebug(CL_CYAN"SkillAmount Tier: %i  Random: %g\n" CL_RESET, satier, random);
					#endif

					switch(satier)
					{
						case 5:  chance = 0.900; break;
						case 4:  chance = 0.700; break;
						case 3:  chance = 0.500; break;
						case 2:  chance = 0.300; break;
						case 1:  chance = 0.200; break;
						default: chance = 0.000; break;
					}
					if(chance < random)
						break;
					skillAmount += 1;
					satier -= 1;
				}

				// Do craft amount multiplier
				if (map_config.craft_amount_multiplier > 1)
				{
					skillAmount += skillAmount * map_config.craft_amount_multiplier;
					if (skillAmount > 9)
					{
						skillAmount = 9;
					}
				}

				if((skillAmount + charSkill) > maxSkill)
				{
					skillAmount = maxSkill - charSkill;
				}

				PChar->RealSkills.skill[skillID] += skillAmount;
				PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, skillID, skillAmount, 38));

				if((charSkill/10) < (charSkill + skillAmount)/10)
				{
					PChar->WorkingSkills.skill[skillID] += 0x20;

					PChar->pushPacket(new CCharSkillsPacket(PChar));
					PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, skillID, (charSkill + skillAmount)/10, 53));
				}

				charutils::SaveCharSkills(PChar, skillID);
			}
		}
	}
	return 0;
}
Ejemplo n.º 3
0
uint8 calcSynthResult(CCharEntity* PChar)
{
	uint8 result = 1;
	uint8 hqtier = 0;
	uint8 mainID = getGeneralCraft(PChar);
	bool canHQ = true;

	double success = 0;
	double chance  = 0;
	double MoonPhase = (double)CVanaTime::getInstance()->getMoonPhase();
	uint8  WeekDay = (uint8)CVanaTime::getInstance()->getWeekday();
	uint8  crystalElement = PChar->CraftContainer->getType();
	uint8  strongElement[8] = {2,3,5,4,0,1,7,6};

	for(uint8 skillID = 49; skillID < 57; ++skillID)
	{
		uint8 checkSkill = PChar->CraftContainer->getQuantity(skillID-40);
		if(checkSkill != 0)
		{
			double synthDiff = getSynthDifficulty(PChar, skillID);
			hqtier = 0;

			if(synthDiff <= 0)
			{
				success = 0.95;

				if((synthDiff <= 0) && (synthDiff >= -10))
				{
					success -= (double)(PChar->CraftContainer->getType() == ELEMENT_LIGHTNING) * 0.2;
					hqtier = 1;
				}
				else if((synthDiff <= -11) && (synthDiff >= -30))
					hqtier = 2;
				else if((synthDiff <= -31) && (synthDiff >= -50))
					hqtier = 3;
				else if(synthDiff <= -51)
					hqtier = 4;
			}
			else
			{
				success = 0.95 - (synthDiff / 10) - (double)(PChar->CraftContainer->getType() == ELEMENT_LIGHTNING) * 0.2;
				canHQ = false;
				if(success < 0.05)
					success = 0.05;

				#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
				ShowDebug(CL_CYAN"SkillID %u: difficulty > 0\n" CL_RESET, skillID);
				#endif
			}

            if(!canSynthesizeHQ(PChar,skillID))
            {
                success += 0.01; //the crafting rings that block HQ synthesis all also increase their respective craft's success rate by 1%
                canHQ = false; //assuming here that if a crafting ring is used matching a recipe's subsynth, overall HQ will still be blocked
            }

			double random = WELL512::drand();
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Success: %g  Random: %g\n" CL_RESET, success, random);
			#endif

			if(random < success)
			{
				for(uint8 i = 0; i < 3; ++i)
				{
					if(mainID != skillID)
					    break;
					
					random = WELL512::drand();
					
					switch(hqtier)
					{
						//case 5:  chance = 0.700; break; 
						//Removed - HQ rate caps at 50%
						case 4:  chance = 0.500; break;
						case 3:  chance = 0.300; break;
						case 2:  chance = 0.100; break;
						case 1:  chance = 0.015; break;
						default: chance = 0.000; break;
					}
					
					if(chance > 0)
					{
						chance *= 1.0 - (MoonPhase - 50)/150;  //new moon +33% of base rate bonus to hq chance, full moon -33%, corresponding/weakday/lightsday -33%, opposing/darksday +33%
						if (crystalElement == WeekDay)
							chance *= 1.0 - ((double)1/3);
						else if (strongElement[crystalElement] == WeekDay)
							chance *= 1.0 + ((double)1/3);
						else if (strongElement[WeekDay] == crystalElement)
							chance *= 1.0 - ((double)1/3);
						else if (WeekDay == LIGHTSDAY)
							chance *= 1.0 - ((double)1/3);
						else if (WeekDay == DARKSDAY)
							chance *= 1.0 + ((double)1/3);
					}
					
					if(chance > 0.500)
					    chance = 0.500;
					
					#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
					ShowDebug(CL_CYAN"HQ Tier: %i HQ Chance: %g Random: %g SkillID: %u\n" CL_RESET, hqtier, chance, random, skillID);
					#endif
					
					if(chance < random)
						break;
					result += 1;
					hqtier -= 1;
				}
			}else{
				// сохраняем умение, из-за которого синтез провалился.
				// используем slotID ячейки кристалла, т.к. он был удален еще в начале синтеза
				PChar->CraftContainer->setInvSlotID(0,skillID);
				result = 0;
				break;
			}
		}
	}

	if(result > SYNTHESIS_SUCCESS && !canHQ)
		result = SYNTHESIS_SUCCESS;

	// результат синтеза записываем в поле quantity ячейки кристалла.
	PChar->CraftContainer->setQuantity(0, result);

	switch(result)
	{
		case SYNTHESIS_FAIL:
			result = RESULT_FAIL;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth failed.\n" CL_RESET);
			#endif
			break;
		case SYNTHESIS_SUCCESS:
			result = RESULT_SUCCESS;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth success.\n" CL_RESET);
			#endif
			break;
		case SYNTHESIS_HQ:
			result = RESULT_HQ;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth HQ.\n" CL_RESET);
			#endif
			break;
		case SYNTHESIS_HQ2:
			result = RESULT_HQ;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth HQ2.\n" CL_RESET);
			#endif
			break;
		case SYNTHESIS_HQ3:
			result = RESULT_HQ;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth HQ3.\n" CL_RESET);
			#endif
			break;
	}
	return result;
}
Ejemplo n.º 4
0
int32 doSynthSkillUp(CCharEntity* PChar)
{
	PROFILE_FUNC();
	//if (PChar->CraftContainer->getType() == ELEMENT_LIGHTNING)
	//{
	//	return 0;
	//} bad idea, you cannot synth any item with lightning crystal

	double MoonPhase = (double)CVanaTime::getInstance()->getMoonPhase();
	double MoonCorrection = MoonPhase / 500;

	for(uint8 skillID = 49; skillID < 57; ++skillID)
	{
		if (PChar->CraftContainer->getQuantity(skillID-40) == 0)	// получаем необходимый уровень умения рецепта
		{
			continue;
		}

		uint8  skillRank = PChar->RealSkills.rank[skillID];
		uint16 maxSkill  = (skillRank+1)*100;

		int32  charSkill = PChar->RealSkills.skill[skillID];
		int32  basDiff   = PChar->CraftContainer->getQuantity(skillID-40) - charSkill/10;
		double synthDiff = getSynthDifficulty(PChar, skillID);

		if ((basDiff <= 0) || ((basDiff > 5) && (PChar->CraftContainer->getQuantity(0) == SYNTHESIS_FAIL)))		// результат синтеза хранится в quantity нулевой ячейки
		{
			return 0;
		}

		if (charSkill < maxSkill)
		{
			double skillUpChance = (synthDiff*(map_config.craft_multiplier - (log(1.2 + charSkill/100) + MoonCorrection)))/10;
			skillUpChance = skillUpChance/(1 + (PChar->CraftContainer->getQuantity(0) == SYNTHESIS_FAIL));		// результат синтеза хранится в quantity нулевой ячейки

			double random = rand() / ((double)RAND_MAX);
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Skill up chance: %g  Random: %g\n" CL_RESET, skillUpChance, random);
			#endif

			if (random < skillUpChance)
			{
				int32  satier = 0;
				int32  skillAmount  = 1;
				double chance = 0;

				if((synthDiff >= 1) && (synthDiff < 3)){
					satier = 1;
				}else if((synthDiff >= 3) && (synthDiff < 5)){
					satier = 2;
				}else if((synthDiff >= 5) && (synthDiff < 8)){
					satier = 3;
				}else if((synthDiff >= 8) && (synthDiff < 10)){
					satier = 4;
				}else if (synthDiff >= 10)
					satier = 5;
				//if (skillRank > 5)
				//	satier--;

				for(uint8 i = 0; i < 4; i ++)
				{
					random = rand() / ((double)RAND_MAX);
					#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
					ShowDebug(CL_CYAN"SkillAmount Tier: %i  Random: %g\n" CL_RESET, satier, random);
					#endif

					switch(satier)
					{
						case 5:  chance = 0.900; break;
						case 4:  chance = 0.700; break;
						case 3:  chance = 0.500; break;
						case 2:  chance = 0.300; break;
						case 1:  chance = 0.200; break;
						default: chance = 0.000; break;
					}
					if(chance < random)
						break;
					skillAmount += 1;
					satier -= 1;
				}

				if((skillAmount + charSkill) > maxSkill)
				{
					skillAmount = maxSkill - charSkill;
				}

				PChar->RealSkills.skill[skillID] += skillAmount;
				PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, skillID, skillAmount, 38));

				if((charSkill/10) < (charSkill + skillAmount)/10)
				{
					PChar->WorkingSkills.skill[skillID] += 0x20;

					PChar->pushPacket(new CCharSkillsPacket(PChar));
					PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, skillID, (charSkill + skillAmount)/10, 53));
				}

				charutils::SaveCharSkills(PChar, skillID);
			}
		}
	}
	return 0;
}
Ejemplo n.º 5
0
uint8 calcSynthResult(CCharEntity* PChar)
{
	PROFILE_FUNC();
	uint8 count  = 0;
	uint8 result = 0;
	uint8 hqtier = 0;

	double success = 0;
	double chance  = 0;

	for(uint8 skillID = 49; skillID < 57; ++skillID)
	{
		uint8 checkSkill = PChar->CraftContainer->getQuantity(skillID-40);
		if(checkSkill != 0)
		{
			double synthDiff = getSynthDifficulty(PChar, skillID);
			hqtier = 0;
			count++;

			if(synthDiff <= 0)
			{
				success = 0.95;

				if((synthDiff <= 0) && (synthDiff >= -10)){
					success -= (double)(PChar->CraftContainer->getType() == ELEMENT_LIGHTNING) * 0.2;
					hqtier = 1;
				}else if((synthDiff <= -11) && (synthDiff >= -30)){
					hqtier = 2;
				}else if((synthDiff <= -31) && (synthDiff >= -50)){
					hqtier = 3;
				}else if((synthDiff <= -51) && (synthDiff >= -70)){
					hqtier = 4;
				}else if (synthDiff <= -71)
					hqtier = 5;
			}else{
				success = 0.95 - (synthDiff / 10) - (double)(PChar->CraftContainer->getType() == ELEMENT_LIGHTNING) * 0.2;
				if(success < 0.05)
					success = 0.05;
			}

			double random = rand() / ((double) RAND_MAX);
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Success: %g  Random: %g\n" CL_RESET, success, random);
			#endif

			if(random < success)
			{
				for(int32 i = 0; i < 3; ++i)
				{
					random = rand() / ((double) RAND_MAX);
					#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
					ShowDebug(CL_CYAN"HQ Tier: %i  Random: %g\n" CL_RESET, hqtier, random);
					#endif

					switch(hqtier)
					{
						case 5:  chance = 0.700; break;
						case 4:  chance = 0.500; break;
						case 3:  chance = 0.300; break;
						case 2:  chance = 0.100; break;
						case 1:  chance = 0.015; break;
						default: chance = 0.000; break;
					}
					if(chance < random)
						break;
					result += 1;
					hqtier -= 1;
				}
			}else{
				// сохраняем умение, из-за которого синтез провалился.
				// используем slotID ячейки кристалла, т.к. он был удален еще в начале синтеза
				PChar->CraftContainer->setInvSlotID(0,skillID);
				result = -1;
				break;
			}
		}
	}

	result = (count == 0 ? SYNTHESIS_SUCCESS : (result == 0xFF ? SYNTHESIS_FAIL : (result/count+1)));

	if ((result > SYNTHESIS_SUCCESS) && (!canSynthesizeHQ(PChar,getGeneralCraft(PChar))))
	{
		result = SYNTHESIS_SUCCESS;
	}

	// результат синтеза записываем в поле quantity ячейки кристалла.
	PChar->CraftContainer->setQuantity(0, result);

	switch(result)
	{
		case SYNTHESIS_FAIL:
			result = RESULT_FAIL;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth failed.\n" CL_RESET);
			#endif
			break;
		case SYNTHESIS_SUCCESS:
			result = RESULT_SUCCESS;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth success.\n" CL_RESET);
			#endif
			break;
		case SYNTHESIS_HQ:
			result = RESULT_HQ;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth HQ.\n" CL_RESET);
			#endif
			break;
		case SYNTHESIS_HQ2:
			result = RESULT_HQ;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth HQ2.\n" CL_RESET);
			#endif
			break;
		case SYNTHESIS_HQ3:
			result = RESULT_HQ;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth HQ3.\n" CL_RESET);
			#endif
			break;
	}
	return result;
}
Ejemplo n.º 6
0
uint8 calcSynthResult(CCharEntity* PChar)
{
	uint8 result = SYNTHESIS_SUCCESS;
	uint8 hqtier = 0;
	uint8 mainID = getGeneralCraft(PChar);
	bool canHQ = true;

	double success = 0;
	double chance  = 0;
	double MoonPhase = (double)CVanaTime::getInstance()->getMoonPhase();
	uint8  WeekDay = (uint8)CVanaTime::getInstance()->getWeekday();
	uint8  crystalElement = PChar->CraftContainer->getType();
	uint8  strongElement[8] = {2,3,5,4,0,1,7,6};

	for(uint8 skillID = 49; skillID < 57; ++skillID)
	{
		uint8 checkSkill = PChar->CraftContainer->getQuantity(skillID-40);
		if(checkSkill != 0)
		{
			double synthDiff = getSynthDifficulty(PChar, skillID);
			hqtier = 0;

			if(synthDiff <= 0)
			{
				success = 0.95;

				if(synthDiff > -11) //0-10 levels over recipe
				{
					success -= (double)(PChar->CraftContainer->getType() == ELEMENT_LIGHTNING) * 0.2;
					hqtier = 1;
				}
				else if(synthDiff > -31) //11-30 levels over recipe
					hqtier = 2;
				else if(synthDiff > -51) //31-50 levels over recipe
					hqtier = 3;
				else //51+ levels over recipe
					hqtier = 4;
			}
			else
			{
				success = 0.95 - (synthDiff / 10) - (double)(PChar->CraftContainer->getType() == ELEMENT_LIGHTNING) * 0.2;
				canHQ = false;
				if(success < 0.05)
					success = 0.05;

				#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
				ShowDebug(CL_CYAN"SkillID %u: difficulty > 0\n" CL_RESET, skillID);
				#endif
			}

			// Apply synthesis success rate modifier
			int16 modSynthSuccess = PChar->getMod(Mod::SYNTH_SUCCESS);
			success += (double)modSynthSuccess * 0.01;

            if(!canSynthesizeHQ(PChar,skillID))
            {
                success += 0.01; //the crafting rings that block HQ synthesis all also increase their respective craft's success rate by 1%
                canHQ = false; //assuming here that if a crafting ring is used matching a recipe's subsynth, overall HQ will still be blocked
            }

			if (success > 0.99)
			{
				// Clamp success rate to 0.99
				// Even if using kitron macaron, breaks can still happen
				// https://www.bluegartr.com/threads/120352-CraftyMath
				//   "I get a 99% success rate, so Kitron is doing something and it's not small."
				// http://www.ffxiah.com/item/5781/kitron-macaron
				//   "According to one of the Japanese wikis, it is said to decrease the minimum break rate from ~5% to 0.5%-2%."
				success = 0.99;
			}

			double random = dsprand::GetRandomNumber(1.);
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Success: %g  Random: %g\n" CL_RESET, success, random);
			#endif

			if(random < success)
			{
                if(mainID == skillID)
				{
                    random = dsprand::GetRandomNumber(1.);

					switch(hqtier)
					{
						case 4:  chance = 0.500; break;
						case 3:  chance = 0.300; break;
						case 2:  chance = 0.100; break;
						case 1:  chance = 0.015; break;
						default: chance = 0.000; break;
					}

					if(chance > 0)
					{
                        if (map_config.craft_moonphase_matters)
                            chance *= 1.0 - (MoonPhase - 50)/150;  //new moon +33% of base rate bonus to hq chance, full moon -33%, corresponding/weakday/lightsday -33%, opposing/darksday +33%
						
                        if (map_config.craft_day_matters)
                        {
                            if (crystalElement == WeekDay)
                                chance *= 1.0 - ((double)1 / 3);
                            else if (strongElement[crystalElement] == WeekDay)
                                chance *= 1.0 + ((double)1 / 3);
                            else if (strongElement[WeekDay] == crystalElement)
                                chance *= 1.0 - ((double)1 / 3);
                            else if (WeekDay == LIGHTSDAY)
                                chance *= 1.0 - ((double)1 / 3);
                            else if (WeekDay == DARKSDAY)
                                chance *= 1.0 + ((double)1 / 3);
                        }

                        chance = dsp_cap(chance, 0., 0.500);
					}

					#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
					ShowDebug(CL_CYAN"HQ Tier: %i HQ Chance: %g Random: %g SkillID: %u\n" CL_RESET, hqtier, chance, random, skillID);
					#endif

                    if (random < chance && canHQ)
                    {
                        random = dsprand::GetRandomNumber(0, 16);

                        if (random == 0)
                            result = SYNTHESIS_HQ3;
                        else if (random < 4)
                            result = SYNTHESIS_HQ2;
                        else
                            result = SYNTHESIS_HQ;

                    }
				}
			}
            else
            {
				// сохраняем умение, из-за которого синтез провалился.
				// используем slotID ячейки кристалла, т.к. он был удален еще в начале синтеза
				PChar->CraftContainer->setInvSlotID(0,skillID);
				result = SYNTHESIS_FAIL;
				break;
			}
		}
	}

	// результат синтеза записываем в поле quantity ячейки кристалла.
	PChar->CraftContainer->setQuantity(0, result);

	switch(result)
	{
		case SYNTHESIS_FAIL:
			result = RESULT_FAIL;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth failed.\n" CL_RESET);
			#endif
			break;
		case SYNTHESIS_SUCCESS:
			result = RESULT_SUCCESS;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth success.\n" CL_RESET);
			#endif
			break;
		case SYNTHESIS_HQ:
			result = RESULT_HQ;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth HQ.\n" CL_RESET);
			#endif
			break;
		case SYNTHESIS_HQ2:
			result = RESULT_HQ;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth HQ2.\n" CL_RESET);
			#endif
			break;
		case SYNTHESIS_HQ3:
			result = RESULT_HQ;
			#ifdef _DSP_SYNTH_DEBUG_MESSAGES_
			ShowDebug(CL_CYAN"Synth HQ3.\n" CL_RESET);
			#endif
			break;
	}
	return result;
}