// 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; } }