Files
abysmal-isle/Scripts/Services/Pet Training/AreaEffects.cs
Unstable Kitsune b918192e4e Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
2023-11-28 23:20:26 -05:00

597 lines
18 KiB
C#

using System;
using Server;
using System.Collections.Generic;
using Server.Spells;
using System.Linq;
using Server.Network;
using Server.Items;
namespace Server.Mobiles
{
public abstract class AreaEffect
{
public virtual int ManaCost { get { return 20; } }
public virtual int MaxRange { get { return 3; } }
public virtual double TriggerChance { get { return 1.0; } }
public virtual TimeSpan CooldownDuration { get { return TimeSpan.FromSeconds(30); } }
public virtual bool RequiresCombatant { get { return true; } }
public virtual int EffectRange { get { return 5; } }
public AreaEffect()
{
}
public static bool CheckThinkTrigger(BaseCreature bc)
{
var profile = PetTrainingHelper.GetAbilityProfile(bc);
if (profile != null)
{
AreaEffect effect = null;
var effects = profile.GetAreaEffects().Where(a => !a.IsInCooldown(bc)).ToArray();
if (effects != null && effects.Length > 0)
{
effect = effects[Utility.Random(effects.Length)];
}
if (effect != null)
{
return effect.Trigger(bc, bc.Combatant as Mobile);
}
}
return false;
}
public virtual bool Trigger(BaseCreature creature, Mobile combatant)
{
if (CheckMana(creature) && Validate(creature, combatant) && TriggerChance >= Utility.RandomDouble())
{
creature.Mana -= ManaCost;
DoEffects(creature, combatant);
AddToCooldown(creature);
return true;
}
return false;
}
public virtual bool Validate(BaseCreature attacker, Mobile defender)
{
if (!attacker.Alive || attacker.Deleted || attacker.IsDeadBondedPet || attacker.BardPacified)
{
return false;
}
return !RequiresCombatant || (defender != null && defender.Alive && !defender.Deleted &&
!defender.IsDeadBondedPet && defender.InRange(attacker.Location, MaxRange) &&
defender.Map == attacker.Map && attacker.InLOS(defender));
}
public bool CheckMana(BaseCreature bc)
{
return !bc.Controlled || bc.Mana >= ManaCost;
}
public virtual void DoEffects(BaseCreature creature, Mobile combatant)
{
if (creature.Map == null || creature.Map == Map.Internal)
return;
var count = 0;
foreach (var m in FindValidTargets(creature, EffectRange))
{
count++;
DoEffect(creature, m);
}
if (count > 0)
{
OnAfterEffects(creature, combatant);
}
}
public virtual void DoEffect(BaseCreature creature, Mobile defender)
{
}
public virtual void OnAfterEffects(BaseCreature creature, Mobile defender)
{
}
public static IEnumerable<Mobile> FindValidTargets(BaseCreature creature, int range)
{
IPooledEnumerable eable = creature.GetMobilesInRange(range);
foreach (Mobile m in eable.OfType<Mobile>())
{
if (ValidTarget(creature, m))
{
yield return m;
}
}
eable.Free();
}
public static bool ValidTarget(Mobile from, Mobile to)
{
return to != from && to.Alive && !to.IsDeadBondedPet &&
from.CanBeHarmful(to, false) &&
SpellHelper.ValidIndirectTarget(from, to) &&
from.InLOS(to);
}
public List<BaseCreature> _Cooldown;
public bool IsInCooldown(BaseCreature m)
{
return _Cooldown != null && _Cooldown.Contains(m);
}
public void AddToCooldown(BaseCreature bc)
{
var cooldown = GetCooldown(bc);
if (cooldown != TimeSpan.MinValue)
{
if (_Cooldown == null)
_Cooldown = new List<BaseCreature>();
_Cooldown.Add(bc);
Timer.DelayCall<BaseCreature>(cooldown, RemoveFromCooldown, bc);
}
}
public virtual TimeSpan GetCooldown(BaseCreature m)
{
return CooldownDuration;
}
public void RemoveFromCooldown(BaseCreature m)
{
_Cooldown.Remove(m);
}
public static AreaEffect[] Effects { get { return _Effects; } }
private static AreaEffect[] _Effects;
static AreaEffect()
{
_Effects = new AreaEffect[7];
_Effects[0] = new AuraOfEnergy();
_Effects[1] = new AuraOfNausea();
_Effects[2] = new EssenceOfDisease();
_Effects[3] = new EssenceOfEarth();
_Effects[4] = new ExplosiveGoo();
_Effects[5] = new AuraDamage();
_Effects[6] = new PoisonBreath();
}
public static AreaEffect AuraOfEnergy
{
get
{
return _Effects[0];
}
}
public static AreaEffect AuraOfNausea
{
get
{
return _Effects[1];
}
}
public static AreaEffect EssenceOfDisease
{
get
{
return _Effects[2];
}
}
public static AreaEffect EssenceOfEarth
{
get
{
return _Effects[3];
}
}
public static AreaEffect ExplosiveGoo
{
get
{
return _Effects[4];
}
}
public static AreaEffect AuraDamage
{
get
{
return _Effects[5];
}
}
public static AreaEffect PoisonBreath
{
get
{
return _Effects[6];
}
}
}
public class AuraOfEnergy : AreaEffect
{
public AuraOfEnergy()
{
}
public override void DoEffect(BaseCreature creature, Mobile defender)
{
AOS.Damage(defender, creature, Utility.RandomMinMax(20, 30), 0, 0, 0, 0, 100);
defender.SendLocalizedMessage(1072073, false, creature.Name); // : The creature's aura of energy is damaging you!
creature.DoHarmful(defender);
defender.FixedParticles(0x374A, 10, 30, 5052, 1278, 0, EffectLayer.Waist);
defender.PlaySound(0x51D);
}
}
public class AuraOfNausea : AreaEffect
{
public override TimeSpan CooldownDuration { get { return TimeSpan.FromSeconds(40 + Utility.RandomDouble() * 30); } }
public override int MaxRange { get { return 4; } }
public override int EffectRange { get { return 4; } }
public override int ManaCost { get { return 100; } }
public static Dictionary<Mobile, Timer> _Table;
public AuraOfNausea()
{
}
public override void DoEffect(BaseCreature creature, Mobile defender)
{
if (_Table == null)
{
_Table = new Dictionary<Mobile, Timer>();
}
if (_Table.ContainsKey(defender))
{
Timer timer = _Table[defender];
if (timer != null)
timer.Stop();
_Table[defender] = Timer.DelayCall<Mobile>(TimeSpan.FromSeconds(30), EndNausea, defender);
}
else
{
_Table.Add(defender, Timer.DelayCall<Mobile>(TimeSpan.FromSeconds(30), EndNausea, defender));
}
defender.Animate(32, 5, 1, true, false, 0); // bow animation
defender.SendLocalizedMessage(1072068); // Your enemy's putrid presence envelops you, overwhelming you with nausea.
BuffInfo.AddBuff(defender, new BuffInfo(BuffIcon.AuraOfNausea, 1153792, 1153819, TimeSpan.FromSeconds(30), defender, "60\t60\t60\t5"));
}
public static void EndNausea(Mobile m)
{
if (_Table != null && _Table.ContainsKey(m))
{
_Table.Remove(m);
BuffInfo.RemoveBuff(m, BuffIcon.AuraOfNausea);
m.Delta(MobileDelta.WeaponDamage);
if (_Table.Count == 0)
_Table = null;
}
}
public static bool UnderNausea(Mobile m)
{
return _Table != null && _Table.ContainsKey(m);
}
}
public class EssenceOfDisease : AreaEffect
{
public EssenceOfDisease()
{
}
public override void DoEffect(BaseCreature creature, Mobile defender)
{
AOS.Damage(defender, creature, Utility.RandomMinMax(20, 30), 0, 0, 0, 100, 0);
defender.SendLocalizedMessage(1072074, false, creature.Name);
creature.DoHarmful(defender);
defender.FixedParticles(0x374A, 10, 30, 5052, 1272, 0, EffectLayer.Waist);
defender.PlaySound(0x476);
}
}
public class EssenceOfEarth : AreaEffect
{
public EssenceOfEarth()
{
}
public override void DoEffect(BaseCreature creature, Mobile defender)
{
AOS.Damage(defender, creature, Utility.RandomMinMax(20, 30), 100, 0, 0, 0, 0);
defender.SendLocalizedMessage(1072075, false, creature.Name);
creature.DoHarmful(defender);
defender.FixedParticles(0x374A, 10, 30, 5052, 1836, 0, EffectLayer.Waist);
defender.PlaySound(0x22C);
}
}
public class ExplosiveGoo : AreaEffect
{
public override int ManaCost { get { return 30; } }
private bool _DoingEffect;
public ExplosiveGoo()
{
}
public override void DoEffects(BaseCreature creature, Mobile combatant)
{
if (_DoingEffect)
return;
Server.Effects.SendTargetParticles(creature, 0x3709, 10, 15, 2724, 0, 9907, EffectLayer.LeftFoot, 0);
creature.PlaySound(0x348);
_DoingEffect = true;
Timer.DelayCall(TimeSpan.FromSeconds(1.0), () =>
{
base.DoEffects(creature, combatant);
_DoingEffect = false;
});
}
public override void DoEffect(BaseCreature creature, Mobile defender)
{
Timer.DelayCall<Mobile>(TimeSpan.FromMilliseconds(Utility.RandomMinMax(10, 1000)), m =>
{
if (m.Alive && !m.Deleted && m.Map != null)
{
Point3D p = m.Location;
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
Server.Effects.SendLocationEffect(new Point3D(p.X + x, p.Y + y, p.Z), m.Map, 0x3728, 13, 1921, 3);
}
}
creature.DoHarmful(defender);
AOS.Damage(m, creature, Utility.RandomMinMax(30, 40), 0, 100, 0, 0, 0);
m.SendLocalizedMessage(1112366); // The flammable goo covering you bursts into flame!
}
}, defender);
}
}
public class PoisonBreath : AreaEffect
{
public override double TriggerChance { get { return 0.4; } }
public override int EffectRange { get { return 10; } }
public override int ManaCost { get { return 50; } }
public PoisonBreath()
{
}
public override void DoEffect(BaseCreature creature, Mobile m)
{
m.ApplyPoison(creature, GetPoison(creature));
Server.Effects.SendLocationParticles(
EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), 0x36B0, 1, 14, 63, 7, 9915, 0);
Server.Effects.PlaySound(m.Location, m.Map, 0x229);
var damage = GetDamage(creature);
if (damage > 0)
{
creature.DoHarmful(m);
AOS.Damage(m, creature, damage, 0, 0, 0, 100, 0);
}
}
public override void OnAfterEffects(BaseCreature creature, Mobile defender)
{
if (creature.Controlled)
{
var profile = PetTrainingHelper.GetAbilityProfile(creature);
if ((profile != null && profile.HasAbility(MagicalAbility.Poisoning)) || 0.2 > Utility.RandomDouble())
creature.CheckSkill(SkillName.Poisoning, 0, creature.Skills[SkillName.Poisoning].Cap);
}
}
public Poison GetPoison(BaseCreature bc)
{
int level = 0;
double total = bc.Skills[SkillName.Poisoning].Value;
if (total >= 100)
level = 4;
else if (total > 60)
level = 3;
else if (total > 40)
level = 2;
else if (total > 20)
level = 1;
return Poison.GetPoison(level);
}
public int GetDamage(BaseCreature bc)
{
if (_DamageCreatures.Any(t => t == bc.GetType()))
return 50;
return 0;
}
private Type[] _DamageCreatures =
{
typeof(ValoriteElemental), typeof(BronzeElemental), typeof(Dimetrosaur), typeof(ChiefParoxysmus)
};
}
public class AuraDamage : AreaEffect
{
public override double TriggerChance { get { return 0.4; } }
public override int EffectRange { get { return 10; } }
public override int ManaCost { get { return 0; } }
public override bool RequiresCombatant { get { return false; } }
public AuraDamage()
{
}
public override TimeSpan GetCooldown(BaseCreature bc)
{
return AuraDefinition.GetDefinition(bc).Cooldown;
}
public override void DoEffect(BaseCreature creature, Mobile m)
{
var def = AuraDefinition.GetDefinition(creature);
if (def.Damage > 0)
{
AOS.Damage(
m,
creature,
def.Damage,
def.Physical,
def.Fire,
def.Cold,
def.Poison,
def.Energy,
def.Chaos,
def.Direct,
DamageType.SpellAOE);
m.RevealingAction();
}
if (creature is IAuraCreature)
{
((IAuraCreature)creature).AuraEffect(m);
}
}
public class AuraDefinition
{
public TimeSpan Cooldown { get; set; }
public int Range { get; set; }
public int Damage { get; set; }
public int Physical { get; set; }
public int Fire { get; set; }
public int Cold { get; set; }
public int Poison { get; set; }
public int Energy { get; set; }
public int Chaos { get; set; }
public int Direct { get; set; }
public Type[] Uses { get; private set; }
public AuraDefinition()
: this(TimeSpan.FromSeconds(5), 4, 5, 0, 0, 0, 0, 0, 0, 100, new Type[] { })
{
}
public AuraDefinition(params Type[] uses)
: this(TimeSpan.FromSeconds(5), 2, 5, 0, 100, 0, 0, 0, 0, 0, uses)
{
}
public AuraDefinition(TimeSpan cooldown, int range, int baseDamage, int phys, int fire, int cold, int poison, int energy, int chaos, int direct, Type[] uses)
{
Cooldown = cooldown;
Range = range;
Damage = baseDamage;
Physical = phys;
Fire = fire;
Cold = cold;
Poison = poison;
Energy = energy;
Chaos = chaos;
Direct = direct;
Uses = uses;
}
public static List<AuraDefinition> Definitions { get; private set; } = new List<AuraDefinition>();
public static void Initialize()
{
AuraDefinition defaul;
AuraDefinition cora;
AuraDefinition fireAura;
AuraDefinition coldAura;
defaul = new AuraDefinition();
Definitions.Add(defaul);
cora = new AuraDefinition(typeof(CoraTheSorceress));
cora.Range = 3;
cora.Damage = 10;
cora.Fire = 0;
Definitions.Add(cora);
fireAura = new AuraDefinition(typeof(FlameElemental), typeof(FireDaemon), typeof(LesserFlameElemental));
fireAura.Range = 5;
fireAura.Damage = 7;
Definitions.Add(fireAura);
coldAura = new AuraDefinition(typeof(ColdDrake), typeof(FrostDrake), typeof(FrostDragon), typeof(SnowElemental), typeof(FrostMite), typeof(IceFiend), typeof(IceElemental), typeof(CorporealBrume));
coldAura.Damage = 15;
coldAura.Fire = 0;
coldAura.Cold = 100;
Definitions.Add(coldAura);
}
public static AuraDefinition GetDefinition(BaseCreature bc)
{
var def = Definitions.FirstOrDefault(d => d.Uses.Any(t => t == bc.GetType()));
if (def == null)
{
return Definitions[0]; // Default
}
return def;
}
}
}
}