// This method was tuenre into a static function to be used outside of the
// class, coz building a magic phrase ane applying a magic action should be
// distinguished but wasn't. (vuarand)
bool CMagicActionBasicDamage::applyOnEntity(
	CMagicPhrase*	phrase,
	CEntityBase*	actor,
	CEntityBase*	target,
	sint32			vamp,
	float			vampRatio,
	CTargetInfos&	targetInfos,
	
	DMGTYPE::EDamageType const	_DmgType,
	sint32 const				_DmgHp,
	sint32 const				_DmgSap,
	sint32 const				_DmgSta,
	sint32 const				_VampirismValue)
{
	// If target is immune to magic tell player and return
	if (targetInfos.Immune)
	{
		SM_STATIC_PARAMS_1(params, STRING_MANAGER::entity);
		params[0].setEIdAIAlias(target->getId(), CAIAliasTranslator::getInstance()->getAIAlias(target->getId()));
		PHRASE_UTILITIES::sendDynamicSystemMessage(actor->getEntityRowId(), "MAGIC_TARGET_IMMUNE", params);
		
		return true;
	}
	
	// If target automatically resist to magic, tell player and return
	if (targetInfos.ResistFactor <= 0.0f)
	{
		PHRASE_UTILITIES::sendSpellResistMessages(actor->getEntityRowId(), target->getEntityRowId());
		return true;
	}
	
	bool sendAggro = true;
	CCreature * npc = dynamic_cast<CCreature*>(target);
	CCharacter * c = dynamic_cast<CCharacter*>(actor);
	if(npc && c)
	{
		if(!PHRASE_UTILITIES::testRange(*actor, *target, (uint32)npc->getMaxHitRangeForPC()*1000))
		{
			const_cast<sint32&>(_DmgHp) = 0;
			const_cast<sint32&>(_DmgSap) = 0;
			const_cast<sint32&>(_DmgSta) = 0;
			const_cast<sint32&>(_VampirismValue) = 0;
			targetInfos.DmgHp = 0;
			sendAggro = false;
			c->sendDynamicSystemMessage(c->getId(), "UNEFFICENT_RANGE");
		}
	}

	sint32 realDmgHp = targetInfos.DmgHp;
	realDmgHp = sint32( target->applyDamageOnArmor( _DmgType, realDmgHp ) );
	if (realDmgHp > target->currentHp())
		realDmgHp = target->currentHp();
	
	targetInfos.ReportAction.Hp += realDmgHp;
	
	// apply vampirism
	vamp += _VampirismValue;
	if (vamp && actor->getId().getType() == RYZOMID::player)
	{
		sint32 vampirise = (sint32) (realDmgHp * vampRatio);
		if (vampirise > vamp)
			vampirise = vamp;
		
		actor->changeCurrentHp(vampirise);
		SM_STATIC_PARAMS_2(params, STRING_MANAGER::entity, STRING_MANAGER::integer);
		params[0].setEIdAIAlias(target->getId(), CAIAliasTranslator::getInstance()->getAIAlias(target->getId()));
		params[1].Int = vampirise;
		CCharacter::sendDynamicSystemMessage(actor->getId(),"EGS_ACTOR_VAMPIRISE_EI", params);
	}
	
	// apply Sap damage
	sint32 realDmgSap = 0;
	{
		SCharacteristicsAndScores& score = target->getScores()._PhysicalScores[SCORES::sap];
		sint32 maxRealDmgSap = (sint32)( _DmgSap * targetInfos.DmgFactor );
		realDmgSap = target->applyDamageOnArmor(_DmgType, maxRealDmgSap);
		if (realDmgSap != 0)
		{
			PHRASE_UTILITIES::sendScoreModifierSpellMessage(actor->getId(), target->getId(), -realDmgSap, -maxRealDmgSap, SCORES::sap, ACTNATURE::OFFENSIVE_MAGIC);
			
			if (realDmgSap > score.Current)
				realDmgSap = score.Current;
			score.Current = score.Current - realDmgSap;
			
			targetInfos.ReportAction.Sap += realDmgSap;
		}
	}
	
	// apply Stamina damage
	sint32 realDmgSta = 0;
	{
		SCharacteristicsAndScores &score = target->getScores()._PhysicalScores[SCORES::stamina];
		sint32 maxRealDmgSta =  sint32( _DmgSta * targetInfos.DmgFactor );
		realDmgSta = target->applyDamageOnArmor( _DmgType, maxRealDmgSta );
		if (realDmgSta != 0)
		{
			PHRASE_UTILITIES::sendScoreModifierSpellMessage(actor->getId(), target->getId(), -realDmgSta, -maxRealDmgSta, SCORES::stamina, ACTNATURE::OFFENSIVE_MAGIC);
			
			if (realDmgSta > score.Current)
				realDmgSta = score.Current;
			score.Current = score.Current - realDmgSta;
			
			targetInfos.ReportAction.Sta += realDmgSta;
		}
	}
	
	targetInfos.ReportAction.ActionNature = ACTNATURE::OFFENSIVE_MAGIC;
	
	// compute aggro
	sint32 max = target->maxHp();
	
	float aggroHp = 0.0f;
	float aggroSap = 0.0f;
	float aggroSta = 0.0f;
	
	CAiEventReport report;
	if (phrase)
		report.Originator = phrase->getActor();
	else
		report.Originator = actor->getEntityRowId();
	report.Target = target->getEntityRowId();
	report.Type = ACTNATURE::OFFENSIVE_MAGIC;
	if (max && _DmgHp != 0)
	{
		aggroHp = min(1.0f, float(realDmgHp)/float(max) );
		report.addDelta(AI_EVENT_REPORT::HitPoints, (-1)*realDmgHp);
	}
	
	max = target->getPhysScores()._PhysicalScores[SCORES::sap].Max;
	if (max && _DmgSap != 0)
	{
		aggroSap = min(1.0f, float(realDmgSap)/float(max) );
		report.addDelta(AI_EVENT_REPORT::Sap, (-1)*realDmgSap);
	}
	
	max = target->getPhysScores()._PhysicalScores[SCORES::stamina].Max;
	if (max && _DmgSta != 0)
	{
		aggroSta = min(1.0f,float(realDmgSta)/float(max));
		report.addDelta(AI_EVENT_REPORT::Stamina, (-1)*realDmgSta);
	}
	
	// send report
	report.AggroAdd = - min(1.0f, 1.0f - (1.0f-aggroHp)*(1.0f-aggroSap)*(1.0f-aggroSta) );
	
	if(sendAggro)
		CPhraseManager::getInstance().addAiEventReport(report);
	
	// apply Hp damage
	if (realDmgHp > 0)
	{
		if ( target->changeCurrentHp( -realDmgHp, actor->getEntityRowId()) )
		{
			PHRASE_UTILITIES::sendScoreModifierSpellMessage( actor->getId(), target->getId(), -realDmgHp, -targetInfos.DmgHp ,SCORES::hit_points , ACTNATURE::OFFENSIVE_MAGIC);
			PHRASE_UTILITIES::sendDeathMessages( actor->getEntityRowId(), target->getEntityRowId() );
		}
		else
		{
			PHRASE_UTILITIES::sendScoreModifierSpellMessage( actor->getId(), target->getId(), -realDmgHp, -targetInfos.DmgHp ,SCORES::hit_points , ACTNATURE::OFFENSIVE_MAGIC);
		}
	}
	
	return !sendAggro;
}
bool CMagicActionBasicDamage::launchOnEntity(
	CMagicPhrase*		phrase,
	CEntityBase*		actor,
	CEntityBase*		target,
	bool				mainTarget,
	uint32				casterSkillvalue,
	uint32				casterSkillBaseValue,
	MBEHAV::CBehaviour&	behav,
	bool				isMad,
	float				rangeFactor,
	CTargetInfos&		targetInfos)
{
	// for main target only, check reflect damage effects
	if (mainTarget)
	{
		const CSEffectPtr effect = target->lookForActiveEffect(EFFECT_FAMILIES::ReflectDamage);
		if ( effect )
		{
			target = actor;
			isMad = true;
		}
	}

	// change caster skill according to target race (for special items that gives a skill bonus against Kitins for exemple)
	casterSkillvalue += actor->getSkillModifierForRace(target->getRace());

	// init target infos
	targetInfos.RowId			= target->getEntityRowId();
	targetInfos.MainTarget		= mainTarget;
	targetInfos.DmgHp			= 0;
	targetInfos.ResistFactor	= 1.0f;
	targetInfos.DmgFactor		= 1.0f;
	targetInfos.Immune			= false;

	targetInfos.ReportAction.TargetRowId = target->getEntityRowId();

	if( target->getId().getType() != RYZOMID::player )
	{
		const CStaticCreatures * creatureSheet = target->getForm();
		if( creatureSheet != 0 )
		{
			targetInfos.ReportAction.DeltaLvl = casterSkillBaseValue - creatureSheet->getXPLevel();
		}
	}

	
	// test resistance
	float resistFactor = 1.0f;
	//if entity invincible, it aways resists the effect
	const CSEffectPtr effect = target->lookForActiveEffect(EFFECT_FAMILIES::Invincibility);
	if ( effect )
	{
		targetInfos.Immune = true;
		resistFactor = 0.0f;
	}
	else
	{
		if (!EntitiesNoResist)
		{
			uint32 resistValue = target->getMagicResistance(_DmgType);

			if (resistValue == CCreatureResists::ImmuneScore )
			{
				targetInfos.Immune = true;
				resistFactor = 0.0f;
			}
			else
			{
				if ( actor->getId().getType() == RYZOMID::player )
				{
					// boost magic skill for low level chars
					uint32 sb = MagicSkillStartValue.get();
					casterSkillvalue = max( sb, casterSkillvalue );

					// add magic boost from consumable
					CCharacter * pC = dynamic_cast<CCharacter *>(actor);
					if(pC)
						casterSkillvalue += pC->magicSuccessModifier();
				}

				// get the chances
				const uint8 roll = (uint8)RandomGenerator.rand( 99 );
				resistFactor = CStaticSuccessTable::getSuccessFactor(SUCCESS_TABLE_TYPE::MagicResistDirect, casterSkillvalue - resistValue, roll);

				// increase resists modifier for next resists test
				if (resistFactor > 0.0f)
					target->incResistModifier(_DmgType, resistFactor);

				if ( resistFactor <= 0.0f )
				{
					// Xp gain log
					if (PlayerManager.logXPGain(actor->getEntityRowId()))
					{
						const uint8 chances = CStaticSuccessTable::getSuccessChance( SUCCESS_TABLE_TYPE::MagicResistDirect, casterSkillvalue - resistValue ); 
						nlinfo("[XPLOG] Magic attack Actor %s on %s, delta = %d, target has Resisted (chances %u, tirage %u)", actor->getId().toString().c_str(), target->getId().toString().c_str(),
							targetInfos.ReportAction.DeltaLvl, chances, roll);
					}
				}
			}
		}
		else
		{
			resistFactor = 1.0f;
		}
	}
	if ( resistFactor > 0.0f )
	{
		if ( resistFactor > 1.0f )
			resistFactor = 1.0f;
		
		float dmgFactor = resistFactor * rangeFactor * (1.0f + phrase->getUsedItemStats().getPowerFactor(_Skill, phrase->getBrickMaxSabrinaCost()));
		
		// if PVP, apply PVP magic damage factor
		if( actor != target && actor->getId().getType() == RYZOMID::player && target->getId().getType() == RYZOMID::player)
		{
			dmgFactor *= PVPMagicDamageFactor.get();
		}

		// add spire effect ( magic offense )
		if ( actor->getId().getType() == RYZOMID::player )
		{
			CCharacter* charac = (CCharacter*)actor;
			const CSEffect* pEffect = charac->lookForActiveEffect( EFFECT_FAMILIES::TotemCombatMagOff );
			if ( pEffect != NULL )
			{
				dmgFactor *= ( 1.0f + pEffect->getParamValue() / 100.0f );
			}
		}
		
		sint32 maxDmgHp =  sint32 ( _DmgHp * dmgFactor );
		sint32 realDmgHp = target->applyDamageOnArmor( _DmgType, maxDmgHp );
		
		// update behaviour for lost Hp
		CCreature * npc = dynamic_cast<CCreature*>(target);
		CCharacter * c = dynamic_cast<CCharacter*>(actor);
		if(npc && c)
		{
			if(PHRASE_UTILITIES::testRange(*actor, *target, (uint32)npc->getMaxHitRangeForPC()*1000))
			{
				behav.DeltaHP -= (sint16)realDmgHp;
			}
			else
			{
				behav.DeltaHP = 0;
			}
		}
		
		// update target infos
		targetInfos.DmgHp			= maxDmgHp;
		targetInfos.ResistFactor	= resistFactor;
		targetInfos.DmgFactor		= dmgFactor;
		
		return false;
	}
	else
	{
		// don't tell the player now, but wait to send message when the missile hit the player (at apply() time)
		targetInfos.ResistFactor	= 0.f;
		
		CAiEventReport report;
		report.Originator = phrase->getActor();
		report.Target = target->getEntityRowId();
		report.Type = ACTNATURE::OFFENSIVE_MAGIC;
		//////////////////////////////////////////////////////////////////////////
		// TEMPORARY : set a small value for resist aggro
		//////////////////////////////////////////////////////////////////////////					
		report.AggroAdd = -0.02f;
		CCreature * npc = dynamic_cast<CCreature*>(target);
		CCharacter * c = dynamic_cast<CCharacter*>(actor);
		if(npc && c && PHRASE_UTILITIES::testRange(*actor, *target, (uint32)npc->getMaxHitRangeForPC()*1000) )
			CPhraseManager::getInstance().addAiEventReport(report);
		return true;
	}
}