int CClient::GetMagicResistRatio() {
	int ret = m_cSkillMastery[SKILL_MAGICRES] +m_iAddMR; 
	if (GetMag() > 50) {
		ret += GetMag() - 50;
	}
	ret += m_iAddResistMagic;
	return ret;
}
void AVector::Normalize() // makes vector unit length
{
	float magnitude = GetMag();
	
	for (int i = 0; i < V_DIMENSION; ++i)
		data[i] /= magnitude;
}
int CClient::GetMaxMP() const
{
	int iRet;

	iRet = (2*(GetMag()) ) + (2*m_iLevel) + ((GetInt())/2);

	return iRet;
}
bool CClient::CanSkillUp(skillIndexes skillindex) {
	int currentskill = m_cSkillMastery[skillindex];
	currentskill++;
	switch (skillindex) {
	case SKILL_MINING:
	case SKILL_HANDATTACK:
	case SKILL_MANUFACTURING:
		// limit: 2*str
		if (currentskill > (GetStr() * 2)) {
			return false;
		}
		break;

	case SKILL_MAGICRES:
		// limit: 2*lvl
		if (currentskill > (GetLevel() * 2)) {
			return false;
		}
		break;

	case SKILL_MAGIC:
	case SKILL_STAFF:
		// limit: 2*mag
		if (currentskill > (GetMag() * 2)) {
			return false;
		}
		break;

	case SKILL_FISHING:
	case SKILL_ARCHERY:
	case SKILL_SHORTSWORD:
	case SKILL_LONGSWORD:
	case SKILL_FENCING:
	case SKILL_AXE:
	case SKILL_SHIELD:
	case SKILL_HAMMER:
		// limit: 2*dex
		if (currentskill > (GetDex() * 2)) {
			return false;
		}
		break;

	case SKILL_FARMING:
	case SKILL_ALCHEMY:
	case SKILL_15:
	case SKILL_PRETENDCORPSE:
		// limit: 2*int
		if (currentskill > (GetInt() * 2)) {
			return false;
		}
		break;

	case SKILL_POISONRES:
		// limit: 2*vit
		if (currentskill > (GetVit() * 2)) {
			return false;
		}
		break;
	}
	return true;
}
void CClient::ValidateSkills(bool logInvalidSkills)
{
	if(IsGM()) return;

	int invalidSkills = 0;
	char logMessage[100];
	for (int skillIndex = 0; skillIndex < MAXSKILLTYPE; skillIndex++)
	{	
		switch (skillIndex) {
		case SKILL_MINING:  
		case SKILL_MANUFACTURING:
		case SKILL_HANDATTACK:
			if (m_cSkillMastery[skillIndex] > (GetStr() * 2)) 
			{	
				invalidSkills += m_cSkillMastery[skillIndex] - (GetStr() * 2);
				m_cSkillMastery[skillIndex] = GetStr() * 2;
				m_iSkillSSN[skillIndex] = 0;
				Notify(NULL, NOTIFY_SKILL, skillIndex, m_cSkillMastery[skillIndex], NULL, NULL);
			}
			break;

		case SKILL_MAGICRES:
			if (m_cSkillMastery[skillIndex] > (m_iLevel * 2)) 
			{	
				invalidSkills += m_cSkillMastery[skillIndex] - (m_iLevel * 2);
				m_cSkillMastery[skillIndex] = m_iLevel * 2;
				m_iSkillSSN[skillIndex] = 0;
				Notify(NULL, NOTIFY_SKILL, skillIndex, m_cSkillMastery[skillIndex], NULL, NULL);
			}
			break;

		case SKILL_MAGIC:
		case SKILL_STAFF:
			if (m_cSkillMastery[skillIndex] > (GetMag() * 2))
			{	
				invalidSkills += m_cSkillMastery[skillIndex] - (GetMag() * 2);
				m_cSkillMastery[skillIndex] = GetMag() * 2;
				m_iSkillSSN[skillIndex] = 0;
				Notify(NULL, NOTIFY_SKILL, skillIndex, m_cSkillMastery[skillIndex], NULL, NULL);
			}
			break;

		case SKILL_FISHING:
		case SKILL_ARCHERY:
		case SKILL_SHORTSWORD:
		case SKILL_LONGSWORD:
		case SKILL_FENCING:
		case SKILL_AXE:
		case SKILL_SHIELD:
		case SKILL_HAMMER:
			if (m_cSkillMastery[skillIndex] > (GetDex() * 2)) 
			{	
				invalidSkills += m_cSkillMastery[skillIndex] - (GetDex() * 2);
				m_cSkillMastery[skillIndex] = GetDex() * 2;
				m_iSkillSSN[skillIndex] = 0;
				Notify(NULL, NOTIFY_SKILL, skillIndex, m_cSkillMastery[skillIndex], NULL, NULL);
			}
			break;

		case SKILL_ALCHEMY:
		case SKILL_FARMING:
		case SKILL_PRETENDCORPSE:
			if (m_cSkillMastery[skillIndex] > (GetInt() * 2)) 
			{	
				invalidSkills += m_cSkillMastery[skillIndex] - (GetInt() * 2);
				m_cSkillMastery[skillIndex] = GetInt() * 2;
				m_iSkillSSN[skillIndex] = 0;
				Notify(NULL, NOTIFY_SKILL, skillIndex, m_cSkillMastery[skillIndex], NULL, NULL);
			}
			break;

		case SKILL_POISONRES:
			if (m_cSkillMastery[skillIndex] > (GetVit() * 2)) 
			{	
				invalidSkills += m_cSkillMastery[skillIndex] - (GetVit() * 2);
				m_cSkillMastery[skillIndex] = GetVit() * 2;
				m_iSkillSSN[skillIndex] = 0;
				Notify(NULL, NOTIFY_SKILL, skillIndex, m_cSkillMastery[skillIndex], NULL, NULL);
			}
			break;
		default:
			m_iSkillSSN[skillIndex] = 0;
			break;
		}
	}

	if(logInvalidSkills && (invalidSkills > 0))
	{
		wsprintf(logMessage, "PC(%s) A skill was too high, reduced by (%d) points", m_cCharName, invalidSkills);
		PutLogList(logMessage);
	}
}