/// <summary>
/// Handles Heavy Stander bonuses and auto-defense, reducing damage
/// and setting the appropriate options on tAction. Returns whether
/// or not Heavy Stander pinged.
/// </summary>
/// <remarks>
/// All active and passive Heavy Standers are checked in sequence,
/// followed by the equipment, with the passive damage reduction
/// stacking. It's unknown whether this is official, and assumedly
/// no monsters have multiple Heavy Stander skills.
/// The ping reduction is only applied once, no matter where it
/// came from.
/// </remarks>
/// <param name="attacker"></param>
/// <param name="target"></param>
/// <param name="damage"></param>
/// <param name="tAction"></param>
public static bool Handle(Creature attacker, Creature target, ref float damage, TargetAction tAction)
{
var pinged = false;
var rank = DefaultMsgRank;
var rnd = RandomProvider.Get();
// Dark Lord is immune to melee and magic damage,
// like a R1 passive defense, but he doesn't ping.
if (target.HasTag("/darklord/") && !target.HasTag("/darklord/darklord2/"))
{
damage = 1;
return false;
}
// Monsters with the /beatable_only/ tag don't take damage from
// anything but pillows. Pillows on the other hand do 3x damage.
// (Guessed, based on event information and client data.)
if (target.HasTag("/beatable_only/"))
{
var rightHand = attacker.RightHand;
if (rightHand == null || !rightHand.HasTag("/pillow/"))
damage = 1;
else
damage *= 3;
}
// Check skills
for (int i = 0; i < Skills.Length; ++i)
{
// Check if skill exists and it's either in use or passive
var skill = target.Skills.Get(Skills[i]);
if (skill != null && (skill.Info.Id == SkillId.HeavyStanderPassive || skill.Has(SkillFlags.InUse)))
{
var damageReduction = skill.RankData.Var1;
var activationChance = skill.RankData.Var3;
// Apply damage reduction
if (damageReduction > 0)
damage = Math.Max(1, damage - (damage / 100 * damageReduction));
// Apply auto defense
if (!pinged && rnd.Next(100) < activationChance)
{
pinged = true;
rank = skill.Info.Rank;
}
}
}
// Check equipment
if (!pinged)
{
var equipment = target.Inventory.GetMainEquipment();
for (int i = 0; i < equipment.Length; ++i)
{
var activationChance = equipment[i].Data.AutoDefenseMelee;
// Add upgrades
activationChance += equipment[i].MetaData1.GetFloat("IM_MLE") * 100;
if (activationChance > 0 && rnd.Next(100) < activationChance)
{
pinged = true;
break;
}
}
}
// Notice, flag, and damage reduction
if (pinged)
{
damage = Math.Max(1, damage / 2);
tAction.EffectFlags |= EffectFlags.HeavyStander;
var msg = "";
if (rank >= SkillRank.Novice && rank <= SkillRank.RA)
msg = rnd.Rnd(Lv1Msgs);
else if (rank >= SkillRank.R9 && rank <= SkillRank.R5)
msg = rnd.Rnd(Lv2Msgs);
else if (rank >= SkillRank.R4 && rank <= SkillRank.R1)
msg = rnd.Rnd(Lv3Msgs);
Send.Notice(attacker, msg);
}
return pinged;
}