Overwrite

Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
Unstable Kitsune
2023-11-28 23:20:26 -05:00
parent 3cd54811de
commit b918192e4e
11608 changed files with 2644205 additions and 47 deletions

View File

@@ -0,0 +1,759 @@
using System;
using Server;
using System.Collections.Generic;
using System.Linq;
using Server.Items;
namespace Server.Mobiles
{
[PropertyObject]
public class AbilityProfile
{
[CommandProperty(AccessLevel.GameMaster)]
public MagicalAbility MagicalAbility { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public AreaEffect[] AreaEffects { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public SpecialAbility[] SpecialAbilities { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public WeaponAbility[] WeaponAbilities { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool TokunoTame { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int RegenHits { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int RegenStam { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int RegenMana { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int DamageIndex { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public BaseCreature Creature { get; private set; }
public List<object> Advancements { get; private set; }
public AbilityProfile(BaseCreature bc)
{
Creature = bc;
DamageIndex = -1;
}
public void OnTame()
{
if (Creature.ControlMaster is PlayerMobile)
{
Server.Engines.Quests.TamingPetQuest.CheckTame((PlayerMobile)Creature.ControlMaster);
}
if (Creature.Map == Map.Tokuno)
{
TokunoTame = true;
}
}
public bool AddAbility(MagicalAbility ability, bool advancement = true)
{
if (Creature.Controlled)
{
var oldAbility = MagicalAbility;
if (IsSpecialMagicalAbility(oldAbility))
{
RemoveSpecialMagicalAbility(oldAbility);
}
OnRemoveMagicalAbility(oldAbility, ability);
MagicalAbility = ability;
}
else
{
MagicalAbility |= ability;
}
OnAddAbility(ability, advancement);
return true;
}
public bool AddAbility(SpecialAbility ability, bool advancement = true)
{
if (SpecialAbilities == null)
{
SpecialAbilities = new SpecialAbility[] { ability };
}
else if (!SpecialAbilities.Any(a => a == ability))
{
var temp = SpecialAbilities;
SpecialAbilities = new SpecialAbility[temp.Length + 1];
for (int i = 0; i < temp.Length; i++)
SpecialAbilities[i] = temp[i];
SpecialAbilities[temp.Length] = ability;
}
OnAddAbility(ability, advancement);
return true;
}
public bool AddAbility(AreaEffect ability, bool advancement = true)
{
if (AreaEffects == null)
{
AreaEffects = new AreaEffect[] { ability };
}
else if (!AreaEffects.Any(a => a == ability))
{
var temp = AreaEffects;
AreaEffects = new AreaEffect[temp.Length + 1];
for (int i = 0; i < temp.Length; i++)
AreaEffects[i] = temp[i];
AreaEffects[temp.Length] = ability;
}
OnAddAbility(ability, advancement);
return true;
}
public bool AddAbility(WeaponAbility ability, bool advancement = true)
{
if (WeaponAbilities == null)
{
WeaponAbilities = new WeaponAbility[] { ability };
}
else if(!WeaponAbilities.Any(a => a == ability))
{
var temp = WeaponAbilities;
WeaponAbilities = new WeaponAbility[temp.Length + 1];
for (int i = 0; i < temp.Length; i++)
WeaponAbilities[i] = temp[i];
WeaponAbilities[temp.Length] = ability;
}
OnAddAbility(ability, advancement);
return true;
}
public void RemoveAbility(MagicalAbility ability)
{
if ((MagicalAbility & ability) != 0)
{
MagicalAbility ^= ability;
RemovePetAdvancement(ability);
}
}
public void RemoveAbility(SpecialAbility ability)
{
if (SpecialAbilities == null || !SpecialAbilities.Any(a => a == ability))
return;
var list = SpecialAbilities.ToList();
list.Remove(ability);
RemovePetAdvancement(ability);
SpecialAbilities = list.ToArray();
ColUtility.Free(list);
}
public void RemoveAbility(WeaponAbility ability)
{
if (WeaponAbilities == null || !WeaponAbilities.Any(a => a == ability))
return;
var list = WeaponAbilities.ToList();
list.Remove(ability);
RemovePetAdvancement(ability);
WeaponAbilities = list.ToArray();
ColUtility.Free(list);
}
public void RemoveAbility(AreaEffect ability)
{
if (AreaEffects == null || !AreaEffects.Any(a => a == ability))
return;
var list = AreaEffects.ToList();
list.Remove(ability);
RemovePetAdvancement(ability);
AreaEffects = list.ToArray();
ColUtility.Free(list);
}
public bool AddAbility(SkillName skill, bool advancement = true)
{
OnAddAbility(skill, advancement);
return true;
}
public bool CanAddAbility(object o)
{
if (!Creature.Controlled)
return true;
if (o is MagicalAbility)
return true;
if (o is SpecialAbility && (SpecialAbilities == null || SpecialAbilities.Length == 0))
return true;
if (o is AreaEffect && (AreaEffects == null || AreaEffects.Length == 0))
return true;
if (o is WeaponAbility && (WeaponAbilities == null || WeaponAbilities.Length < 2))
return true;
return false;
}
public void OnAddAbility(object newAbility, bool advancement)
{
if (advancement)
{
AddPetAdvancement(newAbility);
}
if (newAbility is MagicalAbility)
{
AddMagicalAbility((MagicalAbility)newAbility);
}
var trainPoint = PetTrainingHelper.GetTrainingPoint(newAbility);
if (trainPoint != null && trainPoint.Requirements != null)
{
foreach (var req in trainPoint.Requirements.Where(r => r != null))
{
if (req.Requirement is SkillName)
{
double skill = Creature.Skills[(SkillName)req.Requirement].Base;
double toAdd = req.Cost == 100 ? 20 : 40;
if ((SkillName)req.Requirement == SkillName.Hiding)
toAdd = 100;
if (skill < toAdd)
Creature.Skills[(SkillName)req.Requirement].Base = toAdd;
}
else if (req.Requirement is WeaponAbility)
{
AddAbility((WeaponAbility)req.Requirement);
}
}
}
}
public void AddPetAdvancement(object o)
{
if (Creature.Controlled)
{
if (Advancements == null)
Advancements = new List<object>();
if (!Advancements.Contains(o))
{
Advancements.Add(o);
}
}
}
public void RemovePetAdvancement(object o)
{
if (Creature.Controlled && Advancements != null && Advancements.Contains(o))
{
Advancements.Remove(o);
}
}
public bool HasAbility(object o)
{
if (o is MagicalAbility)
{
return (MagicalAbility & (MagicalAbility)o) != 0;
}
if (o is SpecialAbility && SpecialAbilities != null)
{
return SpecialAbilities.Any(a => a == (SpecialAbility)o);
}
if (o is AreaEffect && AreaEffects != null)
{
return AreaEffects.Any(a => a == (AreaEffect)o);
}
if (o is WeaponAbility && WeaponAbilities != null)
{
return WeaponAbilities.Any(a => a == (WeaponAbility)o);
}
return false;
}
public int AbilityCount()
{
int count = 0;
if (MagicalAbility != MagicalAbility.None)
count++;
if (SpecialAbilities != null)
count += SpecialAbilities.Where(a => !a.NaturalAbility).Count();
if (AreaEffects != null)
count += AreaEffects.Length;
if (WeaponAbilities != null)
count += WeaponAbilities.Length;
return count;
}
public bool CanChooseMagicalAbility(MagicalAbility ability)
{
if (!Creature.Controlled)
return true;
if (HasSpecialMagicalAbility() &&
IsSpecialMagicalAbility(ability) &&
SpecialAbilities != null &&
SpecialAbilities.Length > 0 &&
SpecialAbilities.Any(a => !a.NaturalAbility))
{
return false;
}
return true;
}
public bool CanChooseSpecialAbility(SpecialAbility[] list)
{
if (!Creature.Controlled)
return true;
if (HasSpecialMagicalAbility() &&
list.Any(abil => IsRuleBreaker(abil)) &&
(AreaEffects == null || AreaEffects.Length == 0) &&
(SpecialAbilities == null || SpecialAbilities.Length == 0 || SpecialAbilities.All(a => a.NaturalAbility)))
return true;
return !HasSpecialMagicalAbility() && (SpecialAbilities == null || SpecialAbilities.Where(a => !a.NaturalAbility).Count() == 0) && AbilityCount() < 3;
}
public bool IsRuleBreaker(SpecialAbility ability)
{
return PetTrainingHelper.RuleBreakers.Any(abil => abil == ability);
}
public bool CanChooseAreaEffect()
{
if (!Creature.Controlled)
return true;
if (HasSpecialMagicalAbility() && (AreaEffects == null || AreaEffects.Length == 0) && (SpecialAbilities == null || SpecialAbilities.Length == 0))
return true;
return !HasSpecialMagicalAbility() && (AreaEffects == null || AreaEffects.Length == 0) && AbilityCount() < 3;
}
public bool CanChooseWeaponAbility()
{
if (!Creature.Controlled)
return true;
return !HasSpecialMagicalAbility() && (WeaponAbilities == null || WeaponAbilities.Length < 2) && AbilityCount() < 3;
}
public bool HasSpecialMagicalAbility()
{
return (MagicalAbility & MagicalAbility.Piercing) != 0 ||
(MagicalAbility & MagicalAbility.Bashing) != 0 ||
(MagicalAbility & MagicalAbility.Slashing) != 0 ||
(MagicalAbility & MagicalAbility.BattleDefense) != 0 ||
(MagicalAbility & MagicalAbility.WrestlingMastery) != 0;
}
public bool IsSpecialMagicalAbility(MagicalAbility ability)
{
return ability != MagicalAbility.None && ability <= MagicalAbility.WrestlingMastery;
}
public void AddMagicalAbility(MagicalAbility ability)
{
if (IsSpecialMagicalAbility(ability))
{
//SpecialAbilities = null;
WeaponAbilities = null;
Creature.AI = AIType.AI_Melee;
}
switch (ability)
{
case MagicalAbility.Piercing:
Creature.Mastery = SkillName.Fencing;
break;
case MagicalAbility.Bashing:
Creature.Mastery = SkillName.Macing;
break;
case MagicalAbility.Slashing:
Creature.Mastery = SkillName.Swords;
break;
case MagicalAbility.BattleDefense:
Creature.Mastery = SkillName.Parry;
break;
case MagicalAbility.WrestlingMastery:
Creature.Mastery = SkillName.Wrestling;
break;
case MagicalAbility.Poisoning:
if(Creature.Controlled && Creature.AI != AIType.AI_Melee)
Creature.AI = AIType.AI_Melee;
break;
case MagicalAbility.Bushido:
if (Creature.Controlled && Creature.AI != AIType.AI_Samurai)
Creature.AI = AIType.AI_Samurai;
if (!HasAbility(WeaponAbility.WhirlwindAttack))
{
AddAbility(WeaponAbility.WhirlwindAttack, false);
}
break;
case MagicalAbility.Ninjitsu:
if (Creature.Controlled && Creature.AI != AIType.AI_Ninja)
Creature.AI = AIType.AI_Ninja;
if (!HasAbility(WeaponAbility.FrenziedWhirlwind))
{
AddAbility(WeaponAbility.FrenziedWhirlwind, false);
}
break;
case MagicalAbility.Discordance:
if (Creature.Controlled && Creature.AI != AIType.AI_Melee)
Creature.AI = AIType.AI_Melee;
break;
case MagicalAbility.Magery:
case MagicalAbility.MageryMastery:
if (Creature.Controlled && Creature.AI != AIType.AI_Mage)
Creature.AI = AIType.AI_Mage;
break;
case MagicalAbility.Mysticism:
if (Creature.Controlled && Creature.AI != AIType.AI_Mystic)
Creature.AI = AIType.AI_Mystic;
break;
case MagicalAbility.Spellweaving:
if (Creature.Controlled && Creature.AI != AIType.AI_Spellweaving)
Creature.AI = AIType.AI_Spellweaving;
break;
case MagicalAbility.Chivalry:
if (Creature.Controlled && Creature.AI != AIType.AI_Paladin)
Creature.AI = AIType.AI_Paladin;
break;
case MagicalAbility.Necromage:
if (Creature.Controlled && Creature.AI != AIType.AI_NecroMage)
Creature.AI = AIType.AI_NecroMage;
break;
case MagicalAbility.Necromancy:
if (Creature.Controlled && Creature.AI != AIType.AI_Necro)
Creature.AI = AIType.AI_Necro;
break;
}
}
public void OnRemoveMagicalAbility(MagicalAbility oldAbility, MagicalAbility newAbility)
{
if ((oldAbility & MagicalAbility.Bushido) != 0)
{
if (HasAbility(WeaponAbility.WhirlwindAttack))
{
RemoveAbility(WeaponAbility.WhirlwindAttack);
}
}
if ((oldAbility & MagicalAbility.Ninjitsu) != 0)
{
if (HasAbility(WeaponAbility.FrenziedWhirlwind))
{
RemoveAbility(WeaponAbility.FrenziedWhirlwind);
}
}
}
public void RemoveSpecialMagicalAbility(MagicalAbility ability)
{
//SpecialAbilities = null;
WeaponAbilities = null;
Creature.Mastery = SkillName.Alchemy; // default
}
public bool HasCustomized()
{
return Advancements != null && Advancements.Count > 0;
}
public bool IsNaturalAbility(object o)
{
if (Advancements == null)
return true;
if (o is SpecialAbility)
{
return SpecialAbilities != null && !Advancements.Any(s => s is SpecialAbility && (SpecialAbility)s == (SpecialAbility)o);
}
if (o is WeaponAbility)
{
return WeaponAbilities != null && !Advancements.Any(s => s is WeaponAbility && (WeaponAbility)s == (WeaponAbility)o);
}
return false;
}
public IEnumerable<object> EnumerateAllAbilities()
{
if (MagicalAbility != MagicalAbility.None)
{
foreach (var abil in PetTrainingHelper.MagicalAbilities)
{
if ((MagicalAbility & abil) != 0)
yield return abil;
}
}
if (SpecialAbilities != null)
{
foreach (var abil in SpecialAbilities)
{
yield return abil;
}
}
if (AreaEffects != null)
{
foreach (var effect in AreaEffects)
{
yield return effect;
}
}
if (WeaponAbilities != null)
{
foreach (var abil in WeaponAbilities)
{
yield return abil;
}
}
}
public IEnumerable<SpecialAbility> EnumerateSpecialAbilities()
{
if (SpecialAbilities == null)
{
yield break;
}
foreach (var ability in SpecialAbilities)
{
yield return ability;
}
}
public SpecialAbility[] GetSpecialAbilities()
{
return EnumerateSpecialAbilities().ToArray();
}
public IEnumerable<AreaEffect> EnumerateAreaEffects()
{
if (AreaEffects == null)
{
yield break;
}
foreach (var ability in AreaEffects)
{
yield return ability;
}
}
public AreaEffect[] GetAreaEffects()
{
return EnumerateAreaEffects().ToArray();
}
public override string ToString()
{
return "...";
}
public AbilityProfile(BaseCreature bc, GenericReader reader)
{
int version = reader.ReadInt();
Creature = bc;
switch (version)
{
case 0:
DamageIndex = -1;
break;
case 1:
DamageIndex = reader.ReadInt();
break;
}
MagicalAbility = (MagicalAbility)reader.ReadInt();
TokunoTame = reader.ReadBool();
RegenHits = reader.ReadInt();
RegenStam = reader.ReadInt();
RegenMana = reader.ReadInt();
int count = reader.ReadInt();
SpecialAbilities = new SpecialAbility[count];
for (int i = 0; i < count; i++)
{
SpecialAbilities[i] = SpecialAbility.Abilities[reader.ReadInt()];
}
count = reader.ReadInt();
AreaEffects = new AreaEffect[count];
for (int i = 0; i < count; i++)
{
AreaEffects[i] = AreaEffect.Effects[reader.ReadInt()];
}
count = reader.ReadInt();
WeaponAbilities = new WeaponAbility[count];
for (int i = 0; i < count; i++)
{
WeaponAbilities[i] = WeaponAbility.Abilities[reader.ReadInt()];
}
count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
if (Advancements == null)
Advancements = new List<object>();
switch (reader.ReadInt())
{
case 1: Advancements.Add((MagicalAbility)reader.ReadInt()); break;
case 2: Advancements.Add(SpecialAbility.Abilities[reader.ReadInt()]); break;
case 3: Advancements.Add(AreaEffect.Effects[reader.ReadInt()]); break;
case 4: Advancements.Add(WeaponAbility.Abilities[reader.ReadInt()]); break;
case 5: Advancements.Add((SkillName)reader.ReadInt()); break;
}
}
}
public virtual void Serialize(GenericWriter writer)
{
writer.Write(1);
writer.Write(DamageIndex);
writer.Write((int)MagicalAbility);
writer.Write(TokunoTame);
writer.Write(RegenHits);
writer.Write(RegenStam);
writer.Write(RegenMana);
writer.Write(SpecialAbilities != null ? SpecialAbilities.Length : 0);
if (SpecialAbilities != null)
{
foreach (var abil in SpecialAbilities)
{
writer.Write(Array.IndexOf(SpecialAbility.Abilities, abil));
}
}
writer.Write(AreaEffects != null ? AreaEffects.Length : 0);
if (AreaEffects != null)
{
foreach (var abil in AreaEffects)
{
writer.Write(Array.IndexOf(AreaEffect.Effects, abil));
}
}
writer.Write(WeaponAbilities != null ? WeaponAbilities.Length : 0);
if (WeaponAbilities != null)
{
foreach (var abil in WeaponAbilities)
{
writer.Write(Array.IndexOf(WeaponAbility.Abilities, abil));
}
}
writer.Write(Advancements != null ? Advancements.Count : 0);
if (Advancements != null)
{
foreach (var o in Advancements)
{
if (o is MagicalAbility)
{
writer.Write(1);
writer.Write((int)(MagicalAbility)o);
}
else if (o is SpecialAbility)
{
writer.Write(2);
writer.Write(Array.IndexOf(SpecialAbility.Abilities, (SpecialAbility)o));
}
else if (o is AreaEffect)
{
writer.Write(3);
writer.Write(Array.IndexOf(AreaEffect.Effects, (AreaEffect)o));
}
else if (o is WeaponAbility)
{
writer.Write(4);
writer.Write(Array.IndexOf(WeaponAbility.Abilities, (WeaponAbility)o));
}
else if (o is SkillName)
{
writer.Write(5);
writer.Write((int)(SkillName)o);
}
else
{
writer.Write(0);
}
}
}
}
}
}

View File

@@ -0,0 +1,596 @@
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;
}
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using Server.Mobiles;
namespace Server.Items
{
public class EthologistTitleDeed : BaseRewardTitleDeed
{
public override TextDefinition Title { get { return 1157594; } } // Ethologist
[Constructable]
public EthologistTitleDeed()
{
}
public EthologistTitleDeed(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,186 @@
using Server;
using System;
using Server.Mobiles;
using Server.Gumps;
namespace Server.Items
{
public class PetTrainingGate : Item
{
public override bool ForceShowProperties { get { return true; } }
public override string DefaultName
{
get
{
return "Pet Training Gate - You Must Start Pet Training Before Bringing Your Pet Through The Gate!";
}
}
[Constructable]
public PetTrainingGate()
: base(3948)
{
Hue = 1918;
Movable = false;
}
public override bool OnMoveOver(Mobile m)
{
if (m is BaseCreature)
{
var bc = m as BaseCreature;
var profile = PetTrainingHelper.GetTrainingProfile(bc);
if (bc.Controlled && bc.ControlMaster != null && bc.ControlMaster.InRange(bc.Location, 25)
&& profile != null && profile.HasBegunTraining && profile.TrainingProgress < profile.TrainingProgressMax)
{
profile.TrainingProgress = profile.TrainingProgressMax;
bc.FixedEffect(0x375A, 10, 30);
if (bc.ControlMaster is PlayerMobile)
{
var gump = bc.ControlMaster.FindGump<NewAnimalLoreGump>();
if (gump != null)
gump.Refresh();
else
BaseGump.SendGump(new NewAnimalLoreGump((PlayerMobile)bc.ControlMaster, bc));
}
}
}
return true;
}
public PetTrainingGate(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class PetBondRemoveGate : Item
{
public override bool ForceShowProperties { get { return true; } }
public override string DefaultName
{
get
{
return "Pet Bond Timer Remover";
}
}
[Constructable]
public PetBondRemoveGate()
: base(3948)
{
Hue = 1911;
Movable = false;
}
public override bool OnMoveOver(Mobile m)
{
if (m is BaseCreature)
{
var bc = m as BaseCreature;
var profile = PetTrainingHelper.GetTrainingProfile(bc);
if (bc.Controlled && bc.ControlMaster != null && bc.ControlMaster.InRange(bc.Location, 25)
&& !bc.IsBonded)
{
bc.IsBonded = true;
bc.FixedEffect(0x375A, 10, 30);
}
}
return true;
}
public PetBondRemoveGate(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class PowerScrollGiver : Item
{
public override bool ForceShowProperties { get { return true; } }
public override string DefaultName
{
get
{
return "+20 Power Scrolls";
}
}
[Constructable]
public PowerScrollGiver()
: base(0x1183)
{
Hue = 2214;
Movable = false;
}
public override void OnDoubleClick(Mobile m)
{
if (m.InRange(Location, 3))
{
var bag = new Bag();
foreach (var sk in PetTrainingHelper.MagicSkills)
{
bag.DropItem(new PowerScroll(sk, 120));
}
foreach (var sk in PetTrainingHelper.CombatSkills)
{
bag.DropItem(new PowerScroll(sk, 120));
}
m.AddToBackpack(bag);
}
}
public PowerScrollGiver(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,161 @@
using System;
using Server;
using System.Collections.Generic;
using System.Linq;
using Server.Items;
namespace Server.Mobiles
{
public class PlanningProfile
{
public BaseCreature Creature { get; private set; }
public List<PlanningEntry> Entries { get; private set; }
public PlanningProfile(BaseCreature bc)
{
Creature = bc;
Entries = new List<PlanningEntry>();
}
public void Clear()
{
Entries.Clear();
}
public void AddToPlan(object tp, int value, int cost)
{
var entry = Entries.FirstOrDefault(e => e.TrainPoint == tp);
if (entry != null)
Entries.Remove(entry);
Entries.Add(new PlanningEntry(tp, value, cost));
if (tp is MagicalAbility && (MagicalAbility)tp <= MagicalAbility.WrestlingMastery)
{
var trainingPoint = PetTrainingHelper.GetTrainingPoint(tp);
foreach (var en in Entries)
{
if (trainingPoint.Requirements != null && trainingPoint.Requirements.Length > 0)
{
foreach (var req in trainingPoint.Requirements.Where(r => r != null))
{
if ((req.Requirement is WeaponAbility && en.TrainPoint is WeaponAbility) ||
(req.Requirement is SpecialAbility && en.TrainPoint is SpecialAbility) ||
(req.Requirement is AreaEffect && en.TrainPoint is AreaEffect))
{
en.Value = 0;
en.Cost = 0;
}
}
}
}
}
}
public class PlanningEntry
{
public object TrainPoint { get; private set; }
public int Value { get; set; }
public int Cost { get; set; }
public PlanningEntry(object tp, int value, int cost)
{
TrainPoint = tp;
Value = value;
Cost = cost;
}
}
public PlanningProfile(BaseCreature bc, GenericReader reader)
{
int version = reader.ReadInt();
Entries = new List<PlanningEntry>();
int count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
switch (reader.ReadInt())
{
case 0: break;
case 1: Entries.Add(new PlanningEntry((MagicalAbility)reader.ReadInt(), reader.ReadInt(), reader.ReadInt())); break;
case 2: Entries.Add(new PlanningEntry(SpecialAbility.Abilities[reader.ReadInt()], reader.ReadInt(), reader.ReadInt())); break;
case 3: Entries.Add(new PlanningEntry(AreaEffect.Effects[reader.ReadInt()], reader.ReadInt(), reader.ReadInt())); break;
case 4: Entries.Add(new PlanningEntry(WeaponAbility.Abilities[reader.ReadInt()], reader.ReadInt(), reader.ReadInt())); break;
case 5: Entries.Add(new PlanningEntry((PetStat)reader.ReadInt(), reader.ReadInt(), reader.ReadInt())); break;
case 6: Entries.Add(new PlanningEntry((ResistanceType)reader.ReadInt(), reader.ReadInt(), reader.ReadInt())); break;
case 7: Entries.Add(new PlanningEntry((SkillName)reader.ReadInt(), reader.ReadInt(), reader.ReadInt())); break;
}
}
}
public virtual void Serialize(GenericWriter writer)
{
writer.Write(0);
writer.Write(Entries.Count);
for(int i = 0; i < Entries.Count; i++)
{
var entry = Entries[i];
object o = entry.TrainPoint;
if (o is MagicalAbility)
{
writer.Write(1);
writer.Write((int)(MagicalAbility)o);
writer.Write(entry.Value);
writer.Write(entry.Cost);
}
else if (o is SpecialAbility)
{
writer.Write(2);
writer.Write(Array.IndexOf(SpecialAbility.Abilities, (SpecialAbility)o));
writer.Write(entry.Value);
writer.Write(entry.Cost);
}
else if (o is AreaEffect)
{
writer.Write(3);
writer.Write(Array.IndexOf(AreaEffect.Effects, (AreaEffect)o));
writer.Write(entry.Value);
writer.Write(entry.Cost);
}
else if (o is WeaponAbility)
{
writer.Write(4);
writer.Write(Array.IndexOf(WeaponAbility.Abilities, (WeaponAbility)o));
writer.Write(entry.Value);
writer.Write(entry.Cost);
}
else if (o is PetStat)
{
writer.Write(5);
writer.Write((int)(PetStat)o);
writer.Write(entry.Value);
writer.Write(entry.Cost);
}
else if (o is ResistanceType)
{
writer.Write(6);
writer.Write((int)(ResistanceType)o);
writer.Write(entry.Value);
writer.Write(entry.Cost);
}
else if (o is SkillName)
{
writer.Write(7);
writer.Write((int)(SkillName)o);
writer.Write(entry.Value);
writer.Write(entry.Cost);
}
else
{
writer.Write(0);
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
using System;
using Server;
using Server.Items;
using System.Linq;
namespace Server.Mobiles
{
public class TrainingDefinition
{
public Type CreatureType { get; private set; }
public Class Class { get; private set; }
public MagicalAbility MagicalAbilities { get; private set; }
public SpecialAbility[] SpecialAbilities { get; private set; }
public WeaponAbility[] WeaponAbilities { get; private set; }
public AreaEffect[] AreaEffects { get; private set; }
public int ControlSlotsMin { get; private set; }
public int ControlSlotsMax { get; private set; }
public TrainingDefinition(
Type type,
Class classificaion,
MagicalAbility magicalAbility,
SpecialAbility[] specialAbility,
WeaponAbility[] weaponAbility,
AreaEffect[] areaEffect,
int controlmin,
int controlmax)
{
CreatureType = type;
Class = classificaion;
MagicalAbilities = magicalAbility;
SpecialAbilities = specialAbility;
WeaponAbilities = weaponAbility;
AreaEffects = areaEffect;
ControlSlotsMin = controlmin;
ControlSlotsMax = controlmax;
}
public bool HasSpecialAbility(SpecialAbility ability)
{
return SpecialAbilities != null && SpecialAbilities.Any(a => a == ability);
}
public bool HasAreaEffect(AreaEffect ability)
{
return AreaEffects != null && AreaEffects.Any(a => a == ability);
}
}
}

View File

@@ -0,0 +1,55 @@
using System;
using Server;
using Server.Gumps;
namespace Server.Mobiles
{
public class TrainingPoint
{
public object TrainPoint { get; set; }
public double Weight { get; set; }
public int Start { get; set; }
public int Max { get; set; }
public TextDefinition Name { get; set; }
public TextDefinition Description { get; set; }
public TrainingPointRequirement[] Requirements { get; set; }
public TrainingPoint(object trainpoint, double weight, int start, int max, TextDefinition name, TextDefinition description, params TrainingPointRequirement[] requirements)
{
TrainPoint = trainpoint;
Weight = weight;
Start = start;
Max = max;
Name = name;
Description = description;
Requirements = requirements;
}
public int GetMax(BaseCreature bc)
{
if (TrainPoint is PetStat && (PetStat)TrainPoint == PetStat.BaseDamage)
{
return PetTrainingHelper.GetMaxDamagePerSecond(bc);
}
return Max;
}
}
public class TrainingPointRequirement
{
public object Requirement { get; set; }
public int Cost { get; set; }
public TextDefinition Name { get; set; }
public TrainingPointRequirement(object requirement, int cost, TextDefinition name)
{
Requirement = requirement;
Cost = cost;
Name = name;
}
}
}

View File

@@ -0,0 +1,442 @@
using System;
using Server;
using System.Collections.Generic;
using System.Linq;
using Server.Items;
using Server.Network;
using Server.Gumps;
namespace Server.Mobiles
{
public enum TrainingMode
{
Regular,
Planning
}
[PropertyObject]
public class TrainingProfile
{
[CommandProperty(AccessLevel.GameMaster)]
public TrainingMode TrainingMode { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool HasBegunTraining { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool HasIncreasedControlSlot { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int TrainedThisLevel { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool HasRecievedControlSlotWarning { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public double TrainingProgress { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public double TrainingProgressMax { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public BaseCreature Creature { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public double TrainingProgressPercentile { get { return TrainingProgress / TrainingProgressMax; } }
[CommandProperty(AccessLevel.GameMaster)]
public int ControlSlots { get { return Creature.ControlSlots; } }
[CommandProperty(AccessLevel.GameMaster)]
public int ControlSlotsMin { get { return Creature.ControlSlotsMin; } }
[CommandProperty(AccessLevel.GameMaster)]
public int ControlSlotsMax { get { return Creature.ControlSlotsMax; } }
[CommandProperty(AccessLevel.GameMaster)]
public bool CanApplyOptions { get { return HasBegunTraining && TrainingProgressPercentile >= 1.0; } }
private int _TrainingPoints;
private int _StartingTrainingPoints;
private PlanningProfile _Plan;
[CommandProperty(AccessLevel.GameMaster)]
public int TrainingPoints
{
get { return _TrainingPoints; }
set
{
if (value <= 0)
{
EndTraining();
}
else
{
_TrainingPoints = value;
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int StartingTrainingPoints
{
get { return _StartingTrainingPoints; }
set { _StartingTrainingPoints = value; }
}
public PlanningProfile PlanningProfile
{
get
{
if (_Plan == null)
_Plan = new PlanningProfile(Creature);
return _Plan;
}
}
public static TimeSpan PowerHourDuration = TimeSpan.FromHours(1);
public static TimeSpan PowerHourDelay = TimeSpan.FromHours(24);
[CommandProperty(AccessLevel.GameMaster)]
public DateTime PowerHourBegin { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool InPowerHour { get; set; }
public int PowerHourMultiplier
{
get
{
if (InPowerHour)
{
return 2; // 2x gains from creatures during power hour
}
return 1;
}
}
private static readonly int MaxTrainingProgress = 100;
private Dictionary<BaseCreature, int> _ProgressTable;
public TrainingProfile(BaseCreature bc)
{
Creature = bc;
_ProgressTable = new Dictionary<BaseCreature, int>();
}
private int AssignStartingTrainingPoints()
{
if (ControlSlots != ControlSlotsMin)
{
return 1501;
}
if (ControlSlotsMin == 1 && ControlSlotsMax == 2)
{
return 2556;
}
if (ControlSlotsMin == 1 && ControlSlotsMax == 3)
{
return 2381;
}
return 1501;
}
public void BeginTraining()
{
if (ControlSlots < ControlSlotsMax)
{
TrainingPoints = AssignStartingTrainingPoints();
HasBegunTraining = true;
TrainingProgress = 0;
TrainingProgressMax = MaxTrainingProgress;
}
}
public void OnTrain(PlayerMobile pm, int points)
{
int reqInc;
if (!HasIncreasedControlSlot)
{
reqInc = GetRequirementIncrease(true);
Creature.RemoveFollowers();
Creature.ControlSlots++;
Creature.AddFollowers();
TrainedThisLevel = 0;
pm.SendLocalizedMessage(1157537); // Your pet's control slot have been updated.
HasIncreasedControlSlot = true;
}
else
{
TrainedThisLevel++;
reqInc = GetRequirementIncrease(false);
}
Creature.CurrentTameSkill = Math.Min(BaseCreature.MaxTameRequirement, Creature.CurrentTameSkill + reqInc);
TrainingPoints -= points;
}
public int GetRequirementIncrease(bool slotIncreased)
{
if (slotIncreased)
{
// First level
if (ControlSlotsMin + 1 == ControlSlots)
{
return 21;
}
// subsequent trains of that level
else
{
return 22;
}
}
else
{
// First train of that level (after level increase, so actually 2nd train)
if (TrainedThisLevel == 1)
{
return 3;
}
// subsequent trains of that level
else
{
return 2;
}
}
}
public void EndTraining()
{
HasBegunTraining = false;
_TrainingPoints = 0;
HasRecievedControlSlotWarning = false;
HasIncreasedControlSlot = false;
}
private bool CheckCanProgress(BaseCreature bc, double toGain)
{
if (_ProgressTable.ContainsKey(bc))
{
int gains = GetGainsPerCreature(toGain);
if (_ProgressTable[bc] >= gains)
{
return false;
}
else
{
_ProgressTable[bc]++;
return true;
}
}
_ProgressTable[bc] = 1;
return true;
}
private int GetGainsPerCreature(double toGain)
{
int gains = 0;
switch (ControlSlots)
{
case 1: gains = int.MaxValue; break;
case 2: gains = int.MaxValue; break;
case 3: gains = (int)(((double)MaxTrainingProgress / toGain) / 2.0); break;
default: gains = (int)(((double)MaxTrainingProgress / toGain) / 4.0); break;
}
if (gains < int.MaxValue)
{
gains *= PowerHourMultiplier;
}
return gains;
}
public void CheckProgress(BaseCreature bc)
{
if (ControlSlots >= ControlSlotsMax || !HasBegunTraining || TrainingProgress >= TrainingProgressMax || Creature.ControlMaster == null)
return;
var ourDif = Creature.BardingDifficulty;
var theirDif = bc.BardingDifficulty;
var master = Creature.ControlMaster;
if (Utility.Random(100) < 8 - (1 + (ControlSlots - ControlSlotsMin)))
{
double toGain = GetAdvance(theirDif); // Math.Round(.25 + (Math.Max(0, (bc.BardingDifficulty / Creature.BardingDifficulty)) * 1.0), 2);
if (ourDif - theirDif <= 50 && CheckCanProgress(bc, toGain))
{
if (PowerHourBegin + PowerHourDelay < DateTime.UtcNow)
{
_ProgressTable.Clear();
PowerHourBegin = DateTime.UtcNow;
InPowerHour = true;
master.SendLocalizedMessage(1157569); // [Pet Training Power Hour]: Your pet is under the effects of enhanced training progress for the next hour!
}
else if (InPowerHour && PowerHourBegin + PowerHourDuration < DateTime.UtcNow)
{
InPowerHour = false;
master.SendLocalizedMessage(1157570); // [Pet Training Power Hour]: Your pet is no longer under the effects of enhanced training progress.
}
TrainingProgress = Math.Min(TrainingProgressMax, TrainingProgress + toGain);
if (!bc.Controlled && !bc.Summoned && master is PlayerMobile)
{
int cliloc = 1157574; // *The pet's battle experience has greatly increased!*
if (toGain < 1.3)
cliloc = 1157565; // *The pet's battle experience has slightly increased!*
else if (toGain < 2.5)
cliloc = 1157573; // *The pet's battle experience has fairly increased!*
if (master.HasGump(typeof(PetTrainingProgressGump)))
{
ResendProgressGump(master);
}
else
{
if (master.InRange(Creature.Location, 12))
{
BaseGump.SendGump(new PetTrainingProgressGump((PlayerMobile)master, Creature));
}
}
Creature.PrivateOverheadMessage(MessageType.Regular, 0x59, cliloc, master.NetState);
if (TrainingProgress >= TrainingProgressMax)
{
Creature.PrivateOverheadMessage(MessageType.Regular, 0x59, 1157543, master.NetState); // *The creature surges with battle experience and is ready to train!*
Server.Engines.Quests.LeadingIntoBattleQuest.CheckComplete((PlayerMobile)master);
}
}
else
{
Creature.PrivateOverheadMessage(MessageType.Regular, 0x21, 1157564, master.NetState); // *The pet does not appear to train from that*
}
}
else
{
Creature.PrivateOverheadMessage(MessageType.Regular, 0x21, 1157564, master.NetState); // *The pet does not appear to train from that*
}
}
}
private double GetAdvance(double difficulty)
{
var advance = difficulty / 64;
if (advance >= 2.5)
advance = 2.5;
return advance;
}
public void ResendProgressGump(Mobile m)
{
if (m == null || m.NetState == null || !(m is PlayerMobile))
{
return;
}
PetTrainingProgressGump g = m.FindGump(typeof(PetTrainingProgressGump)) as PetTrainingProgressGump;
if (g == null)
{
Server.Gumps.BaseGump.SendGump(new PetTrainingProgressGump((PlayerMobile)m, Creature));
}
else
{
g.Refresh();
}
}
public override string ToString()
{
return "...";
}
public TrainingProfile(BaseCreature bc, GenericReader reader)
{
int version = reader.ReadInt();
switch (version)
{
case 2:
TrainedThisLevel = reader.ReadInt();
goto case 1;
case 1:
PowerHourBegin = reader.ReadDateTime();
InPowerHour = reader.ReadBool();
break;
}
Creature = bc;
if (reader.ReadInt() == 1)
{
_Plan = new PlanningProfile(bc, reader);
}
TrainingMode = (TrainingMode)reader.ReadInt();
HasBegunTraining = reader.ReadBool();
HasIncreasedControlSlot = reader.ReadBool();
HasRecievedControlSlotWarning = reader.ReadBool();
TrainingProgress = reader.ReadDouble();
TrainingProgressMax = reader.ReadDouble();
_StartingTrainingPoints = reader.ReadInt();
_TrainingPoints = reader.ReadInt();
_ProgressTable = new Dictionary<BaseCreature, int>();
}
public void Serialize(GenericWriter writer)
{
writer.Write(2);
writer.Write(TrainedThisLevel);
writer.Write(PowerHourBegin);
writer.Write(InPowerHour);
if (_Plan != null)
{
writer.Write(1);
_Plan.Serialize(writer);
}
else
{
writer.Write(0);
}
writer.Write((int)TrainingMode);
writer.Write(HasBegunTraining);
writer.Write(HasIncreasedControlSlot);
writer.Write(HasRecievedControlSlotWarning);
writer.Write(TrainingProgress);
writer.Write(TrainingProgressMax);
writer.Write(_StartingTrainingPoints);
writer.Write(_TrainingPoints);
}
}
}